staging:iio:ad7291: Move out of staging
authorLars-Peter Clausen <lars@metafoo.de>
Mon, 30 Jun 2014 08:50:00 +0000 (09:50 +0100)
committerJonathan Cameron <jic23@kernel.org>
Tue, 8 Jul 2014 20:17:30 +0000 (21:17 +0100)
The ad7291 driver is in a reasonable shape. It does not use non-standard API/ABI
and there are no major style issues with the driver. So this patch moves it out
of staging.

There is one small warning from checkpatch which is also fixed in this patch.
The patch also sorts the #include directives in alphabetical order.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
drivers/iio/adc/Kconfig
drivers/iio/adc/Makefile
drivers/iio/adc/ad7291.c [new file with mode: 0644]
drivers/staging/iio/adc/Kconfig
drivers/staging/iio/adc/Makefile
drivers/staging/iio/adc/ad7291.c [deleted file]
drivers/staging/iio/adc/ad7291.h [deleted file]
include/linux/platform_data/ad7291.h [new file with mode: 0644]

index 20a7073f1dd681a9387e378fa4e00c13636b0872..11b048a59fdef60aacdb2131edce83e1f149124c 100644 (file)
@@ -20,6 +20,16 @@ config AD7266
          Say yes here to build support for Analog Devices AD7265 and AD7266
          ADCs.
 
+config AD7291
+       tristate "Analog Devices AD7291 ADC driver"
+       depends on I2C
+       help
+         Say yes here to build support for Analog Devices AD7291
+         8 Channel ADC with temperature sensor.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ad7291.
+
 config AD7298
        tristate "Analog Devices AD7298 ADC driver"
        depends on SPI
index 38cf5c3f5631dc6b907a1844465dcf34f14efd52..ad81b512aa3dee82bc85a50c933a83d3fc49b5ed 100644 (file)
@@ -5,6 +5,7 @@
 # When adding new entries keep the list in alphabetical order
 obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
 obj-$(CONFIG_AD7266) += ad7266.o
+obj-$(CONFIG_AD7291) += ad7291.o
 obj-$(CONFIG_AD7298) += ad7298.o
 obj-$(CONFIG_AD7923) += ad7923.o
 obj-$(CONFIG_AD7476) += ad7476.o
