瀏覽代碼

Merge tag 'iio-for-4.3b-2' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next

Jonathan writes:

Second set of new device support, features and cleanup for the 4.3 cycle.
Take 2 also includes a fix set that was too late for the 4.2 cycle.

As we had a lot of tools and docs work in this set, I have broken those
out into their own categories in this description.

Fixes from the pull request '4th set of IIO fixes for the 4.2 cycle'.
* Poll functions for both event chardev and the buffer one were returning
  negative error codes (via a positive value).
* A recent change to lsiio adding some error handling that was wrong and
  stopped the tool working.
* bmg160 was missing some dependencies in Kconfig
* berlin2-adc had a misshandled register (wrote a value rather than a bitmap)

New device support
* TI opt3001 light sensor
* TXC PA12 ALS and proximity sensor.
* mcp3301 ADC support (in mcp320x driver)
* ST lsm303agr accelerometer and magnetometer drivers (plus some st-sensors
  common support to allow different WHOAMI register addresses, devices with
  fixed scale and allow interrupt equiped magnetometers).
* ADIS16305, ADIS16367, ADIS16445IMUs (in the adis16400 driver)
* ADIS16266 gyro (in the adis16260 driver)
* ADIS16137 gyro (in the adis16136 driver)

New functionality
* mmc35240 DT bindings.
* Inverse unit conversion macros to aid handing of values written to sysfs
  attributes.

Core cleanup
* Forward declaration of struct iio_trigger to avoid a compile warning.

Driver cleanup / fixes
* mxs-lradc
  - Clarify which parts are supported.
  - Fix spelling erorrs.
  - Missing/extra includes
  - reorder includes
  - add datasheet name listings for all usable channels (to allow them
    to be bound by name from consumer drivers)
* acpi-als - add some function prefixes as per general iio style.
* bmc150_magn - replace a magic value with the existing define.
* vf610 - determine possible sample frequencies taking into account the
  electrical characteristics (defining a minimum sample time)
* dht11
  - whitespace
  - additional docs
  - avoid mulitple assignments in one line
  - Use the new funciton ktime_get_resolution_ns to cleanup a nasty trick
    previously used for timing.
* Fix all drivers that consider 0 a valid IRQ for historical reasons.
* Export I2C module alias info where previously missing (to allow autoprobing)
* Export OF module alias info where previously missing.
* mmc35240 - switch some variables into arrays to improve readability.
* mlx90614 - define some magic numbers for readability.
* bmc150_magn
  - expand area locked by a mutex to cover all the use of the
    data->buffer.
  - use descriptive naming for a mask instead of a magic value.
* berin2-adc
  - pass up an error code rather that a generic error
  - constify the iio_chan_spec
  - some other little tidy ups.
* stk8312
  - fix a dependency on triggered buffers in kconfig
  - add a check for invalid attribute values
  - improve error handling by returning error codes where possible and
    return immediately where relevant
  - rework macro defs to use GENMASK etc
  - change some variable types to reduce unnecessary casting
  - clean up code style
  - drop a local buffer copy for bulk reads and use the one in data->buffer
     instead.
* adis16400 - the adis16448 gyroscope scale was wrong.
* adis16480 - some more wrong scales for various parts.
* adis16300 - has an undocumented product id and serial number registers so
  use them.
* iio_simple_dummy - fix some wrong code indentation.
* bmc150-accel - use the chip ID to detect the chip present rather than
  verifying the expected part was there.  This was in response to a wrong
  ACPI entry on the WinBook TW100.
* mma8452
  - fix _get_hp_filter_index
  - drop a double include
  - pass up an error code rather than rewriting it
  - range check input values to attribute writes
  - register defs tidy up using GENMASK and reordering them to be easier to
    follow.
  - various coding style cleanups
  - put the Kconfig entry in the write place (alphabetically).

Tools related
* Tools cleanup - drop an explicity NULL comparison, some unnecessary braces,
  use the ARRAY_SIZE macro, send error messages to stderr instead of dropping
  them in the middle of normal output.
* Fix tools to allow that scale and offset attributes are optional.
* More tools fixes including allowing true 32bit data (previously an overflow
  prevented more than 31bits)
* Drop a stray header guard that ended up in a c file.
* Make calc_digits static as it isn't exported or in the header.
* Set ci_array pointer to NULL after free as a protection against non safe
  usage of the tools core code.  Also convert a double pointer to a single
  one as the extra level of indirection was unnecessary.

Docs
* DocBook introduction by Daniel Baluta.  Glad we are beginning to
  draw together some more introductory docs to suplement the various
  tools / examples.
* Drop bytes_per_datum sysfs attribute docs as it no longer exists.
* A whole load of missing / fixing of kernel-doc for the core of IIO.
* Document the trigger name sysfs attribute in the ABI docs.
* Minor typos in the ABI docs related to power down modes.
Greg Kroah-Hartman 10 年之前
父節點
當前提交
1c46ae0af6
共有 67 個文件被更改,包括 3148 次插入574 次删除
  1. 3 10
      Documentation/ABI/testing/sysfs-bus-iio
  2. 9 0
      Documentation/ABI/testing/sysfs-bus-iio-trigger-sysfs
  3. 1 1
      Documentation/DocBook/Makefile
  4. 697 0
      Documentation/DocBook/iio.tmpl
  5. 1 0
      Documentation/devicetree/bindings/iio/adc/mcp320x.txt
  6. 5 0
      Documentation/devicetree/bindings/iio/adc/vf610-adc.txt
  7. 13 0
      Documentation/devicetree/bindings/iio/magnetometer/mmc35240.txt
  8. 2 0
      Documentation/devicetree/bindings/iio/st-sensors.txt
  9. 1 1
      Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
  10. 14 12
      drivers/iio/accel/Kconfig
  11. 74 82
      drivers/iio/accel/bmc150-accel.c
  12. 1 1
      drivers/iio/accel/kxcjk-1013.c
  13. 123 94
      drivers/iio/accel/mma8452.c
  14. 1 1
      drivers/iio/accel/mma9553.c
  15. 1 0
      drivers/iio/accel/st_accel.h
  16. 6 0
      drivers/iio/accel/st_accel_core.c
  17. 5 0
      drivers/iio/accel/st_accel_i2c.c
  18. 1 0
      drivers/iio/accel/st_accel_spi.c
  19. 61 46
      drivers/iio/accel/stk8312.c
  20. 1 0
      drivers/iio/accel/stk8ba50.c
  21. 2 2
      drivers/iio/adc/Kconfig
  22. 10 12
      drivers/iio/adc/berlin2-adc.c
  23. 15 1
      drivers/iio/adc/mcp320x.c
  24. 75 4
      drivers/iio/adc/vf610_adc.c
  25. 26 26
      drivers/iio/common/st_sensors/st_sensors_core.c
  26. 2 1
      drivers/iio/gyro/Kconfig
  27. 6 0
      drivers/iio/gyro/adis16136.c
  28. 98 39
      drivers/iio/gyro/adis16260.c
  29. 3 0
      drivers/iio/gyro/st_gyro_core.c
  30. 35 30
      drivers/iio/humidity/dht11.c
  31. 44 2
      drivers/iio/imu/adis16400_core.c
  32. 33 6
      drivers/iio/imu/adis16480.c
  33. 4 4
      drivers/iio/imu/kmx61.c
  34. 15 2
      drivers/iio/industrialio-buffer.c
  35. 20 5
      drivers/iio/industrialio-core.c
  36. 7 1
      drivers/iio/industrialio-event.c
  37. 24 3
      drivers/iio/industrialio-trigger.c
  38. 21 0
      drivers/iio/light/Kconfig
  39. 2 0
      drivers/iio/light/Makefile
  40. 9 9
      drivers/iio/light/acpi-als.c
  41. 1 0
      drivers/iio/light/cm32181.c
  42. 1 0
      drivers/iio/light/cm3232.c
  43. 1 0
      drivers/iio/light/cm36651.c
  44. 1 0
      drivers/iio/light/gp2ap020a00f.c
  45. 804 0
      drivers/iio/light/opt3001.c
  46. 483 0
      drivers/iio/light/pa12203001.c
  47. 1 0
      drivers/iio/light/stk3310.c
  48. 12 12
      drivers/iio/magnetometer/bmc150_magn.c
  49. 20 13
      drivers/iio/magnetometer/mmc35240.c
  50. 3 0
      drivers/iio/magnetometer/st_magn.h
  51. 7 0
      drivers/iio/magnetometer/st_magn_buffer.c
  52. 97 1
      drivers/iio/magnetometer/st_magn_core.c
  53. 5 0
      drivers/iio/magnetometer/st_magn_i2c.c
  54. 1 0
      drivers/iio/magnetometer/st_magn_spi.c
  55. 3 0
      drivers/iio/pressure/st_pressure_core.c
  56. 14 6
      drivers/iio/temperature/mlx90614.c
  57. 81 41
      drivers/staging/iio/adc/mxs-lradc.c
  58. 2 0
      include/linux/iio/common/st_sensors.h
  59. 1 1
      include/linux/iio/consumer.h
  60. 17 0
      include/linux/iio/iio.h
  61. 2 1
      include/linux/iio/sysfs.h
  62. 3 0
      include/linux/iio/trigger.h
  63. 27 21
      tools/iio/generic_buffer.c
  64. 8 9
      tools/iio/iio_event_monitor.c
  65. 71 65
      tools/iio/iio_utils.c
  66. 3 1
      tools/iio/iio_utils.h
  67. 8 8
      tools/iio/lsiio.c

+ 3 - 10
Documentation/ABI/testing/sysfs-bus-iio

@@ -493,7 +493,7 @@ Contact:	linux-iio@vger.kernel.org
 Description:
 Description:
 		Specifies the output powerdown mode.
 		Specifies the output powerdown mode.
 		DAC output stage is disconnected from the amplifier and
 		DAC output stage is disconnected from the amplifier and
-		1kohm_to_gnd: connected	to ground via an 1kOhm resistor,
+		1kohm_to_gnd: connected to ground via an 1kOhm resistor,
 		6kohm_to_gnd: connected to ground via a 6kOhm resistor,
 		6kohm_to_gnd: connected to ground via a 6kOhm resistor,
 		20kohm_to_gnd: connected to ground via a 20kOhm resistor,
 		20kohm_to_gnd: connected to ground via a 20kOhm resistor,
 		100kohm_to_gnd: connected to ground via an 100kOhm resistor,
 		100kohm_to_gnd: connected to ground via an 100kOhm resistor,
@@ -503,9 +503,9 @@ Description:
 		outX_powerdown_mode_available. If Y is not present the
 		outX_powerdown_mode_available. If Y is not present the
 		mode is shared across all outputs.
 		mode is shared across all outputs.
 
 
-What:		/sys/.../iio:deviceX/out_votlageY_powerdown_mode_available
+What:		/sys/.../iio:deviceX/out_voltageY_powerdown_mode_available
 What:		/sys/.../iio:deviceX/out_voltage_powerdown_mode_available
 What:		/sys/.../iio:deviceX/out_voltage_powerdown_mode_available
-What:		/sys/.../iio:deviceX/out_altvotlageY_powerdown_mode_available
+What:		/sys/.../iio:deviceX/out_altvoltageY_powerdown_mode_available
 What:		/sys/.../iio:deviceX/out_altvoltage_powerdown_mode_available
 What:		/sys/.../iio:deviceX/out_altvoltage_powerdown_mode_available
 KernelVersion:	2.6.38
 KernelVersion:	2.6.38
 Contact:	linux-iio@vger.kernel.org
 Contact:	linux-iio@vger.kernel.org
@@ -1040,13 +1040,6 @@ Contact:	linux-iio@vger.kernel.org
 Description:
 Description:
 		Number of scans contained by the buffer.
 		Number of scans contained by the buffer.
 
 
-What:		/sys/bus/iio/devices/iio:deviceX/buffer/bytes_per_datum
-KernelVersion:	2.6.37
-Contact:	linux-iio@vger.kernel.org
-Description:
-		Bytes per scan.  Due to alignment fun, the scan may be larger
-		than implied directly by the scan_element parameters.
-
 What:		/sys/bus/iio/devices/iio:deviceX/buffer/enable
 What:		/sys/bus/iio/devices/iio:deviceX/buffer/enable
 KernelVersion:	2.6.35
 KernelVersion:	2.6.35
 Contact:	linux-iio@vger.kernel.org
 Contact:	linux-iio@vger.kernel.org

+ 9 - 0
Documentation/ABI/testing/sysfs-bus-iio-trigger-sysfs

@@ -9,3 +9,12 @@ Description:
 		automated testing or in situations, where other trigger methods
 		automated testing or in situations, where other trigger methods
 		are not applicable. For example no RTC or spare GPIOs.
 		are not applicable. For example no RTC or spare GPIOs.
 		X is the IIO index of the trigger.
 		X is the IIO index of the trigger.
+
+What:		/sys/bus/iio/devices/triggerX/name
+KernelVersion:	2.6.39
+Contact:	linux-iio@vger.kernel.org
+Description:
+		The name attribute holds a description string for the current
+		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.

+ 1 - 1
Documentation/DocBook/Makefile

@@ -15,7 +15,7 @@ DOCBOOKS := z8530book.xml device-drivers.xml \
 	    80211.xml debugobjects.xml sh.xml regulator.xml \
 	    80211.xml debugobjects.xml sh.xml regulator.xml \
 	    alsa-driver-api.xml writing-an-alsa-driver.xml \
 	    alsa-driver-api.xml writing-an-alsa-driver.xml \
 	    tracepoint.xml drm.xml media_api.xml w1.xml \
 	    tracepoint.xml drm.xml media_api.xml w1.xml \
-	    writing_musb_glue_layer.xml crypto-API.xml
+	    writing_musb_glue_layer.xml crypto-API.xml iio.xml
 
 
 include Documentation/DocBook/media/Makefile
 include Documentation/DocBook/media/Makefile
 
 

+ 697 - 0
Documentation/DocBook/iio.tmpl

