Merge tag 'iio-for-4.7a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio...
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 4 Apr 2016 19:31:05 +0000 (12:31 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 4 Apr 2016 19:31:05 +0000 (12:31 -0700)
Jonathan writes:

First round of IIO new device support, features and cleanups for the 4.7 cycle.

New core support
* UV light modifier (for intensity)
* UV light index channel type.

New device support
* hp206c barometer and altimeter
  - new driver.
* mcp4131 potentiometer
  - new driver supporting lots of parts from Microchip.
* mma8452
  - FXLS8471Q support
- NXP LPC18XX SOC ADC
  - new driver.
- NXP LPC18XX SOC DAC
  - new driver.
- rockchip_saradc
  - support rk3399
* st accel
  - h3lis331dl support

Staging driver removals
* adis16204
  - obsolete part making it hard to get parts to test the driver in order
    to clean it up.
* adis16220
  - obsolete part making it hard to get the parts test the driver in order
    to clean it up.

Features
* core
  - convenience functions to claim / release direct access to the device.
    Makes more consistent handling of this corner easier. Used in ad7192 driver.
* ak8975
  - power regulator support.
* at91-sama5d2
  - differential channel support.
* mma8452
  - runtime pm support
  - drop device specific autosleep and use the runtime pm one instead.
* ms5611
  - DT bindings
  - oversampling ratio support

Cleanups and minor fixes
* MAINTAINERS
  - Peter got married - hence name change!

* Documentation
  - Fix a typo in in_proximity_raw description.
  - Add some missing docs for iio_buffer_access_funcs.

* Tools
  - update iio_event_monitor names to match new stuff.
  - make generic_buffer look for triggers ending in -trigger as we let these in
  for a number of drivers a long time back and now it is a fairly common
  option.

Drivers
* staging wide
  - convert bare unsigned usage to unsigned int to comply with coding style.
* non staging wide:
  - since boiler plate gpio handling of interrupts has been moved into the
   ACPI core we don't need to include gpio/consumer.h in a load of drivers so
   drop it.
* ad7606
  - fix an endian casting sparse warning.
* ak8975
  - fix a possible unitialized warning from gcc.
  - drop and unused field left over from earlier cleanups
  - fix a missing regulator_disable on exit.
* at91-sama5d2
  - typo and indentation
  - missing IOMEM dependency.
  - cleanup mode register usage by avoidling erasing whole thing when changing
  the sampling frequency.
* bmc150
  - use the core demux and available_scan_masks to simplify buffer handling
  - optimize the transfers in the trigger handler now we have a magic function
  to emulate bulk reads (under circumstances met here).  This matters with some
  rather dumb i2c adapters in particular.
  - use a single regmap_conf for all bus types as they were all the same.
* bmg160
  - use the core demux and available_scan_masks to simplify the buffer handling
  - optimize the transfers in the trigger handler now we have a magic funciton
  to emulate bulk rads (under circumstances met here).
  - drop gpio interrupt probing from the driver (ACPI) as now handled by the
  ACPI core.
* ina2xx-adc
  - update the CALIB register when RShunt changes.
  - fix scale for VShunt - in reality this error canceled out when used.
* isl29028
  - use regmap to retrieve the struct device instead of carrying a second
  copy of it around.
* kxcjk-1013
  - use core demux
  - optimize i2c transfers in the trigger handler.
* mcp4531
  - refactor to use a pointer to access model parameters instead of indexing
    into the array each time.
* mma8452
  - style fixes
  - avoid swtiching to active whenever the config changes
  - add missin i2c_device_id for mma8451
* mpu6050
  - fix possible NULL dereference.
  - fix the name / chip_id used when ACPI used (otherwise reports as NULL).
* ms5611
  - fix a missing regulator_disable that left the regulator on during removal.
* mxc4005
  - drop gpio interrupt handling for ACPI case from driver as the core now
  handles this case.
* st-sensors
  - note that there are only ever a maximum of 3 axis on current st-sensors
  so just allocate a fixed sized buffer big enough for that.
* tpl0102
  - change the i2c_check_functionality condition to bring it inline with other
    IIO users as EOPNOTSUPP.
* tsl2563
  - replace deprecated flush_scheduled_work

78 files changed:
Documentation/ABI/testing/sysfs-bus-iio
Documentation/devicetree/bindings/iio/accel/mma8452.txt
Documentation/devicetree/bindings/iio/adc/lpc1850-adc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/iio/adc/rockchip-saradc.txt
Documentation/devicetree/bindings/iio/dac/lpc1850-dac.txt [new file with mode: 0644]
Documentation/devicetree/bindings/iio/magnetometer/ak8975.txt
Documentation/devicetree/bindings/iio/potentiometer/mcp4131.txt [new file with mode: 0644]
Documentation/devicetree/bindings/iio/pressure/ms5611.txt [new file with mode: 0644]
Documentation/devicetree/bindings/iio/st-sensors.txt
Documentation/devicetree/bindings/vendor-prefixes.txt
MAINTAINERS
drivers/iio/accel/Kconfig
drivers/iio/accel/bmc150-accel-core.c
drivers/iio/accel/bmc150-accel-i2c.c
drivers/iio/accel/bmc150-accel-spi.c
drivers/iio/accel/bmc150-accel.h
drivers/iio/accel/kxcjk-1013.c
drivers/iio/accel/mma8452.c
drivers/iio/accel/mma9553.c
drivers/iio/accel/mxc4005.c
drivers/iio/accel/st_accel.h
drivers/iio/accel/st_accel_core.c
drivers/iio/accel/st_accel_i2c.c
drivers/iio/accel/stk8312.c
drivers/iio/accel/stk8ba50.c
drivers/iio/adc/Kconfig
drivers/iio/adc/Makefile
drivers/iio/adc/at91-sama5d2_adc.c
drivers/iio/adc/ina2xx-adc.c
drivers/iio/adc/lpc18xx_adc.c [new file with mode: 0644]
drivers/iio/adc/rockchip_saradc.c
drivers/iio/common/st_sensors/st_sensors_buffer.c
drivers/iio/dac/Kconfig
drivers/iio/dac/Makefile
drivers/iio/dac/lpc18xx_dac.c [new file with mode: 0644]
drivers/iio/gyro/bmg160_core.c
drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
drivers/iio/imu/kmx61.c
drivers/iio/industrialio-core.c
drivers/iio/light/stk3310.c
drivers/iio/light/tsl2563.c
drivers/iio/magnetometer/ak8975.c
drivers/iio/magnetometer/bmc150_magn.c
drivers/iio/potentiometer/Kconfig
drivers/iio/potentiometer/Makefile
drivers/iio/potentiometer/mcp4131.c [new file with mode: 0644]
drivers/iio/potentiometer/mcp4531.c
drivers/iio/potentiometer/tpl0102.c
drivers/iio/pressure/Kconfig
drivers/iio/pressure/Makefile
drivers/iio/pressure/hp206c.c [new file with mode: 0644]
drivers/iio/pressure/ms5611.h
drivers/iio/pressure/ms5611_core.c
drivers/iio/pressure/ms5611_i2c.c
drivers/iio/pressure/ms5611_spi.c
drivers/staging/iio/accel/Kconfig
drivers/staging/iio/accel/Makefile
drivers/staging/iio/accel/adis16204.h [deleted file]
drivers/staging/iio/accel/adis16204_core.c [deleted file]
drivers/staging/iio/accel/adis16220.h [deleted file]
drivers/staging/iio/accel/adis16220_core.c [deleted file]
drivers/staging/iio/adc/ad7192.c
drivers/staging/iio/adc/ad7280a.c
drivers/staging/iio/adc/ad7280a.h
drivers/staging/iio/adc/ad7606.h
drivers/staging/iio/adc/ad7606_core.c
drivers/staging/iio/adc/ad7780.c
drivers/staging/iio/impedance-analyzer/ad5933.c
drivers/staging/iio/light/isl29028.c
drivers/staging/iio/meter/ade7758_ring.c
drivers/staging/iio/resolver/ad2s1210.h
drivers/staging/iio/trigger/iio-trig-bfin-timer.c
include/linux/iio/buffer.h
include/linux/iio/iio.h
include/uapi/linux/iio/types.h
tools/iio/generic_buffer.c
tools/iio/iio_event_monitor.c

index 3c66248..f155eff 100644 (file)
@@ -1233,7 +1233,7 @@ KernelVersion:    3.4
 Contact:       linux-iio@vger.kernel.org
 Description:
                Proximity measurement indicating that some
-               object is near the sensor, usually be observing
+               object is near the sensor, usually by observing
                reflectivity of infrared or ultrasound emitted.
                Often these sensors are unit less and as such conversion
                to SI units is not possible. Higher proximity measurements
@@ -1255,12 +1255,23 @@ Description:
 What:          /sys/.../iio:deviceX/in_intensityY_raw
 What:          /sys/.../iio:deviceX/in_intensityY_ir_raw
 What:          /sys/.../iio:deviceX/in_intensityY_both_raw
+What:          /sys/.../iio:deviceX/in_intensityY_uv_raw
 KernelVersion: 3.4
 Contact:       linux-iio@vger.kernel.org
 Description:
                Unit-less light intensity. Modifiers both and ir indicate
                that measurements contains visible and infrared light
-               components or just infrared light, respectively.
+               components or just infrared light, respectively. Modifier uv indicates
+               that measurements contain ultraviolet light components.
+
+What:          /sys/.../iio:deviceX/in_uvindex_input
+KernelVersion: 4.6
+Contact:       linux-iio@vger.kernel.org
+Description:
+               UV light intensity index measuring the human skin's response to
+               different wavelength of sunlight weighted according to the
+               standardised CIE Erythemal Action Spectrum. UV index values range
+               from 0 (low) to >=11 (extreme).
 
 What:          /sys/.../iio:deviceX/in_intensity_red_integration_time
 What:          /sys/.../iio:deviceX/in_intensity_green_integration_time
index 165937e..45f5c5c 100644 (file)
@@ -1,4 +1,4 @@
-Freescale MMA8451Q, MMA8452Q, MMA8453Q, MMA8652FC or MMA8653FC
+Freescale MMA8451Q, MMA8452Q, MMA8453Q, MMA8652FC, MMA8653FC or FXLS8471Q
 triaxial accelerometer
 
 Required properties:
@@ -9,6 +9,7 @@ Required properties:
     * "fsl,mma8453"
     * "fsl,mma8652"
     * "fsl,mma8653"
+    * "fsl,fxls8471"
 
   - reg: the I2C address of the chip
 
diff --git a/Documentation/devicetree/bindings/iio/adc/lpc1850-adc.txt b/Documentation/devicetree/bindings/iio/adc/lpc1850-adc.txt
new file mode 100644 (file)
index 0000000..0bcae51
--- /dev/null
@@ -0,0 +1,21 @@
+NXP LPC1850 ADC bindings
+
+Required properties:
+- compatible: Should be "nxp,lpc1850-adc"
+- reg: Offset and length of the register set for the ADC device
+- interrupts: The interrupt number for the ADC device
+- clocks: The root clock of the ADC controller
+- vref-supply: The regulator supply ADC reference voltage
+- resets: phandle to reset controller and line specifier
+
+Example:
+
+adc0: adc@400e3000 {
+       compatible = "nxp,lpc1850-adc";
+       reg = <0x400e3000 0x1000>;
+       interrupts = <17>;
+       clocks = <&ccu1 CLK_APB3_ADC0>;
+       vref-supply = <&reg_vdda>;
+       resets = <&rgu 40>;
+       status = "disabled";
+};
index a9a5fe1..bf99e2f 100644 (file)
@@ -1,7 +1,11 @@
 Rockchip Successive Approximation Register (SAR) A/D Converter bindings
 
 Required properties:
-- compatible: Should be "rockchip,saradc" or "rockchip,rk3066-tsadc"
+- compatible: should be "rockchip,<name>-saradc" or "rockchip,rk3066-tsadc"
+   - "rockchip,saradc": for rk3188, rk3288
+   - "rockchip,rk3066-tsadc": for rk3036
+   - "rockchip,rk3399-saradc": for rk3399
+
 - reg: physical base address of the controller and length of memory mapped
        region.
 - interrupts: The interrupt number to the cpu. The interrupt specifier format
diff --git a/Documentation/devicetree/bindings/iio/dac/lpc1850-dac.txt b/Documentation/devicetree/bindings/iio/dac/lpc1850-dac.txt
new file mode 100644 (file)
index 0000000..7d6647d
--- /dev/null
@@ -0,0 +1,20 @@
+NXP LPC1850 DAC bindings
+
+Required properties:
+- compatible: Should be "nxp,lpc1850-dac"
+- reg: Offset and length of the register set for the ADC device
+- interrupts: The interrupt number for the ADC device
+- clocks: The root clock of the ADC controller
+- vref-supply: The regulator supply ADC reference voltage
+- resets: phandle to reset controller and line specifier
+
+Example:
+dac: dac@400e1000 {
+       compatible = "nxp,lpc1850-dac";
+       reg = <0x400e1000 0x1000>;
+       interrupts = <0>;
+       clocks = <&ccu1 CLK_APB3_DAC>;
+       vref-supply = <&reg_vdda>;
+       resets = <&rgu 42>;
+       status = "disabled";
+};
index 011679f..34a3206 100644 (file)
@@ -8,6 +8,7 @@ Required properties:
 Optional properties:
 
   - gpios : should be device tree identifier of the magnetometer DRDY pin
+  - vdd-supply: an optional regulator that needs to be on to provide VDD
 
 Example:
 
@@ -15,4 +16,5 @@ ak8975@0c {
         compatible = "asahi-kasei,ak8975";
         reg = <0x0c>;
         gpios = <&gpj0 7 0>;
+        vdd-supply = <&ldo_3v3_gnss>;
 };
diff --git a/Documentation/devicetree/bindings/iio/potentiometer/mcp4131.txt b/Documentation/devicetree/bindings/iio/potentiometer/mcp4131.txt
new file mode 100644 (file)
index 0000000..3ccba16
--- /dev/null
@@ -0,0 +1,84 @@
+* Microchip MCP413X/414X/415X/416X/423X/424X/425X/426X Digital Potentiometer
+  driver
+
+The node for this driver must be a child node of a SPI controller, hence
+all mandatory properties described in
+
+        Documentation/devicetree/bindings/spi/spi-bus.txt
+
+must be specified.
+
+Required properties:
+       - compatible:   Must be one of the following, depending on the
+                       model:
+                       "microchip,mcp4131-502"
+                       "microchip,mcp4131-103"
+                       "microchip,mcp4131-503"
+                       "microchip,mcp4131-104"
+                       "microchip,mcp4132-502"
+                       "microchip,mcp4132-103"
+                       "microchip,mcp4132-503"
+                       "microchip,mcp4132-104"
+                       "microchip,mcp4141-502"
+                       "microchip,mcp4141-103"
+                       "microchip,mcp4141-503"
+                       "microchip,mcp4141-104"
+                       "microchip,mcp4142-502"
+                       "microchip,mcp4142-103"
+                       "microchip,mcp4142-503"
+                       "microchip,mcp4142-104"
+                       "microchip,mcp4151-502"
+                       "microchip,mcp4151-103"
+                       "microchip,mcp4151-503"
+                       "microchip,mcp4151-104"
+                       "microchip,mcp4152-502"
+                       "microchip,mcp4152-103"
+                       "microchip,mcp4152-503"
+                       "microchip,mcp4152-104"
+                       "microchip,mcp4161-502"
+                       "microchip,mcp4161-103"
+                       "microchip,mcp4161-503"
+                       "microchip,mcp4161-104"
+                       "microchip,mcp4162-502"
+                       "microchip,mcp4162-103"
+                       "microchip,mcp4162-503"
+                       "microchip,mcp4162-104"
+                       "microchip,mcp4231-502"
+                       "microchip,mcp4231-103"
+                       "microchip,mcp4231-503"
+                       "microchip,mcp4231-104"
+                       "microchip,mcp4232-502"
+                       "microchip,mcp4232-103"
+                       "microchip,mcp4232-503"
+                       "microchip,mcp4232-104"
+                       "microchip,mcp4241-502"
+                       "microchip,mcp4241-103"
+                       "microchip,mcp4241-503"
+                       "microchip,mcp4241-104"
+                       "microchip,mcp4242-502"
+                       "microchip,mcp4242-103"
+                       "microchip,mcp4242-503"
+                       "microchip,mcp4242-104"
+                       "microchip,mcp4251-502"
+                       "microchip,mcp4251-103"
+                       "microchip,mcp4251-503"
+                       "microchip,mcp4251-104"
+                       "microchip,mcp4252-502"
+                       "microchip,mcp4252-103"
+                       "microchip,mcp4252-503"
+                       "microchip,mcp4252-104"
+                       "microchip,mcp4261-502"
+                       "microchip,mcp4261-103"
+                       "microchip,mcp4261-503"
+                       "microchip,mcp4261-104"
+                       "microchip,mcp4262-502"
+                       "microchip,mcp4262-103"
+                       "microchip,mcp4262-503"
+                       "microchip,mcp4262-104"
+
+Example:
+mcp4131: mcp4131@0 {
+       compatible = "mcp4131-502";
+       reg = <0>;
+       spi-max-frequency = <500000>;
+};
diff --git a/Documentation/devicetree/bindings/iio/pressure/ms5611.txt b/Documentation/devicetree/bindings/iio/pressure/ms5611.txt
new file mode 100644 (file)
index 0000000..17bca86
--- /dev/null
@@ -0,0 +1,19 @@
+MEAS ms5611 family pressure sensors
+
+Pressure sensors from MEAS Switzerland with SPI and I2C bus interfaces.
+
+Required properties:
+- compatible: "meas,ms5611" or "meas,ms5607"
+- reg: the I2C address or SPI chip select the device will respond to
+
+Optional properties:
+- vdd-supply: an optional regulator that needs to be on to provide VDD
+  power to the sensor.
+
+Example:
+
+ms5607@77 {
+       compatible = "meas,ms5607";
+       reg = <0x77>;
+       vdd-supply = <&ldo_3v3_gnss>;
+};
index d4b87cc..71b7bdf 100644 (file)
@@ -37,6 +37,7 @@ Accelerometers:
 - st,lsm330-accel
 - st,lsm303agr-accel
 - st,lis2dh12-accel
+- st,h3lis331dl-accel
 
 Gyroscopes:
 - st,l3g4200d-gyro
index 86740d4..e4e5486 100644 (file)
@@ -141,6 +141,7 @@ lsi LSI Corp. (LSI Logic)
 lltc   Linear Technology Corporation
 marvell        Marvell Technology Group Ltd.
 maxim  Maxim Integrated Products
+meas   Measurement Specialties
 mediatek       MediaTek Inc.
 melexis        Melexis N.V.
 merrii Merrii Technology Co., Ltd.
index 03e00c7..1ace393 100644 (file)
@@ -5538,7 +5538,7 @@ IIO SUBSYSTEM AND DRIVERS
 M:     Jonathan Cameron <jic23@kernel.org>
 R:     Hartmut Knaack <knaack.h@gmx.de>
 R:     Lars-Peter Clausen <lars@metafoo.de>
-R:     Peter Meerwald <pmeerw@pmeerw.net>
+R:     Peter Meerwald-Stadler <pmeerw@pmeerw.net>
 L:     linux-iio@vger.kernel.org
 S:     Maintained
 F:     drivers/iio/
index b0d3ecf..e4a758c 100644 (file)
@@ -64,7 +64,7 @@ config IIO_ST_ACCEL_3AXIS
        help
          Say yes here to build support for STMicroelectronics accelerometers:
          LSM303DLH, LSM303DLHC, LIS3DH, LSM330D, LSM330DL, LSM330DLC,
-         LIS331DLH, LSM303DL, LSM303DLM, LSM330, LIS2DH12.
+         LIS331DLH, LSM303DL, LSM303DLM, LSM330, LIS2DH12, H3LIS331DL.
 
          This driver can also be built as a module. If so, these modules
          will be created:
@@ -143,7 +143,8 @@ config MMA8452
        select IIO_TRIGGERED_BUFFER
        help
          Say yes here to build support for the following Freescale 3-axis
-         accelerometers: MMA8451Q, MMA8452Q, MMA8453Q, MMA8652FC, MMA8653FC.
+         accelerometers: MMA8451Q, MMA8452Q, MMA8453Q, MMA8652FC, MMA8653FC,
+         FXLS8471Q.
 
          To compile this driver as a module, choose M here: the module
          will be called mma8452.
index c73331f..e631ee9 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/acpi.h>
-#include <linux/gpio/consumer.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
 #include <linux/iio/iio.h>
@@ -138,6 +137,7 @@ enum bmc150_accel_axis {
        AXIS_X,
        AXIS_Y,
        AXIS_Z,
+       AXIS_MAX,
 };
 
 enum bmc150_power_modes {
@@ -246,11 +246,12 @@ static const struct {
                                       {500000, BMC150_ACCEL_SLEEP_500_MS},
                                       {1000000, BMC150_ACCEL_SLEEP_1_SEC} };
 
-static const struct regmap_config bmc150_i2c_regmap_conf = {
+const struct regmap_config bmc150_regmap_conf = {
        .reg_bits = 8,
        .val_bits = 8,
        .max_register = 0x3f,
 };
+EXPORT_SYMBOL_GPL(bmc150_regmap_conf);
 
 static int bmc150_accel_set_mode(struct bmc150_accel_data *data,
                                 enum bmc150_power_modes mode,
@@ -988,6 +989,7 @@ static const struct iio_event_spec bmc150_accel_event = {
                .realbits = (bits),                                     \
                .storagebits = 16,                                      \
                .shift = 16 - (bits),                                   \
+               .endianness = IIO_LE,                                   \
        },                                                              \
        .event_spec = &bmc150_accel_event,                              \
        .num_event_specs = 1                                            \
@@ -1104,27 +1106,23 @@ static const struct iio_info bmc150_accel_info_fifo = {
        .driver_module          = THIS_MODULE,
 };
 
+static const unsigned long bmc150_accel_scan_masks[] = {
+                                       BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z),
+                                       0};
+
 static irqreturn_t bmc150_accel_trigger_handler(int irq, void *p)
 {
        struct iio_poll_func *pf = p;
        struct iio_dev *indio_dev = pf->indio_dev;
        struct bmc150_accel_data *data = iio_priv(indio_dev);
-       int bit, ret, i = 0;
-       unsigned int raw_val;
+       int ret;
 
        mutex_lock(&data->mutex);
-       for_each_set_bit(bit, indio_dev->active_scan_mask,
-                        indio_dev->masklength) {
-               ret = regmap_bulk_read(data->regmap,
-                                      BMC150_ACCEL_AXIS_TO_REG(bit), &raw_val,
-                                      2);
-               if (ret < 0) {
-                       mutex_unlock(&data->mutex);
-                       goto err_read;
-               }
-               data->buffer[i++] = raw_val;
-       }
+       ret = regmap_bulk_read(data->regmap, BMC150_ACCEL_REG_XOUT_L,
+                              data->buffer, AXIS_MAX * 2);
        mutex_unlock(&data->mutex);
+       if (ret < 0)
+               goto err_read;
 
        iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
                                           pf->timestamp);
@@ -1574,6 +1572,7 @@ int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq,
        indio_dev->channels = data->chip_info->channels;
        indio_dev->num_channels = data->chip_info->num_channels;
        indio_dev->name = name ? name : data->chip_info->name;
+       indio_dev->available_scan_masks = bmc150_accel_scan_masks;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &bmc150_accel_info;
 
index b41404b..8ca8041 100644 (file)
 
 #include "bmc150-accel.h"
 
-static const struct regmap_config bmc150_i2c_regmap_conf = {
-       .reg_bits = 8,
-       .val_bits = 8,
-};
-
 static int bmc150_accel_probe(struct i2c_client *client,
                              const struct i2c_device_id *id)
 {
@@ -43,7 +38,7 @@ static int bmc150_accel_probe(struct i2c_client *client,
                i2c_check_functionality(client->adapter,
                                        I2C_FUNC_SMBUS_READ_I2C_BLOCK);
 
-       regmap = devm_regmap_init_i2c(client, &bmc150_i2c_regmap_conf);
+       regmap = devm_regmap_init_i2c(client, &bmc150_regmap_conf);
        if (IS_ERR(regmap)) {
                dev_err(&client->dev, "Failed to initialize i2c regmap\n");
                return PTR_ERR(regmap);
index 16b66f2..006794a 100644 (file)
 
 #include "bmc150-accel.h"
 
-static const struct regmap_config bmc150_spi_regmap_conf = {
-       .reg_bits = 8,
-       .val_bits = 8,
-       .max_register = 0x3f,
-};
-
 static int bmc150_accel_probe(struct spi_device *spi)
 {
        struct regmap *regmap;
        const struct spi_device_id *id = spi_get_device_id(spi);
 
-       regmap = devm_regmap_init_spi(spi, &bmc150_spi_regmap_conf);
+       regmap = devm_regmap_init_spi(spi, &bmc150_regmap_conf);
        if (IS_ERR(regmap)) {
                dev_err(&spi->dev, "Failed to initialize spi regmap\n");
                return PTR_ERR(regmap);
index ba03359..38a8b11 100644 (file)
@@ -16,5 +16,6 @@ int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq,
                            const char *name, bool block_supported);
 int bmc150_accel_core_remove(struct device *dev);
 extern const struct dev_pm_ops bmc150_accel_pm_ops;
+extern const struct regmap_config bmc150_regmap_conf;
 
 #endif  /* _BMC150_ACCEL_H_ */
index edec1d0..bfe219a 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/acpi.h>
-#include <linux/gpio/consumer.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
 #include <linux/iio/iio.h>
@@ -115,6 +114,7 @@ enum kxcjk1013_axis {
        AXIS_X,
        AXIS_Y,
        AXIS_Z,
+       AXIS_MAX,
 };
 
 enum kxcjk1013_mode {
@@ -922,7 +922,7 @@ static const struct iio_event_spec kxcjk1013_event = {
                .realbits = 12,                                         \
                .storagebits = 16,                                      \
                .shift = 4,                                             \
-               .endianness = IIO_CPU,                                  \
+               .endianness = IIO_LE,                                   \
        },                                                              \
        .event_spec = &kxcjk1013_event,                         \
        .num_event_specs = 1                                            \
@@ -953,25 +953,23 @@ static const struct iio_info kxcjk1013_info = {
        .driver_module          = THIS_MODULE,
 };
 
+static const unsigned long kxcjk1013_scan_masks[] = {0x7, 0};
+
 static irqreturn_t kxcjk1013_trigger_handler(int irq, void *p)
 {
        struct iio_poll_func *pf = p;
        struct iio_dev *indio_dev = pf->indio_dev;
        struct kxcjk1013_data *data = iio_priv(indio_dev);
-       int bit, ret, i = 0;
+       int ret;
 
        mutex_lock(&data->mutex);
-
-       for_each_set_bit(bit, indio_dev->active_scan_mask,
-                        indio_dev->masklength) {
-               ret = kxcjk1013_get_acc_reg(data, bit);
-               if (ret < 0) {
-                       mutex_unlock(&data->mutex);
-                       goto err;
-               }
-               data->buffer[i++] = ret;
-       }
+       ret = i2c_smbus_read_i2c_block_data_or_emulated(data->client,
+                                                       KXCJK1013_REG_XOUT_L,
+                                                       AXIS_MAX * 2,
+                                                       (u8 *)data->buffer);
        mutex_unlock(&data->mutex);
+       if (ret < 0)
+               goto err;
 
        iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
                                           data->timestamp);
@@ -1204,6 +1202,7 @@ static int kxcjk1013_probe(struct i2c_client *client,
        indio_dev->dev.parent = &client->dev;
        indio_dev->channels = kxcjk1013_channels;
        indio_dev->num_channels = ARRAY_SIZE(kxcjk1013_channels);
+       indio_dev->available_scan_masks = kxcjk1013_scan_masks;
        indio_dev->name = name;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &kxcjk1013_info;
index 7f4994f..e225d3c 100644 (file)
@@ -6,6 +6,7 @@
  * MMA8453Q (10 bit)
  * MMA8652FC (12 bit)
  * MMA8653FC (10 bit)
+ * FXLS8471Q (14 bit)
  *
  * Copyright 2015 Martin Kepplinger <martin.kepplinger@theobroma-systems.com>
  * Copyright 2014 Peter Meerwald <pmeerw@pmeerw.net>
@@ -16,7 +17,7 @@
  *
  * 7-bit I2C slave address 0x1c/0x1d (pin selectable)
  *
- * TODO: orientation events, autosleep
+ * TODO: orientation events
  */
 
 #include <linux/module.h>
@@ -31,6 +32,7 @@
 #include <linux/delay.h>
 #include <linux/of_device.h>
 #include <linux/of_irq.h>
+#include <linux/pm_runtime.h>
 
 #define MMA8452_STATUS                         0x00
 #define  MMA8452_STATUS_DRDY                   (BIT(2) | BIT(1) | BIT(0))
@@ -91,6 +93,9 @@
 #define MMA8453_DEVICE_ID                      0x3a
 #define MMA8652_DEVICE_ID                      0x4a
 #define MMA8653_DEVICE_ID                      0x5a
+#define FXLS8471_DEVICE_ID                     0x6a
+
+#define MMA8452_AUTO_SUSPEND_DELAY_MS          2000
 
 struct mma8452_data {
        struct i2c_client *client;
@@ -172,6 +177,31 @@ static int mma8452_drdy(struct mma8452_data *data)
        return -EIO;
 }
 
+static int mma8452_set_runtime_pm_state(struct i2c_client *client, bool on)
+{
+#ifdef CONFIG_PM
+       int ret;
+
+       if (on) {
+               ret = pm_runtime_get_sync(&client->dev);
+       } else {
+               pm_runtime_mark_last_busy(&client->dev);
+               ret = pm_runtime_put_autosuspend(&client->dev);
+       }
+
+       if (ret < 0) {
+               dev_err(&client->dev,
+                       "failed to change power state to %d\n", on);
+               if (on)
+                       pm_runtime_put_noidle(&client->dev);
+
+               return ret;
+       }
+#endif
+
+       return 0;
+}
+
 static int mma8452_read(struct mma8452_data *data, __be16 buf[3])
 {
        int ret = mma8452_drdy(data);
@@ -179,8 +209,16 @@ static int mma8452_read(struct mma8452_data *data, __be16 buf[3])
        if (ret < 0)
                return ret;
 
-       return i2c_smbus_read_i2c_block_data(data->client, MMA8452_OUT_X,
-                                            3 * sizeof(__be16), (u8 *)buf);
+       ret = mma8452_set_runtime_pm_state(data->client, true);
+       if (ret)
+               return ret;
+
+       ret = i2c_smbus_read_i2c_block_data(data->client, MMA8452_OUT_X,
+                                           3 * sizeof(__be16), (u8 *)buf);
+
+       ret = mma8452_set_runtime_pm_state(data->client, false);
+
+       return ret;
 }
 
 static ssize_t mma8452_show_int_plus_micros(char *buf, const int (*vals)[2],
@@ -357,7 +395,8 @@ static int mma8452_read_raw(struct iio_dev *indio_dev,
                return IIO_VAL_INT_PLUS_MICRO;
        case IIO_CHAN_INFO_CALIBBIAS:
                ret = i2c_smbus_read_byte_data(data->client,
-                                             MMA8452_OFF_X + chan->scan_index);
+                                              MMA8452_OFF_X +
+                                              chan->scan_index);
                if (ret < 0)
                        return ret;
 
@@ -392,24 +431,47 @@ static int mma8452_active(struct mma8452_data *data)
                                         data->ctrl_reg1);
 }
 
+/* returns >0 if active, 0 if in standby and <0 on error */
+static int mma8452_is_active(struct mma8452_data *data)
+{
+       int reg;
+
+       reg = i2c_smbus_read_byte_data(data->client, MMA8452_CTRL_REG1);
+       if (reg < 0)
+               return reg;
+
+       return reg & MMA8452_CTRL_ACTIVE;
+}
+
 static int mma8452_change_config(struct mma8452_data *data, u8 reg, u8 val)
 {
        int ret;
+       int is_active;
 
        mutex_lock(&data->lock);
 
-       /* config can only be changed when in standby */
-       ret = mma8452_standby(data);
-       if (ret < 0)
+       is_active = mma8452_is_active(data);
+       if (is_active < 0) {
+               ret = is_active;
                goto fail;
+       }
+
+       /* config can only be changed when in standby */
+       if (is_active > 0) {
+               ret = mma8452_standby(data);
+               if (ret < 0)
+                       goto fail;
+       }
 
        ret = i2c_smbus_write_byte_data(data->client, reg, val);
        if (ret < 0)
                goto fail;
 
-       ret = mma8452_active(data);
-       if (ret < 0)
-               goto fail;
+       if (is_active > 0) {
+               ret = mma8452_active(data);
+               if (ret < 0)
+                       goto fail;
+       }
 
        ret = 0;
 fail:
@@ -418,7 +480,7 @@ fail:
        return ret;
 }
 
-/* returns >0 if in freefall mode, 0 if not or <0 if an error occured */
+/* returns >0 if in freefall mode, 0 if not or <0 if an error occurred */
 static int mma8452_freefall_mode_enabled(struct mma8452_data *data)
 {
        int val;
@@ -668,7 +730,8 @@ static int mma8452_read_event_config(struct iio_dev *indio_dev,
                if (ret < 0)
                        return ret;
 
-               return !!(ret & BIT(chan->scan_index + chip->ev_cfg_chan_shift));
+               return !!(ret & BIT(chan->scan_index +
+                                   chip->ev_cfg_chan_shift));
        default:
                return -EINVAL;
        }
@@ -682,7 +745,11 @@ static int mma8452_write_event_config(struct iio_dev *indio_dev,
 {
        struct mma8452_data *data = iio_priv(indio_dev);
        const struct mma_chip_info *chip = data->chip_info;
-       int val;
+       int val, ret;
+
+       ret = mma8452_set_runtime_pm_state(data->client, state);
+       if (ret)
+               return ret;
 
        switch (dir) {
        case IIO_EV_DIR_FALLING:
@@ -990,6 +1057,7 @@ enum {
        mma8453,
        mma8652,
        mma8653,
+       fxls8471,
 };
 
 static const struct mma_chip_info mma_chip_info_table[] = {
@@ -1003,7 +1071,7 @@ static const struct mma_chip_info mma_chip_info_table[] = {
                 * bit.
                 * The userspace interface uses m/s^2 and we declare micro units
                 * So scale factor for 12 bit here is given by:
-                *      g * N * 1000000 / 2048 for N = 2, 4, 8 and g=9.80665
+                *      g * N * 1000000 / 2048 for N = 2, 4, 8 and g=9.80665
                 */
                .mma_scales = { {0, 2394}, {0, 4788}, {0, 9577} },
                .ev_cfg = MMA8452_TRANSIENT_CFG,
@@ -1081,6 +1149,22 @@ static const struct mma_chip_info mma_chip_info_table[] = {
                .ev_ths_mask = MMA8452_FF_MT_THS_MASK,
                .ev_count = MMA8452_FF_MT_COUNT,
        },
+       [fxls8471] = {
+               .chip_id = FXLS8471_DEVICE_ID,
+               .channels = mma8451_channels,
+               .num_channels = ARRAY_SIZE(mma8451_channels),
+               .mma_scales = { {0, 2394}, {0, 4788}, {0, 9577} },
+               .ev_cfg = MMA8452_TRANSIENT_CFG,
+               .ev_cfg_ele = MMA8452_TRANSIENT_CFG_ELE,
+               .ev_cfg_chan_shift = 1,
+               .ev_src = MMA8452_TRANSIENT_SRC,
+               .ev_src_xe = MMA8452_TRANSIENT_SRC_XTRANSE,
+               .ev_src_ye = MMA8452_TRANSIENT_SRC_YTRANSE,
+               .ev_src_ze = MMA8452_TRANSIENT_SRC_ZTRANSE,
+               .ev_ths = MMA8452_TRANSIENT_THS,
+               .ev_ths_mask = MMA8452_TRANSIENT_THS_MASK,
+               .ev_count = MMA8452_TRANSIENT_COUNT,
+       },
 };
 
 static struct attribute *mma8452_attributes[] = {
@@ -1114,7 +1198,11 @@ static int mma8452_data_rdy_trigger_set_state(struct iio_trigger *trig,
 {
        struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
        struct mma8452_data *data = iio_priv(indio_dev);
-       int reg;
+       int reg, ret;
+
+       ret = mma8452_set_runtime_pm_state(data->client, state);
+       if (ret)
+               return ret;
 
        reg = i2c_smbus_read_byte_data(data->client, MMA8452_CTRL_REG4);
        if (reg < 0)
@@ -1206,6 +1294,7 @@ static const struct of_device_id mma8452_dt_ids[] = {
        { .compatible = "fsl,mma8453", .data = &mma_chip_info_table[mma8453] },
        { .compatible = "fsl,mma8652", .data = &mma_chip_info_table[mma8652] },
        { .compatible = "fsl,mma8653", .data = &mma_chip_info_table[mma8653] },
+       { .compatible = "fsl,fxls8471", .data = &mma_chip_info_table[fxls8471] },
        { }
 };
 MODULE_DEVICE_TABLE(of, mma8452_dt_ids);
@@ -1243,6 +1332,7 @@ static int mma8452_probe(struct i2c_client *client,
        case MMA8453_DEVICE_ID:
        case MMA8652_DEVICE_ID:
        case MMA8653_DEVICE_ID:
+       case FXLS8471_DEVICE_ID:
                if (ret == data->chip_info->chip_id)
                        break;
        default:
@@ -1340,6 +1430,15 @@ static int mma8452_probe(struct i2c_client *client,
                        goto buffer_cleanup;
        }
 
+       ret = pm_runtime_set_active(&client->dev);
+       if (ret < 0)
+               goto buffer_cleanup;
+
+       pm_runtime_enable(&client->dev);
+       pm_runtime_set_autosuspend_delay(&client->dev,
+                                        MMA8452_AUTO_SUSPEND_DELAY_MS);
+       pm_runtime_use_autosuspend(&client->dev);
+
        ret = iio_device_register(indio_dev);
        if (ret < 0)
                goto buffer_cleanup;
@@ -1364,6 +1463,11 @@ static int mma8452_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);
+       pm_runtime_put_noidle(&client->dev);
+
        iio_triggered_buffer_cleanup(indio_dev);
        mma8452_trigger_cleanup(indio_dev);
        mma8452_standby(iio_priv(indio_dev));
@@ -1371,6 +1475,45 @@ static int mma8452_remove(struct i2c_client *client)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int mma8452_runtime_suspend(struct device *dev)
+{
+       struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+       struct mma8452_data *data = iio_priv(indio_dev);
+       int ret;
+
+       mutex_lock(&data->lock);
+       ret = mma8452_standby(data);
+       mutex_unlock(&data->lock);
+       if (ret < 0) {
+               dev_err(&data->client->dev, "powering off device failed\n");
+               return -EAGAIN;
+       }
+
+       return 0;
+}
+
+static int mma8452_runtime_resume(struct device *dev)
+{
+       struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+       struct mma8452_data *data = iio_priv(indio_dev);
+       int ret, sleep_val;
+
+       ret = mma8452_active(data);
+       if (ret < 0)
+               return ret;
+
+       ret = mma8452_get_odr_index(data);
+       sleep_val = 1000 / mma8452_samp_freq[ret][0];
+       if (sleep_val < 20)
+               usleep_range(sleep_val * 1000, 20000);
+       else
+               msleep_interruptible(sleep_val);
+
+       return 0;
+}
+#endif
+
 #ifdef CONFIG_PM_SLEEP
 static int mma8452_suspend(struct device *dev)
 {
@@ -1383,18 +1526,21 @@ static int mma8452_resume(struct device *dev)
        return mma8452_active(iio_priv(i2c_get_clientdata(
                to_i2c_client(dev))));
 }
-
-static SIMPLE_DEV_PM_OPS(mma8452_pm_ops, mma8452_suspend, mma8452_resume);
-#define MMA8452_PM_OPS (&mma8452_pm_ops)
-#else
-#define MMA8452_PM_OPS NULL
 #endif
 
+static const struct dev_pm_ops mma8452_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(mma8452_suspend, mma8452_resume)
+       SET_RUNTIME_PM_OPS(mma8452_runtime_suspend,
+                          mma8452_runtime_resume, NULL)
+};
+
 static const struct i2c_device_id mma8452_id[] = {
+       { "mma8451", mma8451 },
        { "mma8452", mma8452 },
        { "mma8453", mma8453 },
        { "mma8652", mma8652 },
        { "mma8653", mma8653 },
+       { "fxls8471", fxls8471 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, mma8452_id);
@@ -1403,7 +1549,7 @@ static struct i2c_driver mma8452_driver = {
        .driver = {
                .name   = "mma8452",
                .of_match_table = of_match_ptr(mma8452_dt_ids),
-               .pm     = MMA8452_PM_OPS,
+               .pm     = &mma8452_pm_ops,
        },
        .probe = mma8452_probe,
        .remove = mma8452_remove,
index fa7d362..bb05f3e 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/acpi.h>
-#include <linux/gpio/consumer.h>
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 #include <linux/iio/events.h>
index e72e218..c23f47a 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/i2c.h>
 #include <linux/iio/iio.h>
 #include <linux/acpi.h>
-#include <linux/gpio/consumer.h>
 #include <linux/regmap.h>
 #include <linux/iio/sysfs.h>
 #include <linux/iio/trigger.h>
@@ -380,31 +379,6 @@ static const struct iio_trigger_ops mxc4005_trigger_ops = {
        .owner = THIS_MODULE,
 };
 
-static int mxc4005_gpio_probe(struct i2c_client *client,
-                             struct mxc4005_data *data)
-{
-       struct device *dev;
-       struct gpio_desc *gpio;
-       int ret;
-
-       if (!client)
-               return -EINVAL;
-
-       dev = &client->dev;
-
-       gpio = devm_gpiod_get_index(dev, "mxc4005_int", 0, GPIOD_IN);
-       if (IS_ERR(gpio)) {
-               dev_err(dev, "failed to get acpi gpio index\n");
-               return PTR_ERR(gpio);
-       }
-
-       ret = gpiod_to_irq(gpio);
-
-       dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret);
-
-       return ret;
-}
-
 static int mxc4005_chip_init(struct mxc4005_data *data)
 {
        int ret;
@@ -470,9 +444,6 @@ static int mxc4005_probe(struct i2c_client *client,
                return ret;
        }
 
-       if (client->irq < 0)
-               client->irq = mxc4005_gpio_probe(client, data);
-
        if (client->irq > 0) {
                data->dready_trig = devm_iio_trigger_alloc(&client->dev,
                                                           "%s-dev%d",
index 5d4a189..57f83a6 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/types.h>
 #include <linux/iio/common/st_sensors.h>
 
+#define H3LIS331DL_DRIVER_NAME         "h3lis331dl_accel"
 #define LIS3LV02DL_ACCEL_DEV_NAME      "lis3lv02dl_accel"
 #define LSM303DLHC_ACCEL_DEV_NAME      "lsm303dlhc_accel"
 #define LIS3DH_ACCEL_DEV_NAME          "lis3dh"
index a03a141..fee32e3 100644 (file)
@@ -39,6 +39,9 @@
 #define ST_ACCEL_FS_AVL_6G                     6
 #define ST_ACCEL_FS_AVL_8G                     8
 #define ST_ACCEL_FS_AVL_16G                    16
+#define ST_ACCEL_FS_AVL_100G                   100
+#define ST_ACCEL_FS_AVL_200G                   200
+#define ST_ACCEL_FS_AVL_400G                   400
 
 /* CUSTOM VALUES FOR SENSOR 1 */
 #define ST_ACCEL_1_WAI_EXP                     0x33
 #define ST_ACCEL_5_IG1_EN_MASK                 0x08
 #define ST_ACCEL_5_MULTIREAD_BIT               false
 
+/* CUSTOM VALUES FOR SENSOR 6 */
+#define ST_ACCEL_6_WAI_EXP                     0x32
+#define ST_ACCEL_6_ODR_ADDR                    0x20
+#define ST_ACCEL_6_ODR_MASK                    0x18
+#define ST_ACCEL_6_ODR_AVL_50HZ_VAL            0x00
+#define ST_ACCEL_6_ODR_AVL_100HZ_VAL           0x01
+#define ST_ACCEL_6_ODR_AVL_400HZ_VAL           0x02
+#define ST_ACCEL_6_ODR_AVL_1000HZ_VAL          0x03
+#define ST_ACCEL_6_PW_ADDR                     0x20
+#define ST_ACCEL_6_PW_MASK                     0x20
+#define ST_ACCEL_6_FS_ADDR                     0x23
+#define ST_ACCEL_6_FS_MASK                     0x30
+#define ST_ACCEL_6_FS_AVL_100_VAL              0x00
+#define ST_ACCEL_6_FS_AVL_200_VAL              0x01
+#define ST_ACCEL_6_FS_AVL_400_VAL              0x03
+#define ST_ACCEL_6_FS_AVL_100_GAIN             IIO_G_TO_M_S_2(49000)
+#define ST_ACCEL_6_FS_AVL_200_GAIN             IIO_G_TO_M_S_2(98000)
+#define ST_ACCEL_6_FS_AVL_400_GAIN             IIO_G_TO_M_S_2(195000)
+#define ST_ACCEL_6_BDU_ADDR                    0x23
+#define ST_ACCEL_6_BDU_MASK                    0x80
+#define ST_ACCEL_6_DRDY_IRQ_ADDR               0x22
+#define ST_ACCEL_6_DRDY_IRQ_INT1_MASK          0x02
+#define ST_ACCEL_6_DRDY_IRQ_INT2_MASK          0x10
+#define ST_ACCEL_6_IHL_IRQ_ADDR                        0x22
+#define ST_ACCEL_6_IHL_IRQ_MASK                        0x80
+#define ST_ACCEL_6_MULTIREAD_BIT               true
+
 static const struct iio_chan_spec st_accel_8bit_channels[] = {
        ST_SENSORS_LSM_CHANNELS(IIO_ACCEL,
                        BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
@@ -557,6 +587,68 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
                .multi_read_bit = ST_ACCEL_5_MULTIREAD_BIT,
                .bootime = 2, /* guess */
        },
+       {
+               .wai = ST_ACCEL_6_WAI_EXP,
+               .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
+               .sensors_supported = {
+                       [0] = H3LIS331DL_DRIVER_NAME,
+               },
+               .ch = (struct iio_chan_spec *)st_accel_12bit_channels,
+               .odr = {
+                       .addr = ST_ACCEL_6_ODR_ADDR,
+                       .mask = ST_ACCEL_6_ODR_MASK,
+                       .odr_avl = {
+                               { 50, ST_ACCEL_6_ODR_AVL_50HZ_VAL },
+                               { 100, ST_ACCEL_6_ODR_AVL_100HZ_VAL, },
+                               { 400, ST_ACCEL_6_ODR_AVL_400HZ_VAL, },
+                               { 1000, ST_ACCEL_6_ODR_AVL_1000HZ_VAL, },
+                       },
+               },
+               .pw = {
+                       .addr = ST_ACCEL_6_PW_ADDR,
+                       .mask = ST_ACCEL_6_PW_MASK,
+                       .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
+                       .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
+               },
+               .enable_axis = {
+                       .addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
+                       .mask = ST_SENSORS_DEFAULT_AXIS_MASK,
+               },
+               .fs = {
+                       .addr = ST_ACCEL_6_FS_ADDR,
+                       .mask = ST_ACCEL_6_FS_MASK,
+                       .fs_avl = {
+                               [0] = {
+                                       .num = ST_ACCEL_FS_AVL_100G,
+                                       .value = ST_ACCEL_6_FS_AVL_100_VAL,
+                                       .gain = ST_ACCEL_6_FS_AVL_100_GAIN,
+                               },
+                               [1] = {
+                                       .num = ST_ACCEL_FS_AVL_200G,
+                                       .value = ST_ACCEL_6_FS_AVL_200_VAL,
+                                       .gain = ST_ACCEL_6_FS_AVL_200_GAIN,
+                               },
+                               [2] = {
+                                       .num = ST_ACCEL_FS_AVL_400G,
+                                       .value = ST_ACCEL_6_FS_AVL_400_VAL,
+                                       .gain = ST_ACCEL_6_FS_AVL_400_GAIN,
+                               },
+                       },
+               },
+               .bdu = {
+                       .addr = ST_ACCEL_6_BDU_ADDR,
+                       .mask = ST_ACCEL_6_BDU_MASK,
+               },
+               .drdy_irq = {
+                       .addr = ST_ACCEL_6_DRDY_IRQ_ADDR,
+                       .mask_int1 = ST_ACCEL_6_DRDY_IRQ_INT1_MASK,
+                       .mask_int2 = ST_ACCEL_6_DRDY_IRQ_INT2_MASK,
+                       .addr_ihl = ST_ACCEL_6_IHL_IRQ_ADDR,
+                       .mask_ihl = ST_ACCEL_6_IHL_IRQ_MASK,
+               },
+               .multi_read_bit = ST_ACCEL_6_MULTIREAD_BIT,
+               .bootime = 2,
+       },
 };
 
 static int st_accel_read_raw(struct iio_dev *indio_dev,
index 294a32f..7333ee9 100644 (file)
@@ -76,6 +76,10 @@ static const struct of_device_id st_accel_of_match[] = {
                .compatible = "st,lis2dh12-accel",
                .data = LIS2DH12_ACCEL_DEV_NAME,
        },
+       {
+               .compatible = "st,h3lis331dl-accel",
+               .data = H3LIS331DL_DRIVER_NAME,
+       },
        {},
 };
 MODULE_DEVICE_TABLE(of, st_accel_of_match);
index 85fe7f7..e31023d 100644 (file)
@@ -11,7 +11,6 @@
  */
 
 #include <linux/acpi.h>
-#include <linux/gpio/consumer.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
index 5709d9e..300d955 100644 (file)
@@ -11,7 +11,6 @@
  */
 
 #include <linux/acpi.h>
-#include <linux/gpio/consumer.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
index af4aea7..5937030 100644 (file)
@@ -134,6 +134,7 @@ config AT91_ADC
 config AT91_SAMA5D2_ADC
        tristate "Atmel AT91 SAMA5D2 ADC"
        depends on ARCH_AT91 || COMPILE_TEST
+       depends on HAS_IOMEM
        help
          Say yes here to build support for Atmel SAMA5D2 ADC which is
          available on SAMA5D2 SoC family.
@@ -241,6 +242,16 @@ config LP8788_ADC
          To compile this driver as a module, choose M here: the module will be
          called lp8788_adc.
 
+config LPC18XX_ADC
+       tristate "NXP LPC18xx ADC driver"
+       depends on ARCH_LPC18XX || COMPILE_TEST
+       depends on OF && HAS_IOMEM
+       help
+         Say yes here to build support for NXP LPC18XX ADC.
+
+         To compile this driver as a module, choose M here: the module will be
+         called lpc18xx_adc.
+
 config MAX1027
        tristate "Maxim max1027 ADC driver"
        depends on SPI
index 0cb7921..38638d4 100644 (file)
@@ -25,6 +25,7 @@ obj-$(CONFIG_HI8435) += hi8435.o
 obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o
 obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o
 obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
+obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o
 obj-$(CONFIG_MAX1027) += max1027.o
 obj-$(CONFIG_MAX1363) += max1363.o
 obj-$(CONFIG_MCP320X) += mcp320x.o
index dbee13a..07adb10 100644 (file)
 #define        AT91_SAMA5D2_MR_PRESCAL(v)      ((v) << AT91_SAMA5D2_MR_PRESCAL_OFFSET)
 #define        AT91_SAMA5D2_MR_PRESCAL_OFFSET  8
 #define        AT91_SAMA5D2_MR_PRESCAL_MAX     0xff
+#define AT91_SAMA5D2_MR_PRESCAL_MASK   GENMASK(15, 8)
 /* Startup Time */
 #define        AT91_SAMA5D2_MR_STARTUP(v)      ((v) << 16)
+#define AT91_SAMA5D2_MR_STARTUP_MASK   GENMASK(19, 16)
 /* Analog Change */
 #define        AT91_SAMA5D2_MR_ANACH           BIT(23)
 /* Tracking Time */
 /* Last Converted Data Register */
 #define AT91_SAMA5D2_LCDR      0x20
 /* Interrupt Enable Register */
-#define AT91_SAMA5D2_IER               0x24
+#define AT91_SAMA5D2_IER       0x24
 /* Interrupt Disable Register */
-#define AT91_SAMA5D2_IDR               0x28
+#define AT91_SAMA5D2_IDR       0x28
 /* Interrupt Mask Register */
-#define AT91_SAMA5D2_IMR               0x2c
+#define AT91_SAMA5D2_IMR       0x2c
 /* Interrupt Status Register */
-#define AT91_SAMA5D2_ISR               0x30
+#define AT91_SAMA5D2_ISR       0x30
 /* Last Channel Trigger Mode Register */
 #define AT91_SAMA5D2_LCTMR     0x34
 /* Last Channel Compare Window Register */
 /* Overrun Status Register */
 #define AT91_SAMA5D2_OVER      0x3c
 /* Extended Mode Register */
-#define AT91_SAMA5D2_EMR               0x40
+#define AT91_SAMA5D2_EMR       0x40
 /* Compare Window Register */
-#define AT91_SAMA5D2_CWR               0x44
+#define AT91_SAMA5D2_CWR       0x44
 /* Channel Gain Register */
-#define AT91_SAMA5D2_CGR               0x48
+#define AT91_SAMA5D2_CGR       0x48
+
 /* Channel Offset Register */
-#define AT91_SAMA5D2_COR               0x4c
+#define AT91_SAMA5D2_COR       0x4c
+#define AT91_SAMA5D2_COR_DIFF_OFFSET   16
+
 /* Channel Data Register 0 */
 #define AT91_SAMA5D2_CDR0      0x50
 /* Analog Control Register */
-#define AT91_SAMA5D2_ACR               0x94
+#define AT91_SAMA5D2_ACR       0x94
 /* Touchscreen Mode Register */
 #define AT91_SAMA5D2_TSMR      0xb0
 /* Touchscreen X Position Register */
 /* Correction Select Register */
 #define AT91_SAMA5D2_COSR      0xd0
 /* Correction Value Register */
-#define AT91_SAMA5D2_CVR               0xd4
+#define AT91_SAMA5D2_CVR       0xd4
 /* Channel Error Correction Register */
 #define AT91_SAMA5D2_CECR      0xd8
 /* Write Protection Mode Register */
 /* Version Register */
 #define AT91_SAMA5D2_VERSION   0xfc
 
-#define AT91_AT91_SAMA5D2_CHAN(num, addr)                              \
+#define AT91_SAMA5D2_CHAN_SINGLE(num, addr)                            \
        {                                                               \
                .type = IIO_VOLTAGE,                                    \
                .channel = num,                                         \
                .indexed = 1,                                           \
        }
 
+#define AT91_SAMA5D2_CHAN_DIFF(num, num2, addr)                                \
+       {                                                               \
+               .type = IIO_VOLTAGE,                                    \
+               .differential = 1,                                      \
+               .channel = num,                                         \
+               .channel2 = num2,                                       \
+               .address = addr,                                        \
+               .scan_type = {                                          \
+                       .sign = 's',                                    \
+                       .realbits = 12,                                 \
+               },                                                      \
+               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),           \
+               .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
+               .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\
+               .datasheet_name = "CH"#num"-CH"#num2,                   \
+               .indexed = 1,                                           \
+       }
+
 #define at91_adc_readl(st, reg)                readl_relaxed(st->base + reg)
 #define at91_adc_writel(st, reg, val)  writel_relaxed(val, st->base + reg)
 
@@ -185,18 +208,24 @@ struct at91_adc_state {
 };
 
 static const struct iio_chan_spec at91_adc_channels[] = {
-       AT91_AT91_SAMA5D2_CHAN(0, 0x50),
-       AT91_AT91_SAMA5D2_CHAN(1, 0x54),
-       AT91_AT91_SAMA5D2_CHAN(2, 0x58),
-       AT91_AT91_SAMA5D2_CHAN(3, 0x5c),
-       AT91_AT91_SAMA5D2_CHAN(4, 0x60),
-       AT91_AT91_SAMA5D2_CHAN(5, 0x64),
-       AT91_AT91_SAMA5D2_CHAN(6, 0x68),
-       AT91_AT91_SAMA5D2_CHAN(7, 0x6c),
-       AT91_AT91_SAMA5D2_CHAN(8, 0x70),
-       AT91_AT91_SAMA5D2_CHAN(9, 0x74),
-       AT91_AT91_SAMA5D2_CHAN(10, 0x78),
-       AT91_AT91_SAMA5D2_CHAN(11, 0x7c),
+       AT91_SAMA5D2_CHAN_SINGLE(0, 0x50),
+       AT91_SAMA5D2_CHAN_SINGLE(1, 0x54),
+       AT91_SAMA5D2_CHAN_SINGLE(2, 0x58),
+       AT91_SAMA5D2_CHAN_SINGLE(3, 0x5c),
+       AT91_SAMA5D2_CHAN_SINGLE(4, 0x60),
+       AT91_SAMA5D2_CHAN_SINGLE(5, 0x64),
+       AT91_SAMA5D2_CHAN_SINGLE(6, 0x68),
+       AT91_SAMA5D2_CHAN_SINGLE(7, 0x6c),
+       AT91_SAMA5D2_CHAN_SINGLE(8, 0x70),
+       AT91_SAMA5D2_CHAN_SINGLE(9, 0x74),
+       AT91_SAMA5D2_CHAN_SINGLE(10, 0x78),
+       AT91_SAMA5D2_CHAN_SINGLE(11, 0x7c),
+       AT91_SAMA5D2_CHAN_DIFF(0, 1, 0x50),
+       AT91_SAMA5D2_CHAN_DIFF(2, 3, 0x58),
+       AT91_SAMA5D2_CHAN_DIFF(4, 5, 0x60),
+       AT91_SAMA5D2_CHAN_DIFF(6, 7, 0x68),
+       AT91_SAMA5D2_CHAN_DIFF(8, 9, 0x70),
+       AT91_SAMA5D2_CHAN_DIFF(10, 11, 0x78),
 };
 
 static unsigned at91_adc_startup_time(unsigned startup_time_min,
@@ -226,7 +255,7 @@ static unsigned at91_adc_startup_time(unsigned startup_time_min,
 static void at91_adc_setup_samp_freq(struct at91_adc_state *st, unsigned freq)
 {
        struct iio_dev *indio_dev = iio_priv_to_dev(st);
-       unsigned f_per, prescal, startup;
+       unsigned f_per, prescal, startup, mr;
 
        f_per = clk_get_rate(st->per_clk);
        prescal = (f_per / (2 * freq)) - 1;
@@ -234,10 +263,11 @@ static void at91_adc_setup_samp_freq(struct at91_adc_state *st, unsigned freq)
        startup = at91_adc_startup_time(st->soc_info.startup_time,
                                        freq / 1000);
 
-       at91_adc_writel(st, AT91_SAMA5D2_MR,
-                       AT91_SAMA5D2_MR_TRANSFER(2)
-                       | AT91_SAMA5D2_MR_STARTUP(startup)
-                       | AT91_SAMA5D2_MR_PRESCAL(prescal));
+       mr = at91_adc_readl(st, AT91_SAMA5D2_MR);
+       mr &= ~(AT91_SAMA5D2_MR_STARTUP_MASK | AT91_SAMA5D2_MR_PRESCAL_MASK);
+       mr |= AT91_SAMA5D2_MR_STARTUP(startup);
+       mr |= AT91_SAMA5D2_MR_PRESCAL(prescal);
+       at91_adc_writel(st, AT91_SAMA5D2_MR, mr);
 
        dev_dbg(&indio_dev->dev, "freq: %u, startup: %u, prescal: %u\n",
                freq, startup, prescal);
@@ -278,6 +308,7 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
                             int *val, int *val2, long mask)
 {
        struct at91_adc_state *st = iio_priv(indio_dev);
+       u32 cor = 0;
        int ret;
 
        switch (mask) {
@@ -286,6 +317,11 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
 
                st->chan = chan;
 
+               if (chan->differential)
+                       cor = (BIT(chan->channel) | BIT(chan->channel2)) <<
+                             AT91_SAMA5D2_COR_DIFF_OFFSET;
+
+               at91_adc_writel(st, AT91_SAMA5D2_COR, cor);
                at91_adc_writel(st, AT91_SAMA5D2_CHER, BIT(chan->channel));
                at91_adc_writel(st, AT91_SAMA5D2_IER, BIT(chan->channel));
                at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_START);
@@ -298,6 +334,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
 
                if (ret > 0) {
                        *val = st->conversion_value;
+                       if (chan->scan_type.sign == 's')
+                               *val = sign_extend32(*val, 11);
                        ret = IIO_VAL_INT;
                        st->conversion_done = false;
                }
@@ -310,6 +348,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
 
        case IIO_CHAN_INFO_SCALE:
                *val = st->vref_uv / 1000;
+               if (chan->differential)
+                       *val *= 2;
                *val2 = chan->scan_type.realbits;
                return IIO_VAL_FRACTIONAL_LOG2;
 
@@ -444,6 +484,12 @@ static int at91_adc_probe(struct platform_device *pdev)
 
        at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_SWRST);
        at91_adc_writel(st, AT91_SAMA5D2_IDR, 0xffffffff);
+       /*
+        * Transfer field must be set to 2 according to the datasheet and
+        * allows different analog settings for each channel.
+        */
+       at91_adc_writel(st, AT91_SAMA5D2_MR,
+                       AT91_SAMA5D2_MR_TRANSFER(2) | AT91_SAMA5D2_MR_ANACH);
 
        at91_adc_setup_samp_freq(st, st->soc_info.min_sample_rate);
 
index 65909d5..502f2fb 100644 (file)
@@ -185,9 +185,9 @@ static int ina2xx_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_SCALE:
                switch (chan->address) {
                case INA2XX_SHUNT_VOLTAGE:
-                       /* processed (mV) = raw*1000/shunt_div */
+                       /* processed (mV) = raw/shunt_div */
                        *val2 = chip->config->shunt_div;
-                       *val = 1000;
+                       *val = 1;
                        return IIO_VAL_FRACTIONAL;
 
                case INA2XX_BUS_VOLTAGE:
@@ -350,6 +350,23 @@ static ssize_t ina2xx_allow_async_readout_store(struct device *dev,
        return len;
 }
 
+/*
+ * Set current LSB to 1mA, shunt is in uOhms
+ * (equation 13 in datasheet). We hardcode a Current_LSB
+ * of 1.0 x10-6. The only remaining parameter is RShunt.
+ * There is no need to expose the CALIBRATION register
+ * to the user for now. But we need to reset this register
+ * if the user updates RShunt after driver init, e.g upon
+ * reading an EEPROM/Probe-type value.
+ */
+static int ina2xx_set_calibration(struct ina2xx_chip_info *chip)
+{
+       u16 regval = DIV_ROUND_CLOSEST(chip->config->calibration_factor,
+                                  chip->shunt_resistor);
+
+       return regmap_write(chip->regmap, INA2XX_CALIBRATION, regval);
+}
+
 static int set_shunt_resistor(struct ina2xx_chip_info *chip, unsigned int val)
 {
        if (val <= 0 || val > chip->config->calibration_factor)
@@ -385,6 +402,11 @@ static ssize_t ina2xx_shunt_resistor_store(struct device *dev,
        if (ret)
                return ret;
 
+       /* Update the Calibration register */
+       ret = ina2xx_set_calibration(chip);
+       if (ret)
+               return ret;
+
        return len;
 }
 
@@ -602,24 +624,11 @@ static const struct iio_info ina2xx_info = {
 /* Initialize the configuration and calibration registers. */
 static int ina2xx_init(struct ina2xx_chip_info *chip, unsigned int config)
 {
-       u16 regval;
-       int ret;
-
-       ret = regmap_write(chip->regmap, INA2XX_CONFIG, config);
+       int ret = regmap_write(chip->regmap, INA2XX_CONFIG, config);
        if (ret)
                return ret;
 
-       /*
-        * Set current LSB to 1mA, shunt is in uOhms
-        * (equation 13 in datasheet). We hardcode a Current_LSB
-        * of 1.0 x10-6. The only remaining parameter is RShunt.
-        * There is no need to expose the CALIBRATION register
-        * to the user for now.
-        */
-       regval = DIV_ROUND_CLOSEST(chip->config->calibration_factor,
-                                  chip->shunt_resistor);
-
-       return regmap_write(chip->regmap, INA2XX_CALIBRATION, regval);
+       return ina2xx_set_calibration(chip);
 }
 
 static int ina2xx_probe(struct i2c_client *client,
diff --git a/drivers/iio/adc/lpc18xx_adc.c b/drivers/iio/adc/lpc18xx_adc.c
new file mode 100644 (file)
index 0000000..3ef18f4
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * IIO ADC driver for NXP LPC18xx ADC
+ *
+ * Copyright (C) 2016 Joachim Eastwood <manabian@gmail.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 as
+ * published by the Free Software Foundation.
+ *
+ * UNSUPPORTED hardware features:
+ *  - Hardware triggers
+ *  - Burst mode
+ *  - Interrupts
+ *  - DMA
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/driver.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+
+/* LPC18XX ADC registers and bits */
+#define LPC18XX_ADC_CR                 0x000
+#define  LPC18XX_ADC_CR_CLKDIV_SHIFT   8
+#define  LPC18XX_ADC_CR_PDN            BIT(21)
+#define  LPC18XX_ADC_CR_START_NOW      (0x1 << 24)
+#define LPC18XX_ADC_GDR                        0x004
+
+/* Data register bits */
+#define LPC18XX_ADC_SAMPLE_SHIFT       6
+#define LPC18XX_ADC_SAMPLE_MASK                0x3ff
+#define LPC18XX_ADC_CONV_DONE          BIT(31)
+
+/* Clock should be 4.5 MHz or less */
+#define LPC18XX_ADC_CLK_TARGET         4500000
+
+struct lpc18xx_adc {
+       struct regulator *vref;
+       void __iomem *base;
+       struct device *dev;
+       struct mutex lock;
+       struct clk *clk;
+       u32 cr_reg;
+};
+
+#define LPC18XX_ADC_CHAN(_idx) {                               \
+       .type = IIO_VOLTAGE,                                    \
+       .indexed = 1,                                           \
+       .channel = _idx,                                        \
+       .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),           \
+       .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
+}
+
+static const struct iio_chan_spec lpc18xx_adc_iio_channels[] = {
+       LPC18XX_ADC_CHAN(0),
+       LPC18XX_ADC_CHAN(1),
+       LPC18XX_ADC_CHAN(2),
+       LPC18XX_ADC_CHAN(3),
+       LPC18XX_ADC_CHAN(4),
+       LPC18XX_ADC_CHAN(5),
+       LPC18XX_ADC_CHAN(6),
+       LPC18XX_ADC_CHAN(7),
+};
+
+static int lpc18xx_adc_read_chan(struct lpc18xx_adc *adc, unsigned int ch)
+{
+       int ret;
+       u32 reg;
+
+       reg = adc->cr_reg | BIT(ch) | LPC18XX_ADC_CR_START_NOW;
+       writel(reg, adc->base + LPC18XX_ADC_CR);
+
+       ret = readl_poll_timeout(adc->base + LPC18XX_ADC_GDR, reg,
+                                reg & LPC18XX_ADC_CONV_DONE, 3, 9);
+       if (ret) {
+               dev_warn(adc->dev, "adc read timed out\n");
+               return ret;
+       }
+
+       return (reg >> LPC18XX_ADC_SAMPLE_SHIFT) & LPC18XX_ADC_SAMPLE_MASK;
+}
+
+static int lpc18xx_adc_read_raw(struct iio_dev *indio_dev,
+                               struct iio_chan_spec const *chan,
+                               int *val, int *val2, long mask)
+{
+       struct lpc18xx_adc *adc = iio_priv(indio_dev);
+
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+               mutex_lock(&adc->lock);
+               *val = lpc18xx_adc_read_chan(adc, chan->channel);
+               mutex_unlock(&adc->lock);
+               if (*val < 0)
+                       return *val;
+
+               return IIO_VAL_INT;
+
+       case IIO_CHAN_INFO_SCALE:
+               *val = regulator_get_voltage(adc->vref) / 1000;
+               *val2 = 10;
+
+               return IIO_VAL_FRACTIONAL_LOG2;
+       }
+
+       return -EINVAL;
+}
+
+static const struct iio_info lpc18xx_adc_info = {
+       .read_raw = lpc18xx_adc_read_raw,
+       .driver_module = THIS_MODULE,
+};
+
+static int lpc18xx_adc_probe(struct platform_device *pdev)
+{
+       struct iio_dev *indio_dev;
+       struct lpc18xx_adc *adc;
+       struct resource *res;
+       unsigned int clkdiv;
+       unsigned long rate;
+       int ret;
+
+       indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc));
+       if (!indio_dev)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, indio_dev);
+       adc = iio_priv(indio_dev);
+       adc->dev = &pdev->dev;
+       mutex_init(&adc->lock);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       adc->base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(adc->base))
+               return PTR_ERR(adc->base);
+
+       adc->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(adc->clk)) {
+               dev_err(&pdev->dev, "error getting clock\n");
+               return PTR_ERR(adc->clk);
+       }
+
+       rate = clk_get_rate(adc->clk);
+       clkdiv = DIV_ROUND_UP(rate, LPC18XX_ADC_CLK_TARGET);
+
+       adc->vref = devm_regulator_get(&pdev->dev, "vref");
+       if (IS_ERR(adc->vref)) {
+               dev_err(&pdev->dev, "error getting regulator\n");
+               return PTR_ERR(adc->vref);
+       }
+
+       indio_dev->name = dev_name(&pdev->dev);
+       indio_dev->dev.parent = &pdev->dev;
+       indio_dev->info = &lpc18xx_adc_info;
+       indio_dev->modes = INDIO_DIRECT_MODE;
+       indio_dev->channels = lpc18xx_adc_iio_channels;
+       indio_dev->num_channels = ARRAY_SIZE(lpc18xx_adc_iio_channels);
+
+       ret = regulator_enable(adc->vref);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to enable regulator\n");
+               return ret;
+       }
+
+       ret = clk_prepare_enable(adc->clk);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to enable clock\n");
+               goto dis_reg;
+       }
+
+       adc->cr_reg = (clkdiv << LPC18XX_ADC_CR_CLKDIV_SHIFT) |
+                       LPC18XX_ADC_CR_PDN;
+       writel(adc->cr_reg, adc->base + LPC18XX_ADC_CR);
+
+       ret = iio_device_register(indio_dev);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to register device\n");
+               goto dis_clk;
+       }
+
+       return 0;
+
+dis_clk:
+       writel(0, adc->base + LPC18XX_ADC_CR);
+       clk_disable_unprepare(adc->clk);
+dis_reg:
+       regulator_disable(adc->vref);
+       return ret;
+}
+
+static int lpc18xx_adc_remove(struct platform_device *pdev)
+{
+       struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+       struct lpc18xx_adc *adc = iio_priv(indio_dev);
+
+       iio_device_unregister(indio_dev);
+
+       writel(0, adc->base + LPC18XX_ADC_CR);
+       clk_disable_unprepare(adc->clk);
+       regulator_disable(adc->vref);
+
+       return 0;
+}
+
+static const struct of_device_id lpc18xx_adc_match[] = {
+       { .compatible = "nxp,lpc1850-adc" },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, lpc18xx_adc_match);
+
+static struct platform_driver lpc18xx_adc_driver = {
+       .probe  = lpc18xx_adc_probe,
+       .remove = lpc18xx_adc_remove,
+       .driver = {
+               .name = "lpc18xx-adc",
+               .of_match_table = lpc18xx_adc_match,
+       },
+};
+module_platform_driver(lpc18xx_adc_driver);
+
+MODULE_DESCRIPTION("LPC18xx ADC driver");
+MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
+MODULE_LICENSE("GPL v2");
index 9c311c1..f9ad6c2 100644 (file)
@@ -159,6 +159,22 @@ static const struct rockchip_saradc_data rk3066_tsadc_data = {
        .clk_rate = 50000,
 };
 
+static const struct iio_chan_spec rockchip_rk3399_saradc_iio_channels[] = {
+       ADC_CHANNEL(0, "adc0"),
+       ADC_CHANNEL(1, "adc1"),
+       ADC_CHANNEL(2, "adc2"),
+       ADC_CHANNEL(3, "adc3"),
+       ADC_CHANNEL(4, "adc4"),
+       ADC_CHANNEL(5, "adc5"),
+};
+
+static const struct rockchip_saradc_data rk3399_saradc_data = {
+       .num_bits = 10,
+       .channels = rockchip_rk3399_saradc_iio_channels,
+       .num_channels = ARRAY_SIZE(rockchip_rk3399_saradc_iio_channels),
+       .clk_rate = 1000000,
+};
+
 static const struct of_device_id rockchip_saradc_match[] = {
        {
                .compatible = "rockchip,saradc",
@@ -166,6 +182,9 @@ static const struct of_device_id rockchip_saradc_match[] = {
        }, {
                .compatible = "rockchip,rk3066-tsadc",
                .data = &rk3066_tsadc_data,
+       }, {
+               .compatible = "rockchip,rk3399-saradc",
+               .data = &rk3399_saradc_data,
        },
        {},
 };
index e18bc67..7376496 100644 (file)
 
 int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf)
 {
-       u8 *addr;
+       u8 addr[3]; /* no ST sensor has more than 3 channels */
        int i, n = 0, len;
        struct st_sensor_data *sdata = iio_priv(indio_dev);
        unsigned int num_data_channels = sdata->num_data_channels;
        unsigned int byte_for_channel =
                        indio_dev->channels[0].scan_type.storagebits >> 3;
 
-       addr = kmalloc(num_data_channels, GFP_KERNEL);
-       if (!addr) {
-               len = -ENOMEM;
-               goto st_sensors_get_buffer_element_error;
-       }
-
        for (i = 0; i < num_data_channels; i++) {
                if (test_bit(i, indio_dev->active_scan_mask)) {
                        addr[n] = indio_dev->channels[i].address;
@@ -57,10 +51,8 @@ int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf)
                        u8 *rx_array;
                        rx_array = kmalloc(byte_for_channel * num_data_channels,
                                           GFP_KERNEL);
-                       if (!rx_array) {
-                               len = -ENOMEM;
-                               goto st_sensors_free_memory;
-                       }
+                       if (!rx_array)
+                               return -ENOMEM;
 
                        len = sdata->tf->read_multiple_byte(&sdata->tb,
                                sdata->dev, addr[0],
@@ -68,7 +60,7 @@ int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf)
                                rx_array, sdata->multiread_bit);
                        if (len < 0) {
                                kfree(rx_array);
-                               goto st_sensors_free_memory;
+                               return len;
                        }
 
                        for (i = 0; i < n * byte_for_channel; i++) {
@@ -87,17 +79,11 @@ int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf)
                        buf, sdata->multiread_bit);
                break;
        default:
-               len = -EINVAL;
-               goto st_sensors_free_memory;
-       }
-       if (len != byte_for_channel * n) {
-               len = -EIO;
-               goto st_sensors_free_memory;
+               return -EINVAL;
        }
+       if (len != byte_for_channel * n)
+               return -EIO;
 
-st_sensors_free_memory:
-       kfree(addr);
-st_sensors_get_buffer_element_error:
        return len;
 }
 EXPORT_SYMBOL(st_sensors_get_buffer_element);
index a995139..210db81 100644 (file)
@@ -154,6 +154,16 @@ config AD7303
          To compile this driver as module choose M here: the module will be called
          ad7303.
 
+config LPC18XX_DAC
+       tristate "NXP LPC18xx DAC driver"
+       depends on ARCH_LPC18XX || COMPILE_TEST
+       depends on OF && HAS_IOMEM
+       help
+         Say yes here to build support for NXP LPC18XX DAC.
+
+         To compile this driver as a module, choose M here: the module will be
+         called lpc18xx_dac.
+
 config M62332
        tristate "Mitsubishi M62332 DAC driver"
        depends on I2C
index 67b4842..420a15c 100644 (file)
@@ -17,6 +17,7 @@ obj-$(CONFIG_AD5764) += ad5764.o
 obj-$(CONFIG_AD5791) += ad5791.o
 obj-$(CONFIG_AD5686) += ad5686.o
 obj-$(CONFIG_AD7303) += ad7303.o
+obj-$(CONFIG_LPC18XX_DAC) += lpc18xx_dac.o
 obj-$(CONFIG_M62332) += m62332.o
 obj-$(CONFIG_MAX517) += max517.o
 obj-$(CONFIG_MAX5821) += max5821.o
diff --git a/drivers/iio/dac/lpc18xx_dac.c b/drivers/iio/dac/lpc18xx_dac.c
new file mode 100644 (file)
index 0000000..55d1456
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * IIO DAC driver for NXP LPC18xx DAC
+ *
+ * Copyright (C) 2016 Joachim Eastwood <manabian@gmail.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 as
+ * published by the Free Software Foundation.
+ *
+ * UNSUPPORTED hardware features:
+ *  - Interrupts
+ *  - DMA
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/driver.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+
+/* LPC18XX DAC registers and bits */
+#define LPC18XX_DAC_CR                 0x000
+#define  LPC18XX_DAC_CR_VALUE_SHIFT    6
+#define  LPC18XX_DAC_CR_VALUE_MASK     0x3ff
+#define  LPC18XX_DAC_CR_BIAS           BIT(16)
+#define LPC18XX_DAC_CTRL               0x004
+#define  LPC18XX_DAC_CTRL_DMA_ENA      BIT(3)
+
+struct lpc18xx_dac {
+       struct regulator *vref;
+       void __iomem *base;
+       struct mutex lock;
+       struct clk *clk;
+};
+
+static const struct iio_chan_spec lpc18xx_dac_iio_channels[] = {
+       {
+               .type = IIO_VOLTAGE,
+               .output = 1,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+                                     BIT(IIO_CHAN_INFO_SCALE),
+       },
+};
+
+static int lpc18xx_dac_read_raw(struct iio_dev *indio_dev,
+                               struct iio_chan_spec const *chan,
+                               int *val, int *val2, long mask)
+{
+       struct lpc18xx_dac *dac = iio_priv(indio_dev);
+       u32 reg;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+               reg = readl(dac->base + LPC18XX_DAC_CR);
+               *val = reg >> LPC18XX_DAC_CR_VALUE_SHIFT;
+               *val &= LPC18XX_DAC_CR_VALUE_MASK;
+
+               return IIO_VAL_INT;
+
+       case IIO_CHAN_INFO_SCALE:
+               *val = regulator_get_voltage(dac->vref) / 1000;
+               *val2 = 10;
+
+               return IIO_VAL_FRACTIONAL_LOG2;
+       }
+
+       return -EINVAL;
+}
+
+static int lpc18xx_dac_write_raw(struct iio_dev *indio_dev,
+                                struct iio_chan_spec const *chan,
+                                int val, int val2, long mask)
+{
+       struct lpc18xx_dac *dac = iio_priv(indio_dev);
+       u32 reg;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+               if (val < 0 || val > LPC18XX_DAC_CR_VALUE_MASK)
+                       return -EINVAL;
+
+               reg = LPC18XX_DAC_CR_BIAS;
+               reg |= val << LPC18XX_DAC_CR_VALUE_SHIFT;
+
+               mutex_lock(&dac->lock);
+               writel(reg, dac->base + LPC18XX_DAC_CR);
+               writel(LPC18XX_DAC_CTRL_DMA_ENA, dac->base + LPC18XX_DAC_CTRL);
+               mutex_unlock(&dac->lock);
+
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static const struct iio_info lpc18xx_dac_info = {
+       .read_raw = lpc18xx_dac_read_raw,
+       .write_raw = lpc18xx_dac_write_raw,
+       .driver_module = THIS_MODULE,
+};
+
+static int lpc18xx_dac_probe(struct platform_device *pdev)
+{
+       struct iio_dev *indio_dev;
+       struct lpc18xx_dac *dac;
+       struct resource *res;
+       int ret;
+
+       indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*dac));
+       if (!indio_dev)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, indio_dev);
+       dac = iio_priv(indio_dev);
+       mutex_init(&dac->lock);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       dac->base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(dac->base))
+               return PTR_ERR(dac->base);
+
+       dac->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(dac->clk)) {
+               dev_err(&pdev->dev, "error getting clock\n");
+               return PTR_ERR(dac->clk);
+       }
+
+       dac->vref = devm_regulator_get(&pdev->dev, "vref");
+       if (IS_ERR(dac->vref)) {
+               dev_err(&pdev->dev, "error getting regulator\n");
+               return PTR_ERR(dac->vref);
+       }
+
+       indio_dev->name = dev_name(&pdev->dev);
+       indio_dev->dev.parent = &pdev->dev;
+       indio_dev->info = &lpc18xx_dac_info;
+       indio_dev->modes = INDIO_DIRECT_MODE;
+       indio_dev->channels = lpc18xx_dac_iio_channels;
+       indio_dev->num_channels = ARRAY_SIZE(lpc18xx_dac_iio_channels);
+
+       ret = regulator_enable(dac->vref);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to enable regulator\n");
+               return ret;
+       }
+
+       ret = clk_prepare_enable(dac->clk);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to enable clock\n");
+               goto dis_reg;
+       }
+
+       writel(0, dac->base + LPC18XX_DAC_CTRL);
+       writel(0, dac->base + LPC18XX_DAC_CR);
+
+       ret = iio_device_register(indio_dev);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to register device\n");
+               goto dis_clk;
+       }
+
+       return 0;
+
+dis_clk:
+       clk_disable_unprepare(dac->clk);
+dis_reg:
+       regulator_disable(dac->vref);
+       return ret;
+}
+
+static int lpc18xx_dac_remove(struct platform_device *pdev)
+{
+       struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+       struct lpc18xx_dac *dac = iio_priv(indio_dev);
+
+       iio_device_unregister(indio_dev);
+
+       writel(0, dac->base + LPC18XX_DAC_CTRL);
+       clk_disable_unprepare(dac->clk);
+       regulator_disable(dac->vref);
+
+       return 0;
+}
+
+static const struct of_device_id lpc18xx_dac_match[] = {
+       { .compatible = "nxp,lpc1850-dac" },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, lpc18xx_dac_match);
+
+static struct platform_driver lpc18xx_dac_driver = {
+       .probe  = lpc18xx_dac_probe,
+       .remove = lpc18xx_dac_remove,
+       .driver = {
+               .name = "lpc18xx-dac",
+               .of_match_table = lpc18xx_dac_match,
+       },
+};
+module_platform_driver(lpc18xx_dac_driver);
+
+MODULE_DESCRIPTION("LPC18xx DAC driver");
+MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
+MODULE_LICENSE("GPL v2");
index bbce3b0..2493bb1 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/acpi.h>
-#include <linux/gpio/consumer.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
 #include <linux/iio/iio.h>
@@ -31,7 +30,6 @@
 #include "bmg160.h"
 
 #define BMG160_IRQ_NAME                "bmg160_event"
-#define BMG160_GPIO_NAME               "gpio_int"
 
 #define BMG160_REG_CHIP_ID             0x00
 #define BMG160_CHIP_ID_VAL             0x0F
@@ -116,6 +114,7 @@ enum bmg160_axis {
        AXIS_X,
        AXIS_Y,
        AXIS_Z,
+       AXIS_MAX,
 };
 
 static const struct {
@@ -733,6 +732,7 @@ static const struct iio_event_spec bmg160_event = {
                .sign = 's',                                            \
                .realbits = 16,                                 \
                .storagebits = 16,                                      \
+               .endianness = IIO_LE,                                   \
        },                                                              \
        .event_spec = &bmg160_event,                                    \
        .num_event_specs = 1                                            \
@@ -763,26 +763,23 @@ static const struct iio_info bmg160_info = {
        .driver_module          = THIS_MODULE,
 };
 
+static const unsigned long bmg160_accel_scan_masks[] = {
+                                       BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z),
+                                       0};
+
 static irqreturn_t bmg160_trigger_handler(int irq, void *p)
 {
        struct iio_poll_func *pf = p;
        struct iio_dev *indio_dev = pf->indio_dev;
        struct bmg160_data *data = iio_priv(indio_dev);
-       int bit, ret, i = 0;
-       unsigned int val;
+       int ret;
 
        mutex_lock(&data->mutex);
-       for_each_set_bit(bit, indio_dev->active_scan_mask,
-                        indio_dev->masklength) {
-               ret = regmap_bulk_read(data->regmap, BMG160_AXIS_TO_REG(bit),
-                                      &val, 2);
-               if (ret < 0) {
-                       mutex_unlock(&data->mutex);
-                       goto err;
-               }
-               data->buffer[i++] = ret;
-       }
+       ret = regmap_bulk_read(data->regmap, BMG160_REG_XOUT_L,
+                              data->buffer, AXIS_MAX * 2);
        mutex_unlock(&data->mutex);
+       if (ret < 0)
+               goto err;
 
        iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
                                           pf->timestamp);
@@ -955,29 +952,6 @@ static const struct iio_buffer_setup_ops bmg160_buffer_setup_ops = {
        .postdisable = bmg160_buffer_postdisable,
 };
 
-static int bmg160_gpio_probe(struct bmg160_data *data)
-
-{
-       struct device *dev;
-       struct gpio_desc *gpio;
-
-       dev = data->dev;
-
-       /* data ready gpio interrupt pin */
-       gpio = devm_gpiod_get_index(dev, BMG160_GPIO_NAME, 0, GPIOD_IN);
-       if (IS_ERR(gpio)) {
-               dev_err(dev, "acpi gpio get index failed\n");
-               return PTR_ERR(gpio);
-       }
-
-       data->irq = gpiod_to_irq(gpio);
-
-       dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio),
-               data->irq);
-
-       return 0;
-}
-
 static const char *bmg160_match_acpi_device(struct device *dev)
 {
        const struct acpi_device_id *id;
@@ -1019,12 +993,10 @@ int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq,
        indio_dev->channels = bmg160_channels;
        indio_dev->num_channels = ARRAY_SIZE(bmg160_channels);
        indio_dev->name = name;
+       indio_dev->available_scan_masks = bmg160_accel_scan_masks;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &bmg160_info;
 
-       if (data->irq <= 0)
-               bmg160_gpio_probe(data);
-
        if (data->irq > 0) {
                ret = devm_request_threaded_irq(dev,
                                                data->irq,
index f581256..5ee4e0d 100644 (file)
@@ -104,6 +104,19 @@ static int inv_mpu6050_deselect_bypass(struct i2c_adapter *adap,
        return 0;
 }
 
+static const char *inv_mpu_match_acpi_device(struct device *dev, int *chip_id)
+{
+       const struct acpi_device_id *id;
+
+       id = acpi_match_device(dev->driver->acpi_match_table, dev);
+       if (!id)
+               return NULL;
+
+       *chip_id = (int)id->driver_data;
+
+       return dev_name(dev);
+}
+
 /**
  *  inv_mpu_probe() - probe function.
  *  @client:          i2c client.
@@ -115,14 +128,25 @@ static int inv_mpu_probe(struct i2c_client *client,
                         const struct i2c_device_id *id)
 {
        struct inv_mpu6050_state *st;
-       int result;
-       const char *name = id ? id->name : NULL;
+       int result, chip_type;
        struct regmap *regmap;
+       const char *name;
 
        if (!i2c_check_functionality(client->adapter,
                                     I2C_FUNC_SMBUS_I2C_BLOCK))
                return -EOPNOTSUPP;
 
+       if (id) {
+               chip_type = (int)id->driver_data;
+               name = id->name;
+       } else if (ACPI_HANDLE(&client->dev)) {
+               name = inv_mpu_match_acpi_device(&client->dev, &chip_type);
+               if (!name)
+                       return -ENODEV;
+       } else {
+               return -ENOSYS;
+       }
+
        regmap = devm_regmap_init_i2c(client, &inv_mpu_regmap_config);
        if (IS_ERR(regmap)) {
                dev_err(&client->dev, "Failed to register i2c regmap %d\n",
@@ -131,7 +155,7 @@ static int inv_mpu_probe(struct i2c_client *client,
        }
 
        result = inv_mpu_core_probe(regmap, client->irq, name,
-                                   NULL, id->driver_data);
+                                   NULL, chip_type);
        if (result < 0)
                return result;
 
index dea6c43..7bcb8d8 100644 (file)
@@ -46,6 +46,7 @@ static int inv_mpu_probe(struct spi_device *spi)
        struct regmap *regmap;
        const struct spi_device_id *id = spi_get_device_id(spi);
        const char *name = id ? id->name : NULL;
+       const int chip_type = id ? id->driver_data : 0;
 
        regmap = devm_regmap_init_spi(spi, &inv_mpu_regmap_config);
        if (IS_ERR(regmap)) {
@@ -55,7 +56,7 @@ static int inv_mpu_probe(struct spi_device *spi)
        }
 
        return inv_mpu_core_probe(regmap, spi->irq, name,
-                                 inv_mpu_i2c_disable, id->driver_data);
+                                 inv_mpu_i2c_disable, chip_type);
 }
 
 static int inv_mpu_remove(struct spi_device *spi)
index e5306b4..2e7dd57 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/module.h>
 #include <linux/i2c.h>
 #include <linux/acpi.h>
-#include <linux/gpio/consumer.h>
 #include <linux/interrupt.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
index 70cb7eb..190a593 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/slab.h>
 #include <linux/anon_inodes.h>
 #include <linux/debugfs.h>
+#include <linux/mutex.h>
 #include <linux/iio/iio.h>
 #include "iio_core.h"
 #include "iio_core_trigger.h"
@@ -78,6 +79,7 @@ static const char * const iio_chan_type_name_spec[] = {
        [IIO_CONCENTRATION] = "concentration",
        [IIO_RESISTANCE] = "resistance",
        [IIO_PH] = "ph",
+       [IIO_UVINDEX] = "uvindex",
 };
 
 static const char * const iio_modifier_names[] = {
@@ -100,6 +102,7 @@ static const char * const iio_modifier_names[] = {
        [IIO_MOD_LIGHT_RED] = "red",
        [IIO_MOD_LIGHT_GREEN] = "green",
        [IIO_MOD_LIGHT_BLUE] = "blue",
+       [IIO_MOD_LIGHT_UV] = "uv",
        [IIO_MOD_QUATERNION] = "quaternion",
        [IIO_MOD_TEMP_AMBIENT] = "ambient",
        [IIO_MOD_TEMP_OBJECT] = "object",
@@ -1375,6 +1378,44 @@ void devm_iio_device_unregister(struct device *dev, struct iio_dev *indio_dev)
 }
 EXPORT_SYMBOL_GPL(devm_iio_device_unregister);
 
+/**
+ * iio_device_claim_direct_mode - Keep device in direct mode
+ * @indio_dev: the iio_dev associated with the device
+ *
+ * If the device is in direct mode it is guaranteed to stay
+ * that way until iio_device_release_direct_mode() is called.
+ *
+ * Use with iio_device_release_direct_mode()
+ *
+ * Returns: 0 on success, -EBUSY on failure
+ */
+int iio_device_claim_direct_mode(struct iio_dev *indio_dev)
+{
+       mutex_lock(&indio_dev->mlock);
+
+       if (iio_buffer_enabled(indio_dev)) {
+               mutex_unlock(&indio_dev->mlock);
+               return -EBUSY;
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(iio_device_claim_direct_mode);
+
+/**
+ * iio_device_release_direct_mode - releases claim on direct mode
+ * @indio_dev: the iio_dev associated with the device
+ *
+ * Release the claim. Device is no longer guaranteed to stay
+ * in direct mode.
+ *
+ * Use with iio_device_claim_direct_mode()
+ */
+void iio_device_release_direct_mode(struct iio_dev *indio_dev)
+{
+       mutex_unlock(&indio_dev->mlock);
+}
+EXPORT_SYMBOL_GPL(iio_device_release_direct_mode);
+
 subsys_initcall(iio_init);
 module_exit(iio_exit);
 
index 42d334b..9e847f8 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/regmap.h>
-#include <linux/gpio/consumer.h>
 #include <linux/iio/events.h>
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
index 12731d6..57b108c 100644 (file)
@@ -806,8 +806,7 @@ static int tsl2563_probe(struct i2c_client *client,
        return 0;
 
 fail:
-       cancel_delayed_work(&chip->poweroff_work);
-       flush_scheduled_work();
+       cancel_delayed_work_sync(&chip->poweroff_work);
        return err;
 }
 
index 9c5c9ef..48d127a 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/gpio.h>
 #include <linux/of_gpio.h>
 #include <linux/acpi.h>
+#include <linux/regulator/consumer.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
@@ -361,7 +362,6 @@ static const struct ak_def ak_def_array[AK_MAX_TYPE] = {
 struct ak8975_data {
        struct i2c_client       *client;
        const struct ak_def     *def;
-       struct attribute_group  attrs;
        struct mutex            lock;
        u8                      asa[3];
        long                    raw_to_gauss[3];
@@ -370,8 +370,40 @@ struct ak8975_data {
        wait_queue_head_t       data_ready_queue;
        unsigned long           flags;
        u8                      cntl_cache;
+       struct regulator        *vdd;
 };
 
+/* Enable attached power regulator if any. */
+static int ak8975_power_on(struct i2c_client *client)
+{
+       const struct iio_dev *indio_dev = i2c_get_clientdata(client);
+       struct ak8975_data *data = iio_priv(indio_dev);
+       int ret;
+
+       data->vdd = devm_regulator_get(&client->dev, "vdd");
+       if (IS_ERR_OR_NULL(data->vdd)) {
+               ret = PTR_ERR(data->vdd);
+               if (ret == -ENODEV)
+                       ret = 0;
+       } else {
+               ret = regulator_enable(data->vdd);
+       }
+
+       if (ret)
+               dev_err(&client->dev, "failed to enable Vdd supply: %d\n", ret);
+       return ret;
+}
+
+/* Disable attached power regulator if any. */
+static void ak8975_power_off(const struct i2c_client *client)
+{
+       const struct iio_dev *indio_dev = i2c_get_clientdata(client);
+       const struct ak8975_data *data = iio_priv(indio_dev);
+
+       if (!IS_ERR_OR_NULL(data->vdd))
+               regulator_disable(data->vdd);
+}
+
 /*
  * Return 0 if the i2c device is the one we expect.
  * return a negative error number otherwise
@@ -774,8 +806,11 @@ static int ak8975_probe(struct i2c_client *client,
        if (id) {
                chipset = (enum asahi_compass_chipset)(id->driver_data);
                name = id->name;
-       } else if (ACPI_HANDLE(&client->dev))
+       } else if (ACPI_HANDLE(&client->dev)) {
                name = ak8975_match_acpi_device(&client->dev, &chipset);
+               if (!name)
+                       return -ENODEV;
+       }
        else
                return -ENOSYS;
 
@@ -786,10 +821,15 @@ static int ak8975_probe(struct i2c_client *client,
        }
 
        data->def = &ak_def_array[chipset];
+
+       err = ak8975_power_on(client);
+       if (err)
+               return err;
+
        err = ak8975_who_i_am(client, data->def->type);
        if (err < 0) {
                dev_err(&client->dev, "Unexpected device\n");
-               return err;
+               goto power_off;
        }
        dev_dbg(&client->dev, "Asahi compass chip %s\n", name);
 
@@ -797,7 +837,7 @@ static int ak8975_probe(struct i2c_client *client,
        err = ak8975_setup(client);
        if (err < 0) {
                dev_err(&client->dev, "%s initialization fails\n", name);
-               return err;
+               goto power_off;
        }
 
        mutex_init(&data->lock);
@@ -807,7 +847,26 @@ static int ak8975_probe(struct i2c_client *client,
        indio_dev->info = &ak8975_info;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->name = name;
-       return devm_iio_device_register(&client->dev, indio_dev);
+
+       err = iio_device_register(indio_dev);
+       if (err)
+               goto power_off;
+
+       return 0;
+
+power_off:
+       ak8975_power_off(client);
+       return err;
+}
+
+static int ak8975_remove(struct i2c_client *client)
+{
+       struct iio_dev *indio_dev = i2c_get_clientdata(client);
+
+       iio_device_unregister(indio_dev);
+       ak8975_power_off(client);
+
+       return 0;
 }
 
 static const struct i2c_device_id ak8975_id[] = {
@@ -841,6 +900,7 @@ static struct i2c_driver ak8975_driver = {
                .acpi_match_table = ACPI_PTR(ak_acpi_match),
        },
        .probe          = ak8975_probe,
+       .remove         = ak8975_remove,
        .id_table       = ak8975_id,
 };
 module_i2c_driver(ak8975_driver);
index ffcb75e..0e9da18 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/acpi.h>
-#include <linux/gpio/consumer.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
 #include <linux/iio/iio.h>
index ffc735c..7ea069b 100644 (file)
@@ -5,6 +5,24 @@
 
 menu "Digital potentiometers"
 
+config MCP4131
+       tristate "Microchip MCP413X/414X/415X/416X/423X/424X/425X/426X Digital Potentiometer driver"
+       depends on SPI
+       help
+         Say yes here to build support for the Microchip
+         MCP4131, MCP4132,
+         MCP4141, MCP4142,
+         MCP4151, MCP4152,
+         MCP4161, MCP4162,
+         MCP4231, MCP4232,
+         MCP4241, MCP4242,
+         MCP4251, MCP4252,
+         MCP4261, MCP4262,
+         digital potentiomenter chips.
+
+         To compile this driver as a module, choose M here: the
+         module will be called mcp4131.
+
 config MCP4531
        tristate "Microchip MCP45xx/MCP46xx Digital Potentiometer driver"
        depends on I2C
index b563b49..91a80f8 100644 (file)
@@ -3,5 +3,6 @@
 #
 
 # When adding new entries keep the list in alphabetical order
+obj-$(CONFIG_MCP4131) += mcp4131.o
 obj-$(CONFIG_MCP4531) += mcp4531.o
 obj-$(CONFIG_TPL0102) += tpl0102.o
diff --git a/drivers/iio/potentiometer/mcp4131.c b/drivers/iio/potentiometer/mcp4131.c
new file mode 100644 (file)
index 0000000..4e7e2c6
--- /dev/null
@@ -0,0 +1,494 @@
+/*
+ * Industrial I/O driver for Microchip digital potentiometers
+ *
+ * Copyright (c) 2016 Slawomir Stepien
+ * Based on: Peter Rosin's code from mcp4531.c
+ *
+ * Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/22060b.pdf
+ *
+ * DEVID       #Wipers #Positions      Resistor Opts (kOhm)
+ * mcp4131     1       129             5, 10, 50, 100
+ * mcp4132     1       129             5, 10, 50, 100
+ * mcp4141     1       129             5, 10, 50, 100
+ * mcp4142     1       129             5, 10, 50, 100
+ * mcp4151     1       257             5, 10, 50, 100
+ * mcp4152     1       257             5, 10, 50, 100
+ * mcp4161     1       257             5, 10, 50, 100
+ * mcp4162     1       257             5, 10, 50, 100
+ * mcp4231     2       129             5, 10, 50, 100
+ * mcp4232     2       129             5, 10, 50, 100
+ * mcp4241     2       129             5, 10, 50, 100
+ * mcp4242     2       129             5, 10, 50, 100
+ * mcp4251     2       257             5, 10, 50, 100
+ * mcp4252     2       257             5, 10, 50, 100
+ * mcp4261     2       257             5, 10, 50, 100
+ * mcp4262     2       257             5, 10, 50, 100
+ *
+ * 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.
+ */
+
+/*
+ * TODO:
+ * 1. Write wiper setting to EEPROM for EEPROM capable models.
+ */
+
+#include <linux/cache.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/types.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/spi/spi.h>
+
+#define MCP4131_WRITE          (0x00 << 2)
+#define MCP4131_READ           (0x03 << 2)
+
+#define MCP4131_WIPER_SHIFT    4
+#define MCP4131_CMDERR(r)      ((r[0]) & 0x02)
+#define MCP4131_RAW(r)         ((r[0]) == 0xff ? 0x100 : (r[1]))
+
+struct mcp4131_cfg {
+       int wipers;
+       int max_pos;
+       int kohms;
+};
+
+enum mcp4131_type {
+       MCP413x_502 = 0,
+       MCP413x_103,
+       MCP413x_503,
+       MCP413x_104,
+       MCP414x_502,
+       MCP414x_103,
+       MCP414x_503,
+       MCP414x_104,
+       MCP415x_502,
+       MCP415x_103,
+       MCP415x_503,
+       MCP415x_104,
+       MCP416x_502,
+       MCP416x_103,
+       MCP416x_503,
+       MCP416x_104,
+       MCP423x_502,
+       MCP423x_103,
+       MCP423x_503,
+       MCP423x_104,
+       MCP424x_502,
+       MCP424x_103,
+       MCP424x_503,
+       MCP424x_104,
+       MCP425x_502,
+       MCP425x_103,
+       MCP425x_503,
+       MCP425x_104,
+       MCP426x_502,
+       MCP426x_103,
+       MCP426x_503,
+       MCP426x_104,
+};
+
+static const struct mcp4131_cfg mcp4131_cfg[] = {
+       [MCP413x_502] = { .wipers = 1, .max_pos = 128, .kohms =   5, },
+       [MCP413x_103] = { .wipers = 1, .max_pos = 128, .kohms =  10, },
+       [MCP413x_503] = { .wipers = 1, .max_pos = 128, .kohms =  50, },
+       [MCP413x_104] = { .wipers = 1, .max_pos = 128, .kohms = 100, },
+       [MCP414x_502] = { .wipers = 1, .max_pos = 128, .kohms =   5, },
+       [MCP414x_103] = { .wipers = 1, .max_pos = 128, .kohms =  10, },
+       [MCP414x_503] = { .wipers = 1, .max_pos = 128, .kohms =  50, },
+       [MCP414x_104] = { .wipers = 1, .max_pos = 128, .kohms = 100, },
+       [MCP415x_502] = { .wipers = 1, .max_pos = 256, .kohms =   5, },
+       [MCP415x_103] = { .wipers = 1, .max_pos = 256, .kohms =  10, },
+       [MCP415x_503] = { .wipers = 1, .max_pos = 256, .kohms =  50, },
+       [MCP415x_104] = { .wipers = 1, .max_pos = 256, .kohms = 100, },
+       [MCP416x_502] = { .wipers = 1, .max_pos = 256, .kohms =   5, },
+       [MCP416x_103] = { .wipers = 1, .max_pos = 256, .kohms =  10, },
+       [MCP416x_503] = { .wipers = 1, .max_pos = 256, .kohms =  50, },
+       [MCP416x_104] = { .wipers = 1, .max_pos = 256, .kohms = 100, },
+       [MCP423x_502] = { .wipers = 2, .max_pos = 128, .kohms =   5, },
+       [MCP423x_103] = { .wipers = 2, .max_pos = 128, .kohms =  10, },
+       [MCP423x_503] = { .wipers = 2, .max_pos = 128, .kohms =  50, },
+       [MCP423x_104] = { .wipers = 2, .max_pos = 128, .kohms = 100, },
+       [MCP424x_502] = { .wipers = 2, .max_pos = 128, .kohms =   5, },
+       [MCP424x_103] = { .wipers = 2, .max_pos = 128, .kohms =  10, },
+       [MCP424x_503] = { .wipers = 2, .max_pos = 128, .kohms =  50, },
+       [MCP424x_104] = { .wipers = 2, .max_pos = 128, .kohms = 100, },
+       [MCP425x_502] = { .wipers = 2, .max_pos = 256, .kohms =   5, },
+       [MCP425x_103] = { .wipers = 2, .max_pos = 256, .kohms =  10, },
+       [MCP425x_503] = { .wipers = 2, .max_pos = 256, .kohms =  50, },
+       [MCP425x_104] = { .wipers = 2, .max_pos = 256, .kohms = 100, },
+       [MCP426x_502] = { .wipers = 2, .max_pos = 256, .kohms =   5, },
+       [MCP426x_103] = { .wipers = 2, .max_pos = 256, .kohms =  10, },
+       [MCP426x_503] = { .wipers = 2, .max_pos = 256, .kohms =  50, },
+       [MCP426x_104] = { .wipers = 2, .max_pos = 256, .kohms = 100, },
+};
+
+struct mcp4131_data {
+       struct spi_device *spi;
+       const struct mcp4131_cfg *cfg;
+       struct mutex lock;
+       u8 buf[2] ____cacheline_aligned;
+};
+
+#define MCP4131_CHANNEL(ch) {                                  \
+       .type = IIO_RESISTANCE,                                 \
+       .indexed = 1,                                           \
+       .output = 1,                                            \
+       .channel = (ch),                                        \
+       .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),           \
+       .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),   \
+}
+
+static const struct iio_chan_spec mcp4131_channels[] = {
+       MCP4131_CHANNEL(0),
+       MCP4131_CHANNEL(1),
+};
+
+static int mcp4131_read(struct spi_device *spi, void *buf, size_t len)
+{
+       struct spi_transfer t = {
+               .tx_buf = buf, /* We need to send addr, cmd and 12 bits */
+               .rx_buf = buf,
+               .len = len,
+       };
+       struct spi_message m;
+
+       spi_message_init(&m);
+       spi_message_add_tail(&t, &m);
+
+       return spi_sync(spi, &m);
+}
+
+static int mcp4131_read_raw(struct iio_dev *indio_dev,
+                           struct iio_chan_spec const *chan,
+                           int *val, int *val2, long mask)
+{
+       int err;
+       struct mcp4131_data *data = iio_priv(indio_dev);
+       int address = chan->channel;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+               mutex_lock(&data->lock);
+
+               data->buf[0] = (address << MCP4131_WIPER_SHIFT) | MCP4131_READ;
+               data->buf[1] = 0;
+
+               err = mcp4131_read(data->spi, data->buf, 2);
+               if (err) {
+                       mutex_unlock(&data->lock);
+                       return err;
+               }
+
+               /* Error, bad address/command combination */
+               if (!MCP4131_CMDERR(data->buf)) {
+                       mutex_unlock(&data->lock);
+                       return -EIO;
+               }
+
+               *val = MCP4131_RAW(data->buf);
+               mutex_unlock(&data->lock);
+
+               return IIO_VAL_INT;
+
+       case IIO_CHAN_INFO_SCALE:
+               *val = 1000 * data->cfg->kohms;
+               *val2 = data->cfg->max_pos;
+               return IIO_VAL_FRACTIONAL;
+       }
+
+       return -EINVAL;
+}
+
+static int mcp4131_write_raw(struct iio_dev *indio_dev,
+                            struct iio_chan_spec const *chan,
+                            int val, int val2, long mask)
+{
+       int err;
+       struct mcp4131_data *data = iio_priv(indio_dev);
+       int address = chan->channel << MCP4131_WIPER_SHIFT;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+               if (val > data->cfg->max_pos || val < 0)
+                       return -EINVAL;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       mutex_lock(&data->lock);
+
+       data->buf[0] = address << MCP4131_WIPER_SHIFT;
+       data->buf[0] |= MCP4131_WRITE | (val >> 8);
+       data->buf[1] = val & 0xFF; /* 8 bits here */
+
+       err = spi_write(data->spi, data->buf, 2);
+       mutex_unlock(&data->lock);
+
+       return err;
+}
+
+static const struct iio_info mcp4131_info = {
+       .read_raw = mcp4131_read_raw,
+       .write_raw = mcp4131_write_raw,
+       .driver_module = THIS_MODULE,
+};
+
+static int mcp4131_probe(struct spi_device *spi)
+{
+       int err;
+       struct device *dev = &spi->dev;
+       unsigned long devid = spi_get_device_id(spi)->driver_data;
+       struct mcp4131_data *data;
+       struct iio_dev *indio_dev;
+
+       indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
+       if (!indio_dev)
+               return -ENOMEM;
+
+       data = iio_priv(indio_dev);
+       spi_set_drvdata(spi, indio_dev);
+       data->spi = spi;
+       data->cfg = &mcp4131_cfg[devid];
+
+       mutex_init(&data->lock);
+
+       indio_dev->dev.parent = dev;
+       indio_dev->info = &mcp4131_info;
+       indio_dev->channels = mcp4131_channels;
+       indio_dev->num_channels = data->cfg->wipers;
+       indio_dev->name = spi_get_device_id(spi)->name;
+
+       err = devm_iio_device_register(dev, indio_dev);
+       if (err) {
+               dev_info(&spi->dev, "Unable to register %s\n", indio_dev->name);
+               return err;
+       }
+
+       return 0;
+}
+
+#if defined(CONFIG_OF)
+static const struct of_device_id mcp4131_dt_ids[] = {
+       { .compatible = "microchip,mcp4131-502",
+               .data = &mcp4131_cfg[MCP413x_502] },
+       { .compatible = "microchip,mcp4131-103",
+               .data = &mcp4131_cfg[MCP413x_103] },
+       { .compatible = "microchip,mcp4131-503",
+               .data = &mcp4131_cfg[MCP413x_503] },
+       { .compatible = "microchip,mcp4131-104",
+               .data = &mcp4131_cfg[MCP413x_104] },
+       { .compatible = "microchip,mcp4132-502",
+               .data = &mcp4131_cfg[MCP413x_502] },
+       { .compatible = "microchip,mcp4132-103",
+               .data = &mcp4131_cfg[MCP413x_103] },
+       { .compatible = "microchip,mcp4132-503",
+               .data = &mcp4131_cfg[MCP413x_503] },
+       { .compatible = "microchip,mcp4132-104",
+               .data = &mcp4131_cfg[MCP413x_104] },
+       { .compatible = "microchip,mcp4141-502",
+               .data = &mcp4131_cfg[MCP414x_502] },
+       { .compatible = "microchip,mcp4141-103",
+               .data = &mcp4131_cfg[MCP414x_103] },
+       { .compatible = "microchip,mcp4141-503",
+               .data = &mcp4131_cfg[MCP414x_503] },
+       { .compatible = "microchip,mcp4141-104",
+               .data = &mcp4131_cfg[MCP414x_104] },
+       { .compatible = "microchip,mcp4142-502",
+               .data = &mcp4131_cfg[MCP414x_502] },
+       { .compatible = "microchip,mcp4142-103",
+               .data = &mcp4131_cfg[MCP414x_103] },
+       { .compatible = "microchip,mcp4142-503",
+               .data = &mcp4131_cfg[MCP414x_503] },
+       { .compatible = "microchip,mcp4142-104",
+               .data = &mcp4131_cfg[MCP414x_104] },
+       { .compatible = "microchip,mcp4151-502",
+               .data = &mcp4131_cfg[MCP415x_502] },
+       { .compatible = "microchip,mcp4151-103",
+               .data = &mcp4131_cfg[MCP415x_103] },
+       { .compatible = "microchip,mcp4151-503",
+               .data = &mcp4131_cfg[MCP415x_503] },
+       { .compatible = "microchip,mcp4151-104",
+               .data = &mcp4131_cfg[MCP415x_104] },
+       { .compatible = "microchip,mcp4152-502",
+               .data = &mcp4131_cfg[MCP415x_502] },
+       { .compatible = "microchip,mcp4152-103",
+               .data = &mcp4131_cfg[MCP415x_103] },
+       { .compatible = "microchip,mcp4152-503",
+               .data = &mcp4131_cfg[MCP415x_503] },
+       { .compatible = "microchip,mcp4152-104",
+               .data = &mcp4131_cfg[MCP415x_104] },
+       { .compatible = "microchip,mcp4161-502",
+               .data = &mcp4131_cfg[MCP416x_502] },
+       { .compatible = "microchip,mcp4161-103",
+               .data = &mcp4131_cfg[MCP416x_103] },
+       { .compatible = "microchip,mcp4161-503",
+               .data = &mcp4131_cfg[MCP416x_503] },
+       { .compatible = "microchip,mcp4161-104",
+               .data = &mcp4131_cfg[MCP416x_104] },
+       { .compatible = "microchip,mcp4162-502",
+               .data = &mcp4131_cfg[MCP416x_502] },
+       { .compatible = "microchip,mcp4162-103",
+               .data = &mcp4131_cfg[MCP416x_103] },
+       { .compatible = "microchip,mcp4162-503",
+               .data = &mcp4131_cfg[MCP416x_503] },
+       { .compatible = "microchip,mcp4162-104",
+               .data = &mcp4131_cfg[MCP416x_104] },
+       { .compatible = "microchip,mcp4231-502",
+               .data = &mcp4131_cfg[MCP423x_502] },
+       { .compatible = "microchip,mcp4231-103",
+               .data = &mcp4131_cfg[MCP423x_103] },
+       { .compatible = "microchip,mcp4231-503",
+               .data = &mcp4131_cfg[MCP423x_503] },
+       { .compatible = "microchip,mcp4231-104",
+               .data = &mcp4131_cfg[MCP423x_104] },
+       { .compatible = "microchip,mcp4232-502",
+               .data = &mcp4131_cfg[MCP423x_502] },
+       { .compatible = "microchip,mcp4232-103",
+               .data = &mcp4131_cfg[MCP423x_103] },
+       { .compatible = "microchip,mcp4232-503",
+               .data = &mcp4131_cfg[MCP423x_503] },
+       { .compatible = "microchip,mcp4232-104",
+               .data = &mcp4131_cfg[MCP423x_104] },
+       { .compatible = "microchip,mcp4241-502",
+               .data = &mcp4131_cfg[MCP424x_502] },
+       { .compatible = "microchip,mcp4241-103",
+               .data = &mcp4131_cfg[MCP424x_103] },
+       { .compatible = "microchip,mcp4241-503",
+               .data = &mcp4131_cfg[MCP424x_503] },
+       { .compatible = "microchip,mcp4241-104",
+               .data = &mcp4131_cfg[MCP424x_104] },
+       { .compatible = "microchip,mcp4242-502",
+               .data = &mcp4131_cfg[MCP424x_502] },
+       { .compatible = "microchip,mcp4242-103",
+               .data = &mcp4131_cfg[MCP424x_103] },
+       { .compatible = "microchip,mcp4242-503",
+               .data = &mcp4131_cfg[MCP424x_503] },
+       { .compatible = "microchip,mcp4242-104",
+               .data = &mcp4131_cfg[MCP424x_104] },
+       { .compatible = "microchip,mcp4251-502",
+               .data = &mcp4131_cfg[MCP425x_502] },
+       { .compatible = "microchip,mcp4251-103",
+               .data = &mcp4131_cfg[MCP425x_103] },
+       { .compatible = "microchip,mcp4251-503",
+               .data = &mcp4131_cfg[MCP425x_503] },
+       { .compatible = "microchip,mcp4251-104",
+               .data = &mcp4131_cfg[MCP425x_104] },
+       { .compatible = "microchip,mcp4252-502",
+               .data = &mcp4131_cfg[MCP425x_502] },
+       { .compatible = "microchip,mcp4252-103",
+               .data = &mcp4131_cfg[MCP425x_103] },
+       { .compatible = "microchip,mcp4252-503",
+               .data = &mcp4131_cfg[MCP425x_503] },
+       { .compatible = "microchip,mcp4252-104",
+               .data = &mcp4131_cfg[MCP425x_104] },
+       { .compatible = "microchip,mcp4261-502",
+               .data = &mcp4131_cfg[MCP426x_502] },
+       { .compatible = "microchip,mcp4261-103",
+               .data = &mcp4131_cfg[MCP426x_103] },
+       { .compatible = "microchip,mcp4261-503",
+               .data = &mcp4131_cfg[MCP426x_503] },
+       { .compatible = "microchip,mcp4261-104",
+               .data = &mcp4131_cfg[MCP426x_104] },
+       { .compatible = "microchip,mcp4262-502",
+               .data = &mcp4131_cfg[MCP426x_502] },
+       { .compatible = "microchip,mcp4262-103",
+               .data = &mcp4131_cfg[MCP426x_103] },
+       { .compatible = "microchip,mcp4262-503",
+               .data = &mcp4131_cfg[MCP426x_503] },
+       { .compatible = "microchip,mcp4262-104",
+               .data = &mcp4131_cfg[MCP426x_104] },
+       {}
+};
+MODULE_DEVICE_TABLE(of, mcp4131_dt_ids);
+#endif /* CONFIG_OF */
+
+static const struct spi_device_id mcp4131_id[] = {
+       { "mcp4131-502", MCP413x_502 },
+       { "mcp4131-103", MCP413x_103 },
+       { "mcp4131-503", MCP413x_503 },
+       { "mcp4131-104", MCP413x_104 },
+       { "mcp4132-502", MCP413x_502 },
+       { "mcp4132-103", MCP413x_103 },
+       { "mcp4132-503", MCP413x_503 },
+       { "mcp4132-104", MCP413x_104 },
+       { "mcp4141-502", MCP414x_502 },
+       { "mcp4141-103", MCP414x_103 },
+       { "mcp4141-503", MCP414x_503 },
+       { "mcp4141-104", MCP414x_104 },
+       { "mcp4142-502", MCP414x_502 },
+       { "mcp4142-103", MCP414x_103 },
+       { "mcp4142-503", MCP414x_503 },
+       { "mcp4142-104", MCP414x_104 },
+       { "mcp4151-502", MCP415x_502 },
+       { "mcp4151-103", MCP415x_103 },
+       { "mcp4151-503", MCP415x_503 },
+       { "mcp4151-104", MCP415x_104 },
+       { "mcp4152-502", MCP415x_502 },
+       { "mcp4152-103", MCP415x_103 },
+       { "mcp4152-503", MCP415x_503 },
+       { "mcp4152-104", MCP415x_104 },
+       { "mcp4161-502", MCP416x_502 },
+       { "mcp4161-103", MCP416x_103 },
+       { "mcp4161-503", MCP416x_503 },
+       { "mcp4161-104", MCP416x_104 },
+       { "mcp4162-502", MCP416x_502 },
+       { "mcp4162-103", MCP416x_103 },
+       { "mcp4162-503", MCP416x_503 },
+       { "mcp4162-104", MCP416x_104 },
+       { "mcp4231-502", MCP423x_502 },
+       { "mcp4231-103", MCP423x_103 },
+       { "mcp4231-503", MCP423x_503 },
+       { "mcp4231-104", MCP423x_104 },
+       { "mcp4232-502", MCP423x_502 },
+       { "mcp4232-103", MCP423x_103 },
+       { "mcp4232-503", MCP423x_503 },
+       { "mcp4232-104", MCP423x_104 },
+       { "mcp4241-502", MCP424x_502 },
+       { "mcp4241-103", MCP424x_103 },
+       { "mcp4241-503", MCP424x_503 },
+       { "mcp4241-104", MCP424x_104 },
+       { "mcp4242-502", MCP424x_502 },
+       { "mcp4242-103", MCP424x_103 },
+       { "mcp4242-503", MCP424x_503 },
+       { "mcp4242-104", MCP424x_104 },
+       { "mcp4251-502", MCP425x_502 },
+       { "mcp4251-103", MCP425x_103 },
+       { "mcp4251-503", MCP425x_503 },
+       { "mcp4251-104", MCP425x_104 },
+       { "mcp4252-502", MCP425x_502 },
+       { "mcp4252-103", MCP425x_103 },
+       { "mcp4252-503", MCP425x_503 },
+       { "mcp4252-104", MCP425x_104 },
+       { "mcp4261-502", MCP426x_502 },
+       { "mcp4261-103", MCP426x_103 },
+       { "mcp4261-503", MCP426x_503 },
+       { "mcp4261-104", MCP426x_104 },
+       { "mcp4262-502", MCP426x_502 },
+       { "mcp4262-103", MCP426x_103 },
+       { "mcp4262-503", MCP426x_503 },
+       { "mcp4262-104", MCP426x_104 },
+       {}
+};
+MODULE_DEVICE_TABLE(spi, mcp4131_id);
+
+static struct spi_driver mcp4131_driver = {
+       .driver = {
+               .name   = "mcp4131",
+               .of_match_table = of_match_ptr(mcp4131_dt_ids),
+       },
+       .probe          = mcp4131_probe,
+       .id_table       = mcp4131_id,
+};
+
+module_spi_driver(mcp4131_driver);
+
+MODULE_AUTHOR("Slawomir Stepien <sst@poczta.fm>");
+MODULE_DESCRIPTION("MCP4131 digital potentiometer");
+MODULE_LICENSE("GPL v2");
index 0db67fe..3b72e1a 100644 (file)
@@ -79,7 +79,7 @@ static const struct mcp4531_cfg mcp4531_cfg[] = {
 
 struct mcp4531_data {
        struct i2c_client *client;
-       unsigned long devid;
+       const struct mcp4531_cfg *cfg;
 };
 
 #define MCP4531_CHANNEL(ch) {                                  \
@@ -113,8 +113,8 @@ static int mcp4531_read_raw(struct iio_dev *indio_dev,
                *val = ret;
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_SCALE:
-               *val = 1000 * mcp4531_cfg[data->devid].kohms;
-               *val2 = mcp4531_cfg[data->devid].max_pos;
+               *val = 1000 * data->cfg->kohms;
+               *val2 = data->cfg->max_pos;
                return IIO_VAL_FRACTIONAL;
        }
 
@@ -130,7 +130,7 @@ static int mcp4531_write_raw(struct iio_dev *indio_dev,
 
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
-               if (val > mcp4531_cfg[data->devid].max_pos || val < 0)
+               if (val > data->cfg->max_pos || val < 0)
                        return -EINVAL;
                break;
        default:
@@ -152,7 +152,6 @@ static int mcp4531_probe(struct i2c_client *client,
                         const struct i2c_device_id *id)
 {
        struct device *dev = &client->dev;
-       unsigned long devid = id->driver_data;
        struct mcp4531_data *data;
        struct iio_dev *indio_dev;
 
@@ -168,12 +167,12 @@ static int mcp4531_probe(struct i2c_client *client,
        data = iio_priv(indio_dev);
        i2c_set_clientdata(client, indio_dev);
        data->client = client;
-       data->devid = devid;
+       data->cfg = &mcp4531_cfg[id->driver_data];
 
        indio_dev->dev.parent = dev;
        indio_dev->info = &mcp4531_info;
        indio_dev->channels = mcp4531_channels;
-       indio_dev->num_channels = mcp4531_cfg[devid].wipers;
+       indio_dev->num_channels = data->cfg->wipers;
        indio_dev->name = client->name;
 
        return devm_iio_device_register(dev, indio_dev);
index 313124b..5c304d4 100644 (file)
@@ -118,7 +118,7 @@ static int tpl0102_probe(struct i2c_client *client,
 
        if (!i2c_check_functionality(client->adapter,
                                     I2C_FUNC_SMBUS_WORD_DATA))
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
 
        indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
        if (!indio_dev)
index 31c0e1f..8de0192 100644 (file)
@@ -148,4 +148,14 @@ config T5403
          To compile this driver as a module, choose M here: the module
          will be called t5403.
 
+config HP206C
+       tristate "HOPERF HP206C precision barometer and altimeter sensor"
+       depends on I2C
+       help
+         Say yes here to build support for the HOPREF HP206C precision
+         barometer and altimeter sensor.
+
+         This driver can also be built as a module. If so, the module will
+         be called hp206c.
+
 endmenu
index d336af1..6e60863 100644 (file)
@@ -17,6 +17,7 @@ obj-$(CONFIG_IIO_ST_PRESS) += st_pressure.o
 st_pressure-y := st_pressure_core.o
 st_pressure-$(CONFIG_IIO_BUFFER) += st_pressure_buffer.o
 obj-$(CONFIG_T5403) += t5403.o
+obj-$(CONFIG_HP206C) += hp206c.o
 
 obj-$(CONFIG_IIO_ST_PRESS_I2C) += st_pressure_i2c.o
 obj-$(CONFIG_IIO_ST_PRESS_SPI) += st_pressure_spi.o
diff --git a/drivers/iio/pressure/hp206c.c b/drivers/iio/pressure/hp206c.c
new file mode 100644 (file)
index 0000000..90f2b6e
--- /dev/null
@@ -0,0 +1,426 @@
+/*
+ * hp206c.c - HOPERF HP206C precision barometer and altimeter sensor
+ *
+ * Copyright (c) 2016, Intel Corporation.
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License.  See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * (7-bit I2C slave address 0x76)
+ *
+ * Datasheet:
+ *  http://www.hoperf.com/upload/sensor/HP206C_DataSheet_EN_V2.0.pdf
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/delay.h>
+#include <linux/util_macros.h>
+#include <linux/acpi.h>
+
+/* I2C commands: */
+#define HP206C_CMD_SOFT_RST    0x06
+
+#define HP206C_CMD_ADC_CVT     0x40
+
+#define HP206C_CMD_ADC_CVT_OSR_4096    0x00
+#define HP206C_CMD_ADC_CVT_OSR_2048    0x04
+#define HP206C_CMD_ADC_CVT_OSR_1024    0x08
+#define HP206C_CMD_ADC_CVT_OSR_512     0x0c
+#define HP206C_CMD_ADC_CVT_OSR_256     0x10
+#define HP206C_CMD_ADC_CVT_OSR_128     0x14
+
+#define HP206C_CMD_ADC_CVT_CHNL_PT     0x00
+#define HP206C_CMD_ADC_CVT_CHNL_T      0x02
+
+#define HP206C_CMD_READ_P      0x30
+#define HP206C_CMD_READ_T      0x32
+
+#define HP206C_CMD_READ_REG    0x80
+#define HP206C_CMD_WRITE_REG   0xc0
+
+#define HP206C_REG_INT_EN      0x0b
+#define HP206C_REG_INT_CFG     0x0c
+
+#define HP206C_REG_INT_SRC     0x0d
+#define HP206C_FLAG_DEV_RDY    0x40
+
+#define HP206C_REG_PARA                0x0f
+#define HP206C_FLAG_CMPS_EN    0x80
+
+/* Maximum spin for DEV_RDY */
+#define HP206C_MAX_DEV_RDY_WAIT_COUNT 20
+#define HP206C_DEV_RDY_WAIT_US    20000
+
+struct hp206c_data {
+       struct mutex mutex;
+       struct i2c_client *client;
+       int temp_osr_index;
+       int pres_osr_index;
+};
+
+struct hp206c_osr_setting {
+       u8 osr_mask;
+       unsigned int temp_conv_time_us;
+       unsigned int pres_conv_time_us;
+};
+
+/* Data from Table 5 in datasheet. */
+static const struct hp206c_osr_setting hp206c_osr_settings[] = {
+       { HP206C_CMD_ADC_CVT_OSR_4096,  65600,  131100  },
+       { HP206C_CMD_ADC_CVT_OSR_2048,  32800,  65600   },
+       { HP206C_CMD_ADC_CVT_OSR_1024,  16400,  32800   },
+       { HP206C_CMD_ADC_CVT_OSR_512,   8200,   16400   },
+       { HP206C_CMD_ADC_CVT_OSR_256,   4100,   8200    },
+       { HP206C_CMD_ADC_CVT_OSR_128,   2100,   4100    },
+};
+static const int hp206c_osr_rates[] = { 4096, 2048, 1024, 512, 256, 128 };
+static const char hp206c_osr_rates_str[] = "4096 2048 1024 512 256 128";
+
+static inline int hp206c_read_reg(struct i2c_client *client, u8 reg)
+{
+       return i2c_smbus_read_byte_data(client, HP206C_CMD_READ_REG | reg);
+}
+
+static inline int hp206c_write_reg(struct i2c_client *client, u8 reg, u8 val)
+{
+       return i2c_smbus_write_byte_data(client,
+                       HP206C_CMD_WRITE_REG | reg, val);
+}
+
+static int hp206c_read_20bit(struct i2c_client *client, u8 cmd)
+{
+       int ret;
+       u8 values[3];
+
+       ret = i2c_smbus_read_i2c_block_data(client, cmd, 3, values);
+       if (ret < 0)
+               return ret;
+       if (ret != 3)
+               return -EIO;
+       return ((values[0] & 0xF) << 16) | (values[1] << 8) | (values[2]);
+}
+
+/* Spin for max 160ms until DEV_RDY is 1, or return error. */
+static int hp206c_wait_dev_rdy(struct iio_dev *indio_dev)
+{
+       int ret;
+       int count = 0;
+       struct hp206c_data *data = iio_priv(indio_dev);
+       struct i2c_client *client = data->client;
+
+       while (++count <= HP206C_MAX_DEV_RDY_WAIT_COUNT) {
+               ret = hp206c_read_reg(client, HP206C_REG_INT_SRC);
+               if (ret < 0) {
+                       dev_err(&indio_dev->dev, "Failed READ_REG INT_SRC: %d\n", ret);
+                       return ret;
+               }
+               if (ret & HP206C_FLAG_DEV_RDY)
+                       return 0;
+               usleep_range(HP206C_DEV_RDY_WAIT_US, HP206C_DEV_RDY_WAIT_US * 3 / 2);
+       }
+       return -ETIMEDOUT;
+}
+
+static int hp206c_set_compensation(struct i2c_client *client, bool enabled)
+{
+       int val;
+
+       val = hp206c_read_reg(client, HP206C_REG_PARA);
+       if (val < 0)
+               return val;
+       if (enabled)
+               val |= HP206C_FLAG_CMPS_EN;
+       else
+               val &= ~HP206C_FLAG_CMPS_EN;
+
+       return hp206c_write_reg(client, HP206C_REG_PARA, val);
+}
+
+/* Do a soft reset */
+static int hp206c_soft_reset(struct iio_dev *indio_dev)
+{
+       int ret;
+       struct hp206c_data *data = iio_priv(indio_dev);
+       struct i2c_client *client = data->client;
+
+       ret = i2c_smbus_write_byte(client, HP206C_CMD_SOFT_RST);
+       if (ret) {
+               dev_err(&client->dev, "Failed to reset device: %d\n", ret);
+               return ret;
+       }
+
+       usleep_range(400, 600);
+
+       ret = hp206c_wait_dev_rdy(indio_dev);
+       if (ret) {
+               dev_err(&client->dev, "Device not ready after soft reset: %d\n", ret);
+               return ret;
+       }
+
+       ret = hp206c_set_compensation(client, true);
+       if (ret)
+               dev_err(&client->dev, "Failed to enable compensation: %d\n", ret);
+       return ret;
+}
+
+static int hp206c_conv_and_read(struct iio_dev *indio_dev,
+                               u8 conv_cmd, u8 read_cmd,
+                               unsigned int sleep_us)
+{
+       int ret;
+       struct hp206c_data *data = iio_priv(indio_dev);
+       struct i2c_client *client = data->client;
+
+       ret = hp206c_wait_dev_rdy(indio_dev);
+       if (ret < 0) {
+               dev_err(&indio_dev->dev, "Device not ready: %d\n", ret);
+               return ret;
+       }
+
+       ret = i2c_smbus_write_byte(client, conv_cmd);
+       if (ret < 0) {
+               dev_err(&indio_dev->dev, "Failed convert: %d\n", ret);
+               return ret;
+       }
+
+       usleep_range(sleep_us, sleep_us * 3 / 2);
+
+       ret = hp206c_wait_dev_rdy(indio_dev);
+       if (ret < 0) {
+               dev_err(&indio_dev->dev, "Device not ready: %d\n", ret);
+               return ret;
+       }
+
+       ret = hp206c_read_20bit(client, read_cmd);
+       if (ret < 0)
+               dev_err(&indio_dev->dev, "Failed read: %d\n", ret);
+
+       return ret;
+}
+
+static int hp206c_read_raw(struct iio_dev *indio_dev,
+                          struct iio_chan_spec const *chan, int *val,
+                          int *val2, long mask)
+{
+       int ret;
+       struct hp206c_data *data = iio_priv(indio_dev);
+       const struct hp206c_osr_setting *osr_setting;
+       u8 conv_cmd;
+
+       mutex_lock(&data->mutex);
+
+       switch (mask) {
+       case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+               switch (chan->type) {
+               case IIO_TEMP:
+                       *val = hp206c_osr_rates[data->temp_osr_index];
+                       ret = IIO_VAL_INT;
+                       break;
+
+               case IIO_PRESSURE:
+                       *val = hp206c_osr_rates[data->pres_osr_index];
+                       ret = IIO_VAL_INT;
+                       break;
+               default:
+                       ret = -EINVAL;
+               }
+               break;
+
+       case IIO_CHAN_INFO_RAW:
+               switch (chan->type) {
+               case IIO_TEMP:
+                       osr_setting = &hp206c_osr_settings[data->temp_osr_index];
+                       conv_cmd = HP206C_CMD_ADC_CVT |
+                                       osr_setting->osr_mask |
+                                       HP206C_CMD_ADC_CVT_CHNL_T;
+                       ret = hp206c_conv_and_read(indio_dev,
+                                       conv_cmd,
+                                       HP206C_CMD_READ_T,
+                                       osr_setting->temp_conv_time_us);
+                       if (ret >= 0) {
+                               /* 20 significant bits are provided.
+                                * Extend sign over the rest.
+                                */
+                               *val = sign_extend32(ret, 19);
+                               ret = IIO_VAL_INT;
+                       }
+                       break;
+
+               case IIO_PRESSURE:
+                       osr_setting = &hp206c_osr_settings[data->pres_osr_index];
+                       conv_cmd = HP206C_CMD_ADC_CVT |
+                                       osr_setting->osr_mask |
+                                       HP206C_CMD_ADC_CVT_CHNL_PT;
+                       ret = hp206c_conv_and_read(indio_dev,
+                                       conv_cmd,
+                                       HP206C_CMD_READ_P,
+                                       osr_setting->pres_conv_time_us);
+                       if (ret >= 0) {
+                               *val = ret;
+                               ret = IIO_VAL_INT;
+                       }
+                       break;
+               default:
+                       ret = -EINVAL;
+               }
+               break;
+
+       case IIO_CHAN_INFO_SCALE:
+               switch (chan->type) {
+               case IIO_TEMP:
+                       *val = 0;
+                       *val2 = 10000;
+                       ret = IIO_VAL_INT_PLUS_MICRO;
+                       break;
+
+               case IIO_PRESSURE:
+                       *val = 0;
+                       *val2 = 1000;
+                       ret = IIO_VAL_INT_PLUS_MICRO;
+                       break;
+               default:
+                       ret = -EINVAL;
+               }
+               break;
+
+       default:
+               ret = -EINVAL;
+       }
+
+       mutex_unlock(&data->mutex);
+       return ret;
+}
+
+static int hp206c_write_raw(struct iio_dev *indio_dev,
+                           struct iio_chan_spec const *chan,
+                           int val, int val2, long mask)
+{
+       int ret = 0;
+       struct hp206c_data *data = iio_priv(indio_dev);
+
+       if (mask != IIO_CHAN_INFO_OVERSAMPLING_RATIO)
+               return -EINVAL;
+       mutex_lock(&data->mutex);
+       switch (chan->type) {
+       case IIO_TEMP:
+               data->temp_osr_index = find_closest_descending(val,
+                       hp206c_osr_rates, ARRAY_SIZE(hp206c_osr_rates));
+               break;
+       case IIO_PRESSURE:
+               data->pres_osr_index = find_closest_descending(val,
+                       hp206c_osr_rates, ARRAY_SIZE(hp206c_osr_rates));
+               break;
+       default:
+               ret = -EINVAL;
+       }
+       mutex_unlock(&data->mutex);
+       return ret;
+}
+
+static const struct iio_chan_spec hp206c_channels[] = {
+       {
+               .type = IIO_TEMP,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+                                     BIT(IIO_CHAN_INFO_SCALE) |
+                                     BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+       },
+       {
+               .type = IIO_PRESSURE,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+                                     BIT(IIO_CHAN_INFO_SCALE) |
+                                     BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+       }
+};
+
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(hp206c_osr_rates_str);
+
+static struct attribute *hp206c_attributes[] = {
+       &iio_const_attr_sampling_frequency_available.dev_attr.attr,
+       NULL,
+};
+
+static const struct attribute_group hp206c_attribute_group = {
+       .attrs = hp206c_attributes,
+};
+
+static const struct iio_info hp206c_info = {
+       .attrs = &hp206c_attribute_group,
+       .read_raw = hp206c_read_raw,
+       .write_raw = hp206c_write_raw,
+       .driver_module = THIS_MODULE,
+};
+
+static int hp206c_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
+{
+       struct iio_dev *indio_dev;
+       struct hp206c_data *data;
+       int ret;
+
+       if (!i2c_check_functionality(client->adapter,
+                                    I2C_FUNC_SMBUS_BYTE |
+                                    I2C_FUNC_SMBUS_BYTE_DATA |
+                                    I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
+               dev_err(&client->dev, "Adapter does not support "
+                               "all required i2c functionality\n");
+               return -ENODEV;
+       }
+
+       indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+       if (!indio_dev)
+               return -ENOMEM;
+
+       data = iio_priv(indio_dev);
+       data->client = client;
+       mutex_init(&data->mutex);
+
+       indio_dev->info = &hp206c_info;
+       indio_dev->name = id->name;
+       indio_dev->dev.parent = &client->dev;
+       indio_dev->modes = INDIO_DIRECT_MODE;
+       indio_dev->channels = hp206c_channels;
+       indio_dev->num_channels = ARRAY_SIZE(hp206c_channels);
+
+       i2c_set_clientdata(client, indio_dev);
+
+       /* Do a soft reset on probe */
+       ret = hp206c_soft_reset(indio_dev);
+       if (ret) {
+               dev_err(&client->dev, "Failed to reset on startup: %d\n", ret);
+               return -ENODEV;
+       }
+
+       return devm_iio_device_register(&client->dev, indio_dev);
+}
+
+static const struct i2c_device_id hp206c_id[] = {
+       {"hp206c"},
+       {}
+};
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id hp206c_acpi_match[] = {
+       {"HOP206C", 0},
+       { },
+};
+MODULE_DEVICE_TABLE(acpi, hp206c_acpi_match);
+#endif
+
+static struct i2c_driver hp206c_driver = {
+       .probe = hp206c_probe,
+       .id_table = hp206c_id,
+       .driver = {
+               .name = "hp206c",
+               .acpi_match_table = ACPI_PTR(hp206c_acpi_match),
+       },
+};
+
+module_i2c_driver(hp206c_driver);
+
+MODULE_DESCRIPTION("HOPERF HP206C precision barometer and altimeter sensor");
+MODULE_AUTHOR("Leonard Crestez <leonard.crestez@intel.com>");
+MODULE_LICENSE("GPL v2");
index 8b08e4b..ccda63c 100644 (file)
 #include <linux/iio/iio.h>
 #include <linux/mutex.h>
 
+struct regulator;
+
 #define MS5611_RESET                   0x1e
 #define MS5611_READ_ADC                        0x00
 #define MS5611_READ_PROM_WORD          0xA0
-#define MS5611_START_TEMP_CONV         0x58
-#define MS5611_START_PRESSURE_CONV     0x48
-
-#define MS5611_CONV_TIME_MIN           9040
-#define MS5611_CONV_TIME_MAX           10000
-
 #define MS5611_PROM_WORDS_NB           8
 
 enum {
@@ -39,16 +35,31 @@ struct ms5611_chip_info {
                                            s32 *temp, s32 *pressure);
 };
 
+/*
+ * OverSampling Rate descriptor.
+ * Warning: cmd MUST be kept aligned on a word boundary (see
+ * m5611_spi_read_adc_temp_and_pressure in ms5611_spi.c).
+ */
+struct ms5611_osr {
+       unsigned long conv_usec;
+       u8 cmd;
+       unsigned short rate;
+};
+
 struct ms5611_state {
        void *client;
        struct mutex lock;
 
+       const struct ms5611_osr *pressure_osr;
+       const struct ms5611_osr *temp_osr;
+
        int (*reset)(struct device *dev);
        int (*read_prom_word)(struct device *dev, int index, u16 *word);
        int (*read_adc_temp_and_pressure)(struct device *dev,
                                          s32 *temp, s32 *pressure);
 
        struct ms5611_chip_info *chip_info;
+       struct regulator *vdd;
 };
 
 int ms5611_probe(struct iio_dev *indio_dev, struct device *dev,
index 992ad8d..c4e6586 100644 (file)
 #include <linux/delay.h>
 #include <linux/regulator/consumer.h>
 
+#include <linux/iio/sysfs.h>
 #include <linux/iio/buffer.h>
 #include <linux/iio/triggered_buffer.h>
 #include <linux/iio/trigger_consumer.h>
 #include "ms5611.h"
 
+#define MS5611_INIT_OSR(_cmd, _conv_usec, _rate) \
+       { .cmd = _cmd, .conv_usec = _conv_usec, .rate = _rate }
+
+static const struct ms5611_osr ms5611_avail_pressure_osr[] = {
+       MS5611_INIT_OSR(0x40, 600,  256),
+       MS5611_INIT_OSR(0x42, 1170, 512),
+       MS5611_INIT_OSR(0x44, 2280, 1024),
+       MS5611_INIT_OSR(0x46, 4540, 2048),
+       MS5611_INIT_OSR(0x48, 9040, 4096)
+};
+
+static const struct ms5611_osr ms5611_avail_temp_osr[] = {
+       MS5611_INIT_OSR(0x50, 600,  256),
+       MS5611_INIT_OSR(0x52, 1170, 512),
+       MS5611_INIT_OSR(0x54, 2280, 1024),
+       MS5611_INIT_OSR(0x56, 4540, 2048),
+       MS5611_INIT_OSR(0x58, 9040, 4096)
+};
+
+static const char ms5611_show_osr[] = "256 512 1024 2048 4096";
+
+static IIO_CONST_ATTR(oversampling_ratio_available, ms5611_show_osr);
+
+static struct attribute *ms5611_attributes[] = {
+       &iio_const_attr_oversampling_ratio_available.dev_attr.attr,
+       NULL,
+};
+
+static const struct attribute_group ms5611_attribute_group = {
+       .attrs = ms5611_attributes,
+};
+
 static bool ms5611_prom_is_valid(u16 *prom, size_t len)
 {
        int i, j;
@@ -239,11 +272,70 @@ static int ms5611_read_raw(struct iio_dev *indio_dev,
                default:
                        return -EINVAL;
                }
+       case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+               if (chan->type != IIO_TEMP && chan->type != IIO_PRESSURE)
+                       break;
+               mutex_lock(&st->lock);
+               if (chan->type == IIO_TEMP)
+                       *val = (int)st->temp_osr->rate;
+               else
+                       *val = (int)st->pressure_osr->rate;
+               mutex_unlock(&st->lock);
+               return IIO_VAL_INT;
        }
 
        return -EINVAL;
 }
 
+static const struct ms5611_osr *ms5611_find_osr(int rate,
+                                               const struct ms5611_osr *osr,
+                                               size_t count)
+{
+       unsigned int r;
+
+       for (r = 0; r < count; r++)
+               if ((unsigned short)rate == osr[r].rate)
+                       break;
+       if (r >= count)
+               return NULL;
+       return &osr[r];
+}
+
+static int ms5611_write_raw(struct iio_dev *indio_dev,
+                           struct iio_chan_spec const *chan,
+                           int val, int val2, long mask)
+{
+       struct ms5611_state *st = iio_priv(indio_dev);
+       const struct ms5611_osr *osr = NULL;
+
+       if (mask != IIO_CHAN_INFO_OVERSAMPLING_RATIO)
+               return -EINVAL;
+
+       if (chan->type == IIO_TEMP)
+               osr = ms5611_find_osr(val, ms5611_avail_temp_osr,
+                                     ARRAY_SIZE(ms5611_avail_temp_osr));
+       else if (chan->type == IIO_PRESSURE)
+               osr = ms5611_find_osr(val, ms5611_avail_pressure_osr,
+                                     ARRAY_SIZE(ms5611_avail_pressure_osr));
+       if (!osr)
+               return -EINVAL;
+
+       mutex_lock(&st->lock);
+
+       if (iio_buffer_enabled(indio_dev)) {
+               mutex_unlock(&st->lock);
+               return -EBUSY;
+       }
+
+       if (chan->type == IIO_TEMP)
+               st->temp_osr = osr;
+       else
+               st->pressure_osr = osr;
+
+       mutex_unlock(&st->lock);
+       return 0;
+}
+
 static const unsigned long ms5611_scan_masks[] = {0x3, 0};
 
 static struct ms5611_chip_info chip_info_tbl[] = {
@@ -259,7 +351,8 @@ static const struct iio_chan_spec ms5611_channels[] = {
        {
                .type = IIO_PRESSURE,
                .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
-                       BIT(IIO_CHAN_INFO_SCALE),
+                       BIT(IIO_CHAN_INFO_SCALE) |
+                       BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
                .scan_index = 0,
                .scan_type = {
                        .sign = 's',
@@ -271,7 +364,8 @@ static const struct iio_chan_spec ms5611_channels[] = {
        {
                .type = IIO_TEMP,
                .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
-                       BIT(IIO_CHAN_INFO_SCALE),
+                       BIT(IIO_CHAN_INFO_SCALE) |
+                       BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
                .scan_index = 1,
                .scan_type = {
                        .sign = 's',
@@ -285,30 +379,53 @@ static const struct iio_chan_spec ms5611_channels[] = {
 
 static const struct iio_info ms5611_info = {
        .read_raw = &ms5611_read_raw,
+       .write_raw = &ms5611_write_raw,
+       .attrs = &ms5611_attribute_group,
        .driver_module = THIS_MODULE,
 };
 
 static int ms5611_init(struct iio_dev *indio_dev)
 {
        int ret;
-       struct regulator *vdd = devm_regulator_get(indio_dev->dev.parent,
-                                                  "vdd");
+       struct ms5611_state *st = iio_priv(indio_dev);
 
        /* Enable attached regulator if any. */
-       if (!IS_ERR(vdd)) {
-               ret = regulator_enable(vdd);
+       st->vdd = devm_regulator_get(indio_dev->dev.parent, "vdd");
+       if (!IS_ERR(st->vdd)) {
+               ret = regulator_enable(st->vdd);
                if (ret) {
                        dev_err(indio_dev->dev.parent,
-                               "failed to enable Vdd supply: %d\n", ret);
+                               "failed to enable Vdd supply: %d\n", ret);
                        return ret;
                }
+       } else {
+               ret = PTR_ERR(st->vdd);
+               if (ret != -ENODEV)
+                       return ret;
        }
 
        ret = ms5611_reset(indio_dev);
        if (ret < 0)
-               return ret;
+               goto err_regulator_disable;
 
-       return ms5611_read_prom(indio_dev);
+       ret = ms5611_read_prom(indio_dev);
+       if (ret < 0)
+               goto err_regulator_disable;
+
+       return 0;
+
+err_regulator_disable:
+       if (!IS_ERR_OR_NULL(st->vdd))
+               regulator_disable(st->vdd);
+       return ret;
+}
+
+static void ms5611_fini(const struct iio_dev *indio_dev)
+{
+       const struct ms5611_state *st = iio_priv(indio_dev);
+
+       if (!IS_ERR_OR_NULL(st->vdd))
+               regulator_disable(st->vdd);
 }
 
 int ms5611_probe(struct iio_dev *indio_dev, struct device *dev,
@@ -319,6 +436,11 @@ int ms5611_probe(struct iio_dev *indio_dev, struct device *dev,
 
        mutex_init(&st->lock);
        st->chip_info = &chip_info_tbl[type];
+       st->temp_osr =
+               &ms5611_avail_temp_osr[ARRAY_SIZE(ms5611_avail_temp_osr) - 1];
+       st->pressure_osr =
+               &ms5611_avail_pressure_osr[ARRAY_SIZE(ms5611_avail_pressure_osr)
+                                          - 1];
        indio_dev->dev.parent = dev;
        indio_dev->name = name;
        indio_dev->info = &ms5611_info;
@@ -335,7 +457,7 @@ int ms5611_probe(struct iio_dev *indio_dev, struct device *dev,
                                         ms5611_trigger_handler, NULL);
        if (ret < 0) {
                dev_err(dev, "iio triggered buffer setup failed\n");
-               return ret;
+               goto err_fini;
        }
 
        ret = iio_device_register(indio_dev);
@@ -348,7 +470,8 @@ int ms5611_probe(struct iio_dev *indio_dev, struct device *dev,
 
 err_buffer_cleanup:
        iio_triggered_buffer_cleanup(indio_dev);
-
+err_fini:
+       ms5611_fini(indio_dev);
        return ret;
 }
 EXPORT_SYMBOL(ms5611_probe);
@@ -357,6 +480,7 @@ int ms5611_remove(struct iio_dev *indio_dev)
 {
        iio_device_unregister(indio_dev);
        iio_triggered_buffer_cleanup(indio_dev);
+       ms5611_fini(indio_dev);
 
        return 0;
 }
index 7f6fc8e..55fb5fc 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/delay.h>
 #include <linux/i2c.h>
 #include <linux/module.h>
+#include <linux/of_device.h>
 
 #include "ms5611.h"
 
@@ -62,23 +63,23 @@ static int ms5611_i2c_read_adc_temp_and_pressure(struct device *dev,
 {
        int ret;
        struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev));
+       const struct ms5611_osr *osr = st->temp_osr;
 
-       ret = i2c_smbus_write_byte(st->client, MS5611_START_TEMP_CONV);
+       ret = i2c_smbus_write_byte(st->client, osr->cmd);
        if (ret < 0)
                return ret;
 
-       usleep_range(MS5611_CONV_TIME_MIN, MS5611_CONV_TIME_MAX);
-
+       usleep_range(osr->conv_usec, osr->conv_usec + (osr->conv_usec / 10UL));
        ret = ms5611_i2c_read_adc(st, temp);
        if (ret < 0)
                return ret;
 
-       ret = i2c_smbus_write_byte(st->client, MS5611_START_PRESSURE_CONV);
+       osr = st->pressure_osr;
+       ret = i2c_smbus_write_byte(st->client, osr->cmd);
        if (ret < 0)
                return ret;
 
-       usleep_range(MS5611_CONV_TIME_MIN, MS5611_CONV_TIME_MAX);
-
+       usleep_range(osr->conv_usec, osr->conv_usec + (osr->conv_usec / 10UL));
        return ms5611_i2c_read_adc(st, pressure);
 }
 
@@ -113,6 +114,17 @@ static int ms5611_i2c_remove(struct i2c_client *client)
        return ms5611_remove(i2c_get_clientdata(client));
 }
 
+#if defined(CONFIG_OF)
+static const struct of_device_id ms5611_i2c_matches[] = {
+       { .compatible = "meas,ms5611" },
+       { .compatible = "ms5611" },
+       { .compatible = "meas,ms5607" },
+       { .compatible = "ms5607" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, ms5611_i2c_matches);
+#endif
+
 static const struct i2c_device_id ms5611_id[] = {
        { "ms5611", MS5611 },
        { "ms5607", MS5607 },
@@ -123,6 +135,7 @@ MODULE_DEVICE_TABLE(i2c, ms5611_id);
 static struct i2c_driver ms5611_driver = {
        .driver = {
                .name = "ms5611",
+               .of_match_table = of_match_ptr(ms5611_i2c_matches)
        },
        .id_table = ms5611_id,
        .probe = ms5611_i2c_probe,
index 5cc009e..7600483 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/spi/spi.h>
+#include <linux/of_device.h>
 
 #include "ms5611.h"
 
@@ -55,28 +56,29 @@ static int ms5611_spi_read_adc(struct device *dev, s32 *val)
 static int ms5611_spi_read_adc_temp_and_pressure(struct device *dev,
                                                 s32 *temp, s32 *pressure)
 {
-       u8 cmd;
        int ret;
        struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev));
+       const struct ms5611_osr *osr = st->temp_osr;
 
-       cmd = MS5611_START_TEMP_CONV;
-       ret = spi_write_then_read(st->client, &cmd, 1, NULL, 0);
+       /*
+        * Warning: &osr->cmd MUST be aligned on a word boundary since used as
+        * 2nd argument (void*) of spi_write_then_read.
+        */
+       ret = spi_write_then_read(st->client, &osr->cmd, 1, NULL, 0);
        if (ret < 0)
                return ret;
 
-       usleep_range(MS5611_CONV_TIME_MIN, MS5611_CONV_TIME_MAX);
-
+       usleep_range(osr->conv_usec, osr->conv_usec + (osr->conv_usec / 10UL));
        ret = ms5611_spi_read_adc(dev, temp);
        if (ret < 0)
                return ret;
 
-       cmd = MS5611_START_PRESSURE_CONV;
-       ret = spi_write_then_read(st->client, &cmd, 1, NULL, 0);
+       osr = st->pressure_osr;
+       ret = spi_write_then_read(st->client, &osr->cmd, 1, NULL, 0);
        if (ret < 0)
                return ret;
 
-       usleep_range(MS5611_CONV_TIME_MIN, MS5611_CONV_TIME_MAX);
-
+       usleep_range(osr->conv_usec, osr->conv_usec + (osr->conv_usec / 10UL));
        return ms5611_spi_read_adc(dev, pressure);
 }
 
@@ -114,6 +116,17 @@ static int ms5611_spi_remove(struct spi_device *spi)
        return ms5611_remove(spi_get_drvdata(spi));
 }
 
+#if defined(CONFIG_OF)
+static const struct of_device_id ms5611_spi_matches[] = {
+       { .compatible = "meas,ms5611" },
+       { .compatible = "ms5611" },
+       { .compatible = "meas,ms5607" },
+       { .compatible = "ms5607" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, ms5611_spi_matches);
+#endif
+
 static const struct spi_device_id ms5611_id[] = {
        { "ms5611", MS5611 },
        { "ms5607", MS5607 },
@@ -124,6 +137,7 @@ MODULE_DEVICE_TABLE(spi, ms5611_id);
 static struct spi_driver ms5611_driver = {
        .driver = {
                .name = "ms5611",
+               .of_match_table = of_match_ptr(ms5611_spi_matches)
        },
        .id_table = ms5611_id,
        .probe = ms5611_spi_probe,
index fa67da9..f066aa3 100644 (file)
@@ -27,18 +27,6 @@ config ADIS16203
          To compile this driver as a module, say M here: the module will be
          called adis16203.
 
-config ADIS16204
-       tristate "Analog Devices ADIS16204 Programmable High-g Digital Impact Sensor and Recorder"
-       depends on SPI
-       select IIO_ADIS_LIB
-       select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
-       help
-         Say Y here to build support for Analog Devices adis16204 Programmable
-         High-g Digital Impact Sensor and Recorder.
-
-         To compile this driver as a module, say M here: the module will be
-         called adis16204.
-
 config ADIS16209
        tristate "Analog Devices ADIS16209 Dual-Axis Digital Inclinometer and Accelerometer"
        depends on SPI
@@ -51,17 +39,6 @@ config ADIS16209
          To compile this driver as a module, say M here: the module will be
          called adis16209.
 
-config ADIS16220
-       tristate "Analog Devices ADIS16220 Programmable Digital Vibration Sensor"
-       depends on SPI
-       select IIO_ADIS_LIB
-       help
-         Say Y here to build support for Analog Devices adis16220 programmable
-         digital vibration sensor.
-
-         To compile this driver as a module, say M here: the module will be
-         called adis16220.
-
 config ADIS16240
        tristate "Analog Devices ADIS16240 Programmable Impact Sensor and Recorder"
        depends on SPI
index 1ed137f..415329c 100644 (file)
@@ -8,15 +8,9 @@ obj-$(CONFIG_ADIS16201) += adis16201.o
 adis16203-y             := adis16203_core.o
 obj-$(CONFIG_ADIS16203) += adis16203.o
 
-adis16204-y             := adis16204_core.o
-obj-$(CONFIG_ADIS16204) += adis16204.o
-
 adis16209-y             := adis16209_core.o
 obj-$(CONFIG_ADIS16209) += adis16209.o
 
-adis16220-y             := adis16220_core.o
-obj-$(CONFIG_ADIS16220) += adis16220.o
-
 adis16240-y             := adis16240_core.o
 obj-$(CONFIG_ADIS16240) += adis16240.o
 
diff --git a/drivers/staging/iio/accel/adis16204.h b/drivers/staging/iio/accel/adis16204.h
deleted file mode 100644 (file)
index cfc4038..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-#ifndef SPI_ADIS16204_H_
-#define SPI_ADIS16204_H_
-
-#define ADIS16204_STARTUP_DELAY        220 /* ms */
-
-/* Flash memory write count */
-#define ADIS16204_FLASH_CNT      0x00
-
-/* Output, power supply */
-#define ADIS16204_SUPPLY_OUT     0x02
-
-/* Output, x-axis accelerometer */
-#define ADIS16204_XACCL_OUT      0x04
-
-/* Output, y-axis accelerometer */
-#define ADIS16204_YACCL_OUT      0x06
-
-/* Output, auxiliary ADC input */
-#define ADIS16204_AUX_ADC        0x08
-
-/* Output, temperature */
-#define ADIS16204_TEMP_OUT       0x0A
-
-/* Twos complement */
-#define ADIS16204_X_PEAK_OUT     0x0C
-#define ADIS16204_Y_PEAK_OUT     0x0E
-
-/* Calibration, x-axis acceleration offset null */
-#define ADIS16204_XACCL_NULL     0x10
-
-/* Calibration, y-axis acceleration offset null */
-#define ADIS16204_YACCL_NULL     0x12
-
-/* X-axis scale factor calibration register */
-#define ADIS16204_XACCL_SCALE    0x14
-
-/* Y-axis scale factor calibration register */
-#define ADIS16204_YACCL_SCALE    0x16
-
-/* XY combined acceleration (RSS) */
-#define ADIS16204_XY_RSS_OUT     0x18
-
-/* Peak, XY combined output (RSS) */
-#define ADIS16204_XY_PEAK_OUT    0x1A
-
-/* Capture buffer output register 1 */
-#define ADIS16204_CAP_BUF_1      0x1C
-
-/* Capture buffer output register 2 */
-#define ADIS16204_CAP_BUF_2      0x1E
-
-/* Alarm 1 amplitude threshold */
-#define ADIS16204_ALM_MAG1       0x20
-
-/* Alarm 2 amplitude threshold */
-#define ADIS16204_ALM_MAG2       0x22
-
-/* Alarm control */
-#define ADIS16204_ALM_CTRL       0x28
-
-/* Capture register address pointer */
-#define ADIS16204_CAPT_PNTR      0x2A
-
-/* Auxiliary DAC data */
-#define ADIS16204_AUX_DAC        0x30
-
-/* General-purpose digital input/output control */
-#define ADIS16204_GPIO_CTRL      0x32
-
-/* Miscellaneous control */
-#define ADIS16204_MSC_CTRL       0x34
-
-/* Internal sample period (rate) control */
-#define ADIS16204_SMPL_PRD       0x36
-
-/* Operation, filter configuration */
-#define ADIS16204_AVG_CNT        0x38
-
-/* Operation, sleep mode control */
-#define ADIS16204_SLP_CNT        0x3A
-
-/* Diagnostics, system status register */
-#define ADIS16204_DIAG_STAT      0x3C
-
-/* Operation, system command register */
-#define ADIS16204_GLOB_CMD       0x3E
-
-/* MSC_CTRL */
-
-/* Self-test at power-on: 1 = disabled, 0 = enabled */
-#define ADIS16204_MSC_CTRL_PWRUP_SELF_TEST     BIT(10)
-
-/* Self-test enable */
-#define ADIS16204_MSC_CTRL_SELF_TEST_EN                BIT(8)
-
-/* Data-ready enable: 1 = enabled, 0 = disabled */
-#define ADIS16204_MSC_CTRL_DATA_RDY_EN         BIT(2)
-
-/* Data-ready polarity: 1 = active high, 0 = active low */
-#define ADIS16204_MSC_CTRL_ACTIVE_HIGH         BIT(1)
-
-/* Data-ready line selection: 1 = DIO2, 0 = DIO1 */
-#define ADIS16204_MSC_CTRL_DATA_RDY_DIO2       BIT(0)
-
-/* DIAG_STAT */
-
-/* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */
-#define ADIS16204_DIAG_STAT_ALARM2        BIT(9)
-
-/* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */
-#define ADIS16204_DIAG_STAT_ALARM1        BIT(8)
-
-/* Self-test diagnostic error flag: 1 = error condition, 0 = normal operation */
-#define ADIS16204_DIAG_STAT_SELFTEST_FAIL_BIT 5
-
-/* SPI communications failure */
-#define ADIS16204_DIAG_STAT_SPI_FAIL_BIT      3
-
-/* Flash update failure */
-#define ADIS16204_DIAG_STAT_FLASH_UPT_BIT     2
-
-/* Power supply above 3.625 V */
-#define ADIS16204_DIAG_STAT_POWER_HIGH_BIT    1
-
-/* Power supply below 2.975 V */
-#define ADIS16204_DIAG_STAT_POWER_LOW_BIT     0
-
-/* GLOB_CMD */
-
-#define ADIS16204_GLOB_CMD_SW_RESET    BIT(7)
-#define ADIS16204_GLOB_CMD_CLEAR_STAT  BIT(4)
-#define ADIS16204_GLOB_CMD_FACTORY_CAL BIT(1)
-
-#define ADIS16204_ERROR_ACTIVE          BIT(14)
-
-enum adis16204_scan {
-       ADIS16204_SCAN_ACC_X,
-       ADIS16204_SCAN_ACC_Y,
-       ADIS16204_SCAN_ACC_XY,
-       ADIS16204_SCAN_SUPPLY,
-       ADIS16204_SCAN_AUX_ADC,
-       ADIS16204_SCAN_TEMP,
-};
-
-#endif /* SPI_ADIS16204_H_ */
diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c
deleted file mode 100644 (file)
index 20a9df6..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * ADIS16204 Programmable High-g Digital Impact Sensor and Recorder
- *
- * Copyright 2010 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/delay.h>
-#include <linux/mutex.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/slab.h>
-#include <linux/sysfs.h>
-#include <linux/list.h>
-#include <linux/module.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
-#include <linux/iio/buffer.h>
-#include <linux/iio/imu/adis.h>
-
-#include "adis16204.h"
-
-/* Unique to this driver currently */
-
-static const u8 adis16204_addresses[][2] = {
-       [ADIS16204_SCAN_ACC_X] = { ADIS16204_XACCL_NULL, ADIS16204_X_PEAK_OUT },
-       [ADIS16204_SCAN_ACC_Y] = { ADIS16204_YACCL_NULL, ADIS16204_Y_PEAK_OUT },
-       [ADIS16204_SCAN_ACC_XY] = { 0, ADIS16204_XY_PEAK_OUT },
-};
-
-static int adis16204_read_raw(struct iio_dev *indio_dev,
-                             struct iio_chan_spec const *chan,
-                             int *val, int *val2,
-                             long mask)
-{
-       struct adis *st = iio_priv(indio_dev);
-       int ret;
-       int bits;
-       u8 addr;
-       s16 val16;
-       int addrind;
-
-       switch (mask) {
-       case IIO_CHAN_INFO_RAW:
-               return adis_single_conversion(indio_dev, chan,
-                               ADIS16204_ERROR_ACTIVE, val);
-       case IIO_CHAN_INFO_SCALE:
-               switch (chan->type) {
-               case IIO_VOLTAGE:
-                       if (chan->channel == 0) {
-                               *val = 1;
-                               *val2 = 220000; /* 1.22 mV */
-                       } else {
-                               *val = 0;
-                               *val2 = 610000; /* 0.61 mV */
-                       }
-                       return IIO_VAL_INT_PLUS_MICRO;
-               case IIO_TEMP:
-                       *val = -470; /* 0.47 C */
-                       *val2 = 0;
-                       return IIO_VAL_INT_PLUS_MICRO;
-               case IIO_ACCEL:
-                       *val = 0;
-                       switch (chan->channel2) {
-                       case IIO_MOD_X:
-                       case IIO_MOD_ROOT_SUM_SQUARED_X_Y:
-                               *val2 = IIO_G_TO_M_S_2(17125); /* 17.125 mg */
-                               break;
-                       case IIO_MOD_Y:
-                       case IIO_MOD_Z:
-                               *val2 = IIO_G_TO_M_S_2(8407); /* 8.407 mg */
-                               break;
-                       }
-                       return IIO_VAL_INT_PLUS_MICRO;
-               default:
-                       return -EINVAL;
-               }
-               break;
-       case IIO_CHAN_INFO_OFFSET:
-               *val = 25000 / -470 - 1278; /* 25 C = 1278 */
-               return IIO_VAL_INT;
-       case IIO_CHAN_INFO_CALIBBIAS:
-       case IIO_CHAN_INFO_PEAK:
-               if (mask == IIO_CHAN_INFO_CALIBBIAS) {
-                       bits = 12;
-                       addrind = 0;
-               } else { /* PEAK_SEPARATE */
-                       bits = 14;
-                       addrind = 1;
-               }
-               mutex_lock(&indio_dev->mlock);
-               addr = adis16204_addresses[chan->scan_index][addrind];
-               ret = adis_read_reg_16(st, addr, &val16);
-               if (ret) {
-                       mutex_unlock(&indio_dev->mlock);
-                       return ret;
-               }
-               val16 &= (1 << bits) - 1;
-               val16 = (s16)(val16 << (16 - bits)) >> (16 - bits);
-               *val = val16;
-               mutex_unlock(&indio_dev->mlock);
-               return IIO_VAL_INT;
-       }
-       return -EINVAL;
-}
-
-static int adis16204_write_raw(struct iio_dev *indio_dev,
-                              struct iio_chan_spec const *chan,
-                              int val,
-                              int val2,
-                              long mask)
-{
-       struct adis *st = iio_priv(indio_dev);
-       int bits;
-       s16 val16;
-       u8 addr;
-
-       switch (mask) {
-       case IIO_CHAN_INFO_CALIBBIAS:
-               switch (chan->type) {
-               case IIO_ACCEL:
-                       bits = 12;
-                       break;
-               default:
-                       return -EINVAL;
-               }
-               val16 = val & ((1 << bits) - 1);
-               addr = adis16204_addresses[chan->scan_index][1];
-               return adis_write_reg_16(st, addr, val16);
-       }
-       return -EINVAL;
-}
-
-static const struct iio_chan_spec adis16204_channels[] = {
-       ADIS_SUPPLY_CHAN(ADIS16204_SUPPLY_OUT, ADIS16204_SCAN_SUPPLY, 0, 12),
-       ADIS_AUX_ADC_CHAN(ADIS16204_AUX_ADC, ADIS16204_SCAN_AUX_ADC, 0, 12),
-       ADIS_TEMP_CHAN(ADIS16204_TEMP_OUT, ADIS16204_SCAN_TEMP, 0, 12),
-       ADIS_ACCEL_CHAN(X, ADIS16204_XACCL_OUT, ADIS16204_SCAN_ACC_X,
-                       BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK),
-                       0, 14),
-       ADIS_ACCEL_CHAN(Y, ADIS16204_YACCL_OUT, ADIS16204_SCAN_ACC_Y,
-                       BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_PEAK),
-                       0, 14),
-       ADIS_ACCEL_CHAN(ROOT_SUM_SQUARED_X_Y, ADIS16204_XY_RSS_OUT,
-                       ADIS16204_SCAN_ACC_XY, BIT(IIO_CHAN_INFO_PEAK), 0, 14),
-       IIO_CHAN_SOFT_TIMESTAMP(5),
-};
-
-static const struct iio_info adis16204_info = {
-       .read_raw = &adis16204_read_raw,
-       .write_raw = &adis16204_write_raw,
-       .update_scan_mode = adis_update_scan_mode,
-       .driver_module = THIS_MODULE,
-};
-
-static const char * const adis16204_status_error_msgs[] = {
-       [ADIS16204_DIAG_STAT_SELFTEST_FAIL_BIT] = "Self test failure",
-       [ADIS16204_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure",
-       [ADIS16204_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed",
-       [ADIS16204_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V",
-       [ADIS16204_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 2.975V",
-};
-
-static const struct adis_data adis16204_data = {
-       .read_delay = 20,
-       .msc_ctrl_reg = ADIS16204_MSC_CTRL,
-       .glob_cmd_reg = ADIS16204_GLOB_CMD,
-       .diag_stat_reg = ADIS16204_DIAG_STAT,
-
-       .self_test_mask = ADIS16204_MSC_CTRL_SELF_TEST_EN,
-       .startup_delay = ADIS16204_STARTUP_DELAY,
-
-       .status_error_msgs = adis16204_status_error_msgs,
-       .status_error_mask = BIT(ADIS16204_DIAG_STAT_SELFTEST_FAIL_BIT) |
-               BIT(ADIS16204_DIAG_STAT_SPI_FAIL_BIT) |
-               BIT(ADIS16204_DIAG_STAT_FLASH_UPT_BIT) |
-               BIT(ADIS16204_DIAG_STAT_POWER_HIGH_BIT) |
-               BIT(ADIS16204_DIAG_STAT_POWER_LOW_BIT),
-};
-
-static int adis16204_probe(struct spi_device *spi)
-{
-       int ret;
-       struct adis *st;
-       struct iio_dev *indio_dev;
-
-       /* setup the industrialio driver allocated elements */
-       indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
-       if (!indio_dev)
-               return -ENOMEM;
-       st = iio_priv(indio_dev);
-       /* this is only used for removal purposes */
-       spi_set_drvdata(spi, indio_dev);
-
-       indio_dev->name = spi->dev.driver->name;
-       indio_dev->dev.parent = &spi->dev;
-       indio_dev->info = &adis16204_info;
-       indio_dev->channels = adis16204_channels;
-       indio_dev->num_channels = ARRAY_SIZE(adis16204_channels);
-       indio_dev->modes = INDIO_DIRECT_MODE;
-
-       ret = adis_init(st, indio_dev, spi, &adis16204_data);
-       if (ret)
-               return ret;
-
-       ret = adis_setup_buffer_and_trigger(st, indio_dev, NULL);
-       if (ret)
-               return ret;
-
-       /* Get the device into a sane initial state */
-       ret = adis_initial_startup(st);
-       if (ret)
-               goto error_cleanup_buffer_trigger;
-       ret = iio_device_register(indio_dev);
-       if (ret)
-               goto error_cleanup_buffer_trigger;
-
-       return 0;
-
-error_cleanup_buffer_trigger:
-       adis_cleanup_buffer_and_trigger(st, indio_dev);
-       return ret;
-}
-
-static int adis16204_remove(struct spi_device *spi)
-{
-       struct iio_dev *indio_dev = spi_get_drvdata(spi);
-       struct adis *st = iio_priv(indio_dev);
-
-       iio_device_unregister(indio_dev);
-       adis_cleanup_buffer_and_trigger(st, indio_dev);
-
-       return 0;
-}
-
-static struct spi_driver adis16204_driver = {
-       .driver = {
-               .name = "adis16204",
-       },
-       .probe = adis16204_probe,
-       .remove = adis16204_remove,
-};
-module_spi_driver(adis16204_driver);
-
-MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
-MODULE_DESCRIPTION("ADIS16204 High-g Digital Impact Sensor and Recorder");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("spi:adis16204");
diff --git a/drivers/staging/iio/accel/adis16220.h b/drivers/staging/iio/accel/adis16220.h
deleted file mode 100644 (file)
index 31a1268..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-#ifndef SPI_ADIS16220_H_
-#define SPI_ADIS16220_H_
-
-#include <linux/iio/imu/adis.h>
-
-#define ADIS16220_STARTUP_DELAY        220 /* ms */
-
-/* Flash memory write count */
-#define ADIS16220_FLASH_CNT     0x00
-
-/* Control, acceleration offset adjustment control */
-#define ADIS16220_ACCL_NULL     0x02
-
-/* Control, AIN1 offset adjustment control */
-#define ADIS16220_AIN1_NULL     0x04
-
-/* Control, AIN2 offset adjustment control */
-#define ADIS16220_AIN2_NULL     0x06
-
-/* Output, power supply during capture */
-#define ADIS16220_CAPT_SUPPLY   0x0A
-
-/* Output, temperature during capture */
-#define ADIS16220_CAPT_TEMP     0x0C
-
-/* Output, peak acceleration during capture */
-#define ADIS16220_CAPT_PEAKA    0x0E
-
-/* Output, peak AIN1 level during capture */
-#define ADIS16220_CAPT_PEAK1    0x10
-
-/* Output, peak AIN2 level during capture */
-#define ADIS16220_CAPT_PEAK2    0x12
-
-/* Output, capture buffer for acceleration */
-#define ADIS16220_CAPT_BUFA     0x14
-
-/* Output, capture buffer for AIN1 */
-#define ADIS16220_CAPT_BUF1     0x16
-
-/* Output, capture buffer for AIN2 */
-#define ADIS16220_CAPT_BUF2     0x18
-
-/* Control, capture buffer address pointer */
-#define ADIS16220_CAPT_PNTR     0x1A
-
-/* Control, capture control register */
-#define ADIS16220_CAPT_CTRL     0x1C
-
-/* Control, capture period (automatic mode) */
-#define ADIS16220_CAPT_PRD      0x1E
-
-/* Control, Alarm A, acceleration peak threshold */
-#define ADIS16220_ALM_MAGA      0x20
-
-/* Control, Alarm 1, AIN1 peak threshold */
-#define ADIS16220_ALM_MAG1      0x22
-
-/* Control, Alarm 2, AIN2 peak threshold */
-#define ADIS16220_ALM_MAG2      0x24
-
-/* Control, Alarm S, peak threshold */
-#define ADIS16220_ALM_MAGS      0x26
-
-/* Control, alarm configuration register */
-#define ADIS16220_ALM_CTRL      0x28
-
-/* Control, general I/O configuration */
-#define ADIS16220_GPIO_CTRL     0x32
-
-/* Control, self-test control, AIN configuration */
-#define ADIS16220_MSC_CTRL      0x34
-
-/* Control, digital I/O configuration */
-#define ADIS16220_DIO_CTRL      0x36
-
-/* Control, filter configuration */
-#define ADIS16220_AVG_CNT       0x38
-
-/* Status, system status */
-#define ADIS16220_DIAG_STAT     0x3C
-
-/* Control, system commands */
-#define ADIS16220_GLOB_CMD      0x3E
-
-/* Status, self-test response */
-#define ADIS16220_ST_DELTA      0x40
-
-/* Lot Identification Code 1 */
-#define ADIS16220_LOT_ID1       0x52
-
-/* Lot Identification Code 2 */
-#define ADIS16220_LOT_ID2       0x54
-
-/* Product identifier; convert to decimal = 16220 */
-#define ADIS16220_PROD_ID       0x56
-
-/* Serial number */
-#define ADIS16220_SERIAL_NUM    0x58
-
-#define ADIS16220_CAPTURE_SIZE  2048
-
-/* MSC_CTRL */
-
-#define ADIS16220_MSC_CTRL_SELF_TEST_EN                BIT(8)
-#define ADIS16220_MSC_CTRL_POWER_SUP_COM_AIN1  BIT(1)
-#define ADIS16220_MSC_CTRL_POWER_SUP_COM_AIN2  BIT(0)
-
-/* DIO_CTRL */
-
-#define ADIS16220_MSC_CTRL_DIO2_BUSY_IND     (BIT(5) | BIT(4))
-#define ADIS16220_MSC_CTRL_DIO1_BUSY_IND     (BIT(3) | BIT(2))
-#define ADIS16220_MSC_CTRL_DIO2_ACT_HIGH     BIT(1)
-#define ADIS16220_MSC_CTRL_DIO1_ACT_HIGH     BIT(0)
-
-/* DIAG_STAT */
-
-/* AIN2 sample > ALM_MAG2 */
-#define ADIS16220_DIAG_STAT_ALM_MAG2    BIT(14)
-
-/* AIN1 sample > ALM_MAG1 */
-#define ADIS16220_DIAG_STAT_ALM_MAG1    BIT(13)
-
-/* Acceleration sample > ALM_MAGA */
-#define ADIS16220_DIAG_STAT_ALM_MAGA    BIT(12)
-
-/* Error condition programmed into ALM_MAGS[11:0] and ALM_CTRL[5:4] is true */
-#define ADIS16220_DIAG_STAT_ALM_MAGS    BIT(11)
-
-/* |Peak value in AIN2 data capture| > ALM_MAG2 */
-#define ADIS16220_DIAG_STAT_PEAK_AIN2   BIT(10)
-
-/* |Peak value in AIN1 data capture| > ALM_MAG1 */
-#define ADIS16220_DIAG_STAT_PEAK_AIN1   BIT(9)
-
-/* |Peak value in acceleration data capture| > ALM_MAGA */
-#define ADIS16220_DIAG_STAT_PEAK_ACCEL  BIT(8)
-
-/* Data ready, capture complete */
-#define ADIS16220_DIAG_STAT_DATA_RDY    BIT(7)
-
-#define ADIS16220_DIAG_STAT_FLASH_CHK  BIT(6)
-
-#define ADIS16220_DIAG_STAT_SELF_TEST  BIT(5)
-
-/* Capture period violation/interruption */
-#define ADIS16220_DIAG_STAT_VIOLATION_BIT      4
-
-/* SPI communications failure */
-#define ADIS16220_DIAG_STAT_SPI_FAIL_BIT       3
-
-/* Flash update failure */
-#define ADIS16220_DIAG_STAT_FLASH_UPT_BIT      2
-
-/* Power supply above 3.625 V */
-#define ADIS16220_DIAG_STAT_POWER_HIGH_BIT     1
-
-/* Power supply below 3.15 V */
-#define ADIS16220_DIAG_STAT_POWER_LOW_BIT      0
-
-/* GLOB_CMD */
-
-#define ADIS16220_GLOB_CMD_SW_RESET    BIT(7)
-#define ADIS16220_GLOB_CMD_SELF_TEST   BIT(2)
-#define ADIS16220_GLOB_CMD_PWR_DOWN    BIT(1)
-
-#define ADIS16220_MAX_TX 2048
-#define ADIS16220_MAX_RX 2048
-
-#define ADIS16220_SPI_BURST    (u32)(1000 * 1000)
-#define ADIS16220_SPI_FAST     (u32)(2000 * 1000)
-
-/**
- * struct adis16220_state - device instance specific data
- * @adis:              adis device
- * @tx:                        transmit buffer
- * @rx:                        receive buffer
- * @buf_lock:          mutex to protect tx and rx
- **/
-struct adis16220_state {
-       struct adis adis;
-
-       struct mutex            buf_lock;
-       u8                      tx[ADIS16220_MAX_TX] ____cacheline_aligned;
-       u8                      rx[ADIS16220_MAX_RX];
-};
-
-#endif /* SPI_ADIS16220_H_ */
diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c
deleted file mode 100644 (file)
index d016521..0000000
+++ /dev/null
@@ -1,494 +0,0 @@
-/*
- * ADIS16220 Programmable Digital Vibration Sensor driver
- *
- * Copyright 2010 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/delay.h>
-#include <linux/mutex.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/slab.h>
-#include <linux/sysfs.h>
-#include <linux/module.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
-
-#include "adis16220.h"
-
-static ssize_t adis16220_read_16bit(struct device *dev,
-                                   struct device_attribute *attr,
-                                   char *buf)
-{
-       struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-       struct adis16220_state *st = iio_priv(indio_dev);
-       ssize_t ret;
-       u16 val;
-
-       /* Take the iio_dev status lock */
-       mutex_lock(&indio_dev->mlock);
-       ret = adis_read_reg_16(&st->adis, this_attr->address, &val);
-       mutex_unlock(&indio_dev->mlock);
-       if (ret)
-               return ret;
-       return sprintf(buf, "%u\n", val);
-}
-
-static ssize_t adis16220_write_16bit(struct device *dev,
-                                    struct device_attribute *attr,
-                                    const char *buf,
-                                    size_t len)
-{
-       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-       struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-       struct adis16220_state *st = iio_priv(indio_dev);
-       int ret;
-       u16 val;
-
-       ret = kstrtou16(buf, 10, &val);
-       if (ret)
-               goto error_ret;
-       ret = adis_write_reg_16(&st->adis, this_attr->address, val);
-
-error_ret:
-       return ret ? ret : len;
-}
-
-static int adis16220_capture(struct iio_dev *indio_dev)
-{
-       struct adis16220_state *st = iio_priv(indio_dev);
-       int ret;
-
-        /* initiates a manual data capture */
-       ret = adis_write_reg_16(&st->adis, ADIS16220_GLOB_CMD, 0xBF08);
-       if (ret)
-               dev_err(&indio_dev->dev, "problem beginning capture");
-
-       usleep_range(10000, 11000); /* delay for capture to finish */
-
-       return ret;
-}
-
-static ssize_t adis16220_write_capture(struct device *dev,
-                                      struct device_attribute *attr,
-                                      const char *buf, size_t len)
-{
-       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-       bool val;
-       int ret;
-
-       ret = strtobool(buf, &val);
-       if (ret)
-               return ret;
-       if (!val)
-               return -EINVAL;
-       ret = adis16220_capture(indio_dev);
-       if (ret)
-               return ret;
-
-       return len;
-}
-
-static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev,
-                                            char *buf,
-                                            loff_t off,
-                                            size_t count,
-                                            int addr)
-{
-       struct adis16220_state *st = iio_priv(indio_dev);
-       struct spi_transfer xfers[] = {
-               {
-                       .tx_buf = st->tx,
-                       .bits_per_word = 8,
-                       .len = 2,
-                       .cs_change = 1,
-                       .delay_usecs = 25,
-               }, {
-                       .tx_buf = st->tx,
-                       .rx_buf = st->rx,
-                       .bits_per_word = 8,
-                       .cs_change = 1,
-                       .delay_usecs = 25,
-               },
-       };
-       int ret;
-       int i;
-
-       if (unlikely(!count))
-               return count;
-
-       if ((off >= ADIS16220_CAPTURE_SIZE) || (count & 1) || (off & 1))
-               return -EINVAL;
-
-       if (off + count > ADIS16220_CAPTURE_SIZE)
-               count = ADIS16220_CAPTURE_SIZE - off;
-
-       /* write the begin position of capture buffer */
-       ret = adis_write_reg_16(&st->adis,
-                               ADIS16220_CAPT_PNTR,
-                               off > 1);
-       if (ret)
-               return -EIO;
-
-       /* read count/2 values from capture buffer */
-       mutex_lock(&st->buf_lock);
-
-       for (i = 0; i < count; i += 2) {
-               st->tx[i] = ADIS_READ_REG(addr);
-               st->tx[i + 1] = 0;
-       }
-       xfers[1].len = count;
-
-       ret = spi_sync_transfer(st->adis.spi, xfers, ARRAY_SIZE(xfers));
-       if (ret) {
-               mutex_unlock(&st->buf_lock);
-               return -EIO;
-       }
-
-       memcpy(buf, st->rx, count);
-
-       mutex_unlock(&st->buf_lock);
-       return count;
-}
-
-static ssize_t adis16220_accel_bin_read(struct file *filp, struct kobject *kobj,
-                                       struct bin_attribute *attr,
-                                       char *buf,
-                                       loff_t off,
-                                       size_t count)
-{
-       struct iio_dev *indio_dev = dev_to_iio_dev(kobj_to_dev(kobj));
-
-       return adis16220_capture_buffer_read(indio_dev, buf,
-                                       off, count,
-                                       ADIS16220_CAPT_BUFA);
-}
-
-static struct bin_attribute accel_bin = {
-       .attr = {
-               .name = "accel_bin",
-               .mode = S_IRUGO,
-       },
-       .read = adis16220_accel_bin_read,
-       .size = ADIS16220_CAPTURE_SIZE,
-};
-
-static ssize_t adis16220_adc1_bin_read(struct file *filp, struct kobject *kobj,
-                                      struct bin_attribute *attr,
-                                      char *buf, loff_t off,
-                                      size_t count)
-{
-       struct iio_dev *indio_dev = dev_to_iio_dev(kobj_to_dev(kobj));
-
-       return adis16220_capture_buffer_read(indio_dev, buf,
-                                       off, count,
-                                       ADIS16220_CAPT_BUF1);
-}
-
-static struct bin_attribute adc1_bin = {
-       .attr = {
-               .name = "in0_bin",
-               .mode = S_IRUGO,
-       },
-       .read =  adis16220_adc1_bin_read,
-       .size = ADIS16220_CAPTURE_SIZE,
-};
-
-static ssize_t adis16220_adc2_bin_read(struct file *filp, struct kobject *kobj,
-                                      struct bin_attribute *attr,
-                                      char *buf, loff_t off,
-                                      size_t count)
-{
-       struct iio_dev *indio_dev = dev_to_iio_dev(kobj_to_dev(kobj));
-
-       return adis16220_capture_buffer_read(indio_dev, buf,
-                                       off, count,
-                                       ADIS16220_CAPT_BUF2);
-}
-
-static struct bin_attribute adc2_bin = {
-       .attr = {
-               .name = "in1_bin",
-               .mode = S_IRUGO,
-       },
-       .read =  adis16220_adc2_bin_read,
-       .size = ADIS16220_CAPTURE_SIZE,
-};
-
-#define IIO_DEV_ATTR_CAPTURE(_store)                           \
-       IIO_DEVICE_ATTR(capture, S_IWUSR, NULL, _store, 0)
-
-static IIO_DEV_ATTR_CAPTURE(adis16220_write_capture);
-
-#define IIO_DEV_ATTR_CAPTURE_COUNT(_mode, _show, _store, _addr)                \
-       IIO_DEVICE_ATTR(capture_count, _mode, _show, _store, _addr)
-
-static IIO_DEV_ATTR_CAPTURE_COUNT(S_IWUSR | S_IRUGO,
-               adis16220_read_16bit,
-               adis16220_write_16bit,
-               ADIS16220_CAPT_PNTR);
-
-enum adis16220_channel {
-       in_supply, in_1, in_2, accel, temp
-};
-
-struct adis16220_address_spec {
-       u8 addr;
-       u8 bits;
-       bool sign;
-};
-
-/* Address / bits / signed */
-static const struct adis16220_address_spec adis16220_addresses[][3] = {
-       [in_supply] =   { { ADIS16220_CAPT_SUPPLY,      12, 0 }, },
-       [in_1] =        { { ADIS16220_CAPT_BUF1,        16, 1 },
-                         { ADIS16220_AIN1_NULL,        16, 1 },
-                         { ADIS16220_CAPT_PEAK1,       16, 1 }, },
-       [in_2] =        { { ADIS16220_CAPT_BUF2,        16, 1 },
-                         { ADIS16220_AIN2_NULL,        16, 1 },
-                         { ADIS16220_CAPT_PEAK2,       16, 1 }, },
-       [accel] =       { { ADIS16220_CAPT_BUFA,        16, 1 },
-                         { ADIS16220_ACCL_NULL,        16, 1 },
-                         { ADIS16220_CAPT_PEAKA,       16, 1 }, },
-       [temp] =        { { ADIS16220_CAPT_TEMP,        12, 0 }, }
-};
-
-static int adis16220_read_raw(struct iio_dev *indio_dev,
-                             struct iio_chan_spec const *chan,
-                             int *val, int *val2,
-                             long mask)
-{
-       struct adis16220_state *st = iio_priv(indio_dev);
-       const struct adis16220_address_spec *addr;
-       int ret = -EINVAL;
-       int addrind = 0;
-       u16 uval;
-       s16 sval;
-       u8 bits;
-
-       switch (mask) {
-       case IIO_CHAN_INFO_RAW:
-               addrind = 0;
-               break;
-       case IIO_CHAN_INFO_OFFSET:
-               if (chan->type == IIO_TEMP) {
-                       *val = 25000 / -470 - 1278; /* 25 C = 1278 */
-                       return IIO_VAL_INT;
-               }
-               addrind = 1;
-               break;
-       case IIO_CHAN_INFO_PEAK:
-               addrind = 2;
-               break;
-       case IIO_CHAN_INFO_SCALE:
-               switch (chan->type) {
-               case IIO_TEMP:
-                       *val = -470; /* -0.47 C */
-                       *val2 = 0;
-                       return IIO_VAL_INT_PLUS_MICRO;
-               case IIO_ACCEL:
-                       *val2 = IIO_G_TO_M_S_2(19073); /* 19.073 g */
-                       return IIO_VAL_INT_PLUS_MICRO;
-               case IIO_VOLTAGE:
-                       if (chan->channel == 0) {
-                               *val = 1;
-                               *val2 = 220700; /* 1.2207 mV */
-                       } else {
-                               /* Should really be dependent on VDD */
-                               *val2 = 305180; /* 305.18 uV */
-                       }
-                       return IIO_VAL_INT_PLUS_MICRO;
-               default:
-                       return -EINVAL;
-               }
-       default:
-               return -EINVAL;
-       }
-       addr = &adis16220_addresses[chan->address][addrind];
-       if (addr->sign) {
-               ret = adis_read_reg_16(&st->adis, addr->addr, &sval);
-               if (ret)
-                       return ret;
-               bits = addr->bits;
-               sval &= (1 << bits) - 1;
-               sval = (s16)(sval << (16 - bits)) >> (16 - bits);
-               *val = sval;
-               return IIO_VAL_INT;
-       }
-       ret = adis_read_reg_16(&st->adis, addr->addr, &uval);
-       if (ret)
-               return ret;
-       bits = addr->bits;
-       uval &= (1 << bits) - 1;
-       *val = uval;
-       return IIO_VAL_INT;
-}
-
-static const struct iio_chan_spec adis16220_channels[] = {
-       {
-               .type = IIO_VOLTAGE,
-               .indexed = 1,
-               .channel = 0,
-               .extend_name = "supply",
-               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
-                       BIT(IIO_CHAN_INFO_SCALE),
-               .address = in_supply,
-       }, {
-               .type = IIO_ACCEL,
-               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
-                       BIT(IIO_CHAN_INFO_OFFSET) |
-                       BIT(IIO_CHAN_INFO_SCALE) |
-                       BIT(IIO_CHAN_INFO_PEAK),
-               .address = accel,
-       }, {
-               .type = IIO_TEMP,
-               .indexed = 1,
-               .channel = 0,
-               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
-                       BIT(IIO_CHAN_INFO_OFFSET) |
-                       BIT(IIO_CHAN_INFO_SCALE),
-               .address = temp,
-       }, {
-               .type = IIO_VOLTAGE,
-               .indexed = 1,
-               .channel = 1,
-               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
-                       BIT(IIO_CHAN_INFO_OFFSET) |
-                       BIT(IIO_CHAN_INFO_SCALE),
-               .address = in_1,
-       }, {
-               .type = IIO_VOLTAGE,
-               .indexed = 1,
-               .channel = 2,
-               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
-               .address = in_2,
-       }
-};
-
-static struct attribute *adis16220_attributes[] = {
-       &iio_dev_attr_capture.dev_attr.attr,
-       &iio_dev_attr_capture_count.dev_attr.attr,
-       NULL
-};
-
-static const struct attribute_group adis16220_attribute_group = {
-       .attrs = adis16220_attributes,
-};
-
-static const struct iio_info adis16220_info = {
-       .attrs = &adis16220_attribute_group,
-       .driver_module = THIS_MODULE,
-       .read_raw = &adis16220_read_raw,
-};
-
-static const char * const adis16220_status_error_msgs[] = {
-       [ADIS16220_DIAG_STAT_VIOLATION_BIT] = "Capture period violation/interruption",
-       [ADIS16220_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure",
-       [ADIS16220_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed",
-       [ADIS16220_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V",
-       [ADIS16220_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 3.15V",
-};
-
-static const struct adis_data adis16220_data = {
-       .read_delay = 35,
-       .write_delay = 35,
-       .msc_ctrl_reg = ADIS16220_MSC_CTRL,
-       .glob_cmd_reg = ADIS16220_GLOB_CMD,
-       .diag_stat_reg = ADIS16220_DIAG_STAT,
-
-       .self_test_mask = ADIS16220_MSC_CTRL_SELF_TEST_EN,
-       .startup_delay = ADIS16220_STARTUP_DELAY,
-
-       .status_error_msgs = adis16220_status_error_msgs,
-       .status_error_mask = BIT(ADIS16220_DIAG_STAT_VIOLATION_BIT) |
-               BIT(ADIS16220_DIAG_STAT_SPI_FAIL_BIT) |
-               BIT(ADIS16220_DIAG_STAT_FLASH_UPT_BIT) |
-               BIT(ADIS16220_DIAG_STAT_POWER_HIGH_BIT) |
-               BIT(ADIS16220_DIAG_STAT_POWER_LOW_BIT),
-};
-
-static int adis16220_probe(struct spi_device *spi)
-{
-       int ret;
-       struct adis16220_state *st;
-       struct iio_dev *indio_dev;
-
-       /* setup the industrialio driver allocated elements */
-       indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
-       if (!indio_dev)
-               return -ENOMEM;
-
-       st = iio_priv(indio_dev);
-       /* this is only used for removal purposes */
-       spi_set_drvdata(spi, indio_dev);
-
-       indio_dev->name = spi->dev.driver->name;
-       indio_dev->dev.parent = &spi->dev;
-       indio_dev->info = &adis16220_info;
-       indio_dev->modes = INDIO_DIRECT_MODE;
-       indio_dev->channels = adis16220_channels;
-       indio_dev->num_channels = ARRAY_SIZE(adis16220_channels);
-
-       ret = devm_iio_device_register(&spi->dev, indio_dev);
-       if (ret)
-               return ret;
-
-       ret = sysfs_create_bin_file(&indio_dev->dev.kobj, &accel_bin);
-       if (ret)
-               return ret;
-
-       ret = sysfs_create_bin_file(&indio_dev->dev.kobj, &adc1_bin);
-       if (ret)
-               goto error_rm_accel_bin;
-
-       ret = sysfs_create_bin_file(&indio_dev->dev.kobj, &adc2_bin);
-       if (ret)
-               goto error_rm_adc1_bin;
-
-       ret = adis_init(&st->adis, indio_dev, spi, &adis16220_data);
-       if (ret)
-               goto error_rm_adc2_bin;
-       /* Get the device into a sane initial state */
-       ret = adis_initial_startup(&st->adis);
-       if (ret)
-               goto error_rm_adc2_bin;
-       return 0;
-
-error_rm_adc2_bin:
-       sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc2_bin);
-error_rm_adc1_bin:
-       sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc1_bin);
-error_rm_accel_bin:
-       sysfs_remove_bin_file(&indio_dev->dev.kobj, &accel_bin);
-       return ret;
-}
-
-static int adis16220_remove(struct spi_device *spi)
-{
-       struct iio_dev *indio_dev = spi_get_drvdata(spi);
-
-       sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc2_bin);
-       sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc1_bin);
-       sysfs_remove_bin_file(&indio_dev->dev.kobj, &accel_bin);
-
-       return 0;
-}
-
-static struct spi_driver adis16220_driver = {
-       .driver = {
-               .name = "adis16220",
-       },
-       .probe = adis16220_probe,
-       .remove = adis16220_remove,
-};
-module_spi_driver(adis16220_driver);
-
-MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
-MODULE_DESCRIPTION("Analog Devices ADIS16220 Digital Vibration Sensor");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("spi:adis16220");
index f91468e..1cf6b79 100644 (file)
@@ -349,11 +349,9 @@ static ssize_t ad7192_write_frequency(struct device *dev,
        if (lval == 0)
                return -EINVAL;
 
-       mutex_lock(&indio_dev->mlock);
-       if (iio_buffer_enabled(indio_dev)) {
-               mutex_unlock(&indio_dev->mlock);
-               return -EBUSY;
-       }
+       ret = iio_device_claim_direct_mode(indio_dev);
+       if (ret)
+               return ret;
 
        div = st->mclk / (lval * st->f_order * 1024);
        if (div < 1 || div > 1023) {
@@ -366,7 +364,7 @@ static ssize_t ad7192_write_frequency(struct device *dev,
        ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode);
 
 out:
-       mutex_unlock(&indio_dev->mlock);
+       iio_device_release_direct_mode(indio_dev);
 
        return ret ? ret : len;
 }
@@ -434,11 +432,9 @@ static ssize_t ad7192_set(struct device *dev,
        if (ret < 0)
                return ret;
 
-       mutex_lock(&indio_dev->mlock);
-       if (iio_buffer_enabled(indio_dev)) {
-               mutex_unlock(&indio_dev->mlock);
-               return -EBUSY;
-       }
+       ret = iio_device_claim_direct_mode(indio_dev);
+       if (ret)
+               return ret;
 
        switch ((u32)this_attr->address) {
        case AD7192_REG_GPOCON:
@@ -461,7 +457,7 @@ static ssize_t ad7192_set(struct device *dev,
                ret = -EINVAL;
        }
 
-       mutex_unlock(&indio_dev->mlock);
+       iio_device_release_direct_mode(indio_dev);
 
        return ret ? ret : len;
 }
@@ -555,11 +551,9 @@ static int ad7192_write_raw(struct iio_dev *indio_dev,
        int ret, i;
        unsigned int tmp;
 
-       mutex_lock(&indio_dev->mlock);
-       if (iio_buffer_enabled(indio_dev)) {
-               mutex_unlock(&indio_dev->mlock);
-               return -EBUSY;
-       }
+       ret = iio_device_claim_direct_mode(indio_dev);
+       if (ret)
+               return ret;
 
        switch (mask) {
        case IIO_CHAN_INFO_SCALE:
@@ -582,7 +576,7 @@ static int ad7192_write_raw(struct iio_dev *indio_dev,
                ret = -EINVAL;
        }
 
-       mutex_unlock(&indio_dev->mlock);
+       iio_device_release_direct_mode(indio_dev);
 
        return ret;
 }
index 62e5eca..a06b46c 100644 (file)
@@ -155,7 +155,7 @@ static void ad7280_crc8_build_table(unsigned char *crc_tab)
        }
 }
 
-static unsigned char ad7280_calc_crc8(unsigned char *crc_tab, unsigned val)
+static unsigned char ad7280_calc_crc8(unsigned char *crc_tab, unsigned int val)
 {
        unsigned char crc;
 
@@ -165,7 +165,7 @@ static unsigned char ad7280_calc_crc8(unsigned char *crc_tab, unsigned val)
        return  crc ^ (val & 0xFF);
 }
 
-static int ad7280_check_crc(struct ad7280_state *st, unsigned val)
+static int ad7280_check_crc(struct ad7280_state *st, unsigned int val)
 {
        unsigned char crc = ad7280_calc_crc8(st->crc_tab, val >> 10);
 
@@ -191,7 +191,7 @@ static void ad7280_delay(struct ad7280_state *st)
                usleep_range(250, 500);
 }
 
-static int __ad7280_read32(struct ad7280_state *st, unsigned *val)
+static int __ad7280_read32(struct ad7280_state *st, unsigned int *val)
 {
        int ret;
        struct spi_transfer t = {
@@ -211,10 +211,10 @@ static int __ad7280_read32(struct ad7280_state *st, unsigned *val)
        return 0;
 }
 
-static int ad7280_write(struct ad7280_state *st, unsigned devaddr,
-                       unsigned addr, bool all, unsigned val)
+static int ad7280_write(struct ad7280_state *st, unsigned int devaddr,
+                       unsigned int addr, bool all, unsigned int val)
 {
-       unsigned reg = devaddr << 27 | addr << 21 |
+       unsigned int reg = devaddr << 27 | addr << 21 |
                        (val & 0xFF) << 13 | all << 12;
 
        reg |= ad7280_calc_crc8(st->crc_tab, reg >> 11) << 3 | 0x2;
@@ -223,11 +223,11 @@ static int ad7280_write(struct ad7280_state *st, unsigned devaddr,
        return spi_write(st->spi, &st->buf[0], 4);
 }
 
-static int ad7280_read(struct ad7280_state *st, unsigned devaddr,
-                      unsigned addr)
+static int ad7280_read(struct ad7280_state *st, unsigned int devaddr,
+                      unsigned int addr)
 {
        int ret;
-       unsigned tmp;
+       unsigned int tmp;
 
        /* turns off the read operation on all parts */
        ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_HB, 1,
@@ -261,11 +261,11 @@ static int ad7280_read(struct ad7280_state *st, unsigned devaddr,
        return (tmp >> 13) & 0xFF;
 }
 
-static int ad7280_read_channel(struct ad7280_state *st, unsigned devaddr,
-                              unsigned addr)
+static int ad7280_read_channel(struct ad7280_state *st, unsigned int devaddr,
+                              unsigned int addr)
 {
        int ret;
-       unsigned tmp;
+       unsigned int tmp;
 
        ret = ad7280_write(st, devaddr, AD7280A_READ, 0, addr << 2);
        if (ret)
@@ -299,11 +299,11 @@ static int ad7280_read_channel(struct ad7280_state *st, unsigned devaddr,
        return (tmp >> 11) & 0xFFF;
 }
 
-static int ad7280_read_all_channels(struct ad7280_state *st, unsigned cnt,
-                                   unsigned *array)
+static int ad7280_read_all_channels(struct ad7280_state *st, unsigned int cnt,
+                                   unsigned int *array)
 {
        int i, ret;
-       unsigned tmp, sum = 0;
+       unsigned int tmp, sum = 0;
 
        ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_READ, 1,
                           AD7280A_CELL_VOLTAGE_1 << 2);
@@ -338,7 +338,7 @@ static int ad7280_read_all_channels(struct ad7280_state *st, unsigned cnt,
 
 static int ad7280_chain_setup(struct ad7280_state *st)
 {
-       unsigned val, n;
+       unsigned int val, n;
        int ret;
 
        ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CONTROL_LB, 1,
@@ -401,7 +401,7 @@ static ssize_t ad7280_store_balance_sw(struct device *dev,
        struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
        bool readin;
        int ret;
-       unsigned devaddr, ch;
+       unsigned int devaddr, ch;
 
        ret = strtobool(buf, &readin);
        if (ret)
@@ -431,7 +431,7 @@ static ssize_t ad7280_show_balance_timer(struct device *dev,
        struct ad7280_state *st = iio_priv(indio_dev);
        struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
        int ret;
-       unsigned msecs;
+       unsigned int msecs;
 
        mutex_lock(&indio_dev->mlock);
        ret = ad7280_read(st, this_attr->address >> 8,
@@ -602,7 +602,7 @@ static ssize_t ad7280_read_channel_config(struct device *dev,
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
        struct ad7280_state *st = iio_priv(indio_dev);
        struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-       unsigned val;
+       unsigned int val;
 
        switch ((u32)this_attr->address) {
        case AD7280A_CELL_OVERVOLTAGE:
@@ -683,7 +683,7 @@ static irqreturn_t ad7280_event_handler(int irq, void *private)
 {
        struct iio_dev *indio_dev = private;
        struct ad7280_state *st = iio_priv(indio_dev);
-       unsigned *channels;
+       unsigned int *channels;
        int i, ret;
 
        channels = kcalloc(st->scan_cnt, sizeof(*channels), GFP_KERNEL);
index 732347a..ccfb90d 100644 (file)
 #define AD7280A_ALERT_REMOVE_AUX4_AUX5         BIT(1)
 
 struct ad7280_platform_data {
-       unsigned acquisition_time;
-       unsigned conversion_averaging;
-       unsigned chain_last_alert_ignore;
-       bool thermistor_term_en;
+       unsigned int            acquisition_time;
+       unsigned int            conversion_averaging;
+       unsigned int            chain_last_alert_ignore;
+       bool                    thermistor_term_en;
 };
 
 #endif /* IIO_ADC_AD7280_H_ */
index cca9469..39f5044 100644 (file)
  */
 
 struct ad7606_platform_data {
-       unsigned                        default_os;
-       unsigned                        default_range;
-       unsigned                        gpio_convst;
-       unsigned                        gpio_reset;
-       unsigned                        gpio_range;
-       unsigned                        gpio_os0;
-       unsigned                        gpio_os1;
-       unsigned                        gpio_os2;
-       unsigned                        gpio_frstdata;
-       unsigned                        gpio_stby;
+       unsigned int                    default_os;
+       unsigned int                    default_range;
+       unsigned int                    gpio_convst;
+       unsigned int                    gpio_reset;
+       unsigned int                    gpio_range;
+       unsigned int                    gpio_os0;
+       unsigned int                    gpio_os1;
+       unsigned int                    gpio_os2;
+       unsigned int                    gpio_frstdata;
+       unsigned int                    gpio_stby;
 };
 
 /**
@@ -52,7 +52,7 @@ struct ad7606_chip_info {
        const char                      *name;
        u16                             int_vref_mv;
        const struct iio_chan_spec      *channels;
-       unsigned                        num_channels;
+       unsigned int                    num_channels;
 };
 
 /**
@@ -67,8 +67,8 @@ struct ad7606_state {
        struct work_struct              poll_work;
        wait_queue_head_t               wq_data_avail;
        const struct ad7606_bus_ops     *bops;
-       unsigned                        range;
-       unsigned                        oversampling;
+       unsigned int                    range;
+       unsigned int                    oversampling;
        bool                            done;
        void __iomem                    *base_address;
 
@@ -86,7 +86,7 @@ struct ad7606_bus_ops {
 };
 
 struct iio_dev *ad7606_probe(struct device *dev, int irq,
-                             void __iomem *base_address, unsigned id,
+                             void __iomem *base_address, unsigned int id,
                              const struct ad7606_bus_ops *bops);
 int ad7606_remove(struct iio_dev *indio_dev, int irq);
 int ad7606_reset(struct ad7606_state *st);
index fe6caee..6dbc811 100644 (file)
@@ -36,7 +36,7 @@ int ad7606_reset(struct ad7606_state *st)
        return -ENODEV;
 }
 
-static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned ch)
+static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch)
 {
        struct ad7606_state *st = iio_priv(indio_dev);
        int ret;
@@ -155,7 +155,7 @@ static ssize_t ad7606_show_oversampling_ratio(struct device *dev,
        return sprintf(buf, "%u\n", st->oversampling);
 }
 
-static int ad7606_oversampling_get_index(unsigned val)
+static int ad7606_oversampling_get_index(unsigned int val)
 {
        unsigned char supported[] = {0, 2, 4, 8, 16, 32, 64};
        int i;
@@ -446,7 +446,7 @@ static const struct iio_info ad7606_info_range = {
 
 struct iio_dev *ad7606_probe(struct device *dev, int irq,
                             void __iomem *base_address,
-                            unsigned id,
+                            unsigned int id,
                             const struct ad7606_bus_ops *bops)
 {
        struct ad7606_platform_data *pdata = dev->platform_data;
index 1439cfd..c9a0c2a 100644 (file)
@@ -63,7 +63,7 @@ static int ad7780_set_mode(struct ad_sigma_delta *sigma_delta,
                           enum ad_sigma_delta_mode mode)
 {
        struct ad7780_state *st = ad_sigma_delta_to_ad7780(sigma_delta);
-       unsigned val;
+       unsigned int val;
 
        switch (mode) {
        case AD_SD_MODE_SINGLE:
index e6fdb3d..9f43976 100644 (file)
@@ -101,14 +101,14 @@ struct ad5933_state {
        unsigned long                   mclk_hz;
        unsigned char                   ctrl_hb;
        unsigned char                   ctrl_lb;
-       unsigned                        range_avail[4];
+       unsigned int                    range_avail[4];
        unsigned short                  vref_mv;
        unsigned short                  settling_cycles;
        unsigned short                  freq_points;
-       unsigned                        freq_start;
-       unsigned                        freq_inc;
-       unsigned                        state;
-       unsigned                        poll_time_jiffies;
+       unsigned int                    freq_start;
+       unsigned int                    freq_inc;
+       unsigned int                    state;
+       unsigned int                    poll_time_jiffies;
 };
 
 static struct ad5933_platform_data ad5933_default_pdata  = {
@@ -222,7 +222,7 @@ static int ad5933_wait_busy(struct ad5933_state *st, unsigned char event)
 }
 
 static int ad5933_set_freq(struct ad5933_state *st,
-                          unsigned reg, unsigned long freq)
+                          unsigned int reg, unsigned long freq)
 {
        unsigned long long freqreg;
        union {
@@ -282,7 +282,7 @@ static int ad5933_setup(struct ad5933_state *st)
 static void ad5933_calc_out_ranges(struct ad5933_state *st)
 {
        int i;
-       unsigned normalized_3v3[4] = {1980, 198, 383, 970};
+       unsigned int normalized_3v3[4] = {1980, 198, 383, 970};
 
        for (i = 0; i < 4; i++)
                st->range_avail[i] = normalized_3v3[i] * st->vref_mv / 3300;
index 6e2ba45..2e3b1d6 100644 (file)
@@ -69,7 +69,6 @@ enum als_ir_mode {
 };
 
 struct isl29028_chip {
-       struct device           *dev;
        struct mutex            lock;
        struct regmap           *regmap;
 
@@ -166,20 +165,21 @@ static int isl29028_set_als_ir_mode(struct isl29028_chip *chip,
 
 static int isl29028_read_als_ir(struct isl29028_chip *chip, int *als_ir)
 {
+       struct device *dev = regmap_get_device(chip->regmap);
        unsigned int lsb;
        unsigned int msb;
        int ret;
 
        ret = regmap_read(chip->regmap, ISL29028_REG_ALSIR_L, &lsb);
        if (ret < 0) {
-               dev_err(chip->dev,
+               dev_err(dev,
                        "Error in reading register ALSIR_L err %d\n", ret);
                return ret;
        }
 
        ret = regmap_read(chip->regmap, ISL29028_REG_ALSIR_U, &msb);
        if (ret < 0) {
-               dev_err(chip->dev,
+               dev_err(dev,
                        "Error in reading register ALSIR_U err %d\n", ret);
                return ret;
        }
@@ -190,12 +190,13 @@ static int isl29028_read_als_ir(struct isl29028_chip *chip, int *als_ir)
 
 static int isl29028_read_proxim(struct isl29028_chip *chip, int *prox)
 {
+       struct device *dev = regmap_get_device(chip->regmap);
        unsigned int data;
        int ret;
 
        ret = regmap_read(chip->regmap, ISL29028_REG_PROX_DATA, &data);
        if (ret < 0) {
-               dev_err(chip->dev, "Error in reading register %d, error %d\n",
+               dev_err(dev, "Error in reading register %d, error %d\n",
                        ISL29028_REG_PROX_DATA, ret);
                return ret;
        }
@@ -218,13 +219,14 @@ static int isl29028_proxim_get(struct isl29028_chip *chip, int *prox_data)
 
 static int isl29028_als_get(struct isl29028_chip *chip, int *als_data)
 {
+       struct device *dev = regmap_get_device(chip->regmap);
        int ret;
        int als_ir_data;
 
        if (chip->als_ir_mode != MODE_ALS) {
                ret = isl29028_set_als_ir_mode(chip, MODE_ALS);
                if (ret < 0) {
-                       dev_err(chip->dev,
+                       dev_err(dev,
                                "Error in enabling ALS mode err %d\n", ret);
                        return ret;
                }
@@ -251,12 +253,13 @@ static int isl29028_als_get(struct isl29028_chip *chip, int *als_data)
 
 static int isl29028_ir_get(struct isl29028_chip *chip, int *ir_data)
 {
+       struct device *dev = regmap_get_device(chip->regmap);
        int ret;
 
        if (chip->als_ir_mode != MODE_IR) {
                ret = isl29028_set_als_ir_mode(chip, MODE_IR);
                if (ret < 0) {
-                       dev_err(chip->dev,
+                       dev_err(dev,
                                "Error in enabling IR mode err %d\n", ret);
                        return ret;
                }
@@ -271,25 +274,26 @@ static int isl29028_write_raw(struct iio_dev *indio_dev,
                              int val, int val2, long mask)
 {
        struct isl29028_chip *chip = iio_priv(indio_dev);
+       struct device *dev = regmap_get_device(chip->regmap);
        int ret = -EINVAL;
 
        mutex_lock(&chip->lock);
        switch (chan->type) {
        case IIO_PROXIMITY:
                if (mask != IIO_CHAN_INFO_SAMP_FREQ) {
-                       dev_err(chip->dev,
+                       dev_err(dev,
                                "proximity: mask value 0x%08lx not supported\n",
                                mask);
                        break;
                }
                if (val < 1 || val > 100) {
-                       dev_err(chip->dev,
+                       dev_err(dev,
                                "Samp_freq %d is not in range[1:100]\n", val);
                        break;
                }
                ret = isl29028_set_proxim_sampling(chip, val);
                if (ret < 0) {
-                       dev_err(chip->dev,
+                       dev_err(dev,
                                "Setting proximity samp_freq fail, err %d\n",
                                ret);
                        break;
@@ -299,19 +303,19 @@ static int isl29028_write_raw(struct iio_dev *indio_dev,
 
        case IIO_LIGHT:
                if (mask != IIO_CHAN_INFO_SCALE) {
-                       dev_err(chip->dev,
+                       dev_err(dev,
                                "light: mask value 0x%08lx not supported\n",
                                mask);
                        break;
                }
                if ((val != 125) && (val != 2000)) {
-                       dev_err(chip->dev,
+                       dev_err(dev,
                                "lux scale %d is invalid [125, 2000]\n", val);
                        break;
                }
                ret = isl29028_set_als_scale(chip, val);
                if (ret < 0) {
-                       dev_err(chip->dev,
+                       dev_err(dev,
                                "Setting lux scale fail with error %d\n", ret);
                        break;
                }
@@ -319,7 +323,7 @@ static int isl29028_write_raw(struct iio_dev *indio_dev,
                break;
 
        default:
-               dev_err(chip->dev, "Unsupported channel type\n");
+               dev_err(dev, "Unsupported channel type\n");
                break;
        }
        mutex_unlock(&chip->lock);
@@ -331,6 +335,7 @@ static int isl29028_read_raw(struct iio_dev *indio_dev,
                             int *val, int *val2, long mask)
 {
        struct isl29028_chip *chip = iio_priv(indio_dev);
+       struct device *dev = regmap_get_device(chip->regmap);
        int ret = -EINVAL;
 
        mutex_lock(&chip->lock);
@@ -370,7 +375,7 @@ static int isl29028_read_raw(struct iio_dev *indio_dev,
                break;
 
        default:
-               dev_err(chip->dev, "mask value 0x%08lx not supported\n", mask);
+               dev_err(dev, "mask value 0x%08lx not supported\n", mask);
                break;
        }
        mutex_unlock(&chip->lock);
@@ -417,6 +422,7 @@ static const struct iio_info isl29028_info = {
 
 static int isl29028_chip_init(struct isl29028_chip *chip)
 {
+       struct device *dev = regmap_get_device(chip->regmap);
        int ret;
 
        chip->enable_prox  = false;
@@ -426,35 +432,33 @@ static int isl29028_chip_init(struct isl29028_chip *chip)
 
        ret = regmap_write(chip->regmap, ISL29028_REG_TEST1_MODE, 0x0);
        if (ret < 0) {
-               dev_err(chip->dev, "%s(): write to reg %d failed, err = %d\n",
+               dev_err(dev, "%s(): write to reg %d failed, err = %d\n",
                        __func__, ISL29028_REG_TEST1_MODE, ret);
                return ret;
        }
        ret = regmap_write(chip->regmap, ISL29028_REG_TEST2_MODE, 0x0);
        if (ret < 0) {
-               dev_err(chip->dev, "%s(): write to reg %d failed, err = %d\n",
+               dev_err(dev, "%s(): write to reg %d failed, err = %d\n",
                        __func__, ISL29028_REG_TEST2_MODE, ret);
                return ret;
        }
 
        ret = regmap_write(chip->regmap, ISL29028_REG_CONFIGURE, 0x0);
        if (ret < 0) {
-               dev_err(chip->dev, "%s(): write to reg %d failed, err = %d\n",
+               dev_err(dev, "%s(): write to reg %d failed, err = %d\n",
                        __func__, ISL29028_REG_CONFIGURE, ret);
                return ret;
        }
 
        ret = isl29028_set_proxim_sampling(chip, chip->prox_sampling);
        if (ret < 0) {
-               dev_err(chip->dev, "setting the proximity, err = %d\n",
-                       ret);
+               dev_err(dev, "setting the proximity, err = %d\n", ret);
                return ret;
        }
 
        ret = isl29028_set_als_scale(chip, chip->lux_scale);
        if (ret < 0)
-               dev_err(chip->dev,
-                       "setting als scale failed, err = %d\n", ret);
+               dev_err(dev, "setting als scale failed, err = %d\n", ret);
        return ret;
 }
 
@@ -496,19 +500,19 @@ static int isl29028_probe(struct i2c_client *client,
        chip = iio_priv(indio_dev);
 
        i2c_set_clientdata(client, indio_dev);
-       chip->dev = &client->dev;
        mutex_init(&chip->lock);
 
        chip->regmap = devm_regmap_init_i2c(client, &isl29028_regmap_config);
        if (IS_ERR(chip->regmap)) {
                ret = PTR_ERR(chip->regmap);
-               dev_err(chip->dev, "regmap initialization failed: %d\n", ret);
+               dev_err(&client->dev, "regmap initialization failed: %d\n",
+                       ret);
                return ret;
        }
 
        ret = isl29028_chip_init(chip);
        if (ret < 0) {
-               dev_err(chip->dev, "chip initialization failed: %d\n", ret);
+               dev_err(&client->dev, "chip initialization failed: %d\n", ret);
                return ret;
        }
 
@@ -520,7 +524,8 @@ static int isl29028_probe(struct i2c_client *client,
        indio_dev->modes = INDIO_DIRECT_MODE;
        ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev);
        if (ret < 0) {
-               dev_err(chip->dev, "iio registration fails with error %d\n",
+               dev_err(&client->dev,
+                       "iio registration fails with error %d\n",
                        ret);
                return ret;
        }
index 9a24e02..a6b76d4 100644 (file)
@@ -33,7 +33,7 @@ static int ade7758_spi_read_burst(struct iio_dev *indio_dev)
        return ret;
 }
 
-static int ade7758_write_waveform_type(struct device *dev, unsigned type)
+static int ade7758_write_waveform_type(struct device *dev, unsigned int type)
 {
        int ret;
        u8 reg;
@@ -85,7 +85,7 @@ static irqreturn_t ade7758_trigger_handler(int irq, void *p)
  **/
 static int ade7758_ring_preenable(struct iio_dev *indio_dev)
 {
-       unsigned channel;
+       unsigned int channel;
 
        if (bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
                return -EINVAL;
index c7158f6..e9b2147 100644 (file)
@@ -12,9 +12,9 @@
 #define _AD2S1210_H
 
 struct ad2s1210_platform_data {
-       unsigned sample;
-       unsigned a[2];
-       unsigned res[2];
-       bool gpioin;
+       unsigned int            sample;
+       unsigned int            a[2];
+       unsigned int            res[2];
+       bool                    gpioin;
 };
 #endif /* _AD2S1210_H */
index 8667334..38dca69 100644 (file)
@@ -55,12 +55,12 @@ static struct bfin_timer iio_bfin_timer_code[MAX_BLACKFIN_GPTIMERS] = {
 };
 
 struct bfin_tmr_state {
-       struct iio_trigger *trig;
-       struct bfin_timer *t;
-       unsigned timer_num;
-       bool output_enable;
-       unsigned int duty;
-       int irq;
+       struct iio_trigger      *trig;
+       struct bfin_timer       *t;
+       unsigned int            timer_num;
+       bool                    output_enable;
+       unsigned int            duty;
+       int                     irq;
 };
 
 static int iio_bfin_tmr_set_state(struct iio_trigger *trig, bool state)
index 2ec3ad5..70a5164 100644 (file)
@@ -83,10 +83,12 @@ struct iio_buffer_access_funcs {
  * @access:            [DRIVER] buffer access functions associated with the
  *                     implementation.
  * @scan_el_dev_attr_list:[INTERN] list of scan element related attributes.
+ * @buffer_group:      [INTERN] attributes of the buffer group
  * @scan_el_group:     [DRIVER] attribute group for those attributes not
  *                     created from the iio_chan_info array.
  * @pollq:             [INTERN] wait queue to allow for polling on the buffer.
  * @stufftoread:       [INTERN] flag to indicate new data.
+ * @attrs:             [INTERN] standard attributes of the buffer
  * @demux_list:                [INTERN] list of operations required to demux the scan.
  * @demux_bounce:      [INTERN] buffer for doing gather from incoming scan.
  * @buffer_list:       [INTERN] entry in the devices list of current buffers.
index b2b1677..0b2773a 100644 (file)
@@ -527,6 +527,8 @@ void iio_device_unregister(struct iio_dev *indio_dev);
 int devm_iio_device_register(struct device *dev, struct iio_dev *indio_dev);
 void devm_iio_device_unregister(struct device *dev, struct iio_dev *indio_dev);
 int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp);
+int iio_device_claim_direct_mode(struct iio_dev *indio_dev);
+void iio_device_release_direct_mode(struct iio_dev *indio_dev);
 
 extern struct bus_type iio_bus_type;
 
index c077617..b0916fc 100644 (file)
@@ -38,6 +38,7 @@ enum iio_chan_type {
        IIO_CONCENTRATION,
        IIO_RESISTANCE,
        IIO_PH,
+       IIO_UVINDEX,
 };
 
 enum iio_modifier {
@@ -77,6 +78,7 @@ enum iio_modifier {
        IIO_MOD_Q,
        IIO_MOD_CO2,
        IIO_MOD_VOC,
+       IIO_MOD_LIGHT_UV,
 };
 
 enum iio_event_type {
index 01c4f67..c42b7f8 100644 (file)
@@ -304,7 +304,19 @@ int main(int argc, char **argv)
                        }
                }
 
-               /* Verify the trigger exists */
+               /* Look for this "-devN" trigger */
+               trig_num = find_type_by_name(trigger_name, "trigger");
+               if (trig_num < 0) {
+                       /* OK try the simpler "-trigger" suffix instead */
+                       free(trigger_name);
+                       ret = asprintf(&trigger_name,
+                                      "%s-trigger", device_name);
+                       if (ret < 0) {
+                               ret = -ENOMEM;
+                               goto error_free_dev_dir_name;
+                       }
+               }
+
                trig_num = find_type_by_name(trigger_name, "trigger");
                if (trig_num < 0) {
                        fprintf(stderr, "Failed to find the trigger %s\n",
index d51eb04..d9b7e0f 100644 (file)
@@ -53,6 +53,10 @@ static const char * const iio_chan_type_name_spec[] = {
        [IIO_ENERGY] = "energy",
        [IIO_DISTANCE] = "distance",
        [IIO_VELOCITY] = "velocity",
+       [IIO_CONCENTRATION] = "concentration",
+       [IIO_RESISTANCE] = "resistance",
+       [IIO_PH] = "ph",
+       [IIO_UVINDEX] = "uvindex",
 };
 
 static const char * const iio_ev_type_text[] = {
@@ -90,6 +94,7 @@ static const char * const iio_modifier_names[] = {
        [IIO_MOD_LIGHT_RED] = "red",
        [IIO_MOD_LIGHT_GREEN] = "green",
        [IIO_MOD_LIGHT_BLUE] = "blue",
+       [IIO_MOD_LIGHT_UV] = "uv",
        [IIO_MOD_QUATERNION] = "quaternion",
        [IIO_MOD_TEMP_AMBIENT] = "ambient",
        [IIO_MOD_TEMP_OBJECT] = "object",
@@ -102,6 +107,10 @@ static const char * const iio_modifier_names[] = {
        [IIO_MOD_WALKING] = "walking",
        [IIO_MOD_STILL] = "still",
        [IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z] = "sqrt(x^2+y^2+z^2)",
+       [IIO_MOD_I] = "i",
+       [IIO_MOD_Q] = "q",
+       [IIO_MOD_CO2] = "co2",
+       [IIO_MOD_VOC] = "voc",
 };
 
 static bool event_is_known(struct iio_event_data *event)
@@ -136,6 +145,10 @@ static bool event_is_known(struct iio_event_data *event)
        case IIO_ENERGY:
        case IIO_DISTANCE:
        case IIO_VELOCITY:
+       case IIO_CONCENTRATION:
+       case IIO_RESISTANCE:
+       case IIO_PH:
+       case IIO_UVINDEX:
                break;
        default:
                return false;
@@ -162,6 +175,7 @@ static bool event_is_known(struct iio_event_data *event)
        case IIO_MOD_LIGHT_RED:
        case IIO_MOD_LIGHT_GREEN:
        case IIO_MOD_LIGHT_BLUE:
+       case IIO_MOD_LIGHT_UV:
        case IIO_MOD_QUATERNION:
        case IIO_MOD_TEMP_AMBIENT:
        case IIO_MOD_TEMP_OBJECT:
@@ -174,6 +188,10 @@ static bool event_is_known(struct iio_event_data *event)
        case IIO_MOD_WALKING:
        case IIO_MOD_STILL:
        case IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z:
+       case IIO_MOD_I:
+       case IIO_MOD_Q:
+       case IIO_MOD_CO2:
+       case IIO_MOD_VOC:
                break;
        default:
                return false;