diff --git a/drivers/iio/adc/ad7291.c b/drivers/iio/adc/ad7291.c
new file mode 100644 (file)
index 0000000..4ed78b9
--- /dev/null
@@ -0,0 +1,585 @@
+/*
+ * AD7291 8-Channel, I2C, 12-Bit SAR ADC with Temperature Sensor
+ *
+ * Copyright 2010-2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/events.h>
+
+#include <linux/platform_data/ad7291.h>
+
+/*
+ * Simplified handling
+ *
+ * If no events enabled - single polled channel read
+ * If event enabled direct reads disable unless channel
+ * is in the read mask.
+ *
+ * The noise-delayed bit as per datasheet suggestion is always enabled.
+ */
+
+/*
+ * AD7291 registers definition
+ */
+#define AD7291_COMMAND                 0x00
+#define AD7291_VOLTAGE                 0x01
+#define AD7291_T_SENSE                 0x02
+#define AD7291_T_AVERAGE               0x03
+#define AD7291_DATA_HIGH(x)            ((x) * 3 + 0x4)
+#define AD7291_DATA_LOW(x)             ((x) * 3 + 0x5)
+#define AD7291_HYST(x)                 ((x) * 3 + 0x6)
+#define AD7291_VOLTAGE_ALERT_STATUS    0x1F
+#define AD7291_T_ALERT_STATUS          0x20
+
+#define AD7291_BITS                    12
+#define AD7291_VOLTAGE_LIMIT_COUNT     8
+
+
+/*
+ * AD7291 command
+ */
+#define AD7291_AUTOCYCLE               BIT(0)
+#define AD7291_RESET                   BIT(1)
+#define AD7291_ALERT_CLEAR             BIT(2)
+#define AD7291_ALERT_POLARITY          BIT(3)
+#define AD7291_EXT_REF                 BIT(4)
+#define AD7291_NOISE_DELAY             BIT(5)
+#define AD7291_T_SENSE_MASK            BIT(7)
+#define AD7291_VOLTAGE_MASK            GENMASK(15, 8)
+#define AD7291_VOLTAGE_OFFSET          8
+
+/*
+ * AD7291 value masks
+ */
+#define AD7291_VALUE_MASK              GENMASK(11, 0)
+
+/*
+ * AD7291 alert register bits
+ */
+#define AD7291_T_LOW                   BIT(0)
+#define AD7291_T_HIGH                  BIT(1)
+#define AD7291_T_AVG_LOW               BIT(2)
+#define AD7291_T_AVG_HIGH              BIT(3)
+#define AD7291_V_LOW(x)                        BIT((x) * 2)
+#define AD7291_V_HIGH(x)               BIT((x) * 2 + 1)
+
+
+struct ad7291_chip_info {
+       struct i2c_client       *client;
+       struct regulator        *reg;
+       u16                     command;
+       u16                     c_mask; /* Active voltage channels for events */
+       struct mutex            state_lock;
+};
+
+static int ad7291_i2c_read(struct ad7291_chip_info *chip, u8 reg, u16 *data)
+{
+       struct i2c_client *client = chip->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 = ret;
+
+       return 0;
+}
+
+static int ad7291_i2c_write(struct ad7291_chip_info *chip, u8 reg, u16 data)
+{
+       return i2c_smbus_write_word_swapped(chip->client, reg, data);
+}
+
+static irqreturn_t ad7291_event_handler(int irq, void *private)
+{
+       struct iio_dev *indio_dev = private;
+       struct ad7291_chip_info *chip = iio_priv(private);
+       u16 t_status, v_status;
+       u16 command;
+       int i;
+       s64 timestamp = iio_get_time_ns();
+
+       if (ad7291_i2c_read(chip, AD7291_T_ALERT_STATUS, &t_status))
+               return IRQ_HANDLED;
+
+       if (ad7291_i2c_read(chip, AD7291_VOLTAGE_ALERT_STATUS, &v_status))
+               return IRQ_HANDLED;
+
+       if (!(t_status || v_status))
+               return IRQ_HANDLED;
+
+       command = chip->command | AD7291_ALERT_CLEAR;
+       ad7291_i2c_write(chip, AD7291_COMMAND, command);
+
+       command = chip->command & ~AD7291_ALERT_CLEAR;
+       ad7291_i2c_write(chip, AD7291_COMMAND, command);
+
+       /* For now treat t_sense and t_sense_average the same */
+       if ((t_status & AD7291_T_LOW) || (t_status & AD7291_T_AVG_LOW))
+               iio_push_event(indio_dev,
+                              IIO_UNMOD_EVENT_CODE(IIO_TEMP,
+                                                   0,
+                                                   IIO_EV_TYPE_THRESH,
+                                                   IIO_EV_DIR_FALLING),
+                              timestamp);
+       if ((t_status & AD7291_T_HIGH) || (t_status & AD7291_T_AVG_HIGH))
+               iio_push_event(indio_dev,
+                              IIO_UNMOD_EVENT_CODE(IIO_TEMP,
+                                                   0,
+                                                   IIO_EV_TYPE_THRESH,
+                                                   IIO_EV_DIR_RISING),
+                              timestamp);
+
+       for (i = 0; i < AD7291_VOLTAGE_LIMIT_COUNT; i++) {
+               if (v_status & AD7291_V_LOW(i))
+                       iio_push_event(indio_dev,
+                                      IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE,
+                                                           i,
+                                                           IIO_EV_TYPE_THRESH,
+                                                           IIO_EV_DIR_FALLING),
+                                      timestamp);
+               if (v_status & AD7291_V_HIGH(i))
+                       iio_push_event(indio_dev,
+                                      IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE,
+                                                           i,
+                                                           IIO_EV_TYPE_THRESH,
+                                                           IIO_EV_DIR_RISING),
+                                      timestamp);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static unsigned int ad7291_threshold_reg(const struct iio_chan_spec *chan,
+                                        enum iio_event_direction dir,
+                                        enum iio_event_info info)
+{
+       unsigned int offset;
+
+       switch (chan->type) {
+       case IIO_VOLTAGE:
+               offset = chan->channel;
+               break;
+       case IIO_TEMP:
+               offset = AD7291_VOLTAGE_OFFSET;
+               break;
+       default:
+           return 0;
+       }
+
+       switch (info) {
+       case IIO_EV_INFO_VALUE:
+               if (dir == IIO_EV_DIR_FALLING)
+                       return AD7291_DATA_HIGH(offset);
+               else
+                       return AD7291_DATA_LOW(offset);
+       case IIO_EV_INFO_HYSTERESIS:
+               return AD7291_HYST(offset);
+       default:
+               break;
+       }
+       return 0;
+}
+
+static int ad7291_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)
+{
+       struct ad7291_chip_info *chip = iio_priv(indio_dev);
+       int ret;
+       u16 uval;
+
+       ret = ad7291_i2c_read(chip, ad7291_threshold_reg(chan, dir, info),
+                             &uval);
+       if (ret < 0)
+               return ret;
+
+       if (info == IIO_EV_INFO_HYSTERESIS || chan->type == IIO_VOLTAGE)
+               *val = uval & AD7291_VALUE_MASK;
+
+       else
+               *val = sign_extend32(uval, 11);
+
+       return IIO_VAL_INT;
+}
+
+static int ad7291_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)
+{
+       struct ad7291_chip_info *chip = iio_priv(indio_dev);
+
+       if (info == IIO_EV_INFO_HYSTERESIS || chan->type == IIO_VOLTAGE) {
+               if (val > AD7291_VALUE_MASK || val < 0)
+                       return -EINVAL;
+       } else {
+               if (val > 2047 || val < -2048)
+                       return -EINVAL;
+       }
+
+       return ad7291_i2c_write(chip, ad7291_threshold_reg(chan, dir, info),
+                               val);
+}
+
+static int ad7291_read_event_config(struct iio_dev *indio_dev,
+                                   const struct iio_chan_spec *chan,
+                                   enum iio_event_type type,
+                                   enum iio_event_direction dir)
+{
+       struct ad7291_chip_info *chip = iio_priv(indio_dev);
+       /*
+        * To be enabled the channel must simply be on. If any are enabled
+        * we are in continuous sampling mode
+        */
+
+       switch (chan->type) {
+       case IIO_VOLTAGE:
+               return !!(chip->c_mask & BIT(15 - chan->channel));
+       case IIO_TEMP:
+               /* always on */
+               return 1;
+       default:
+               return -EINVAL;
+       }
+
+}
+
+static int ad7291_write_event_config(struct iio_dev *indio_dev,
+                                    const struct iio_chan_spec *chan,
+                                    enum iio_event_type type,
+                                    enum iio_event_direction dir,
+                                    int state)
+{
+       int ret = 0;
+       struct ad7291_chip_info *chip = iio_priv(indio_dev);
+       unsigned int mask;
+       u16 regval;
+
+       mutex_lock(&chip->state_lock);
+       regval = chip->command;
+       /*
+        * To be enabled the channel must simply be on. If any are enabled
+        * use continuous sampling mode.
+        * Possible to disable temp as well but that makes single read tricky.
+        */
+
+       mask = BIT(15 - chan->channel);
+
+       switch (chan->type) {
+       case IIO_VOLTAGE:
+               if ((!state) && (chip->c_mask & mask))
+                       chip->c_mask &= ~mask;
+               else if (state && (!(chip->c_mask & mask)))
+                       chip->c_mask |= mask;
+               else
+                       break;
+
+               regval &= ~AD7291_AUTOCYCLE;
+               regval |= chip->c_mask;
+               if (chip->c_mask) /* Enable autocycle? */
+                       regval |= AD7291_AUTOCYCLE;
+
+               ret = ad7291_i2c_write(chip, AD7291_COMMAND, regval);
+               if (ret < 0)
+                       goto error_ret;
+
+               chip->command = regval;
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+error_ret:
+       mutex_unlock(&chip->state_lock);
+       return ret;
+}
+
+static int ad7291_read_raw(struct iio_dev *indio_dev,
+                          struct iio_chan_spec const *chan,
+                          int *val,
+                          int *val2,
+                          long mask)
+{
+       int ret;
+       struct ad7291_chip_info *chip = iio_priv(indio_dev);
+       u16 regval;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+               switch (chan->type) {
+               case IIO_VOLTAGE:
+                       mutex_lock(&chip->state_lock);
+                       /* If in autocycle mode drop through */
+                       if (chip->command & AD7291_AUTOCYCLE) {
+                               mutex_unlock(&chip->state_lock);
+                               return -EBUSY;
+                       }
+                       /* Enable this channel alone */
+                       regval = chip->command & (~AD7291_VOLTAGE_MASK);
+                       regval |= BIT(15 - chan->channel);
+                       ret = ad7291_i2c_write(chip, AD7291_COMMAND, regval);
+                       if (ret < 0) {
+                               mutex_unlock(&chip->state_lock);
+                               return ret;
+                       }
+                       /* Read voltage */
+                       ret = i2c_smbus_read_word_swapped(chip->client,
+                                                         AD7291_VOLTAGE);
+                       if (ret < 0) {
+                               mutex_unlock(&chip->state_lock);
+                               return ret;
+                       }
+                       *val = ret & AD7291_VALUE_MASK;
+                       mutex_unlock(&chip->state_lock);
+                       return IIO_VAL_INT;
+               case IIO_TEMP:
+                       /* Assumes tsense bit of command register always set */
+                       ret = i2c_smbus_read_word_swapped(chip->client,
+                                                         AD7291_T_SENSE);
+                       if (ret < 0)
+                               return ret;
+                       *val = sign_extend32(ret, 11);
+                       return IIO_VAL_INT;
+               default:
+                       return -EINVAL;
+               }
+       case IIO_CHAN_INFO_AVERAGE_RAW:
+               ret = i2c_smbus_read_word_swapped(chip->client,
+                                                 AD7291_T_AVERAGE);
+                       if (ret < 0)
+                               return ret;
+                       *val = sign_extend32(ret, 11);
+                       return IIO_VAL_INT;
+       case IIO_CHAN_INFO_SCALE:
+               switch (chan->type) {
+               case IIO_VOLTAGE:
+                       if (chip->reg) {
+                               int vref;
+
+                               vref = regulator_get_voltage(chip->reg);
+                               if (vref < 0)
+                                       return vref;
+                               *val = vref / 1000;
+                       } else {
+                               *val = 2500;
+                       }
+                       *val2 = AD7291_BITS;
+                       return IIO_VAL_FRACTIONAL_LOG2;
+               case IIO_TEMP:
+                       /*
+                        * One LSB of the ADC corresponds to 0.25 deg C.
+                        * The temperature reading is in 12-bit twos
+                        * complement format
+                        */
+                       *val = 250;
+                       return IIO_VAL_INT;
+               default:
+                       return -EINVAL;
+               }
+       default:
+               return -EINVAL;
+       }
+}
+
+static const struct iio_event_spec ad7291_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 AD7291_VOLTAGE_CHAN(_chan)                                     \
+{                                                                      \
+       .type = IIO_VOLTAGE,                                            \
+       .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),                   \
+       .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),           \
+       .indexed = 1,                                                   \
+       .channel = _chan,                                               \
+       .event_spec = ad7291_events,                                    \
+       .num_event_specs = ARRAY_SIZE(ad7291_events),                   \
+}
+
+static const struct iio_chan_spec ad7291_channels[] = {
+       AD7291_VOLTAGE_CHAN(0),
+       AD7291_VOLTAGE_CHAN(1),
+       AD7291_VOLTAGE_CHAN(2),
+       AD7291_VOLTAGE_CHAN(3),
+       AD7291_VOLTAGE_CHAN(4),
+       AD7291_VOLTAGE_CHAN(5),
+       AD7291_VOLTAGE_CHAN(6),
+       AD7291_VOLTAGE_CHAN(7),
+       {
+               .type = IIO_TEMP,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+                               BIT(IIO_CHAN_INFO_AVERAGE_RAW) |
+                               BIT(IIO_CHAN_INFO_SCALE),
+               .indexed = 1,
+               .channel = 0,
+               .event_spec = ad7291_events,
+               .num_event_specs = ARRAY_SIZE(ad7291_events),
+       }
+};
+
+static const struct iio_info ad7291_info = {
+       .read_raw = &ad7291_read_raw,
+       .read_event_config = &ad7291_read_event_config,
+       .write_event_config = &ad7291_write_event_config,
+       .read_event_value = &ad7291_read_event_value,
+       .write_event_value = &ad7291_write_event_value,
+       .driver_module = THIS_MODULE,
+};
+
+static int ad7291_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
+{
+       struct ad7291_platform_data *pdata = client->dev.platform_data;
+       struct ad7291_chip_info *chip;
+       struct iio_dev *indio_dev;
+       int ret = 0;
+
+       indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
+       if (!indio_dev)
+               return -ENOMEM;
+       chip = iio_priv(indio_dev);
+
+       if (pdata && pdata->use_external_ref) {
+               chip->reg = devm_regulator_get(&client->dev, "vref");
+               if (IS_ERR(chip->reg))
+                       return ret;
+
+               ret = regulator_enable(chip->reg);
+               if (ret)
+                       return ret;
+       }
+
+       mutex_init(&chip->state_lock);
+       /* this is only used for device removal purposes */
+       i2c_set_clientdata(client, indio_dev);
+
+       chip->client = client;
+
+       chip->command = AD7291_NOISE_DELAY |
+                       AD7291_T_SENSE_MASK | /* Tsense always enabled */
+                       AD7291_ALERT_POLARITY; /* set irq polarity low level */
+
+       if (pdata && pdata->use_external_ref)
+               chip->command |= AD7291_EXT_REF;
+
+       indio_dev->name = id->name;
+       indio_dev->channels = ad7291_channels;
+       indio_dev->num_channels = ARRAY_SIZE(ad7291_channels);
+
+       indio_dev->dev.parent = &client->dev;
+       indio_dev->info = &ad7291_info;
+       indio_dev->modes = INDIO_DIRECT_MODE;
+
+       ret = ad7291_i2c_write(chip, AD7291_COMMAND, AD7291_RESET);
+       if (ret) {
+               ret = -EIO;
+               goto error_disable_reg;
+       }
+
+       ret = ad7291_i2c_write(chip, AD7291_COMMAND, chip->command);
+       if (ret) {
+               ret = -EIO;
+               goto error_disable_reg;
+       }
+
+       if (client->irq > 0) {
+               ret = request_threaded_irq(client->irq,
+                                          NULL,
+                                          &ad7291_event_handler,
+                                          IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+                                          id->name,
+                                          indio_dev);
+               if (ret)
+                       goto error_disable_reg;
+       }
+
+       ret = iio_device_register(indio_dev);
+       if (ret)
+               goto error_unreg_irq;
+
+       return 0;
+
+error_unreg_irq:
+       if (client->irq)
+               free_irq(client->irq, indio_dev);
+error_disable_reg:
+       if (chip->reg)
+               regulator_disable(chip->reg);
+
+       return ret;
+}
+
+static int ad7291_remove(struct i2c_client *client)
+{
+       struct iio_dev *indio_dev = i2c_get_clientdata(client);
+       struct ad7291_chip_info *chip = iio_priv(indio_dev);
+
+       iio_device_unregister(indio_dev);
+
+       if (client->irq)
+               free_irq(client->irq, indio_dev);
+
+       if (chip->reg)
+               regulator_disable(chip->reg);
+
+       return 0;
+}
+
+static const struct i2c_device_id ad7291_id[] = {
+       { "ad7291", 0 },
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, ad7291_id);
+
+static struct i2c_driver ad7291_driver = {
+       .driver = {
+               .name = KBUILD_MODNAME,
+       },
+       .probe = ad7291_probe,
+       .remove = ad7291_remove,
+       .id_table = ad7291_id,
+};
+module_i2c_driver(ad7291_driver);
+
+MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
+MODULE_DESCRIPTION("Analog Devices AD7291 ADC driver");
+MODULE_LICENSE("GPL v2");
index b87e382ad76898c5bdc6e01d34b8a41d7759196e..75d2d1bf93d12b9b4e93b8cc4433d488a02f47ac 100644 (file)
@@ -3,13 +3,6 @@
 #
 menu "Analog to digital converters"
 