@@ -0,0 +1,697 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="iioid">
+  <bookinfo>
+    <title>Industrial I/O driver developer's guide </title>
+
+    <authorgroup>
+      <author>
+        <firstname>Daniel</firstname>
+        <surname>Baluta</surname>
+        <affiliation>
+          <address>
+            <email>daniel.baluta@intel.com</email>
+          </address>
+        </affiliation>
+      </author>
+    </authorgroup>
+
+    <copyright>
+      <year>2015</year>
+      <holder>Intel Corporation</holder>
+    </copyright>
+
+    <legalnotice>
+      <para>
+        This documentation is free software; you can redistribute
+        it and/or modify it under the terms of the GNU General Public
+        License version 2.
+      </para>
+    </legalnotice>
+  </bookinfo>
+
+  <toc></toc>
+
+  <chapter id="intro">
+    <title>Introduction</title>
+    <para>
+      The main purpose of the Industrial I/O subsystem (IIO) is to provide
+      support for devices that in some sense perform either analog-to-digital
+      conversion (ADC) or digital-to-analog conversion (DAC) or both. The aim
+      is to fill the gap between the somewhat similar hwmon and input
+      subsystems.
+      Hwmon is directed at low sample rate sensors used to monitor and
+      control the system itself, like fan speed control or temperature
+      measurement. Input is, as its name suggests, focused on human interaction
+      input devices (keyboard, mouse, touchscreen). In some cases there is
+      considerable overlap between these and IIO.
+  </para>
+  <para>
+    Devices that fall into this category include:
+    <itemizedlist>
+      <listitem>
+        analog to digital converters (ADCs)
+      </listitem>
+      <listitem>
+        accelerometers
+      </listitem>
+      <listitem>
+        capacitance to digital converters (CDCs)
+      </listitem>
+      <listitem>
+        digital to analog converters (DACs)
+      </listitem>
+      <listitem>
+        gyroscopes
+      </listitem>
+      <listitem>
+        inertial measurement units (IMUs)
+      </listitem>
+      <listitem>
+        color and light sensors
+      </listitem>
+      <listitem>
+        magnetometers
+      </listitem>
+      <listitem>
+        pressure sensors
+      </listitem>
+      <listitem>
+        proximity sensors
+      </listitem>
+      <listitem>
+        temperature sensors
+      </listitem>
+    </itemizedlist>
+    Usually these sensors are connected via SPI or I2C. A common use case of the
+    sensors devices is to have combined functionality (e.g. light plus proximity
+    sensor).
+  </para>
+  </chapter>
+  <chapter id='iiosubsys'>
+    <title>Industrial I/O core</title>
+    <para>
+      The Industrial I/O core offers:
+      <itemizedlist>
+        <listitem>
+         a unified framework for writing drivers for many different types of
+         embedded sensors.
+        </listitem>
+        <listitem>
+         a standard interface to user space applications manipulating sensors.
+        </listitem>
+      </itemizedlist>
+      The implementation can be found under <filename>
+      drivers/iio/industrialio-*</filename>
+  </para>
+  <sect1 id="iiodevice">
+    <title> Industrial I/O devices </title>
+
+!Finclude/linux/iio/iio.h iio_dev
+!Fdrivers/iio/industrialio-core.c iio_device_alloc
+!Fdrivers/iio/industrialio-core.c iio_device_free
+!Fdrivers/iio/industrialio-core.c iio_device_register
+!Fdrivers/iio/industrialio-core.c iio_device_unregister
+
+    <para>
+      An IIO device usually corresponds to a single hardware sensor and it
+      provides all the information needed by a driver handling a device.
+      Let's first have a look at the functionality embedded in an IIO
+      device then we will show how a device driver makes use of an IIO
+      device.
+    </para>
+    <para>
+        There are two ways for a user space application to interact
+        with an IIO driver.
+      <itemizedlist>
+        <listitem>
+          <filename>/sys/bus/iio/iio:deviceX/</filename>, this
+          represents a hardware sensor and groups together the data
+          channels of the same chip.
+        </listitem>
+        <listitem>
+          <filename>/dev/iio:deviceX</filename>, character device node
+          interface used for buffered data transfer and for events information
+          retrieval.
+        </listitem>
+      </itemizedlist>
+    </para>
+    A typical IIO driver will register itself as an I2C or SPI driver and will
+    create two routines, <function> probe </function> and <function> remove
+    </function>. At <function>probe</function>:
+    <itemizedlist>
+    <listitem>call <function>iio_device_alloc</function>, which allocates memory
+      for an IIO device.
+    </listitem>
+    <listitem> initialize IIO device fields with driver specific information
+              (e.g. device name, device channels).
+    </listitem>
+    <listitem>call <function> iio_device_register</function>, this registers the
+      device with the IIO core. After this call the device is ready to accept
+      requests from user space applications.
+    </listitem>
+    </itemizedlist>
+      At <function>remove</function>, we free the resources allocated in
+      <function>probe</function> in reverse order:
+    <itemizedlist>
+    <listitem><function>iio_device_unregister</function>, unregister the device
+      from the IIO core.
+    </listitem>
+    <listitem><function>iio_device_free</function>, free the memory allocated
+      for the IIO device.
+    </listitem>
+    </itemizedlist>
+
+    <sect2 id="iioattr"> <title> IIO device sysfs interface </title>
+      <para>
+        Attributes are sysfs files used to expose chip info and also allowing
+        applications to set various configuration parameters. For device
+        with index X, attributes can be found under
+        <filename>/sys/bus/iio/iio:deviceX/ </filename> directory.
+        Common attributes are:
+        <itemizedlist>
+          <listitem><filename>name</filename>, description of the physical
+            chip.
+          </listitem>
+          <listitem><filename>dev</filename>, shows the major:minor pair
+            associated with <filename>/dev/iio:deviceX</filename> node.
+          </listitem>
+          <listitem><filename>sampling_frequency_available</filename>,
+            available discrete set of sampling frequency values for
+            device.
+          </listitem>
+      </itemizedlist>
+      Available standard attributes for IIO devices are described in the
+      <filename>Documentation/ABI/testing/sysfs-bus-iio </filename> file
+      in the Linux kernel sources.
+      </para>
+    </sect2>
+    <sect2 id="iiochannel"> <title> IIO device channels </title>
+!Finclude/linux/iio/iio.h iio_chan_spec structure.
+      <para>
+        An IIO device channel is a representation of a data channel. An
+        IIO device can have one or multiple channels. For example:
+        <itemizedlist>
+          <listitem>
+          a thermometer sensor has one channel representing the
+          temperature measurement.
+          </listitem>
+          <listitem>
+          a light sensor with two channels indicating the measurements in
+          the visible and infrared spectrum.
+          </listitem>
+          <listitem>
+          an accelerometer can have up to 3 channels representing
+          acceleration on X, Y and Z axes.
+          </listitem>
+        </itemizedlist>
+      An IIO channel is described by the <type> struct iio_chan_spec
+      </type>. A thermometer driver for the temperature sensor in the
+      example above would have to describe its channel as follows:
+      <programlisting>
+      static const struct iio_chan_spec temp_channel[] = {
+          {
+              .type = IIO_TEMP,
+              .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+          },
+      };
+
+      </programlisting>
+      Channel sysfs attributes exposed to userspace are specified in
+      the form of <emphasis>bitmasks</emphasis>. Depending on their
+      shared info, attributes can be set in one of the following masks:
+      <itemizedlist>
+      <listitem><emphasis>info_mask_separate</emphasis>, attributes will
+        be specific to this channel</listitem>
+      <listitem><emphasis>info_mask_shared_by_type</emphasis>,
+        attributes are shared by all channels of the same type</listitem>
+      <listitem><emphasis>info_mask_shared_by_dir</emphasis>, attributes
+        are shared by all channels of the same direction </listitem>
+      <listitem><emphasis>info_mask_shared_by_all</emphasis>,
+        attributes are shared by all channels</listitem>
+      </itemizedlist>
+      When there are multiple data channels per channel type we have two
+      ways to distinguish between them:
+      <itemizedlist>
+      <listitem> set <emphasis> .modified</emphasis> field of <type>
+        iio_chan_spec</type> to 1. Modifiers are specified using
+        <emphasis>.channel2</emphasis> field of the same
+        <type>iio_chan_spec</type> structure and are used to indicate a
+        physically unique characteristic of the channel such as its direction
+        or spectral response. For example, a light sensor can have two channels,
+        one for infrared light and one for both infrared and visible light.
+      </listitem>
+      <listitem> set <emphasis>.indexed </emphasis> field of
+        <type>iio_chan_spec</type> to 1. In this case the channel is
+        simply another instance with an index specified by the
+        <emphasis>.channel</emphasis> field.
+      </listitem>
+      </itemizedlist>
+      Here is how we can make use of the channel's modifiers:
+      <programlisting>
+      static const struct iio_chan_spec light_channels[] = {
+          {
+              .type = IIO_INTENSITY,
+              .modified = 1,
+              .channel2 = IIO_MOD_LIGHT_IR,
+              .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+              .info_mask_shared = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+          },
+          {
+              .type = IIO_INTENSITY,
+              .modified = 1,
+              .channel2 = IIO_MOD_LIGHT_BOTH,
+              .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+              .info_mask_shared = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+          },
+          {
+              .type = IIO_LIGHT,
+              .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+              .info_mask_shared = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+          },
+
+      }
+      </programlisting>
+      This channel's definition will generate two separate sysfs files
+      for raw data retrieval:
+      <itemizedlist>
+      <listitem>
+      <filename>/sys/bus/iio/iio:deviceX/in_intensity_ir_raw</filename>
+      </listitem>
+      <listitem>
+      <filename>/sys/bus/iio/iio:deviceX/in_intensity_both_raw</filename>
+      </listitem>
+      </itemizedlist>
+      one file for processed data:
+      <itemizedlist>
+      <listitem>
+      <filename>/sys/bus/iio/iio:deviceX/in_illuminance_input
+      </filename>
+      </listitem>
+      </itemizedlist>
+      and one shared sysfs file for sampling frequency:
+      <itemizedlist>
+      <listitem>
+      <filename>/sys/bus/iio/iio:deviceX/sampling_frequency.
+      </filename>
+      </listitem>
+      </itemizedlist>
+      </para>
+      <para>
+      Here is how we can make use of the channel's indexing:
+      <programlisting>
+      static const struct iio_chan_spec light_channels[] = {
+          {
+              .type = IIO_VOLTAGE,
+              .indexed = 1,
+              .channel = 0,
+              .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+          },
+          {
+              .type = IIO_VOLTAGE,
+              .indexed = 1,
+              .channel = 1,
+              .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+          },
+      }
+      </programlisting>
+      This will generate two separate attributes files for raw data
+      retrieval:
+      <itemizedlist>
+      <listitem>
+        <filename>/sys/bus/iio/devices/iio:deviceX/in_voltage0_raw</filename>,
+          representing voltage measurement for channel 0.
+      </listitem>
+      <listitem>
+        <filename>/sys/bus/iio/devices/iio:deviceX/in_voltage1_raw</filename>,
+          representing voltage measurement for channel 1.
+      </listitem>
+      </itemizedlist>
+      </para>
+    </sect2>
+  </sect1>
+
+  <sect1 id="iiobuffer"> <title> Industrial I/O buffers </title>
+!Finclude/linux/iio/buffer.h iio_buffer
+!Edrivers/iio/industrialio-buffer.c
+
+    <para>
+    The Industrial I/O core offers a way for continuous data capture
+    based on a trigger source. Multiple data channels can be read at once
+    from <filename>/dev/iio:deviceX</filename> character device node,
+    thus reducing the CPU load.
+    </para>
+
+    <sect2 id="iiobuffersysfs">
+    <title>IIO buffer sysfs interface </title>
+    <para>
+      An IIO buffer has an associated attributes directory under <filename>
+      /sys/bus/iio/iio:deviceX/buffer/</filename>. Here are the existing
+      attributes:
+      <itemizedlist>
+      <listitem>
+      <emphasis>length</emphasis>, the total number of data samples
+      (capacity) that can be stored by the buffer.
+      </listitem>
+      <listitem>
+        <emphasis>enable</emphasis>, activate buffer capture.
+      </listitem>
+      </itemizedlist>
+
+    </para>
+    </sect2>
+    <sect2 id="iiobuffersetup"> <title> IIO buffer setup </title>
+      <para>The meta information associated with a channel reading
+        placed in a buffer is called a <emphasis> scan element </emphasis>.
+        The important bits configuring scan elements are exposed to
+        userspace applications via the <filename>
+        /sys/bus/iio/iio:deviceX/scan_elements/</filename> directory. This
+        file contains attributes of the following form:
+      <itemizedlist>
+      <listitem><emphasis>enable</emphasis>, used for enabling a channel.
+        If and only if its attribute is non zero, then a triggered capture
+        will contain data samples for this channel.
+      </listitem>
+      <listitem><emphasis>type</emphasis>, description of the scan element
+        data storage within the buffer and hence the form in which it is
+        read from user space. Format is <emphasis>
+        [be|le]:[s|u]bits/storagebitsXrepeat[>>shift] </emphasis>.
+        <itemizedlist>
+        <listitem> <emphasis>be</emphasis> or <emphasis>le</emphasis>, specifies
+          big or little endian.
+        </listitem>
+        <listitem>
+        <emphasis>s </emphasis>or <emphasis>u</emphasis>, specifies if
+          signed (2's complement) or unsigned.
+        </listitem>
+        <listitem><emphasis>bits</emphasis>, is the number of valid data
+          bits.
+        </listitem>
+        <listitem><emphasis>storagebits</emphasis>, is the number of bits
+          (after padding) that it occupies in the buffer.
+        </listitem>
+        <listitem>
+        <emphasis>shift</emphasis>, if specified, is the shift that needs
+          to be applied prior to masking out unused bits.
+        </listitem>
+        <listitem>
+        <emphasis>repeat</emphasis>, specifies the number of bits/storagebits
+        repetitions. When the repeat element is 0 or 1, then the repeat
+        value is omitted.
+        </listitem>
+        </itemizedlist>
+      </listitem>
+      </itemizedlist>
+      For example, a driver for a 3-axis accelerometer with 12 bit
+      resolution where data is stored in two 8-bits registers as
+      follows:
+      <programlisting>
+        7   6   5   4   3   2   1   0
+      +---+---+---+---+---+---+---+---+
+      |D3 |D2 |D1 |D0 | X | X | X | X | (LOW byte, address 0x06)
+      +---+---+---+---+---+---+---+---+
+
+        7   6   5   4   3   2   1   0
+      +---+---+---+---+---+---+---+---+
+      |D11|D10|D9 |D8 |D7 |D6 |D5 |D4 | (HIGH byte, address 0x07)
+      +---+---+---+---+---+---+---+---+
+      </programlisting>
+
+      will have the following scan element type for each axis:
+      <programlisting>
+      $ cat /sys/bus/iio/devices/iio:device0/scan_elements/in_accel_y_type
+      le:s12/16>>4
+      </programlisting>
+      A user space application will interpret data samples read from the
+      buffer as two byte little endian signed data, that needs a 4 bits
+      right shift before masking out the 12 valid bits of data.
+    </para>
+    <para>
+      For implementing buffer support a driver should initialize the following
+      fields in <type>iio_chan_spec</type> definition:
+      <programlisting>
+          struct iio_chan_spec {
+              /* other members */
+              int scan_index
+              struct {
+                  char sign;
+                  u8 realbits;
+                  u8 storagebits;
+                  u8 shift;
+                  u8 repeat;
+                  enum iio_endian endianness;
+              } scan_type;
+          };
+      </programlisting>
+      The driver implementing the accelerometer described above will
+      have the following channel definition:
+      <programlisting>
+      struct struct iio_chan_spec accel_channels[] = {
+          {
+            .type = IIO_ACCEL,
+            .modified = 1,
+            .channel2 = IIO_MOD_X,
+            /* other stuff here */
+            .scan_index = 0,
+            .scan_type = {
+              .sign = 's',
+              .realbits = 12,
+              .storgebits = 16,
+              .shift = 4,
+              .endianness = IIO_LE,
+            },
+        }
+        /* similar for Y (with channel2 = IIO_MOD_Y, scan_index = 1)
+         * and Z (with channel2 = IIO_MOD_Z, scan_index = 2) axis
+         */
+    }
+    </programlisting>
+    </para>
+    <para>
+    Here <emphasis> scan_index </emphasis> defines the order in which
+    the enabled channels are placed inside the buffer. Channels with a lower
+    scan_index will be placed before channels with a higher index. Each
+    channel needs to have a unique scan_index.
+    </para>
+    <para>
+    Setting scan_index to -1 can be used to indicate that the specific
+    channel does not support buffered capture. In this case no entries will
+    be created for the channel in the scan_elements directory.
+    </para>
+    </sect2>
+  </sect1>
+
+  <sect1 id="iiotrigger"> <title> Industrial I/O triggers  </title>
+!Finclude/linux/iio/trigger.h iio_trigger
+!Edrivers/iio/industrialio-trigger.c
+    <para>
+      In many situations it is useful for a driver to be able to
+      capture data based on some external event (trigger) as opposed
+      to periodically polling for data. An IIO trigger can be provided
+      by a device driver that also has an IIO device based on hardware
+      generated events (e.g. data ready or threshold exceeded) or
+      provided by a separate driver from an independent interrupt
+      source (e.g. GPIO line connected to some external system, timer
+      interrupt or user space writing a specific file in sysfs). A
+      trigger may initiate data capture for a number of sensors and
+      also it may be completely unrelated to the sensor itself.
+    </para>
+
+    <sect2 id="iiotrigsysfs"> <title> IIO trigger sysfs interface </title>
+      There are two locations in sysfs related to triggers:
+      <itemizedlist>
+        <listitem><filename>/sys/bus/iio/devices/triggerY</filename>,
+          this file is created once an IIO trigger is registered with
+          the IIO core and corresponds to trigger with index Y. Because
+          triggers can be very different depending on type there are few
+          standard attributes that we can describe here:
+          <itemizedlist>
+            <listitem>
+              <emphasis>name</emphasis>, trigger name that can be later
+                used for association with a device.
+            </listitem>
+            <listitem>
+            <emphasis>sampling_frequency</emphasis>, some timer based
+              triggers use this attribute to specify the frequency for
+              trigger calls.
+            </listitem>
+          </itemizedlist>
+        </listitem>
+        <listitem>
+          <filename>/sys/bus/iio/devices/iio:deviceX/trigger/</filename>, this
+          directory is created once the device supports a triggered
+          buffer. We can associate a trigger with our device by writing
+          the trigger's name in the <filename>current_trigger</filename> file.
+        </listitem>
+      </itemizedlist>
+    </sect2>
+
+    <sect2 id="iiotrigattr"> <title> IIO trigger setup</title>
+
+    <para>
+      Let's see a simple example of how to setup a trigger to be used
+      by a driver.
+
+      <programlisting>
+      struct iio_trigger_ops trigger_ops = {
+          .set_trigger_state = sample_trigger_state,
+          .validate_device = sample_validate_device,
+      }
+
+      struct iio_trigger *trig;
+
+      /* first, allocate memory for our trigger */
+      trig = iio_trigger_alloc(dev, "trig-%s-%d", name, idx);
+
+      /* setup trigger operations field */
+      trig->ops = &amp;trigger_ops;
+
+      /* now register the trigger with the IIO core */
+      iio_trigger_register(trig);
+      </programlisting>
+    </para>
+    </sect2>
+
+    <sect2 id="iiotrigsetup"> <title> IIO trigger ops</title>
+!Finclude/linux/iio/trigger.h iio_trigger_ops
+     <para>
+        Notice that a trigger has a set of operations attached:
+        <itemizedlist>
+        <listitem>
+          <function>set_trigger_state</function>, switch the trigger on/off
+          on demand.
+        </listitem>
+        <listitem>
+          <function>validate_device</function>, function to validate the
+          device when the current trigger gets changed.
+        </listitem>
+        </itemizedlist>
+      </para>
+    </sect2>
+  </sect1>
+  <sect1 id="iiotriggered_buffer">
+    <title> Industrial I/O triggered buffers </title>
+    <para>
+    Now that we know what buffers and triggers are let's see how they
+    work together.
+    </para>
+    <sect2 id="iiotrigbufsetup"> <title> IIO triggered buffer setup</title>
+!Edrivers/iio/industrialio-triggered-buffer.c
+!Finclude/linux/iio/iio.h iio_buffer_setup_ops
+
+
+    <para>
+    A typical triggered buffer setup looks like this:
+    <programlisting>
+    const struct iio_buffer_setup_ops sensor_buffer_setup_ops = {
+      .preenable    = sensor_buffer_preenable,
+      .postenable   = sensor_buffer_postenable,
+      .postdisable  = sensor_buffer_postdisable,
+      .predisable   = sensor_buffer_predisable,
+    };
+
+    irqreturn_t sensor_iio_pollfunc(int irq, void *p)
+    {
+        pf->timestamp = iio_get_time_ns();
+        return IRQ_WAKE_THREAD;
+    }
+
+    irqreturn_t sensor_trigger_handler(int irq, void *p)
+    {
+        u16 buf[8];
+        int i = 0;
+
+        /* read data for each active channel */
+        for_each_set_bit(bit, active_scan_mask, masklength)
+            buf[i++] = sensor_get_data(bit)
+
+        iio_push_to_buffers_with_timestamp(indio_dev, buf, timestamp);
+
+        iio_trigger_notify_done(trigger);
+        return IRQ_HANDLED;
+    }
+
+    /* setup triggered buffer, usually in probe function */
+    iio_triggered_buffer_setup(indio_dev, sensor_iio_polfunc,
+                               sensor_trigger_handler,
+                               sensor_buffer_setup_ops);
+    </programlisting>
+    </para>
+    The important things to notice here are:
+    <itemizedlist>
+    <listitem><function> iio_buffer_setup_ops</function>, the buffer setup
+    functions to be called at predefined points in the buffer configuration
+    sequence (e.g. before enable, after disable). If not specified, the
+    IIO core uses the default <type>iio_triggered_buffer_setup_ops</type>.
+    </listitem>
+    <listitem><function>sensor_iio_pollfunc</function>, the function that
+    will be used as top half of poll function. It should do as little
+    processing as possible, because it runs in interrupt context. The most
+    common operation is recording of the current timestamp and for this reason
+    one can use the IIO core defined <function>iio_pollfunc_store_time
+    </function> function.
+    </listitem>
+    <listitem><function>sensor_trigger_handler</function>, the function that
+    will be used as bottom half of the poll function. This runs in the
+    context of a kernel thread and all the processing takes place here.
+    It usually reads data from the device and stores it in the internal
+    buffer together with the timestamp recorded in the top half.
+    </listitem>
+    </itemizedlist>
+    </sect2>
+  </sect1>
+  </chapter>
+  <chapter id='iioresources'>
+    <title> Resources </title>
+      IIO core may change during time so the best documentation to read is the
+      source code. There are several locations where you should look:
+      <itemizedlist>
+        <listitem>
+          <filename>drivers/iio/</filename>, contains the IIO core plus
+          and directories for each sensor type (e.g. accel, magnetometer,
+          etc.)
+        </listitem>
+        <listitem>
+          <filename>include/linux/iio/</filename>, contains the header
+          files, nice to read for the internal kernel interfaces.
+        </listitem>
+        <listitem>
+        <filename>include/uapi/linux/iio/</filename>, contains files to be
+          used by user space applications.
+        </listitem>
+        <listitem>
+         <filename>tools/iio/</filename>, contains tools for rapidly
+          testing buffers, events and device creation.
+        </listitem>
+        <listitem>
+          <filename>drivers/staging/iio/</filename>, contains code for some
+          drivers or experimental features that are not yet mature enough
+          to be moved out.
+        </listitem>
+      </itemizedlist>
+    <para>
+    Besides the code, there are some good online documentation sources:
+    <itemizedlist>
+    <listitem>
+      <ulink url="http://marc.info/?l=linux-iio"> Industrial I/O mailing
+      list </ulink>
+    </listitem>
+    <listitem>
+      <ulink url="http://wiki.analog.com/software/linux/docs/iio/iio">
+      Analog Device IIO wiki page </ulink>
+    </listitem>
+    <listitem>
+      <ulink url="https://fosdem.org/2015/schedule/event/iiosdr/">
+      Using the Linux IIO framework for SDR, Lars-Peter Clausen's
+      presentation at FOSDEM </ulink>
+    </listitem>
+    </itemizedlist>
+    </para>
+  </chapter>
+</book>
+
+<!--
+vim: softtabstop=2:shiftwidth=2:expandtab:textwidth=72
+-->

+ 1 - 0
Documentation/devicetree/bindings/iio/adc/mcp320x.txt

@@ -18,6 +18,7 @@ Required properties:
 				"mcp3202"
 				"mcp3202"
 				"mcp3204"
 				"mcp3204"
 				"mcp3208"
 				"mcp3208"
+				"mcp3301"
 
 
 
 
 Examples:
 Examples:

+ 5 - 0
Documentation/devicetree/bindings/iio/adc/vf610-adc.txt

@@ -17,6 +17,11 @@ Recommended properties:
   - Frequency in normal mode (ADLPC=0, ADHSC=0)
   - Frequency in normal mode (ADLPC=0, ADHSC=0)
   - Frequency in high-speed mode (ADLPC=0, ADHSC=1)
   - Frequency in high-speed mode (ADLPC=0, ADHSC=1)
   - Frequency in low-power mode (ADLPC=1, ADHSC=0)
   - Frequency in low-power mode (ADLPC=1, ADHSC=0)
+- min-sample-time: Minimum sampling time in nanoseconds. This value has
+  to be chosen according to the conversion mode and the connected analog
+  source resistance (R_as) and capacitance (C_as). Refer the datasheet's
+  operating requirements. A safe default across a wide range of R_as and
+  C_as as well as conversion modes is 1000ns.
 
 
 Example:
 Example:
 adc0: adc@4003b000 {
 adc0: adc@4003b000 {

+ 13 - 0
Documentation/devicetree/bindings/iio/magnetometer/mmc35240.txt

@@ -0,0 +1,13 @@
+* MEMSIC MMC35240 magnetometer sensor
+
+Required properties:
+
+  - compatible : should be "memsic,mmc35240"
+  - reg : the I2C address of the magnetometer
+
+Example:
+
+mmc35240@30 {
+        compatible = "memsic,mmc35240";
+        reg = <0x30>;
+};

+ 2 - 0
Documentation/devicetree/bindings/iio/st-sensors.txt

@@ -35,6 +35,7 @@ Accelerometers:
 - st,lsm303dl-accel
 - st,lsm303dl-accel
 - st,lsm303dlm-accel
 - st,lsm303dlm-accel
 - st,lsm330-accel
 - st,lsm330-accel
+- st,lsm303agr-accel
 
 
 Gyroscopes:
 Gyroscopes:
 - st,l3g4200d-gyro
 - st,l3g4200d-gyro
@@ -46,6 +47,7 @@ Gyroscopes:
 - st,lsm330-gyro
 - st,lsm330-gyro
 
 
 Magnetometers:
 Magnetometers:
+- st,lsm303agr-magn
 - st,lsm303dlh-magn
 - st,lsm303dlh-magn
 - st,lsm303dlhc-magn
 - st,lsm303dlhc-magn
 - st,lsm303dlm-magn
 - st,lsm303dlm-magn

+ 1 - 1
Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt

@@ -1,4 +1,4 @@
-* Freescale i.MX28 LRADC device driver
+* Freescale MXS LRADC device driver
 
 
 Required properties:
 Required properties:
 - compatible: Should be "fsl,imx23-lradc" for i.MX23 SoC and "fsl,imx28-lradc"
 - compatible: Should be "fsl,imx23-lradc" for i.MX23 SoC and "fsl,imx28-lradc"

+ 14 - 12
drivers/iio/accel/Kconfig

@@ -86,18 +86,6 @@ config KXSD9
 	  To compile this driver as a module, choose M here: the module
 	  To compile this driver as a module, choose M here: the module
 	  will be called kxsd9.
 	  will be called kxsd9.
 
 
-config MMA8452
-	tristate "Freescale MMA8452Q Accelerometer 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.
-
-	  To compile this driver as a module, choose M here: the module
-	  will be called mma8452.
-
 config KXCJK1013
 config KXCJK1013
 	tristate "Kionix 3-Axis Accelerometer Driver"
 	tristate "Kionix 3-Axis Accelerometer Driver"
 	depends on I2C
 	depends on I2C
@@ -111,6 +99,18 @@ config KXCJK1013
 	  To compile this driver as a module, choose M here: the module will
 	  To compile this driver as a module, choose M here: the module will
 	  be called kxcjk-1013.
 	  be called kxcjk-1013.
 
 
+config MMA8452
+	tristate "Freescale MMA8452Q Accelerometer 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.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called mma8452.
+
 config MMA9551_CORE
 config MMA9551_CORE
 	tristate
 	tristate
 
 
@@ -140,6 +140,8 @@ config MMA9553
 config STK8312
 config STK8312
 	tristate "Sensortek STK8312 3-Axis Accelerometer Driver"
 	tristate "Sensortek STK8312 3-Axis Accelerometer Driver"
 	depends on I2C
 	depends on I2C
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
 	help
 	help
 	  Say yes here to get support for the Sensortek STK8312 3-axis
 	  Say yes here to get support for the Sensortek STK8312 3-axis
 	  accelerometer.
 	  accelerometer.

+ 74 - 82
drivers/iio/accel/bmc150-accel.c

@@ -151,6 +151,7 @@ struct bmc150_scale_info {
 };
 };
 
 
 struct bmc150_accel_chip_info {
 struct bmc150_accel_chip_info {
+	const char *name;
 	u8 chip_id;
 	u8 chip_id;
 	const struct iio_chan_spec *channels;
 	const struct iio_chan_spec *channels;
 	int num_channels;
 	int num_channels;
@@ -345,63 +346,6 @@ static int bmc150_accel_any_motion_setup(struct bmc150_accel_trigger *t,
 	return 0;
 	return 0;
 }
 }
 
 
-static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
-{
-	int ret;
-
-	ret = i2c_smbus_read_byte_data(data->client, BMC150_ACCEL_REG_CHIP_ID);
-	if (ret < 0) {
-		dev_err(&data->client->dev, "Error: Reading chip id\n");
-		return ret;
-	}
-
-	dev_dbg(&data->client->dev, "Chip Id %x\n", ret);
-	if (ret != data->chip_info->chip_id) {
-		dev_err(&data->client->dev, "Invalid chip %x\n", ret);
-		return -ENODEV;
-	}
-
-	ret = bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_NORMAL, 0);
-	if (ret < 0)
-		return ret;
-
-	/* Set Bandwidth */
-	ret = bmc150_accel_set_bw(data, BMC150_ACCEL_DEF_BW, 0);
-	if (ret < 0)
-		return ret;
-
-	/* Set Default Range */
-	ret = i2c_smbus_write_byte_data(data->client,
-					BMC150_ACCEL_REG_PMU_RANGE,
-					BMC150_ACCEL_DEF_RANGE_4G);
-	if (ret < 0) {
-		dev_err(&data->client->dev, "Error writing reg_pmu_range\n");
-		return ret;
-	}
-
-	data->range = BMC150_ACCEL_DEF_RANGE_4G;
-
-	/* Set default slope duration and thresholds */
-	data->slope_thres = BMC150_ACCEL_DEF_SLOPE_THRESHOLD;
-	data->slope_dur = BMC150_ACCEL_DEF_SLOPE_DURATION;
-	ret = bmc150_accel_update_slope(data);
-	if (ret < 0)
-		return ret;
-
-	/* Set default as latched interrupts */
-	ret = i2c_smbus_write_byte_data(data->client,
-					BMC150_ACCEL_REG_INT_RST_LATCH,
-					BMC150_ACCEL_INT_MODE_LATCH_INT |
-					BMC150_ACCEL_INT_MODE_LATCH_RESET);
-	if (ret < 0) {
-		dev_err(&data->client->dev,
-			"Error writing reg_int_rst_latch\n");
-		return ret;
-	}
-
-	return 0;
-}
-
 static int bmc150_accel_get_bw(struct bmc150_accel_data *data, int *val,
 static int bmc150_accel_get_bw(struct bmc150_accel_data *data, int *val,
 			       int *val2)
 			       int *val2)
 {
 {
@@ -1119,6 +1063,7 @@ enum {
 
 
 static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = {
 static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = {
 	[bmc150] = {
 	[bmc150] = {
+		.name = "BMC150A",
 		.chip_id = 0xFA,
 		.chip_id = 0xFA,
 		.channels = bmc150_accel_channels,
 		.channels = bmc150_accel_channels,
 		.num_channels = ARRAY_SIZE(bmc150_accel_channels),
 		.num_channels = ARRAY_SIZE(bmc150_accel_channels),
@@ -1128,6 +1073,7 @@ static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = {
 				 {76590, BMC150_ACCEL_DEF_RANGE_16G} },
 				 {76590, BMC150_ACCEL_DEF_RANGE_16G} },
 	},
 	},
 	[bmi055] = {
 	[bmi055] = {
+		.name = "BMI055A",
 		.chip_id = 0xFA,
 		.chip_id = 0xFA,
 		.channels = bmc150_accel_channels,
 		.channels = bmc150_accel_channels,
 		.num_channels = ARRAY_SIZE(bmc150_accel_channels),
 		.num_channels = ARRAY_SIZE(bmc150_accel_channels),
@@ -1137,6 +1083,7 @@ static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = {
 				 {76590, BMC150_ACCEL_DEF_RANGE_16G} },
 				 {76590, BMC150_ACCEL_DEF_RANGE_16G} },
 	},
 	},
 	[bma255] = {
 	[bma255] = {
+		.name = "BMA0255",
 		.chip_id = 0xFA,
 		.chip_id = 0xFA,
 		.channels = bmc150_accel_channels,
 		.channels = bmc150_accel_channels,
 		.num_channels = ARRAY_SIZE(bmc150_accel_channels),
 		.num_channels = ARRAY_SIZE(bmc150_accel_channels),
@@ -1146,6 +1093,7 @@ static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = {
 				 {76590, BMC150_ACCEL_DEF_RANGE_16G} },
 				 {76590, BMC150_ACCEL_DEF_RANGE_16G} },
 	},
 	},
 	[bma250e] = {
 	[bma250e] = {
+		.name = "BMA250E",
 		.chip_id = 0xF9,
 		.chip_id = 0xF9,
 		.channels = bma250e_accel_channels,
 		.channels = bma250e_accel_channels,
 		.num_channels = ARRAY_SIZE(bma250e_accel_channels),
 		.num_channels = ARRAY_SIZE(bma250e_accel_channels),
@@ -1155,6 +1103,7 @@ static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = {
 				 {306457, BMC150_ACCEL_DEF_RANGE_16G} },
 				 {306457, BMC150_ACCEL_DEF_RANGE_16G} },
 	},
 	},
 	[bma222e] = {
 	[bma222e] = {
+		.name = "BMA222E",
 		.chip_id = 0xF8,
 		.chip_id = 0xF8,
 		.channels = bma222e_accel_channels,
 		.channels = bma222e_accel_channels,
 		.num_channels = ARRAY_SIZE(bma222e_accel_channels),
 		.num_channels = ARRAY_SIZE(bma222e_accel_channels),
@@ -1164,6 +1113,7 @@ static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = {
 				 {1225831, BMC150_ACCEL_DEF_RANGE_16G} },
 				 {1225831, BMC150_ACCEL_DEF_RANGE_16G} },
 	},
 	},
 	[bma280] = {
 	[bma280] = {
+		.name = "BMA0280",
 		.chip_id = 0xFB,
 		.chip_id = 0xFB,
 		.channels = bma280_accel_channels,
 		.channels = bma280_accel_channels,
 		.num_channels = ARRAY_SIZE(bma280_accel_channels),
 		.num_channels = ARRAY_SIZE(bma280_accel_channels),
@@ -1410,20 +1360,6 @@ static irqreturn_t bmc150_accel_irq_handler(int irq, void *private)
 	return IRQ_NONE;
 	return IRQ_NONE;
 }
 }
 
 
-static const char *bmc150_accel_match_acpi_device(struct device *dev, int *data)
-{
-	const struct acpi_device_id *id;
-
-	id = acpi_match_device(dev->driver->acpi_match_table, dev);
-
-	if (!id)
-		return NULL;
-
-	*data = (int)id->driver_data;
-
-	return dev_name(dev);
-}
-
 static int bmc150_accel_gpio_probe(struct i2c_client *client,
 static int bmc150_accel_gpio_probe(struct i2c_client *client,
 				   struct bmc150_accel_data *data)
 				   struct bmc150_accel_data *data)
 {
 {
@@ -1618,6 +1554,70 @@ static const struct iio_buffer_setup_ops bmc150_accel_buffer_ops = {
 	.postdisable = bmc150_accel_buffer_postdisable,
 	.postdisable = bmc150_accel_buffer_postdisable,
 };
 };
 
 
+static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
+{
+	int ret, i;
+
+	ret = i2c_smbus_read_byte_data(data->client, BMC150_ACCEL_REG_CHIP_ID);
+	if (ret < 0) {
+		dev_err(&data->client->dev, "Error: Reading chip id\n");
+		return ret;
+	}
+
+	dev_dbg(&data->client->dev, "Chip Id %x\n", ret);
+	for (i = 0; i < ARRAY_SIZE(bmc150_accel_chip_info_tbl); i++) {
+		if (bmc150_accel_chip_info_tbl[i].chip_id == ret) {
+			data->chip_info = &bmc150_accel_chip_info_tbl[i];
+			break;
+		}
+	}
+
+	if (!data->chip_info) {
+		dev_err(&data->client->dev, "Unsupported chip %x\n", ret);
+		return -ENODEV;
+	}
+
+	ret = bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_NORMAL, 0);
+	if (ret < 0)
+		return ret;
+
+	/* Set Bandwidth */
+	ret = bmc150_accel_set_bw(data, BMC150_ACCEL_DEF_BW, 0);
+	if (ret < 0)
+		return ret;
+
+	/* Set Default Range */
+	ret = i2c_smbus_write_byte_data(data->client,
+					BMC150_ACCEL_REG_PMU_RANGE,
+					BMC150_ACCEL_DEF_RANGE_4G);
+	if (ret < 0) {
+		dev_err(&data->client->dev, "Error writing reg_pmu_range\n");
+		return ret;
+	}
+
+	data->range = BMC150_ACCEL_DEF_RANGE_4G;
+
+	/* Set default slope duration and thresholds */
+	data->slope_thres = BMC150_ACCEL_DEF_SLOPE_THRESHOLD;
+	data->slope_dur = BMC150_ACCEL_DEF_SLOPE_DURATION;
+	ret = bmc150_accel_update_slope(data);
+	if (ret < 0)
+		return ret;
+
+	/* Set default as latched interrupts */
+	ret = i2c_smbus_write_byte_data(data->client,
+					BMC150_ACCEL_REG_INT_RST_LATCH,
+					BMC150_ACCEL_INT_MODE_LATCH_INT |
+					BMC150_ACCEL_INT_MODE_LATCH_RESET);
+	if (ret < 0) {
+		dev_err(&data->client->dev,
+			"Error writing reg_int_rst_latch\n");
+		return ret;
+	}
+
+	return 0;
+}
+
 static int bmc150_accel_probe(struct i2c_client *client,
 static int bmc150_accel_probe(struct i2c_client *client,
 			      const struct i2c_device_id *id)
 			      const struct i2c_device_id *id)
 {
 {
@@ -1625,7 +1625,6 @@ static int bmc150_accel_probe(struct i2c_client *client,
 	struct iio_dev *indio_dev;
 	struct iio_dev *indio_dev;
 	int ret;
 	int ret;
 	const char *name = NULL;
 	const char *name = NULL;
-	int chip_id = 0;
 
 
 	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
 	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
 	if (!indio_dev)
 	if (!indio_dev)
@@ -1635,15 +1634,8 @@ static int bmc150_accel_probe(struct i2c_client *client,
 	i2c_set_clientdata(client, indio_dev);
 	i2c_set_clientdata(client, indio_dev);
 	data->client = client;
 	data->client = client;
 
 
-	if (id) {
+	if (id)
 		name = id->name;
 		name = id->name;
-		chip_id = id->driver_data;
-	}
-
-	if (ACPI_HANDLE(&client->dev))
-		name = bmc150_accel_match_acpi_device(&client->dev, &chip_id);
-
-	data->chip_info = &bmc150_accel_chip_info_tbl[chip_id];
 
 
 	ret = bmc150_accel_chip_init(data);
 	ret = bmc150_accel_chip_init(data);
 	if (ret < 0)
 	if (ret < 0)
@@ -1654,7 +1646,7 @@ static int bmc150_accel_probe(struct i2c_client *client,
 	indio_dev->dev.parent = &client->dev;
 	indio_dev->dev.parent = &client->dev;
 	indio_dev->channels = data->chip_info->channels;
 	indio_dev->channels = data->chip_info->channels;
 	indio_dev->num_channels = data->chip_info->num_channels;
 	indio_dev->num_channels = data->chip_info->num_channels;
-	indio_dev->name = name;
+	indio_dev->name = name ? name : data->chip_info->name;
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->info = &bmc150_accel_info;
 	indio_dev->info = &bmc150_accel_info;
 
 
@@ -1670,7 +1662,7 @@ static int bmc150_accel_probe(struct i2c_client *client,
 	if (client->irq < 0)
 	if (client->irq < 0)
 		client->irq = bmc150_accel_gpio_probe(client, data);
 		client->irq = bmc150_accel_gpio_probe(client, data);
 
 
-	if (client->irq >= 0) {
+	if (client->irq > 0) {
 		ret = devm_request_threaded_irq(
 		ret = devm_request_threaded_irq(
 						&client->dev, client->irq,
 						&client->dev, client->irq,
 						bmc150_accel_irq_handler,
 						bmc150_accel_irq_handler,

+ 1 - 1
drivers/iio/accel/kxcjk-1013.c

@@ -1240,7 +1240,7 @@ static int kxcjk1013_probe(struct i2c_client *client,
 	if (client->irq < 0)
 	if (client->irq < 0)
 		client->irq = kxcjk1013_gpio_probe(client, data);
 		client->irq = kxcjk1013_gpio_probe(client, data);
 
 
-	if (client->irq >= 0) {
+	if (client->irq > 0) {
 		ret = devm_request_threaded_irq(&client->dev, client->irq,
 		ret = devm_request_threaded_irq(&client->dev, client->irq,
 						kxcjk1013_data_rdy_trig_poll,
 						kxcjk1013_data_rdy_trig_poll,
 						kxcjk1013_event_handler,
 						kxcjk1013_event_handler,

+ 123 - 94
drivers/iio/accel/mma8452.c

@@ -16,7 +16,6 @@
 #include <linux/i2c.h>
 #include <linux/i2c.h>
 #include <linux/iio/iio.h>
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 #include <linux/iio/sysfs.h>
-#include <linux/iio/trigger_consumer.h>
 #include <linux/iio/buffer.h>
 #include <linux/iio/buffer.h>
 #include <linux/iio/trigger.h>
 #include <linux/iio/trigger.h>
 #include <linux/iio/trigger_consumer.h>
 #include <linux/iio/trigger_consumer.h>
@@ -24,54 +23,51 @@
 #include <linux/iio/events.h>
 #include <linux/iio/events.h>
 #include <linux/delay.h>
 #include <linux/delay.h>
 
 
-#define MMA8452_STATUS 0x00
-#define MMA8452_OUT_X 0x01 /* MSB first, 12-bit  */
-#define MMA8452_OUT_Y 0x03
-#define MMA8452_OUT_Z 0x05
-#define MMA8452_INT_SRC 0x0c
-#define MMA8452_WHO_AM_I 0x0d
-#define MMA8452_DATA_CFG 0x0e
-#define MMA8452_HP_FILTER_CUTOFF 0x0f
-#define MMA8452_HP_FILTER_CUTOFF_SEL_MASK	(BIT(0) | BIT(1))
-#define MMA8452_TRANSIENT_CFG 0x1d
-#define MMA8452_TRANSIENT_CFG_ELE		BIT(4)
-#define MMA8452_TRANSIENT_CFG_CHAN(chan)	BIT(chan + 1)
-#define MMA8452_TRANSIENT_CFG_HPF_BYP		BIT(0)
-#define MMA8452_TRANSIENT_SRC 0x1e
-#define MMA8452_TRANSIENT_SRC_XTRANSE		BIT(1)
-#define MMA8452_TRANSIENT_SRC_YTRANSE		BIT(3)
-#define MMA8452_TRANSIENT_SRC_ZTRANSE		BIT(5)
-#define MMA8452_TRANSIENT_THS 0x1f
-#define MMA8452_TRANSIENT_THS_MASK	0x7f
-#define MMA8452_TRANSIENT_COUNT 0x20
-#define MMA8452_OFF_X 0x2f
-#define MMA8452_OFF_Y 0x30
-#define MMA8452_OFF_Z 0x31
-#define MMA8452_CTRL_REG1 0x2a
-#define MMA8452_CTRL_REG2 0x2b
-#define MMA8452_CTRL_REG2_RST		BIT(6)
-#define MMA8452_CTRL_REG4 0x2d
-#define MMA8452_CTRL_REG5 0x2e
-
-#define MMA8452_MAX_REG 0x31
-
-#define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0))
-
-#define MMA8452_CTRL_DR_MASK (BIT(5) | BIT(4) | BIT(3))
-#define MMA8452_CTRL_DR_SHIFT 3
-#define MMA8452_CTRL_DR_DEFAULT 0x4 /* 50 Hz sample frequency */
-#define MMA8452_CTRL_ACTIVE BIT(0)
-
-#define MMA8452_DATA_CFG_FS_MASK (BIT(1) | BIT(0))
-#define MMA8452_DATA_CFG_FS_2G 0
-#define MMA8452_DATA_CFG_FS_4G 1
-#define MMA8452_DATA_CFG_FS_8G 2
-#define MMA8452_DATA_CFG_HPF_MASK BIT(4)
-
-#define MMA8452_INT_DRDY	BIT(0)
-#define MMA8452_INT_TRANS	BIT(5)
-
-#define MMA8452_DEVICE_ID 0x2a
+#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_Y				0x03
+#define MMA8452_OUT_Z				0x05
+#define MMA8452_INT_SRC				0x0c
+#define MMA8452_WHO_AM_I			0x0d
+#define MMA8452_DATA_CFG			0x0e
+#define  MMA8452_DATA_CFG_FS_MASK		GENMASK(1, 0)
+#define  MMA8452_DATA_CFG_FS_2G			0
+#define  MMA8452_DATA_CFG_FS_4G			1
+#define  MMA8452_DATA_CFG_FS_8G			2
+#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_TRANSIENT_CFG			0x1d
+#define  MMA8452_TRANSIENT_CFG_HPF_BYP		BIT(0)
+#define  MMA8452_TRANSIENT_CFG_CHAN(chan)	BIT(chan + 1)
+#define  MMA8452_TRANSIENT_CFG_ELE		BIT(4)
+#define MMA8452_TRANSIENT_SRC			0x1e
+#define  MMA8452_TRANSIENT_SRC_XTRANSE		BIT(1)
+#define  MMA8452_TRANSIENT_SRC_YTRANSE		BIT(3)
+#define  MMA8452_TRANSIENT_SRC_ZTRANSE		BIT(5)
+#define MMA8452_TRANSIENT_THS			0x1f
+#define  MMA8452_TRANSIENT_THS_MASK		GENMASK(6, 0)
+#define MMA8452_TRANSIENT_COUNT			0x20
+#define MMA8452_CTRL_REG1			0x2a
+#define  MMA8452_CTRL_ACTIVE			BIT(0)
+#define  MMA8452_CTRL_DR_MASK			GENMASK(5, 3)
+#define  MMA8452_CTRL_DR_SHIFT			3
+#define  MMA8452_CTRL_DR_DEFAULT		0x4 /* 50 Hz sample frequency */
+#define MMA8452_CTRL_REG2			0x2b
+#define  MMA8452_CTRL_REG2_RST			BIT(6)
+#define MMA8452_CTRL_REG4			0x2d
+#define MMA8452_CTRL_REG5			0x2e
+#define MMA8452_OFF_X				0x2f
+#define MMA8452_OFF_Y				0x30
+#define MMA8452_OFF_Z				0x31
+
+#define MMA8452_MAX_REG				0x31
+
+#define  MMA8452_INT_DRDY			BIT(0)
+#define  MMA8452_INT_TRANS			BIT(5)
+
+#define  MMA8452_DEVICE_ID			0x2a
 
 
 struct mma8452_data {
 struct mma8452_data {
 	struct i2c_client *client;
 	struct i2c_client *client;
@@ -91,30 +87,34 @@ static int mma8452_drdy(struct mma8452_data *data)
 			return ret;
 			return ret;
 		if ((ret & MMA8452_STATUS_DRDY) == MMA8452_STATUS_DRDY)
 		if ((ret & MMA8452_STATUS_DRDY) == MMA8452_STATUS_DRDY)
 			return 0;
 			return 0;
+
 		msleep(20);
 		msleep(20);
 	}
 	}
 
 
 	dev_err(&data->client->dev, "data not ready\n");
 	dev_err(&data->client->dev, "data not ready\n");
+
 	return -EIO;
 	return -EIO;
 }
 }
 
 
 static int mma8452_read(struct mma8452_data *data, __be16 buf[3])
 static int mma8452_read(struct mma8452_data *data, __be16 buf[3])
 {
 {
 	int ret = mma8452_drdy(data);
 	int ret = mma8452_drdy(data);
+
 	if (ret < 0)
 	if (ret < 0)
 		return ret;
 		return ret;
-	return i2c_smbus_read_i2c_block_data(data->client,
-		MMA8452_OUT_X, 3 * sizeof(__be16), (u8 *) buf);
+
+	return i2c_smbus_read_i2c_block_data(data->client, MMA8452_OUT_X,
+					     3 * sizeof(__be16), (u8 *)buf);
 }
 }
 
 
-static ssize_t mma8452_show_int_plus_micros(char *buf,
-	const int (*vals)[2], int n)
+static ssize_t mma8452_show_int_plus_micros(char *buf, const int (*vals)[2],
+					    int n)
 {
 {
 	size_t len = 0;
 	size_t len = 0;
 
 
 	while (n-- > 0)
 	while (n-- > 0)
-		len += scnprintf(buf + len, PAGE_SIZE - len,
-			"%d.%06d ", vals[n][0], vals[n][1]);
+		len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%06d ",
+				 vals[n][0], vals[n][1]);
 
 
 	/* replace trailing space by newline */
 	/* replace trailing space by newline */
 	buf[len - 1] = '\n';
 	buf[len - 1] = '\n';
@@ -123,7 +123,7 @@ static ssize_t mma8452_show_int_plus_micros(char *buf,
 }
 }
 
 
 static int mma8452_get_int_plus_micros_index(const int (*vals)[2], int n,
 static int mma8452_get_int_plus_micros_index(const int (*vals)[2], int n,
-					int val, int val2)
+					     int val, int val2)
 {
 {
 	while (n-- > 0)
 	while (n-- > 0)
 		if (val == vals[n][0] && val2 == vals[n][1])
 		if (val == vals[n][0] && val2 == vals[n][1])
@@ -147,7 +147,7 @@ static const int mma8452_samp_freq[8][2] = {
  * Hardware has fullscale of -2G, -4G, -8G corresponding to raw value -2048
  * Hardware has fullscale of -2G, -4G, -8G corresponding to raw value -2048
  * The userspace interface uses m/s^2 and we declare micro units
  * The userspace interface uses m/s^2 and we declare micro units
  * So scale factor is given by:
  * So scale factor is given by:
- * 	g * N * 1000000 / 2048 for N = 2, 4, 8 and g=9.80665
+ *	g * N * 1000000 / 2048 for N = 2, 4, 8 and g = 9.80665
  */
  */
 static const int mma8452_scales[3][2] = {
 static const int mma8452_scales[3][2] = {
 	{0, 9577}, {0, 19154}, {0, 38307}
 	{0, 9577}, {0, 19154}, {0, 38307}
@@ -178,17 +178,19 @@ static const int mma8452_hp_filter_cutoff[8][4][2] = {
 };
 };
 
 
 static ssize_t mma8452_show_samp_freq_avail(struct device *dev,
 static ssize_t mma8452_show_samp_freq_avail(struct device *dev,
-				struct device_attribute *attr, char *buf)
+					    struct device_attribute *attr,
+					    char *buf)
 {
 {
 	return mma8452_show_int_plus_micros(buf, mma8452_samp_freq,
 	return mma8452_show_int_plus_micros(buf, mma8452_samp_freq,
-		ARRAY_SIZE(mma8452_samp_freq));
+					    ARRAY_SIZE(mma8452_samp_freq));
 }
 }
 
 
 static ssize_t mma8452_show_scale_avail(struct device *dev,
 static ssize_t mma8452_show_scale_avail(struct device *dev,
-				struct device_attribute *attr, char *buf)
+					struct device_attribute *attr,
+					char *buf)
 {
 {
 	return mma8452_show_int_plus_micros(buf, mma8452_scales,
 	return mma8452_show_int_plus_micros(buf, mma8452_scales,
-		ARRAY_SIZE(mma8452_scales));
+					    ARRAY_SIZE(mma8452_scales));
 }
 }
 
 
 static ssize_t mma8452_show_hp_cutoff_avail(struct device *dev,
 static ssize_t mma8452_show_hp_cutoff_avail(struct device *dev,
@@ -205,22 +207,23 @@ static ssize_t mma8452_show_hp_cutoff_avail(struct device *dev,
 
 
 static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(mma8452_show_samp_freq_avail);
 static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(mma8452_show_samp_freq_avail);
 static IIO_DEVICE_ATTR(in_accel_scale_available, S_IRUGO,
 static IIO_DEVICE_ATTR(in_accel_scale_available, S_IRUGO,
-	mma8452_show_scale_avail, NULL, 0);
+		       mma8452_show_scale_avail, NULL, 0);
 static IIO_DEVICE_ATTR(in_accel_filter_high_pass_3db_frequency_available,
 static IIO_DEVICE_ATTR(in_accel_filter_high_pass_3db_frequency_available,
-			S_IRUGO, mma8452_show_hp_cutoff_avail, NULL, 0);
+		       S_IRUGO, mma8452_show_hp_cutoff_avail, NULL, 0);
 
 
 static int mma8452_get_samp_freq_index(struct mma8452_data *data,
 static int mma8452_get_samp_freq_index(struct mma8452_data *data,
-	int val, int val2)
+				       int val, int val2)
 {
 {
 	return mma8452_get_int_plus_micros_index(mma8452_samp_freq,
 	return mma8452_get_int_plus_micros_index(mma8452_samp_freq,
-		ARRAY_SIZE(mma8452_samp_freq), val, val2);
+						 ARRAY_SIZE(mma8452_samp_freq),
+						 val, val2);
 }
 }
 
 
-static int mma8452_get_scale_index(struct mma8452_data *data,
-	int val, int val2)
+static int mma8452_get_scale_index(struct mma8452_data *data, int val, int val2)
 {
 {
 	return mma8452_get_int_plus_micros_index(mma8452_scales,
 	return mma8452_get_int_plus_micros_index(mma8452_scales,
-		ARRAY_SIZE(mma8452_scales), val, val2);
+						 ARRAY_SIZE(mma8452_scales),
+						 val, val2);
 }
 }
 
 
 static int mma8452_get_hp_filter_index(struct mma8452_data *data,
 static int mma8452_get_hp_filter_index(struct mma8452_data *data,
@@ -229,7 +232,7 @@ static int mma8452_get_hp_filter_index(struct mma8452_data *data,
 	int i = mma8452_get_odr_index(data);
 	int i = mma8452_get_odr_index(data);
 
 
 	return mma8452_get_int_plus_micros_index(mma8452_hp_filter_cutoff[i],
 	return mma8452_get_int_plus_micros_index(mma8452_hp_filter_cutoff[i],
-		ARRAY_SIZE(mma8452_scales[0]), val, val2);
+		ARRAY_SIZE(mma8452_hp_filter_cutoff[0]), val, val2);
 }
 }
 
 
 static int mma8452_read_hp_filter(struct mma8452_data *data, int *hz, int *uHz)
 static int mma8452_read_hp_filter(struct mma8452_data *data, int *hz, int *uHz)
@@ -266,25 +269,31 @@ static int mma8452_read_raw(struct iio_dev *indio_dev,
 		mutex_unlock(&data->lock);
 		mutex_unlock(&data->lock);
 		if (ret < 0)
 		if (ret < 0)
 			return ret;
 			return ret;
-		*val = sign_extend32(
-			be16_to_cpu(buffer[chan->scan_index]) >> 4, 11);
+
+		*val = sign_extend32(be16_to_cpu(buffer[chan->scan_index]) >> 4,
+				     11);
+
 		return IIO_VAL_INT;
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
 	case IIO_CHAN_INFO_SCALE:
 		i = data->data_cfg & MMA8452_DATA_CFG_FS_MASK;
 		i = data->data_cfg & MMA8452_DATA_CFG_FS_MASK;
 		*val = mma8452_scales[i][0];
 		*val = mma8452_scales[i][0];
 		*val2 = mma8452_scales[i][1];
 		*val2 = mma8452_scales[i][1];
+
 		return IIO_VAL_INT_PLUS_MICRO;
 		return IIO_VAL_INT_PLUS_MICRO;
 	case IIO_CHAN_INFO_SAMP_FREQ:
 	case IIO_CHAN_INFO_SAMP_FREQ:
 		i = mma8452_get_odr_index(data);
 		i = mma8452_get_odr_index(data);
 		*val = mma8452_samp_freq[i][0];
 		*val = mma8452_samp_freq[i][0];
 		*val2 = mma8452_samp_freq[i][1];
 		*val2 = mma8452_samp_freq[i][1];
+
 		return IIO_VAL_INT_PLUS_MICRO;
 		return IIO_VAL_INT_PLUS_MICRO;
 	case IIO_CHAN_INFO_CALIBBIAS:
 	case IIO_CHAN_INFO_CALIBBIAS:
-		ret = i2c_smbus_read_byte_data(data->client, MMA8452_OFF_X +
-			chan->scan_index);
+		ret = i2c_smbus_read_byte_data(data->client,
+					      MMA8452_OFF_X + chan->scan_index);
 		if (ret < 0)
 		if (ret < 0)
 			return ret;
 			return ret;
+
 		*val = sign_extend32(ret, 7);
 		*val = sign_extend32(ret, 7);
+
 		return IIO_VAL_INT;
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:
 	case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:
 		if (data->data_cfg & MMA8452_DATA_CFG_HPF_MASK) {
 		if (data->data_cfg & MMA8452_DATA_CFG_HPF_MASK) {
@@ -295,21 +304,23 @@ static int mma8452_read_raw(struct iio_dev *indio_dev,
 			*val = 0;
 			*val = 0;
 			*val2 = 0;
 			*val2 = 0;
 		}
 		}
+
 		return IIO_VAL_INT_PLUS_MICRO;
 		return IIO_VAL_INT_PLUS_MICRO;
 	}
 	}
+
 	return -EINVAL;
 	return -EINVAL;
 }
 }
 
 
 static int mma8452_standby(struct mma8452_data *data)
 static int mma8452_standby(struct mma8452_data *data)
 {
 {
 	return i2c_smbus_write_byte_data(data->client, MMA8452_CTRL_REG1,
 	return i2c_smbus_write_byte_data(data->client, MMA8452_CTRL_REG1,
-		data->ctrl_reg1 & ~MMA8452_CTRL_ACTIVE);
+					data->ctrl_reg1 & ~MMA8452_CTRL_ACTIVE);
 }
 }
 
 
 static int mma8452_active(struct mma8452_data *data)
 static int mma8452_active(struct mma8452_data *data)
 {
 {
 	return i2c_smbus_write_byte_data(data->client, MMA8452_CTRL_REG1,
 	return i2c_smbus_write_byte_data(data->client, MMA8452_CTRL_REG1,
-		data->ctrl_reg1);
+					 data->ctrl_reg1);
 }
 }
 
 
 static int mma8452_change_config(struct mma8452_data *data, u8 reg, u8 val)
 static int mma8452_change_config(struct mma8452_data *data, u8 reg, u8 val)
@@ -334,6 +345,7 @@ static int mma8452_change_config(struct mma8452_data *data, u8 reg, u8 val)
 	ret = 0;
 	ret = 0;
 fail:
 fail:
 	mutex_unlock(&data->lock);
 	mutex_unlock(&data->lock);
+
 	return ret;
 	return ret;
 }
 }
 
 
@@ -344,12 +356,13 @@ static int mma8452_set_hp_filter_frequency(struct mma8452_data *data,
 
 
 	i = mma8452_get_hp_filter_index(data, val, val2);
 	i = mma8452_get_hp_filter_index(data, val, val2);
 	if (i < 0)
 	if (i < 0)
-		return -EINVAL;
+		return i;
 
 
 	reg = i2c_smbus_read_byte_data(data->client,
 	reg = i2c_smbus_read_byte_data(data->client,
 				       MMA8452_HP_FILTER_CUTOFF);
 				       MMA8452_HP_FILTER_CUTOFF);
 	if (reg < 0)
 	if (reg < 0)
 		return reg;
 		return reg;
+
 	reg &= ~MMA8452_HP_FILTER_CUTOFF_SEL_MASK;
 	reg &= ~MMA8452_HP_FILTER_CUTOFF_SEL_MASK;
 	reg |= i;
 	reg |= i;
 
 
@@ -370,25 +383,30 @@ static int mma8452_write_raw(struct iio_dev *indio_dev,
 	case IIO_CHAN_INFO_SAMP_FREQ:
 	case IIO_CHAN_INFO_SAMP_FREQ:
 		i = mma8452_get_samp_freq_index(data, val, val2);
 		i = mma8452_get_samp_freq_index(data, val, val2);
 		if (i < 0)
 		if (i < 0)
-			return -EINVAL;
+			return i;
 
 
 		data->ctrl_reg1 &= ~MMA8452_CTRL_DR_MASK;
 		data->ctrl_reg1 &= ~MMA8452_CTRL_DR_MASK;
 		data->ctrl_reg1 |= i << MMA8452_CTRL_DR_SHIFT;
 		data->ctrl_reg1 |= i << MMA8452_CTRL_DR_SHIFT;
+
 		return mma8452_change_config(data, MMA8452_CTRL_REG1,
 		return mma8452_change_config(data, MMA8452_CTRL_REG1,
-			data->ctrl_reg1);
+					     data->ctrl_reg1);
 	case IIO_CHAN_INFO_SCALE:
 	case IIO_CHAN_INFO_SCALE:
 		i = mma8452_get_scale_index(data, val, val2);
 		i = mma8452_get_scale_index(data, val, val2);
 		if (i < 0)
 		if (i < 0)
-			return -EINVAL;
+			return i;
+
 		data->data_cfg &= ~MMA8452_DATA_CFG_FS_MASK;
 		data->data_cfg &= ~MMA8452_DATA_CFG_FS_MASK;
 		data->data_cfg |= i;
 		data->data_cfg |= i;
+
 		return mma8452_change_config(data, MMA8452_DATA_CFG,
 		return mma8452_change_config(data, MMA8452_DATA_CFG,
-			data->data_cfg);
+					     data->data_cfg);
 	case IIO_CHAN_INFO_CALIBBIAS:
 	case IIO_CHAN_INFO_CALIBBIAS:
 		if (val < -128 || val > 127)
 		if (val < -128 || val > 127)
 			return -EINVAL;
 			return -EINVAL;
-		return mma8452_change_config(data, MMA8452_OFF_X +
-			chan->scan_index, val);
+
+		return mma8452_change_config(data,
+					     MMA8452_OFF_X + chan->scan_index,
+					     val);
 
 
 	case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:
 	case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:
 		if (val == 0 && val2 == 0) {
 		if (val == 0 && val2 == 0) {
@@ -399,8 +417,9 @@ static int mma8452_write_raw(struct iio_dev *indio_dev,
 			if (ret < 0)
 			if (ret < 0)
 				return ret;
 				return ret;
 		}
 		}
+
 		return mma8452_change_config(data, MMA8452_DATA_CFG,
 		return mma8452_change_config(data, MMA8452_DATA_CFG,
-						data->data_cfg);
+					     data->data_cfg);
 
 
 	default:
 	default:
 		return -EINVAL;
 		return -EINVAL;
@@ -425,6 +444,7 @@ static int mma8452_read_thresh(struct iio_dev *indio_dev,
 			return ret;
 			return ret;
 
 
 		*val = ret & MMA8452_TRANSIENT_THS_MASK;
 		*val = ret & MMA8452_TRANSIENT_THS_MASK;
+
 		return IIO_VAL_INT;
 		return IIO_VAL_INT;
 
 
 	case IIO_EV_INFO_PERIOD:
 	case IIO_EV_INFO_PERIOD:
@@ -437,6 +457,7 @@ static int mma8452_read_thresh(struct iio_dev *indio_dev,
 				mma8452_get_odr_index(data)];
 				mma8452_get_odr_index(data)];
 		*val = us / USEC_PER_SEC;
 		*val = us / USEC_PER_SEC;
 		*val2 = us % USEC_PER_SEC;
 		*val2 = us % USEC_PER_SEC;
+
 		return IIO_VAL_INT_PLUS_MICRO;
 		return IIO_VAL_INT_PLUS_MICRO;
 
 
 	case IIO_EV_INFO_HIGH_PASS_FILTER_3DB:
 	case IIO_EV_INFO_HIGH_PASS_FILTER_3DB:
@@ -453,6 +474,7 @@ static int mma8452_read_thresh(struct iio_dev *indio_dev,
 			if (ret < 0)
 			if (ret < 0)
 				return ret;
 				return ret;
 		}
 		}
+
 		return IIO_VAL_INT_PLUS_MICRO;
 		return IIO_VAL_INT_PLUS_MICRO;
 
 
 	default:
 	default:
@@ -472,19 +494,22 @@ static int mma8452_write_thresh(struct iio_dev *indio_dev,
 
 
 	switch (info) {
 	switch (info) {
 	case IIO_EV_INFO_VALUE:
 	case IIO_EV_INFO_VALUE:
-		return mma8452_change_config(data, MMA8452_TRANSIENT_THS,
-					     val & MMA8452_TRANSIENT_THS_MASK);
+		if (val < 0 || val > MMA8452_TRANSIENT_THS_MASK)
+			return -EINVAL;
+
+		return mma8452_change_config(data, MMA8452_TRANSIENT_THS, val);
 
 
 	case IIO_EV_INFO_PERIOD:
 	case IIO_EV_INFO_PERIOD:
 		steps = (val * USEC_PER_SEC + val2) /
 		steps = (val * USEC_PER_SEC + val2) /
 				mma8452_transient_time_step_us[
 				mma8452_transient_time_step_us[
 					mma8452_get_odr_index(data)];
 					mma8452_get_odr_index(data)];
 
 
-		if (steps > 0xff)
+		if (steps < 0 || steps > 0xff)
 			return -EINVAL;
 			return -EINVAL;
 
 
 		return mma8452_change_config(data, MMA8452_TRANSIENT_COUNT,
 		return mma8452_change_config(data, MMA8452_TRANSIENT_COUNT,
 					     steps);
 					     steps);
+
 	case IIO_EV_INFO_HIGH_PASS_FILTER_3DB:
 	case IIO_EV_INFO_HIGH_PASS_FILTER_3DB:
 		reg = i2c_smbus_read_byte_data(data->client,
 		reg = i2c_smbus_read_byte_data(data->client,
 					       MMA8452_TRANSIENT_CFG);
 					       MMA8452_TRANSIENT_CFG);
@@ -499,6 +524,7 @@ static int mma8452_write_thresh(struct iio_dev *indio_dev,
 			if (ret < 0)
 			if (ret < 0)
 				return ret;
 				return ret;
 		}
 		}
+
 		return mma8452_change_config(data, MMA8452_TRANSIENT_CFG, reg);
 		return mma8452_change_config(data, MMA8452_TRANSIENT_CFG, reg);
 
 
 	default:
 	default:
@@ -608,15 +634,16 @@ static irqreturn_t mma8452_trigger_handler(int irq, void *p)
 	u8 buffer[16]; /* 3 16-bit channels + padding + ts */
 	u8 buffer[16]; /* 3 16-bit channels + padding + ts */
 	int ret;
 	int ret;
 
 
-	ret = mma8452_read(data, (__be16 *) buffer);
+	ret = mma8452_read(data, (__be16 *)buffer);
 	if (ret < 0)
 	if (ret < 0)
 		goto done;
 		goto done;
 
 
 	iio_push_to_buffers_with_timestamp(indio_dev, buffer,
 	iio_push_to_buffers_with_timestamp(indio_dev, buffer,
-		iio_get_time_ns());
+					   iio_get_time_ns());
 
 
 done:
 done:
 	iio_trigger_notify_done(indio_dev->trig);
 	iio_trigger_notify_done(indio_dev->trig);
+
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;
 }
 }
 
 
@@ -674,10 +701,10 @@ static struct attribute_group mma8452_event_attribute_group = {
 	.modified = 1, \
 	.modified = 1, \
 	.channel2 = IIO_MOD_##axis, \
 	.channel2 = IIO_MOD_##axis, \
 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
-		BIT(IIO_CHAN_INFO_CALIBBIAS), \
+			      BIT(IIO_CHAN_INFO_CALIBBIAS), \
 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
-		BIT(IIO_CHAN_INFO_SCALE) | \
-		BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY), \
+			BIT(IIO_CHAN_INFO_SCALE) | \
+			BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY), \
 	.scan_index = idx, \
 	.scan_index = idx, \
 	.scan_type = { \
 	.scan_type = { \
 		.sign = 's', \
 		.sign = 's', \
@@ -780,6 +807,7 @@ static int mma8452_trigger_setup(struct iio_dev *indio_dev)
 		return ret;
 		return ret;
 
 
 	indio_dev->trig = trig;
 	indio_dev->trig = trig;
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -849,7 +877,7 @@ static int mma8452_probe(struct i2c_client *client,
 
 
 	data->data_cfg = MMA8452_DATA_CFG_FS_2G;
 	data->data_cfg = MMA8452_DATA_CFG_FS_2G;
 	ret = i2c_smbus_write_byte_data(client, MMA8452_DATA_CFG,
 	ret = i2c_smbus_write_byte_data(client, MMA8452_DATA_CFG,
-		data->data_cfg);
+					data->data_cfg);
 	if (ret < 0)
 	if (ret < 0)
 		return ret;
 		return ret;
 
 
@@ -891,14 +919,14 @@ static int mma8452_probe(struct i2c_client *client,
 	}
 	}
 
 
 	data->ctrl_reg1 = MMA8452_CTRL_ACTIVE |
 	data->ctrl_reg1 = MMA8452_CTRL_ACTIVE |
-		(MMA8452_CTRL_DR_DEFAULT << MMA8452_CTRL_DR_SHIFT);
+			  (MMA8452_CTRL_DR_DEFAULT << MMA8452_CTRL_DR_SHIFT);
 	ret = i2c_smbus_write_byte_data(client, MMA8452_CTRL_REG1,
 	ret = i2c_smbus_write_byte_data(client, MMA8452_CTRL_REG1,
 					data->ctrl_reg1);
 					data->ctrl_reg1);
 	if (ret < 0)
 	if (ret < 0)
 		goto trigger_cleanup;
 		goto trigger_cleanup;
 
 
 	ret = iio_triggered_buffer_setup(indio_dev, NULL,
 	ret = iio_triggered_buffer_setup(indio_dev, NULL,
-		mma8452_trigger_handler, NULL);
+					 mma8452_trigger_handler, NULL);
 	if (ret < 0)
 	if (ret < 0)
 		goto trigger_cleanup;
 		goto trigger_cleanup;
 
 
@@ -968,6 +996,7 @@ static const struct of_device_id mma8452_dt_ids[] = {
 	{ .compatible = "fsl,mma8452" },
 	{ .compatible = "fsl,mma8452" },
 	{ }
 	{ }
 };
 };
+MODULE_DEVICE_TABLE(of, mma8452_dt_ids);
 
 
 static struct i2c_driver mma8452_driver = {
 static struct i2c_driver mma8452_driver = {
 	.driver = {
 	.driver = {

+ 1 - 1
drivers/iio/accel/mma9553.c

@@ -1149,7 +1149,7 @@ static int mma9553_probe(struct i2c_client *client,
 	if (client->irq < 0)
 	if (client->irq < 0)
 		client->irq = mma9553_gpio_probe(client);
 		client->irq = mma9553_gpio_probe(client);
 
 
-	if (client->irq >= 0) {
+	if (client->irq > 0) {
 		ret = devm_request_threaded_irq(&client->dev, client->irq,
 		ret = devm_request_threaded_irq(&client->dev, client->irq,
 						mma9553_irq_handler,
 						mma9553_irq_handler,
 						mma9553_event_handler,
 						mma9553_event_handler,

+ 1 - 0
drivers/iio/accel/st_accel.h

@@ -26,6 +26,7 @@
 #define LSM303DLH_ACCEL_DEV_NAME	"lsm303dlh_accel"
 #define LSM303DLH_ACCEL_DEV_NAME	"lsm303dlh_accel"
 #define LSM303DLM_ACCEL_DEV_NAME	"lsm303dlm_accel"
 #define LSM303DLM_ACCEL_DEV_NAME	"lsm303dlm_accel"
 #define LSM330_ACCEL_DEV_NAME		"lsm330_accel"
 #define LSM330_ACCEL_DEV_NAME		"lsm330_accel"
+#define LSM303AGR_ACCEL_DEV_NAME	"lsm303agr_accel"
 
 
 /**
 /**
 * struct st_sensors_platform_data - default accel platform data
 * struct st_sensors_platform_data - default accel platform data

+ 6 - 0
drivers/iio/accel/st_accel_core.c

@@ -226,12 +226,14 @@ static const struct iio_chan_spec st_accel_16bit_channels[] = {
 static const struct st_sensor_settings st_accel_sensors_settings[] = {
 static const struct st_sensor_settings st_accel_sensors_settings[] = {
 	{
 	{
 		.wai = ST_ACCEL_1_WAI_EXP,
 		.wai = ST_ACCEL_1_WAI_EXP,
+		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 		.sensors_supported = {
 		.sensors_supported = {
 			[0] = LIS3DH_ACCEL_DEV_NAME,
 			[0] = LIS3DH_ACCEL_DEV_NAME,
 			[1] = LSM303DLHC_ACCEL_DEV_NAME,
 			[1] = LSM303DLHC_ACCEL_DEV_NAME,
 			[2] = LSM330D_ACCEL_DEV_NAME,
 			[2] = LSM330D_ACCEL_DEV_NAME,
 			[3] = LSM330DL_ACCEL_DEV_NAME,
 			[3] = LSM330DL_ACCEL_DEV_NAME,
 			[4] = LSM330DLC_ACCEL_DEV_NAME,
 			[4] = LSM330DLC_ACCEL_DEV_NAME,
+			[5] = LSM303AGR_ACCEL_DEV_NAME,
 		},
 		},
 		.ch = (struct iio_chan_spec *)st_accel_12bit_channels,
 		.ch = (struct iio_chan_spec *)st_accel_12bit_channels,
 		.odr = {
 		.odr = {
@@ -297,6 +299,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
 	},
 	},
 	{
 	{
 		.wai = ST_ACCEL_2_WAI_EXP,
 		.wai = ST_ACCEL_2_WAI_EXP,
+		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 		.sensors_supported = {
 		.sensors_supported = {
 			[0] = LIS331DLH_ACCEL_DEV_NAME,
 			[0] = LIS331DLH_ACCEL_DEV_NAME,
 			[1] = LSM303DL_ACCEL_DEV_NAME,
 			[1] = LSM303DL_ACCEL_DEV_NAME,
@@ -359,6 +362,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
 	},
 	},
 	{
 	{
 		.wai = ST_ACCEL_3_WAI_EXP,
 		.wai = ST_ACCEL_3_WAI_EXP,
+		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 		.sensors_supported = {
 		.sensors_supported = {
 			[0] = LSM330_ACCEL_DEV_NAME,
 			[0] = LSM330_ACCEL_DEV_NAME,
 		},
 		},
@@ -437,6 +441,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
 	},
 	},
 	{
 	{
 		.wai = ST_ACCEL_4_WAI_EXP,
 		.wai = ST_ACCEL_4_WAI_EXP,
+		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 		.sensors_supported = {
 		.sensors_supported = {
 			[0] = LIS3LV02DL_ACCEL_DEV_NAME,
 			[0] = LIS3LV02DL_ACCEL_DEV_NAME,
 		},
 		},
@@ -494,6 +499,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
 	},
 	},
 	{
 	{
 		.wai = ST_ACCEL_5_WAI_EXP,
 		.wai = ST_ACCEL_5_WAI_EXP,
+		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 		.sensors_supported = {
 		.sensors_supported = {
 			[0] = LIS331DL_ACCEL_DEV_NAME,
 			[0] = LIS331DL_ACCEL_DEV_NAME,
 		},
 		},

+ 5 - 0
drivers/iio/accel/st_accel_i2c.c

@@ -68,6 +68,10 @@ static const struct of_device_id st_accel_of_match[] = {
 		.compatible = "st,lsm330-accel",
 		.compatible = "st,lsm330-accel",
 		.data = LSM330_ACCEL_DEV_NAME,
 		.data = LSM330_ACCEL_DEV_NAME,
 	},
 	},
+	{
+		.compatible = "st,lsm303agr-accel",
+		.data = LSM303AGR_ACCEL_DEV_NAME,
+	},
 	{},
 	{},
 };
 };
 MODULE_DEVICE_TABLE(of, st_accel_of_match);
 MODULE_DEVICE_TABLE(of, st_accel_of_match);
@@ -116,6 +120,7 @@ static const struct i2c_device_id st_accel_id_table[] = {
 	{ LSM303DL_ACCEL_DEV_NAME },
 	{ LSM303DL_ACCEL_DEV_NAME },
 	{ LSM303DLM_ACCEL_DEV_NAME },
 	{ LSM303DLM_ACCEL_DEV_NAME },
 	{ LSM330_ACCEL_DEV_NAME },
 	{ LSM330_ACCEL_DEV_NAME },
+	{ LSM303AGR_ACCEL_DEV_NAME },
 	{},
 	{},
 };
 };
 MODULE_DEVICE_TABLE(i2c, st_accel_id_table);
 MODULE_DEVICE_TABLE(i2c, st_accel_id_table);

+ 1 - 0
drivers/iio/accel/st_accel_spi.c

@@ -57,6 +57,7 @@ static const struct spi_device_id st_accel_id_table[] = {
 	{ LSM303DL_ACCEL_DEV_NAME },
 	{ LSM303DL_ACCEL_DEV_NAME },
 	{ LSM303DLM_ACCEL_DEV_NAME },
 	{ LSM303DLM_ACCEL_DEV_NAME },
 	{ LSM330_ACCEL_DEV_NAME },
 	{ LSM330_ACCEL_DEV_NAME },
+	{ LSM303AGR_ACCEL_DEV_NAME },
 	{},
 	{},
 };
 };
 MODULE_DEVICE_TABLE(spi, st_accel_id_table);
 MODULE_DEVICE_TABLE(spi, st_accel_id_table);

+ 61 - 46
drivers/iio/accel/stk8312.c

@@ -37,16 +37,16 @@
 #define STK8312_REG_OTPDATA		0x3E
 #define STK8312_REG_OTPDATA		0x3E
 #define STK8312_REG_OTPCTRL		0x3F
 #define STK8312_REG_OTPCTRL		0x3F
 
 
-#define STK8312_MODE_ACTIVE		0x01
+#define STK8312_MODE_ACTIVE		BIT(0)
 #define STK8312_MODE_STANDBY		0x00
 #define STK8312_MODE_STANDBY		0x00
-#define STK8312_DREADY_BIT		0x10
-#define STK8312_INT_MODE		0xC0
-#define STK8312_RNG_MASK		0xC0
-#define STK8312_SR_MASK			0x07
-#define STK8312_SR_400HZ_IDX		0
+#define STK8312_MODE_INT_AH_PP		0xC0	/* active-high, push-pull */
+#define STK8312_DREADY_BIT		BIT(4)
+#define STK8312_RNG_6G			1
 #define STK8312_RNG_SHIFT		6
 #define STK8312_RNG_SHIFT		6
-#define STK8312_READ_RETRIES		16
-#define STK8312_ALL_CHANNEL_MASK	7
+#define STK8312_RNG_MASK		GENMASK(7, 6)
+#define STK8312_SR_MASK			GENMASK(2, 0)
+#define STK8312_SR_400HZ_IDX		0
+#define STK8312_ALL_CHANNEL_MASK	GENMASK(2, 0)
 #define STK8312_ALL_CHANNEL_SIZE	3
 #define STK8312_ALL_CHANNEL_SIZE	3
 
 
 #define STK8312_DRIVER_NAME		"stk8312"
 #define STK8312_DRIVER_NAME		"stk8312"
@@ -69,8 +69,8 @@ static const int stk8312_scale_table[][2] = {
 };
 };
 
 
 static const struct {
 static const struct {
-	u16 val;
-	u32 val2;
+	int val;
+	int val2;
 } stk8312_samp_freq_table[] = {
 } stk8312_samp_freq_table[] = {
 	{400, 0}, {200, 0}, {100, 0}, {50, 0}, {25, 0},
 	{400, 0}, {200, 0}, {100, 0}, {50, 0}, {25, 0},
 	{12, 500000}, {6, 250000}, {3, 125000}
 	{12, 500000}, {6, 250000}, {3, 125000}
@@ -103,7 +103,7 @@ static const struct iio_chan_spec stk8312_channels[] = {
 struct stk8312_data {
 struct stk8312_data {
 	struct i2c_client *client;
 	struct i2c_client *client;
 	struct mutex lock;
 	struct mutex lock;
-	int range;
+	u8 range;
 	u8 sample_rate_idx;
 	u8 sample_rate_idx;
 	u8 mode;
 	u8 mode;
 	struct iio_trigger *dready_trig;
 	struct iio_trigger *dready_trig;
@@ -144,22 +144,25 @@ static int stk8312_otp_init(struct stk8312_data *data)
 		if (ret < 0)
 		if (ret < 0)
 			goto exit_err;
 			goto exit_err;
 		count--;
 		count--;
-	} while (!(ret & 0x80) && count > 0);
+	} while (!(ret & BIT(7)) && count > 0);
 
 
-	if (count == 0)
+	if (count == 0) {
+		ret = -ETIMEDOUT;
 		goto exit_err;
 		goto exit_err;
+	}
 
 
 	ret = i2c_smbus_read_byte_data(client, STK8312_REG_OTPDATA);
 	ret = i2c_smbus_read_byte_data(client, STK8312_REG_OTPDATA);
+	if (ret == 0)
+		ret = -EINVAL;
 	if (ret < 0)
 	if (ret < 0)
 		goto exit_err;
 		goto exit_err;
 
 
-	ret = i2c_smbus_write_byte_data(data->client,
-			STK8312_REG_AFECTRL, ret);
+	ret = i2c_smbus_write_byte_data(data->client, STK8312_REG_AFECTRL, ret);
 	if (ret < 0)
 	if (ret < 0)
 		goto exit_err;
 		goto exit_err;
 	msleep(150);
 	msleep(150);
 
 
-	return ret;
+	return 0;
 
 
 exit_err:
 exit_err:
 	dev_err(&client->dev, "failed to initialize sensor\n");
 	dev_err(&client->dev, "failed to initialize sensor\n");
@@ -203,8 +206,11 @@ static int stk8312_set_interrupts(struct stk8312_data *data, u8 int_mask)
 		return ret;
 		return ret;
 
 
 	ret = i2c_smbus_write_byte_data(client, STK8312_REG_INTSU, int_mask);
 	ret = i2c_smbus_write_byte_data(client, STK8312_REG_INTSU, int_mask);
-	if (ret < 0)
+	if (ret < 0) {
 		dev_err(&client->dev, "failed to set interrupts\n");
 		dev_err(&client->dev, "failed to set interrupts\n");
+		stk8312_set_mode(data, mode);
+		return ret;
+	}
 
 
 	return stk8312_set_mode(data, mode);
 	return stk8312_set_mode(data, mode);
 }
 }
@@ -228,7 +234,7 @@ static int stk8312_data_rdy_trigger_set_state(struct iio_trigger *trig,
 
 
 	data->dready_trigger_on = state;
 	data->dready_trigger_on = state;
 
 
-	return ret;
+	return 0;
 }
 }
 
 
 static const struct iio_trigger_ops stk8312_trigger_ops = {
 static const struct iio_trigger_ops stk8312_trigger_ops = {
@@ -236,7 +242,7 @@ static const struct iio_trigger_ops stk8312_trigger_ops = {
 	.owner = THIS_MODULE,
 	.owner = THIS_MODULE,
 };
 };
 
 
-static int stk8312_set_sample_rate(struct stk8312_data *data, int rate)
+static int stk8312_set_sample_rate(struct stk8312_data *data, u8 rate)
 {
 {
 	int ret;
 	int ret;
 	u8 masked_reg;
 	u8 masked_reg;
@@ -253,20 +259,24 @@ static int stk8312_set_sample_rate(struct stk8312_data *data, int rate)
 		return ret;
 		return ret;
 
 
 	ret = i2c_smbus_read_byte_data(client, STK8312_REG_SR);
 	ret = i2c_smbus_read_byte_data(client, STK8312_REG_SR);
-	if (ret < 0) {
-		dev_err(&client->dev, "failed to set sampling rate\n");
-		return ret;
-	}
+	if (ret < 0)
+		goto err_activate;
 
 
 	masked_reg = (ret & (~STK8312_SR_MASK)) | rate;
 	masked_reg = (ret & (~STK8312_SR_MASK)) | rate;
 
 
 	ret = i2c_smbus_write_byte_data(client, STK8312_REG_SR, masked_reg);
 	ret = i2c_smbus_write_byte_data(client, STK8312_REG_SR, masked_reg);
 	if (ret < 0)
 	if (ret < 0)
-		dev_err(&client->dev, "failed to set sampling rate\n");
-	else
-		data->sample_rate_idx = rate;
+		goto err_activate;
+
+	data->sample_rate_idx = rate;
 
 
 	return stk8312_set_mode(data, mode);
 	return stk8312_set_mode(data, mode);
+
+err_activate:
+	dev_err(&client->dev, "failed to set sampling rate\n");
+	stk8312_set_mode(data, mode);
+
+	return ret;
 }
 }
 
 
 static int stk8312_set_range(struct stk8312_data *data, u8 range)
 static int stk8312_set_range(struct stk8312_data *data, u8 range)
@@ -288,21 +298,25 @@ static int stk8312_set_range(struct stk8312_data *data, u8 range)
 		return ret;
 		return ret;
 
 
 	ret = i2c_smbus_read_byte_data(client, STK8312_REG_STH);
 	ret = i2c_smbus_read_byte_data(client, STK8312_REG_STH);
-	if (ret < 0) {
-		dev_err(&client->dev, "failed to change sensor range\n");
-		return ret;
-	}
+	if (ret < 0)
+		goto err_activate;
 
 
 	masked_reg = ret & (~STK8312_RNG_MASK);
 	masked_reg = ret & (~STK8312_RNG_MASK);
 	masked_reg |= range << STK8312_RNG_SHIFT;
 	masked_reg |= range << STK8312_RNG_SHIFT;
 
 
 	ret = i2c_smbus_write_byte_data(client, STK8312_REG_STH, masked_reg);
 	ret = i2c_smbus_write_byte_data(client, STK8312_REG_STH, masked_reg);
 	if (ret < 0)
 	if (ret < 0)
-		dev_err(&client->dev, "failed to change sensor range\n");
-	else
-		data->range = range;
+		goto err_activate;
+
+	data->range = range;
 
 
 	return stk8312_set_mode(data, mode);
 	return stk8312_set_mode(data, mode);
+
+err_activate:
+	dev_err(&client->dev, "failed to change sensor range\n");
+	stk8312_set_mode(data, mode);
+
+	return ret;
 }
 }
 
 
 static int stk8312_read_accel(struct stk8312_data *data, u8 address)
 static int stk8312_read_accel(struct stk8312_data *data, u8 address)
@@ -335,18 +349,21 @@ static int stk8312_read_raw(struct iio_dev *indio_dev,
 		ret = stk8312_set_mode(data, data->mode | STK8312_MODE_ACTIVE);
 		ret = stk8312_set_mode(data, data->mode | STK8312_MODE_ACTIVE);
 		if (ret < 0) {
 		if (ret < 0) {
 			mutex_unlock(&data->lock);
 			mutex_unlock(&data->lock);
-			return -EINVAL;
+			return ret;
 		}
 		}
 		ret = stk8312_read_accel(data, chan->address);
 		ret = stk8312_read_accel(data, chan->address);
 		if (ret < 0) {
 		if (ret < 0) {
 			stk8312_set_mode(data,
 			stk8312_set_mode(data,
 					 data->mode & (~STK8312_MODE_ACTIVE));
 					 data->mode & (~STK8312_MODE_ACTIVE));
 			mutex_unlock(&data->lock);
 			mutex_unlock(&data->lock);
-			return -EINVAL;
+			return ret;
 		}
 		}
 		*val = sign_extend32(ret, 7);
 		*val = sign_extend32(ret, 7);
-		stk8312_set_mode(data, data->mode & (~STK8312_MODE_ACTIVE));
+		ret = stk8312_set_mode(data,
+				       data->mode & (~STK8312_MODE_ACTIVE));
 		mutex_unlock(&data->lock);
 		mutex_unlock(&data->lock);
+		if (ret < 0)
+			return ret;
 		return IIO_VAL_INT;
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
 	case IIO_CHAN_INFO_SCALE:
 		*val = stk8312_scale_table[data->range - 1][0];
 		*val = stk8312_scale_table[data->range - 1][0];
@@ -418,7 +435,6 @@ static irqreturn_t stk8312_trigger_handler(int irq, void *p)
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct stk8312_data *data = iio_priv(indio_dev);
 	struct stk8312_data *data = iio_priv(indio_dev);
 	int bit, ret, i = 0;
 	int bit, ret, i = 0;
-	u8 buffer[STK8312_ALL_CHANNEL_SIZE];
 
 
 	mutex_lock(&data->lock);
 	mutex_lock(&data->lock);
 	/*
 	/*
@@ -429,18 +445,15 @@ static irqreturn_t stk8312_trigger_handler(int irq, void *p)
 		ret = i2c_smbus_read_i2c_block_data(data->client,
 		ret = i2c_smbus_read_i2c_block_data(data->client,
 						    STK8312_REG_XOUT,
 						    STK8312_REG_XOUT,
 						    STK8312_ALL_CHANNEL_SIZE,
 						    STK8312_ALL_CHANNEL_SIZE,
-						    buffer);
+						    data->buffer);
 		if (ret < STK8312_ALL_CHANNEL_SIZE) {
 		if (ret < STK8312_ALL_CHANNEL_SIZE) {
 			dev_err(&data->client->dev, "register read failed\n");
 			dev_err(&data->client->dev, "register read failed\n");
 			mutex_unlock(&data->lock);
 			mutex_unlock(&data->lock);
 			goto err;
 			goto err;
 		}
 		}
-		data->buffer[0] = buffer[0];
-		data->buffer[1] = buffer[1];
-		data->buffer[2] = buffer[2];
 	} else {
 	} else {
 		for_each_set_bit(bit, indio_dev->active_scan_mask,
 		for_each_set_bit(bit, indio_dev->active_scan_mask,
-			   indio_dev->masklength) {
+				 indio_dev->masklength) {
 			ret = stk8312_read_accel(data, bit);
 			ret = stk8312_read_accel(data, bit);
 			if (ret < 0) {
 			if (ret < 0) {
 				mutex_unlock(&data->lock);
 				mutex_unlock(&data->lock);
@@ -547,11 +560,12 @@ static int stk8312_probe(struct i2c_client *client,
 		return ret;
 		return ret;
 	}
 	}
 	data->sample_rate_idx = STK8312_SR_400HZ_IDX;
 	data->sample_rate_idx = STK8312_SR_400HZ_IDX;
-	ret = stk8312_set_range(data, 1);
+	ret = stk8312_set_range(data, STK8312_RNG_6G);
 	if (ret < 0)
 	if (ret < 0)
 		return ret;
 		return ret;
 
 
-	ret = stk8312_set_mode(data, STK8312_INT_MODE | STK8312_MODE_ACTIVE);
+	ret = stk8312_set_mode(data,
+			       STK8312_MODE_INT_AH_PP | STK8312_MODE_ACTIVE);
 	if (ret < 0)
 	if (ret < 0)
 		return ret;
 		return ret;
 
 
@@ -606,7 +620,7 @@ static int stk8312_probe(struct i2c_client *client,
 		goto err_buffer_cleanup;
 		goto err_buffer_cleanup;
 	}
 	}
 
 
-	return ret;
+	return 0;
 
 
 err_buffer_cleanup:
 err_buffer_cleanup:
 	iio_triggered_buffer_cleanup(indio_dev);
 	iio_triggered_buffer_cleanup(indio_dev);
@@ -662,6 +676,7 @@ static const struct i2c_device_id stk8312_i2c_id[] = {
 	{"STK8312", 0},
 	{"STK8312", 0},
 	{}
 	{}
 };
 };
+MODULE_DEVICE_TABLE(i2c, stk8312_i2c_id);
 
 
 static const struct acpi_device_id stk8312_acpi_id[] = {
 static const struct acpi_device_id stk8312_acpi_id[] = {
 	{"STK8312", 0},
 	{"STK8312", 0},
@@ -672,7 +687,7 @@ MODULE_DEVICE_TABLE(acpi, stk8312_acpi_id);
 
 
 static struct i2c_driver stk8312_driver = {
 static struct i2c_driver stk8312_driver = {
 	.driver = {
 	.driver = {
-		.name = "stk8312",
+		.name = STK8312_DRIVER_NAME,
 		.pm = STK8312_PM_OPS,
 		.pm = STK8312_PM_OPS,
 		.acpi_match_table = ACPI_PTR(stk8312_acpi_id),
 		.acpi_match_table = ACPI_PTR(stk8312_acpi_id),
 	},
 	},

+ 1 - 0
drivers/iio/accel/stk8ba50.c

@@ -572,6 +572,7 @@ static const struct i2c_device_id stk8ba50_i2c_id[] = {
 	{"stk8ba50", 0},
 	{"stk8ba50", 0},
 	{}
 	{}
 };
 };
+MODULE_DEVICE_TABLE(i2c, stk8ba50_i2c_id);
 
 
 static const struct acpi_device_id stk8ba50_acpi_id[] = {
 static const struct acpi_device_id stk8ba50_acpi_id[] = {
 	{"STK8BA50", 0},
 	{"STK8BA50", 0},

+ 2 - 2
drivers/iio/adc/Kconfig

@@ -228,8 +228,8 @@ config MCP320X
 	depends on SPI
 	depends on SPI
 	help
 	help
 	  Say yes here to build support for Microchip Technology's
 	  Say yes here to build support for Microchip Technology's
-	  MCP3001, MCP3002, MCP3004, MCP3008, MCP3201, MCP3202, MCP3204 or
-	  MCP3208 analog to digital converter.
+	  MCP3001, MCP3002, MCP3004, MCP3008, MCP3201, MCP3202, MCP3204,
+	  MCP3208 or MCP3301 analog to digital converter.
 
 
 	  This driver can also be built as a module. If so, the module will be
 	  This driver can also be built as a module. If so, the module will be
 	  called mcp320x.
 	  called mcp320x.

+ 10 - 12
drivers/iio/adc/berlin2-adc.c

@@ -26,7 +26,7 @@
 #define BERLIN2_SM_CTRL				0x14
 #define BERLIN2_SM_CTRL				0x14
 #define  BERLIN2_SM_CTRL_SM_SOC_INT		BIT(1)
 #define  BERLIN2_SM_CTRL_SM_SOC_INT		BIT(1)
 #define  BERLIN2_SM_CTRL_SOC_SM_INT		BIT(2)
 #define  BERLIN2_SM_CTRL_SOC_SM_INT		BIT(2)
-#define  BERLIN2_SM_CTRL_ADC_SEL(x)		(BIT(x) << 5)	/* 0-15 */
+#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		(0xf << 5)
 #define  BERLIN2_SM_CTRL_ADC_POWER		BIT(9)
 #define  BERLIN2_SM_CTRL_ADC_POWER		BIT(9)
 #define  BERLIN2_SM_CTRL_ADC_CLKSEL_DIV2	(0x0 << 10)
 #define  BERLIN2_SM_CTRL_ADC_CLKSEL_DIV2	(0x0 << 10)
@@ -53,14 +53,14 @@
 #define  BERLIN2_SM_ADC_MASK			0x3ff
 #define  BERLIN2_SM_ADC_MASK			0x3ff
 #define BERLIN2_SM_ADC_STATUS			0x1c
 #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(x)	BIT(x)		/* 0-15 */
-#define  BERLIN2_SM_ADC_STATUS_DATA_RDY_MASK	0xf
+#define  BERLIN2_SM_ADC_STATUS_DATA_RDY_MASK	GENMASK(15, 0)
 #define  BERLIN2_SM_ADC_STATUS_INT_EN(x)	(BIT(x) << 16)	/* 0-15 */
 #define  BERLIN2_SM_ADC_STATUS_INT_EN(x)	(BIT(x) << 16)	/* 0-15 */
-#define  BERLIN2_SM_ADC_STATUS_INT_EN_MASK	(0xf << 16)
+#define  BERLIN2_SM_ADC_STATUS_INT_EN_MASK	GENMASK(31, 16)
 #define BERLIN2_SM_TSEN_STATUS			0x24
 #define BERLIN2_SM_TSEN_STATUS			0x24
 #define  BERLIN2_SM_TSEN_STATUS_DATA_RDY	BIT(0)
 #define  BERLIN2_SM_TSEN_STATUS_DATA_RDY	BIT(0)
 #define  BERLIN2_SM_TSEN_STATUS_INT_EN		BIT(1)
 #define  BERLIN2_SM_TSEN_STATUS_INT_EN		BIT(1)
 #define BERLIN2_SM_TSEN_DATA			0x28
 #define BERLIN2_SM_TSEN_DATA			0x28
-#define  BERLIN2_SM_TSEN_MASK			0xfff
+#define  BERLIN2_SM_TSEN_MASK			GENMASK(9, 0)
 #define BERLIN2_SM_TSEN_CTRL			0x74
 #define BERLIN2_SM_TSEN_CTRL			0x74
 #define  BERLIN2_SM_TSEN_CTRL_START		BIT(8)
 #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_4	(0x0 << 21)	/* 4 us */
@@ -86,7 +86,7 @@ struct berlin2_adc_priv {
 			.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
 			.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
 		}
 		}
 
 
-static struct iio_chan_spec berlin2_adc_channels[] = {
+static const struct iio_chan_spec berlin2_adc_channels[] = {
 	BERLIN2_ADC_CHANNEL(0, IIO_VOLTAGE),	/* external input */
 	BERLIN2_ADC_CHANNEL(0, IIO_VOLTAGE),	/* external input */
 	BERLIN2_ADC_CHANNEL(1, IIO_VOLTAGE),	/* external input */
 	BERLIN2_ADC_CHANNEL(1, IIO_VOLTAGE),	/* external input */
 	BERLIN2_ADC_CHANNEL(2, IIO_VOLTAGE),	/* external input */
 	BERLIN2_ADC_CHANNEL(2, IIO_VOLTAGE),	/* external input */
@@ -103,7 +103,6 @@ static struct iio_chan_spec berlin2_adc_channels[] = {
 	BERLIN2_ADC_CHANNEL(7, IIO_VOLTAGE),	/* reserved */
 	BERLIN2_ADC_CHANNEL(7, IIO_VOLTAGE),	/* reserved */
 	IIO_CHAN_SOFT_TIMESTAMP(8),		/* timestamp */
 	IIO_CHAN_SOFT_TIMESTAMP(8),		/* timestamp */
 };
 };
-#define BERLIN2_N_CHANNELS	ARRAY_SIZE(berlin2_adc_channels)
 
 
 static int berlin2_adc_read(struct iio_dev *indio_dev, int channel)
 static int berlin2_adc_read(struct iio_dev *indio_dev, int channel)
 {
 {
@@ -221,7 +220,7 @@ static int berlin2_adc_read_raw(struct iio_dev *indio_dev,
 			return temp;
 			return temp;
 
 
 		if (temp > 2047)
 		if (temp > 2047)
-			temp = -(4096 - temp);
+			temp -= 4096;
 
 
 		/* Convert to milli Celsius */
 		/* Convert to milli Celsius */
 		*val = ((temp * 100000) / 264 - 270000);
 		*val = ((temp * 100000) / 264 - 270000);
@@ -286,8 +285,7 @@ static int berlin2_adc_probe(struct platform_device *pdev)
 	int irq, tsen_irq;
 	int irq, tsen_irq;
 	int ret;
 	int ret;
 
 
-	indio_dev = devm_iio_device_alloc(&pdev->dev,
-					  sizeof(struct berlin2_adc_priv));
+	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
 	if (!indio_dev)
 	if (!indio_dev)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
@@ -301,11 +299,11 @@ static int berlin2_adc_probe(struct platform_device *pdev)
 
 
 	irq = platform_get_irq_byname(pdev, "adc");
 	irq = platform_get_irq_byname(pdev, "adc");
 	if (irq < 0)
 	if (irq < 0)
-		return -ENODEV;
+		return irq;
 
 
 	tsen_irq = platform_get_irq_byname(pdev, "tsen");
 	tsen_irq = platform_get_irq_byname(pdev, "tsen");
 	if (tsen_irq < 0)
 	if (tsen_irq < 0)
-		return -ENODEV;
+		return tsen_irq;
 
 
 	ret = devm_request_irq(&pdev->dev, irq, berlin2_adc_irq, 0,
 	ret = devm_request_irq(&pdev->dev, irq, berlin2_adc_irq, 0,
 			pdev->dev.driver->name, indio_dev);
 			pdev->dev.driver->name, indio_dev);
@@ -325,8 +323,8 @@ static int berlin2_adc_probe(struct platform_device *pdev)
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->info = &berlin2_adc_info;
 	indio_dev->info = &berlin2_adc_info;
 
 
-	indio_dev->num_channels = BERLIN2_N_CHANNELS;
 	indio_dev->channels = berlin2_adc_channels;
 	indio_dev->channels = berlin2_adc_channels;
+	indio_dev->num_channels = ARRAY_SIZE(berlin2_adc_channels);
 
 
 	/* Power up the ADC */
 	/* Power up the ADC */
 	regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL,
 	regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL,

+ 15 - 1
drivers/iio/adc/mcp320x.c

@@ -25,6 +25,7 @@
  * http://ww1.microchip.com/downloads/en/DeviceDoc/21290D.pdf  mcp3201
  * http://ww1.microchip.com/downloads/en/DeviceDoc/21290D.pdf  mcp3201
  * http://ww1.microchip.com/downloads/en/DeviceDoc/21034D.pdf  mcp3202
  * http://ww1.microchip.com/downloads/en/DeviceDoc/21034D.pdf  mcp3202
  * http://ww1.microchip.com/downloads/en/DeviceDoc/21298c.pdf  mcp3204/08
  * http://ww1.microchip.com/downloads/en/DeviceDoc/21298c.pdf  mcp3204/08
+ * http://ww1.microchip.com/downloads/en/DeviceDoc/21700E.pdf  mcp3301
  *
  *
  * This program is free software; you can redistribute it and/or modify
  * 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
  * it under the terms of the GNU General Public License version 2 as
@@ -47,6 +48,7 @@ enum {
 	mcp3202,
 	mcp3202,
 	mcp3204,
 	mcp3204,
 	mcp3208,
 	mcp3208,
+	mcp3301,
 };
 };
 
 
 struct mcp320x_chip_info {
 struct mcp320x_chip_info {
@@ -76,6 +78,7 @@ static int mcp320x_channel_to_tx_data(int device_index,
 	switch (device_index) {
 	switch (device_index) {
 	case mcp3001:
 	case mcp3001:
 	case mcp3201:
 	case mcp3201:
+	case mcp3301:
 		return 0;
 		return 0;
 	case mcp3002:
 	case mcp3002:
 	case mcp3202:
 	case mcp3202:
@@ -102,7 +105,7 @@ static int mcp320x_adc_conversion(struct mcp320x *adc, u8 channel,
 	adc->tx_buf = mcp320x_channel_to_tx_data(device_index,
 	adc->tx_buf = mcp320x_channel_to_tx_data(device_index,
 						channel, differential);
 						channel, differential);
 
 
-	if (device_index != mcp3001 && device_index != mcp3201) {
+	if (device_index != mcp3001 && device_index != mcp3201 && device_index != mcp3301) {
 		ret = spi_sync(adc->spi, &adc->msg);
 		ret = spi_sync(adc->spi, &adc->msg);
 		if (ret < 0)
 		if (ret < 0)
 			return ret;
 			return ret;
@@ -125,6 +128,8 @@ static int mcp320x_adc_conversion(struct mcp320x *adc, u8 channel,
 	case mcp3204:
 	case mcp3204:
 	case mcp3208:
 	case mcp3208:
 		return (adc->rx_buf[0] << 4 | adc->rx_buf[1] >> 4);
 		return (adc->rx_buf[0] << 4 | adc->rx_buf[1] >> 4);
+	case mcp3301:
+		return sign_extend32((adc->rx_buf[0] & 0x1f) << 8 | adc->rx_buf[1], 12);
 	default:
 	default:
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
@@ -274,6 +279,11 @@ static const struct mcp320x_chip_info mcp320x_chip_infos[] = {
 		.num_channels = ARRAY_SIZE(mcp3208_channels),
 		.num_channels = ARRAY_SIZE(mcp3208_channels),
 		.resolution = 12
 		.resolution = 12
 	},
 	},
+	[mcp3301] = {
+		.channels = mcp3201_channels,
+		.num_channels = ARRAY_SIZE(mcp3201_channels),
+		.resolution = 13
+	},
 };
 };
 
 
 static int mcp320x_probe(struct spi_device *spi)
 static int mcp320x_probe(struct spi_device *spi)
@@ -368,6 +378,9 @@ static const struct of_device_id mcp320x_dt_ids[] = {
 	}, {
 	}, {
 		.compatible = "mcp3208",
 		.compatible = "mcp3208",
 		.data = &mcp320x_chip_infos[mcp3208],
 		.data = &mcp320x_chip_infos[mcp3208],
+	}, {
+		.compatible = "mcp3301",
+		.data = &mcp320x_chip_infos[mcp3301],
 	}, {
 	}, {
 	}
 	}
 };
 };
@@ -383,6 +396,7 @@ static const struct spi_device_id mcp320x_id[] = {
 	{ "mcp3202", mcp3202 },
 	{ "mcp3202", mcp3202 },
 	{ "mcp3204", mcp3204 },
 	{ "mcp3204", mcp3204 },
 	{ "mcp3208", mcp3208 },
 	{ "mcp3208", mcp3208 },
+	{ "mcp3301", mcp3301 },
 	{ }
 	{ }
 };
 };
 MODULE_DEVICE_TABLE(spi, mcp320x_id);
 MODULE_DEVICE_TABLE(spi, mcp320x_id);

+ 75 - 4
drivers/iio/adc/vf610_adc.c

@@ -68,6 +68,9 @@
 #define VF610_ADC_CLK_DIV8		0x60
 #define VF610_ADC_CLK_DIV8		0x60
 #define VF610_ADC_CLK_MASK		0x60
 #define VF610_ADC_CLK_MASK		0x60
 #define VF610_ADC_ADLSMP_LONG		0x10
 #define VF610_ADC_ADLSMP_LONG		0x10
+#define VF610_ADC_ADSTS_SHORT   0x100
+#define VF610_ADC_ADSTS_NORMAL  0x200
+#define VF610_ADC_ADSTS_LONG    0x300
 #define VF610_ADC_ADSTS_MASK		0x300
 #define VF610_ADC_ADSTS_MASK		0x300
 #define VF610_ADC_ADLPC_EN		0x80
 #define VF610_ADC_ADLPC_EN		0x80
 #define VF610_ADC_ADHSC_EN		0x400
 #define VF610_ADC_ADHSC_EN		0x400
@@ -98,6 +101,8 @@
 #define VF610_ADC_CALF			0x2
 #define VF610_ADC_CALF			0x2
 #define VF610_ADC_TIMEOUT		msecs_to_jiffies(100)
 #define VF610_ADC_TIMEOUT		msecs_to_jiffies(100)
 
 
+#define DEFAULT_SAMPLE_TIME		1000
+
 enum clk_sel {
 enum clk_sel {
 	VF610_ADCIOC_BUSCLK_SET,
 	VF610_ADCIOC_BUSCLK_SET,
 	VF610_ADCIOC_ALTCLK_SET,
 	VF610_ADCIOC_ALTCLK_SET,
@@ -124,6 +129,17 @@ enum conversion_mode_sel {
 	VF610_ADC_CONV_LOW_POWER,
 	VF610_ADC_CONV_LOW_POWER,
 };
 };
 
 
+enum lst_adder_sel {
+	VF610_ADCK_CYCLES_3,
+	VF610_ADCK_CYCLES_5,
+	VF610_ADCK_CYCLES_7,
+	VF610_ADCK_CYCLES_9,
+	VF610_ADCK_CYCLES_13,
+	VF610_ADCK_CYCLES_17,
+	VF610_ADCK_CYCLES_21,
+	VF610_ADCK_CYCLES_25,
+};
+
 struct vf610_adc_feature {
 struct vf610_adc_feature {
 	enum clk_sel	clk_sel;
 	enum clk_sel	clk_sel;
 	enum vol_ref	vol_ref;
 	enum vol_ref	vol_ref;
@@ -132,6 +148,8 @@ struct vf610_adc_feature {
 	int	clk_div;
 	int	clk_div;
 	int     sample_rate;
 	int     sample_rate;
 	int	res_mode;
 	int	res_mode;
+	u32 lst_adder_index;
+	u32 default_sample_time;
 
 
 	bool	calibration;
 	bool	calibration;
 	bool	ovwren;
 	bool	ovwren;
@@ -155,11 +173,13 @@ struct vf610_adc {
 };
 };
 
 
 static const u32 vf610_hw_avgs[] = { 1, 4, 8, 16, 32 };
 static const u32 vf610_hw_avgs[] = { 1, 4, 8, 16, 32 };
+static const u32 vf610_lst_adder[] = { 3, 5, 7, 9, 13, 17, 21, 25 };
 
 
 static inline void vf610_adc_calculate_rates(struct vf610_adc *info)
 static inline void vf610_adc_calculate_rates(struct vf610_adc *info)
 {
 {
 	struct vf610_adc_feature *adc_feature = &info->adc_feature;
 	struct vf610_adc_feature *adc_feature = &info->adc_feature;
 	unsigned long adck_rate, ipg_rate = clk_get_rate(info->clk);
 	unsigned long adck_rate, ipg_rate = clk_get_rate(info->clk);
+	u32 adck_period, lst_addr_min;
 	int divisor, i;
 	int divisor, i;
 
 
 	adck_rate = info->max_adck_rate[adc_feature->conv_mode];
 	adck_rate = info->max_adck_rate[adc_feature->conv_mode];
@@ -173,6 +193,19 @@ static inline void vf610_adc_calculate_rates(struct vf610_adc *info)
 		adc_feature->clk_div = 8;
 		adc_feature->clk_div = 8;
 	}
 	}
 
 
+	/*
+	 * Determine the long sample time adder value to be used based
+	 * on the default minimum sample time provided.
+	 */
+	adck_period = NSEC_PER_SEC / adck_rate;
+	lst_addr_min = adc_feature->default_sample_time / adck_period;
+	for (i = 0; i < ARRAY_SIZE(vf610_lst_adder); i++) {
+		if (vf610_lst_adder[i] > lst_addr_min) {
+			adc_feature->lst_adder_index = i;
+			break;
+		}
+	}
+
 	/*
 	/*
 	 * Calculate ADC sample frequencies
 	 * Calculate ADC sample frequencies
 	 * Sample time unit is ADCK cycles. ADCK clk source is ipg clock,
 	 * Sample time unit is ADCK cycles. ADCK clk source is ipg clock,
@@ -182,12 +215,13 @@ static inline void vf610_adc_calculate_rates(struct vf610_adc *info)
 	 * SFCAdder: fixed to 6 ADCK cycles
 	 * SFCAdder: fixed to 6 ADCK cycles
 	 * AverageNum: 1, 4, 8, 16, 32 samples for hardware average.
 	 * AverageNum: 1, 4, 8, 16, 32 samples for hardware average.
 	 * BCT (Base Conversion Time): fixed to 25 ADCK cycles for 12 bit mode
 	 * BCT (Base Conversion Time): fixed to 25 ADCK cycles for 12 bit mode
-	 * LSTAdder(Long Sample Time): fixed to 3 ADCK cycles
+	 * LSTAdder(Long Sample Time): 3, 5, 7, 9, 13, 17, 21, 25 ADCK cycles
 	 */
 	 */
 	adck_rate = ipg_rate / info->adc_feature.clk_div;
 	adck_rate = ipg_rate / info->adc_feature.clk_div;
 	for (i = 0; i < ARRAY_SIZE(vf610_hw_avgs); i++)
 	for (i = 0; i < ARRAY_SIZE(vf610_hw_avgs); i++)
 		info->sample_freq_avail[i] =
 		info->sample_freq_avail[i] =
-			adck_rate / (6 + vf610_hw_avgs[i] * (25 + 3));
+			adck_rate / (6 + vf610_hw_avgs[i] *
+			 (25 + vf610_lst_adder[adc_feature->lst_adder_index]));
 }
 }
 
 
 static inline void vf610_adc_cfg_init(struct vf610_adc *info)
 static inline void vf610_adc_cfg_init(struct vf610_adc *info)
@@ -347,8 +381,40 @@ static void vf610_adc_sample_set(struct vf610_adc *info)
 		break;
 		break;
 	}
 	}
 
 
-	/* Use the short sample mode */
-	cfg_data &= ~(VF610_ADC_ADLSMP_LONG | VF610_ADC_ADSTS_MASK);
+	/*
+	 * Set ADLSMP and ADSTS based on the Long Sample Time Adder value
+	 * determined.
+	 */
+	switch (adc_feature->lst_adder_index) {
+	case VF610_ADCK_CYCLES_3:
+		break;
+	case VF610_ADCK_CYCLES_5:
+		cfg_data |= VF610_ADC_ADSTS_SHORT;
+		break;
+	case VF610_ADCK_CYCLES_7:
+		cfg_data |= VF610_ADC_ADSTS_NORMAL;
+		break;
+	case VF610_ADCK_CYCLES_9:
+		cfg_data |= VF610_ADC_ADSTS_LONG;
+		break;
+	case VF610_ADCK_CYCLES_13:
+		cfg_data |= VF610_ADC_ADLSMP_LONG;
+		break;
+	case VF610_ADCK_CYCLES_17:
+		cfg_data |= VF610_ADC_ADLSMP_LONG;
+		cfg_data |= VF610_ADC_ADSTS_SHORT;
+		break;
+	case VF610_ADCK_CYCLES_21:
+		cfg_data |= VF610_ADC_ADLSMP_LONG;
+		cfg_data |= VF610_ADC_ADSTS_NORMAL;
+		break;
+	case VF610_ADCK_CYCLES_25:
+		cfg_data |= VF610_ADC_ADLSMP_LONG;
+		cfg_data |= VF610_ADC_ADSTS_NORMAL;
+		break;
+	default:
+		dev_err(info->dev, "error in sample time select\n");
+	}
 
 
 	/* update hardware average selection */
 	/* update hardware average selection */
 	cfg_data &= ~VF610_ADC_AVGS_MASK;
 	cfg_data &= ~VF610_ADC_AVGS_MASK;
@@ -713,6 +779,11 @@ static int vf610_adc_probe(struct platform_device *pdev)
 	of_property_read_u32_array(pdev->dev.of_node, "fsl,adck-max-frequency",
 	of_property_read_u32_array(pdev->dev.of_node, "fsl,adck-max-frequency",
 			info->max_adck_rate, 3);
 			info->max_adck_rate, 3);
 
 
+	ret = of_property_read_u32(pdev->dev.of_node, "min-sample-time",
+			&info->adc_feature.default_sample_time);
+	if (ret)
+		info->adc_feature.default_sample_time = DEFAULT_SAMPLE_TIME;
+
 	platform_set_drvdata(pdev, indio_dev);
 	platform_set_drvdata(pdev, indio_dev);
 
 
 	init_completion(&info->completion);
 	init_completion(&info->completion);

+ 26 - 26
drivers/iio/common/st_sensors/st_sensors_core.c

@@ -126,6 +126,9 @@ static int st_sensors_set_fullscale(struct iio_dev *indio_dev, unsigned int fs)
 	int err, i = 0;
 	int err, i = 0;
 	struct st_sensor_data *sdata = iio_priv(indio_dev);
 	struct st_sensor_data *sdata = iio_priv(indio_dev);
 
 
+	if (sdata->sensor_settings->fs.addr == 0)
+		return 0;
+
 	err = st_sensors_match_fs(sdata->sensor_settings, fs, &i);
 	err = st_sensors_match_fs(sdata->sensor_settings, fs, &i);
 	if (err < 0)
 	if (err < 0)
 		goto st_accel_set_fullscale_error;
 		goto st_accel_set_fullscale_error;
@@ -479,46 +482,43 @@ int st_sensors_check_device_support(struct iio_dev *indio_dev,
 			int num_sensors_list,
 			int num_sensors_list,
 			const struct st_sensor_settings *sensor_settings)
 			const struct st_sensor_settings *sensor_settings)
 {
 {
-	u8 wai;
 	int i, n, err;
 	int i, n, err;
+	u8 wai;
 	struct st_sensor_data *sdata = iio_priv(indio_dev);
 	struct st_sensor_data *sdata = iio_priv(indio_dev);
 
 
-	err = sdata->tf->read_byte(&sdata->tb, sdata->dev,
-					ST_SENSORS_DEFAULT_WAI_ADDRESS, &wai);
-	if (err < 0) {
-		dev_err(&indio_dev->dev, "failed to read Who-Am-I register.\n");
-		goto read_wai_error;
-	}
-
 	for (i = 0; i < num_sensors_list; i++) {
 	for (i = 0; i < num_sensors_list; i++) {
-		if (sensor_settings[i].wai == wai)
+		for (n = 0; n < ST_SENSORS_MAX_4WAI; n++) {
+			if (strcmp(indio_dev->name,
+				sensor_settings[i].sensors_supported[n]) == 0) {
+				break;
+			}
+		}
+		if (n < ST_SENSORS_MAX_4WAI)
 			break;
 			break;
 	}
 	}
-	if (i == num_sensors_list)
-		goto device_not_supported;
+	if (i == num_sensors_list) {
+		dev_err(&indio_dev->dev, "device name %s not recognized.\n",
+							indio_dev->name);
+		return -ENODEV;
+	}
 
 
-	for (n = 0; n < ARRAY_SIZE(sensor_settings[i].sensors_supported); n++) {
-		if (strcmp(indio_dev->name,
-				&sensor_settings[i].sensors_supported[n][0]) == 0)
-			break;
+	err = sdata->tf->read_byte(&sdata->tb, sdata->dev,
+					sensor_settings[i].wai_addr, &wai);
+	if (err < 0) {
+		dev_err(&indio_dev->dev, "failed to read Who-Am-I register.\n");
+		return err;
 	}
 	}
-	if (n == ARRAY_SIZE(sensor_settings[i].sensors_supported)) {
-		dev_err(&indio_dev->dev, "device name \"%s\" and WhoAmI (0x%02x) mismatch",
-			indio_dev->name, wai);
-		goto sensor_name_mismatch;
+
+	if (sensor_settings[i].wai != wai) {
+		dev_err(&indio_dev->dev, "%s: WhoAmI mismatch (0x%x).\n",
+						indio_dev->name, wai);
+		return -EINVAL;
 	}
 	}
 
 
 	sdata->sensor_settings =
 	sdata->sensor_settings =
 			(struct st_sensor_settings *)&sensor_settings[i];
 			(struct st_sensor_settings *)&sensor_settings[i];
 
 
 	return i;
 	return i;
-
-device_not_supported:
-	dev_err(&indio_dev->dev, "device not supported: WhoAmI (0x%x).\n", wai);
-sensor_name_mismatch:
-	err = -ENODEV;
-read_wai_error:
-	return err;
 }
 }
 EXPORT_SYMBOL(st_sensors_check_device_support);
 EXPORT_SYMBOL(st_sensors_check_device_support);
 
 

+ 2 - 1
drivers/iio/gyro/Kconfig

@@ -53,7 +53,8 @@ config ADXRS450
 config BMG160
 config BMG160
 	tristate "BOSCH BMG160 Gyro Sensor"
 	tristate "BOSCH BMG160 Gyro Sensor"
 	depends on I2C
 	depends on I2C
-	select IIO_TRIGGERED_BUFFER if IIO_BUFFER
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
 	help
 	help
 	  Say yes here to build support for Bosch BMG160 Tri-axis Gyro Sensor
 	  Say yes here to build support for Bosch BMG160 Tri-axis Gyro Sensor
 	  driver. This driver also supports BMI055 gyroscope.
 	  driver. This driver also supports BMI055 gyroscope.

+ 6 - 0
drivers/iio/gyro/adis16136.c

@@ -473,6 +473,7 @@ enum adis16136_id {
 	ID_ADIS16133,
 	ID_ADIS16133,
 	ID_ADIS16135,
 	ID_ADIS16135,
 	ID_ADIS16136,
 	ID_ADIS16136,
+	ID_ADIS16137,
 };
 };
 
 
 static const struct adis16136_chip_info adis16136_chip_info[] = {
 static const struct adis16136_chip_info adis16136_chip_info[] = {
@@ -488,6 +489,10 @@ static const struct adis16136_chip_info adis16136_chip_info[] = {
 		.precision = IIO_DEGREE_TO_RAD(450),
 		.precision = IIO_DEGREE_TO_RAD(450),
 		.fullscale = 24623,
 		.fullscale = 24623,
 	},
 	},
+	[ID_ADIS16137] = {
+		.precision = IIO_DEGREE_TO_RAD(1000),
+		.fullscale = 24609,
+	},
 };
 };
 
 
 static int adis16136_probe(struct spi_device *spi)
 static int adis16136_probe(struct spi_device *spi)
@@ -557,6 +562,7 @@ static const struct spi_device_id adis16136_ids[] = {
 	{ "adis16133", ID_ADIS16133 },
 	{ "adis16133", ID_ADIS16133 },
 	{ "adis16135", ID_ADIS16135 },
 	{ "adis16135", ID_ADIS16135 },
 	{ "adis16136", ID_ADIS16136 },
 	{ "adis16136", ID_ADIS16136 },
+	{ "adis16137", ID_ADIS16137 },
 	{ }
 	{ }
 };
 };
 MODULE_DEVICE_TABLE(spi, adis16136_ids);
 MODULE_DEVICE_TABLE(spi, adis16136_ids);

+ 98 - 39
drivers/iio/gyro/adis16260.c

@@ -101,19 +101,24 @@
 #define ADIS16260_SCAN_TEMP	3
 #define ADIS16260_SCAN_TEMP	3
 #define ADIS16260_SCAN_ANGL	4
 #define ADIS16260_SCAN_ANGL	4
 
 
-/* Power down the device */
-static int adis16260_stop_device(struct iio_dev *indio_dev)
-{
-	struct adis *adis = iio_priv(indio_dev);
-	int ret;
-	u16 val = ADIS16260_SLP_CNT_POWER_OFF;
+struct adis16260_chip_info {
+	unsigned int gyro_max_val;
+	unsigned int gyro_max_scale;
+	const struct iio_chan_spec *channels;
+	unsigned int num_channels;
+};
 
 
-	ret = adis_write_reg_16(adis, ADIS16260_SLP_CNT, val);
-	if (ret)
-		dev_err(&indio_dev->dev, "problem with turning device off: SLP_CNT");
+struct adis16260 {
+	const struct adis16260_chip_info *info;
 
 
-	return ret;
-}
+	struct adis adis;
+};
+
+enum adis16260_type {
+	ADIS16251,
+	ADIS16260,
+	ADIS16266,
+};
 
 
 static const struct iio_chan_spec adis16260_channels[] = {
 static const struct iio_chan_spec adis16260_channels[] = {
 	ADIS_GYRO_CHAN(X, ADIS16260_GYRO_OUT, ADIS16260_SCAN_GYRO,
 	ADIS_GYRO_CHAN(X, ADIS16260_GYRO_OUT, ADIS16260_SCAN_GYRO,
@@ -131,6 +136,55 @@ static const struct iio_chan_spec adis16260_channels[] = {
 	IIO_CHAN_SOFT_TIMESTAMP(5),
 	IIO_CHAN_SOFT_TIMESTAMP(5),
 };
 };
 
 
+static const struct iio_chan_spec adis16266_channels[] = {
+	ADIS_GYRO_CHAN(X, ADIS16260_GYRO_OUT, ADIS16260_SCAN_GYRO,
+		BIT(IIO_CHAN_INFO_CALIBBIAS) |
+		BIT(IIO_CHAN_INFO_CALIBSCALE),
+		BIT(IIO_CHAN_INFO_SAMP_FREQ), 14),
+	ADIS_TEMP_CHAN(ADIS16260_TEMP_OUT, ADIS16260_SCAN_TEMP,
+		BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
+	ADIS_SUPPLY_CHAN(ADIS16260_SUPPLY_OUT, ADIS16260_SCAN_SUPPLY,
+		BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
+	ADIS_AUX_ADC_CHAN(ADIS16260_AUX_ADC, ADIS16260_SCAN_AUX_ADC,
+		BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
+	IIO_CHAN_SOFT_TIMESTAMP(4),
+};
+
+static const struct adis16260_chip_info adis16260_chip_info_table[] = {
+	[ADIS16251] = {
+		.gyro_max_scale = 80,
+		.gyro_max_val = IIO_RAD_TO_DEGREE(4368),
+		.channels = adis16260_channels,
+		.num_channels = ARRAY_SIZE(adis16260_channels),
+	},
+	[ADIS16260] = {
+		.gyro_max_scale = 320,
+		.gyro_max_val = IIO_RAD_TO_DEGREE(4368),
+		.channels = adis16260_channels,
+		.num_channels = ARRAY_SIZE(adis16260_channels),
+	},
+	[ADIS16266] = {
+		.gyro_max_scale = 14000,
+		.gyro_max_val = IIO_RAD_TO_DEGREE(3357),
+		.channels = adis16266_channels,
+		.num_channels = ARRAY_SIZE(adis16266_channels),
+	},
+};
+
+/* Power down the device */
+static int adis16260_stop_device(struct iio_dev *indio_dev)
+{
+	struct adis16260 *adis16260 = iio_priv(indio_dev);
+	int ret;
+	u16 val = ADIS16260_SLP_CNT_POWER_OFF;
+
+	ret = adis_write_reg_16(&adis16260->adis, ADIS16260_SLP_CNT, val);
+	if (ret)
+		dev_err(&indio_dev->dev, "problem with turning device off: SLP_CNT");
+
+	return ret;
+}
+
 static const u8 adis16260_addresses[][2] = {
 static const u8 adis16260_addresses[][2] = {
 	[ADIS16260_SCAN_GYRO] = { ADIS16260_GYRO_OFF, ADIS16260_GYRO_SCALE },
 	[ADIS16260_SCAN_GYRO] = { ADIS16260_GYRO_OFF, ADIS16260_GYRO_SCALE },
 };
 };
@@ -140,7 +194,9 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
 			      int *val, int *val2,
 			      int *val, int *val2,
 			      long mask)
 			      long mask)
 {
 {
-	struct adis *adis = iio_priv(indio_dev);
+	struct adis16260 *adis16260 = iio_priv(indio_dev);
+	const struct adis16260_chip_info *info = adis16260->info;
+	struct adis *adis = &adis16260->adis;
 	int ret;
 	int ret;
 	u8 addr;
 	u8 addr;
 	s16 val16;
 	s16 val16;
@@ -152,15 +208,9 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
 	case IIO_CHAN_INFO_SCALE:
 	case IIO_CHAN_INFO_SCALE:
 		switch (chan->type) {
 		switch (chan->type) {
 		case IIO_ANGL_VEL:
 		case IIO_ANGL_VEL:
-			*val = 0;
-			if (spi_get_device_id(adis->spi)->driver_data) {
-				/* 0.01832 degree / sec */
-				*val2 = IIO_DEGREE_TO_RAD(18320);
-			} else {
-				/* 0.07326 degree / sec */
-				*val2 = IIO_DEGREE_TO_RAD(73260);
-			}
-			return IIO_VAL_INT_PLUS_MICRO;
+			*val = info->gyro_max_scale;
+			*val2 = info->gyro_max_val;
+			return IIO_VAL_FRACTIONAL;
 		case IIO_INCLI:
 		case IIO_INCLI:
 			*val = 0;
 			*val = 0;
 			*val2 = IIO_DEGREE_TO_RAD(36630);
 			*val2 = IIO_DEGREE_TO_RAD(36630);
@@ -224,7 +274,8 @@ static int adis16260_write_raw(struct iio_dev *indio_dev,
 			       int val2,
 			       int val2,
 			       long mask)
 			       long mask)
 {
 {
-	struct adis *adis = iio_priv(indio_dev);
+	struct adis16260 *adis16260 = iio_priv(indio_dev);
+	struct adis *adis = &adis16260->adis;
 	int ret;
 	int ret;
 	u8 addr;
 	u8 addr;
 	u8 t;
 	u8 t;
@@ -305,35 +356,42 @@ static const struct adis_data adis16260_data = {
 
 
 static int adis16260_probe(struct spi_device *spi)
 static int adis16260_probe(struct spi_device *spi)
 {
 {
+	const struct spi_device_id *id;
+	struct adis16260 *adis16260;
 	struct iio_dev *indio_dev;
 	struct iio_dev *indio_dev;
-	struct adis *adis;
 	int ret;
 	int ret;
 
 
+	id = spi_get_device_id(spi);
+	if (!id)
+		return -ENODEV;
+
 	/* setup the industrialio driver allocated elements */
 	/* setup the industrialio driver allocated elements */
-	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adis));
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adis16260));
 	if (!indio_dev)
 	if (!indio_dev)
 		return -ENOMEM;
 		return -ENOMEM;
-	adis = iio_priv(indio_dev);
+	adis16260 = iio_priv(indio_dev);
 	/* this is only used for removal purposes */
 	/* this is only used for removal purposes */
 	spi_set_drvdata(spi, indio_dev);
 	spi_set_drvdata(spi, indio_dev);
 
 
-	indio_dev->name = spi_get_device_id(spi)->name;
+	adis16260->info = &adis16260_chip_info_table[id->driver_data];
+
+	indio_dev->name = id->name;
 	indio_dev->dev.parent = &spi->dev;
 	indio_dev->dev.parent = &spi->dev;
 	indio_dev->info = &adis16260_info;
 	indio_dev->info = &adis16260_info;
-	indio_dev->channels = adis16260_channels;
-	indio_dev->num_channels = ARRAY_SIZE(adis16260_channels);
+	indio_dev->channels = adis16260->info->channels;
+	indio_dev->num_channels = adis16260->info->num_channels;
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->modes = INDIO_DIRECT_MODE;
 
 
-	ret = adis_init(adis, indio_dev, spi, &adis16260_data);
+	ret = adis_init(&adis16260->adis, indio_dev, spi, &adis16260_data);
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 
 
-	ret = adis_setup_buffer_and_trigger(adis, indio_dev, NULL);
+	ret = adis_setup_buffer_and_trigger(&adis16260->adis, indio_dev, NULL);
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 
 
 	/* Get the device into a sane initial state */
 	/* Get the device into a sane initial state */
-	ret = adis_initial_startup(adis);
+	ret = adis_initial_startup(&adis16260->adis);
 	if (ret)
 	if (ret)
 		goto error_cleanup_buffer_trigger;
 		goto error_cleanup_buffer_trigger;
 	ret = iio_device_register(indio_dev);
 	ret = iio_device_register(indio_dev);
@@ -343,18 +401,18 @@ static int adis16260_probe(struct spi_device *spi)
 	return 0;
 	return 0;
 
 
 error_cleanup_buffer_trigger:
 error_cleanup_buffer_trigger:
-	adis_cleanup_buffer_and_trigger(adis, indio_dev);
+	adis_cleanup_buffer_and_trigger(&adis16260->adis, indio_dev);
 	return ret;
 	return ret;
 }
 }
 
 
 static int adis16260_remove(struct spi_device *spi)
 static int adis16260_remove(struct spi_device *spi)
 {
 {
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
-	struct adis *adis = iio_priv(indio_dev);
+	struct adis16260 *adis16260 = iio_priv(indio_dev);
 
 
 	iio_device_unregister(indio_dev);
 	iio_device_unregister(indio_dev);
 	adis16260_stop_device(indio_dev);
 	adis16260_stop_device(indio_dev);
-	adis_cleanup_buffer_and_trigger(adis, indio_dev);
+	adis_cleanup_buffer_and_trigger(&adis16260->adis, indio_dev);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -364,11 +422,12 @@ static int adis16260_remove(struct spi_device *spi)
  * support for the on chip filtering.
  * support for the on chip filtering.
  */
  */
 static const struct spi_device_id adis16260_id[] = {
 static const struct spi_device_id adis16260_id[] = {
-	{"adis16260", 0},
-	{"adis16265", 0},
-	{"adis16250", 0},
-	{"adis16255", 0},
-	{"adis16251", 1},
+	{"adis16260", ADIS16260},
+	{"adis16265", ADIS16260},
+	{"adis16266", ADIS16266},
+	{"adis16250", ADIS16260},
+	{"adis16255", ADIS16260},
+	{"adis16251", ADIS16251},
 	{}
 	{}
 };
 };
 MODULE_DEVICE_TABLE(spi, adis16260_id);
 MODULE_DEVICE_TABLE(spi, adis16260_id);

+ 3 - 0
drivers/iio/gyro/st_gyro_core.c

@@ -131,6 +131,7 @@ static const struct iio_chan_spec st_gyro_16bit_channels[] = {
 static const struct st_sensor_settings st_gyro_sensors_settings[] = {
 static const struct st_sensor_settings st_gyro_sensors_settings[] = {
 	{
 	{
 		.wai = ST_GYRO_1_WAI_EXP,
 		.wai = ST_GYRO_1_WAI_EXP,
+		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 		.sensors_supported = {
 		.sensors_supported = {
 			[0] = L3G4200D_GYRO_DEV_NAME,
 			[0] = L3G4200D_GYRO_DEV_NAME,
 			[1] = LSM330DL_GYRO_DEV_NAME,
 			[1] = LSM330DL_GYRO_DEV_NAME,
@@ -190,6 +191,7 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = {
 	},
 	},
 	{
 	{
 		.wai = ST_GYRO_2_WAI_EXP,
 		.wai = ST_GYRO_2_WAI_EXP,
+		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 		.sensors_supported = {
 		.sensors_supported = {
 			[0] = L3GD20_GYRO_DEV_NAME,
 			[0] = L3GD20_GYRO_DEV_NAME,
 			[1] = LSM330D_GYRO_DEV_NAME,
 			[1] = LSM330D_GYRO_DEV_NAME,
@@ -252,6 +254,7 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = {
 	},
 	},
 	{
 	{
 		.wai = ST_GYRO_3_WAI_EXP,
 		.wai = ST_GYRO_3_WAI_EXP,
+		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 		.sensors_supported = {
 		.sensors_supported = {
 			[0] = L3GD20_GYRO_DEV_NAME,
 			[0] = L3GD20_GYRO_DEV_NAME,
 		},
 		},

+ 35 - 30
drivers/iio/humidity/dht11.c

@@ -33,6 +33,7 @@
 #include <linux/delay.h>
 #include <linux/delay.h>
 #include <linux/gpio.h>
 #include <linux/gpio.h>
 #include <linux/of_gpio.h>
 #include <linux/of_gpio.h>
+#include <linux/timekeeping.h>
 
 
 #include <linux/iio/iio.h>
 #include <linux/iio/iio.h>
 
 
@@ -46,7 +47,8 @@
  * Note that when reading the sensor actually 84 edges are detected, but
  * Note that when reading the sensor actually 84 edges are detected, but
  * since the last edge is not significant, we only store 83:
  * since the last edge is not significant, we only store 83:
  */
  */
-#define DHT11_EDGES_PER_READ (2*DHT11_BITS_PER_READ + DHT11_EDGES_PREAMBLE + 1)
+#define DHT11_EDGES_PER_READ (2 * DHT11_BITS_PER_READ + \
+			      DHT11_EDGES_PREAMBLE + 1)
 
 
 /* Data transmission timing (nano seconds) */
 /* Data transmission timing (nano seconds) */
 #define DHT11_START_TRANSMISSION	18  /* ms */
 #define DHT11_START_TRANSMISSION	18  /* ms */
@@ -62,6 +64,7 @@ struct dht11 {
 	int				irq;
 	int				irq;
 
 
 	struct completion		completion;
 	struct completion		completion;
+	/* The iio sysfs interface doesn't prevent concurrent reads: */
 	struct mutex			lock;
 	struct mutex			lock;
 
 
 	s64				timestamp;
 	s64				timestamp;
@@ -87,32 +90,20 @@ static unsigned char dht11_decode_byte(int *timing, int threshold)
 	return ret;
 	return ret;
 }
 }
 
 
-static int dht11_decode(struct dht11 *dht11, int offset)
+static int dht11_decode(struct dht11 *dht11, int offset, int timeres)
 {
 {
-	int i, t, timing[DHT11_BITS_PER_READ], threshold,
-		timeres = DHT11_SENSOR_RESPONSE;
+	int i, t, timing[DHT11_BITS_PER_READ], threshold;
 	unsigned char temp_int, temp_dec, hum_int, hum_dec, checksum;
 	unsigned char temp_int, temp_dec, hum_int, hum_dec, checksum;
 
 
-	/* Calculate timestamp resolution */
-	for (i = 1; i < dht11->num_edges; ++i) {
-		t = dht11->edges[i].ts - dht11->edges[i-1].ts;
-		if (t > 0 && t < timeres)
-			timeres = t;
-	}
-	if (2*timeres > DHT11_DATA_BIT_HIGH) {
-		pr_err("dht11: timeresolution %d too bad for decoding\n",
-			timeres);
-		return -EIO;
-	}
 	threshold = DHT11_DATA_BIT_HIGH / timeres;
 	threshold = DHT11_DATA_BIT_HIGH / timeres;
-	if (DHT11_DATA_BIT_LOW/timeres + 1 >= threshold)
+	if (DHT11_DATA_BIT_LOW / timeres + 1 >= threshold)
 		pr_err("dht11: WARNING: decoding ambiguous\n");
 		pr_err("dht11: WARNING: decoding ambiguous\n");
 
 
 	/* scale down with timeres and check validity */
 	/* scale down with timeres and check validity */
 	for (i = 0; i < DHT11_BITS_PER_READ; ++i) {
 	for (i = 0; i < DHT11_BITS_PER_READ; ++i) {
-		t = dht11->edges[offset + 2*i + 2].ts -
-			dht11->edges[offset + 2*i + 1].ts;
-		if (!dht11->edges[offset + 2*i + 1].value)
+		t = dht11->edges[offset + 2 * i + 2].ts -
+			dht11->edges[offset + 2 * i + 1].ts;
+		if (!dht11->edges[offset + 2 * i + 1].value)
 			return -EIO;  /* lost synchronisation */
 			return -EIO;  /* lost synchronisation */
 		timing[i] = t / timeres;
 		timing[i] = t / timeres;
 	}
 	}
@@ -126,7 +117,7 @@ static int dht11_decode(struct dht11 *dht11, int offset)
 	if (((hum_int + hum_dec + temp_int + temp_dec) & 0xff) != checksum)
 	if (((hum_int + hum_dec + temp_int + temp_dec) & 0xff) != checksum)
 		return -EIO;
 		return -EIO;
 
 
-	dht11->timestamp = iio_get_time_ns();
+	dht11->timestamp = ktime_get_real_ns();
 	if (hum_int < 20) {  /* DHT22 */
 	if (hum_int < 20) {  /* DHT22 */
 		dht11->temperature = (((temp_int & 0x7f) << 8) + temp_dec) *
 		dht11->temperature = (((temp_int & 0x7f) << 8) + temp_dec) *
 					((temp_int & 0x80) ? -100 : 100);
 					((temp_int & 0x80) ? -100 : 100);
@@ -154,7 +145,7 @@ static irqreturn_t dht11_handle_irq(int irq, void *data)
 
 
 	/* TODO: Consider making the handler safe for IRQ sharing */
 	/* TODO: Consider making the handler safe for IRQ sharing */
 	if (dht11->num_edges < DHT11_EDGES_PER_READ && dht11->num_edges >= 0) {
 	if (dht11->num_edges < DHT11_EDGES_PER_READ && dht11->num_edges >= 0) {
-		dht11->edges[dht11->num_edges].ts = iio_get_time_ns();
+		dht11->edges[dht11->num_edges].ts = ktime_get_real_ns();
 		dht11->edges[dht11->num_edges++].value =
 		dht11->edges[dht11->num_edges++].value =
 						gpio_get_value(dht11->gpio);
 						gpio_get_value(dht11->gpio);
 
 
@@ -166,14 +157,26 @@ static irqreturn_t dht11_handle_irq(int irq, void *data)
 }
 }
 
 
 static int dht11_read_raw(struct iio_dev *iio_dev,
 static int dht11_read_raw(struct iio_dev *iio_dev,
-			const struct iio_chan_spec *chan,
+			  const struct iio_chan_spec *chan,
 			int *val, int *val2, long m)
 			int *val, int *val2, long m)
 {
 {
 	struct dht11 *dht11 = iio_priv(iio_dev);
 	struct dht11 *dht11 = iio_priv(iio_dev);
-	int ret;
+	int ret, timeres;
 
 
 	mutex_lock(&dht11->lock);
 	mutex_lock(&dht11->lock);
-	if (dht11->timestamp + DHT11_DATA_VALID_TIME < iio_get_time_ns()) {
+	if (dht11->timestamp + DHT11_DATA_VALID_TIME < ktime_get_real_ns()) {
+		timeres = ktime_get_resolution_ns();
+		if (DHT11_DATA_BIT_HIGH < 2 * timeres) {
+			dev_err(dht11->dev, "timeresolution %dns too low\n",
+				timeres);
+			/* In theory a better clock could become available
+			 * at some point ... and there is no error code
+			 * that really fits better.
+			 */
+			ret = -EAGAIN;
+			goto err;
+		}
+
 		reinit_completion(&dht11->completion);
 		reinit_completion(&dht11->completion);
 
 
 		dht11->num_edges = 0;
 		dht11->num_edges = 0;
@@ -192,13 +195,13 @@ static int dht11_read_raw(struct iio_dev *iio_dev,
 			goto err;
 			goto err;
 
 
 		ret = wait_for_completion_killable_timeout(&dht11->completion,
 		ret = wait_for_completion_killable_timeout(&dht11->completion,
-								 HZ);
+							   HZ);
 
 
 		free_irq(dht11->irq, iio_dev);
 		free_irq(dht11->irq, iio_dev);
 
 
 		if (ret == 0 && dht11->num_edges < DHT11_EDGES_PER_READ - 1) {
 		if (ret == 0 && dht11->num_edges < DHT11_EDGES_PER_READ - 1) {
 			dev_err(&iio_dev->dev,
 			dev_err(&iio_dev->dev,
-					"Only %d signal edges detected\n",
+				"Only %d signal edges detected\n",
 					dht11->num_edges);
 					dht11->num_edges);
 			ret = -ETIMEDOUT;
 			ret = -ETIMEDOUT;
 		}
 		}
@@ -206,9 +209,10 @@ static int dht11_read_raw(struct iio_dev *iio_dev,
 			goto err;
 			goto err;
 
 
 		ret = dht11_decode(dht11,
 		ret = dht11_decode(dht11,
-				dht11->num_edges == DHT11_EDGES_PER_READ ?
+				   dht11->num_edges == DHT11_EDGES_PER_READ ?
 					DHT11_EDGES_PREAMBLE :
 					DHT11_EDGES_PREAMBLE :
-					DHT11_EDGES_PREAMBLE - 2);
+					DHT11_EDGES_PREAMBLE - 2,
+				timeres);
 		if (ret)
 		if (ret)
 			goto err;
 			goto err;
 	}
 	}
@@ -261,9 +265,10 @@ static int dht11_probe(struct platform_device *pdev)
 	dht11 = iio_priv(iio);
 	dht11 = iio_priv(iio);
 	dht11->dev = dev;
 	dht11->dev = dev;
 
 
-	dht11->gpio = ret = of_get_gpio(node, 0);
+	ret = of_get_gpio(node, 0);
 	if (ret < 0)
 	if (ret < 0)
 		return ret;
 		return ret;
+	dht11->gpio = ret;
 	ret = devm_gpio_request_one(dev, dht11->gpio, GPIOF_IN, pdev->name);
 	ret = devm_gpio_request_one(dev, dht11->gpio, GPIOF_IN, pdev->name);
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
@@ -274,7 +279,7 @@ static int dht11_probe(struct platform_device *pdev)
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	dht11->timestamp = iio_get_time_ns() - DHT11_DATA_VALID_TIME - 1;
+	dht11->timestamp = ktime_get_real_ns() - DHT11_DATA_VALID_TIME - 1;
 	dht11->num_edges = -1;
 	dht11->num_edges = -1;
 
 
 	platform_set_drvdata(pdev, iio);
 	platform_set_drvdata(pdev, iio);

+ 44 - 2
drivers/iio/imu/adis16400_core.c

@@ -139,7 +139,9 @@ enum adis16400_chip_variant {
 	ADIS16360,
 	ADIS16360,
 	ADIS16362,
 	ADIS16362,
 	ADIS16364,
 	ADIS16364,
+	ADIS16367,
 	ADIS16400,
 	ADIS16400,
+	ADIS16445,
 	ADIS16448,
 	ADIS16448,
 };
 };
 
 
@@ -622,6 +624,17 @@ static const struct iio_chan_spec adis16400_channels[] = {
 	IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
 	IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
 };
 };
 
 
+static const struct iio_chan_spec adis16445_channels[] = {
+	ADIS16400_GYRO_CHAN(X, ADIS16400_XGYRO_OUT, 16),
+	ADIS16400_GYRO_CHAN(Y, ADIS16400_YGYRO_OUT, 16),
+	ADIS16400_GYRO_CHAN(Z, ADIS16400_ZGYRO_OUT, 16),
+	ADIS16400_ACCEL_CHAN(X, ADIS16400_XACCL_OUT, 16),
+	ADIS16400_ACCEL_CHAN(Y, ADIS16400_YACCL_OUT, 16),
+	ADIS16400_ACCEL_CHAN(Z, ADIS16400_ZACCL_OUT, 16),
+	ADIS16400_TEMP_CHAN(ADIS16448_TEMP_OUT, 12),
+	IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
+};
+
 static const struct iio_chan_spec adis16448_channels[] = {
 static const struct iio_chan_spec adis16448_channels[] = {
 	ADIS16400_GYRO_CHAN(X, ADIS16400_XGYRO_OUT, 16),
 	ADIS16400_GYRO_CHAN(X, ADIS16400_XGYRO_OUT, 16),
 	ADIS16400_GYRO_CHAN(Y, ADIS16400_YGYRO_OUT, 16),
 	ADIS16400_GYRO_CHAN(Y, ADIS16400_YGYRO_OUT, 16),
@@ -696,7 +709,8 @@ static struct adis16400_chip_info adis16400_chips[] = {
 	[ADIS16300] = {
 	[ADIS16300] = {
 		.channels = adis16300_channels,
 		.channels = adis16300_channels,
 		.num_channels = ARRAY_SIZE(adis16300_channels),
 		.num_channels = ARRAY_SIZE(adis16300_channels),
-		.flags = ADIS16400_HAS_SLOW_MODE,
+		.flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE |
+				ADIS16400_HAS_SERIAL_NUMBER,
 		.gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
 		.gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
 		.accel_scale_micro = 5884,
 		.accel_scale_micro = 5884,
 		.temp_scale_nano = 140000000, /* 0.14 C */
 		.temp_scale_nano = 140000000, /* 0.14 C */
@@ -763,6 +777,18 @@ static struct adis16400_chip_info adis16400_chips[] = {
 		.set_freq = adis16400_set_freq,
 		.set_freq = adis16400_set_freq,
 		.get_freq = adis16400_get_freq,
 		.get_freq = adis16400_get_freq,
 	},
 	},
+	[ADIS16367] = {
+		.channels = adis16350_channels,
+		.num_channels = ARRAY_SIZE(adis16350_channels),
+		.flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE |
+				ADIS16400_HAS_SERIAL_NUMBER,
+		.gyro_scale_micro = IIO_DEGREE_TO_RAD(2000), /* 0.2 deg/s */
+		.accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */
+		.temp_scale_nano = 136000000, /* 0.136 C */
+		.temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
+		.set_freq = adis16400_set_freq,
+		.get_freq = adis16400_get_freq,
+	},
 	[ADIS16400] = {
 	[ADIS16400] = {
 		.channels = adis16400_channels,
 		.channels = adis16400_channels,
 		.num_channels = ARRAY_SIZE(adis16400_channels),
 		.num_channels = ARRAY_SIZE(adis16400_channels),
@@ -774,13 +800,26 @@ static struct adis16400_chip_info adis16400_chips[] = {
 		.set_freq = adis16400_set_freq,
 		.set_freq = adis16400_set_freq,
 		.get_freq = adis16400_get_freq,
 		.get_freq = adis16400_get_freq,
 	},
 	},
+	[ADIS16445] = {
+		.channels = adis16445_channels,
+		.num_channels = ARRAY_SIZE(adis16445_channels),
+		.flags = ADIS16400_HAS_PROD_ID |
+				ADIS16400_HAS_SERIAL_NUMBER |
+				ADIS16400_BURST_DIAG_STAT,
+		.gyro_scale_micro = IIO_DEGREE_TO_RAD(10000), /* 0.01 deg/s */
+		.accel_scale_micro = IIO_G_TO_M_S_2(250), /* 1/4000 g */
+		.temp_scale_nano = 73860000, /* 0.07386 C */
+		.temp_offset = 31000000 / 73860, /* 31 C = 0x00 */
+		.set_freq = adis16334_set_freq,
+		.get_freq = adis16334_get_freq,
+	},
 	[ADIS16448] = {
 	[ADIS16448] = {
 		.channels = adis16448_channels,
 		.channels = adis16448_channels,
 		.num_channels = ARRAY_SIZE(adis16448_channels),
 		.num_channels = ARRAY_SIZE(adis16448_channels),
 		.flags = ADIS16400_HAS_PROD_ID |
 		.flags = ADIS16400_HAS_PROD_ID |
 				ADIS16400_HAS_SERIAL_NUMBER |
 				ADIS16400_HAS_SERIAL_NUMBER |
 				ADIS16400_BURST_DIAG_STAT,
 				ADIS16400_BURST_DIAG_STAT,
-		.gyro_scale_micro = IIO_DEGREE_TO_RAD(10000), /* 0.01 deg/s */
+		.gyro_scale_micro = IIO_DEGREE_TO_RAD(40000), /* 0.04 deg/s */
 		.accel_scale_micro = IIO_G_TO_M_S_2(833), /* 1/1200 g */
 		.accel_scale_micro = IIO_G_TO_M_S_2(833), /* 1/1200 g */
 		.temp_scale_nano = 73860000, /* 0.07386 C */
 		.temp_scale_nano = 73860000, /* 0.07386 C */
 		.temp_offset = 31000000 / 73860, /* 31 C = 0x00 */
 		.temp_offset = 31000000 / 73860, /* 31 C = 0x00 */
@@ -926,6 +965,7 @@ static int adis16400_remove(struct spi_device *spi)
 
 
 static const struct spi_device_id adis16400_id[] = {
 static const struct spi_device_id adis16400_id[] = {
 	{"adis16300", ADIS16300},
 	{"adis16300", ADIS16300},
+	{"adis16305", ADIS16300},
 	{"adis16334", ADIS16334},
 	{"adis16334", ADIS16334},
 	{"adis16350", ADIS16350},
 	{"adis16350", ADIS16350},
 	{"adis16354", ADIS16350},
 	{"adis16354", ADIS16350},
@@ -934,8 +974,10 @@ static const struct spi_device_id adis16400_id[] = {
 	{"adis16362", ADIS16362},
 	{"adis16362", ADIS16362},
 	{"adis16364", ADIS16364},
 	{"adis16364", ADIS16364},
 	{"adis16365", ADIS16360},
 	{"adis16365", ADIS16360},
+	{"adis16367", ADIS16367},
 	{"adis16400", ADIS16400},
 	{"adis16400", ADIS16400},
 	{"adis16405", ADIS16400},
 	{"adis16405", ADIS16400},
+	{"adis16445", ADIS16445},
 	{"adis16448", ADIS16448},
 	{"adis16448", ADIS16448},
 	{}
 	{}
 };
 };

+ 33 - 6
drivers/iio/imu/adis16480.c

@@ -110,6 +110,10 @@
 struct adis16480_chip_info {
 struct adis16480_chip_info {
 	unsigned int num_channels;
 	unsigned int num_channels;
 	const struct iio_chan_spec *channels;
 	const struct iio_chan_spec *channels;
+	unsigned int gyro_max_val;
+	unsigned int gyro_max_scale;
+	unsigned int accel_max_val;
+	unsigned int accel_max_scale;
 };
 };
 
 
 struct adis16480 {
 struct adis16480 {
@@ -497,19 +501,21 @@ static int adis16480_set_filter_freq(struct iio_dev *indio_dev,
 static int adis16480_read_raw(struct iio_dev *indio_dev,
 static int adis16480_read_raw(struct iio_dev *indio_dev,
 	const struct iio_chan_spec *chan, int *val, int *val2, long info)
 	const struct iio_chan_spec *chan, int *val, int *val2, long info)
 {
 {
+	struct adis16480 *st = iio_priv(indio_dev);
+
 	switch (info) {
 	switch (info) {
 	case IIO_CHAN_INFO_RAW:
 	case IIO_CHAN_INFO_RAW:
 		return adis_single_conversion(indio_dev, chan, 0, val);
 		return adis_single_conversion(indio_dev, chan, 0, val);
 	case IIO_CHAN_INFO_SCALE:
 	case IIO_CHAN_INFO_SCALE:
 		switch (chan->type) {
 		switch (chan->type) {
 		case IIO_ANGL_VEL:
 		case IIO_ANGL_VEL:
-			*val = 0;
-			*val2 = IIO_DEGREE_TO_RAD(20000); /* 0.02 degree/sec */
-			return IIO_VAL_INT_PLUS_MICRO;
+			*val = st->chip_info->gyro_max_scale;
+			*val2 = st->chip_info->gyro_max_val;
+			return IIO_VAL_FRACTIONAL;
 		case IIO_ACCEL:
 		case IIO_ACCEL:
-			*val = 0;
-			*val2 = IIO_G_TO_M_S_2(800); /* 0.8 mg */
-			return IIO_VAL_INT_PLUS_MICRO;
+			*val = st->chip_info->accel_max_scale;
+			*val2 = st->chip_info->accel_max_val;
+			return IIO_VAL_FRACTIONAL;
 		case IIO_MAGN:
 		case IIO_MAGN:
 			*val = 0;
 			*val = 0;
 			*val2 = 100; /* 0.0001 gauss */
 			*val2 = 100; /* 0.0001 gauss */
@@ -674,18 +680,39 @@ static const struct adis16480_chip_info adis16480_chip_info[] = {
 	[ADIS16375] = {
 	[ADIS16375] = {
 		.channels = adis16485_channels,
 		.channels = adis16485_channels,
 		.num_channels = ARRAY_SIZE(adis16485_channels),
 		.num_channels = ARRAY_SIZE(adis16485_channels),
+		/*
+		 * storing the value in rad/degree and the scale in degree
+		 * gives us the result in rad and better precession than
+		 * storing the scale directly in rad.
+		 */
+		.gyro_max_val = IIO_RAD_TO_DEGREE(22887),
+		.gyro_max_scale = 300,
+		.accel_max_val = IIO_M_S_2_TO_G(21973),
+		.accel_max_scale = 18,
 	},
 	},
 	[ADIS16480] = {
 	[ADIS16480] = {
 		.channels = adis16480_channels,
 		.channels = adis16480_channels,
 		.num_channels = ARRAY_SIZE(adis16480_channels),
 		.num_channels = ARRAY_SIZE(adis16480_channels),
+		.gyro_max_val = IIO_RAD_TO_DEGREE(22500),
+		.gyro_max_scale = 450,
+		.accel_max_val = IIO_M_S_2_TO_G(12500),
+		.accel_max_scale = 5,
 	},
 	},
 	[ADIS16485] = {
 	[ADIS16485] = {
 		.channels = adis16485_channels,
 		.channels = adis16485_channels,
 		.num_channels = ARRAY_SIZE(adis16485_channels),
 		.num_channels = ARRAY_SIZE(adis16485_channels),
+		.gyro_max_val = IIO_RAD_TO_DEGREE(22500),
+		.gyro_max_scale = 450,
+		.accel_max_val = IIO_M_S_2_TO_G(20000),
+		.accel_max_scale = 5,
 	},
 	},
 	[ADIS16488] = {
 	[ADIS16488] = {
 		.channels = adis16480_channels,
 		.channels = adis16480_channels,
 		.num_channels = ARRAY_SIZE(adis16480_channels),
 		.num_channels = ARRAY_SIZE(adis16480_channels),
+		.gyro_max_val = IIO_RAD_TO_DEGREE(22500),
+		.gyro_max_scale = 450,
+		.accel_max_val = IIO_M_S_2_TO_G(22500),
+		.accel_max_scale = 18,
 	},
 	},
 };
 };
 
 

+ 4 - 4
drivers/iio/imu/kmx61.c

@@ -1363,7 +1363,7 @@ static int kmx61_probe(struct i2c_client *client,
 	if (client->irq < 0)
 	if (client->irq < 0)
 		client->irq = kmx61_gpio_probe(client, data);
 		client->irq = kmx61_gpio_probe(client, data);
 
 
-	if (client->irq >= 0) {
+	if (client->irq > 0) {
 		ret = devm_request_threaded_irq(&client->dev, client->irq,
 		ret = devm_request_threaded_irq(&client->dev, client->irq,
 						kmx61_data_rdy_trig_poll,
 						kmx61_data_rdy_trig_poll,
 						kmx61_event_handler,
 						kmx61_event_handler,
@@ -1445,10 +1445,10 @@ err_iio_unregister_mag:
 err_iio_unregister_acc:
 err_iio_unregister_acc:
 	iio_device_unregister(data->acc_indio_dev);
 	iio_device_unregister(data->acc_indio_dev);
 err_buffer_cleanup_mag:
 err_buffer_cleanup_mag:
-	if (client->irq >= 0)
+	if (client->irq > 0)
 		iio_triggered_buffer_cleanup(data->mag_indio_dev);
 		iio_triggered_buffer_cleanup(data->mag_indio_dev);
 err_buffer_cleanup_acc:
 err_buffer_cleanup_acc:
-	if (client->irq >= 0)
+	if (client->irq > 0)
 		iio_triggered_buffer_cleanup(data->acc_indio_dev);
 		iio_triggered_buffer_cleanup(data->acc_indio_dev);
 err_trigger_unregister_motion:
 err_trigger_unregister_motion:
 	iio_trigger_unregister(data->motion_trig);
 	iio_trigger_unregister(data->motion_trig);
@@ -1472,7 +1472,7 @@ static int kmx61_remove(struct i2c_client *client)
 	iio_device_unregister(data->acc_indio_dev);
 	iio_device_unregister(data->acc_indio_dev);
 	iio_device_unregister(data->mag_indio_dev);
 	iio_device_unregister(data->mag_indio_dev);
 
 
-	if (client->irq >= 0) {
+	if (client->irq > 0) {
 		iio_triggered_buffer_cleanup(data->acc_indio_dev);
 		iio_triggered_buffer_cleanup(data->acc_indio_dev);
 		iio_triggered_buffer_cleanup(data->mag_indio_dev);
 		iio_triggered_buffer_cleanup(data->mag_indio_dev);
 		iio_trigger_unregister(data->acc_dready_trig);
 		iio_trigger_unregister(data->acc_dready_trig);

+ 15 - 2
drivers/iio/industrialio-buffer.c

@@ -91,9 +91,16 @@ static bool iio_buffer_ready(struct iio_dev *indio_dev, struct iio_buffer *buf,
 
 
 /**
 /**
  * iio_buffer_read_first_n_outer() - chrdev read for buffer access
  * iio_buffer_read_first_n_outer() - chrdev read for buffer access
+ * @filp:	File structure pointer for the char device
+ * @buf:	Destination buffer for iio buffer read
+ * @n:		First n bytes to read
+ * @f_ps:	Long offset provided by the user as a seek position
  *
  *
  * This function relies on all buffer implementations having an
  * This function relies on all buffer implementations having an
  * iio_buffer as their first element.
  * iio_buffer as their first element.
+ *
+ * Return: negative values corresponding to error codes or ret != 0
+ *	   for ending the reading activity
  **/
  **/
 ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf,
 ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf,
 				      size_t n, loff_t *f_ps)
 				      size_t n, loff_t *f_ps)
@@ -143,6 +150,12 @@ ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf,
 
 
 /**
 /**
  * iio_buffer_poll() - poll the buffer to find out if it has data
  * iio_buffer_poll() - poll the buffer to find out if it has data
+ * @filp:	File structure pointer for device access
+ * @wait:	Poll table structure pointer for which the driver adds
+ *		a wait queue
+ *
+ * Return: (POLLIN | POLLRDNORM) if data is available for reading
+ *	   or 0 for other cases
  */
  */
 unsigned int iio_buffer_poll(struct file *filp,
 unsigned int iio_buffer_poll(struct file *filp,
 			     struct poll_table_struct *wait)
 			     struct poll_table_struct *wait)
@@ -151,7 +164,7 @@ unsigned int iio_buffer_poll(struct file *filp,
 	struct iio_buffer *rb = indio_dev->buffer;
 	struct iio_buffer *rb = indio_dev->buffer;
 
 
 	if (!indio_dev->info)
 	if (!indio_dev->info)
-		return -ENODEV;
+		return 0;
 
 
 	poll_wait(filp, &rb->pollq, wait);
 	poll_wait(filp, &rb->pollq, wait);
 	if (iio_buffer_ready(indio_dev, rb, rb->watermark, 0))
 	if (iio_buffer_ready(indio_dev, rb, rb->watermark, 0))
@@ -1136,7 +1149,7 @@ int iio_scan_mask_query(struct iio_dev *indio_dev,
 EXPORT_SYMBOL_GPL(iio_scan_mask_query);
 EXPORT_SYMBOL_GPL(iio_scan_mask_query);
 
 
 /**
 /**
- * struct iio_demux_table() - table describing demux memcpy ops
+ * struct iio_demux_table - table describing demux memcpy ops
  * @from:	index to copy from
  * @from:	index to copy from
  * @to:		index to copy to
  * @to:		index to copy to
  * @length:	how many bytes to copy
  * @length:	how many bytes to copy

+ 20 - 5
drivers/iio/industrialio-core.c

@@ -406,10 +406,16 @@ EXPORT_SYMBOL_GPL(iio_enum_write);
 
 
 /**
 /**
  * iio_format_value() - Formats a IIO value into its string representation
  * iio_format_value() - Formats a IIO value into its string representation
- * @buf: The buffer to which the formated value gets written
- * @type: One of the IIO_VAL_... constants. This decides how the val and val2
- *        parameters are formatted.
- * @vals: pointer to the values, exact meaning depends on the type parameter.
+ * @buf:	The buffer to which the formatted value gets written
+ * @type:	One of the IIO_VAL_... constants. This decides how the val
+ *		and val2 parameters are formatted.
+ * @size:	Number of IIO value entries contained in vals
+ * @vals:	Pointer to the values, exact meaning depends on the
+ *		type parameter.
+ *
+ * Return: 0 by default, a negative number on failure or the
+ *	   total number of characters written for a type that belongs
+ *	   to the IIO_VAL_... constant.
  */
  */
 ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals)
 ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals)
 {
 {
@@ -1096,6 +1102,11 @@ EXPORT_SYMBOL_GPL(devm_iio_device_free);
 
 
 /**
 /**
  * iio_chrdev_open() - chrdev file open for buffer access and ioctls
  * iio_chrdev_open() - chrdev file open for buffer access and ioctls
+ * @inode:	Inode structure for identifying the device in the file system
+ * @filp:	File structure for iio device used to keep and later access
+ *		private data
+ *
+ * Return: 0 on success or -EBUSY if the device is already opened
  **/
  **/
 static int iio_chrdev_open(struct inode *inode, struct file *filp)
 static int iio_chrdev_open(struct inode *inode, struct file *filp)
 {
 {
@@ -1114,7 +1125,11 @@ static int iio_chrdev_open(struct inode *inode, struct file *filp)
 
 
 /**
 /**
  * iio_chrdev_release() - chrdev file close buffer access and ioctls
  * iio_chrdev_release() - chrdev file close buffer access and ioctls
- **/
+ * @inode:	Inode structure pointer for the char device
+ * @filp:	File structure pointer for the char device
+ *
+ * Return: 0 for successful release
+ */
 static int iio_chrdev_release(struct inode *inode, struct file *filp)
 static int iio_chrdev_release(struct inode *inode, struct file *filp)
 {
 {
 	struct iio_dev *indio_dev = container_of(inode->i_cdev,
 	struct iio_dev *indio_dev = container_of(inode->i_cdev,

+ 7 - 1
drivers/iio/industrialio-event.c

@@ -32,6 +32,7 @@
  * @dev_attr_list:	list of event interface sysfs attribute
  * @dev_attr_list:	list of event interface sysfs attribute
  * @flags:		file operations related flags including busy flag.
  * @flags:		file operations related flags including busy flag.
  * @group:		event interface sysfs attribute group
  * @group:		event interface sysfs attribute group
+ * @read_lock:		lock to protect kfifo read operations
  */
  */
 struct iio_event_interface {
 struct iio_event_interface {
 	wait_queue_head_t	wait;
 	wait_queue_head_t	wait;
@@ -75,6 +76,11 @@ EXPORT_SYMBOL(iio_push_event);
 
 
 /**
 /**
  * iio_event_poll() - poll the event queue to find out if it has data
  * iio_event_poll() - poll the event queue to find out if it has data
+ * @filep:	File structure pointer to identify the device
+ * @wait:	Poll table pointer to add the wait queue on
+ *
+ * Return: (POLLIN | POLLRDNORM) if data is available for reading
+ *	   or a negative error code on failure
  */
  */
 static unsigned int iio_event_poll(struct file *filep,
 static unsigned int iio_event_poll(struct file *filep,
 			     struct poll_table_struct *wait)
 			     struct poll_table_struct *wait)
@@ -84,7 +90,7 @@ static unsigned int iio_event_poll(struct file *filep,
 	unsigned int events = 0;
 	unsigned int events = 0;
 
 
 	if (!indio_dev->info)
 	if (!indio_dev->info)
-		return -ENODEV;
+		return events;
 
 
 	poll_wait(filep, &ev_int->wait, wait);
 	poll_wait(filep, &ev_int->wait, wait);
 
 

+ 24 - 3
drivers/iio/industrialio-trigger.c

@@ -40,7 +40,14 @@ static DEFINE_MUTEX(iio_trigger_list_lock);
 
 
 /**
 /**
  * iio_trigger_read_name() - retrieve useful identifying name
  * iio_trigger_read_name() - retrieve useful identifying name
- **/
+ * @dev:	device associated with the iio_trigger
+ * @attr:	pointer to the device_attribute structure that is
+ *		being processed
+ * @buf:	buffer to print the name into
+ *
+ * Return: a negative number on failure or the number of written
+ *	   characters on success.
+ */
 static ssize_t iio_trigger_read_name(struct device *dev,
 static ssize_t iio_trigger_read_name(struct device *dev,
 				     struct device_attribute *attr,
 				     struct device_attribute *attr,
 				     char *buf)
 				     char *buf)
@@ -288,10 +295,17 @@ EXPORT_SYMBOL_GPL(iio_dealloc_pollfunc);
 
 
 /**
 /**
  * iio_trigger_read_current() - trigger consumer sysfs query current trigger
  * iio_trigger_read_current() - trigger consumer sysfs query current trigger
+ * @dev:	device associated with an industrial I/O device
+ * @attr:	pointer to the device_attribute structure that
+ *		is being processed
+ * @buf:	buffer where the current trigger name will be printed into
  *
  *
  * For trigger consumers the current_trigger interface allows the trigger
  * For trigger consumers the current_trigger interface allows the trigger
  * used by the device to be queried.
  * used by the device to be queried.
- **/
+ *
+ * Return: a negative number on failure, the number of characters written
+ *	   on success or 0 if no trigger is available
+ */
 static ssize_t iio_trigger_read_current(struct device *dev,
 static ssize_t iio_trigger_read_current(struct device *dev,
 					struct device_attribute *attr,
 					struct device_attribute *attr,
 					char *buf)
 					char *buf)
@@ -305,11 +319,18 @@ static ssize_t iio_trigger_read_current(struct device *dev,
 
 
 /**
 /**
  * iio_trigger_write_current() - trigger consumer sysfs set current trigger
  * iio_trigger_write_current() - trigger consumer sysfs set current trigger
+ * @dev:	device associated with an industrial I/O device
+ * @attr:	device attribute that is being processed
+ * @buf:	string buffer that holds the name of the trigger
+ * @len:	length of the trigger name held by buf
  *
  *
  * For trigger consumers the current_trigger interface allows the trigger
  * For trigger consumers the current_trigger interface allows the trigger
  * used for this device to be specified at run time based on the trigger's
  * used for this device to be specified at run time based on the trigger's
  * name.
  * name.
- **/
+ *
+ * Return: negative error code on failure or length of the buffer
+ *	   on success
+ */
 static ssize_t iio_trigger_write_current(struct device *dev,
 static ssize_t iio_trigger_write_current(struct device *dev,
 					 struct device_attribute *attr,
 					 struct device_attribute *attr,
 					 const char *buf,
 					 const char *buf,

+ 21 - 0
drivers/iio/light/Kconfig

@@ -210,6 +210,27 @@ config LTR501
 	 This driver can also be built as a module.  If so, the module
 	 This driver can also be built as a module.  If so, the module
          will be called ltr501.
          will be called ltr501.
 
 
+config OPT3001
+	tristate "Texas Instruments OPT3001 Light Sensor"
+	depends on I2C
+	help
+	  If you say Y or M here, you get support for Texas Instruments
+	  OPT3001 Ambient Light Sensor.
+
+	  If built as a dynamically linked module, it will be called
+	  opt3001.
+
+config PA12203001
+        tristate "TXC PA12203001 light and proximity sensor"
+        depends on I2C
+        select REGMAP_I2C
+        help
+         If you say yes here you get support for the TXC PA12203001
+         ambient light and proximity sensor.
+
+         This driver can also be built as a module.  If so, the module
+         will be called pa12203001.
+
 config STK3310
 config STK3310
 	tristate "STK3310 ALS and proximity sensor"
 	tristate "STK3310 ALS and proximity sensor"
 	depends on I2C
 	depends on I2C

+ 2 - 0
drivers/iio/light/Makefile

@@ -19,6 +19,8 @@ obj-$(CONFIG_ISL29125)		+= isl29125.o
 obj-$(CONFIG_JSA1212)		+= jsa1212.o
 obj-$(CONFIG_JSA1212)		+= jsa1212.o
 obj-$(CONFIG_SENSORS_LM3533)	+= lm3533-als.o
 obj-$(CONFIG_SENSORS_LM3533)	+= lm3533-als.o
 obj-$(CONFIG_LTR501)		+= ltr501.o
 obj-$(CONFIG_LTR501)		+= ltr501.o
+obj-$(CONFIG_OPT3001)		+= opt3001.o
+obj-$(CONFIG_PA12203001)	+= pa12203001.o
 obj-$(CONFIG_RPR0521)		+= rpr0521.o
 obj-$(CONFIG_RPR0521)		+= rpr0521.o
 obj-$(CONFIG_SENSORS_TSL2563)	+= tsl2563.o
 obj-$(CONFIG_SENSORS_TSL2563)	+= tsl2563.o
 obj-$(CONFIG_STK3310)          += stk3310.o
 obj-$(CONFIG_STK3310)          += stk3310.o

+ 9 - 9
drivers/iio/light/acpi-als.c

@@ -65,20 +65,20 @@ static const struct iio_chan_spec acpi_als_channels[] = {
  * to acpi_als_channels[], the evt_buffer below will grow
  * to acpi_als_channels[], the evt_buffer below will grow
  * automatically.
  * automatically.
  */
  */
-#define EVT_NR_SOURCES		ARRAY_SIZE(acpi_als_channels)
-#define EVT_BUFFER_SIZE		\
-	(sizeof(s64) + (EVT_NR_SOURCES * sizeof(s32)))
+#define ACPI_ALS_EVT_NR_SOURCES		ARRAY_SIZE(acpi_als_channels)
+#define ACPI_ALS_EVT_BUFFER_SIZE		\
+	(sizeof(s64) + (ACPI_ALS_EVT_NR_SOURCES * sizeof(s32)))
 
 
 struct acpi_als {
 struct acpi_als {
 	struct acpi_device	*device;
 	struct acpi_device	*device;
 	struct mutex		lock;
 	struct mutex		lock;
 
 
-	s32			evt_buffer[EVT_BUFFER_SIZE];
+	s32			evt_buffer[ACPI_ALS_EVT_BUFFER_SIZE];
 };
 };
 
 
 /*
 /*
  * All types of properties the ACPI0008 block can report. The ALI, ALC, ALT
  * All types of properties the ACPI0008 block can report. The ALI, ALC, ALT
- * and ALP can all be handled by als_read_value() below, while the ALR is
+ * and ALP can all be handled by acpi_als_read_value() below, while the ALR is
  * special.
  * special.
  *
  *
  * The _ALR property returns tables that can be used to fine-tune the values
  * The _ALR property returns tables that can be used to fine-tune the values
@@ -93,7 +93,7 @@ struct acpi_als {
 #define ACPI_ALS_POLLING	"_ALP"
 #define ACPI_ALS_POLLING	"_ALP"
 #define ACPI_ALS_TABLES		"_ALR"
 #define ACPI_ALS_TABLES		"_ALR"
 
 
-static int als_read_value(struct acpi_als *als, char *prop, s32 *val)
+static int acpi_als_read_value(struct acpi_als *als, char *prop, s32 *val)
 {
 {
 	unsigned long long temp_val;
 	unsigned long long temp_val;
 	acpi_status status;
 	acpi_status status;
@@ -122,11 +122,11 @@ static void acpi_als_notify(struct acpi_device *device, u32 event)
 
 
 	mutex_lock(&als->lock);
 	mutex_lock(&als->lock);
 
 
-	memset(buffer, 0, EVT_BUFFER_SIZE);
+	memset(buffer, 0, ACPI_ALS_EVT_BUFFER_SIZE);
 
 
 	switch (event) {
 	switch (event) {
 	case ACPI_ALS_NOTIFY_ILLUMINANCE:
 	case ACPI_ALS_NOTIFY_ILLUMINANCE:
-		ret = als_read_value(als, ACPI_ALS_ILLUMINANCE, &val);
+		ret = acpi_als_read_value(als, ACPI_ALS_ILLUMINANCE, &val);
 		if (ret < 0)
 		if (ret < 0)
 			goto out;
 			goto out;
 		*buffer++ = val;
 		*buffer++ = val;
@@ -159,7 +159,7 @@ static int acpi_als_read_raw(struct iio_dev *indio_dev,
 	if (chan->type != IIO_LIGHT)
 	if (chan->type != IIO_LIGHT)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	ret = als_read_value(als, ACPI_ALS_ILLUMINANCE, &temp_val);
+	ret = acpi_als_read_value(als, ACPI_ALS_ILLUMINANCE, &temp_val);
 	if (ret < 0)
 	if (ret < 0)
 		return ret;
 		return ret;
 
 

+ 1 - 0
drivers/iio/light/cm32181.c

@@ -353,6 +353,7 @@ static const struct of_device_id cm32181_of_match[] = {
 	{ .compatible = "capella,cm32181" },
 	{ .compatible = "capella,cm32181" },
 	{ }
 	{ }
 };
 };
+MODULE_DEVICE_TABLE(of, cm32181_of_match);
 
 
 static struct i2c_driver cm32181_driver = {
 static struct i2c_driver cm32181_driver = {
 	.driver = {
 	.driver = {

+ 1 - 0
drivers/iio/light/cm3232.c

@@ -417,6 +417,7 @@ static const struct of_device_id cm3232_of_match[] = {
 	{.compatible = "capella,cm3232"},
 	{.compatible = "capella,cm3232"},
 	{}
 	{}
 };
 };
+MODULE_DEVICE_TABLE(of, cm3232_of_match);
 
 
 static struct i2c_driver cm3232_driver = {
 static struct i2c_driver cm3232_driver = {
 	.driver = {
 	.driver = {

+ 1 - 0
drivers/iio/light/cm36651.c

@@ -731,6 +731,7 @@ static const struct of_device_id cm36651_of_match[] = {
 	{ .compatible = "capella,cm36651" },
 	{ .compatible = "capella,cm36651" },
 	{ }
 	{ }
 };
 };
+MODULE_DEVICE_TABLE(of, cm36651_of_match);
 
 
 static struct i2c_driver cm36651_driver = {
 static struct i2c_driver cm36651_driver = {
 	.driver = {
 	.driver = {

+ 1 - 0
drivers/iio/light/gp2ap020a00f.c

@@ -1634,6 +1634,7 @@ static const struct of_device_id gp2ap020a00f_of_match[] = {
 	{ .compatible = "sharp,gp2ap020a00f" },
 	{ .compatible = "sharp,gp2ap020a00f" },
 	{ }
 	{ }
 };
 };
+MODULE_DEVICE_TABLE(of, gp2ap020a00f_of_match);
 #endif
 #endif
 
 
 static struct i2c_driver gp2ap020a00f_driver = {
 static struct i2c_driver gp2ap020a00f_driver = {

+ 804 - 0
drivers/iio/light/opt3001.c

@@ -0,0 +1,804 @@
+/**
+ * opt3001.c - Texas Instruments OPT3001 Light Sensor
+ *
+ * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * Author: Andreas Dannenberg <dannenberg@ti.com>
+ * Based on previous work from: Felipe Balbi <balbi@ti.com>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 of the License
+ * as published by the Free Software Foundation.
+ *
+ * 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/bitops.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include <linux/iio/events.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+#define OPT3001_RESULT		0x00
+#define OPT3001_CONFIGURATION	0x01
+#define OPT3001_LOW_LIMIT	0x02
+#define OPT3001_HIGH_LIMIT	0x03
+#define OPT3001_MANUFACTURER_ID	0x7e
+#define OPT3001_DEVICE_ID	0x7f
+
+#define OPT3001_CONFIGURATION_RN_MASK	(0xf << 12)
+#define OPT3001_CONFIGURATION_RN_AUTO	(0xc << 12)
+
+#define OPT3001_CONFIGURATION_CT	BIT(11)
+
+#define OPT3001_CONFIGURATION_M_MASK	(3 << 9)
+#define OPT3001_CONFIGURATION_M_SHUTDOWN (0 << 9)
+#define OPT3001_CONFIGURATION_M_SINGLE	(1 << 9)
+#define OPT3001_CONFIGURATION_M_CONTINUOUS (2 << 9) /* also 3 << 9 */
+
+#define OPT3001_CONFIGURATION_OVF	BIT(8)
+#define OPT3001_CONFIGURATION_CRF	BIT(7)
+#define OPT3001_CONFIGURATION_FH	BIT(6)
+#define OPT3001_CONFIGURATION_FL	BIT(5)
+#define OPT3001_CONFIGURATION_L		BIT(4)
+#define OPT3001_CONFIGURATION_POL	BIT(3)
+#define OPT3001_CONFIGURATION_ME	BIT(2)
+
+#define OPT3001_CONFIGURATION_FC_MASK	(3 << 0)
+
+/* The end-of-conversion enable is located in the low-limit register */
+#define OPT3001_LOW_LIMIT_EOC_ENABLE	0xc000
+
+#define OPT3001_REG_EXPONENT(n)		((n) >> 12)
+#define OPT3001_REG_MANTISSA(n)		((n) & 0xfff)
+
+/*
+ * Time to wait for conversion result to be ready. The device datasheet
+ * worst-case max value is 880ms. Add some slack to be on the safe side.
+ */
+#define OPT3001_RESULT_READY_TIMEOUT	msecs_to_jiffies(1000)
+
+struct opt3001 {
+	struct i2c_client	*client;
+	struct device		*dev;
+
+	struct mutex		lock;
+	u16			ok_to_ignore_lock:1;
+	u16			result_ready:1;
+	wait_queue_head_t	result_ready_queue;
+	u16			result;
+
+	u32			int_time;
+	u32			mode;
+
+	u16			high_thresh_mantissa;
+	u16			low_thresh_mantissa;
+
+	u8			high_thresh_exp;
+	u8			low_thresh_exp;
+};
+
+struct opt3001_scale {
+	int	val;
+	int	val2;
+};
+
+static const struct opt3001_scale opt3001_scales[] = {
+	{
+		.val = 40,
+		.val2 = 950000,
+	},
+	{
+		.val = 81,
+		.val2 = 900000,
+	},
+	{
+		.val = 163,
+		.val2 = 800000,
+	},
+	{
+		.val = 327,
+		.val2 = 600000,
+	},
+	{
+		.val = 655,
+		.val2 = 200000,
+	},
+	{
+		.val = 1310,
+		.val2 = 400000,
+	},
+	{
+		.val = 2620,
+		.val2 = 800000,
+	},
+	{
+		.val = 5241,
+		.val2 = 600000,
+	},
+	{
+		.val = 10483,
+		.val2 = 200000,
+	},
+	{
+		.val = 20966,
+		.val2 = 400000,
+	},
+	{
+		.val = 83865,
+		.val2 = 600000,
+	},
+};
+
+static int opt3001_find_scale(const struct opt3001 *opt, int val,
+		int val2, u8 *exponent)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(opt3001_scales); i++) {
+		const struct opt3001_scale *scale = &opt3001_scales[i];
+
+		/*
+		 * Combine the integer and micro parts for comparison
+		 * purposes. Use milli lux precision to avoid 32-bit integer
+		 * overflows.
+		 */
+		if ((val * 1000 + val2 / 1000) <=
+				(scale->val * 1000 + scale->val2 / 1000)) {
+			*exponent = i;
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
+static void opt3001_to_iio_ret(struct opt3001 *opt, u8 exponent,
+		u16 mantissa, int *val, int *val2)
+{
+	int lux;
+
+	lux = 10 * (mantissa << exponent);
+	*val = lux / 1000;
+	*val2 = (lux - (*val * 1000)) * 1000;
+}
+
+static void opt3001_set_mode(struct opt3001 *opt, u16 *reg, u16 mode)
+{
+	*reg &= ~OPT3001_CONFIGURATION_M_MASK;
+	*reg |= mode;
+	opt->mode = mode;
+}
+
+static IIO_CONST_ATTR_INT_TIME_AVAIL("0.1 0.8");
+
+static struct attribute *opt3001_attributes[] = {
+	&iio_const_attr_integration_time_available.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group opt3001_attribute_group = {
+	.attrs = opt3001_attributes,
+};
+
+static const struct iio_event_spec opt3001_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_chan_spec opt3001_channels[] = {
+	{
+		.type = IIO_LIGHT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+				BIT(IIO_CHAN_INFO_INT_TIME),
+		.event_spec = opt3001_event_spec,
+		.num_event_specs = ARRAY_SIZE(opt3001_event_spec),
+	},
+	IIO_CHAN_SOFT_TIMESTAMP(1),
+};
+
+static int opt3001_get_lux(struct opt3001 *opt, int *val, int *val2)
+{
+	int ret;
+	u16 mantissa;
+	u16 reg;
+	u8 exponent;
+	u16 value;
+
+	/*
+	 * Enable the end-of-conversion interrupt mechanism. Note that doing
+	 * so will overwrite the low-level limit value however we will restore
+	 * this value later on.
+	 */
+	ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_LOW_LIMIT,
+			OPT3001_LOW_LIMIT_EOC_ENABLE);
+	if (ret < 0) {
+		dev_err(opt->dev, "failed to write register %02x\n",
+				OPT3001_LOW_LIMIT);
+		return ret;
+	}
+
+	/* Reset data-ready indicator flag (will be set in the IRQ routine) */
+	opt->result_ready = false;
+
+	/* Allow IRQ to access the device despite lock being set */
+	opt->ok_to_ignore_lock = true;
+
+	/* Configure for single-conversion mode and start a new conversion */
+	ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION);
+	if (ret < 0) {
+		dev_err(opt->dev, "failed to read register %02x\n",
+				OPT3001_CONFIGURATION);
+		goto err;
+	}
+
+	reg = ret;
+	opt3001_set_mode(opt, &reg, OPT3001_CONFIGURATION_M_SINGLE);
+
+	ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_CONFIGURATION,
+			reg);
+	if (ret < 0) {
+		dev_err(opt->dev, "failed to write register %02x\n",
+				OPT3001_CONFIGURATION);
+		goto err;
+	}
+
+	/* Wait for the IRQ to indicate the conversion is complete */
+	ret = wait_event_timeout(opt->result_ready_queue, opt->result_ready,
+			OPT3001_RESULT_READY_TIMEOUT);
+
+err:
+	/* Disallow IRQ to access the device while lock is active */
+	opt->ok_to_ignore_lock = false;
+
+	if (ret == 0)
+		return -ETIMEDOUT;
+	else if (ret < 0)
+		return ret;
+
+	/*
+	 * Disable the end-of-conversion interrupt mechanism by restoring the
+	 * low-level limit value (clearing OPT3001_LOW_LIMIT_EOC_ENABLE). Note
+	 * that selectively clearing those enable bits would affect the actual
+	 * limit value due to bit-overlap and therefore can't be done.
+	 */
+	value = (opt->low_thresh_exp << 12) | opt->low_thresh_mantissa;
+	ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_LOW_LIMIT,
+			value);
+	if (ret < 0) {
+		dev_err(opt->dev, "failed to write register %02x\n",
+				OPT3001_LOW_LIMIT);
+		return ret;
+	}
+
+	exponent = OPT3001_REG_EXPONENT(opt->result);
+	mantissa = OPT3001_REG_MANTISSA(opt->result);
+
+	opt3001_to_iio_ret(opt, exponent, mantissa, val, val2);
+
+	return IIO_VAL_INT_PLUS_MICRO;
+}
+
+static int opt3001_get_int_time(struct opt3001 *opt, int *val, int *val2)
+{
+	*val = 0;
+	*val2 = opt->int_time;
+
+	return IIO_VAL_INT_PLUS_MICRO;
+}
+
+static int opt3001_set_int_time(struct opt3001 *opt, int time)
+{
+	int ret;
+	u16 reg;
+
+	ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION);
+	if (ret < 0) {
+		dev_err(opt->dev, "failed to read register %02x\n",
+				OPT3001_CONFIGURATION);
+		return ret;
+	}
+
+	reg = ret;
+
+	switch (time) {
+	case 100000:
+		reg &= ~OPT3001_CONFIGURATION_CT;
+		opt->int_time = 100000;
+		break;
+	case 800000:
+		reg |= OPT3001_CONFIGURATION_CT;
+		opt->int_time = 800000;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return i2c_smbus_write_word_swapped(opt->client, OPT3001_CONFIGURATION,
+			reg);
+}
+
+static int opt3001_read_raw(struct iio_dev *iio,
+		struct iio_chan_spec const *chan, int *val, int *val2,
+		long mask)
+{
+	struct opt3001 *opt = iio_priv(iio);
+	int ret;
+
+	if (opt->mode == OPT3001_CONFIGURATION_M_CONTINUOUS)
+		return -EBUSY;
+
+	if (chan->type != IIO_LIGHT)
+		return -EINVAL;
+
+	mutex_lock(&opt->lock);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_PROCESSED:
+		ret = opt3001_get_lux(opt, val, val2);
+		break;
+	case IIO_CHAN_INFO_INT_TIME:
+		ret = opt3001_get_int_time(opt, val, val2);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	mutex_unlock(&opt->lock);
+
+	return ret;
+}
+
+static int opt3001_write_raw(struct iio_dev *iio,
+		struct iio_chan_spec const *chan, int val, int val2,
+		long mask)
+{
+	struct opt3001 *opt = iio_priv(iio);
+	int ret;
+
+	if (opt->mode == OPT3001_CONFIGURATION_M_CONTINUOUS)
+		return -EBUSY;
+
+	if (chan->type != IIO_LIGHT)
+		return -EINVAL;
+
+	if (mask != IIO_CHAN_INFO_INT_TIME)
+		return -EINVAL;
+
+	if (val != 0)
+		return -EINVAL;
+
+	mutex_lock(&opt->lock);
+	ret = opt3001_set_int_time(opt, val2);
+	mutex_unlock(&opt->lock);
+
+	return ret;
+}
+
+static int opt3001_read_event_value(struct iio_dev *iio,
+		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 opt3001 *opt = iio_priv(iio);
+	int ret = IIO_VAL_INT_PLUS_MICRO;
+
+	mutex_lock(&opt->lock);
+
+	switch (dir) {
+	case IIO_EV_DIR_RISING:
+		opt3001_to_iio_ret(opt, opt->high_thresh_exp,
+				opt->high_thresh_mantissa, val, val2);
+		break;
+	case IIO_EV_DIR_FALLING:
+		opt3001_to_iio_ret(opt, opt->low_thresh_exp,
+				opt->low_thresh_mantissa, val, val2);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	mutex_unlock(&opt->lock);
+
+	return ret;
+}
+
+static int opt3001_write_event_value(struct iio_dev *iio,
+		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 opt3001 *opt = iio_priv(iio);
+	int ret;
+
+	u16 mantissa;
+	u16 value;
+	u16 reg;
+
+	u8 exponent;
+
+	if (val < 0)
+		return -EINVAL;
+
+	mutex_lock(&opt->lock);
+
+	ret = opt3001_find_scale(opt, val, val2, &exponent);
+	if (ret < 0) {
+		dev_err(opt->dev, "can't find scale for %d.%06u\n", val, val2);
+		goto err;
+	}
+
+	mantissa = (((val * 1000) + (val2 / 1000)) / 10) >> exponent;
+	value = (exponent << 12) | mantissa;
+
+	switch (dir) {
+	case IIO_EV_DIR_RISING:
+		reg = OPT3001_HIGH_LIMIT;
+		opt->high_thresh_mantissa = mantissa;
+		opt->high_thresh_exp = exponent;
+		break;
+	case IIO_EV_DIR_FALLING:
+		reg = OPT3001_LOW_LIMIT;
+		opt->low_thresh_mantissa = mantissa;
+		opt->low_thresh_exp = exponent;
+		break;
+	default:
+		ret = -EINVAL;
+		goto err;
+	}
+
+	ret = i2c_smbus_write_word_swapped(opt->client, reg, value);
+	if (ret < 0) {
+		dev_err(opt->dev, "failed to write register %02x\n", reg);
+		goto err;
+	}
+
+err:
+	mutex_unlock(&opt->lock);
+
+	return ret;
+}
+
+static int opt3001_read_event_config(struct iio_dev *iio,
+		const struct iio_chan_spec *chan, enum iio_event_type type,
+		enum iio_event_direction dir)
+{
+	struct opt3001 *opt = iio_priv(iio);
+
+	return opt->mode == OPT3001_CONFIGURATION_M_CONTINUOUS;
+}
+
+static int opt3001_write_event_config(struct iio_dev *iio,
+		const struct iio_chan_spec *chan, enum iio_event_type type,
+		enum iio_event_direction dir, int state)
+{
+	struct opt3001 *opt = iio_priv(iio);
+	int ret;
+	u16 mode;
+	u16 reg;
+
+	if (state && opt->mode == OPT3001_CONFIGURATION_M_CONTINUOUS)
+		return 0;
+
+	if (!state && opt->mode == OPT3001_CONFIGURATION_M_SHUTDOWN)
+		return 0;
+
+	mutex_lock(&opt->lock);
+
+	mode = state ? OPT3001_CONFIGURATION_M_CONTINUOUS
+		: OPT3001_CONFIGURATION_M_SHUTDOWN;
+
+	ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION);
+	if (ret < 0) {
+		dev_err(opt->dev, "failed to read register %02x\n",
+				OPT3001_CONFIGURATION);
+		goto err;
+	}
+
+	reg = ret;
+	opt3001_set_mode(opt, &reg, mode);
+
+	ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_CONFIGURATION,
+			reg);
+	if (ret < 0) {
+		dev_err(opt->dev, "failed to write register %02x\n",
+				OPT3001_CONFIGURATION);
+		goto err;
+	}
+
+err:
+	mutex_unlock(&opt->lock);
+
+	return ret;
+}
+
+static const struct iio_info opt3001_info = {
+	.driver_module = THIS_MODULE,
+	.attrs = &opt3001_attribute_group,
+	.read_raw = opt3001_read_raw,
+	.write_raw = opt3001_write_raw,
+	.read_event_value = opt3001_read_event_value,
+	.write_event_value = opt3001_write_event_value,
+	.read_event_config = opt3001_read_event_config,
+	.write_event_config = opt3001_write_event_config,
+};
+
+static int opt3001_read_id(struct opt3001 *opt)
+{
+	char manufacturer[2];
+	u16 device_id;
+	int ret;
+
+	ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_MANUFACTURER_ID);
+	if (ret < 0) {
+		dev_err(opt->dev, "failed to read register %02x\n",
+				OPT3001_MANUFACTURER_ID);
+		return ret;
+	}
+
+	manufacturer[0] = ret >> 8;
+	manufacturer[1] = ret & 0xff;
+
+	ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_DEVICE_ID);
+	if (ret < 0) {
+		dev_err(opt->dev, "failed to read register %02x\n",
+				OPT3001_DEVICE_ID);
+		return ret;
+	}
+
+	device_id = ret;
+
+	dev_info(opt->dev, "Found %c%c OPT%04x\n", manufacturer[0],
+			manufacturer[1], device_id);
+
+	return 0;
+}
+
+static int opt3001_configure(struct opt3001 *opt)
+{
+	int ret;
+	u16 reg;
+
+	ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION);
+	if (ret < 0) {
+		dev_err(opt->dev, "failed to read register %02x\n",
+				OPT3001_CONFIGURATION);
+		return ret;
+	}
+
+	reg = ret;
+
+	/* Enable automatic full-scale setting mode */
+	reg &= ~OPT3001_CONFIGURATION_RN_MASK;
+	reg |= OPT3001_CONFIGURATION_RN_AUTO;
+
+	/* Reflect status of the device's integration time setting */
+	if (reg & OPT3001_CONFIGURATION_CT)
+		opt->int_time = 800000;
+	else
+		opt->int_time = 100000;
+
+	/* Ensure device is in shutdown initially */
+	opt3001_set_mode(opt, &reg, OPT3001_CONFIGURATION_M_SHUTDOWN);
+
+	/* Configure for latched window-style comparison operation */
+	reg |= OPT3001_CONFIGURATION_L;
+	reg &= ~OPT3001_CONFIGURATION_POL;
+	reg &= ~OPT3001_CONFIGURATION_ME;
+	reg &= ~OPT3001_CONFIGURATION_FC_MASK;
+
+	ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_CONFIGURATION,
+			reg);
+	if (ret < 0) {
+		dev_err(opt->dev, "failed to write register %02x\n",
+				OPT3001_CONFIGURATION);
+		return ret;
+	}
+
+	ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_LOW_LIMIT);
+	if (ret < 0) {
+		dev_err(opt->dev, "failed to read register %02x\n",
+				OPT3001_LOW_LIMIT);
+		return ret;
+	}
+
+	opt->low_thresh_mantissa = OPT3001_REG_MANTISSA(ret);
+	opt->low_thresh_exp = OPT3001_REG_EXPONENT(ret);
+
+	ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_HIGH_LIMIT);
+	if (ret < 0) {
+		dev_err(opt->dev, "failed to read register %02x\n",
+				OPT3001_HIGH_LIMIT);
+		return ret;
+	}
+
+	opt->high_thresh_mantissa = OPT3001_REG_MANTISSA(ret);
+	opt->high_thresh_exp = OPT3001_REG_EXPONENT(ret);
+
+	return 0;
+}
+
+static irqreturn_t opt3001_irq(int irq, void *_iio)
+{
+	struct iio_dev *iio = _iio;
+	struct opt3001 *opt = iio_priv(iio);
+	int ret;
+
+	if (!opt->ok_to_ignore_lock)
+		mutex_lock(&opt->lock);
+
+	ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION);
+	if (ret < 0) {
+		dev_err(opt->dev, "failed to read register %02x\n",
+				OPT3001_CONFIGURATION);
+		goto out;
+	}
+
+	if ((ret & OPT3001_CONFIGURATION_M_MASK) ==
+			OPT3001_CONFIGURATION_M_CONTINUOUS) {
+		if (ret & OPT3001_CONFIGURATION_FH)
+			iio_push_event(iio,
+					IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
+							IIO_EV_TYPE_THRESH,
+							IIO_EV_DIR_RISING),
+					iio_get_time_ns());
+		if (ret & OPT3001_CONFIGURATION_FL)
+			iio_push_event(iio,
+					IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
+							IIO_EV_TYPE_THRESH,
+							IIO_EV_DIR_FALLING),
+					iio_get_time_ns());
+	} else if (ret & OPT3001_CONFIGURATION_CRF) {
+		ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_RESULT);
+		if (ret < 0) {
+			dev_err(opt->dev, "failed to read register %02x\n",
+					OPT3001_RESULT);
+			goto out;
+		}
+		opt->result = ret;
+		opt->result_ready = true;
+		wake_up(&opt->result_ready_queue);
+	}
+
+out:
+	if (!opt->ok_to_ignore_lock)
+		mutex_unlock(&opt->lock);
+
+	return IRQ_HANDLED;
+}
+
+static int opt3001_probe(struct i2c_client *client,
+		const struct i2c_device_id *id)
+{
+	struct device *dev = &client->dev;
+
+	struct iio_dev *iio;
+	struct opt3001 *opt;
+	int irq = client->irq;
+	int ret;
+
+	iio = devm_iio_device_alloc(dev, sizeof(*opt));
+	if (!iio)
+		return -ENOMEM;
+
+	opt = iio_priv(iio);
+	opt->client = client;
+	opt->dev = dev;
+
+	mutex_init(&opt->lock);
+	init_waitqueue_head(&opt->result_ready_queue);
+	i2c_set_clientdata(client, iio);
+
+	ret = opt3001_read_id(opt);
+	if (ret)
+		return ret;
+
+	ret = opt3001_configure(opt);
+	if (ret)
+		return ret;
+
+	iio->name = client->name;
+	iio->channels = opt3001_channels;
+	iio->num_channels = ARRAY_SIZE(opt3001_channels);
+	iio->dev.parent = dev;
+	iio->modes = INDIO_DIRECT_MODE;
+	iio->info = &opt3001_info;
+
+	ret = devm_iio_device_register(dev, iio);
+	if (ret) {
+		dev_err(dev, "failed to register IIO device\n");
+		return ret;
+	}
+
+	ret = request_threaded_irq(irq, NULL, opt3001_irq,
+			IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+			"opt3001", iio);
+	if (ret) {
+		dev_err(dev, "failed to request IRQ #%d\n", irq);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int opt3001_remove(struct i2c_client *client)
+{
+	struct iio_dev *iio = i2c_get_clientdata(client);
+	struct opt3001 *opt = iio_priv(iio);
+	int ret;
+	u16 reg;
+
+	free_irq(client->irq, iio);
+
+	ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION);
+	if (ret < 0) {
+		dev_err(opt->dev, "failed to read register %02x\n",
+				OPT3001_CONFIGURATION);
+		return ret;
+	}
+
+	reg = ret;
+	opt3001_set_mode(opt, &reg, OPT3001_CONFIGURATION_M_SHUTDOWN);
+
+	ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_CONFIGURATION,
+			reg);
+	if (ret < 0) {
+		dev_err(opt->dev, "failed to write register %02x\n",
+				OPT3001_CONFIGURATION);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct i2c_device_id opt3001_id[] = {
+	{ "opt3001", 0 },
+	{ } /* Terminating Entry */
+};
+MODULE_DEVICE_TABLE(i2c, opt3001_id);
+
+static const struct of_device_id opt3001_of_match[] = {
+	{ .compatible = "ti,opt3001" },
+	{ }
+};
+
+static struct i2c_driver opt3001_driver = {
+	.probe = opt3001_probe,
+	.remove = opt3001_remove,
+	.id_table = opt3001_id,
+
+	.driver = {
+		.name = "opt3001",
+		.of_match_table = of_match_ptr(opt3001_of_match),
+		.owner = THIS_MODULE,
+	},
+};
+
+module_i2c_driver(opt3001_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Andreas Dannenberg <dannenberg@ti.com>");
+MODULE_DESCRIPTION("Texas Instruments OPT3001 Light Sensor Driver");

+ 483 - 0
drivers/iio/light/pa12203001.c

@@ -0,0 +1,483 @@
+/*
+ * Copyright (c) 2015 Intel Corporation
+ *
+ * Driver for TXC PA12203001 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.
+ * 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>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#define PA12203001_DRIVER_NAME	"pa12203001"
+
+#define PA12203001_REG_CFG0		0x00
+#define PA12203001_REG_CFG1		0x01
+#define PA12203001_REG_CFG2		0x02
+#define PA12203001_REG_CFG3		0x03
+
+#define PA12203001_REG_ADL		0x0b
+#define PA12203001_REG_PDH		0x0e
+
+#define PA12203001_REG_POFS		0x10
+#define PA12203001_REG_PSET		0x11
+
+#define PA12203001_ALS_EN_MASK		BIT(0)
+#define PA12203001_PX_EN_MASK		BIT(1)
+#define PA12203001_PX_NORMAL_MODE_MASK		GENMASK(7, 6)
+#define PA12203001_AFSR_MASK		GENMASK(5, 4)
+#define PA12203001_AFSR_SHIFT		4
+
+#define PA12203001_PSCAN			0x03
+
+/* als range 31000, ps, als disabled */
+#define PA12203001_REG_CFG0_DEFAULT		0x30
+
+/* led current: 100 mA */
+#define PA12203001_REG_CFG1_DEFAULT		0x20
+
+/* ps mode: normal, interrupts not active */
+#define PA12203001_REG_CFG2_DEFAULT		0xcc
+
+#define PA12203001_REG_CFG3_DEFAULT		0x00
+
+#define PA12203001_SLEEP_DELAY_MS		3000
+
+#define PA12203001_CHIP_ENABLE		0xff
+#define PA12203001_CHIP_DISABLE		0x00
+
+/* available scales: corresponding to [500, 4000, 7000, 31000]  lux */
+static const int pa12203001_scales[] = { 7629, 61036, 106813, 473029};
+
+struct pa12203001_data {
+	struct i2c_client *client;
+
+	/* protect device states */
+	struct mutex lock;
+
+	bool als_enabled;
+	bool px_enabled;
+	bool als_needs_enable;
+	bool px_needs_enable;
+
+	struct regmap *map;
+};
+
+static const struct {
+	u8 reg;
+	u8 val;
+} regvals[] = {
+	{PA12203001_REG_CFG0, PA12203001_REG_CFG0_DEFAULT},
+	{PA12203001_REG_CFG1, PA12203001_REG_CFG1_DEFAULT},
+	{PA12203001_REG_CFG2, PA12203001_REG_CFG2_DEFAULT},
+	{PA12203001_REG_CFG3, PA12203001_REG_CFG3_DEFAULT},
+	{PA12203001_REG_PSET, PA12203001_PSCAN},
+};
+
+static IIO_CONST_ATTR(in_illuminance_scale_available,
+		      "0.007629 0.061036 0.106813 0.473029");
+
+static struct attribute *pa12203001_attrs[] = {
+	&iio_const_attr_in_illuminance_scale_available.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group pa12203001_attr_group = {
+	.attrs = pa12203001_attrs,
+};
+
+static const struct iio_chan_spec pa12203001_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 const struct regmap_range pa12203001_volatile_regs_ranges[] = {
+	regmap_reg_range(PA12203001_REG_ADL, PA12203001_REG_ADL + 1),
+	regmap_reg_range(PA12203001_REG_PDH, PA12203001_REG_PDH),
+};
+
+static const struct regmap_access_table pa12203001_volatile_regs = {
+	.yes_ranges = pa12203001_volatile_regs_ranges,
+	.n_yes_ranges = ARRAY_SIZE(pa12203001_volatile_regs_ranges),
+};
+
+static const struct regmap_config pa12203001_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = PA12203001_REG_PSET,
+	.cache_type = REGCACHE_RBTREE,
+	.volatile_table = &pa12203001_volatile_regs,
+};
+
+static inline int pa12203001_als_enable(struct pa12203001_data *data, u8 enable)
+{
+	int ret;
+
+	ret = regmap_update_bits(data->map, PA12203001_REG_CFG0,
+				 PA12203001_ALS_EN_MASK, enable);
+	if (ret < 0)
+		return ret;
+
+	data->als_enabled = !!enable;
+
+	return 0;
+}
+
+static inline int pa12203001_px_enable(struct pa12203001_data *data, u8 enable)
+{
+	int ret;
+
+	ret = regmap_update_bits(data->map, PA12203001_REG_CFG0,
+				 PA12203001_PX_EN_MASK, enable);
+	if (ret < 0)
+		return ret;
+
+	data->px_enabled = !!enable;
+
+	return 0;
+}
+
+static int pa12203001_set_power_state(struct pa12203001_data *data, bool on,
+				      u8 mask)
+{
+#ifdef CONFIG_PM
+	int ret;
+
+	if (on && (mask & PA12203001_ALS_EN_MASK)) {
+		mutex_lock(&data->lock);
+		if (data->px_enabled) {
+			ret = pa12203001_als_enable(data,
+						    PA12203001_ALS_EN_MASK);
+			if (ret < 0)
+				goto err;
+		} else {
+			data->als_needs_enable = true;
+		}
+		mutex_unlock(&data->lock);
+	}
+
+	if (on && (mask & PA12203001_PX_EN_MASK)) {
+		mutex_lock(&data->lock);
+		if (data->als_enabled) {
+			ret = pa12203001_px_enable(data, PA12203001_PX_EN_MASK);
+			if (ret < 0)
+				goto err;
+		} else {
+			data->px_needs_enable = true;
+		}
+		mutex_unlock(&data->lock);
+	}
+
+	if (on) {
+		ret = pm_runtime_get_sync(&data->client->dev);
+		if (ret < 0)
+			pm_runtime_put_noidle(&data->client->dev);
+
+	} else {
+		pm_runtime_mark_last_busy(&data->client->dev);
+		ret = pm_runtime_put_autosuspend(&data->client->dev);
+	}
+
+	return ret;
+
+err:
+	mutex_unlock(&data->lock);
+	return ret;
+
+#endif
+	return 0;
+}
+
+static int pa12203001_read_raw(struct iio_dev *indio_dev,
+			       struct iio_chan_spec const *chan, int *val,
+			       int *val2, long mask)
+{
+	struct pa12203001_data *data = iio_priv(indio_dev);
+	int ret;
+	u8 dev_mask;
+	unsigned int reg_byte;
+	__le16 reg_word;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		switch (chan->type) {
+		case IIO_LIGHT:
+			dev_mask = PA12203001_ALS_EN_MASK;
+			ret = pa12203001_set_power_state(data, true, dev_mask);
+			if (ret < 0)
+				return ret;
+			/*
+			 * ALS ADC value is stored in registers
+			 * PA12203001_REG_ADL and in PA12203001_REG_ADL + 1.
+			 */
+			ret = regmap_bulk_read(data->map, PA12203001_REG_ADL,
+					       &reg_word, 2);
+			if (ret < 0)
+				goto reg_err;
+
+			*val = le16_to_cpu(reg_word);
+			ret = pa12203001_set_power_state(data, false, dev_mask);
+			if (ret < 0)
+				return ret;
+			break;
+		case IIO_PROXIMITY:
+			dev_mask = PA12203001_PX_EN_MASK;
+			ret = pa12203001_set_power_state(data, true, dev_mask);
+			if (ret < 0)
+				return ret;
+			ret = regmap_read(data->map, PA12203001_REG_PDH,
+					  &reg_byte);
+			if (ret < 0)
+				goto reg_err;
+
+			*val = reg_byte;
+			ret = pa12203001_set_power_state(data, false, dev_mask);
+			if (ret < 0)
+				return ret;
+			break;
+		default:
+			return -EINVAL;
+		}
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		ret = regmap_read(data->map, PA12203001_REG_CFG0, &reg_byte);
+		if (ret < 0)
+			return ret;
+		*val = 0;
+		reg_byte = (reg_byte & PA12203001_AFSR_MASK);
+		*val2 = pa12203001_scales[reg_byte >> 4];
+		return IIO_VAL_INT_PLUS_MICRO;
+	default:
+		return -EINVAL;
+	}
+
+reg_err:
+	pa12203001_set_power_state(data, false, dev_mask);
+	return ret;
+}
+
+static int pa12203001_write_raw(struct iio_dev *indio_dev,
+				struct iio_chan_spec const *chan, int val,
+				int val2, long mask)
+{
+	struct pa12203001_data *data = iio_priv(indio_dev);
+	int i, ret, new_val;
+	unsigned int reg_byte;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SCALE:
+		ret = regmap_read(data->map, PA12203001_REG_CFG0, &reg_byte);
+		if (val != 0 || ret < 0)
+			return -EINVAL;
+		for (i = 0; i < ARRAY_SIZE(pa12203001_scales); i++) {
+			if (val2 == pa12203001_scales[i]) {
+				new_val = i << PA12203001_AFSR_SHIFT;
+				return regmap_update_bits(data->map,
+							  PA12203001_REG_CFG0,
+							  PA12203001_AFSR_MASK,
+							  new_val);
+			}
+		}
+		break;
+	default:
+		break;
+	}
+
+	return -EINVAL;
+}
+
+static const struct iio_info pa12203001_info = {
+	.driver_module	= THIS_MODULE,
+	.read_raw = pa12203001_read_raw,
+	.write_raw = pa12203001_write_raw,
+	.attrs = &pa12203001_attr_group,
+};
+
+static int pa12203001_init(struct iio_dev *indio_dev)
+{
+	struct pa12203001_data *data = iio_priv(indio_dev);
+	int i, ret;
+
+	for (i = 0; i < ARRAY_SIZE(regvals); i++) {
+		ret = regmap_write(data->map, regvals[i].reg, regvals[i].val);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int pa12203001_power_chip(struct iio_dev *indio_dev, u8 state)
+{
+	struct pa12203001_data *data = iio_priv(indio_dev);
+	int ret;
+
+	mutex_lock(&data->lock);
+	ret = pa12203001_als_enable(data, state);
+	if (ret < 0)
+		goto out;
+
+	ret = pa12203001_px_enable(data, state);
+
+out:
+	mutex_unlock(&data->lock);
+	return ret;
+}
+
+static int pa12203001_probe(struct i2c_client *client,
+			    const struct i2c_device_id *id)
+{
+	struct pa12203001_data *data;
+	struct iio_dev *indio_dev;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(&client->dev,
+					  sizeof(struct pa12203001_data));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	data = iio_priv(indio_dev);
+	i2c_set_clientdata(client, indio_dev);
+	data->client = client;
+
+	data->map = devm_regmap_init_i2c(client, &pa12203001_regmap_config);
+	if (IS_ERR(data->map))
+		return PTR_ERR(data->map);
+
+	mutex_init(&data->lock);
+
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->info = &pa12203001_info;
+	indio_dev->name = PA12203001_DRIVER_NAME;
+	indio_dev->channels = pa12203001_channels;
+	indio_dev->num_channels = ARRAY_SIZE(pa12203001_channels);
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	ret = pa12203001_init(indio_dev);
+	if (ret < 0)
+		return ret;
+
+	ret = pa12203001_power_chip(indio_dev, PA12203001_CHIP_ENABLE);
+	if (ret < 0)
+		return ret;
+
+	ret = pm_runtime_set_active(&client->dev);
+	if (ret < 0) {
+		pa12203001_power_chip(indio_dev, PA12203001_CHIP_DISABLE);
+		return ret;
+	}
+
+	pm_runtime_enable(&client->dev);
+	pm_runtime_set_autosuspend_delay(&client->dev,
+					 PA12203001_SLEEP_DELAY_MS);
+	pm_runtime_use_autosuspend(&client->dev);
+
+	return iio_device_register(indio_dev);
+}
+
+static int pa12203001_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+
+	iio_device_unregister(indio_dev);
+
+	pm_runtime_disable(&client->dev);
+	pm_runtime_set_suspended(&client->dev);
+
+	return pa12203001_power_chip(indio_dev, PA12203001_CHIP_DISABLE);
+}
+
+#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM)
+static int pa12203001_suspend(struct device *dev)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+
+	return pa12203001_power_chip(indio_dev, PA12203001_CHIP_DISABLE);
+}
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+static int pa12203001_resume(struct device *dev)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+
+	return pa12203001_power_chip(indio_dev, PA12203001_CHIP_ENABLE);
+}
+#endif
+
+#ifdef CONFIG_PM
+static int pa12203001_runtime_resume(struct device *dev)
+{
+	struct pa12203001_data *data;
+
+	data = iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
+
+	mutex_lock(&data->lock);
+	if (data->als_needs_enable) {
+		pa12203001_als_enable(data, PA12203001_ALS_EN_MASK);
+		data->als_needs_enable = false;
+	}
+	if (data->px_needs_enable) {
+		pa12203001_px_enable(data, PA12203001_PX_EN_MASK);
+		data->px_needs_enable = false;
+	}
+	mutex_unlock(&data->lock);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops pa12203001_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(pa12203001_suspend, pa12203001_resume)
+	SET_RUNTIME_PM_OPS(pa12203001_suspend, pa12203001_runtime_resume, NULL)
+};
+
+static const struct acpi_device_id pa12203001_acpi_match[] = {
+	{ "TXCPA122", 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(acpi, pa12203001_acpi_match);
+
+static const struct i2c_device_id pa12203001_id[] = {
+		{"txcpa122", 0},
+		{}
+};
+
+MODULE_DEVICE_TABLE(i2c, pa12203001_id);
+
+static struct i2c_driver pa12203001_driver = {
+	.driver = {
+		.name = PA12203001_DRIVER_NAME,
+		.pm = &pa12203001_pm_ops,
+		.acpi_match_table = ACPI_PTR(pa12203001_acpi_match),
+	},
+	.probe = pa12203001_probe,
+	.remove = pa12203001_remove,
+	.id_table = pa12203001_id,
+
+};
+module_i2c_driver(pa12203001_driver);
+
+MODULE_AUTHOR("Adriana Reus <adriana.reus@intel.com>");
+MODULE_DESCRIPTION("Driver for TXC PA12203001 Proximity and Light Sensor");
+MODULE_LICENSE("GPL v2");

+ 1 - 0
drivers/iio/light/stk3310.c

@@ -676,6 +676,7 @@ static const struct i2c_device_id stk3310_i2c_id[] = {
 	{"STK3311", 0},
 	{"STK3311", 0},
 	{}
 	{}
 };
 };
+MODULE_DEVICE_TABLE(i2c, stk3310_i2c_id);
 
 
 static const struct acpi_device_id stk3310_acpi_id[] = {
 static const struct acpi_device_id stk3310_acpi_id[] = {
 	{"STK3310", 0},
 	{"STK3310", 0},

+ 12 - 12
drivers/iio/magnetometer/bmc150_magn.c

@@ -85,6 +85,7 @@
 #define BMC150_MAGN_REG_HIGH_THRESH		0x50
 #define BMC150_MAGN_REG_HIGH_THRESH		0x50
 #define BMC150_MAGN_REG_REP_XY			0x51
 #define BMC150_MAGN_REG_REP_XY			0x51
 #define BMC150_MAGN_REG_REP_Z			0x52
 #define BMC150_MAGN_REG_REP_Z			0x52
+#define BMC150_MAGN_REG_REP_DATAMASK		GENMASK(7, 0)
 
 
 #define BMC150_MAGN_REG_TRIM_START		0x5D
 #define BMC150_MAGN_REG_TRIM_START		0x5D
 #define BMC150_MAGN_REG_TRIM_END		0x71
 #define BMC150_MAGN_REG_TRIM_END		0x71
@@ -559,7 +560,7 @@ static int bmc150_magn_write_raw(struct iio_dev *indio_dev,
 			}
 			}
 			ret = regmap_update_bits(data->regmap,
 			ret = regmap_update_bits(data->regmap,
 						 BMC150_MAGN_REG_REP_XY,
 						 BMC150_MAGN_REG_REP_XY,
-						 0xFF,
+						 BMC150_MAGN_REG_REP_DATAMASK,
 						 BMC150_MAGN_REPXY_TO_REGVAL
 						 BMC150_MAGN_REPXY_TO_REGVAL
 						 (val));
 						 (val));
 			mutex_unlock(&data->mutex);
 			mutex_unlock(&data->mutex);
@@ -575,7 +576,7 @@ static int bmc150_magn_write_raw(struct iio_dev *indio_dev,
 			}
 			}
 			ret = regmap_update_bits(data->regmap,
 			ret = regmap_update_bits(data->regmap,
 						 BMC150_MAGN_REG_REP_Z,
 						 BMC150_MAGN_REG_REP_Z,
-						 0xFF,
+						 BMC150_MAGN_REG_REP_DATAMASK,
 						 BMC150_MAGN_REPZ_TO_REGVAL
 						 BMC150_MAGN_REPZ_TO_REGVAL
 						 (val));
 						 (val));
 			mutex_unlock(&data->mutex);
 			mutex_unlock(&data->mutex);
@@ -651,7 +652,9 @@ static const struct iio_info bmc150_magn_info = {
 	.driver_module = THIS_MODULE,
 	.driver_module = THIS_MODULE,
 };
 };
 
 
-static const unsigned long bmc150_magn_scan_masks[] = {0x07, 0};
+static const unsigned long bmc150_magn_scan_masks[] = {
+					BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z),
+					0};
 
 
 static irqreturn_t bmc150_magn_trigger_handler(int irq, void *p)
 static irqreturn_t bmc150_magn_trigger_handler(int irq, void *p)
 {
 {
@@ -662,7 +665,6 @@ static irqreturn_t bmc150_magn_trigger_handler(int irq, void *p)
 
 
 	mutex_lock(&data->mutex);
 	mutex_lock(&data->mutex);
 	ret = bmc150_magn_read_xyz(data, data->buffer);
 	ret = bmc150_magn_read_xyz(data, data->buffer);
-	mutex_unlock(&data->mutex);
 	if (ret < 0)
 	if (ret < 0)
 		goto err;
 		goto err;
 
 
@@ -670,6 +672,7 @@ static irqreturn_t bmc150_magn_trigger_handler(int irq, void *p)
 					   pf->timestamp);
 					   pf->timestamp);
 
 
 err:
 err:
+	mutex_unlock(&data->mutex);
 	iio_trigger_notify_done(indio_dev->trig);
 	iio_trigger_notify_done(indio_dev->trig);
 
 
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;
@@ -781,29 +784,23 @@ static int bmc150_magn_data_rdy_trigger_set_state(struct iio_trigger *trig,
 	if (state == data->dready_trigger_on)
 	if (state == data->dready_trigger_on)
 		goto err_unlock;
 		goto err_unlock;
 
 
-	ret = bmc150_magn_set_power_state(data, state);
-	if (ret < 0)
-		goto err_unlock;
-
 	ret = regmap_update_bits(data->regmap, BMC150_MAGN_REG_INT_DRDY,
 	ret = regmap_update_bits(data->regmap, BMC150_MAGN_REG_INT_DRDY,
 				 BMC150_MAGN_MASK_DRDY_EN,
 				 BMC150_MAGN_MASK_DRDY_EN,
 				 state << BMC150_MAGN_SHIFT_DRDY_EN);
 				 state << BMC150_MAGN_SHIFT_DRDY_EN);
 	if (ret < 0)
 	if (ret < 0)
-		goto err_poweroff;
+		goto err_unlock;
 
 
 	data->dready_trigger_on = state;
 	data->dready_trigger_on = state;
 
 
 	if (state) {
 	if (state) {
 		ret = bmc150_magn_reset_intr(data);
 		ret = bmc150_magn_reset_intr(data);
 		if (ret < 0)
 		if (ret < 0)
-			goto err_poweroff;
+			goto err_unlock;
 	}
 	}
 	mutex_unlock(&data->mutex);
 	mutex_unlock(&data->mutex);
 
 
 	return 0;
 	return 0;
 
 
-err_poweroff:
-	bmc150_magn_set_power_state(data, false);
 err_unlock:
 err_unlock:
 	mutex_unlock(&data->mutex);
 	mutex_unlock(&data->mutex);
 	return ret;
 	return ret;
@@ -1041,6 +1038,9 @@ static int bmc150_magn_runtime_suspend(struct device *dev)
 	return 0;
 	return 0;
 }
 }
 
 
+/*
+ * Should be called with data->mutex held.
+ */
 static int bmc150_magn_runtime_resume(struct device *dev)
 static int bmc150_magn_runtime_resume(struct device *dev)
 {
 {
 	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
 	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));

+ 20 - 13
drivers/iio/magnetometer/mmc35240.c

@@ -316,31 +316,31 @@ static int mmc35240_read_measurement(struct mmc35240_data *data, __le16 buf[3])
 static int mmc35240_raw_to_mgauss(struct mmc35240_data *data, int index,
 static int mmc35240_raw_to_mgauss(struct mmc35240_data *data, int index,
 				  __le16 buf[], int *val)
 				  __le16 buf[], int *val)
 {
 {
-	int raw_x, raw_y, raw_z;
-	int sens_x, sens_y, sens_z;
+	int raw[3];
+	int sens[3];
 	int nfo;
 	int nfo;
 
 
-	raw_x = le16_to_cpu(buf[AXIS_X]);
-	raw_y = le16_to_cpu(buf[AXIS_Y]);
-	raw_z = le16_to_cpu(buf[AXIS_Z]);
+	raw[AXIS_X] = le16_to_cpu(buf[AXIS_X]);
+	raw[AXIS_Y] = le16_to_cpu(buf[AXIS_Y]);
+	raw[AXIS_Z] = le16_to_cpu(buf[AXIS_Z]);
 
 
-	sens_x = mmc35240_props_table[data->res].sens[AXIS_X];
-	sens_y = mmc35240_props_table[data->res].sens[AXIS_Y];
-	sens_z = mmc35240_props_table[data->res].sens[AXIS_Z];
+	sens[AXIS_X] = mmc35240_props_table[data->res].sens[AXIS_X];
+	sens[AXIS_Y] = mmc35240_props_table[data->res].sens[AXIS_Y];
+	sens[AXIS_Z] = mmc35240_props_table[data->res].sens[AXIS_Z];
 
 
 	nfo = mmc35240_props_table[data->res].nfo;
 	nfo = mmc35240_props_table[data->res].nfo;
 
 
 	switch (index) {
 	switch (index) {
 	case AXIS_X:
 	case AXIS_X:
-		*val = (raw_x - nfo) * 1000 / sens_x;
+		*val = (raw[AXIS_X] - nfo) * 1000 / sens[AXIS_X];
 		break;
 		break;
 	case AXIS_Y:
 	case AXIS_Y:
-		*val = (raw_y - nfo) * 1000 / sens_y -
-			(raw_z - nfo)  * 1000 / sens_z;
+		*val = (raw[AXIS_Y] - nfo) * 1000 / sens[AXIS_Y] -
+			(raw[AXIS_Z] - nfo)  * 1000 / sens[AXIS_Z];
 		break;
 		break;
 	case AXIS_Z:
 	case AXIS_Z:
-		*val = (raw_y - nfo) * 1000 / sens_y +
-			(raw_z - nfo) * 1000 / sens_z;
+		*val = (raw[AXIS_Y] - nfo) * 1000 / sens[AXIS_Y] +
+			(raw[AXIS_Z] - nfo) * 1000 / sens[AXIS_Z];
 		break;
 		break;
 	default:
 	default:
 		return -EINVAL;
 		return -EINVAL;
@@ -559,6 +559,12 @@ static const struct dev_pm_ops mmc35240_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(mmc35240_suspend, mmc35240_resume)
 	SET_SYSTEM_SLEEP_PM_OPS(mmc35240_suspend, mmc35240_resume)
 };
 };
 
 
+static const struct of_device_id mmc35240_of_match[] = {
+	{ .compatible = "memsic,mmc35240", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, mmc35240_of_match);
+
 static const struct acpi_device_id mmc35240_acpi_match[] = {
 static const struct acpi_device_id mmc35240_acpi_match[] = {
 	{"MMC35240", 0},
 	{"MMC35240", 0},
 	{ },
 	{ },
@@ -574,6 +580,7 @@ MODULE_DEVICE_TABLE(i2c, mmc35240_id);
 static struct i2c_driver mmc35240_driver = {
 static struct i2c_driver mmc35240_driver = {
 	.driver = {
 	.driver = {
 		.name = MMC35240_DRV_NAME,
 		.name = MMC35240_DRV_NAME,
+		.of_match_table = mmc35240_of_match,
 		.pm = &mmc35240_pm_ops,
 		.pm = &mmc35240_pm_ops,
 		.acpi_match_table = ACPI_PTR(mmc35240_acpi_match),
 		.acpi_match_table = ACPI_PTR(mmc35240_acpi_match),
 	},
 	},

+ 3 - 0
drivers/iio/magnetometer/st_magn.h

@@ -18,6 +18,7 @@
 #define LSM303DLHC_MAGN_DEV_NAME	"lsm303dlhc_magn"
 #define LSM303DLHC_MAGN_DEV_NAME	"lsm303dlhc_magn"
 #define LSM303DLM_MAGN_DEV_NAME		"lsm303dlm_magn"
 #define LSM303DLM_MAGN_DEV_NAME		"lsm303dlm_magn"
 #define LIS3MDL_MAGN_DEV_NAME		"lis3mdl"
 #define LIS3MDL_MAGN_DEV_NAME		"lis3mdl"
+#define LSM303AGR_MAGN_DEV_NAME		"lsm303agr_magn"
 
 
 int st_magn_common_probe(struct iio_dev *indio_dev);
 int st_magn_common_probe(struct iio_dev *indio_dev);
 void st_magn_common_remove(struct iio_dev *indio_dev);
 void st_magn_common_remove(struct iio_dev *indio_dev);
@@ -25,6 +26,8 @@ void st_magn_common_remove(struct iio_dev *indio_dev);
 #ifdef CONFIG_IIO_BUFFER
 #ifdef CONFIG_IIO_BUFFER
 int st_magn_allocate_ring(struct iio_dev *indio_dev);
 int st_magn_allocate_ring(struct iio_dev *indio_dev);
 void st_magn_deallocate_ring(struct iio_dev *indio_dev);
 void st_magn_deallocate_ring(struct iio_dev *indio_dev);
+int st_magn_trig_set_state(struct iio_trigger *trig, bool state);
+#define ST_MAGN_TRIGGER_SET_STATE (&st_magn_trig_set_state)
 #else /* CONFIG_IIO_BUFFER */
 #else /* CONFIG_IIO_BUFFER */
 static inline int st_magn_probe_trigger(struct iio_dev *indio_dev, int irq)
 static inline int st_magn_probe_trigger(struct iio_dev *indio_dev, int irq)
 {
 {

+ 7 - 0
drivers/iio/magnetometer/st_magn_buffer.c

@@ -23,6 +23,13 @@
 #include <linux/iio/common/st_sensors.h>
 #include <linux/iio/common/st_sensors.h>
 #include "st_magn.h"
 #include "st_magn.h"
 
 
+int st_magn_trig_set_state(struct iio_trigger *trig, bool state)
+{
+	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+
+	return st_sensors_set_dataready_irq(indio_dev, state);
+}
+
 static int st_magn_buffer_preenable(struct iio_dev *indio_dev)
 static int st_magn_buffer_preenable(struct iio_dev *indio_dev)
 {
 {
 	return st_sensors_set_enable(indio_dev, true);
 	return st_sensors_set_enable(indio_dev, true);

+ 97 - 1
drivers/iio/magnetometer/st_magn_core.c

@@ -43,6 +43,7 @@
 #define ST_MAGN_FS_AVL_8000MG			8000
 #define ST_MAGN_FS_AVL_8000MG			8000
 #define ST_MAGN_FS_AVL_8100MG			8100
 #define ST_MAGN_FS_AVL_8100MG			8100
 #define ST_MAGN_FS_AVL_12000MG			12000
 #define ST_MAGN_FS_AVL_12000MG			12000
+#define ST_MAGN_FS_AVL_15000MG			15000
 #define ST_MAGN_FS_AVL_16000MG			16000
 #define ST_MAGN_FS_AVL_16000MG			16000
 
 
 /* CUSTOM VALUES FOR SENSOR 0 */
 /* CUSTOM VALUES FOR SENSOR 0 */
@@ -157,6 +158,29 @@
 #define ST_MAGN_2_OUT_Y_L_ADDR			0x2a
 #define ST_MAGN_2_OUT_Y_L_ADDR			0x2a
 #define ST_MAGN_2_OUT_Z_L_ADDR			0x2c
 #define ST_MAGN_2_OUT_Z_L_ADDR			0x2c
 
 
+/* CUSTOM VALUES FOR SENSOR 3 */
+#define ST_MAGN_3_WAI_ADDR			0x4f
+#define ST_MAGN_3_WAI_EXP			0x40
+#define ST_MAGN_3_ODR_ADDR			0x60
+#define ST_MAGN_3_ODR_MASK			0x0c
+#define ST_MAGN_3_ODR_AVL_10HZ_VAL		0x00
+#define ST_MAGN_3_ODR_AVL_20HZ_VAL		0x01
+#define ST_MAGN_3_ODR_AVL_50HZ_VAL		0x02
+#define ST_MAGN_3_ODR_AVL_100HZ_VAL		0x03
+#define ST_MAGN_3_PW_ADDR			0x60
+#define ST_MAGN_3_PW_MASK			0x03
+#define ST_MAGN_3_PW_ON				0x00
+#define ST_MAGN_3_PW_OFF			0x03
+#define ST_MAGN_3_BDU_ADDR			0x62
+#define ST_MAGN_3_BDU_MASK			0x10
+#define ST_MAGN_3_DRDY_IRQ_ADDR			0x62
+#define ST_MAGN_3_DRDY_INT_MASK			0x01
+#define ST_MAGN_3_FS_AVL_15000_GAIN		1500
+#define ST_MAGN_3_MULTIREAD_BIT			false
+#define ST_MAGN_3_OUT_X_L_ADDR			0x68
+#define ST_MAGN_3_OUT_Y_L_ADDR			0x6a
+#define ST_MAGN_3_OUT_Z_L_ADDR			0x6c
+
 static const struct iio_chan_spec st_magn_16bit_channels[] = {
 static const struct iio_chan_spec st_magn_16bit_channels[] = {
 	ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
 	ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
 			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
 			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
@@ -189,9 +213,26 @@ static const struct iio_chan_spec st_magn_2_16bit_channels[] = {
 	IIO_CHAN_SOFT_TIMESTAMP(3)
 	IIO_CHAN_SOFT_TIMESTAMP(3)
 };
 };
 
 
+static const struct iio_chan_spec st_magn_3_16bit_channels[] = {
+	ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
+			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
+			ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16,
+			ST_MAGN_3_OUT_X_L_ADDR),
+	ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
+			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
+			ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16,
+			ST_MAGN_3_OUT_Y_L_ADDR),
+	ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
+			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
+			ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16,
+			ST_MAGN_3_OUT_Z_L_ADDR),
+	IIO_CHAN_SOFT_TIMESTAMP(3)
+};
+
 static const struct st_sensor_settings st_magn_sensors_settings[] = {
 static const struct st_sensor_settings st_magn_sensors_settings[] = {
 	{
 	{
 		.wai = 0, /* This sensor has no valid WhoAmI report 0 */
 		.wai = 0, /* This sensor has no valid WhoAmI report 0 */
+		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 		.sensors_supported = {
 		.sensors_supported = {
 			[0] = LSM303DLH_MAGN_DEV_NAME,
 			[0] = LSM303DLH_MAGN_DEV_NAME,
 		},
 		},
@@ -268,6 +309,7 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = {
 	},
 	},
 	{
 	{
 		.wai = ST_MAGN_1_WAI_EXP,
 		.wai = ST_MAGN_1_WAI_EXP,
+		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 		.sensors_supported = {
 		.sensors_supported = {
 			[0] = LSM303DLHC_MAGN_DEV_NAME,
 			[0] = LSM303DLHC_MAGN_DEV_NAME,
 			[1] = LSM303DLM_MAGN_DEV_NAME,
 			[1] = LSM303DLM_MAGN_DEV_NAME,
@@ -346,6 +388,7 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = {
 	},
 	},
 	{
 	{
 		.wai = ST_MAGN_2_WAI_EXP,
 		.wai = ST_MAGN_2_WAI_EXP,
+		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 		.sensors_supported = {
 		.sensors_supported = {
 			[0] = LIS3MDL_MAGN_DEV_NAME,
 			[0] = LIS3MDL_MAGN_DEV_NAME,
 		},
 		},
@@ -399,6 +442,48 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = {
 		.multi_read_bit = ST_MAGN_2_MULTIREAD_BIT,
 		.multi_read_bit = ST_MAGN_2_MULTIREAD_BIT,
 		.bootime = 2,
 		.bootime = 2,
 	},
 	},
+	{
+		.wai = ST_MAGN_3_WAI_EXP,
+		.wai_addr = ST_MAGN_3_WAI_ADDR,
+		.sensors_supported = {
+			[0] = LSM303AGR_MAGN_DEV_NAME,
+		},
+		.ch = (struct iio_chan_spec *)st_magn_3_16bit_channels,
+		.odr = {
+			.addr = ST_MAGN_3_ODR_ADDR,
+			.mask = ST_MAGN_3_ODR_MASK,
+			.odr_avl = {
+				{ 10, ST_MAGN_3_ODR_AVL_10HZ_VAL, },
+				{ 20, ST_MAGN_3_ODR_AVL_20HZ_VAL, },
+				{ 50, ST_MAGN_3_ODR_AVL_50HZ_VAL, },
+				{ 100, ST_MAGN_3_ODR_AVL_100HZ_VAL, },
+			},
+		},
+		.pw = {
+			.addr = ST_MAGN_3_PW_ADDR,
+			.mask = ST_MAGN_3_PW_MASK,
+			.value_on = ST_MAGN_3_PW_ON,
+			.value_off = ST_MAGN_3_PW_OFF,
+		},
+		.fs = {
+			.fs_avl = {
+				[0] = {
+					.num = ST_MAGN_FS_AVL_15000MG,
+					.gain = ST_MAGN_3_FS_AVL_15000_GAIN,
+				},
+			},
+		},
+		.bdu = {
+			.addr = ST_MAGN_3_BDU_ADDR,
+			.mask = ST_MAGN_3_BDU_MASK,
+		},
+		.drdy_irq = {
+			.addr = ST_MAGN_3_DRDY_IRQ_ADDR,
+			.mask_int1 = ST_MAGN_3_DRDY_INT_MASK,
+		},
+		.multi_read_bit = ST_MAGN_3_MULTIREAD_BIT,
+		.bootime = 2,
+	},
 };
 };
 
 
 static int st_magn_read_raw(struct iio_dev *indio_dev,
 static int st_magn_read_raw(struct iio_dev *indio_dev,
@@ -477,6 +562,16 @@ static const struct iio_info magn_info = {
 	.write_raw = &st_magn_write_raw,
 	.write_raw = &st_magn_write_raw,
 };
 };
 
 
+#ifdef CONFIG_IIO_TRIGGER
+static const struct iio_trigger_ops st_magn_trigger_ops = {
+	.owner = THIS_MODULE,
+	.set_trigger_state = ST_MAGN_TRIGGER_SET_STATE,
+};
+#define ST_MAGN_TRIGGER_OPS (&st_magn_trigger_ops)
+#else
+#define ST_MAGN_TRIGGER_OPS NULL
+#endif
+
 int st_magn_common_probe(struct iio_dev *indio_dev)
 int st_magn_common_probe(struct iio_dev *indio_dev)
 {
 {
 	struct st_sensor_data *mdata = iio_priv(indio_dev);
 	struct st_sensor_data *mdata = iio_priv(indio_dev);
@@ -513,7 +608,8 @@ int st_magn_common_probe(struct iio_dev *indio_dev)
 		return err;
 		return err;
 
 
 	if (irq > 0) {
 	if (irq > 0) {
-		err = st_sensors_allocate_trigger(indio_dev, NULL);
+		err = st_sensors_allocate_trigger(indio_dev,
+						ST_MAGN_TRIGGER_OPS);
 		if (err < 0)
 		if (err < 0)
 			goto st_magn_probe_trigger_error;
 			goto st_magn_probe_trigger_error;
 	}
 	}

+ 5 - 0
drivers/iio/magnetometer/st_magn_i2c.c

@@ -36,6 +36,10 @@ static const struct of_device_id st_magn_of_match[] = {
 		.compatible = "st,lis3mdl-magn",
 		.compatible = "st,lis3mdl-magn",
 		.data = LIS3MDL_MAGN_DEV_NAME,
 		.data = LIS3MDL_MAGN_DEV_NAME,
 	},
 	},
+	{
+		.compatible = "st,lsm303agr-magn",
+		.data = LSM303AGR_MAGN_DEV_NAME,
+	},
 	{},
 	{},
 };
 };
 MODULE_DEVICE_TABLE(of, st_magn_of_match);
 MODULE_DEVICE_TABLE(of, st_magn_of_match);
@@ -79,6 +83,7 @@ static const struct i2c_device_id st_magn_id_table[] = {
 	{ LSM303DLHC_MAGN_DEV_NAME },
 	{ LSM303DLHC_MAGN_DEV_NAME },
 	{ LSM303DLM_MAGN_DEV_NAME },
 	{ LSM303DLM_MAGN_DEV_NAME },
 	{ LIS3MDL_MAGN_DEV_NAME },
 	{ LIS3MDL_MAGN_DEV_NAME },
+	{ LSM303AGR_MAGN_DEV_NAME },
 	{},
 	{},
 };
 };
 MODULE_DEVICE_TABLE(i2c, st_magn_id_table);
 MODULE_DEVICE_TABLE(i2c, st_magn_id_table);

+ 1 - 0
drivers/iio/magnetometer/st_magn_spi.c

@@ -51,6 +51,7 @@ static const struct spi_device_id st_magn_id_table[] = {
 	{ LSM303DLHC_MAGN_DEV_NAME },
 	{ LSM303DLHC_MAGN_DEV_NAME },
 	{ LSM303DLM_MAGN_DEV_NAME },
 	{ LSM303DLM_MAGN_DEV_NAME },
 	{ LIS3MDL_MAGN_DEV_NAME },
 	{ LIS3MDL_MAGN_DEV_NAME },
+	{ LSM303AGR_MAGN_DEV_NAME },
 	{},
 	{},
 };
 };
 MODULE_DEVICE_TABLE(spi, st_magn_id_table);
 MODULE_DEVICE_TABLE(spi, st_magn_id_table);

+ 3 - 0
drivers/iio/pressure/st_pressure_core.c

@@ -178,6 +178,7 @@ static const struct iio_chan_spec st_press_lps001wp_channels[] = {
 static const struct st_sensor_settings st_press_sensors_settings[] = {
 static const struct st_sensor_settings st_press_sensors_settings[] = {
 	{
 	{
 		.wai = ST_PRESS_LPS331AP_WAI_EXP,
 		.wai = ST_PRESS_LPS331AP_WAI_EXP,
+		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 		.sensors_supported = {
 		.sensors_supported = {
 			[0] = LPS331AP_PRESS_DEV_NAME,
 			[0] = LPS331AP_PRESS_DEV_NAME,
 		},
 		},
@@ -225,6 +226,7 @@ static const struct st_sensor_settings st_press_sensors_settings[] = {
 	},
 	},
 	{
 	{
 		.wai = ST_PRESS_LPS001WP_WAI_EXP,
 		.wai = ST_PRESS_LPS001WP_WAI_EXP,
+		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 		.sensors_supported = {
 		.sensors_supported = {
 			[0] = LPS001WP_PRESS_DEV_NAME,
 			[0] = LPS001WP_PRESS_DEV_NAME,
 		},
 		},
@@ -260,6 +262,7 @@ static const struct st_sensor_settings st_press_sensors_settings[] = {
 	},
 	},
 	{
 	{
 		.wai = ST_PRESS_LPS25H_WAI_EXP,
 		.wai = ST_PRESS_LPS25H_WAI_EXP,
+		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 		.sensors_supported = {
 		.sensors_supported = {
 			[0] = LPS25H_PRESS_DEV_NAME,
 			[0] = LPS25H_PRESS_DEV_NAME,
 		},
 		},

+ 14 - 6
drivers/iio/temperature/mlx90614.c

@@ -65,6 +65,13 @@
 
 
 #define MLX90614_AUTOSLEEP_DELAY 5000 /* default autosleep delay */
 #define MLX90614_AUTOSLEEP_DELAY 5000 /* default autosleep delay */
 
 
+/* Magic constants */
+#define MLX90614_CONST_OFFSET_DEC -13657 /* decimal part of the Kelvin offset */
+#define MLX90614_CONST_OFFSET_REM 500000 /* remainder of offset (273.15*50) */
+#define MLX90614_CONST_SCALE 20 /* Scale in milliKelvin (0.02 * 1000) */
+#define MLX90614_CONST_RAW_EMISSIVITY_MAX 65535 /* max value for emissivity */
+#define MLX90614_CONST_EMISSIVITY_RESOLUTION 15259 /* 1/65535 ~ 0.000015259 */
+
 struct mlx90614_data {
 struct mlx90614_data {
 	struct i2c_client *client;
 	struct i2c_client *client;
 	struct mutex lock; /* for EEPROM access only */
 	struct mutex lock; /* for EEPROM access only */
@@ -204,11 +211,11 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev,
 		*val = ret;
 		*val = ret;
 		return IIO_VAL_INT;
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_OFFSET:
 	case IIO_CHAN_INFO_OFFSET:
-		*val = -13657;
-		*val2 = 500000;
+		*val = MLX90614_CONST_OFFSET_DEC;
+		*val2 = MLX90614_CONST_OFFSET_REM;
 		return IIO_VAL_INT_PLUS_MICRO;
 		return IIO_VAL_INT_PLUS_MICRO;
 	case IIO_CHAN_INFO_SCALE:
 	case IIO_CHAN_INFO_SCALE:
-		*val = 20;
+		*val = MLX90614_CONST_SCALE;
 		return IIO_VAL_INT;
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_CALIBEMISSIVITY: /* 1/65535 / LSB */
 	case IIO_CHAN_INFO_CALIBEMISSIVITY: /* 1/65535 / LSB */
 		mlx90614_power_get(data, false);
 		mlx90614_power_get(data, false);
@@ -221,12 +228,12 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev,
 		if (ret < 0)
 		if (ret < 0)
 			return ret;
 			return ret;
 
 
-		if (ret == 65535) {
+		if (ret == MLX90614_CONST_RAW_EMISSIVITY_MAX) {
 			*val = 1;
 			*val = 1;
 			*val2 = 0;
 			*val2 = 0;
 		} else {
 		} else {
 			*val = 0;
 			*val = 0;
-			*val2 = ret * 15259; /* 1/65535 ~ 0.000015259 */
+			*val2 = ret * MLX90614_CONST_EMISSIVITY_RESOLUTION;
 		}
 		}
 		return IIO_VAL_INT_PLUS_NANO;
 		return IIO_VAL_INT_PLUS_NANO;
 	default:
 	default:
@@ -245,7 +252,8 @@ static int mlx90614_write_raw(struct iio_dev *indio_dev,
 	case IIO_CHAN_INFO_CALIBEMISSIVITY: /* 1/65535 / LSB */
 	case IIO_CHAN_INFO_CALIBEMISSIVITY: /* 1/65535 / LSB */
 		if (val < 0 || val2 < 0 || val > 1 || (val == 1 && val2 != 0))
 		if (val < 0 || val2 < 0 || val > 1 || (val == 1 && val2 != 0))
 			return -EINVAL;
 			return -EINVAL;
-		val = val * 65535 + val2 / 15259; /* 1/65535 ~ 0.000015259 */
+		val = val * MLX90614_CONST_RAW_EMISSIVITY_MAX +
+			val2 / MLX90614_CONST_EMISSIVITY_RESOLUTION;
 
 
 		mlx90614_power_get(data, false);
 		mlx90614_power_get(data, false);
 		mutex_lock(&data->lock);
 		mutex_lock(&data->lock);

+ 81 - 41
drivers/staging/iio/adc/mxs-lradc.c

@@ -1,5 +1,5 @@
 /*
 /*
- * Freescale i.MX28 LRADC driver
+ * Freescale MXS LRADC driver
  *
  *
  * Copyright (c) 2012 DENX Software Engineering, GmbH.
  * Copyright (c) 2012 DENX Software Engineering, GmbH.
  * Marek Vasut <marex@denx.de>
  * Marek Vasut <marex@denx.de>
@@ -15,34 +15,30 @@
  * GNU General Public License for more details.
  * GNU General Public License for more details.
  */
  */
 
 
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/device.h>
 #include <linux/err.h>
 #include <linux/err.h>
+#include <linux/input.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
-#include <linux/device.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/kernel.h>
-#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
 #include <linux/of.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_device.h>
-#include <linux/sysfs.h>
-#include <linux/list.h>
-#include <linux/io.h>
-#include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
-#include <linux/spinlock.h>
-#include <linux/wait.h>
-#include <linux/sched.h>
+#include <linux/slab.h>
 #include <linux/stmp_device.h>
 #include <linux/stmp_device.h>
-#include <linux/bitops.h>
-#include <linux/completion.h>
-#include <linux/delay.h>
-#include <linux/input.h>
-#include <linux/clk.h>
+#include <linux/sysfs.h>
 
 
-#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
 #include <linux/iio/buffer.h>
 #include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
 #include <linux/iio/trigger.h>
 #include <linux/iio/trigger.h>
 #include <linux/iio/trigger_consumer.h>
 #include <linux/iio/trigger_consumer.h>
 #include <linux/iio/triggered_buffer.h>
 #include <linux/iio/triggered_buffer.h>
+#include <linux/iio/sysfs.h>
 
 
 #define DRIVER_NAME		"mxs-lradc"
 #define DRIVER_NAME		"mxs-lradc"
 
 
@@ -65,14 +61,14 @@
  * Once the pen touches the touchscreen, the touchscreen switches from
  * Once the pen touches the touchscreen, the touchscreen switches from
  * IRQ-driven mode to polling mode to prevent interrupt storm. The polling
  * IRQ-driven mode to polling mode to prevent interrupt storm. The polling
  * is realized by worker thread, which is called every 20 or so milliseconds.
  * is realized by worker thread, which is called every 20 or so milliseconds.
- * This gives the touchscreen enough fluence and does not strain the system
+ * This gives the touchscreen enough fluency and does not strain the system
  * too much.
  * too much.
  */
  */
 #define LRADC_TS_SAMPLE_DELAY_MS	5
 #define LRADC_TS_SAMPLE_DELAY_MS	5
 
 
 /*
 /*
  * The LRADC reads the following amount of samples from each touchscreen
  * The LRADC reads the following amount of samples from each touchscreen
- * channel and the driver then computes avarage of these.
+ * channel and the driver then computes average of these.
  */
  */
 #define LRADC_TS_SAMPLE_AMOUNT		4
 #define LRADC_TS_SAMPLE_AMOUNT		4
 
 
@@ -238,7 +234,7 @@ struct mxs_lradc {
 	 * CH5 -- Touch screen YNLR
 	 * CH5 -- Touch screen YNLR
 	 * CH6 -- Touch screen WIPER (5-wire only)
 	 * CH6 -- Touch screen WIPER (5-wire only)
 	 *
 	 *
-	 * The bitfields below represents which parts of the LRADC block are
+	 * The bit fields below represents which parts of the LRADC block are
 	 * switched into special mode of operation. These channels can not
 	 * switched into special mode of operation. These channels can not
 	 * be sampled as regular LRADC channels. The driver will refuse any
 	 * be sampled as regular LRADC channels. The driver will refuse any
 	 * attempt to sample these channels.
 	 * attempt to sample these channels.
@@ -252,7 +248,7 @@ struct mxs_lradc {
 	struct input_dev	*ts_input;
 	struct input_dev	*ts_input;
 
 
 	enum mxs_lradc_id	soc;
 	enum mxs_lradc_id	soc;
-	enum lradc_ts_plate	cur_plate; /* statemachine */
+	enum lradc_ts_plate	cur_plate; /* state machine */
 	bool			ts_valid;
 	bool			ts_valid;
 	unsigned		ts_x_pos;
 	unsigned		ts_x_pos;
 	unsigned		ts_y_pos;
 	unsigned		ts_y_pos;
@@ -812,7 +808,7 @@ static int mxs_lradc_read_single(struct iio_dev *iio_dev, int chan, int *val)
 	int ret;
 	int ret;
 
 
 	/*
 	/*
-	 * See if there is no buffered operation in progess. If there is, simply
+	 * See if there is no buffered operation in progress. If there is, simply
 	 * bail out. This can be improved to support both buffered and raw IO at
 	 * bail out. This can be improved to support both buffered and raw IO at
 	 * the same time, yet the code becomes horribly complicated. Therefore I
 	 * the same time, yet the code becomes horribly complicated. Therefore I
 	 * applied KISS principle here.
 	 * applied KISS principle here.
@@ -1369,7 +1365,7 @@ static const struct iio_buffer_setup_ops mxs_lradc_buffer_ops = {
  * Driver initialization
  * Driver initialization
  */
  */
 
 
-#define MXS_ADC_CHAN(idx, chan_type) {				\
+#define MXS_ADC_CHAN(idx, chan_type, name) {			\
 	.type = (chan_type),					\
 	.type = (chan_type),					\
 	.indexed = 1,						\
 	.indexed = 1,						\
 	.scan_index = (idx),					\
 	.scan_index = (idx),					\
@@ -1382,17 +1378,18 @@ static const struct iio_buffer_setup_ops mxs_lradc_buffer_ops = {
 		.realbits = LRADC_RESOLUTION,			\
 		.realbits = LRADC_RESOLUTION,			\
 		.storagebits = 32,				\
 		.storagebits = 32,				\
 	},							\
 	},							\
+	.datasheet_name = (name),				\
 }
 }
 
 
-static const struct iio_chan_spec mxs_lradc_chan_spec[] = {
-	MXS_ADC_CHAN(0, IIO_VOLTAGE),
-	MXS_ADC_CHAN(1, IIO_VOLTAGE),
-	MXS_ADC_CHAN(2, IIO_VOLTAGE),
-	MXS_ADC_CHAN(3, IIO_VOLTAGE),
-	MXS_ADC_CHAN(4, IIO_VOLTAGE),
-	MXS_ADC_CHAN(5, IIO_VOLTAGE),
-	MXS_ADC_CHAN(6, IIO_VOLTAGE),
-	MXS_ADC_CHAN(7, IIO_VOLTAGE),	/* VBATT */
+static const struct iio_chan_spec mx23_lradc_chan_spec[] = {
+	MXS_ADC_CHAN(0, IIO_VOLTAGE, "LRADC0"),
+	MXS_ADC_CHAN(1, IIO_VOLTAGE, "LRADC1"),
+	MXS_ADC_CHAN(2, IIO_VOLTAGE, "LRADC2"),
+	MXS_ADC_CHAN(3, IIO_VOLTAGE, "LRADC3"),
+	MXS_ADC_CHAN(4, IIO_VOLTAGE, "LRADC4"),
+	MXS_ADC_CHAN(5, IIO_VOLTAGE, "LRADC5"),
+	MXS_ADC_CHAN(6, IIO_VOLTAGE, "VDDIO"),
+	MXS_ADC_CHAN(7, IIO_VOLTAGE, "VBATT"),
 	/* Combined Temperature sensors */
 	/* Combined Temperature sensors */
 	{
 	{
 		.type = IIO_TEMP,
 		.type = IIO_TEMP,
@@ -1403,6 +1400,7 @@ static const struct iio_chan_spec mxs_lradc_chan_spec[] = {
 				      BIT(IIO_CHAN_INFO_SCALE),
 				      BIT(IIO_CHAN_INFO_SCALE),
 		.channel = 8,
 		.channel = 8,
 		.scan_type = {.sign = 'u', .realbits = 18, .storagebits = 32,},
 		.scan_type = {.sign = 'u', .realbits = 18, .storagebits = 32,},
+		.datasheet_name = "TEMP_DIE",
 	},
 	},
 	/* Hidden channel to keep indexes */
 	/* Hidden channel to keep indexes */
 	{
 	{
@@ -1411,12 +1409,48 @@ static const struct iio_chan_spec mxs_lradc_chan_spec[] = {
 		.scan_index = -1,
 		.scan_index = -1,
 		.channel = 9,
 		.channel = 9,
 	},
 	},
-	MXS_ADC_CHAN(10, IIO_VOLTAGE),	/* VDDIO */
-	MXS_ADC_CHAN(11, IIO_VOLTAGE),	/* VTH */
-	MXS_ADC_CHAN(12, IIO_VOLTAGE),	/* VDDA */
-	MXS_ADC_CHAN(13, IIO_VOLTAGE),	/* VDDD */
-	MXS_ADC_CHAN(14, IIO_VOLTAGE),	/* VBG */
-	MXS_ADC_CHAN(15, IIO_VOLTAGE),	/* VDD5V */
+	MXS_ADC_CHAN(10, IIO_VOLTAGE, NULL),
+	MXS_ADC_CHAN(11, IIO_VOLTAGE, NULL),
+	MXS_ADC_CHAN(12, IIO_VOLTAGE, "USB_DP"),
+	MXS_ADC_CHAN(13, IIO_VOLTAGE, "USB_DN"),
+	MXS_ADC_CHAN(14, IIO_VOLTAGE, "VBG"),
+	MXS_ADC_CHAN(15, IIO_VOLTAGE, "VDD5V"),
+};
+
+static const struct iio_chan_spec mx28_lradc_chan_spec[] = {
+	MXS_ADC_CHAN(0, IIO_VOLTAGE, "LRADC0"),
+	MXS_ADC_CHAN(1, IIO_VOLTAGE, "LRADC1"),
+	MXS_ADC_CHAN(2, IIO_VOLTAGE, "LRADC2"),
+	MXS_ADC_CHAN(3, IIO_VOLTAGE, "LRADC3"),
+	MXS_ADC_CHAN(4, IIO_VOLTAGE, "LRADC4"),
+	MXS_ADC_CHAN(5, IIO_VOLTAGE, "LRADC5"),
+	MXS_ADC_CHAN(6, IIO_VOLTAGE, "LRADC6"),
+	MXS_ADC_CHAN(7, IIO_VOLTAGE, "VBATT"),
+	/* Combined Temperature sensors */
+	{
+		.type = IIO_TEMP,
+		.indexed = 1,
+		.scan_index = 8,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				      BIT(IIO_CHAN_INFO_OFFSET) |
+				      BIT(IIO_CHAN_INFO_SCALE),
+		.channel = 8,
+		.scan_type = {.sign = 'u', .realbits = 18, .storagebits = 32,},
+		.datasheet_name = "TEMP_DIE",
+	},
+	/* Hidden channel to keep indexes */
+	{
+		.type = IIO_TEMP,
+		.indexed = 1,
+		.scan_index = -1,
+		.channel = 9,
+	},
+	MXS_ADC_CHAN(10, IIO_VOLTAGE, "VDDIO"),
+	MXS_ADC_CHAN(11, IIO_VOLTAGE, "VTH"),
+	MXS_ADC_CHAN(12, IIO_VOLTAGE, "VDDA"),
+	MXS_ADC_CHAN(13, IIO_VOLTAGE, "VDDD"),
+	MXS_ADC_CHAN(14, IIO_VOLTAGE, "VBG"),
+	MXS_ADC_CHAN(15, IIO_VOLTAGE, "VDD5V"),
 };
 };
 
 
 static int mxs_lradc_hw_init(struct mxs_lradc *lradc)
 static int mxs_lradc_hw_init(struct mxs_lradc *lradc)
@@ -1612,10 +1646,16 @@ static int mxs_lradc_probe(struct platform_device *pdev)
 	iio->dev.parent = &pdev->dev;
 	iio->dev.parent = &pdev->dev;
 	iio->info = &mxs_lradc_iio_info;
 	iio->info = &mxs_lradc_iio_info;
 	iio->modes = INDIO_DIRECT_MODE;
 	iio->modes = INDIO_DIRECT_MODE;
-	iio->channels = mxs_lradc_chan_spec;
-	iio->num_channels = ARRAY_SIZE(mxs_lradc_chan_spec);
 	iio->masklength = LRADC_MAX_TOTAL_CHANS;
 	iio->masklength = LRADC_MAX_TOTAL_CHANS;
 
 
+	if (lradc->soc == IMX23_LRADC) {
+		iio->channels = mx23_lradc_chan_spec;
+		iio->num_channels = ARRAY_SIZE(mx23_lradc_chan_spec);
+	} else {
+		iio->channels = mx28_lradc_chan_spec;
+		iio->num_channels = ARRAY_SIZE(mx28_lradc_chan_spec);
+	}
+
 	ret = iio_triggered_buffer_setup(iio, &iio_pollfunc_store_time,
 	ret = iio_triggered_buffer_setup(iio, &iio_pollfunc_store_time,
 				&mxs_lradc_trigger_handler,
 				&mxs_lradc_trigger_handler,
 				&mxs_lradc_buffer_ops);
 				&mxs_lradc_buffer_ops);
@@ -1707,6 +1747,6 @@ static struct platform_driver mxs_lradc_driver = {
 module_platform_driver(mxs_lradc_driver);
 module_platform_driver(mxs_lradc_driver);
 
 
 MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
 MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
-MODULE_DESCRIPTION("Freescale i.MX28 LRADC driver");
+MODULE_DESCRIPTION("Freescale MXS LRADC driver");
 MODULE_LICENSE("GPL v2");
 MODULE_LICENSE("GPL v2");
 MODULE_ALIAS("platform:" DRIVER_NAME);
 MODULE_ALIAS("platform:" DRIVER_NAME);

+ 2 - 0
include/linux/iio/common/st_sensors.h

@@ -166,6 +166,7 @@ struct st_sensor_transfer_function {
 /**
 /**
  * struct st_sensor_settings - ST specific sensor settings
  * struct st_sensor_settings - ST specific sensor settings
  * @wai: Contents of WhoAmI register.
  * @wai: Contents of WhoAmI register.
+ * @wai_addr: The address of WhoAmI register.
  * @sensors_supported: List of supported sensors by struct itself.
  * @sensors_supported: List of supported sensors by struct itself.
  * @ch: IIO channels for the sensor.
  * @ch: IIO channels for the sensor.
  * @odr: Output data rate register and ODR list available.
  * @odr: Output data rate register and ODR list available.
@@ -179,6 +180,7 @@ struct st_sensor_transfer_function {
  */
  */
 struct st_sensor_settings {
 struct st_sensor_settings {
 	u8 wai;
 	u8 wai;
+	u8 wai_addr;
 	char sensors_supported[ST_SENSORS_MAX_4WAI][ST_SENSORS_MAX_NAME];
 	char sensors_supported[ST_SENSORS_MAX_4WAI][ST_SENSORS_MAX_NAME];
 	struct iio_chan_spec *ch;
 	struct iio_chan_spec *ch;
 	int num_ch;
 	int num_ch;

+ 1 - 1
include/linux/iio/consumer.h

@@ -100,7 +100,7 @@ void iio_channel_stop_all_cb(struct iio_cb_buffer *cb_buff);
 
 
 /**
 /**
  * iio_channel_cb_get_channels() - get access to the underlying channels.
  * iio_channel_cb_get_channels() - get access to the underlying channels.
- * @cb_buff:		The callback buffer from whom we want the channel
+ * @cb_buffer:		The callback buffer from whom we want the channel
  *			information.
  *			information.
  *
  *
  * This function allows one to obtain information about the channels.
  * This function allows one to obtain information about the channels.

+ 17 - 0
include/linux/iio/iio.h

@@ -644,6 +644,15 @@ int iio_str_to_fixpoint(const char *str, int fract_mult, int *integer,
  */
  */
 #define IIO_DEGREE_TO_RAD(deg) (((deg) * 314159ULL + 9000000ULL) / 18000000ULL)
 #define IIO_DEGREE_TO_RAD(deg) (((deg) * 314159ULL + 9000000ULL) / 18000000ULL)
 
 
+/**
+ * IIO_RAD_TO_DEGREE() - Convert rad to degree
+ * @rad: A value in rad
+ *
+ * Returns the given value converted from rad to degree
+ */
+#define IIO_RAD_TO_DEGREE(rad) \
+	(((rad) * 18000000ULL + 314159ULL / 2) / 314159ULL)
+
 /**
 /**
  * IIO_G_TO_M_S_2() - Convert g to meter / second**2
  * IIO_G_TO_M_S_2() - Convert g to meter / second**2
  * @g: A value in g
  * @g: A value in g
@@ -652,4 +661,12 @@ int iio_str_to_fixpoint(const char *str, int fract_mult, int *integer,
  */
  */
 #define IIO_G_TO_M_S_2(g) ((g) * 980665ULL / 100000ULL)
 #define IIO_G_TO_M_S_2(g) ((g) * 980665ULL / 100000ULL)
 
 
+/**
+ * IIO_M_S_2_TO_G() - Convert meter / second**2 to g
+ * @ms2: A value in meter / second**2
+ *
+ * Returns the given value converted from meter / second**2 to g
+ */
+#define IIO_M_S_2_TO_G(ms2) (((ms2) * 100000ULL + 980665ULL / 2) / 980665ULL)
+
 #endif /* _INDUSTRIAL_IO_H_ */
 #endif /* _INDUSTRIAL_IO_H_ */

+ 2 - 1
include/linux/iio/sysfs.h

@@ -18,7 +18,8 @@ struct iio_chan_spec;
  * struct iio_dev_attr - iio specific device attribute
  * struct iio_dev_attr - iio specific device attribute
  * @dev_attr:	underlying device attribute
  * @dev_attr:	underlying device attribute
  * @address:	associated register address
  * @address:	associated register address
- * @l:		list head for maintaining list of dynamically created attrs.
+ * @l:		list head for maintaining list of dynamically created attrs
+ * @c:		specification for the underlying channel
  */
  */
 struct iio_dev_attr {
 struct iio_dev_attr {
 	struct device_attribute dev_attr;
 	struct device_attribute dev_attr;

+ 3 - 0
include/linux/iio/trigger.h

@@ -18,6 +18,9 @@ struct iio_subirq {
 	bool enabled;
 	bool enabled;
 };
 };
 
 
+struct iio_dev;
+struct iio_trigger;
+
 /**
 /**
  * struct iio_trigger_ops - operations structure for an iio_trigger.
  * struct iio_trigger_ops - operations structure for an iio_trigger.
  * @owner:		used to monitor usage count of the trigger.
  * @owner:		used to monitor usage count of the trigger.

+ 27 - 21
tools/iio/generic_buffer.c

@@ -193,15 +193,15 @@ void process_scan(char *data,
 
 
 void print_usage(void)
 void print_usage(void)
 {
 {
-	printf("Usage: generic_buffer [options]...\n"
-	       "Capture, convert and output data from IIO device buffer\n"
-	       "  -c <n>     Do n conversions\n"
-	       "  -e         Disable wait for event (new data)\n"
-	       "  -g         Use trigger-less mode\n"
-	       "  -l <n>     Set buffer length to n samples\n"
-	       "  -n <name>  Set device name (mandatory)\n"
-	       "  -t <name>  Set trigger name\n"
-	       "  -w <n>     Set delay between reads in us (event-less mode)\n");
+	fprintf(stderr, "Usage: generic_buffer [options]...\n"
+		"Capture, convert and output data from IIO device buffer\n"
+		"  -c <n>     Do n conversions\n"
+		"  -e         Disable wait for event (new data)\n"
+		"  -g         Use trigger-less mode\n"
+		"  -l <n>     Set buffer length to n samples\n"
+		"  -n <name>  Set device name (mandatory)\n"
+		"  -t <name>  Set trigger name\n"
+		"  -w <n>     Set delay between reads in us (event-less mode)\n");
 }
 }
 
 
 int main(int argc, char **argv)
 int main(int argc, char **argv)
@@ -270,8 +270,8 @@ int main(int argc, char **argv)
 		}
 		}
 	}
 	}
 
 
-	if (device_name == NULL) {
-		printf("Device name not set\n");
+	if (!device_name) {
+		fprintf(stderr, "Device name not set\n");
 		print_usage();
 		print_usage();
 		return -1;
 		return -1;
 	}
 	}
@@ -279,7 +279,7 @@ int main(int argc, char **argv)
 	/* Find the device requested */
 	/* Find the device requested */
 	dev_num = find_type_by_name(device_name, "iio:device");
 	dev_num = find_type_by_name(device_name, "iio:device");
 	if (dev_num < 0) {
 	if (dev_num < 0) {
-		printf("Failed to find the %s\n", device_name);
+		fprintf(stderr, "Failed to find the %s\n", device_name);
 		return dev_num;
 		return dev_num;
 	}
 	}
 
 
@@ -290,7 +290,7 @@ int main(int argc, char **argv)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	if (!notrigger) {
 	if (!notrigger) {
-		if (trigger_name == NULL) {
+		if (!trigger_name) {
 			/*
 			/*
 			 * Build the trigger name. If it is device associated
 			 * Build the trigger name. If it is device associated
 			 * its name is <device_name>_dev[n] where n matches
 			 * its name is <device_name>_dev[n] where n matches
@@ -307,7 +307,8 @@ int main(int argc, char **argv)
 		/* Verify the trigger exists */
 		/* Verify the trigger exists */
 		trig_num = find_type_by_name(trigger_name, "trigger");
 		trig_num = find_type_by_name(trigger_name, "trigger");
 		if (trig_num < 0) {
 		if (trig_num < 0) {
-			printf("Failed to find the trigger %s\n", trigger_name);
+			fprintf(stderr, "Failed to find the trigger %s\n",
+				trigger_name);
 			ret = trig_num;
 			ret = trig_num;
 			goto error_free_triggername;
 			goto error_free_triggername;
 		}
 		}
@@ -323,8 +324,8 @@ int main(int argc, char **argv)
 	 */
 	 */
 	ret = build_channel_array(dev_dir_name, &channels, &num_channels);
 	ret = build_channel_array(dev_dir_name, &channels, &num_channels);
 	if (ret) {
 	if (ret) {
-		printf("Problem reading scan element information\n");
-		printf("diag %s\n", dev_dir_name);
+		fprintf(stderr, "Problem reading scan element information\n"
+			"diag %s\n", dev_dir_name);
 		goto error_free_triggername;
 		goto error_free_triggername;
 	}
 	}
 
 
@@ -350,7 +351,8 @@ int main(int argc, char **argv)
 						    dev_dir_name,
 						    dev_dir_name,
 						    trigger_name);
 						    trigger_name);
 		if (ret < 0) {
 		if (ret < 0) {
-			printf("Failed to write current_trigger file\n");
+			fprintf(stderr,
+				"Failed to write current_trigger file\n");
 			goto error_free_buf_dir_name;
 			goto error_free_buf_dir_name;
 		}
 		}
 	}
 	}
@@ -362,8 +364,11 @@ int main(int argc, char **argv)
 
 
 	/* Enable the buffer */
 	/* Enable the buffer */
 	ret = write_sysfs_int("enable", buf_dir_name, 1);
 	ret = write_sysfs_int("enable", buf_dir_name, 1);
-	if (ret < 0)
+	if (ret < 0) {
+		fprintf(stderr,
+			"Failed to enable buffer: %s\n", strerror(-ret));
 		goto error_free_buf_dir_name;
 		goto error_free_buf_dir_name;
+	}
 
 
 	scan_size = size_from_channelarray(channels, num_channels);
 	scan_size = size_from_channelarray(channels, num_channels);
 	data = malloc(scan_size * buf_len);
 	data = malloc(scan_size * buf_len);
@@ -382,7 +387,7 @@ int main(int argc, char **argv)
 	fp = open(buffer_access, O_RDONLY | O_NONBLOCK);
 	fp = open(buffer_access, O_RDONLY | O_NONBLOCK);
 	if (fp == -1) { /* TODO: If it isn't there make the node */
 	if (fp == -1) { /* TODO: If it isn't there make the node */
 		ret = -errno;
 		ret = -errno;
-		printf("Failed to open %s\n", buffer_access);
+		fprintf(stderr, "Failed to open %s\n", buffer_access);
 		goto error_free_buffer_access;
 		goto error_free_buffer_access;
 	}
 	}
 
 
@@ -410,7 +415,7 @@ int main(int argc, char **argv)
 		read_size = read(fp, data, toread * scan_size);
 		read_size = read(fp, data, toread * scan_size);
 		if (read_size < 0) {
 		if (read_size < 0) {
 			if (errno == EAGAIN) {
 			if (errno == EAGAIN) {
-				printf("nothing available\n");
+				fprintf(stderr, "nothing available\n");
 				continue;
 				continue;
 			} else {
 			} else {
 				break;
 				break;
@@ -431,7 +436,8 @@ int main(int argc, char **argv)
 		ret = write_sysfs_string("trigger/current_trigger",
 		ret = write_sysfs_string("trigger/current_trigger",
 					 dev_dir_name, "NULL");
 					 dev_dir_name, "NULL");
 		if (ret < 0)
 		if (ret < 0)
-			printf("Failed to write to %s\n", dev_dir_name);
+			fprintf(stderr, "Failed to write to %s\n",
+				dev_dir_name);
 
 
 error_close_buffer_access:
 error_close_buffer_access:
 	if (close(fp) == -1)
 	if (close(fp) == -1)

+ 8 - 9
tools/iio/iio_event_monitor.c

@@ -215,8 +215,8 @@ static void print_event(struct iio_event_data *event)
 	bool diff = IIO_EVENT_CODE_EXTRACT_DIFF(event->id);
 	bool diff = IIO_EVENT_CODE_EXTRACT_DIFF(event->id);
 
 
 	if (!event_is_known(event)) {
 	if (!event_is_known(event)) {
-		printf("Unknown event: time: %lld, id: %llx\n",
-		       event->timestamp, event->id);
+		fprintf(stderr, "Unknown event: time: %lld, id: %llx\n",
+			event->timestamp, event->id);
 
 
 		return;
 		return;
 	}
 	}
@@ -251,7 +251,7 @@ int main(int argc, char **argv)
 	int fd, event_fd;
 	int fd, event_fd;
 
 
 	if (argc <= 1) {
 	if (argc <= 1) {
-		printf("Usage: %s <device_name>\n", argv[0]);
+		fprintf(stderr, "Usage: %s <device_name>\n", argv[0]);
 		return -1;
 		return -1;
 	}
 	}
 
 
@@ -262,9 +262,8 @@ int main(int argc, char **argv)
 		printf("Found IIO device with name %s with device number %d\n",
 		printf("Found IIO device with name %s with device number %d\n",
 		       device_name, dev_num);
 		       device_name, dev_num);
 		ret = asprintf(&chrdev_name, "/dev/iio:device%d", dev_num);
 		ret = asprintf(&chrdev_name, "/dev/iio:device%d", dev_num);
-		if (ret < 0) {
+		if (ret < 0)
 			return -ENOMEM;
 			return -ENOMEM;
-		}
 	} else {
 	} else {
 		/*
 		/*
 		 * If we can't find an IIO device by name assume device_name is
 		 * If we can't find an IIO device by name assume device_name is
@@ -278,14 +277,14 @@ int main(int argc, char **argv)
 	fd = open(chrdev_name, 0);
 	fd = open(chrdev_name, 0);
 	if (fd == -1) {
 	if (fd == -1) {
 		ret = -errno;
 		ret = -errno;
-		fprintf(stdout, "Failed to open %s\n", chrdev_name);
+		fprintf(stderr, "Failed to open %s\n", chrdev_name);
 		goto error_free_chrdev_name;
 		goto error_free_chrdev_name;
 	}
 	}
 
 
 	ret = ioctl(fd, IIO_GET_EVENT_FD_IOCTL, &event_fd);
 	ret = ioctl(fd, IIO_GET_EVENT_FD_IOCTL, &event_fd);
 	if (ret == -1 || event_fd == -1) {
 	if (ret == -1 || event_fd == -1) {
 		ret = -errno;
 		ret = -errno;
-		fprintf(stdout, "Failed to retrieve event fd\n");
+		fprintf(stderr, "Failed to retrieve event fd\n");
 		if (close(fd) == -1)
 		if (close(fd) == -1)
 			perror("Failed to close character device file");
 			perror("Failed to close character device file");
 
 
@@ -301,7 +300,7 @@ int main(int argc, char **argv)
 		ret = read(event_fd, &event, sizeof(event));
 		ret = read(event_fd, &event, sizeof(event));
 		if (ret == -1) {
 		if (ret == -1) {
 			if (errno == EAGAIN) {
 			if (errno == EAGAIN) {
-				printf("nothing available\n");
+				fprintf(stderr, "nothing available\n");
 				continue;
 				continue;
 			} else {
 			} else {
 				ret = -errno;
 				ret = -errno;
@@ -311,7 +310,7 @@ int main(int argc, char **argv)
 		}
 		}
 
 
 		if (ret != sizeof(event)) {
 		if (ret != sizeof(event)) {
-			printf("Reading event failed!\n");
+			fprintf(stderr, "Reading event failed!\n");
 			ret = -EIO;
 			ret = -EIO;
 			break;
 			break;
 		}
 		}

+ 71 - 65
tools/iio/iio_utils.c

@@ -6,9 +6,6 @@
  * under the terms of the GNU General Public License version 2 as published by
  * under the terms of the GNU General Public License version 2 as published by
  * the Free Software Foundation.
  * the Free Software Foundation.
  */
  */
-#ifndef _IIO_UTILS_H
-#define _IIO_UTILS_H
-
 #include <string.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdio.h>
@@ -39,7 +36,7 @@ int iioutils_break_up_name(const char *full_name, char **generic_name)
 	char *working, *prefix = "";
 	char *working, *prefix = "";
 	int i, ret;
 	int i, ret;
 
 
-	for (i = 0; i < sizeof(iio_direction) / sizeof(iio_direction[0]); i++)
+	for (i = 0; i < ARRAY_SIZE(iio_direction); i++)
 		if (!strncmp(full_name, iio_direction[i],
 		if (!strncmp(full_name, iio_direction[i],
 			     strlen(iio_direction[i]))) {
 			     strlen(iio_direction[i]))) {
 			prefix = iio_direction[i];
 			prefix = iio_direction[i];
@@ -117,13 +114,13 @@ int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used,
 	}
 	}
 
 
 	dp = opendir(scan_el_dir);
 	dp = opendir(scan_el_dir);
-	if (dp == NULL) {
+	if (!dp) {
 		ret = -errno;
 		ret = -errno;
 		goto error_free_builtname_generic;
 		goto error_free_builtname_generic;
 	}
 	}
 
 
 	ret = -ENOENT;
 	ret = -ENOENT;
-	while (ent = readdir(dp), ent != NULL)
+	while (ent = readdir(dp), ent)
 		/*
 		/*
 		 * Do we allow devices to override a generic name with
 		 * Do we allow devices to override a generic name with
 		 * a specific one?
 		 * a specific one?
@@ -138,9 +135,10 @@ int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used,
 			}
 			}
 
 
 			sysfsfp = fopen(filename, "r");
 			sysfsfp = fopen(filename, "r");
-			if (sysfsfp == NULL) {
+			if (!sysfsfp) {
 				ret = -errno;
 				ret = -errno;
-				printf("failed to open %s\n", filename);
+				fprintf(stderr, "failed to open %s\n",
+					filename);
 				goto error_free_filename;
 				goto error_free_filename;
 			}
 			}
 
 
@@ -152,11 +150,13 @@ int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used,
 				     &padint, shift);
 				     &padint, shift);
 			if (ret < 0) {
 			if (ret < 0) {
 				ret = -errno;
 				ret = -errno;
-				printf("failed to pass scan type description\n");
+				fprintf(stderr,
+					"failed to pass scan type description\n");
 				goto error_close_sysfsfp;
 				goto error_close_sysfsfp;
 			} else if (ret != 5) {
 			} else if (ret != 5) {
 				ret = -EIO;
 				ret = -EIO;
-				printf("scan type description didn't match\n");
+				fprintf(stderr,
+					"scan type description didn't match\n");
 				goto error_close_sysfsfp;
 				goto error_close_sysfsfp;
 			}
 			}
 
 
@@ -165,12 +165,13 @@ int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used,
 			if (*bits_used == 64)
 			if (*bits_used == 64)
 				*mask = ~0;
 				*mask = ~0;
 			else
 			else
-				*mask = (1 << *bits_used) - 1;
+				*mask = (1ULL << *bits_used) - 1;
 
 
 			*is_signed = (signchar == 's');
 			*is_signed = (signchar == 's');
 			if (fclose(sysfsfp)) {
 			if (fclose(sysfsfp)) {
 				ret = -errno;
 				ret = -errno;
-				printf("Failed to close %s\n", filename);
+				fprintf(stderr, "Failed to close %s\n",
+					filename);
 				goto error_free_filename;
 				goto error_free_filename;
 			}
 			}
 
 
@@ -235,13 +236,13 @@ int iioutils_get_param_float(float *output, const char *param_name,
 	}
 	}
 
 
 	dp = opendir(device_dir);
 	dp = opendir(device_dir);
-	if (dp == NULL) {
+	if (!dp) {
 		ret = -errno;
 		ret = -errno;
 		goto error_free_builtname_generic;
 		goto error_free_builtname_generic;
 	}
 	}
 
 
 	ret = -ENOENT;
 	ret = -ENOENT;
-	while (ent = readdir(dp), ent != NULL)
+	while (ent = readdir(dp), ent)
 		if ((strcmp(builtname, ent->d_name) == 0) ||
 		if ((strcmp(builtname, ent->d_name) == 0) ||
 		    (strcmp(builtname_generic, ent->d_name) == 0)) {
 		    (strcmp(builtname_generic, ent->d_name) == 0)) {
 			ret = asprintf(&filename,
 			ret = asprintf(&filename,
@@ -285,17 +286,17 @@ error_free_builtname:
  * @cnt: the amount of array elements
  * @cnt: the amount of array elements
  **/
  **/
 
 
-void bsort_channel_array_by_index(struct iio_channel_info **ci_array, int cnt)
+void bsort_channel_array_by_index(struct iio_channel_info *ci_array, int cnt)
 {
 {
 	struct iio_channel_info temp;
 	struct iio_channel_info temp;
 	int x, y;
 	int x, y;
 
 
 	for (x = 0; x < cnt; x++)
 	for (x = 0; x < cnt; x++)
 		for (y = 0; y < (cnt - 1); y++)
 		for (y = 0; y < (cnt - 1); y++)
-			if ((*ci_array)[y].index > (*ci_array)[y + 1].index) {
-				temp = (*ci_array)[y + 1];
-				(*ci_array)[y + 1] = (*ci_array)[y];
-				(*ci_array)[y] = temp;
+			if (ci_array[y].index > ci_array[y + 1].index) {
+				temp = ci_array[y + 1];
+				ci_array[y + 1] = ci_array[y];
+				ci_array[y] = temp;
 			}
 			}
 }
 }
 
 
@@ -325,12 +326,12 @@ int build_channel_array(const char *device_dir,
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	dp = opendir(scan_el_dir);
 	dp = opendir(scan_el_dir);
-	if (dp == NULL) {
+	if (!dp) {
 		ret = -errno;
 		ret = -errno;
 		goto error_free_name;
 		goto error_free_name;
 	}
 	}
 
 
-	while (ent = readdir(dp), ent != NULL)
+	while (ent = readdir(dp), ent)
 		if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
 		if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
 			   "_en") == 0) {
 			   "_en") == 0) {
 			ret = asprintf(&filename,
 			ret = asprintf(&filename,
@@ -341,7 +342,7 @@ int build_channel_array(const char *device_dir,
 			}
 			}
 
 
 			sysfsfp = fopen(filename, "r");
 			sysfsfp = fopen(filename, "r");
-			if (sysfsfp == NULL) {
+			if (!sysfsfp) {
 				ret = -errno;
 				ret = -errno;
 				free(filename);
 				free(filename);
 				goto error_close_dir;
 				goto error_close_dir;
@@ -369,13 +370,13 @@ int build_channel_array(const char *device_dir,
 		}
 		}
 
 
 	*ci_array = malloc(sizeof(**ci_array) * (*counter));
 	*ci_array = malloc(sizeof(**ci_array) * (*counter));
-	if (*ci_array == NULL) {
+	if (!*ci_array) {
 		ret = -ENOMEM;
 		ret = -ENOMEM;
 		goto error_close_dir;
 		goto error_close_dir;
 	}
 	}
 
 
 	seekdir(dp, 0);
 	seekdir(dp, 0);
-	while (ent = readdir(dp), ent != NULL) {
+	while (ent = readdir(dp), ent) {
 		if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
 		if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
 			   "_en") == 0) {
 			   "_en") == 0) {
 			int current_enabled = 0;
 			int current_enabled = 0;
@@ -391,7 +392,7 @@ int build_channel_array(const char *device_dir,
 			}
 			}
 
 
 			sysfsfp = fopen(filename, "r");
 			sysfsfp = fopen(filename, "r");
-			if (sysfsfp == NULL) {
+			if (!sysfsfp) {
 				ret = -errno;
 				ret = -errno;
 				free(filename);
 				free(filename);
 				count--;
 				count--;
@@ -424,7 +425,7 @@ int build_channel_array(const char *device_dir,
 			current->name = strndup(ent->d_name,
 			current->name = strndup(ent->d_name,
 						strlen(ent->d_name) -
 						strlen(ent->d_name) -
 						strlen("_en"));
 						strlen("_en"));
-			if (current->name == NULL) {
+			if (!current->name) {
 				free(filename);
 				free(filename);
 				ret = -ENOMEM;
 				ret = -ENOMEM;
 				count--;
 				count--;
@@ -452,9 +453,10 @@ int build_channel_array(const char *device_dir,
 			}
 			}
 
 
 			sysfsfp = fopen(filename, "r");
 			sysfsfp = fopen(filename, "r");
-			if (sysfsfp == NULL) {
+			if (!sysfsfp) {
 				ret = -errno;
 				ret = -errno;
-				printf("failed to open %s\n", filename);
+				fprintf(stderr, "failed to open %s\n",
+					filename);
 				free(filename);
 				free(filename);
 				goto error_cleanup_array;
 				goto error_cleanup_array;
 			}
 			}
@@ -482,7 +484,7 @@ int build_channel_array(const char *device_dir,
 						       device_dir,
 						       device_dir,
 						       current->name,
 						       current->name,
 						       current->generic_name);
 						       current->generic_name);
-			if (ret < 0)
+			if ((ret < 0) && (ret != -ENOENT))
 				goto error_cleanup_array;
 				goto error_cleanup_array;
 
 
 			ret = iioutils_get_param_float(&current->offset,
 			ret = iioutils_get_param_float(&current->offset,
@@ -490,7 +492,7 @@ int build_channel_array(const char *device_dir,
 						       device_dir,
 						       device_dir,
 						       current->name,
 						       current->name,
 						       current->generic_name);
 						       current->generic_name);
-			if (ret < 0)
+			if ((ret < 0) && (ret != -ENOENT))
 				goto error_cleanup_array;
 				goto error_cleanup_array;
 
 
 			ret = iioutils_get_type(&current->is_signed,
 			ret = iioutils_get_type(&current->is_signed,
@@ -514,7 +516,7 @@ int build_channel_array(const char *device_dir,
 
 
 	free(scan_el_dir);
 	free(scan_el_dir);
 	/* reorder so that the array is in index order */
 	/* reorder so that the array is in index order */
-	bsort_channel_array_by_index(ci_array, *counter);
+	bsort_channel_array_by_index(*ci_array, *counter);
 
 
 	return 0;
 	return 0;
 
 
@@ -524,6 +526,8 @@ error_cleanup_array:
 		free((*ci_array)[i].generic_name);
 		free((*ci_array)[i].generic_name);
 	}
 	}
 	free(*ci_array);
 	free(*ci_array);
+	*ci_array = NULL;
+	*counter = 0;
 error_close_dir:
 error_close_dir:
 	if (dp)
 	if (dp)
 		if (closedir(dp) == -1)
 		if (closedir(dp) == -1)
@@ -535,7 +539,7 @@ error_free_name:
 	return ret;
 	return ret;
 }
 }
 
 
-int calc_digits(int num)
+static int calc_digits(int num)
 {
 {
 	int count = 0;
 	int count = 0;
 
 
@@ -567,12 +571,12 @@ int find_type_by_name(const char *name, const char *type)
 	char *filename;
 	char *filename;
 
 
 	dp = opendir(iio_dir);
 	dp = opendir(iio_dir);
-	if (dp == NULL) {
-		printf("No industrialio devices available\n");
+	if (!dp) {
+		fprintf(stderr, "No industrialio devices available\n");
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
-	while (ent = readdir(dp), ent != NULL) {
+	while (ent = readdir(dp), ent) {
 		if (strcmp(ent->d_name, ".") != 0 &&
 		if (strcmp(ent->d_name, ".") != 0 &&
 		    strcmp(ent->d_name, "..") != 0 &&
 		    strcmp(ent->d_name, "..") != 0 &&
 		    strlen(ent->d_name) > strlen(type) &&
 		    strlen(ent->d_name) > strlen(type) &&
@@ -581,11 +585,13 @@ int find_type_by_name(const char *name, const char *type)
 			ret = sscanf(ent->d_name + strlen(type), "%d", &number);
 			ret = sscanf(ent->d_name + strlen(type), "%d", &number);
 			if (ret < 0) {
 			if (ret < 0) {
 				ret = -errno;
 				ret = -errno;
-				printf("failed to read element number\n");
+				fprintf(stderr,
+					"failed to read element number\n");
 				goto error_close_dir;
 				goto error_close_dir;
 			} else if (ret != 1) {
 			} else if (ret != 1) {
 				ret = -EIO;
 				ret = -EIO;
-				printf("failed to match element number\n");
+				fprintf(stderr,
+					"failed to match element number\n");
 				goto error_close_dir;
 				goto error_close_dir;
 			}
 			}
 
 
@@ -595,7 +601,7 @@ int find_type_by_name(const char *name, const char *type)
 			    ":", 1) != 0) {
 			    ":", 1) != 0) {
 				filename = malloc(strlen(iio_dir) + strlen(type)
 				filename = malloc(strlen(iio_dir) + strlen(type)
 						  + numstrlen + 6);
 						  + numstrlen + 6);
-				if (filename == NULL) {
+				if (!filename) {
 					ret = -ENOMEM;
 					ret = -ENOMEM;
 					goto error_close_dir;
 					goto error_close_dir;
 				}
 				}
@@ -654,7 +660,7 @@ static int _write_sysfs_int(const char *filename, const char *basedir, int val,
 	int test;
 	int test;
 	char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
 	char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
 
 
-	if (temp == NULL)
+	if (!temp)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	ret = sprintf(temp, "%s/%s", basedir, filename);
 	ret = sprintf(temp, "%s/%s", basedir, filename);
@@ -662,9 +668,9 @@ static int _write_sysfs_int(const char *filename, const char *basedir, int val,
 		goto error_free;
 		goto error_free;
 
 
 	sysfsfp = fopen(temp, "w");
 	sysfsfp = fopen(temp, "w");
-	if (sysfsfp == NULL) {
+	if (!sysfsfp) {
 		ret = -errno;
 		ret = -errno;
-		printf("failed to open %s\n", temp);
+		fprintf(stderr, "failed to open %s\n", temp);
 		goto error_free;
 		goto error_free;
 	}
 	}
 
 
@@ -683,9 +689,9 @@ static int _write_sysfs_int(const char *filename, const char *basedir, int val,
 
 
 	if (verify) {
 	if (verify) {
 		sysfsfp = fopen(temp, "r");
 		sysfsfp = fopen(temp, "r");
-		if (sysfsfp == NULL) {
+		if (!sysfsfp) {
 			ret = -errno;
 			ret = -errno;
-			printf("failed to open %s\n", temp);
+			fprintf(stderr, "failed to open %s\n", temp);
 			goto error_free;
 			goto error_free;
 		}
 		}
 
 
@@ -703,8 +709,9 @@ static int _write_sysfs_int(const char *filename, const char *basedir, int val,
 		}
 		}
 
 
 		if (test != val) {
 		if (test != val) {
-			printf("Possible failure in int write %d to %s/%s\n",
-			       val, basedir, filename);
+			fprintf(stderr,
+				"Possible failure in int write %d to %s/%s\n",
+				val, basedir, filename);
 			ret = -1;
 			ret = -1;
 		}
 		}
 	}
 	}
@@ -749,8 +756,8 @@ static int _write_sysfs_string(const char *filename, const char *basedir,
 	FILE  *sysfsfp;
 	FILE  *sysfsfp;
 	char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
 	char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
 
 
-	if (temp == NULL) {
-		printf("Memory allocation failed\n");
+	if (!temp) {
+		fprintf(stderr, "Memory allocation failed\n");
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
 
 
@@ -759,9 +766,9 @@ static int _write_sysfs_string(const char *filename, const char *basedir,
 		goto error_free;
 		goto error_free;
 
 
 	sysfsfp = fopen(temp, "w");
 	sysfsfp = fopen(temp, "w");
-	if (sysfsfp == NULL) {
+	if (!sysfsfp) {
 		ret = -errno;
 		ret = -errno;
-		printf("Could not open %s\n", temp);
+		fprintf(stderr, "Could not open %s\n", temp);
 		goto error_free;
 		goto error_free;
 	}
 	}
 
 
@@ -780,9 +787,9 @@ static int _write_sysfs_string(const char *filename, const char *basedir,
 
 
 	if (verify) {
 	if (verify) {
 		sysfsfp = fopen(temp, "r");
 		sysfsfp = fopen(temp, "r");
-		if (sysfsfp == NULL) {
+		if (!sysfsfp) {
 			ret = -errno;
 			ret = -errno;
-			printf("Could not open file to verify\n");
+			fprintf(stderr, "Could not open file to verify\n");
 			goto error_free;
 			goto error_free;
 		}
 		}
 
 
@@ -800,9 +807,10 @@ static int _write_sysfs_string(const char *filename, const char *basedir,
 		}
 		}
 
 
 		if (strcmp(temp, val) != 0) {
 		if (strcmp(temp, val) != 0) {
-			printf("Possible failure in string write of %s "
-			       "Should be %s written to %s/%s\n", temp, val,
-			       basedir, filename);
+			fprintf(stderr,
+				"Possible failure in string write of %s "
+				"Should be %s written to %s/%s\n", temp, val,
+				basedir, filename);
 			ret = -1;
 			ret = -1;
 		}
 		}
 	}
 	}
@@ -855,8 +863,8 @@ int read_sysfs_posint(const char *filename, const char *basedir)
 	FILE  *sysfsfp;
 	FILE  *sysfsfp;
 	char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
 	char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
 
 
-	if (temp == NULL) {
-		printf("Memory allocation failed");
+	if (!temp) {
+		fprintf(stderr, "Memory allocation failed");
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
 
 
@@ -865,7 +873,7 @@ int read_sysfs_posint(const char *filename, const char *basedir)
 		goto error_free;
 		goto error_free;
 
 
 	sysfsfp = fopen(temp, "r");
 	sysfsfp = fopen(temp, "r");
-	if (sysfsfp == NULL) {
+	if (!sysfsfp) {
 		ret = -errno;
 		ret = -errno;
 		goto error_free;
 		goto error_free;
 	}
 	}
@@ -902,8 +910,8 @@ int read_sysfs_float(const char *filename, const char *basedir, float *val)
 	FILE  *sysfsfp;
 	FILE  *sysfsfp;
 	char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
 	char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
 
 
-	if (temp == NULL) {
-		printf("Memory allocation failed");
+	if (!temp) {
+		fprintf(stderr, "Memory allocation failed");
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
 
 
@@ -912,7 +920,7 @@ int read_sysfs_float(const char *filename, const char *basedir, float *val)
 		goto error_free;
 		goto error_free;
 
 
 	sysfsfp = fopen(temp, "r");
 	sysfsfp = fopen(temp, "r");
-	if (sysfsfp == NULL) {
+	if (!sysfsfp) {
 		ret = -errno;
 		ret = -errno;
 		goto error_free;
 		goto error_free;
 	}
 	}
@@ -949,8 +957,8 @@ int read_sysfs_string(const char *filename, const char *basedir, char *str)
 	FILE  *sysfsfp;
 	FILE  *sysfsfp;
 	char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
 	char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
 
 
-	if (temp == NULL) {
-		printf("Memory allocation failed");
+	if (!temp) {
+		fprintf(stderr, "Memory allocation failed");
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
 
 
@@ -959,7 +967,7 @@ int read_sysfs_string(const char *filename, const char *basedir, char *str)
 		goto error_free;
 		goto error_free;
 
 
 	sysfsfp = fopen(temp, "r");
 	sysfsfp = fopen(temp, "r");
-	if (sysfsfp == NULL) {
+	if (!sysfsfp) {
 		ret = -errno;
 		ret = -errno;
 		goto error_free;
 		goto error_free;
 	}
 	}
@@ -981,5 +989,3 @@ error_free:
 
 
 	return ret;
 	return ret;
 }
 }
-
-#endif /* _IIO_UTILS_H */

+ 3 - 1
tools/iio/iio_utils.h

@@ -18,6 +18,8 @@
 #define FORMAT_SCAN_ELEMENTS_DIR "%s/scan_elements"
 #define FORMAT_SCAN_ELEMENTS_DIR "%s/scan_elements"
 #define FORMAT_TYPE_FILE "%s_type"
 #define FORMAT_TYPE_FILE "%s_type"
 
 
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
+
 extern const char *iio_dir;
 extern const char *iio_dir;
 
 
 /**
 /**
@@ -58,7 +60,7 @@ int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used,
 int iioutils_get_param_float(float *output, const char *param_name,
 int iioutils_get_param_float(float *output, const char *param_name,
 			     const char *device_dir, const char *name,
 			     const char *device_dir, const char *name,
 			     const char *generic_name);
 			     const char *generic_name);
-void bsort_channel_array_by_index(struct iio_channel_info **ci_array, int cnt);
+void bsort_channel_array_by_index(struct iio_channel_info *ci_array, int cnt);
 int build_channel_array(const char *device_dir,
 int build_channel_array(const char *device_dir,
 			struct iio_channel_info **ci_array, int *counter);
 			struct iio_channel_info **ci_array, int *counter);
 int find_type_by_name(const char *name, const char *type);
 int find_type_by_name(const char *name, const char *type);

+ 8 - 8
tools/iio/lsiio.c

@@ -46,10 +46,10 @@ static int dump_channels(const char *dev_dir_name)
 	const struct dirent *ent;
 	const struct dirent *ent;
 
 
 	dp = opendir(dev_dir_name);
 	dp = opendir(dev_dir_name);
-	if (dp == NULL)
+	if (!dp)
 		return -errno;
 		return -errno;
 
 
-	while (ent = readdir(dp), ent != NULL)
+	while (ent = readdir(dp), ent)
 		if (check_prefix(ent->d_name, "in_") &&
 		if (check_prefix(ent->d_name, "in_") &&
 		    check_postfix(ent->d_name, "_raw"))
 		    check_postfix(ent->d_name, "_raw"))
 			printf("   %-10s\n", ent->d_name);
 			printf("   %-10s\n", ent->d_name);
@@ -69,7 +69,7 @@ static int dump_one_device(const char *dev_dir_name)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	ret = read_sysfs_string("name", dev_dir_name, name);
 	ret = read_sysfs_string("name", dev_dir_name, name);
-	if (ret)
+	if (ret < 0)
 		return ret;
 		return ret;
 
 
 	printf("Device %03d: %s\n", dev_idx, name);
 	printf("Device %03d: %s\n", dev_idx, name);
@@ -92,7 +92,7 @@ static int dump_one_trigger(const char *dev_dir_name)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	ret = read_sysfs_string("name", dev_dir_name, name);
 	ret = read_sysfs_string("name", dev_dir_name, name);
-	if (ret)
+	if (ret < 0)
 		return ret;
 		return ret;
 
 
 	printf("Trigger %03d: %s\n", dev_idx, name);
 	printf("Trigger %03d: %s\n", dev_idx, name);
@@ -107,12 +107,12 @@ static int dump_devices(void)
 	DIR *dp;
 	DIR *dp;
 
 
 	dp = opendir(iio_dir);
 	dp = opendir(iio_dir);
-	if (dp == NULL) {
-		printf("No industrial I/O devices available\n");
+	if (!dp) {
+		fprintf(stderr, "No industrial I/O devices available\n");
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
-	while (ent = readdir(dp), ent != NULL) {
+	while (ent = readdir(dp), ent) {
 		if (check_prefix(ent->d_name, type_device)) {
 		if (check_prefix(ent->d_name, type_device)) {
 			char *dev_dir_name;
 			char *dev_dir_name;
 
 
@@ -134,7 +134,7 @@ static int dump_devices(void)
 		}
 		}
 	}
 	}
 	rewinddir(dp);
 	rewinddir(dp);
-	while (ent = readdir(dp), ent != NULL) {
+	while (ent = readdir(dp), ent) {
 		if (check_prefix(ent->d_name, type_trigger)) {
 		if (check_prefix(ent->d_name, type_trigger)) {
 			char *dev_dir_name;
 			char *dev_dir_name;