Merge tag 'iio-for-3.16a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23...
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 26 Apr 2014 15:12:25 +0000 (08:12 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 26 Apr 2014 15:12:25 +0000 (08:12 -0700)
Jonathan writes:

First round of IIO new driver, functionality and cleanups for the 3.16 cycle.

New device support
* AS3935 Lightning Sensor
* MCP3426/7/8 support added to the existing MCP3422 ADC driver
* AK8963 support in the AK8975 driver
* MPU6500 support in the MPU6050 driver (the functionality that is different
  is mostly not supported yet in either part).

Staging Graduations
* AD799x ADC

New functionality
* ACPI enumeration for the ak8975 driver

Cleanup / tweaks
* Use snprintf as a matter of good practice in a few additional places.
* Document *_mean_raw attributes.  These have been there a while, but were
  undocumented.
* Add an in kernel interface to get the mean values.
* Bug in the length of the event info mask that by coincidence wasn't yet
  actually causing any problems.
* itg3000 drop an unreachable return statement.
* spear_adc cleanups (heading for a staging graduation but a few more
  issues showed up in the review of these patches).
* Exynos ADC dependencies changed so it is only built when Exynos is present
  or COMPILE_TEST and OF are set.
* tsl2583 cleanups.
* Some cut and paste typos in the comments of various drivers still in staging.
* Couple of minor improvements to the ST sensor drivers.

40 files changed:
Documentation/ABI/testing/sysfs-bus-iio
Documentation/ABI/testing/sysfs-bus-iio-proximity-as3935 [new file with mode: 0644]
Documentation/devicetree/bindings/iio/proximity/as3935.txt [new file with mode: 0644]
Documentation/devicetree/bindings/vendor-prefixes.txt
drivers/iio/Kconfig
drivers/iio/Makefile
drivers/iio/accel/st_accel_core.c
drivers/iio/adc/Kconfig
drivers/iio/adc/Makefile
drivers/iio/adc/ad799x.c [new file with mode: 0644]
drivers/iio/adc/mcp3422.c
drivers/iio/common/st_sensors/st_sensors_core.c
drivers/iio/gyro/itg3200_core.c
drivers/iio/gyro/st_gyro_core.c
drivers/iio/imu/inv_mpu6050/Kconfig
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
drivers/iio/industrialio-core.c
drivers/iio/industrialio-event.c
drivers/iio/inkern.c
drivers/iio/magnetometer/Kconfig
drivers/iio/magnetometer/ak8975.c
drivers/iio/magnetometer/st_magn_core.c
drivers/iio/pressure/st_pressure_core.c
drivers/iio/proximity/Kconfig [new file with mode: 0644]
drivers/iio/proximity/Makefile [new file with mode: 0644]
drivers/iio/proximity/as3935.c [new file with mode: 0644]
drivers/staging/iio/adc/Kconfig
drivers/staging/iio/adc/Makefile
drivers/staging/iio/adc/ad7606.h
drivers/staging/iio/adc/ad7816.c
drivers/staging/iio/adc/ad799x.h [deleted file]
drivers/staging/iio/adc/ad799x_core.c [deleted file]
drivers/staging/iio/adc/ad799x_ring.c [deleted file]
drivers/staging/iio/adc/spear_adc.c
drivers/staging/iio/addac/adt7316.c
drivers/staging/iio/cdc/ad7152.c
drivers/staging/iio/cdc/ad7746.c
include/linux/iio/common/st_sensors.h
include/linux/iio/consumer.h

index 6e02c50..58ba333 100644 (file)
@@ -210,6 +210,14 @@ Contact:   linux-iio@vger.kernel.org
 Description:
                Scaled humidity measurement in milli percent.
 
+What:          /sys/bus/iio/devices/iio:deviceX/in_X_mean_raw
+KernelVersion: 3.5
+Contact:       linux-iio@vger.kernel.org
+Description:
+               Averaged raw measurement from channel X. The number of values
+               used for averaging is device specific. The converting rules for
+               normal raw values also applies to the averaged raw values.
+
 What:          /sys/bus/iio/devices/iio:deviceX/in_accel_offset
 What:          /sys/bus/iio/devices/iio:deviceX/in_accel_x_offset
 What:          /sys/bus/iio/devices/iio:deviceX/in_accel_y_offset
diff --git a/Documentation/ABI/testing/sysfs-bus-iio-proximity-as3935 b/Documentation/ABI/testing/sysfs-bus-iio-proximity-as3935
new file mode 100644 (file)
index 0000000..6708c5e
--- /dev/null
@@ -0,0 +1,16 @@
+What           /sys/bus/iio/devices/iio:deviceX/in_proximity_raw
+Date:          March 2014
+KernelVersion: 3.15
+Contact:       Matt Ranostay <mranostay@gmail.com>
+Description:
+               Get the current distance in meters of storm (1km steps)
+               1000-40000 = distance in meters
+
+What           /sys/bus/iio/devices/iio:deviceX/sensor_sensitivity
+Date:          March 2014
+KernelVersion: 3.15
+Contact:       Matt Ranostay <mranostay@gmail.com>
+Description:
+               Show or set the gain boost of the amp, from 0-31 range.
+               18 = indoors (default)
+               14 = outdoors
diff --git a/Documentation/devicetree/bindings/iio/proximity/as3935.txt b/Documentation/devicetree/bindings/iio/proximity/as3935.txt
new file mode 100644 (file)
index 0000000..ae23dd8
--- /dev/null
@@ -0,0 +1,28 @@
+Austrian Microsystems AS3935 Franklin lightning sensor device driver
+
+Required properties:
+       - compatible: must be "ams,as3935"
+       - reg: SPI chip select number for the device
+       - spi-cpha: SPI Mode 1. Refer to spi/spi-bus.txt for generic SPI
+       slave node bindings.
+       - interrupt-parent : should be the phandle for the interrupt controller
+       - interrupts : the sole interrupt generated by the device
+
+       Refer to interrupt-controller/interrupts.txt for generic
+       interrupt client node bindings.
+
+Optional properties:
+       - ams,tuning-capacitor-pf: Calibration tuning capacitor stepping
+         value 0 - 120pF. This will require using the calibration data from
+         the manufacturer.
+
+Example:
+
+as3935@0 {
+       compatible = "ams,as3935";
+       reg = <0>;
+       spi-cpha;
+       interrupt-parent = <&gpio1>;
+       interrupts = <16 1>;
+       ams,tuning-capacitor-pf = <80>;
+};
index abc3080..7e88bc6 100644 (file)
@@ -13,6 +13,7 @@ allwinner     Allwinner Technology Co., Ltd.
 altr   Altera Corp.
 amcc   Applied Micro Circuits Corporation (APM, formally AMCC)
 amd    Advanced Micro Devices (AMD), Inc.
+ams    AMS AG
 amstaos        AMS-Taos Inc.
 apm    Applied Micro Circuits Corporation (APM)
 arm    ARM Ltd.
index 5dd0e12..743485e 100644 (file)
@@ -74,6 +74,7 @@ if IIO_TRIGGER
    source "drivers/iio/trigger/Kconfig"
 endif #IIO_TRIGGER
 source "drivers/iio/pressure/Kconfig"
+source "drivers/iio/proximity/Kconfig"
 source "drivers/iio/temperature/Kconfig"
 
 endif # IIO
index 887d390..698afc2 100644 (file)
@@ -24,5 +24,6 @@ obj-y += light/
 obj-y += magnetometer/
 obj-y += orientation/
 obj-y += pressure/
+obj-y += proximity/
 obj-y += temperature/
 obj-y += trigger/
index 38caedc..a2abf7c 100644 (file)
@@ -459,6 +459,8 @@ int st_accel_common_probe(struct iio_dev *indio_dev,
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &accel_info;
 
+       st_sensors_power_enable(indio_dev);
+
        err = st_sensors_check_device_support(indio_dev,
                                ARRAY_SIZE(st_accel_sensors), st_accel_sensors);
        if (err < 0)
@@ -496,6 +498,9 @@ int st_accel_common_probe(struct iio_dev *indio_dev,
        if (err)
                goto st_accel_device_register_error;
 
+       dev_info(&indio_dev->dev, "registered accelerometer %s\n",
+                indio_dev->name);
+
        return 0;
 
 st_accel_device_register_error:
@@ -512,6 +517,8 @@ void st_accel_common_remove(struct iio_dev *indio_dev)
 {
        struct st_sensor_data *adata = iio_priv(indio_dev);
 
+       st_sensors_power_disable(indio_dev);
+
        iio_device_unregister(indio_dev);
        if (adata->get_irq_data_ready(indio_dev) > 0)
                st_sensors_deallocate_trigger(indio_dev);
index d86196c..6cbf34a 100644 (file)
@@ -96,6 +96,17 @@ config AD7923
          To compile this driver as a module, choose M here: the
          module will be called ad7923.
 
+config AD799X
+       tristate "Analog Devices AD799x ADC driver"
+       depends on I2C
+       select IIO_BUFFER
+       select IIO_TRIGGERED_BUFFER
+       help
+         Say yes here to build support for Analog Devices:
+         ad7991, ad7995, ad7999, ad7992, ad7993, ad7994, ad7997, ad7998
+         i2c analog to digital converters (ADC). Provides direct access
+         via sysfs.
+
 config AT91_ADC
        tristate "Atmel AT91 ADC"
        depends on ARCH_AT91
@@ -107,7 +118,7 @@ config AT91_ADC
 
 config EXYNOS_ADC
        bool "Exynos ADC driver support"
-       depends on OF
+       depends on ARCH_EXYNOS || (OF && COMPILE_TEST)
        help
          Core support for the ADC block found in the Samsung EXYNOS series
          of SoCs for drivers such as the touchscreen and hwmon to use to share
@@ -146,11 +157,12 @@ config MCP320X
          called mcp320x.
 
 config MCP3422
-       tristate "Microchip Technology MCP3422/3/4 driver"
+       tristate "Microchip Technology MCP3422/3/4/6/7/8 driver"
        depends on I2C
        help
-         Say yes here to build support for Microchip Technology's MCP3422,
-         MCP3423 or MCP3424 analog to digital converters.
+         Say yes here to build support for Microchip Technology's
+         MCP3422, MCP3423, MCP3424, MCP3426, MCP3427 or MCP3428
+         analog to digital converters.
 
          This driver can also be built as a module. If so, the module will be
          called mcp3422.
index ab346d8..9d60f2d 100644 (file)
@@ -11,6 +11,7 @@ obj-$(CONFIG_AD7476) += ad7476.o
 obj-$(CONFIG_AD7791) += ad7791.o
 obj-$(CONFIG_AD7793) += ad7793.o
 obj-$(CONFIG_AD7887) += ad7887.o
+obj-$(CONFIG_AD799X) += ad799x.o
 obj-$(CONFIG_AT91_ADC) += at91_adc.o
 obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
 obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
diff --git a/drivers/iio/adc/ad799x.c b/drivers/iio/adc/ad799x.c
new file mode 100644 (file)
index 0000000..16a8b14
--- /dev/null
@@ -0,0 +1,794 @@
+/*
+ * iio/adc/ad799x.c
+ * Copyright (C) 2010-2011 Michael Hennerich, Analog Devices Inc.
+ *
+ * based on iio/adc/max1363
+ * Copyright (C) 2008-2010 Jonathan Cameron
+ *
+ * based on linux/drivers/i2c/chips/max123x
+ * Copyright (C) 2002-2004 Stefan Eletzhofer
+ *
+ * based on linux/drivers/acron/char/pcf8583.c
+ * Copyright (C) 2000 Russell King
+ *
+ * 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.
+ *
+ * ad799x.c
+ *
+ * Support for ad7991, ad7995, ad7999, ad7992, ad7993, ad7994, ad7997,
+ * ad7998 and similar chips.
+ *
+ */
+
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/sysfs.h>
+#include <linux/i2c.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/module.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/events.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#define AD799X_CHANNEL_SHIFT                   4
+#define AD799X_STORAGEBITS                     16
+/*
+ * AD7991, AD7995 and AD7999 defines
+ */
+
+#define AD7991_REF_SEL                         0x08
+#define AD7991_FLTR                            0x04
+#define AD7991_BIT_TRIAL_DELAY                 0x02
+#define AD7991_SAMPLE_DELAY                    0x01
+
+/*
+ * AD7992, AD7993, AD7994, AD7997 and AD7998 defines
+ */
+
+#define AD7998_FLTR                            0x08
+#define AD7998_ALERT_EN                                0x04
+#define AD7998_BUSY_ALERT                      0x02
+#define AD7998_BUSY_ALERT_POL                  0x01
+
+#define AD7998_CONV_RES_REG                    0x0
+#define AD7998_ALERT_STAT_REG                  0x1
+#define AD7998_CONF_REG                                0x2
+#define AD7998_CYCLE_TMR_REG                   0x3
+
+#define AD7998_DATALOW_REG(x)                  ((x) * 3 + 0x4)
+#define AD7998_DATAHIGH_REG(x)                 ((x) * 3 + 0x5)
+#define AD7998_HYST_REG(x)                     ((x) * 3 + 0x6)
+
+#define AD7998_CYC_MASK                                0x7
+#define AD7998_CYC_DIS                         0x0
+#define AD7998_CYC_TCONF_32                    0x1
+#define AD7998_CYC_TCONF_64                    0x2
+#define AD7998_CYC_TCONF_128                   0x3
+#define AD7998_CYC_TCONF_256                   0x4
+#define AD7998_CYC_TCONF_512                   0x5
+#define AD7998_CYC_TCONF_1024                  0x6
+#define AD7998_CYC_TCONF_2048                  0x7
+
+#define AD7998_ALERT_STAT_CLEAR                        0xFF
+
+/*
+ * AD7997 and AD7997 defines
+ */
+
+#define AD7997_8_READ_SINGLE                   0x80
+#define AD7997_8_READ_SEQUENCE                 0x70
+/* TODO: move this into a common header */
+#define RES_MASK(bits) ((1 << (bits)) - 1)
+
+enum {
+       ad7991,
+       ad7995,
+       ad7999,
+       ad7992,
+       ad7993,
+       ad7994,
+       ad7997,
+       ad7998
+};
+
+/**
+ * struct ad799x_chip_info - chip specific information
+ * @channel:           channel specification
+ * @num_channels:      number of channels
+ * @monitor_mode:      whether the chip supports monitor interrupts
+ * @default_config:    device default configuration
+ * @event_attrs:       pointer to the monitor event attribute group
+ */
+struct ad799x_chip_info {
+       struct iio_chan_spec            channel[9];
+       int                             num_channels;
+       u16                             default_config;
+       const struct iio_info           *info;
+};
+
+struct ad799x_state {
+       struct i2c_client               *client;
+       const struct ad799x_chip_info   *chip_info;
+       struct regulator                *reg;
+       struct regulator                *vref;
+       unsigned                        id;
+       u16                             config;
+
+       u8                              *rx_buf;
+       unsigned int                    transfer_size;
+};
+
+/**
+ * ad799x_trigger_handler() bh of trigger launched polling to ring buffer
+ *
+ * Currently there is no option in this driver to disable the saving of
+ * timestamps within the ring.
+ **/
+static irqreturn_t ad799x_trigger_handler(int irq, void *p)
+{
+       struct iio_poll_func *pf = p;
+       struct iio_dev *indio_dev = pf->indio_dev;
+       struct ad799x_state *st = iio_priv(indio_dev);
+       int b_sent;
+       u8 cmd;
+
+       switch (st->id) {
+       case ad7991:
+       case ad7995:
+       case ad7999:
+               cmd = st->config |
+                       (*indio_dev->active_scan_mask << AD799X_CHANNEL_SHIFT);
+               break;
+       case ad7992:
+       case ad7993:
+       case ad7994:
+               cmd = (*indio_dev->active_scan_mask << AD799X_CHANNEL_SHIFT) |
+                       AD7998_CONV_RES_REG;
+               break;
+       case ad7997:
+       case ad7998:
+               cmd = AD7997_8_READ_SEQUENCE | AD7998_CONV_RES_REG;
+               break;
+       default:
+               cmd = 0;
+       }
+
+       b_sent = i2c_smbus_read_i2c_block_data(st->client,
+                       cmd, st->transfer_size, st->rx_buf);
+       if (b_sent < 0)
+               goto out;
+
+       iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf,
+                       iio_get_time_ns());
+out:
+       iio_trigger_notify_done(indio_dev->trig);
+
+       return IRQ_HANDLED;
+}
+
+/*
+ * ad799x register access by I2C
+ */
+static int ad799x_i2c_read16(struct ad799x_state *st, u8 reg, u16 *data)
+{
+       struct i2c_client *client = st->client;
+       int ret = 0;
+
+       ret = i2c_smbus_read_word_swapped(client, reg);
+       if (ret < 0) {
+               dev_err(&client->dev, "I2C read error\n");
+               return ret;
+       }
+
+       *data = (u16)ret;
+
+       return 0;
+}
+
+static int ad799x_i2c_read8(struct ad799x_state *st, u8 reg, u8 *data)
+{
+       struct i2c_client *client = st->client;
+       int ret = 0;
+
+       ret = i2c_smbus_read_byte_data(client, reg);
+       if (ret < 0) {
+               dev_err(&client->dev, "I2C read error\n");
+               return ret;
+       }
+
+       *data = (u8)ret;
+
+       return 0;
+}
+
+static int ad799x_i2c_write16(struct ad799x_state *st, u8 reg, u16 data)
+{
+       struct i2c_client *client = st->client;
+       int ret = 0;
+
+       ret = i2c_smbus_write_word_swapped(client, reg, data);
+       if (ret < 0)
+               dev_err(&client->dev, "I2C write error\n");
+
+       return ret;
+}
+
+static int ad799x_i2c_write8(struct ad799x_state *st, u8 reg, u8 data)
+{
+       struct i2c_client *client = st->client;
+       int ret = 0;
+
+       ret = i2c_smbus_write_byte_data(client, reg, data);
+       if (ret < 0)
+               dev_err(&client->dev, "I2C write error\n");
+
+       return ret;
+}
+
+static int ad7997_8_update_scan_mode(struct iio_dev *indio_dev,
+       const unsigned long *scan_mask)
+{
+       struct ad799x_state *st = iio_priv(indio_dev);
+
+       kfree(st->rx_buf);
+       st->rx_buf = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
+       if (!st->rx_buf)
+               return -ENOMEM;
+
+       st->transfer_size = bitmap_weight(scan_mask, indio_dev->masklength) * 2;
+
+       switch (st->id) {
+       case ad7997:
+       case ad7998:
+               return ad799x_i2c_write16(st, AD7998_CONF_REG,
+                       st->config | (*scan_mask << AD799X_CHANNEL_SHIFT));
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static int ad799x_scan_direct(struct ad799x_state *st, unsigned ch)
+{
+       u16 rxbuf;
+       u8 cmd;
+       int ret;
+
+       switch (st->id) {
+       case ad7991:
+       case ad7995:
+       case ad7999:
+               cmd = st->config | ((1 << ch) << AD799X_CHANNEL_SHIFT);
+               break;
+       case ad7992:
+       case ad7993:
+       case ad7994:
+               cmd = (1 << ch) << AD799X_CHANNEL_SHIFT;
+               break;
+       case ad7997:
+       case ad7998:
+               cmd = (ch << AD799X_CHANNEL_SHIFT) | AD7997_8_READ_SINGLE;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       ret = ad799x_i2c_read16(st, cmd, &rxbuf);
+       if (ret < 0)
+               return ret;
+
+       return rxbuf;
+}
+
+static int ad799x_read_raw(struct iio_dev *indio_dev,
+                          struct iio_chan_spec const *chan,
+                          int *val,
+                          int *val2,
+                          long m)
+{
+       int ret;
+       struct ad799x_state *st = iio_priv(indio_dev);
+
+       switch (m) {
+       case IIO_CHAN_INFO_RAW:
+               mutex_lock(&indio_dev->mlock);
+               if (iio_buffer_enabled(indio_dev))
+                       ret = -EBUSY;
+               else
+                       ret = ad799x_scan_direct(st, chan->scan_index);
+               mutex_unlock(&indio_dev->mlock);
+
+               if (ret < 0)
+                       return ret;
+               *val = (ret >> chan->scan_type.shift) &
+                       RES_MASK(chan->scan_type.realbits);
+               return IIO_VAL_INT;
+       case IIO_CHAN_INFO_SCALE:
+               ret = regulator_get_voltage(st->vref);
+               if (ret < 0)
+                       return ret;
+               *val = ret / 1000;
+               *val2 = chan->scan_type.realbits;
+               return IIO_VAL_FRACTIONAL_LOG2;
+       }
+       return -EINVAL;
+}
+static const unsigned int ad7998_frequencies[] = {
+       [AD7998_CYC_DIS]        = 0,
+       [AD7998_CYC_TCONF_32]   = 15625,
+       [AD7998_CYC_TCONF_64]   = 7812,
+       [AD7998_CYC_TCONF_128]  = 3906,
+       [AD7998_CYC_TCONF_512]  = 976,
+       [AD7998_CYC_TCONF_1024] = 488,
+       [AD7998_CYC_TCONF_2048] = 244,
+};
+static ssize_t ad799x_read_frequency(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+       struct ad799x_state *st = iio_priv(indio_dev);
+
+       int ret;
+       u8 val;
+       ret = ad799x_i2c_read8(st, AD7998_CYCLE_TMR_REG, &val);
+       if (ret)
+               return ret;
+
+       val &= AD7998_CYC_MASK;
+
+       return sprintf(buf, "%u\n", ad7998_frequencies[val]);
+}
+
+static ssize_t ad799x_write_frequency(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf,
+                                        size_t len)
+{
+       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+       struct ad799x_state *st = iio_priv(indio_dev);
+
+       long val;
+       int ret, i;
+       u8 t;
+
+       ret = kstrtol(buf, 10, &val);
+       if (ret)
+               return ret;
+
+       mutex_lock(&indio_dev->mlock);
+       ret = ad799x_i2c_read8(st, AD7998_CYCLE_TMR_REG, &t);
+       if (ret)
+               goto error_ret_mutex;
+       /* Wipe the bits clean */
+       t &= ~AD7998_CYC_MASK;
+
+       for (i = 0; i < ARRAY_SIZE(ad7998_frequencies); i++)
+               if (val == ad7998_frequencies[i])
+                       break;
+       if (i == ARRAY_SIZE(ad7998_frequencies)) {
+               ret = -EINVAL;
+               goto error_ret_mutex;
+       }
+       t |= i;
+       ret = ad799x_i2c_write8(st, AD7998_CYCLE_TMR_REG, t);
+
+error_ret_mutex:
+       mutex_unlock(&indio_dev->mlock);
+
+       return ret ? ret : len;
+}
+
+static int ad799x_read_event_config(struct iio_dev *indio_dev,
+                                   const struct iio_chan_spec *chan,
+                                   enum iio_event_type type,
+                                   enum iio_event_direction dir)
+{
+       return 1;
+}
+
+static unsigned int ad799x_threshold_reg(const struct iio_chan_spec *chan,
+                                        enum iio_event_direction dir,
+                                        enum iio_event_info info)
+{
+       switch (info) {
+       case IIO_EV_INFO_VALUE:
+               if (dir == IIO_EV_DIR_FALLING)
+                       return AD7998_DATALOW_REG(chan->channel);
+               else
+                       return AD7998_DATAHIGH_REG(chan->channel);
+       case IIO_EV_INFO_HYSTERESIS:
+               return AD7998_HYST_REG(chan->channel);
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int ad799x_write_event_value(struct iio_dev *indio_dev,
+                                   const struct iio_chan_spec *chan,
+                                   enum iio_event_type type,
+                                   enum iio_event_direction dir,
+                                   enum iio_event_info info,
+                                   int val, int val2)
+{
+       int ret;
+       struct ad799x_state *st = iio_priv(indio_dev);
+
+       mutex_lock(&indio_dev->mlock);
+       ret = ad799x_i2c_write16(st, ad799x_threshold_reg(chan, dir, info),
+               val);
+       mutex_unlock(&indio_dev->mlock);
+
+       return ret;
+}
+
+static int ad799x_read_event_value(struct iio_dev *indio_dev,
+                                   const struct iio_chan_spec *chan,
+                                   enum iio_event_type type,
+                                   enum iio_event_direction dir,
+                                   enum iio_event_info info,
+                                   int *val, int *val2)
+{
+       int ret;
+       struct ad799x_state *st = iio_priv(indio_dev);
+       u16 valin;
+
+       mutex_lock(&indio_dev->mlock);
+       ret = ad799x_i2c_read16(st, ad799x_threshold_reg(chan, dir, info),
+               &valin);
+       mutex_unlock(&indio_dev->mlock);
+       if (ret < 0)
+               return ret;
+       *val = valin;
+
+       return IIO_VAL_INT;
+}
+
+static irqreturn_t ad799x_event_handler(int irq, void *private)
+{
+       struct iio_dev *indio_dev = private;
+       struct ad799x_state *st = iio_priv(private);
+       u8 status;
+       int i, ret;
+
+       ret = ad799x_i2c_read8(st, AD7998_ALERT_STAT_REG, &status);
+       if (ret)
+               goto done;
+
+       if (!status)
+               goto done;
+
+       ad799x_i2c_write8(st, AD7998_ALERT_STAT_REG, AD7998_ALERT_STAT_CLEAR);
+
+       for (i = 0; i < 8; i++) {
+               if (status & (1 << i))
+                       iio_push_event(indio_dev,
+                                      i & 0x1 ?
+                                      IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE,
+                                                           (i >> 1),
+                                                           IIO_EV_TYPE_THRESH,
+                                                           IIO_EV_DIR_RISING) :
+                                      IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE,
+                                                           (i >> 1),
+                                                           IIO_EV_TYPE_THRESH,
+                                                           IIO_EV_DIR_FALLING),
+                                      iio_get_time_ns());
+       }
+
+done:
+       return IRQ_HANDLED;
+}
+
+static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
+                             ad799x_read_frequency,
+                             ad799x_write_frequency);
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("15625 7812 3906 1953 976 488 244 0");
+
+static struct attribute *ad799x_event_attributes[] = {
+       &iio_dev_attr_sampling_frequency.dev_attr.attr,
+       &iio_const_attr_sampling_frequency_available.dev_attr.attr,
+       NULL,
+};
+
+static struct attribute_group ad799x_event_attrs_group = {
+       .attrs = ad799x_event_attributes,
+       .name = "events",
+};
+
+static const struct iio_info ad7991_info = {
+       .read_raw = &ad799x_read_raw,
+       .driver_module = THIS_MODULE,
+};
+
+static const struct iio_info ad7993_4_7_8_info = {
+       .read_raw = &ad799x_read_raw,
+       .event_attrs = &ad799x_event_attrs_group,
+       .read_event_config = &ad799x_read_event_config,
+       .read_event_value = &ad799x_read_event_value,
+       .write_event_value = &ad799x_write_event_value,
+       .driver_module = THIS_MODULE,
+       .update_scan_mode = ad7997_8_update_scan_mode,
+};
+
+static const struct iio_event_spec ad799x_events[] = {
+       {
+               .type = IIO_EV_TYPE_THRESH,
+               .dir = IIO_EV_DIR_RISING,
+               .mask_separate = BIT(IIO_EV_INFO_VALUE) |
+                       BIT(IIO_EV_INFO_ENABLE),
+       }, {
+               .type = IIO_EV_TYPE_THRESH,
+               .dir = IIO_EV_DIR_FALLING,
+               .mask_separate = BIT(IIO_EV_INFO_VALUE) |
+                       BIT(IIO_EV_INFO_ENABLE),
+       }, {
+               .type = IIO_EV_TYPE_THRESH,
+               .dir = IIO_EV_DIR_EITHER,
+               .mask_separate = BIT(IIO_EV_INFO_HYSTERESIS),
+       },
+};
+
+#define _AD799X_CHANNEL(_index, _realbits, _ev_spec, _num_ev_spec) { \
+       .type = IIO_VOLTAGE, \
+       .indexed = 1, \
+       .channel = (_index), \
+       .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+       .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+       .scan_index = (_index), \
+       .scan_type = { \
+               .sign = 'u', \
+               .realbits = (_realbits), \
+               .storagebits = 16, \
+               .shift = 12 - (_realbits), \
+               .endianness = IIO_BE, \
+       }, \
+       .event_spec = _ev_spec, \
+       .num_event_specs = _num_ev_spec, \
+}
+
+#define AD799X_CHANNEL(_index, _realbits) \
+       _AD799X_CHANNEL(_index, _realbits, NULL, 0)
+
+#define AD799X_CHANNEL_WITH_EVENTS(_index, _realbits) \
+       _AD799X_CHANNEL(_index, _realbits, ad799x_events, \
+               ARRAY_SIZE(ad799x_events))
+
+static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
+       [ad7991] = {
+               .channel = {
+                       AD799X_CHANNEL(0, 12),
+                       AD799X_CHANNEL(1, 12),
+                       AD799X_CHANNEL(2, 12),
+                       AD799X_CHANNEL(3, 12),
+                       IIO_CHAN_SOFT_TIMESTAMP(4),
+               },
+               .num_channels = 5,
+               .info = &ad7991_info,
+       },
+       [ad7995] = {
+               .channel = {
+                       AD799X_CHANNEL(0, 10),
+                       AD799X_CHANNEL(1, 10),
+                       AD799X_CHANNEL(2, 10),
+                       AD799X_CHANNEL(3, 10),
+                       IIO_CHAN_SOFT_TIMESTAMP(4),
+               },
+               .num_channels = 5,
+               .info = &ad7991_info,
+       },
+       [ad7999] = {
+               .channel = {
+                       AD799X_CHANNEL(0, 8),
+                       AD799X_CHANNEL(1, 8),
+                       AD799X_CHANNEL(2, 8),
+                       AD799X_CHANNEL(3, 8),
+                       IIO_CHAN_SOFT_TIMESTAMP(4),
+               },
+               .num_channels = 5,
+               .info = &ad7991_info,
+       },
+       [ad7992] = {
+               .channel = {
+                       AD799X_CHANNEL_WITH_EVENTS(0, 12),
+                       AD799X_CHANNEL_WITH_EVENTS(1, 12),
+                       IIO_CHAN_SOFT_TIMESTAMP(3),
+               },
+               .num_channels = 3,
+               .default_config = AD7998_ALERT_EN,
+               .info = &ad7993_4_7_8_info,
+       },
+       [ad7993] = {
+               .channel = {
+                       AD799X_CHANNEL_WITH_EVENTS(0, 10),
+                       AD799X_CHANNEL_WITH_EVENTS(1, 10),
+                       AD799X_CHANNEL_WITH_EVENTS(2, 10),
+                       AD799X_CHANNEL_WITH_EVENTS(3, 10),
+                       IIO_CHAN_SOFT_TIMESTAMP(4),
+               },
+               .num_channels = 5,
+               .default_config = AD7998_ALERT_EN,
+               .info = &ad7993_4_7_8_info,
+       },
+       [ad7994] = {
+               .channel = {
+                       AD799X_CHANNEL_WITH_EVENTS(0, 12),
+                       AD799X_CHANNEL_WITH_EVENTS(1, 12),
+                       AD799X_CHANNEL_WITH_EVENTS(2, 12),
+                       AD799X_CHANNEL_WITH_EVENTS(3, 12),
+                       IIO_CHAN_SOFT_TIMESTAMP(4),
+               },
+               .num_channels = 5,
+               .default_config = AD7998_ALERT_EN,
+               .info = &ad7993_4_7_8_info,
+       },
+       [ad7997] = {
+               .channel = {
+                       AD799X_CHANNEL_WITH_EVENTS(0, 10),
+                       AD799X_CHANNEL_WITH_EVENTS(1, 10),
+                       AD799X_CHANNEL_WITH_EVENTS(2, 10),
+                       AD799X_CHANNEL_WITH_EVENTS(3, 10),
+                       AD799X_CHANNEL(4, 10),
+                       AD799X_CHANNEL(5, 10),
+                       AD799X_CHANNEL(6, 10),
+                       AD799X_CHANNEL(7, 10),
+                       IIO_CHAN_SOFT_TIMESTAMP(8),
+               },
+               .num_channels = 9,
+               .default_config = AD7998_ALERT_EN,
+               .info = &ad7993_4_7_8_info,
+       },
+       [ad7998] = {
+               .channel = {
+                       AD799X_CHANNEL_WITH_EVENTS(0, 12),
+                       AD799X_CHANNEL_WITH_EVENTS(1, 12),
+                       AD799X_CHANNEL_WITH_EVENTS(2, 12),
+                       AD799X_CHANNEL_WITH_EVENTS(3, 12),
+                       AD799X_CHANNEL(4, 12),
+                       AD799X_CHANNEL(5, 12),
+                       AD799X_CHANNEL(6, 12),
+                       AD799X_CHANNEL(7, 12),
+                       IIO_CHAN_SOFT_TIMESTAMP(8),
+               },
+               .num_channels = 9,
+               .default_config = AD7998_ALERT_EN,
+               .info = &ad7993_4_7_8_info,
+       },
+};
+
+static int ad799x_probe(struct i2c_client *client,
+                                  const struct i2c_device_id *id)
+{
+       int ret;
+       struct ad799x_state *st;
+       struct iio_dev *indio_dev;
+
+       indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
+       if (indio_dev == NULL)
+               return -ENOMEM;
+
+       st = iio_priv(indio_dev);
+       /* this is only used for device removal purposes */
+       i2c_set_clientdata(client, indio_dev);
+
+       st->id = id->driver_data;
+       st->chip_info = &ad799x_chip_info_tbl[st->id];
+       st->config = st->chip_info->default_config;
+
+       /* TODO: Add pdata options for filtering and bit delay */
+
+       st->reg = devm_regulator_get(&client->dev, "vcc");
+       if (IS_ERR(st->reg))
+               return PTR_ERR(st->reg);
+       ret = regulator_enable(st->reg);
+       if (ret)
+               return ret;
+       st->vref = devm_regulator_get(&client->dev, "vref");
+       if (IS_ERR(st->vref)) {
+               ret = PTR_ERR(st->vref);
+               goto error_disable_reg;
+       }
+       ret = regulator_enable(st->vref);
+       if (ret)
+               goto error_disable_reg;
+
+       st->client = client;
+
+       indio_dev->dev.parent = &client->dev;
+       indio_dev->name = id->name;
+       indio_dev->info = st->chip_info->info;
+
+       indio_dev->modes = INDIO_DIRECT_MODE;
+       indio_dev->channels = st->chip_info->channel;
+       indio_dev->num_channels = st->chip_info->num_channels;
+
+       ret = iio_triggered_buffer_setup(indio_dev, NULL,
+               &ad799x_trigger_handler, NULL);
+       if (ret)
+               goto error_disable_reg;
+
+       if (client->irq > 0) {
+               ret = devm_request_threaded_irq(&client->dev,
+                                               client->irq,
+                                               NULL,
+                                               ad799x_event_handler,
+                                               IRQF_TRIGGER_FALLING |
+                                               IRQF_ONESHOT,
+                                               client->name,
+                                               indio_dev);
+               if (ret)
+                       goto error_cleanup_ring;
+       }
+       ret = iio_device_register(indio_dev);
+       if (ret)
+               goto error_cleanup_ring;
+
+       return 0;
+
+error_cleanup_ring:
+       iio_triggered_buffer_cleanup(indio_dev);
+error_disable_reg:
+       if (!IS_ERR(st->vref))
+               regulator_disable(st->vref);
+       if (!IS_ERR(st->reg))
+               regulator_disable(st->reg);
+
+       return ret;
+}
+
+static int ad799x_remove(struct i2c_client *client)
+{
+       struct iio_dev *indio_dev = i2c_get_clientdata(client);
+       struct ad799x_state *st = iio_priv(indio_dev);
+
+       iio_device_unregister(indio_dev);
+
+       iio_triggered_buffer_cleanup(indio_dev);
+       if (!IS_ERR(st->vref))
+               regulator_disable(st->vref);
+       if (!IS_ERR(st->reg))
+               regulator_disable(st->reg);
+       kfree(st->rx_buf);
+
+       return 0;
+}
+
+static const struct i2c_device_id ad799x_id[] = {
+       { "ad7991", ad7991 },
+       { "ad7995", ad7995 },
+       { "ad7999", ad7999 },
+       { "ad7992", ad7992 },
+       { "ad7993", ad7993 },
+       { "ad7994", ad7994 },
+       { "ad7997", ad7997 },
+       { "ad7998", ad7998 },
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, ad799x_id);
+
+static struct i2c_driver ad799x_driver = {
+       .driver = {
+               .name = "ad799x",
+       },
+       .probe = ad799x_probe,
+       .remove = ad799x_remove,
+       .id_table = ad799x_id,
+};
+module_i2c_driver(ad799x_driver);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("Analog Devices AD799x ADC");
+MODULE_LICENSE("GPL v2");
index 47dcb34..5167225 100644 (file)
@@ -1,10 +1,11 @@
 /*
- * mcp3422.c - driver for the Microchip mcp3422/3/4 chip family
+ * mcp3422.c - driver for the Microchip mcp3422/3/4/6/7/8 chip family
  *
  * Copyright (C) 2013, Angelo Compagnucci
  * Author: Angelo Compagnucci <angelo.compagnucci@gmail.com>
  *
  * Datasheet: http://ww1.microchip.com/downloads/en/devicedoc/22088b.pdf
+ *            http://ww1.microchip.com/downloads/en/DeviceDoc/22226a.pdf
  *
  * This driver exports the value of analog input voltage to sysfs, the
  * voltage unit is nV.
@@ -96,6 +97,7 @@ static const int mcp3422_sign_extend[4] = {
 /* Client data (each client gets its own) */
 struct mcp3422 {
        struct i2c_client *i2c;
+       u8 id;
        u8 config;
        u8 pga[4];
        struct mutex lock;
@@ -238,6 +240,8 @@ static int mcp3422_write_raw(struct iio_dev *iio,
                        temp = MCP3422_SRATE_15;
                        break;
                case 3:
+                       if (adc->id > 4)
+                               return -EINVAL;
                        temp = MCP3422_SRATE_3;
                        break;
                default:
@@ -271,6 +275,17 @@ static int mcp3422_write_raw_get_fmt(struct iio_dev *indio_dev,
        }
 }
 
+static ssize_t mcp3422_show_samp_freqs(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct mcp3422 *adc = iio_priv(dev_to_iio_dev(dev));
+
+       if (adc->id > 4)
+               return sprintf(buf, "240 60 15\n");
+
+       return sprintf(buf, "240 60 15 3\n");
+}
+
 static ssize_t mcp3422_show_scales(struct device *dev,
                struct device_attribute *attr, char *buf)
 {
@@ -284,12 +299,13 @@ static ssize_t mcp3422_show_scales(struct device *dev,
                mcp3422_scales[sample_rate][3]);
 }
 
-static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("240 60 15 3");
+static IIO_DEVICE_ATTR(sampling_frequency_available, S_IRUGO,
+               mcp3422_show_samp_freqs, NULL, 0);
 static IIO_DEVICE_ATTR(in_voltage_scale_available, S_IRUGO,
                mcp3422_show_scales, NULL, 0);
 
 static struct attribute *mcp3422_attributes[] = {
-       &iio_const_attr_sampling_frequency_available.dev_attr.attr,
+       &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
        &iio_dev_attr_in_voltage_scale_available.dev_attr.attr,
        NULL,
 };
@@ -335,6 +351,7 @@ static int mcp3422_probe(struct i2c_client *client,
 
        adc = iio_priv(indio_dev);
        adc->i2c = client;
+       adc->id = (u8)(id->driver_data);
 
        mutex_init(&adc->lock);
 
@@ -343,13 +360,16 @@ static int mcp3422_probe(struct i2c_client *client,
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &mcp3422_info;
 
-       switch ((unsigned int)(id->driver_data)) {
+       switch (adc->id) {
        case 2:
        case 3:
+       case 6:
+       case 7:
                indio_dev->channels = mcp3422_channels;
                indio_dev->num_channels = ARRAY_SIZE(mcp3422_channels);
                break;
        case 4:
+       case 8:
                indio_dev->channels = mcp3424_channels;
                indio_dev->num_channels = ARRAY_SIZE(mcp3424_channels);
                break;
@@ -375,6 +395,9 @@ static const struct i2c_device_id mcp3422_id[] = {
        { "mcp3422", 2 },
        { "mcp3423", 3 },
        { "mcp3424", 4 },
+       { "mcp3426", 6 },
+       { "mcp3427", 7 },
+       { "mcp3428", 8 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, mcp3422_id);
@@ -399,5 +422,5 @@ static struct i2c_driver mcp3422_driver = {
 module_i2c_driver(mcp3422_driver);
 
 MODULE_AUTHOR("Angelo Compagnucci <angelo.compagnucci@gmail.com>");
-MODULE_DESCRIPTION("Microchip mcp3422/3/4 driver");
+MODULE_DESCRIPTION("Microchip mcp3422/3/4/6/7/8 driver");
 MODULE_LICENSE("GPL v2");
index 7ba1ef2..e8b932f 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/iio/iio.h>
+#include <linux/regulator/consumer.h>
 #include <asm/unaligned.h>
 
 #include <linux/iio/common/st_sensors.h>
@@ -198,6 +199,42 @@ int st_sensors_set_axis_enable(struct iio_dev *indio_dev, u8 axis_enable)
 }
 EXPORT_SYMBOL(st_sensors_set_axis_enable);
 
+void st_sensors_power_enable(struct iio_dev *indio_dev)
+{
+       struct st_sensor_data *pdata = iio_priv(indio_dev);
+       int err;
+
+       /* Regulators not mandatory, but if requested we should enable them. */
+       pdata->vdd = devm_regulator_get_optional(indio_dev->dev.parent, "vdd");
+       if (!IS_ERR(pdata->vdd)) {
+               err = regulator_enable(pdata->vdd);
+               if (err != 0)
+                       dev_warn(&indio_dev->dev,
+                                "Failed to enable specified Vdd supply\n");
+       }
+
+       pdata->vdd_io = devm_regulator_get_optional(indio_dev->dev.parent, "vddio");
+       if (!IS_ERR(pdata->vdd_io)) {
+               err = regulator_enable(pdata->vdd_io);
+               if (err != 0)
+                       dev_warn(&indio_dev->dev,
+                                "Failed to enable specified Vdd_IO supply\n");
+       }
+}
+EXPORT_SYMBOL(st_sensors_power_enable);
+
+void st_sensors_power_disable(struct iio_dev *indio_dev)
+{
+       struct st_sensor_data *pdata = iio_priv(indio_dev);
+
+       if (!IS_ERR(pdata->vdd))
+               regulator_disable(pdata->vdd);
+
+       if (!IS_ERR(pdata->vdd_io))
+               regulator_disable(pdata->vdd_io);
+}
+EXPORT_SYMBOL(st_sensors_power_disable);
+
 static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev,
                                       struct st_sensors_platform_data *pdata)
 {
index 4d3f3b9..8295e31 100644 (file)
@@ -110,8 +110,6 @@ static int itg3200_read_raw(struct iio_dev *indio_dev,
        default:
                return -EINVAL;
        }
-
-       return ret;
 }
 
 static ssize_t itg3200_read_frequency(struct device *dev,
index a8e174a..ed74a90 100644 (file)
@@ -311,6 +311,8 @@ int st_gyro_common_probe(struct iio_dev *indio_dev,
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &gyro_info;
 
+       st_sensors_power_enable(indio_dev);
+
        err = st_sensors_check_device_support(indio_dev,
                                ARRAY_SIZE(st_gyro_sensors), st_gyro_sensors);
        if (err < 0)
@@ -344,6 +346,9 @@ int st_gyro_common_probe(struct iio_dev *indio_dev,
        if (err)
                goto st_gyro_device_register_error;
 
+       dev_info(&indio_dev->dev, "registered gyroscope %s\n",
+                indio_dev->name);
+
        return 0;
 
 st_gyro_device_register_error:
@@ -360,6 +365,8 @@ void st_gyro_common_remove(struct iio_dev *indio_dev)
 {
        struct st_sensor_data *gdata = iio_priv(indio_dev);
 
+       st_sensors_power_disable(indio_dev);
+
        iio_device_unregister(indio_dev);
        if (gdata->get_irq_data_ready(indio_dev) > 0)
                st_sensors_deallocate_trigger(indio_dev);
index 361b232..2d0608b 100644 (file)
@@ -9,6 +9,8 @@ config INV_MPU6050_IIO
        select IIO_TRIGGERED_BUFFER
        help
          This driver supports the Invensense MPU6050 devices.
+         This driver can also support MPU6500 in MPU6050 compatibility mode
+         and also in MPU6500 mode with some limitations.
          It is a gyroscope/accelerometer combo device.
          This driver can be built as a module. The module will be called
          inv-mpu6050.
index cb9f96b..af287bf 100644 (file)
@@ -764,6 +764,7 @@ static SIMPLE_DEV_PM_OPS(inv_mpu_pmops, inv_mpu_suspend, inv_mpu_resume);
  */
 static const struct i2c_device_id inv_mpu_id[] = {
        {"mpu6050", INV_MPU6050},
+       {"mpu6500", INV_MPU6500},
        {}
 };
 
index 0ab382b..e779931 100644 (file)
@@ -59,6 +59,7 @@ struct inv_mpu6050_reg_map {
 /*device enum */
 enum inv_devices {
        INV_MPU6050,
+       INV_MPU6500,
        INV_NUM_PARTS
 };
 
index ede16ae..184444d 100644 (file)
@@ -340,7 +340,7 @@ ssize_t iio_enum_read(struct iio_dev *indio_dev,
        else if (i >= e->num_items)
                return -EINVAL;
 
-       return sprintf(buf, "%s\n", e->items[i]);
+       return snprintf(buf, PAGE_SIZE, "%s\n", e->items[i]);
 }
 EXPORT_SYMBOL_GPL(iio_enum_read);
 
@@ -716,6 +716,8 @@ static int iio_device_add_info_mask_type(struct iio_dev *indio_dev,
        int i, ret, attrcount = 0;
 
        for_each_set_bit(i, infomask, sizeof(infomask)*8) {
+               if (i >= ARRAY_SIZE(iio_chan_info_postfix))
+                       return -EINVAL;
                ret = __iio_add_chan_devattr(iio_chan_info_postfix[i],
                                             chan,
                                             &iio_read_channel_info,
@@ -820,7 +822,7 @@ static ssize_t iio_show_dev_name(struct device *dev,
                                 char *buf)
 {
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-       return sprintf(buf, "%s\n", indio_dev->name);
+       return snprintf(buf, PAGE_SIZE, "%s\n", indio_dev->name);
 }
 
 static DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL);
index ea6e06b..dddfb0f 100644 (file)
@@ -321,7 +321,9 @@ static int iio_device_add_event(struct iio_dev *indio_dev,
        char *postfix;
        int ret;
 
-       for_each_set_bit(i, mask, sizeof(*mask)) {
+       for_each_set_bit(i, mask, sizeof(*mask)*8) {
+               if (i >= ARRAY_SIZE(iio_ev_info_text))
+                       return -EINVAL;
                postfix = kasprintf(GFP_KERNEL, "%s_%s_%s",
                                iio_ev_type_text[type], iio_ev_dir_text[dir],
                                iio_ev_info_text[i]);
index 0cf5f8e..adeba5a 100644 (file)
@@ -443,6 +443,24 @@ err_unlock:
 }
 EXPORT_SYMBOL_GPL(iio_read_channel_raw);
 
+int iio_read_channel_average_raw(struct iio_channel *chan, int *val)
+{
+       int ret;
+
+       mutex_lock(&chan->indio_dev->info_exist_lock);
+       if (chan->indio_dev->info == NULL) {
+               ret = -ENODEV;
+               goto err_unlock;
+       }
+
+       ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_AVERAGE_RAW);
+err_unlock:
+       mutex_unlock(&chan->indio_dev->info_exist_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(iio_read_channel_average_raw);
+
 static int iio_convert_raw_to_processed_unlocked(struct iio_channel *chan,
        int raw, int *processed, unsigned int scale)
 {
index d86d226..05a364c 100644 (file)
@@ -11,7 +11,8 @@ config AK8975
        depends on GPIOLIB
        help
          Say yes here to build support for Asahi Kasei AK8975 3-Axis
-         Magnetometer.
+         Magnetometer. This driver can also support AK8963, if i2c
+         device name is identified as ak8963.
 
          To compile this driver as a module, choose M here: the module
          will be called ak8975.
index 74866d1..f5c1d41 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/bitops.h>
 #include <linux/gpio.h>
 #include <linux/of_gpio.h>
+#include <linux/acpi.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 #define AK8975_MAX_CONVERSION_TIMEOUT  500
 #define AK8975_CONVERSION_DONE_POLL_TIME 10
 #define AK8975_DATA_READY_TIMEOUT      ((100*HZ)/1000)
-#define RAW_TO_GAUSS(asa) ((((asa) + 128) * 3000) / 256)
+#define RAW_TO_GAUSS_8975(asa) ((((asa) + 128) * 3000) / 256)
+#define RAW_TO_GAUSS_8963(asa) ((((asa) + 128) * 6000) / 256)
+
+/* Compatible Asahi Kasei Compass parts */
+enum asahi_compass_chipset {
+       AK8975,
+       AK8963,
+};
 
 /*
  * Per-instance context data for the device.
@@ -101,6 +109,7 @@ struct ak8975_data {
        int                     eoc_irq;
        wait_queue_head_t       data_ready_queue;
        unsigned long           flags;
+       enum asahi_compass_chipset chipset;
 };
 
 static const int ak8975_index_to_reg[] = {
@@ -272,9 +281,21 @@ static int ak8975_setup(struct i2c_client *client)
  * Since ASA doesn't change, we cache the resultant scale factor into the
  * device context in ak8975_setup().
  */
-       data->raw_to_gauss[0] = RAW_TO_GAUSS(data->asa[0]);
-       data->raw_to_gauss[1] = RAW_TO_GAUSS(data->asa[1]);
-       data->raw_to_gauss[2] = RAW_TO_GAUSS(data->asa[2]);
+       if (data->chipset == AK8963) {
+               /*
+                * H range is +-8190 and magnetometer range is +-4912.
+                * So HuT using the above explanation for 8975,
+                * 4912/8190 = ~ 6/10.
+                * So the Hadj should use 6/10 instead of 3/10.
+                */
+               data->raw_to_gauss[0] = RAW_TO_GAUSS_8963(data->asa[0]);
+               data->raw_to_gauss[1] = RAW_TO_GAUSS_8963(data->asa[1]);
+               data->raw_to_gauss[2] = RAW_TO_GAUSS_8963(data->asa[2]);
+       } else {
+               data->raw_to_gauss[0] = RAW_TO_GAUSS_8975(data->asa[0]);
+               data->raw_to_gauss[1] = RAW_TO_GAUSS_8975(data->asa[1]);
+               data->raw_to_gauss[2] = RAW_TO_GAUSS_8975(data->asa[2]);
+       }
 
        return 0;
 }
@@ -455,6 +476,27 @@ static const struct iio_info ak8975_info = {
        .driver_module = THIS_MODULE,
 };
 
+static const struct acpi_device_id ak_acpi_match[] = {
+       {"AK8975", AK8975},
+       {"AK8963", AK8963},
+       {"INVN6500", AK8963},
+       { },
+};
+MODULE_DEVICE_TABLE(acpi, ak_acpi_match);
+
+static char *ak8975_match_acpi_device(struct device *dev,
+                               enum asahi_compass_chipset *chipset)
+{
+       const struct acpi_device_id *id;
+
+       id = acpi_match_device(dev->driver->acpi_match_table, dev);
+       if (!id)
+               return NULL;
+       *chipset = (int)id->driver_data;
+
+       return (char *)dev_name(dev);
+}
+
 static int ak8975_probe(struct i2c_client *client,
                        const struct i2c_device_id *id)
 {
@@ -462,6 +504,7 @@ static int ak8975_probe(struct i2c_client *client,
        struct iio_dev *indio_dev;
        int eoc_gpio;
        int err;
+       char *name = NULL;
 
        /* Grab and set up the supplied GPIO. */
        if (client->dev.platform_data)
@@ -499,6 +542,19 @@ static int ak8975_probe(struct i2c_client *client,
        data->eoc_gpio = eoc_gpio;
        data->eoc_irq = 0;
 
+       /* id will be NULL when enumerated via ACPI */
+       if (id) {
+               data->chipset =
+                       (enum asahi_compass_chipset)(id->driver_data);
+               name = (char *) id->name;
+       } else if (ACPI_HANDLE(&client->dev))
+               name = ak8975_match_acpi_device(&client->dev, &data->chipset);
+       else {
+               err = -ENOSYS;
+               goto exit_free_iio;
+       }
+       dev_dbg(&client->dev, "Asahi compass chip %s\n", name);
+
        /* Perform some basic start-of-day setup of the device. */
        err = ak8975_setup(client);
        if (err < 0) {
@@ -515,7 +571,7 @@ static int ak8975_probe(struct i2c_client *client,
        indio_dev->info = &ak8975_info;
        indio_dev->name = id->name;
        indio_dev->modes = INDIO_DIRECT_MODE;
-
+       indio_dev->name = name;
        err = iio_device_register(indio_dev);
        if (err < 0)
                goto exit_free_iio;
@@ -552,7 +608,8 @@ static int ak8975_remove(struct i2c_client *client)
 }
 
 static const struct i2c_device_id ak8975_id[] = {
-       {"ak8975", 0},
+       {"ak8975", AK8975},
+       {"ak8963", AK8963},
        {}
 };
 
@@ -569,6 +626,7 @@ static struct i2c_driver ak8975_driver = {
        .driver = {
                .name   = "ak8975",
                .of_match_table = ak8975_of_match,
+               .acpi_match_table = ACPI_PTR(ak_acpi_match),
        },
        .probe          = ak8975_probe,
        .remove         = ak8975_remove,
index 52bbcfa..240a21d 100644 (file)
@@ -355,6 +355,8 @@ int st_magn_common_probe(struct iio_dev *indio_dev,
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &magn_info;
 
+       st_sensors_power_enable(indio_dev);
+
        err = st_sensors_check_device_support(indio_dev,
                                ARRAY_SIZE(st_magn_sensors), st_magn_sensors);
        if (err < 0)
@@ -387,6 +389,9 @@ int st_magn_common_probe(struct iio_dev *indio_dev,
        if (err)
                goto st_magn_device_register_error;
 
+       dev_info(&indio_dev->dev, "registered magnetometer %s\n",
+                indio_dev->name);
+
        return 0;
 
 st_magn_device_register_error:
@@ -403,6 +408,8 @@ void st_magn_common_remove(struct iio_dev *indio_dev)
 {
        struct st_sensor_data *mdata = iio_priv(indio_dev);
 
+       st_sensors_power_disable(indio_dev);
+
        iio_device_unregister(indio_dev);
        if (mdata->get_irq_data_ready(indio_dev) > 0)
                st_sensors_deallocate_trigger(indio_dev);
index 7418768..cd7e01f 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/iio/sysfs.h>
 #include <linux/iio/trigger.h>
 #include <linux/iio/buffer.h>
-#include <linux/regulator/consumer.h>
 #include <asm/unaligned.h>
 
 #include <linux/iio/common/st_sensors.h>
@@ -387,40 +386,6 @@ static const struct iio_trigger_ops st_press_trigger_ops = {
 #define ST_PRESS_TRIGGER_OPS NULL
 #endif
 
-static void st_press_power_enable(struct iio_dev *indio_dev)
-{
-       struct st_sensor_data *pdata = iio_priv(indio_dev);
-       int err;
-
-       /* Regulators not mandatory, but if requested we should enable them. */
-       pdata->vdd = devm_regulator_get_optional(&indio_dev->dev, "vdd");
-       if (!IS_ERR(pdata->vdd)) {
-               err = regulator_enable(pdata->vdd);
-               if (err != 0)
-                       dev_warn(&indio_dev->dev,
-                                "Failed to enable specified Vdd supply\n");
-       }
-
-       pdata->vdd_io = devm_regulator_get_optional(&indio_dev->dev, "vddio");
-       if (!IS_ERR(pdata->vdd_io)) {
-               err = regulator_enable(pdata->vdd_io);
-               if (err != 0)
-                       dev_warn(&indio_dev->dev,
-                                "Failed to enable specified Vdd_IO supply\n");
-       }
-}
-
-static void st_press_power_disable(struct iio_dev *indio_dev)
-{
-       struct st_sensor_data *pdata = iio_priv(indio_dev);
-
-       if (!IS_ERR(pdata->vdd))
-               regulator_disable(pdata->vdd);
-
-       if (!IS_ERR(pdata->vdd_io))
-               regulator_disable(pdata->vdd_io);
-}
-
 int st_press_common_probe(struct iio_dev *indio_dev,
                                struct st_sensors_platform_data *plat_data)
 {
@@ -431,7 +396,7 @@ int st_press_common_probe(struct iio_dev *indio_dev,
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &press_info;
 
-       st_press_power_enable(indio_dev);
+       st_sensors_power_enable(indio_dev);
 
        err = st_sensors_check_device_support(indio_dev,
                                              ARRAY_SIZE(st_press_sensors),
@@ -474,6 +439,9 @@ int st_press_common_probe(struct iio_dev *indio_dev,
        if (err)
                goto st_press_device_register_error;
 
+       dev_info(&indio_dev->dev, "registered pressure sensor %s\n",
+                indio_dev->name);
+
        return err;
 
 st_press_device_register_error:
@@ -490,7 +458,7 @@ void st_press_common_remove(struct iio_dev *indio_dev)
 {
        struct st_sensor_data *pdata = iio_priv(indio_dev);
 
-       st_press_power_disable(indio_dev);
+       st_sensors_power_disable(indio_dev);
 
        iio_device_unregister(indio_dev);
        if (pdata->get_irq_data_ready(indio_dev) > 0)
diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig
new file mode 100644 (file)
index 0000000..0c8cdf5
--- /dev/null
@@ -0,0 +1,19 @@
+#
+# Proximity sensors
+#
+
+menu "Lightning sensors"
+
+config AS3935
+       tristate "AS3935 Franklin lightning sensor"
+       select IIO_BUFFER
+       select IIO_TRIGGERED_BUFFER
+       depends on SPI
+       help
+         Say Y here to build SPI interface support for the Austrian
+         Microsystems AS3935 lightning detection sensor.
+
+         To compile this driver as a module, choose M here: the
+         module will be called as3935
+
+endmenu
diff --git a/drivers/iio/proximity/Makefile b/drivers/iio/proximity/Makefile
new file mode 100644 (file)
index 0000000..743adee
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Makefile for IIO proximity sensors
+#
+
+# When adding new entries keep the list in alphabetical order
+obj-$(CONFIG_AS3935)           += as3935.o
diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c
new file mode 100644 (file)
index 0000000..bf677bf
--- /dev/null
@@ -0,0 +1,456 @@
+/*
+ * as3935.c - Support for AS3935 Franklin lightning sensor
+ *
+ * Copyright (C) 2014 Matt Ranostay <mranostay@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <linux/err.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/of_gpio.h>
+
+
+#define AS3935_AFE_GAIN                0x00
+#define AS3935_AFE_MASK                0x3F
+#define AS3935_AFE_GAIN_MAX    0x1F
+#define AS3935_AFE_PWR_BIT     BIT(0)
+
+#define AS3935_INT             0x03
+#define AS3935_INT_MASK                0x07
+#define AS3935_EVENT_INT       BIT(3)
+#define AS3935_NOISE_INT       BIT(1)
+
+#define AS3935_DATA            0x07
+#define AS3935_DATA_MASK       0x3F
+
+#define AS3935_TUNE_CAP                0x08
+#define AS3935_CALIBRATE       0x3D
+
+#define AS3935_WRITE_DATA      BIT(15)
+#define AS3935_READ_DATA       BIT(14)
+#define AS3935_ADDRESS(x)      ((x) << 8)
+
+#define MAX_PF_CAP             120
+#define TUNE_CAP_DIV           8
+
+struct as3935_state {
+       struct spi_device *spi;
+       struct iio_trigger *trig;
+       struct mutex lock;
+       struct delayed_work work;
+
+       u32 tune_cap;
+       u8 buf[2] ____cacheline_aligned;
+};
+
+static const struct iio_chan_spec as3935_channels[] = {
+       {
+               .type           = IIO_PROXIMITY,
+               .info_mask_separate =
+                       BIT(IIO_CHAN_INFO_RAW) |
+                       BIT(IIO_CHAN_INFO_PROCESSED),
+               .scan_index     = 0,
+               .scan_type = {
+                       .sign           = 'u',
+                       .realbits       = 6,
+                       .storagebits    = 8,
+               },
+       },
+       IIO_CHAN_SOFT_TIMESTAMP(1),
+};
+
+static int as3935_read(struct as3935_state *st, unsigned int reg, int *val)
+{
+       u8 cmd;
+       int ret;
+
+       cmd = (AS3935_READ_DATA | AS3935_ADDRESS(reg)) >> 8;
+       ret = spi_w8r8(st->spi, cmd);
+       if (ret < 0)
+               return ret;
+       *val = ret;
+
+       return 0;
+};
+
+static int as3935_write(struct as3935_state *st,
+                               unsigned int reg,
+                               unsigned int val)
+{
+       u8 *buf = st->buf;
+
+       buf[0] = (AS3935_WRITE_DATA | AS3935_ADDRESS(reg)) >> 8;
+       buf[1] = val;
+
+       return spi_write(st->spi, buf, 2);
+};
+
+static ssize_t as3935_sensor_sensitivity_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct as3935_state *st = iio_priv(dev_to_iio_dev(dev));
+       int val, ret;
+
+       ret = as3935_read(st, AS3935_AFE_GAIN, &val);
+       if (ret)
+               return ret;
+       val = (val & AS3935_AFE_MASK) >> 1;
+
+       return sprintf(buf, "%d\n", val);
+};
+
+static ssize_t as3935_sensor_sensitivity_store(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *buf, size_t len)
+{
+       struct as3935_state *st = iio_priv(dev_to_iio_dev(dev));
+       unsigned long val;
+       int ret;
+
+       ret = kstrtoul((const char *) buf, 10, &val);
+       if (ret)
+               return -EINVAL;
+
+       if (val > AS3935_AFE_GAIN_MAX)
+               return -EINVAL;
+
+       as3935_write(st, AS3935_AFE_GAIN, val << 1);
+
+       return len;
+};
+
+static IIO_DEVICE_ATTR(sensor_sensitivity, S_IRUGO | S_IWUSR,
+       as3935_sensor_sensitivity_show, as3935_sensor_sensitivity_store, 0);
+
+
+static struct attribute *as3935_attributes[] = {
+       &iio_dev_attr_sensor_sensitivity.dev_attr.attr,
+       NULL,
+};
+
+static struct attribute_group as3935_attribute_group = {
+       .attrs = as3935_attributes,
+};
+
+static int as3935_read_raw(struct iio_dev *indio_dev,
+                          struct iio_chan_spec const *chan,
+                          int *val,
+                          int *val2,
+                          long m)
+{
+       struct as3935_state *st = iio_priv(indio_dev);
+       int ret;
+
+
+       switch (m) {
+       case IIO_CHAN_INFO_PROCESSED:
+       case IIO_CHAN_INFO_RAW:
+               *val2 = 0;
+               ret = as3935_read(st, AS3935_DATA, val);
+               if (ret)
+                       return ret;
+
+               if (m == IIO_CHAN_INFO_RAW)
+                       return IIO_VAL_INT;
+
+               /* storm out of range */
+               if (*val == AS3935_DATA_MASK)
+                       return -EINVAL;
+               *val *= 1000;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return IIO_VAL_INT;
+}
+
+static const struct iio_info as3935_info = {
+       .driver_module = THIS_MODULE,
+       .attrs = &as3935_attribute_group,
+       .read_raw = &as3935_read_raw,
+};
+
+static irqreturn_t as3935_trigger_handler(int irq, void *private)
+{
+       struct iio_poll_func *pf = private;
+       struct iio_dev *indio_dev = pf->indio_dev;
+       struct as3935_state *st = iio_priv(indio_dev);
+       int val, ret;
+
+       ret = as3935_read(st, AS3935_DATA, &val);
+       if (ret)
+               goto err_read;
+       val &= AS3935_DATA_MASK;
+       val *= 1000;
+
+       iio_push_to_buffers_with_timestamp(indio_dev, &val, pf->timestamp);
+err_read:
+       iio_trigger_notify_done(indio_dev->trig);
+
+       return IRQ_HANDLED;
+};
+
+static const struct iio_trigger_ops iio_interrupt_trigger_ops = {
+       .owner = THIS_MODULE,
+};
+
+static void as3935_event_work(struct work_struct *work)
+{
+       struct as3935_state *st;
+       int val;
+
+       st = container_of(work, struct as3935_state, work.work);
+
+       as3935_read(st, AS3935_INT, &val);
+       val &= AS3935_INT_MASK;
+
+       switch (val) {
+       case AS3935_EVENT_INT:
+               iio_trigger_poll(st->trig, iio_get_time_ns());
+               break;
+       case AS3935_NOISE_INT:
+               dev_warn(&st->spi->dev, "noise level is too high");
+               break;
+       }
+};
+
+static irqreturn_t as3935_interrupt_handler(int irq, void *private)
+{
+       struct iio_dev *indio_dev = private;
+       struct as3935_state *st = iio_priv(indio_dev);
+
+       /*
+        * Delay work for >2 milliseconds after an interrupt to allow
+        * estimated distance to recalculated.
+        */
+
+       schedule_delayed_work(&st->work, msecs_to_jiffies(3));
+
+       return IRQ_HANDLED;
+}
+
+static void calibrate_as3935(struct as3935_state *st)
+{
+       mutex_lock(&st->lock);
+
+       /* mask disturber interrupt bit */
+       as3935_write(st, AS3935_INT, BIT(5));
+
+       as3935_write(st, AS3935_CALIBRATE, 0x96);
+       as3935_write(st, AS3935_TUNE_CAP,
+               BIT(5) | (st->tune_cap / TUNE_CAP_DIV));
+
+       mdelay(2);
+       as3935_write(st, AS3935_TUNE_CAP, (st->tune_cap / TUNE_CAP_DIV));
+
+       mutex_unlock(&st->lock);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int as3935_suspend(struct spi_device *spi, pm_message_t msg)
+{
+       struct iio_dev *indio_dev = spi_get_drvdata(spi);
+       struct as3935_state *st = iio_priv(indio_dev);
+       int val, ret;
+
+       mutex_lock(&st->lock);
+       ret = as3935_read(st, AS3935_AFE_GAIN, &val);
+       if (ret)
+               goto err_suspend;
+       val |= AS3935_AFE_PWR_BIT;
+
+       ret = as3935_write(st, AS3935_AFE_GAIN, val);
+
+err_suspend:
+       mutex_unlock(&st->lock);
+
+       return ret;
+}
+
+static int as3935_resume(struct spi_device *spi)
+{
+       struct iio_dev *indio_dev = spi_get_drvdata(spi);
+       struct as3935_state *st = iio_priv(indio_dev);
+       int val, ret;
+
+       mutex_lock(&st->lock);
+       ret = as3935_read(st, AS3935_AFE_GAIN, &val);
+       if (ret)
+               goto err_resume;
+       val &= ~AS3935_AFE_PWR_BIT;
+       ret = as3935_write(st, AS3935_AFE_GAIN, val);
+
+err_resume:
+       mutex_unlock(&st->lock);
+
+       return ret;
+}
+#else
+#define as3935_suspend NULL
+#define as3935_resume  NULL
+#endif
+
+static int as3935_probe(struct spi_device *spi)
+{
+       struct iio_dev *indio_dev;
+       struct iio_trigger *trig;
+       struct as3935_state *st;
+       struct device_node *np = spi->dev.of_node;
+       int ret;
+
+       /* Be sure lightning event interrupt is specified */
+       if (!spi->irq) {
+               dev_err(&spi->dev, "unable to get event interrupt\n");
+               return -EINVAL;
+       }
+
+       indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(st));
+       if (!indio_dev)
+               return -ENOMEM;
+
+       st = iio_priv(indio_dev);
+       st->spi = spi;
+       st->tune_cap = 0;
+
+       spi_set_drvdata(spi, indio_dev);
+       mutex_init(&st->lock);
+       INIT_DELAYED_WORK(&st->work, as3935_event_work);
+
+       ret = of_property_read_u32(np,
+                       "ams,tuning-capacitor-pf", &st->tune_cap);
+       if (ret) {
+               st->tune_cap = 0;
+               dev_warn(&spi->dev,
+                       "no tuning-capacitor-pf set, defaulting to %d",
+                       st->tune_cap);
+       }
+
+       if (st->tune_cap > MAX_PF_CAP) {
+               dev_err(&spi->dev,
+                       "wrong tuning-capacitor-pf setting of %d\n",
+                       st->tune_cap);
+               return -EINVAL;
+       }
+
+       indio_dev->dev.parent = &spi->dev;
+       indio_dev->name = spi_get_device_id(spi)->name;
+       indio_dev->channels = as3935_channels;
+       indio_dev->num_channels = ARRAY_SIZE(as3935_channels);
+       indio_dev->modes = INDIO_DIRECT_MODE;
+       indio_dev->info = &as3935_info;
+
+       trig = devm_iio_trigger_alloc(&spi->dev, "%s-dev%d",
+                                     indio_dev->name, indio_dev->id);
+
+       if (!trig)
+               return -ENOMEM;
+
+       st->trig = trig;
+       trig->dev.parent = indio_dev->dev.parent;
+       iio_trigger_set_drvdata(trig, indio_dev);
+       trig->ops = &iio_interrupt_trigger_ops;
+
+       ret = iio_trigger_register(trig);
+       if (ret) {
+               dev_err(&spi->dev, "failed to register trigger\n");
+               return ret;
+       }
+
+       ret = iio_triggered_buffer_setup(indio_dev, NULL,
+               &as3935_trigger_handler, NULL);
+
+       if (ret) {
+               dev_err(&spi->dev, "cannot setup iio trigger\n");
+               goto unregister_trigger;
+       }
+
+       calibrate_as3935(st);
+
+       ret = devm_request_irq(&spi->dev, spi->irq,
+                               &as3935_interrupt_handler,
+                               IRQF_TRIGGER_RISING,
+                               dev_name(&spi->dev),
+                               indio_dev);
+
+       if (ret) {
+               dev_err(&spi->dev, "unable to request irq\n");
+               goto unregister_buffer;
+       }
+
+       ret = iio_device_register(indio_dev);
+       if (ret < 0) {
+               dev_err(&spi->dev, "unable to register device\n");
+               goto unregister_buffer;
+       }
+       return 0;
+
+unregister_buffer:
+       iio_triggered_buffer_cleanup(indio_dev);
+
+unregister_trigger:
+       iio_trigger_unregister(st->trig);
+
+       return ret;
+};
+
+static int as3935_remove(struct spi_device *spi)
+{
+       struct iio_dev *indio_dev = spi_get_drvdata(spi);
+       struct as3935_state *st = iio_priv(indio_dev);
+
+       iio_device_unregister(indio_dev);
+       iio_triggered_buffer_cleanup(indio_dev);
+       iio_trigger_unregister(st->trig);
+
+       return 0;
+};
+
+static const struct spi_device_id as3935_id[] = {
+       {"as3935", 0},
+       {},
+};
+MODULE_DEVICE_TABLE(spi, as3935_id);
+
+static struct spi_driver as3935_driver = {
+       .driver = {
+               .name   = "as3935",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = as3935_probe,
+       .remove         = as3935_remove,
+       .id_table       = as3935_id,
+       .suspend        = as3935_suspend,
+       .resume         = as3935_resume,
+};
+module_spi_driver(as3935_driver);
+
+MODULE_AUTHOR("Matt Ranostay <mranostay@gmail.com>");
+MODULE_DESCRIPTION("AS3935 lightning sensor");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("spi:as3935");
index 3633298..b87e382 100644 (file)
@@ -37,26 +37,6 @@ config AD7606_IFACE_SPI
          Say yes here to include parallel interface support on the AD7606
          ADC driver.
 
-config AD799X
-       tristate "Analog Devices AD799x ADC driver"
-       depends on I2C
-       select IIO_TRIGGER if IIO_BUFFER
-       select AD799X_RING_BUFFER
-       help
-         Say yes here to build support for Analog Devices:
-         ad7991, ad7995, ad7999, ad7992, ad7993, ad7994, ad7997, ad7998
-         i2c analog to digital converters (ADC). Provides direct access
-         via sysfs.
-
-config AD799X_RING_BUFFER
-       bool "Analog Devices AD799x: use ring buffer"
-       depends on AD799X
-       select IIO_BUFFER
-       select IIO_TRIGGERED_BUFFER
-       help
-         Say yes here to include ring buffer support in the AD799X
-         ADC driver.
-
 config AD7780
        tristate "Analog Devices AD7780 and similar ADCs driver"
        depends on SPI
index 3e9fb14..afdcd1f 100644 (file)
@@ -8,10 +8,6 @@ ad7606-$(CONFIG_AD7606_IFACE_PARALLEL) += ad7606_par.o
 ad7606-$(CONFIG_AD7606_IFACE_SPI) += ad7606_spi.o
 obj-$(CONFIG_AD7606) += ad7606.o
 
-ad799x-y := ad799x_core.o
-ad799x-$(CONFIG_AD799X_RING_BUFFER) += ad799x_ring.o
-obj-$(CONFIG_AD799X) += ad799x.o
-
 obj-$(CONFIG_AD7291) += ad7291.o
 obj-$(CONFIG_AD7780) += ad7780.o
 obj-$(CONFIG_AD7816) += ad7816.o
index 93c7299..ec89d05 100644 (file)
@@ -14,7 +14,7 @@
  */
 
 /**
- * struct ad7606_platform_data - platform/board specifc information
+ * struct ad7606_platform_data - platform/board specific information
  * @default_os:                default oversampling value {0, 2, 4, 8, 16, 32, 64}
  * @default_range:     default range +/-{5000, 10000} mVolt
  * @gpio_convst:       number of gpio connected to the CONVST pin
@@ -41,7 +41,7 @@ struct ad7606_platform_data {
 };
 
 /**
- * struct ad7606_chip_info - chip specifc information
+ * struct ad7606_chip_info - chip specific information
  * @name:              identification string for chip
  * @int_vref_mv:       the internal reference voltage
  * @channels:          channel specification
index 2369cf2..158d770 100644 (file)
@@ -40,7 +40,7 @@
 
 
 /*
- * struct ad7816_chip_info - chip specifc information
+ * struct ad7816_chip_info - chip specific information
  */
 
 struct ad7816_chip_info {
diff --git a/drivers/staging/iio/adc/ad799x.h b/drivers/staging/iio/adc/ad799x.h
deleted file mode 100644 (file)
index fc8c852..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2010-2011 Michael Hennerich, Analog Devices Inc.
- * Copyright (C) 2008-2010 Jonathan Cameron
- *
- * 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.
- *
- * ad799x.h
- */
-
-#ifndef _AD799X_H_
-#define  _AD799X_H_
-
-#define AD799X_CHANNEL_SHIFT                   4
-#define AD799X_STORAGEBITS                     16
-/*
- * AD7991, AD7995 and AD7999 defines
- */
-
-#define AD7991_REF_SEL                         0x08
-#define AD7991_FLTR                            0x04
-#define AD7991_BIT_TRIAL_DELAY                 0x02
-#define AD7991_SAMPLE_DELAY                    0x01
-
-/*
- * AD7992, AD7993, AD7994, AD7997 and AD7998 defines
- */
-
-#define AD7998_FLTR                            0x08
-#define AD7998_ALERT_EN                                0x04
-#define AD7998_BUSY_ALERT                      0x02
-#define AD7998_BUSY_ALERT_POL                  0x01
-
-#define AD7998_CONV_RES_REG                    0x0
-#define AD7998_ALERT_STAT_REG                  0x1
-#define AD7998_CONF_REG                                0x2
-#define AD7998_CYCLE_TMR_REG                   0x3
-
-#define AD7998_DATALOW_REG(x)                  ((x) * 3 + 0x4)
-#define AD7998_DATAHIGH_REG(x)                 ((x) * 3 + 0x5)
-#define AD7998_HYST_REG(x)                     ((x) * 3 + 0x6)
-
-#define AD7998_CYC_MASK                                0x7
-#define AD7998_CYC_DIS                         0x0
-#define AD7998_CYC_TCONF_32                    0x1
-#define AD7998_CYC_TCONF_64                    0x2
-#define AD7998_CYC_TCONF_128                   0x3
-#define AD7998_CYC_TCONF_256                   0x4
-#define AD7998_CYC_TCONF_512                   0x5
-#define AD7998_CYC_TCONF_1024                  0x6
-#define AD7998_CYC_TCONF_2048                  0x7
-
-#define AD7998_ALERT_STAT_CLEAR                        0xFF
-
-/*
- * AD7997 and AD7997 defines
- */
-
-#define AD7997_8_READ_SINGLE                   0x80
-#define AD7997_8_READ_SEQUENCE                 0x70
-/* TODO: move this into a common header */
-#define RES_MASK(bits) ((1 << (bits)) - 1)
-
-enum {
-       ad7991,
-       ad7995,
-       ad7999,
-       ad7992,
-       ad7993,
-       ad7994,
-       ad7997,
-       ad7998
-};
-
-struct ad799x_state;
-
-/**
- * struct ad799x_chip_info - chip specifc information
- * @channel:           channel specification
- * @num_channels:      number of channels
- * @monitor_mode:      whether the chip supports monitor interrupts
- * @default_config:    device default configuration
- * @event_attrs:       pointer to the monitor event attribute group
- */
-
-struct ad799x_chip_info {
-       struct iio_chan_spec            channel[9];
-       int                             num_channels;
-       u16                             default_config;
-       const struct iio_info           *info;
-};
-
-struct ad799x_state {
-       struct i2c_client               *client;
-       const struct ad799x_chip_info   *chip_info;
-       struct regulator                *reg;
-       struct regulator                *vref;
-       unsigned                        id;
-       u16                             config;
-
-       u8                              *rx_buf;
-       unsigned int                    transfer_size;
-};
-
-#ifdef CONFIG_AD799X_RING_BUFFER
-int ad799x_register_ring_funcs_and_init(struct iio_dev *indio_dev);
-void ad799x_ring_cleanup(struct iio_dev *indio_dev);
-#else /* CONFIG_AD799X_RING_BUFFER */
-
-static inline int
-ad799x_register_ring_funcs_and_init(struct iio_dev *indio_dev)
-{
-       return 0;
-}
-
-static inline void ad799x_ring_cleanup(struct iio_dev *indio_dev)
-{
-}
-#endif /* CONFIG_AD799X_RING_BUFFER */
-#endif /* _AD799X_H_ */
diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c
deleted file mode 100644 (file)
index 979ec77..0000000
+++ /dev/null
@@ -1,657 +0,0 @@
-/*
- * iio/adc/ad799x.c
- * Copyright (C) 2010-2011 Michael Hennerich, Analog Devices Inc.
- *
- * based on iio/adc/max1363
- * Copyright (C) 2008-2010 Jonathan Cameron
- *
- * based on linux/drivers/i2c/chips/max123x
- * Copyright (C) 2002-2004 Stefan Eletzhofer
- *
- * based on linux/drivers/acron/char/pcf8583.c
- * Copyright (C) 2000 Russell King
- *
- * 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.
- *
- * ad799x.c
- *
- * Support for ad7991, ad7995, ad7999, ad7992, ad7993, ad7994, ad7997,
- * ad7998 and similar chips.
- *
- */
-
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/sysfs.h>
-#include <linux/i2c.h>
-#include <linux/regulator/consumer.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-#include <linux/err.h>
-#include <linux/module.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
-#include <linux/iio/events.h>
-#include <linux/iio/buffer.h>
-
-#include "ad799x.h"
-
-/*
- * ad799x register access by I2C
- */
-static int ad799x_i2c_read16(struct ad799x_state *st, u8 reg, u16 *data)
-{
-       struct i2c_client *client = st->client;
-       int ret = 0;
-
-       ret = i2c_smbus_read_word_swapped(client, reg);
-       if (ret < 0) {
-               dev_err(&client->dev, "I2C read error\n");
-               return ret;
-       }
-
-       *data = (u16)ret;
-
-       return 0;
-}
-
-static int ad799x_i2c_read8(struct ad799x_state *st, u8 reg, u8 *data)
-{
-       struct i2c_client *client = st->client;
-       int ret = 0;
-
-       ret = i2c_smbus_read_byte_data(client, reg);
-       if (ret < 0) {
-               dev_err(&client->dev, "I2C read error\n");
-               return ret;
-       }
-
-       *data = (u8)ret;
-
-       return 0;
-}
-
-static int ad799x_i2c_write16(struct ad799x_state *st, u8 reg, u16 data)
-{
-       struct i2c_client *client = st->client;
-       int ret = 0;
-
-       ret = i2c_smbus_write_word_swapped(client, reg, data);
-       if (ret < 0)
-               dev_err(&client->dev, "I2C write error\n");
-
-       return ret;
-}
-
-static int ad799x_i2c_write8(struct ad799x_state *st, u8 reg, u8 data)
-{
-       struct i2c_client *client = st->client;
-       int ret = 0;
-
-       ret = i2c_smbus_write_byte_data(client, reg, data);
-       if (ret < 0)
-               dev_err(&client->dev, "I2C write error\n");
-
-       return ret;
-}
-
-static int ad7997_8_update_scan_mode(struct iio_dev *indio_dev,
-       const unsigned long *scan_mask)
-{
-       struct ad799x_state *st = iio_priv(indio_dev);
-
-       kfree(st->rx_buf);
-       st->rx_buf = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
-       if (!st->rx_buf)
-               return -ENOMEM;
-
-       st->transfer_size = bitmap_weight(scan_mask, indio_dev->masklength) * 2;
-
-       switch (st->id) {
-       case ad7997:
-       case ad7998:
-               return ad799x_i2c_write16(st, AD7998_CONF_REG,
-                       st->config | (*scan_mask << AD799X_CHANNEL_SHIFT));
-       default:
-               break;
-       }
-
-       return 0;
-}
-
-static int ad799x_scan_direct(struct ad799x_state *st, unsigned ch)
-{
-       u16 rxbuf;
-       u8 cmd;
-       int ret;
-
-       switch (st->id) {
-       case ad7991:
-       case ad7995:
-       case ad7999:
-               cmd = st->config | ((1 << ch) << AD799X_CHANNEL_SHIFT);
-               break;
-       case ad7992:
-       case ad7993:
-       case ad7994:
-               cmd = (1 << ch) << AD799X_CHANNEL_SHIFT;
-               break;
-       case ad7997:
-       case ad7998:
-               cmd = (ch << AD799X_CHANNEL_SHIFT) | AD7997_8_READ_SINGLE;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       ret = ad799x_i2c_read16(st, cmd, &rxbuf);
-       if (ret < 0)
-               return ret;
-
-       return rxbuf;
-}
-
-static int ad799x_read_raw(struct iio_dev *indio_dev,
-                          struct iio_chan_spec const *chan,
-                          int *val,
-                          int *val2,
-                          long m)
-{
-       int ret;
-       struct ad799x_state *st = iio_priv(indio_dev);
-
-       switch (m) {
-       case IIO_CHAN_INFO_RAW:
-               mutex_lock(&indio_dev->mlock);
-               if (iio_buffer_enabled(indio_dev))
-                       ret = -EBUSY;
-               else
-                       ret = ad799x_scan_direct(st, chan->scan_index);
-               mutex_unlock(&indio_dev->mlock);
-
-               if (ret < 0)
-                       return ret;
-               *val = (ret >> chan->scan_type.shift) &
-                       RES_MASK(chan->scan_type.realbits);
-               return IIO_VAL_INT;
-       case IIO_CHAN_INFO_SCALE:
-               ret = regulator_get_voltage(st->vref);
-               if (ret < 0)
-                       return ret;
-               *val = ret / 1000;
-               *val2 = chan->scan_type.realbits;
-               return IIO_VAL_FRACTIONAL_LOG2;
-       }
-       return -EINVAL;
-}
-static const unsigned int ad7998_frequencies[] = {
-       [AD7998_CYC_DIS]        = 0,
-       [AD7998_CYC_TCONF_32]   = 15625,
-       [AD7998_CYC_TCONF_64]   = 7812,
-       [AD7998_CYC_TCONF_128]  = 3906,
-       [AD7998_CYC_TCONF_512]  = 976,
-       [AD7998_CYC_TCONF_1024] = 488,
-       [AD7998_CYC_TCONF_2048] = 244,
-};
-static ssize_t ad799x_read_frequency(struct device *dev,
-                                       struct device_attribute *attr,
-                                       char *buf)
-{
-       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-       struct ad799x_state *st = iio_priv(indio_dev);
-
-       int ret;
-       u8 val;
-       ret = ad799x_i2c_read8(st, AD7998_CYCLE_TMR_REG, &val);
-       if (ret)
-               return ret;
-
-       val &= AD7998_CYC_MASK;
-
-       return sprintf(buf, "%u\n", ad7998_frequencies[val]);
-}
-
-static ssize_t ad799x_write_frequency(struct device *dev,
-                                        struct device_attribute *attr,
-                                        const char *buf,
-                                        size_t len)
-{
-       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-       struct ad799x_state *st = iio_priv(indio_dev);
-
-       long val;
-       int ret, i;
-       u8 t;
-
-       ret = kstrtol(buf, 10, &val);
-       if (ret)
-               return ret;
-
-       mutex_lock(&indio_dev->mlock);
-       ret = ad799x_i2c_read8(st, AD7998_CYCLE_TMR_REG, &t);
-       if (ret)
-               goto error_ret_mutex;
-       /* Wipe the bits clean */
-       t &= ~AD7998_CYC_MASK;
-
-       for (i = 0; i < ARRAY_SIZE(ad7998_frequencies); i++)
-               if (val == ad7998_frequencies[i])
-                       break;
-       if (i == ARRAY_SIZE(ad7998_frequencies)) {
-               ret = -EINVAL;
-               goto error_ret_mutex;
-       }
-       t |= i;
-       ret = ad799x_i2c_write8(st, AD7998_CYCLE_TMR_REG, t);
-
-error_ret_mutex:
-       mutex_unlock(&indio_dev->mlock);
-
-       return ret ? ret : len;
-}
-
-static int ad799x_read_event_config(struct iio_dev *indio_dev,
-                                   const struct iio_chan_spec *chan,
-                                   enum iio_event_type type,
-                                   enum iio_event_direction dir)
-{
-       return 1;
-}
-
-static unsigned int ad799x_threshold_reg(const struct iio_chan_spec *chan,
-                                        enum iio_event_direction dir,
-                                        enum iio_event_info info)
-{
-       switch (info) {
-       case IIO_EV_INFO_VALUE:
-               if (dir == IIO_EV_DIR_FALLING)
-                       return AD7998_DATALOW_REG(chan->channel);
-               else
-                       return AD7998_DATAHIGH_REG(chan->channel);
-       case IIO_EV_INFO_HYSTERESIS:
-               return AD7998_HYST_REG(chan->channel);
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int ad799x_write_event_value(struct iio_dev *indio_dev,
-                                   const struct iio_chan_spec *chan,
-                                   enum iio_event_type type,
-                                   enum iio_event_direction dir,
-                                   enum iio_event_info info,
-                                   int val, int val2)
-{
-       int ret;
-       struct ad799x_state *st = iio_priv(indio_dev);
-
-       mutex_lock(&indio_dev->mlock);
-       ret = ad799x_i2c_write16(st, ad799x_threshold_reg(chan, dir, info),
-               val);
-       mutex_unlock(&indio_dev->mlock);
-
-       return ret;
-}
-
-static int ad799x_read_event_value(struct iio_dev *indio_dev,
-                                   const struct iio_chan_spec *chan,
-                                   enum iio_event_type type,
-                                   enum iio_event_direction dir,
-                                   enum iio_event_info info,
-                                   int *val, int *val2)
-{
-       int ret;
-       struct ad799x_state *st = iio_priv(indio_dev);
-       u16 valin;
-
-       mutex_lock(&indio_dev->mlock);
-       ret = ad799x_i2c_read16(st, ad799x_threshold_reg(chan, dir, info),
-               &valin);
-       mutex_unlock(&indio_dev->mlock);
-       if (ret < 0)
-               return ret;
-       *val = valin;
-
-       return IIO_VAL_INT;
-}
-
-static irqreturn_t ad799x_event_handler(int irq, void *private)
-{
-       struct iio_dev *indio_dev = private;
-       struct ad799x_state *st = iio_priv(private);
-       u8 status;
-       int i, ret;
-
-       ret = ad799x_i2c_read8(st, AD7998_ALERT_STAT_REG, &status);
-       if (ret)
-               goto done;
-
-       if (!status)
-               goto done;
-
-       ad799x_i2c_write8(st, AD7998_ALERT_STAT_REG, AD7998_ALERT_STAT_CLEAR);
-
-       for (i = 0; i < 8; i++) {
-               if (status & (1 << i))
-                       iio_push_event(indio_dev,
-                                      i & 0x1 ?
-                                      IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE,
-                                                           (i >> 1),
-                                                           IIO_EV_TYPE_THRESH,
-                                                           IIO_EV_DIR_RISING) :
-                                      IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE,
-                                                           (i >> 1),
-                                                           IIO_EV_TYPE_THRESH,
-                                                           IIO_EV_DIR_FALLING),
-                                      iio_get_time_ns());
-       }
-
-done:
-       return IRQ_HANDLED;
-}
-
-static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
-                             ad799x_read_frequency,
-                             ad799x_write_frequency);
-static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("15625 7812 3906 1953 976 488 244 0");
-
-static struct attribute *ad799x_event_attributes[] = {
-       &iio_dev_attr_sampling_frequency.dev_attr.attr,
-       &iio_const_attr_sampling_frequency_available.dev_attr.attr,
-       NULL,
-};
-
-static struct attribute_group ad799x_event_attrs_group = {
-       .attrs = ad799x_event_attributes,
-       .name = "events",
-};
-
-static const struct iio_info ad7991_info = {
-       .read_raw = &ad799x_read_raw,
-       .driver_module = THIS_MODULE,
-};
-
-static const struct iio_info ad7993_4_7_8_info = {
-       .read_raw = &ad799x_read_raw,
-       .event_attrs = &ad799x_event_attrs_group,
-       .read_event_config = &ad799x_read_event_config,
-       .read_event_value = &ad799x_read_event_value,
-       .write_event_value = &ad799x_write_event_value,
-       .driver_module = THIS_MODULE,
-       .update_scan_mode = ad7997_8_update_scan_mode,
-};
-
-static const struct iio_event_spec ad799x_events[] = {
-       {
-               .type = IIO_EV_TYPE_THRESH,
-               .dir = IIO_EV_DIR_RISING,
-               .mask_separate = BIT(IIO_EV_INFO_VALUE) |
-                       BIT(IIO_EV_INFO_ENABLE),
-       }, {
-               .type = IIO_EV_TYPE_THRESH,
-               .dir = IIO_EV_DIR_FALLING,
-               .mask_separate = BIT(IIO_EV_INFO_VALUE) |
-                       BIT(IIO_EV_INFO_ENABLE),
-       }, {
-               .type = IIO_EV_TYPE_THRESH,
-               .dir = IIO_EV_DIR_EITHER,
-               .mask_separate = BIT(IIO_EV_INFO_HYSTERESIS),
-       },
-};
-
-#define _AD799X_CHANNEL(_index, _realbits, _ev_spec, _num_ev_spec) { \
-       .type = IIO_VOLTAGE, \
-       .indexed = 1, \
-       .channel = (_index), \
-       .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
-       .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
-       .scan_index = (_index), \
-       .scan_type = { \
-               .sign = 'u', \
-               .realbits = (_realbits), \
-               .storagebits = 16, \
-               .shift = 12 - (_realbits), \
-               .endianness = IIO_BE, \
-       }, \
-       .event_spec = _ev_spec, \
-       .num_event_specs = _num_ev_spec, \
-}
-
-#define AD799X_CHANNEL(_index, _realbits) \
-       _AD799X_CHANNEL(_index, _realbits, NULL, 0)
-
-#define AD799X_CHANNEL_WITH_EVENTS(_index, _realbits) \
-       _AD799X_CHANNEL(_index, _realbits, ad799x_events, \
-               ARRAY_SIZE(ad799x_events))
-
-static const struct ad799x_chip_info ad799x_chip_info_tbl[] = {
-       [ad7991] = {
-               .channel = {
-                       AD799X_CHANNEL(0, 12),
-                       AD799X_CHANNEL(1, 12),
-                       AD799X_CHANNEL(2, 12),
-                       AD799X_CHANNEL(3, 12),
-                       IIO_CHAN_SOFT_TIMESTAMP(4),
-               },
-               .num_channels = 5,
-               .info = &ad7991_info,
-       },
-       [ad7995] = {
-               .channel = {
-                       AD799X_CHANNEL(0, 10),
-                       AD799X_CHANNEL(1, 10),
-                       AD799X_CHANNEL(2, 10),
-                       AD799X_CHANNEL(3, 10),
-                       IIO_CHAN_SOFT_TIMESTAMP(4),
-               },
-               .num_channels = 5,
-               .info = &ad7991_info,
-       },
-       [ad7999] = {
-               .channel = {
-                       AD799X_CHANNEL(0, 8),
-                       AD799X_CHANNEL(1, 8),
-                       AD799X_CHANNEL(2, 8),
-                       AD799X_CHANNEL(3, 8),
-                       IIO_CHAN_SOFT_TIMESTAMP(4),
-               },
-               .num_channels = 5,
-               .info = &ad7991_info,
-       },
-       [ad7992] = {
-               .channel = {
-                       AD799X_CHANNEL_WITH_EVENTS(0, 12),
-                       AD799X_CHANNEL_WITH_EVENTS(1, 12),
-                       IIO_CHAN_SOFT_TIMESTAMP(3),
-               },
-               .num_channels = 3,
-               .default_config = AD7998_ALERT_EN,
-               .info = &ad7993_4_7_8_info,
-       },
-       [ad7993] = {
-               .channel = {
-                       AD799X_CHANNEL_WITH_EVENTS(0, 10),
-                       AD799X_CHANNEL_WITH_EVENTS(1, 10),
-                       AD799X_CHANNEL_WITH_EVENTS(2, 10),
-                       AD799X_CHANNEL_WITH_EVENTS(3, 10),
-                       IIO_CHAN_SOFT_TIMESTAMP(4),
-               },
-               .num_channels = 5,
-               .default_config = AD7998_ALERT_EN,
-               .info = &ad7993_4_7_8_info,
-       },
-       [ad7994] = {
-               .channel = {
-                       AD799X_CHANNEL_WITH_EVENTS(0, 12),
-                       AD799X_CHANNEL_WITH_EVENTS(1, 12),
-                       AD799X_CHANNEL_WITH_EVENTS(2, 12),
-                       AD799X_CHANNEL_WITH_EVENTS(3, 12),
-                       IIO_CHAN_SOFT_TIMESTAMP(4),
-               },
-               .num_channels = 5,
-               .default_config = AD7998_ALERT_EN,
-               .info = &ad7993_4_7_8_info,
-       },
-       [ad7997] = {
-               .channel = {
-                       AD799X_CHANNEL_WITH_EVENTS(0, 10),
-                       AD799X_CHANNEL_WITH_EVENTS(1, 10),
-                       AD799X_CHANNEL_WITH_EVENTS(2, 10),
-                       AD799X_CHANNEL_WITH_EVENTS(3, 10),
-                       AD799X_CHANNEL(4, 10),
-                       AD799X_CHANNEL(5, 10),
-                       AD799X_CHANNEL(6, 10),
-                       AD799X_CHANNEL(7, 10),
-                       IIO_CHAN_SOFT_TIMESTAMP(8),
-               },
-               .num_channels = 9,
-               .default_config = AD7998_ALERT_EN,
-               .info = &ad7993_4_7_8_info,
-       },
-       [ad7998] = {
-               .channel = {
-                       AD799X_CHANNEL_WITH_EVENTS(0, 12),
-                       AD799X_CHANNEL_WITH_EVENTS(1, 12),
-                       AD799X_CHANNEL_WITH_EVENTS(2, 12),
-                       AD799X_CHANNEL_WITH_EVENTS(3, 12),
-                       AD799X_CHANNEL(4, 12),
-                       AD799X_CHANNEL(5, 12),
-                       AD799X_CHANNEL(6, 12),
-                       AD799X_CHANNEL(7, 12),
-                       IIO_CHAN_SOFT_TIMESTAMP(8),
-               },
-               .num_channels = 9,
-               .default_config = AD7998_ALERT_EN,
-               .info = &ad7993_4_7_8_info,
-       },
-};
-
-static int ad799x_probe(struct i2c_client *client,
-                                  const struct i2c_device_id *id)
-{
-       int ret;
-       struct ad799x_state *st;
-       struct iio_dev *indio_dev;
-
-       indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
-       if (indio_dev == NULL)
-               return -ENOMEM;
-
-       st = iio_priv(indio_dev);
-       /* this is only used for device removal purposes */
-       i2c_set_clientdata(client, indio_dev);
-
-       st->id = id->driver_data;
-       st->chip_info = &ad799x_chip_info_tbl[st->id];
-       st->config = st->chip_info->default_config;
-
-       /* TODO: Add pdata options for filtering and bit delay */
-
-       st->reg = devm_regulator_get(&client->dev, "vcc");
-       if (IS_ERR(st->reg))
-               return PTR_ERR(st->reg);
-       ret = regulator_enable(st->reg);
-       if (ret)
-               return ret;
-       st->vref = devm_regulator_get(&client->dev, "vref");
-       if (IS_ERR(st->vref)) {
-               ret = PTR_ERR(st->vref);
-               goto error_disable_reg;
-       }
-       ret = regulator_enable(st->vref);
-       if (ret)
-               goto error_disable_reg;
-
-       st->client = client;
-
-       indio_dev->dev.parent = &client->dev;
-       indio_dev->name = id->name;
-       indio_dev->info = st->chip_info->info;
-
-       indio_dev->modes = INDIO_DIRECT_MODE;
-       indio_dev->channels = st->chip_info->channel;
-       indio_dev->num_channels = st->chip_info->num_channels;
-
-       ret = ad799x_register_ring_funcs_and_init(indio_dev);
-       if (ret)
-               goto error_disable_reg;
-
-       if (client->irq > 0) {
-               ret = devm_request_threaded_irq(&client->dev,
-                                               client->irq,
-                                               NULL,
-                                               ad799x_event_handler,
-                                               IRQF_TRIGGER_FALLING |
-                                               IRQF_ONESHOT,
-                                               client->name,
-                                               indio_dev);
-               if (ret)
-                       goto error_cleanup_ring;
-       }
-       ret = iio_device_register(indio_dev);
-       if (ret)
-               goto error_cleanup_ring;
-
-       return 0;
-
-error_cleanup_ring:
-       ad799x_ring_cleanup(indio_dev);
-error_disable_reg:
-       if (!IS_ERR(st->vref))
-               regulator_disable(st->vref);
-       if (!IS_ERR(st->reg))
-               regulator_disable(st->reg);
-
-       return ret;
-}
-
-static int ad799x_remove(struct i2c_client *client)
-{
-       struct iio_dev *indio_dev = i2c_get_clientdata(client);
-       struct ad799x_state *st = iio_priv(indio_dev);
-
-       iio_device_unregister(indio_dev);
-
-       ad799x_ring_cleanup(indio_dev);
-       if (!IS_ERR(st->vref))
-               regulator_disable(st->vref);
-       if (!IS_ERR(st->reg))
-               regulator_disable(st->reg);
-       kfree(st->rx_buf);
-
-       return 0;
-}
-
-static const struct i2c_device_id ad799x_id[] = {
-       { "ad7991", ad7991 },
-       { "ad7995", ad7995 },
-       { "ad7999", ad7999 },
-       { "ad7992", ad7992 },
-       { "ad7993", ad7993 },
-       { "ad7994", ad7994 },
-       { "ad7997", ad7997 },
-       { "ad7998", ad7998 },
-       {}
-};
-
-MODULE_DEVICE_TABLE(i2c, ad799x_id);
-
-static struct i2c_driver ad799x_driver = {
-       .driver = {
-               .name = "ad799x",
-       },
-       .probe = ad799x_probe,
-       .remove = ad799x_remove,
-       .id_table = ad799x_id,
-};
-module_i2c_driver(ad799x_driver);
-
-MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
-MODULE_DESCRIPTION("Analog Devices AD799x ADC");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/adc/ad799x_ring.c b/drivers/staging/iio/adc/ad799x_ring.c
deleted file mode 100644 (file)
index 0ff6c03..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2010-2012 Michael Hennerich, Analog Devices Inc.
- * Copyright (C) 2008-2010 Jonathan Cameron
- *
- * 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.
- *
- * ad799x_ring.c
- */
-
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/i2c.h>
-#include <linux/bitops.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/buffer.h>
-#include <linux/iio/trigger_consumer.h>
-#include <linux/iio/triggered_buffer.h>
-
-#include "ad799x.h"
-
-/**
- * ad799x_trigger_handler() bh of trigger launched polling to ring buffer
- *
- * Currently there is no option in this driver to disable the saving of
- * timestamps within the ring.
- **/
-
-static irqreturn_t ad799x_trigger_handler(int irq, void *p)
-{
-       struct iio_poll_func *pf = p;
-       struct iio_dev *indio_dev = pf->indio_dev;
-       struct ad799x_state *st = iio_priv(indio_dev);
-       int b_sent;
-       u8 cmd;
-
-       switch (st->id) {
-       case ad7991:
-       case ad7995:
-       case ad7999:
-               cmd = st->config |
-                       (*indio_dev->active_scan_mask << AD799X_CHANNEL_SHIFT);
-               break;
-       case ad7992:
-       case ad7993:
-       case ad7994:
-               cmd = (*indio_dev->active_scan_mask << AD799X_CHANNEL_SHIFT) |
-                       AD7998_CONV_RES_REG;
-               break;
-       case ad7997:
-       case ad7998:
-               cmd = AD7997_8_READ_SEQUENCE | AD7998_CONV_RES_REG;
-               break;
-       default:
-               cmd = 0;
-       }
-
-       b_sent = i2c_smbus_read_i2c_block_data(st->client,
-                       cmd, st->transfer_size, st->rx_buf);
-       if (b_sent < 0)
-               goto out;
-
-       iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf,
-                       iio_get_time_ns());
-out:
-       iio_trigger_notify_done(indio_dev->trig);
-
-       return IRQ_HANDLED;
-}
-
-int ad799x_register_ring_funcs_and_init(struct iio_dev *indio_dev)
-{
-       return iio_triggered_buffer_setup(indio_dev, NULL,
-               &ad799x_trigger_handler, NULL);
-}
-
-void ad799x_ring_cleanup(struct iio_dev *indio_dev)
-{
-       iio_triggered_buffer_cleanup(indio_dev);
-}
index 970d9ed..c5492ba 100644 (file)
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 
-/*
- * SPEAR registers definitions
- */
-
-#define SCAN_RATE_LO(x)                ((x) & 0xFFFF)
-#define SCAN_RATE_HI(x)                (((x) >> 0x10) & 0xFFFF)
-#define CLK_LOW(x)             (((x) & 0xf) << 0)
-#define CLK_HIGH(x)            (((x) & 0xf) << 4)
+/* SPEAR registers definitions */
+#define SPEAR600_ADC_SCAN_RATE_LO(x)   ((x) & 0xFFFF)
+#define SPEAR600_ADC_SCAN_RATE_HI(x)   (((x) >> 0x10) & 0xFFFF)
+#define SPEAR_ADC_CLK_LOW(x)           (((x) & 0xf) << 0)
+#define SPEAR_ADC_CLK_HIGH(x)          (((x) & 0xf) << 4)
 
 /* Bit definitions for SPEAR_ADC_STATUS */
-#define START_CONVERSION       (1 << 0)
-#define CHANNEL_NUM(x)         ((x) << 1)
-#define ADC_ENABLE             (1 << 4)
-#define AVG_SAMPLE(x)          ((x) << 5)
-#define VREF_INTERNAL          (1 << 9)
+#define SPEAR_ADC_STATUS_START_CONVERSION      (1 << 0)
+#define SPEAR_ADC_STATUS_CHANNEL_NUM(x)                ((x) << 1)
+#define SPEAR_ADC_STATUS_ADC_ENABLE            (1 << 4)
+#define SPEAR_ADC_STATUS_AVG_SAMPLE(x)         ((x) << 5)
+#define SPEAR_ADC_STATUS_VREF_INTERNAL         (1 << 9)
 
-#define DATA_MASK              0x03ff
-#define DATA_BITS              10
+#define SPEAR_ADC_DATA_MASK            0x03ff
+#define SPEAR_ADC_DATA_BITS            10
 
-#define MOD_NAME "spear-adc"
+#define SPEAR_ADC_MOD_NAME "spear-adc"
 
-#define ADC_CHANNEL_NUM                8
+#define SPEAR_ADC_CHANNEL_NUM          8
 
-#define CLK_MIN                        2500000
-#define CLK_MAX                        20000000
+#define SPEAR_ADC_CLK_MIN                      2500000
+#define SPEAR_ADC_CLK_MAX                      20000000
 
 struct adc_regs_spear3xx {
        u32 status;
        u32 average;
        u32 scan_rate;
        u32 clk;        /* Not avail for 1340 & 1310 */
-       u32 ch_ctrl[ADC_CHANNEL_NUM];
-       u32 ch_data[ADC_CHANNEL_NUM];
+       u32 ch_ctrl[SPEAR_ADC_CHANNEL_NUM];
+       u32 ch_data[SPEAR_ADC_CHANNEL_NUM];
 };
 
 struct chan_data {
@@ -66,14 +63,14 @@ struct adc_regs_spear6xx {
        u32 status;
        u32 pad[2];
        u32 clk;
-       u32 ch_ctrl[ADC_CHANNEL_NUM];
-       struct chan_data ch_data[ADC_CHANNEL_NUM];
+       u32 ch_ctrl[SPEAR_ADC_CHANNEL_NUM];
+       struct chan_data ch_data[SPEAR_ADC_CHANNEL_NUM];
        u32 scan_rate_lo;
        u32 scan_rate_hi;
        struct chan_data average;
 };
 
-struct spear_adc_info {
+struct spear_adc_state {
        struct device_node *np;
        struct adc_regs_spear3xx __iomem *adc_base_spear3xx;
        struct adc_regs_spear6xx __iomem *adc_base_spear6xx;
@@ -91,100 +88,129 @@ struct spear_adc_info {
  * static inline functions, because of different register offsets
  * on different SoC variants (SPEAr300 vs SPEAr600 etc).
  */
-static void spear_adc_set_status(struct spear_adc_info *info, u32 val)
+static void spear_adc_set_status(struct spear_adc_state *st, u32 val)
 {
-       __raw_writel(val, &info->adc_base_spear6xx->status);
+       __raw_writel(val, &st->adc_base_spear6xx->status);
 }
 
-static void spear_adc_set_clk(struct spear_adc_info *info, u32 val)
+static void spear_adc_set_clk(struct spear_adc_state *st, u32 val)
 {
        u32 clk_high, clk_low, count;
-       u32 apb_clk = clk_get_rate(info->clk);
+       u32 apb_clk = clk_get_rate(st->clk);
 
        count = (apb_clk + val - 1) / val;
        clk_low = count / 2;
        clk_high = count - clk_low;
-       info->current_clk = apb_clk / count;
+       st->current_clk = apb_clk / count;
 
-       __raw_writel(CLK_LOW(clk_low) | CLK_HIGH(clk_high),
-                    &info->adc_base_spear6xx->clk);
+       __raw_writel(SPEAR_ADC_CLK_LOW(clk_low) | SPEAR_ADC_CLK_HIGH(clk_high),
+                    &st->adc_base_spear6xx->clk);
 }
 
-static void spear_adc_set_ctrl(struct spear_adc_info *info, int n,
+static void spear_adc_set_ctrl(struct spear_adc_state *st, int n,
                               u32 val)
 {
-       __raw_writel(val, &info->adc_base_spear6xx->ch_ctrl[n]);
+       __raw_writel(val, &st->adc_base_spear6xx->ch_ctrl[n]);
 }
 
-static u32 spear_adc_get_average(struct spear_adc_info *info)
+static u32 spear_adc_get_average(struct spear_adc_state *st)
 {
-       if (of_device_is_compatible(info->np, "st,spear600-adc")) {
-               return __raw_readl(&info->adc_base_spear6xx->average.msb) &
-                       DATA_MASK;
+       if (of_device_is_compatible(st->np, "st,spear600-adc")) {
+               return __raw_readl(&st->adc_base_spear6xx->average.msb) &
+                       SPEAR_ADC_DATA_MASK;
        } else {
-               return __raw_readl(&info->adc_base_spear3xx->average) &
-                       DATA_MASK;
+               return __raw_readl(&st->adc_base_spear3xx->average) &
+                       SPEAR_ADC_DATA_MASK;
        }
 }
 
-static void spear_adc_set_scanrate(struct spear_adc_info *info, u32 rate)
+static void spear_adc_set_scanrate(struct spear_adc_state *st, u32 rate)
 {
-       if (of_device_is_compatible(info->np, "st,spear600-adc")) {
-               __raw_writel(SCAN_RATE_LO(rate),
-                            &info->adc_base_spear6xx->scan_rate_lo);
-               __raw_writel(SCAN_RATE_HI(rate),
-                            &info->adc_base_spear6xx->scan_rate_hi);
+       if (of_device_is_compatible(st->np, "st,spear600-adc")) {
+               __raw_writel(SPEAR600_ADC_SCAN_RATE_LO(rate),
+                            &st->adc_base_spear6xx->scan_rate_lo);
+               __raw_writel(SPEAR600_ADC_SCAN_RATE_HI(rate),
+                            &st->adc_base_spear6xx->scan_rate_hi);
        } else {
-               __raw_writel(rate, &info->adc_base_spear3xx->scan_rate);
+               __raw_writel(rate, &st->adc_base_spear3xx->scan_rate);
        }
 }
 
-static int spear_read_raw(struct iio_dev *indio_dev,
-                         struct iio_chan_spec const *chan,
-                         int *val,
-                         int *val2,
-                         long mask)
+static int spear_adc_read_raw(struct iio_dev *indio_dev,
+                             struct iio_chan_spec const *chan,
+                             int *val,
+                             int *val2,
+                             long mask)
 {
-       struct spear_adc_info *info = iio_priv(indio_dev);
+       struct spear_adc_state *st = iio_priv(indio_dev);
        u32 status;
 
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
                mutex_lock(&indio_dev->mlock);
 
-               status = CHANNEL_NUM(chan->channel) |
-                       AVG_SAMPLE(info->avg_samples) |
-                       START_CONVERSION | ADC_ENABLE;
-               if (info->vref_external == 0)
-                       status |= VREF_INTERNAL;
+               status = SPEAR_ADC_STATUS_CHANNEL_NUM(chan->channel) |
+                       SPEAR_ADC_STATUS_AVG_SAMPLE(st->avg_samples) |
+                       SPEAR_ADC_STATUS_START_CONVERSION |
+                       SPEAR_ADC_STATUS_ADC_ENABLE;
+               if (st->vref_external == 0)
+                       status |= SPEAR_ADC_STATUS_VREF_INTERNAL;
 
-               spear_adc_set_status(info, status);
-               wait_for_completion(&info->completion); /* set by ISR */
-               *val = info->value;
+               spear_adc_set_status(st, status);
+               wait_for_completion(&st->completion); /* set by ISR */
+               *val = st->value;
 
                mutex_unlock(&indio_dev->mlock);
 
                return IIO_VAL_INT;
 
        case IIO_CHAN_INFO_SCALE:
-               *val = info->vref_external;
-               *val2 = DATA_BITS;
+               *val = st->vref_external;
+               *val2 = SPEAR_ADC_DATA_BITS;
                return IIO_VAL_FRACTIONAL_LOG2;
+       case IIO_CHAN_INFO_SAMP_FREQ:
+               *val = st->current_clk;
+               return IIO_VAL_INT;
        }
 
        return -EINVAL;
 }
 
+static int spear_adc_write_raw(struct iio_dev *indio_dev,
+                              struct iio_chan_spec const *chan,
+                              int val,
+                              int val2,
+                              long mask)
+{
+       struct spear_adc_state *st = iio_priv(indio_dev);
+       int ret = 0;
+
+       if (mask != IIO_CHAN_INFO_SAMP_FREQ)
+               return -EINVAL;
+
+       mutex_lock(&indio_dev->mlock);
+
+       if ((val < SPEAR_ADC_CLK_MIN) ||
+               (val > SPEAR_ADC_CLK_MAX) ||
+               (val2 != 0)) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       spear_adc_set_clk(st, val);
+
+out:
+       mutex_unlock(&indio_dev->mlock);
+       return ret;
+}
+
 #define SPEAR_ADC_CHAN(idx) {                          \
        .type = IIO_VOLTAGE,                            \
        .indexed = 1,                                   \
        .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),\
        .channel = idx,                                 \
-       .scan_type = {                                  \
-               .sign = 'u',                            \
-               .storagebits = 16,                      \
-       },                                              \
 }
 
 static const struct iio_chan_spec spear_adc_iio_channels[] = {
@@ -200,92 +226,34 @@ static const struct iio_chan_spec spear_adc_iio_channels[] = {
 
 static irqreturn_t spear_adc_isr(int irq, void *dev_id)
 {
-       struct spear_adc_info *info = (struct spear_adc_info *)dev_id;
+       struct spear_adc_state *st = (struct spear_adc_state *)dev_id;
 
        /* Read value to clear IRQ */
-       info->value = spear_adc_get_average(info);
-       complete(&info->completion);
+       st->value = spear_adc_get_average(st);
+       complete(&st->completion);
 
        return IRQ_HANDLED;
 }
 
-static int spear_adc_configure(struct spear_adc_info *info)
+static int spear_adc_configure(struct spear_adc_state *st)
 {
        int i;
 
        /* Reset ADC core */
-       spear_adc_set_status(info, 0);
-       __raw_writel(0, &info->adc_base_spear6xx->clk);
+       spear_adc_set_status(st, 0);
+       __raw_writel(0, &st->adc_base_spear6xx->clk);
        for (i = 0; i < 8; i++)
-               spear_adc_set_ctrl(info, i, 0);
-       spear_adc_set_scanrate(info, 0);
+               spear_adc_set_ctrl(st, i, 0);
+       spear_adc_set_scanrate(st, 0);
 
-       spear_adc_set_clk(info, info->sampling_freq);
+       spear_adc_set_clk(st, st->sampling_freq);
 
        return 0;
 }
 
-static ssize_t spear_adc_read_frequency(struct device *dev,
-                                       struct device_attribute *attr,
-                                       char *buf)
-{
-       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-       struct spear_adc_info *info = iio_priv(indio_dev);
-
-       return sprintf(buf, "%d\n", info->current_clk);
-}
-
-static ssize_t spear_adc_write_frequency(struct device *dev,
-                                        struct device_attribute *attr,
-                                        const char *buf,
-                                        size_t len)
-{
-       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-       struct spear_adc_info *info = iio_priv(indio_dev);
-       u32 clk_high, clk_low, count;
-       u32 apb_clk = clk_get_rate(info->clk);
-       unsigned long lval;
-       int ret;
-
-       ret = kstrtoul(buf, 10, &lval);
-       if (ret)
-               return ret;
-
-       mutex_lock(&indio_dev->mlock);
-
-       if ((lval < CLK_MIN) || (lval > CLK_MAX)) {
-               ret = -EINVAL;
-               goto out;
-       }
-
-       count = (apb_clk + lval - 1) / lval;
-       clk_low = count / 2;
-       clk_high = count - clk_low;
-       info->current_clk = apb_clk / count;
-       spear_adc_set_clk(info, lval);
-
-out:
-       mutex_unlock(&indio_dev->mlock);
-
-       return ret ? ret : len;
-}
-
-static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
-                             spear_adc_read_frequency,
-                             spear_adc_write_frequency);
-
-static struct attribute *spear_attributes[] = {
-       &iio_dev_attr_sampling_frequency.dev_attr.attr,
-       NULL
-};
-
-static const struct attribute_group spear_attribute_group = {
-       .attrs = spear_attributes,
-};
-
-static const struct iio_info spear_adc_iio_info = {
-       .read_raw = &spear_read_raw,
-       .attrs = &spear_attribute_group,
+static const struct iio_info spear_adc_info = {
+       .read_raw = &spear_adc_read_raw,
+       .write_raw = &spear_adc_write_raw,
        .driver_module = THIS_MODULE,
 };
 
@@ -293,40 +261,40 @@ static int spear_adc_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
        struct device *dev = &pdev->dev;
-       struct spear_adc_info *info;
-       struct iio_dev *iodev = NULL;
+       struct spear_adc_state *st;
+       struct iio_dev *indio_dev = NULL;
        int ret = -ENODEV;
        int irq;
 
-       iodev = devm_iio_device_alloc(dev, sizeof(struct spear_adc_info));
-       if (!iodev) {
+       indio_dev = devm_iio_device_alloc(dev, sizeof(struct spear_adc_state));
+       if (!indio_dev) {
                dev_err(dev, "failed allocating iio device\n");
                return -ENOMEM;
        }
 
-       info = iio_priv(iodev);
-       info->np = np;
+       st = iio_priv(indio_dev);
+       st->np = np;
 
        /*
         * SPEAr600 has a different register layout than other SPEAr SoC's
         * (e.g. SPEAr3xx). Let's provide two register base addresses
         * to support multi-arch kernels.
         */
-       info->adc_base_spear6xx = of_iomap(np, 0);
-       if (!info->adc_base_spear6xx) {
+       st->adc_base_spear6xx = of_iomap(np, 0);
+       if (!st->adc_base_spear6xx) {
                dev_err(dev, "failed mapping memory\n");
                return -ENOMEM;
        }
-       info->adc_base_spear3xx =
-               (struct adc_regs_spear3xx __iomem *)info->adc_base_spear6xx;
+       st->adc_base_spear3xx =
+               (struct adc_regs_spear3xx __iomem *)st->adc_base_spear6xx;
 
-       info->clk = clk_get(dev, NULL);
-       if (IS_ERR(info->clk)) {
+       st->clk = clk_get(dev, NULL);
+       if (IS_ERR(st->clk)) {
                dev_err(dev, "failed getting clock\n");
                goto errout1;
        }
 
-       ret = clk_prepare_enable(info->clk);
+       ret = clk_prepare_enable(st->clk);
        if (ret) {
                dev_err(dev, "failed enabling clock\n");
                goto errout2;
@@ -339,14 +307,15 @@ static int spear_adc_probe(struct platform_device *pdev)
                goto errout3;
        }
 
-       ret = devm_request_irq(dev, irq, spear_adc_isr, 0, MOD_NAME, info);
+       ret = devm_request_irq(dev, irq, spear_adc_isr, 0, SPEAR_ADC_MOD_NAME,
+                              st);
        if (ret < 0) {
                dev_err(dev, "failed requesting interrupt\n");
                goto errout3;
        }
 
        if (of_property_read_u32(np, "sampling-frequency",
-                                &info->sampling_freq)) {
+                                &st->sampling_freq)) {
                dev_err(dev, "sampling-frequency missing in DT\n");
                ret = -EINVAL;
                goto errout3;
@@ -356,28 +325,28 @@ static int spear_adc_probe(struct platform_device *pdev)
         * Optional avg_samples defaults to 0, resulting in single data
         * conversion
         */
-       of_property_read_u32(np, "average-samples", &info->avg_samples);
+       of_property_read_u32(np, "average-samples", &st->avg_samples);
 
        /*
         * Optional vref_external defaults to 0, resulting in internal vref
         * selection
         */
-       of_property_read_u32(np, "vref-external", &info->vref_external);
+       of_property_read_u32(np, "vref-external", &st->vref_external);
 
-       spear_adc_configure(info);
+       spear_adc_configure(st);
 
-       platform_set_drvdata(pdev, iodev);
+       platform_set_drvdata(pdev, indio_dev);
 
-       init_completion(&info->completion);
+       init_completion(&st->completion);
 
-       iodev->name = MOD_NAME;
-       iodev->dev.parent = dev;
-       iodev->info = &spear_adc_iio_info;
-       iodev->modes = INDIO_DIRECT_MODE;
-       iodev->channels = spear_adc_iio_channels;
-       iodev->num_channels = ARRAY_SIZE(spear_adc_iio_channels);
+       indio_dev->name = SPEAR_ADC_MOD_NAME;
+       indio_dev->dev.parent = dev;
+       indio_dev->info = &spear_adc_info;
+       indio_dev->modes = INDIO_DIRECT_MODE;
+       indio_dev->channels = spear_adc_iio_channels;
+       indio_dev->num_channels = ARRAY_SIZE(spear_adc_iio_channels);
 
-       ret = iio_device_register(iodev);
+       ret = iio_device_register(indio_dev);
        if (ret)
                goto errout3;
 
@@ -386,23 +355,23 @@ static int spear_adc_probe(struct platform_device *pdev)
        return 0;
 
 errout3:
-       clk_disable_unprepare(info->clk);
+       clk_disable_unprepare(st->clk);
 errout2:
-       clk_put(info->clk);
+       clk_put(st->clk);
 errout1:
-       iounmap(info->adc_base_spear6xx);
+       iounmap(st->adc_base_spear6xx);
        return ret;
 }
 
 static int spear_adc_remove(struct platform_device *pdev)
 {
-       struct iio_dev *iodev = platform_get_drvdata(pdev);
-       struct spear_adc_info *info = iio_priv(iodev);
+       struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+       struct spear_adc_state *st = iio_priv(indio_dev);
 
-       iio_device_unregister(iodev);
-       clk_disable_unprepare(info->clk);
-       clk_put(info->clk);
-       iounmap(info->adc_base_spear6xx);
+       iio_device_unregister(indio_dev);
+       clk_disable_unprepare(st->clk);
+       clk_put(st->clk);
+       iounmap(st->adc_base_spear6xx);
 
        return 0;
 }
@@ -419,7 +388,7 @@ static struct platform_driver spear_adc_driver = {
        .probe          = spear_adc_probe,
        .remove         = spear_adc_remove,
        .driver         = {
-               .name   = MOD_NAME,
+               .name   = SPEAR_ADC_MOD_NAME,
                .owner  = THIS_MODULE,
                .of_match_table = of_match_ptr(spear_adc_dt_ids),
        },
index 9f0ebb3..5f1770e 100644 (file)
 #define ID_ADT75XX             0x10
 
 /*
- * struct adt7316_chip_info - chip specifc information
+ * struct adt7316_chip_info - chip specific information
  */
 
 struct adt7316_chip_info {
@@ -208,7 +208,7 @@ struct adt7316_chip_info {
        (ADT7316_TEMP_INT_MASK)
 
 /*
- * struct adt7316_chip_info - chip specifc information
+ * struct adt7316_chip_info - chip specific information
  */
 
 struct adt7316_limit_regs {
index f2c309d..87110d9 100644 (file)
@@ -78,7 +78,7 @@ enum {
 };
 
 /*
- * struct ad7152_chip_info - chip specifc information
+ * struct ad7152_chip_info - chip specific information
  */
 
 struct ad7152_chip_info {
index cbb1588..e6e9eaa 100644 (file)
@@ -91,7 +91,7 @@
 #define AD7746_CAPDAC_DACP(x)          ((x) & 0x7F)
 
 /*
- * struct ad7746_chip_info - chip specifc information
+ * struct ad7746_chip_info - chip specific information
  */
 
 struct ad7746_chip_info {
index 3c005eb..96f51f0 100644 (file)
@@ -269,6 +269,10 @@ int st_sensors_set_enable(struct iio_dev *indio_dev, bool enable);
 
 int st_sensors_set_axis_enable(struct iio_dev *indio_dev, u8 axis_enable);
 
+void st_sensors_power_enable(struct iio_dev *indio_dev);
+
+void st_sensors_power_disable(struct iio_dev *indio_dev);
+
 int st_sensors_set_odr(struct iio_dev *indio_dev, unsigned int odr);
 
 int st_sensors_set_dataready_irq(struct iio_dev *indio_dev, bool enable);
index 2752b1f..651f9a0 100644 (file)
@@ -122,6 +122,19 @@ struct iio_channel
 int iio_read_channel_raw(struct iio_channel *chan,
                         int *val);
 
+/**
+ * iio_read_channel_average_raw() - read from a given channel
+ * @chan:              The channel being queried.
+ * @val:               Value read back.
+ *
+ * Note raw reads from iio channels are in adc counts and hence
+ * scale will need to be applied if standard units required.
+ *
+ * In opposit to the normal iio_read_channel_raw this function
+ * returns the average of multiple reads.
+ */
+int iio_read_channel_average_raw(struct iio_channel *chan, int *val);
+
 /**
  * iio_read_channel_processed() - read processed value from a given channel
  * @chan:              The channel being queried.