-config AD7291
-       tristate "Analog Devices AD7291 ADC driver"
-       depends on I2C
-       help
-         Say yes here to build support for Analog Devices AD7291
-         8 Channel ADC with temperature sensor.
-
 config AD7606
        tristate "Analog Devices AD7606 ADC driver"
        depends on GPIOLIB
index afdcd1ff08ff1a775c9254d5d2aacaf4c162e263..1c4277dbd31859292b2e07c1dda496c6fe79be72 100644 (file)
@@ -8,7 +8,6 @@ ad7606-$(CONFIG_AD7606_IFACE_PARALLEL) += ad7606_par.o
 ad7606-$(CONFIG_AD7606_IFACE_SPI) += ad7606_spi.o
 obj-$(CONFIG_AD7606) += ad7606.o
 
-obj-$(CONFIG_AD7291) += ad7291.o
 obj-$(CONFIG_AD7780) += ad7780.o
 obj-$(CONFIG_AD7816) += ad7816.o
 obj-$(CONFIG_AD7192) += ad7192.o
diff --git a/drivers/staging/iio/adc/ad7291.c b/drivers/staging/iio/adc/ad7291.c
deleted file mode 100644 (file)
index 9139958..0000000
+++ /dev/null
@@ -1,584 +0,0 @@
-/*
- * AD7291 8-Channel, I2C, 12-Bit SAR ADC with Temperature Sensor
- *
- * Copyright 2010-2011 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/sysfs.h>
-#include <linux/i2c.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/regulator/consumer.h>
-#include <linux/err.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
-#include <linux/iio/events.h>
-
-#include "ad7291.h"
-
-/*
- * Simplified handling
- *
- * If no events enabled - single polled channel read
- * If event enabled direct reads disable unless channel
- * is in the read mask.
- *
- * The noise-delayed bit as per datasheet suggestion is always enabled.
- */
-
-/*
- * AD7291 registers definition
- */
-#define AD7291_COMMAND                 0x00
-#define AD7291_VOLTAGE                 0x01
-#define AD7291_T_SENSE                 0x02
-#define AD7291_T_AVERAGE               0x03
-#define AD7291_DATA_HIGH(x)            ((x) * 3 + 0x4)
-#define AD7291_DATA_LOW(x)             ((x) * 3 + 0x5)
-#define AD7291_HYST(x)                 ((x) * 3 + 0x6)
-#define AD7291_VOLTAGE_ALERT_STATUS    0x1F
-#define AD7291_T_ALERT_STATUS          0x20
-
-#define AD7291_BITS                    12
-#define AD7291_VOLTAGE_LIMIT_COUNT     8
-
-
-/*
- * AD7291 command
- */
-#define AD7291_AUTOCYCLE               BIT(0)
-#define AD7291_RESET                   BIT(1)
-#define AD7291_ALERT_CLEAR             BIT(2)
-#define AD7291_ALERT_POLARITY          BIT(3)
-#define AD7291_EXT_REF                 BIT(4)
-#define AD7291_NOISE_DELAY             BIT(5)
-#define AD7291_T_SENSE_MASK            BIT(7)
-#define AD7291_VOLTAGE_MASK            GENMASK(15, 8)
-#define AD7291_VOLTAGE_OFFSET          8
-
-/*
- * AD7291 value masks
- */
-#define AD7291_VALUE_MASK              GENMASK(11, 0)
-
-/*
- * AD7291 alert register bits
- */
-#define AD7291_T_LOW                   BIT(0)
-#define AD7291_T_HIGH                  BIT(1)
-#define AD7291_T_AVG_LOW               BIT(2)
-#define AD7291_T_AVG_HIGH              BIT(3)
-#define AD7291_V_LOW(x)                        BIT((x) * 2)
-#define AD7291_V_HIGH(x)               BIT((x) * 2 + 1)
-
-
-struct ad7291_chip_info {
-       struct i2c_client       *client;
-       struct regulator        *reg;
-       u16                     command;
-       u16                     c_mask; /* Active voltage channels for events */
-       struct mutex            state_lock;
-};
-
-static int ad7291_i2c_read(struct ad7291_chip_info *chip, u8 reg, u16 *data)
-{
-       struct i2c_client *client = chip->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 = ret;
-
-       return 0;
-}
-
-static int ad7291_i2c_write(struct ad7291_chip_info *chip, u8 reg, u16 data)
-{
-       return i2c_smbus_write_word_swapped(chip->client, reg, data);
-}
-
-static irqreturn_t ad7291_event_handler(int irq, void *private)
-{
-       struct iio_dev *indio_dev = private;
-       struct ad7291_chip_info *chip = iio_priv(private);
-       u16 t_status, v_status;
-       u16 command;
-       int i;
-       s64 timestamp = iio_get_time_ns();
-
-       if (ad7291_i2c_read(chip, AD7291_T_ALERT_STATUS, &t_status))
-               return IRQ_HANDLED;
-
-       if (ad7291_i2c_read(chip, AD7291_VOLTAGE_ALERT_STATUS, &v_status))
-               return IRQ_HANDLED;
-
-       if (!(t_status || v_status))
-               return IRQ_HANDLED;
-
-       command = chip->command | AD7291_ALERT_CLEAR;
-       ad7291_i2c_write(chip, AD7291_COMMAND, command);
-
-       command = chip->command & ~AD7291_ALERT_CLEAR;
-       ad7291_i2c_write(chip, AD7291_COMMAND, command);
-
-       /* For now treat t_sense and t_sense_average the same */
-       if ((t_status & AD7291_T_LOW) || (t_status & AD7291_T_AVG_LOW))
-               iio_push_event(indio_dev,
-                              IIO_UNMOD_EVENT_CODE(IIO_TEMP,
-                                                   0,
-                                                   IIO_EV_TYPE_THRESH,
-                                                   IIO_EV_DIR_FALLING),
-                              timestamp);
-       if ((t_status & AD7291_T_HIGH) || (t_status & AD7291_T_AVG_HIGH))
-               iio_push_event(indio_dev,
-                              IIO_UNMOD_EVENT_CODE(IIO_TEMP,
-                                                   0,
-                                                   IIO_EV_TYPE_THRESH,
-                                                   IIO_EV_DIR_RISING),
-                              timestamp);
-
-       for (i = 0; i < AD7291_VOLTAGE_LIMIT_COUNT; i++) {
-               if (v_status & AD7291_V_LOW(i))
-                       iio_push_event(indio_dev,
-                                      IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE,
-                                                           i,
-                                                           IIO_EV_TYPE_THRESH,
-                                                           IIO_EV_DIR_FALLING),
-                                      timestamp);
-               if (v_status & AD7291_V_HIGH(i))
-                       iio_push_event(indio_dev,
-                                      IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE,
-                                                           i,
-                                                           IIO_EV_TYPE_THRESH,
-                                                           IIO_EV_DIR_RISING),
-                                      timestamp);
-       }
-
-       return IRQ_HANDLED;
-}
-
-static unsigned int ad7291_threshold_reg(const struct iio_chan_spec *chan,
-                                        enum iio_event_direction dir,
-                                        enum iio_event_info info)
-{
-       unsigned int offset;
-
-       switch (chan->type) {
-       case IIO_VOLTAGE:
-               offset = chan->channel;
-               break;
-       case IIO_TEMP:
-               offset = AD7291_VOLTAGE_OFFSET;
-               break;
-       default:
-           return 0;
-       }
-
-       switch (info) {
-       case IIO_EV_INFO_VALUE:
-               if (dir == IIO_EV_DIR_FALLING)
-                       return AD7291_DATA_HIGH(offset);
-               else
-                       return AD7291_DATA_LOW(offset);
-       case IIO_EV_INFO_HYSTERESIS:
-               return AD7291_HYST(offset);
-       default:
-               break;
-       }
-       return 0;
-}
-
-static int ad7291_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)
-{
-       struct ad7291_chip_info *chip = iio_priv(indio_dev);
-       int ret;
-       u16 uval;
-
-       ret = ad7291_i2c_read(chip, ad7291_threshold_reg(chan, dir, info),
-                             &uval);
-       if (ret < 0)
-               return ret;
-
-       if (info == IIO_EV_INFO_HYSTERESIS || chan->type == IIO_VOLTAGE)
-               *val = uval & AD7291_VALUE_MASK;
-
-       else
-               *val = sign_extend32(uval, 11);
-
-       return IIO_VAL_INT;
-}
-
-static int ad7291_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)
-{
-       struct ad7291_chip_info *chip = iio_priv(indio_dev);
-
-       if (info == IIO_EV_INFO_HYSTERESIS || chan->type == IIO_VOLTAGE) {
-               if (val > AD7291_VALUE_MASK || val < 0)
-                       return -EINVAL;
-       } else {
-               if (val > 2047 || val < -2048)
-                       return -EINVAL;
-       }
-
-       return ad7291_i2c_write(chip, ad7291_threshold_reg(chan, dir, info),
-                               val);
-}
-
-static int ad7291_read_event_config(struct iio_dev *indio_dev,
-                                   const struct iio_chan_spec *chan,
-                                   enum iio_event_type type,
-                                   enum iio_event_direction dir)
-{
-       struct ad7291_chip_info *chip = iio_priv(indio_dev);
-       /*
-        * To be enabled the channel must simply be on. If any are enabled
-        * we are in continuous sampling mode
-        */
-
-       switch (chan->type) {
-       case IIO_VOLTAGE:
-               return !!(chip->c_mask & BIT(15 - chan->channel));
-       case IIO_TEMP:
-               /* always on */
-               return 1;
-       default:
-               return -EINVAL;
-       }
-
-}
-
-static int ad7291_write_event_config(struct iio_dev *indio_dev,
-                                    const struct iio_chan_spec *chan,
-                                    enum iio_event_type type,
-                                    enum iio_event_direction dir,
-                                    int state)
-{
-       int ret = 0;
-       struct ad7291_chip_info *chip = iio_priv(indio_dev);
-       unsigned int mask;
-       u16 regval;
-
-       mutex_lock(&chip->state_lock);
-       regval = chip->command;
-       /*
-        * To be enabled the channel must simply be on. If any are enabled
-        * use continuous sampling mode.
-        * Possible to disable temp as well but that makes single read tricky.
-        */
-
-       mask = BIT(15 - chan->channel);
-
-       switch (chan->type) {
-       case IIO_VOLTAGE:
-               if ((!state) && (chip->c_mask & mask))
-                       chip->c_mask &= ~mask;
-               else if (state && (!(chip->c_mask & mask)))
-                       chip->c_mask |= mask;
-               else
-                       break;
-
-               regval &= ~AD7291_AUTOCYCLE;
-               regval |= chip->c_mask;
-               if (chip->c_mask) /* Enable autocycle? */
-                       regval |= AD7291_AUTOCYCLE;
-
-               ret = ad7291_i2c_write(chip, AD7291_COMMAND, regval);
-               if (ret < 0)
-                       goto error_ret;
-
-               chip->command = regval;
-               break;
-       default:
-               ret = -EINVAL;
-       }
-
-error_ret:
-       mutex_unlock(&chip->state_lock);
-       return ret;
-}
-
-static int ad7291_read_raw(struct iio_dev *indio_dev,
-                          struct iio_chan_spec const *chan,
-                          int *val,
-                          int *val2,
-                          long mask)
-{
-       int ret;
-       struct ad7291_chip_info *chip = iio_priv(indio_dev);
-       u16 regval;
-
-       switch (mask) {
-       case IIO_CHAN_INFO_RAW:
-               switch (chan->type) {
-               case IIO_VOLTAGE:
-                       mutex_lock(&chip->state_lock);
-                       /* If in autocycle mode drop through */
-                       if (chip->command & AD7291_AUTOCYCLE) {
-                               mutex_unlock(&chip->state_lock);
-                               return -EBUSY;
-                       }
-                       /* Enable this channel alone */
-                       regval = chip->command & (~AD7291_VOLTAGE_MASK);
-                       regval |= BIT(15 - chan->channel);
-                       ret = ad7291_i2c_write(chip, AD7291_COMMAND, regval);
-                       if (ret < 0) {
-                               mutex_unlock(&chip->state_lock);
-                               return ret;
-                       }
-                       /* Read voltage */
-                       ret = i2c_smbus_read_word_swapped(chip->client,
-                                                         AD7291_VOLTAGE);
-                       if (ret < 0) {
-                               mutex_unlock(&chip->state_lock);
-                               return ret;
-                       }
-                       *val = ret & AD7291_VALUE_MASK;
-                       mutex_unlock(&chip->state_lock);
-                       return IIO_VAL_INT;
-               case IIO_TEMP:
-                       /* Assumes tsense bit of command register always set */
-                       ret = i2c_smbus_read_word_swapped(chip->client,
-                                                         AD7291_T_SENSE);
-                       if (ret < 0)
-                               return ret;
-                       *val = sign_extend32(ret, 11);
-                       return IIO_VAL_INT;
-               default:
-                       return -EINVAL;
-               }
-       case IIO_CHAN_INFO_AVERAGE_RAW:
-               ret = i2c_smbus_read_word_swapped(chip->client,
-                                                 AD7291_T_AVERAGE);
-                       if (ret < 0)
-                               return ret;
-                       *val = sign_extend32(ret, 11);
-                       return IIO_VAL_INT;
-       case IIO_CHAN_INFO_SCALE:
-               switch (chan->type) {
-               case IIO_VOLTAGE:
-                       if (chip->reg) {
-                               int vref;
-                               vref = regulator_get_voltage(chip->reg);
-                               if (vref < 0)
-                                       return vref;
-                               *val = vref / 1000;
-                       } else {
-                               *val = 2500;
-                       }
-                       *val2 = AD7291_BITS;
-                       return IIO_VAL_FRACTIONAL_LOG2;
-               case IIO_TEMP:
-                       /*
-                        * One LSB of the ADC corresponds to 0.25 deg C.
-                        * The temperature reading is in 12-bit twos
-                        * complement format
-                        */
-                       *val = 250;
-                       return IIO_VAL_INT;
-               default:
-                       return -EINVAL;
-               }
-       default:
-               return -EINVAL;
-       }
-}
-
-static const struct iio_event_spec ad7291_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 AD7291_VOLTAGE_CHAN(_chan)                                     \
-{                                                                      \
-       .type = IIO_VOLTAGE,                                            \
-       .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),                   \
-       .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),           \
-       .indexed = 1,                                                   \
-       .channel = _chan,                                               \
-       .event_spec = ad7291_events,                                    \
-       .num_event_specs = ARRAY_SIZE(ad7291_events),                   \
-}
-
-static const struct iio_chan_spec ad7291_channels[] = {
-       AD7291_VOLTAGE_CHAN(0),
-       AD7291_VOLTAGE_CHAN(1),
-       AD7291_VOLTAGE_CHAN(2),
-       AD7291_VOLTAGE_CHAN(3),
-       AD7291_VOLTAGE_CHAN(4),
-       AD7291_VOLTAGE_CHAN(5),
-       AD7291_VOLTAGE_CHAN(6),
-       AD7291_VOLTAGE_CHAN(7),
-       {
-               .type = IIO_TEMP,
-               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
-                               BIT(IIO_CHAN_INFO_AVERAGE_RAW) |
-                               BIT(IIO_CHAN_INFO_SCALE),
-               .indexed = 1,
-               .channel = 0,
-               .event_spec = ad7291_events,
-               .num_event_specs = ARRAY_SIZE(ad7291_events),
-       }
-};
-
-static const struct iio_info ad7291_info = {
-       .read_raw = &ad7291_read_raw,
-       .read_event_config = &ad7291_read_event_config,
-       .write_event_config = &ad7291_write_event_config,
-       .read_event_value = &ad7291_read_event_value,
-       .write_event_value = &ad7291_write_event_value,
-       .driver_module = THIS_MODULE,
-};
-
-static int ad7291_probe(struct i2c_client *client,
-                       const struct i2c_device_id *id)
-{
-       struct ad7291_platform_data *pdata = client->dev.platform_data;
-       struct ad7291_chip_info *chip;
-       struct iio_dev *indio_dev;
-       int ret = 0;
-
-       indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
-       if (!indio_dev)
-               return -ENOMEM;
-       chip = iio_priv(indio_dev);
-
-       if (pdata && pdata->use_external_ref) {
-               chip->reg = devm_regulator_get(&client->dev, "vref");
-               if (IS_ERR(chip->reg))
-                       return ret;
-
-               ret = regulator_enable(chip->reg);
-               if (ret)
-                       return ret;
-       }
-
-       mutex_init(&chip->state_lock);
-       /* this is only used for device removal purposes */
-       i2c_set_clientdata(client, indio_dev);
-
-       chip->client = client;
-
-       chip->command = AD7291_NOISE_DELAY |
-                       AD7291_T_SENSE_MASK | /* Tsense always enabled */
-                       AD7291_ALERT_POLARITY; /* set irq polarity low level */
-
-       if (pdata && pdata->use_external_ref)
-               chip->command |= AD7291_EXT_REF;
-
-       indio_dev->name = id->name;
-       indio_dev->channels = ad7291_channels;
-       indio_dev->num_channels = ARRAY_SIZE(ad7291_channels);
-
-       indio_dev->dev.parent = &client->dev;
-       indio_dev->info = &ad7291_info;
-       indio_dev->modes = INDIO_DIRECT_MODE;
-
-       ret = ad7291_i2c_write(chip, AD7291_COMMAND, AD7291_RESET);
-       if (ret) {
-               ret = -EIO;
-               goto error_disable_reg;
-       }
-
-       ret = ad7291_i2c_write(chip, AD7291_COMMAND, chip->command);
-       if (ret) {
-               ret = -EIO;
-               goto error_disable_reg;
-       }
-
-       if (client->irq > 0) {
-               ret = request_threaded_irq(client->irq,
-                                          NULL,
-                                          &ad7291_event_handler,
-                                          IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-                                          id->name,
-                                          indio_dev);
-               if (ret)
-                       goto error_disable_reg;
-       }
-
-       ret = iio_device_register(indio_dev);
-       if (ret)
-               goto error_unreg_irq;
-
-       return 0;
-
-error_unreg_irq:
-       if (client->irq)
-               free_irq(client->irq, indio_dev);
-error_disable_reg:
-       if (chip->reg)
-               regulator_disable(chip->reg);
-
-       return ret;
-}
-
-static int ad7291_remove(struct i2c_client *client)
-{
-       struct iio_dev *indio_dev = i2c_get_clientdata(client);
-       struct ad7291_chip_info *chip = iio_priv(indio_dev);
-
-       iio_device_unregister(indio_dev);
-
-       if (client->irq)
-               free_irq(client->irq, indio_dev);
-
-       if (chip->reg)
-               regulator_disable(chip->reg);
-
-       return 0;
-}
-
-static const struct i2c_device_id ad7291_id[] = {
-       { "ad7291", 0 },
-       {}
-};
-
-MODULE_DEVICE_TABLE(i2c, ad7291_id);
-
-static struct i2c_driver ad7291_driver = {
-       .driver = {
-               .name = KBUILD_MODNAME,
-       },
-       .probe = ad7291_probe,
-       .remove = ad7291_remove,
-       .id_table = ad7291_id,
-};
-module_i2c_driver(ad7291_driver);
-
-MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
-MODULE_DESCRIPTION("Analog Devices AD7291 ADC driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/adc/ad7291.h b/drivers/staging/iio/adc/ad7291.h
deleted file mode 100644 (file)
index bbd89fa..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef __IIO_AD7291_H__
-#define __IIO_AD7291_H__
-
-/**
- * struct ad7291_platform_data - AD7291 platform data
- * @use_external_ref: Whether to use an external or internal reference voltage
- */
-struct ad7291_platform_data {
-       bool use_external_ref;
-};
-
-#endif
diff --git a/include/linux/platform_data/ad7291.h b/include/linux/platform_data/ad7291.h
new file mode 100644 (file)
index 0000000..bbd89fa
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __IIO_AD7291_H__
+#define __IIO_AD7291_H__
+
+/**
+ * struct ad7291_platform_data - AD7291 platform data
+ * @use_external_ref: Whether to use an external or internal reference voltage
+ */
+struct ad7291_platform_data {
+       bool use_external_ref;
+};
+
+#endif