Merge tag 'iio-for-4.9b' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio...
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 14 Sep 2016 18:42:03 +0000 (20:42 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 14 Sep 2016 18:42:03 +0000 (20:42 +0200)
Jonathan writes:

Second set of iio new device support, features and cleanups for the 4.9 cycle.

New device support
* ad8801 dac
  - new driver supporting ad8801 and ad8803 DACs.
adc12138
  - new driver supporting TI adc12130/adc12132 and adc12138 ADCs.
* ltc2485 adc
  - new driver
* mxc6255
  - add support for the mxc6225 part name and fixup the ID check so it works.
* vz89x VOC sensor
  - add support for the vz89te part which drops the voc_short channel and adds
    CRCs compared to other supported parts.

New features
* core
  - immutable triggers.  These effectively grant exclusive control over a
    trigger. The typical usecase is a device representing an analog part
    (perhaps a MUX) that needs to control the sampling of a downstream
    ADC.
  - resource managed trigger registration and triggered_buffer_init.
  - iio_push_event now protected against case of the event interface
    registration not having yet occured.  Only matters if an interrupt
    can occur during this window - might happen on shared interrupt lines.
  - helper to let a driver query if the trigger it is using is provided by
    itself (using the convention of both device and trigger having the same
    parent).
* tools
  - iio-utils. Used channel modifier scaling in preference to generic scaling
    when both exist.
* at91-adc
  - Add support for touchscreen switches closure time needed by some newer
    parts.
* stx104
  - support the ADC channels on this ADC/DAC board. As these are the primary
    feature of the board also move the driver to the iio/adc directory.
* sx9500
  - device tree bindings.

Cleanups / Fixes
* ad5755
  - fix an off-by-one on devnr limit check (introduced earlier this cycle)
* ad7266
  - drop NULL check on devm_regulator_get_optional as it can't return NULL.
* ak8974
  - avoid an unused functional warning due to rework in PM core code.
  - remove .owner field setting as done by i2c_core.
* ina2xx
  - clear out a left over debug field from chip global data.
* hid-sensors
  - avoid an unused functional warning due to rework in PM core code.
* maxim-thermocouple
  - fix non static symbol warnings.
* ms5611
  - fetch and enable regulators unconditionally when they aren't optional.
* sca3000
  - whitespace cleanup.
* st_sensors
  - fetch and enable regulators unconditionally rather than having them
    supported as optional regulators (missunderstanding on my part amongst
    others a while back)
  - followup to previous patch fixes error checking on the regulators.
  - mark symbols static where possible.
  - use the 'is it my trigger' help function.  This prevents the odd case
    of another device triggering from the st-sensors trigger whilst the
    st-sensors trigger is itself not using it but rather using say an hrtimer.
* ti-ads1015
  - add missing of_node_put.
* vz89x
  - rework to all support of new devices.
  - prevent reading of a corrupted buffer.
  - fixup a return value of 0/1 in a bool returning function.

Address updates
- Vlad Dogaru email address change.

39 files changed:
.mailmap
Documentation/devicetree/bindings/iio/adc/ti-adc12138.txt [new file with mode: 0644]
Documentation/devicetree/bindings/iio/proximity/sx9500.txt [new file with mode: 0644]
Documentation/driver-model/devres.txt
MAINTAINERS
drivers/iio/accel/mxc6255.c
drivers/iio/adc/Kconfig
drivers/iio/adc/Makefile
drivers/iio/adc/ad7266.c
drivers/iio/adc/at91_adc.c
drivers/iio/adc/ina2xx-adc.c
drivers/iio/adc/ltc2485.c [new file with mode: 0644]
drivers/iio/adc/stx104.c [new file with mode: 0644]
drivers/iio/adc/ti-adc12138.c [new file with mode: 0644]
drivers/iio/adc/ti-ads1015.c
drivers/iio/adc/ti-ads8688.c
drivers/iio/buffer/industrialio-triggered-buffer.c
drivers/iio/chemical/vz89x.c
drivers/iio/common/hid-sensors/hid-sensor-trigger.c
drivers/iio/common/st_sensors/st_sensors_buffer.c
drivers/iio/common/st_sensors/st_sensors_core.c
drivers/iio/common/st_sensors/st_sensors_trigger.c
drivers/iio/dac/Kconfig
drivers/iio/dac/Makefile
drivers/iio/dac/ad5755.c
drivers/iio/dac/ad8801.c [new file with mode: 0644]
drivers/iio/dac/stx104.c [deleted file]
drivers/iio/industrialio-core.c
drivers/iio/industrialio-event.c
drivers/iio/industrialio-trigger.c
drivers/iio/magnetometer/ak8974.c
drivers/iio/pressure/ms5611_core.c
drivers/iio/proximity/sx9500.c
drivers/iio/temperature/maxim_thermocouple.c
drivers/staging/iio/accel/sca3000_core.c
include/linux/iio/iio.h
include/linux/iio/trigger.h
include/linux/iio/triggered_buffer.h
tools/iio/iio_utils.c

index de22dae..377d16f 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -159,6 +159,7 @@ Valdis Kletnieks <Valdis.Kletnieks@vt.edu>
 Viresh Kumar <vireshk@kernel.org> <viresh.kumar@st.com>
 Viresh Kumar <vireshk@kernel.org> <viresh.linux@gmail.com>
 Viresh Kumar <vireshk@kernel.org> <viresh.kumar2@arm.com>
+Vlad Dogaru <ddvlad@gmail.com> <vlad.dogaru@intel.com>
 Vladimir Davydov <vdavydov.dev@gmail.com> <vdavydov@virtuozzo.com>
 Vladimir Davydov <vdavydov.dev@gmail.com> <vdavydov@parallels.com>
 Takashi YOSHII <takashi.yoshii.zj@renesas.com>
diff --git a/Documentation/devicetree/bindings/iio/adc/ti-adc12138.txt b/Documentation/devicetree/bindings/iio/adc/ti-adc12138.txt
new file mode 100644 (file)
index 0000000..049a1d3
--- /dev/null
@@ -0,0 +1,37 @@
+* Texas Instruments' ADC12130/ADC12132/ADC12138
+
+Required properties:
+ - compatible: Should be one of
+       * "ti,adc12130"
+       * "ti,adc12132"
+       * "ti,adc12138"
+ - reg: SPI chip select number for the device
+ - interrupts: Should contain interrupt for EOC (end of conversion)
+ - clocks: phandle to conversion clock input
+ - spi-max-frequency: Definision as per
+       Documentation/devicetree/bindings/spi/spi-bus.txt
+ - vref-p-supply: The regulator supply for positive analog voltage reference
+
+Optional properties:
+ - vref-n-supply: The regulator supply for negative analog voltage reference
+       (Note that this must not go below GND or exceed vref-p)
+       If not specified, this is assumed to be analog ground.
+ - ti,acquisition-time: The number of conversion clock periods for the S/H's
+       acquisition time.  Should be one of 6, 10, 18, 34.  If not specified,
+       default value of 10 is used.
+       For high source impedances, this value can be increased to 18 or 34.
+       For less ADC accuracy and/or slower CCLK frequencies this value may be
+       decreased to 6.  See section 6.0 INPUT SOURCE RESISTANCE in the
+       datasheet for details.
+
+Example:
+adc@0 {
+       compatible = "ti,adc12138";
+       reg = <0>;
+       interrupts = <28 IRQ_TYPE_EDGE_RISING>;
+       interrupt-parent = <&gpio1>;
+       clocks = <&cclk>;
+       vref-p-supply = <&ldo4_reg>;
+       spi-max-frequency = <5000000>;
+       ti,acquisition-time = <6>;
+};
diff --git a/Documentation/devicetree/bindings/iio/proximity/sx9500.txt b/Documentation/devicetree/bindings/iio/proximity/sx9500.txt
new file mode 100644 (file)
index 0000000..b301dd2
--- /dev/null
@@ -0,0 +1,24 @@
+Semtech's SX9500 capacitive proximity button device driver
+
+Required properties:
+       - compatible: must be "semtech,sx9500"
+       - reg: i2c address where to find the device
+       - 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:
+       - reset-gpios: Reference to the GPIO connected to the device's active
+         low reset pin.
+
+Example:
+
+sx9500@28 {
+       compatible = "semtech,sx9500";
+       reg = <0x28>;
+       interrupt-parent = <&gpio2>;
+       interrupts = <16 IRQ_TYPE_LEVEL_LOW>;
+       reset-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>;
+};
index b0d775d..75bc5b8 100644 (file)
@@ -266,8 +266,12 @@ IIO
   devm_iio_device_unregister()
   devm_iio_kfifo_allocate()
   devm_iio_kfifo_free()
+  devm_iio_triggered_buffer_setup()
+  devm_iio_triggered_buffer_cleanup()
   devm_iio_trigger_alloc()
   devm_iio_trigger_free()
+  devm_iio_trigger_register()
+  devm_iio_trigger_unregister()
   devm_iio_channel_get()
   devm_iio_channel_release()
   devm_iio_channel_get_all()
index ad01604..1b65477 100644 (file)
@@ -810,11 +810,11 @@ L:        alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Maintained
 F:     sound/aoa/
 
-APEX EMBEDDED SYSTEMS STX104 DAC DRIVER
+APEX EMBEDDED SYSTEMS STX104 IIO DRIVER
 M:     William Breathitt Gray <vilhelm.gray@gmail.com>
 L:     linux-iio@vger.kernel.org
 S:     Maintained
-F:     drivers/iio/dac/stx104.c
+F:     drivers/iio/adc/stx104.c
 
 APM DRIVER
 M:     Jiri Kosina <jikos@kernel.org>
index 97ccde7..0abad69 100644 (file)
@@ -154,7 +154,7 @@ static int mxc6255_probe(struct i2c_client *client,
                return ret;
        }
 
-       if (chip_id != MXC6255_CHIP_ID) {
+       if ((chip_id & 0x1f) != MXC6255_CHIP_ID) {
                dev_err(&client->dev, "Invalid chip id %x\n", chip_id);
                return -ENODEV;
        }
@@ -171,12 +171,14 @@ static int mxc6255_probe(struct i2c_client *client,
 }
 
 static const struct acpi_device_id mxc6255_acpi_match[] = {
+       {"MXC6225",     0},
        {"MXC6255",     0},
        { }
 };
 MODULE_DEVICE_TABLE(acpi, mxc6255_acpi_match);
 
 static const struct i2c_device_id mxc6255_id[] = {
+       {"mxc6225",     0},
        {"mxc6255",     0},
        { }
 };
index 586830e..7edcf32 100644 (file)
@@ -264,6 +264,15 @@ config LPC18XX_ADC
          To compile this driver as a module, choose M here: the module will be
          called lpc18xx_adc.
 
+config LTC2485
+       tristate "Linear Technology LTC2485 ADC driver"
+       depends on I2C
+       help
+         Say yes here to build support for Linear Technology LTC2485 ADC.
+
+         To compile this driver as a module, choose M here: the module will be
+         called ltc2485.
+
 config MAX1027
        tristate "Maxim max1027 ADC driver"
        depends on SPI
@@ -410,6 +419,21 @@ config ROCKCHIP_SARADC
          To compile this driver as a module, choose M here: the
          module will be called rockchip_saradc.
 
+config STX104
+       tristate "Apex Embedded Systems STX104 driver"
+       depends on X86 && ISA_BUS_API
+       select GPIOLIB
+       help
+         Say yes here to build support for the Apex Embedded Systems STX104
+         integrated analog PC/104 card.
+
+         This driver supports the 16 channels of single-ended (8 channels of
+         differential) analog inputs, 2 channels of analog output, 4 digital
+         inputs, and 4 digital outputs provided by the STX104.
+
+         The base port addresses for the devices may be configured via the base
+         array module parameter.
+
 config TI_ADC081C
        tristate "Texas Instruments ADC081C/ADC101C/ADC121C family"
        depends on I2C
@@ -430,6 +454,18 @@ config TI_ADC0832
          This driver can also be built as a module. If so, the module will be
          called ti-adc0832.
 
+config TI_ADC12138
+       tristate "Texas Instruments ADC12130/ADC12132/ADC12138"
+       depends on SPI
+       select IIO_BUFFER
+       select IIO_TRIGGERED_BUFFER
+       help
+         If you say yes here you get support for Texas Instruments ADC12130,
+         ADC12132 and ADC12138 chips.
+
+         This driver can also be built as a module. If so, the module will be
+         called ti-adc12138.
+
 config TI_ADC128S052
        tristate "Texas Instruments ADC128S052/ADC122S021/ADC124S021"
        depends on SPI
index 33254eb..7a40c04 100644 (file)
@@ -27,6 +27,7 @@ obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o
 obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o
 obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
 obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o
+obj-$(CONFIG_LTC2485) += ltc2485.o
 obj-$(CONFIG_MAX1027) += max1027.o
 obj-$(CONFIG_MAX1363) += max1363.o
 obj-$(CONFIG_MCP320X) += mcp320x.o
@@ -39,8 +40,10 @@ obj-$(CONFIG_PALMAS_GPADC) += palmas_gpadc.o
 obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o
 obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o
 obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o
+obj-$(CONFIG_STX104) += stx104.o
 obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
 obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o
+obj-$(CONFIG_TI_ADC12138) += ti-adc12138.o
 obj-$(CONFIG_TI_ADC128S052) += ti-adc128s052.o
 obj-$(CONFIG_TI_ADC161S626) += ti-adc161s626.o
 obj-$(CONFIG_TI_ADS1015) += ti-ads1015.o
index c0f6a98..b8d5cfd 100644 (file)
@@ -481,7 +481,7 @@ error_free_gpios:
        if (!st->fixed_addr)
                gpio_free_array(st->gpios, ARRAY_SIZE(st->gpios));
 error_disable_reg:
-       if (!IS_ERR_OR_NULL(st->reg))
+       if (!IS_ERR(st->reg))
                regulator_disable(st->reg);
 
        return ret;
@@ -496,7 +496,7 @@ static int ad7266_remove(struct spi_device *spi)
        iio_triggered_buffer_cleanup(indio_dev);
        if (!st->fixed_addr)
                gpio_free_array(st->gpios, ARRAY_SIZE(st->gpios));
-       if (!IS_ERR_OR_NULL(st->reg))
+       if (!IS_ERR(st->reg))
                regulator_disable(st->reg);
 
        return 0;
index 0438c68..bbdac07 100644 (file)
 #define                AT91_ADC_TSMR_TSAV      (3 << 4)        /* Averages samples */
 #define                        AT91_ADC_TSMR_TSAV_(x)          ((x) << 4)
 #define                AT91_ADC_TSMR_SCTIM     (0x0f << 16)    /* Switch closure time */
+#define                        AT91_ADC_TSMR_SCTIM_(x)         ((x) << 16)
 #define                AT91_ADC_TSMR_PENDBC    (0x0f << 28)    /* Pen Debounce time */
 #define                        AT91_ADC_TSMR_PENDBC_(x)        ((x) << 28)
 #define                AT91_ADC_TSMR_NOTSDMA   (1 << 22)       /* No Touchscreen DMA */
 #define MAX_RLPOS_BITS         10
 #define TOUCH_SAMPLE_PERIOD_US_RL      10000   /* 10ms, the SoC can't keep up with 2ms */
 #define TOUCH_SHTIM                    0xa
+#define TOUCH_SCTIM_US         10              /* 10us for the Touchscreen Switches Closure Time */
 
 /**
  * struct at91_adc_reg_desc - Various informations relative to registers
@@ -1001,7 +1003,9 @@ static void atmel_ts_close(struct input_dev *dev)
 
 static int at91_ts_hw_init(struct at91_adc_state *st, u32 adc_clk_khz)
 {
+       struct iio_dev *idev = iio_priv_to_dev(st);
        u32 reg = 0;
+       u32 tssctim = 0;
        int i = 0;
 
        /* a Pen Detect Debounce Time is necessary for the ADC Touch to avoid
@@ -1034,11 +1038,20 @@ static int at91_ts_hw_init(struct at91_adc_state *st, u32 adc_clk_khz)
                return 0;
        }
 
+       /* Touchscreen Switches Closure time needed for allowing the value to
+        * stabilize.
+        * Switch Closure Time = (TSSCTIM * 4) ADCClock periods
+        */
+       tssctim = DIV_ROUND_UP(TOUCH_SCTIM_US * adc_clk_khz / 1000, 4);
+       dev_dbg(&idev->dev, "adc_clk at: %d KHz, tssctim at: %d\n",
+               adc_clk_khz, tssctim);
+
        if (st->touchscreen_type == ATMEL_ADC_TOUCHSCREEN_4WIRE)
                reg = AT91_ADC_TSMR_TSMODE_4WIRE_PRESS;
        else
                reg = AT91_ADC_TSMR_TSMODE_5WIRE;
 
+       reg |= AT91_ADC_TSMR_SCTIM_(tssctim) & AT91_ADC_TSMR_SCTIM;
        reg |= AT91_ADC_TSMR_TSAV_(st->caps->ts_filter_average)
               & AT91_ADC_TSMR_TSAV;
        reg |= AT91_ADC_TSMR_PENDBC_(st->ts_pendbc) & AT91_ADC_TSMR_PENDBC;
index 955f3fd..59b7d76 100644 (file)
@@ -114,7 +114,6 @@ struct ina2xx_chip_info {
        struct mutex state_lock;
        unsigned int shunt_resistor;
        int avg;
-       s64 prev_ns; /* track buffer capture time, check for underruns */
        int int_time_vbus; /* Bus voltage integration time uS */
        int int_time_vshunt; /* Shunt voltage integration time uS */
        bool allow_async_readout;
@@ -509,8 +508,6 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev)
        iio_push_to_buffers_with_timestamp(indio_dev,
                                           (unsigned int *)data, time_a);
 
-       chip->prev_ns = time_a;
-
        return (unsigned long)(time_b - time_a) / 1000;
 };
 
@@ -554,8 +551,6 @@ static int ina2xx_buffer_enable(struct iio_dev *indio_dev)
        dev_dbg(&indio_dev->dev, "Async readout mode: %d\n",
                chip->allow_async_readout);
 
-       chip->prev_ns = iio_get_time_ns(indio_dev);
-
        chip->task = kthread_run(ina2xx_capture_thread, (void *)indio_dev,
                                 "%s:%d-%uus", indio_dev->name, indio_dev->id,
                                 sampling_us);
diff --git a/drivers/iio/adc/ltc2485.c b/drivers/iio/adc/ltc2485.c
new file mode 100644 (file)
index 0000000..eab91f1
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * ltc2485.c - Driver for Linear Technology LTC2485 ADC
+ *
+ * Copyright (C) 2016 Alison Schofield <amsfield22@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Datasheet: http://cds.linear.com/docs/en/datasheet/2485fd.pdf
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+/* Power-on configuration: rejects both 50/60Hz, operates at 1x speed */
+#define LTC2485_CONFIG_DEFAULT         0
+
+struct ltc2485_data {
+       struct i2c_client       *client;
+       ktime_t                 time_prev;      /* last conversion */
+};
+
+static void ltc2485_wait_conv(struct ltc2485_data *data)
+{
+       const unsigned int conv_time = 147;     /* conversion time ms */
+       unsigned int time_elapsed;
+
+       /* delay if conversion time not passed since last read or write */
+       time_elapsed = ktime_ms_delta(ktime_get(), data->time_prev);
+
+       if (time_elapsed < conv_time)
+               msleep(conv_time - time_elapsed);
+}
+
+static int ltc2485_read(struct ltc2485_data *data, int *val)
+{
+       struct i2c_client *client = data->client;
+       __be32 buf = 0;
+       int ret;
+
+       ltc2485_wait_conv(data);
+
+       ret = i2c_master_recv(client, (char *)&buf, 4);
+       if (ret < 0)  {
+               dev_err(&client->dev, "i2c_master_recv failed\n");
+               return ret;
+       }
+       data->time_prev = ktime_get();
+       *val = sign_extend32(be32_to_cpu(buf) >> 6, 24);
+
+       return ret;
+}
+
+static int ltc2485_read_raw(struct iio_dev *indio_dev,
+                           struct iio_chan_spec const *chan,
+                           int *val, int *val2, long mask)
+{
+       struct ltc2485_data *data = iio_priv(indio_dev);
+       int ret;
+
+       if (mask == IIO_CHAN_INFO_RAW) {
+               ret = ltc2485_read(data, val);
+               if (ret < 0)
+                       return ret;
+
+               return IIO_VAL_INT;
+
+       } else if (mask == IIO_CHAN_INFO_SCALE) {
+               *val = 5000;                    /* on board vref millivolts */
+               *val2 = 25;                     /* 25 (24 + sign) data bits */
+               return IIO_VAL_FRACTIONAL_LOG2;
+
+       } else {
+               return -EINVAL;
+       }
+}
+
+static const struct iio_chan_spec ltc2485_channel[] = {
+       {
+               .type = IIO_VOLTAGE,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+               .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE)
+       },
+};
+
+static const struct iio_info ltc2485_info = {
+       .read_raw = ltc2485_read_raw,
+       .driver_module = THIS_MODULE,
+};
+
+static int ltc2485_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
+{
+       struct iio_dev *indio_dev;
+       struct ltc2485_data *data;
+       int ret;
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
+                                    I2C_FUNC_SMBUS_WRITE_BYTE))
+               return -EOPNOTSUPP;
+
+       indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+       if (!indio_dev)
+               return -ENOMEM;
+
+       data = iio_priv(indio_dev);
+       i2c_set_clientdata(client, indio_dev);
+       data->client = client;
+
+       indio_dev->dev.parent = &client->dev;
+       indio_dev->name = id->name;
+       indio_dev->info = &ltc2485_info;
+       indio_dev->modes = INDIO_DIRECT_MODE;
+       indio_dev->channels = ltc2485_channel;
+       indio_dev->num_channels = ARRAY_SIZE(ltc2485_channel);
+
+       ret = i2c_smbus_write_byte(data->client, LTC2485_CONFIG_DEFAULT);
+       if (ret < 0)
+               return ret;
+
+       data->time_prev = ktime_get();
+
+       return devm_iio_device_register(&client->dev, indio_dev);
+}
+
+static const struct i2c_device_id ltc2485_id[] = {
+       { "ltc2485", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, ltc2485_id);
+
+static struct i2c_driver ltc2485_driver = {
+       .driver = {
+               .name = "ltc2485",
+       },
+       .probe = ltc2485_probe,
+       .id_table = ltc2485_id,
+};
+module_i2c_driver(ltc2485_driver);
+
+MODULE_AUTHOR("Alison Schofield <amsfield22@gmail.com>");
+MODULE_DESCRIPTION("Linear Technology LTC2485 ADC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/stx104.c b/drivers/iio/adc/stx104.c
new file mode 100644 (file)
index 0000000..7e36457
--- /dev/null
@@ -0,0 +1,380 @@
+/*
+ * IIO driver for the Apex Embedded Systems STX104
+ * Copyright (C) 2016 William Breathitt Gray
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/gpio/driver.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/types.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/isa.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/spinlock.h>
+
+#define STX104_OUT_CHAN(chan) {                                \
+       .type = IIO_VOLTAGE,                            \
+       .channel = chan,                                \
+       .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
+       .indexed = 1,                                   \
+       .output = 1                                     \
+}
+#define STX104_IN_CHAN(chan, diff) {                                   \
+       .type = IIO_VOLTAGE,                                            \
+       .channel = chan,                                                \
+       .channel2 = chan,                                               \
+       .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_HARDWAREGAIN) |   \
+               BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE),   \
+       .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),                   \
+       .indexed = 1,                                                   \
+       .differential = diff                                            \
+}
+
+#define STX104_NUM_OUT_CHAN 2
+
+#define STX104_EXTENT 16
+
+static unsigned int base[max_num_isa_dev(STX104_EXTENT)];
+static unsigned int num_stx104;
+module_param_array(base, uint, &num_stx104, 0);
+MODULE_PARM_DESC(base, "Apex Embedded Systems STX104 base addresses");
+
+/**
+ * struct stx104_iio - IIO device private data structure
+ * @chan_out_states:   channels' output states
+ * @base:              base port address of the IIO device
+ */
+struct stx104_iio {
+       unsigned int chan_out_states[STX104_NUM_OUT_CHAN];
+       unsigned int base;
+};
+
+/**
+ * struct stx104_gpio - GPIO device private data structure
+ * @chip:      instance of the gpio_chip
+ * @lock:      synchronization lock to prevent I/O race conditions
+ * @base:      base port address of the GPIO device
+ * @out_state: output bits state
+ */
+struct stx104_gpio {
+       struct gpio_chip chip;
+       spinlock_t lock;
+       unsigned int base;
+       unsigned int out_state;
+};
+
+/**
+ * struct stx104_dev - STX104 device private data structure
+ * @indio_dev: IIO device
+ * @chip:      instance of the gpio_chip
+ */
+struct stx104_dev {
+       struct iio_dev *indio_dev;
+       struct gpio_chip *chip;
+};
+
+static int stx104_read_raw(struct iio_dev *indio_dev,
+       struct iio_chan_spec const *chan, int *val, int *val2, long mask)
+{
+       struct stx104_iio *const priv = iio_priv(indio_dev);
+       unsigned int adc_config;
+       int adbu;
+       int gain;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_HARDWAREGAIN:
+               /* get gain configuration */
+               adc_config = inb(priv->base + 11);
+               gain = adc_config & 0x3;
+
+               *val = 1 << gain;
+               return IIO_VAL_INT;
+       case IIO_CHAN_INFO_RAW:
+               if (chan->output) {
+                       *val = priv->chan_out_states[chan->channel];
+                       return IIO_VAL_INT;
+               }
+
+               /* select ADC channel */
+               outb(chan->channel | (chan->channel << 4), priv->base + 2);
+
+               /* trigger ADC sample capture and wait for completion */
+               outb(0, priv->base);
+               while (inb(priv->base + 8) & BIT(7));
+
+               *val = inw(priv->base);
+               return IIO_VAL_INT;
+       case IIO_CHAN_INFO_OFFSET:
+               /* get ADC bipolar/unipolar configuration */
+               adc_config = inb(priv->base + 11);
+               adbu = !(adc_config & BIT(2));
+
+               *val = -32768 * adbu;
+               return IIO_VAL_INT;
+       case IIO_CHAN_INFO_SCALE:
+               /* get ADC bipolar/unipolar and gain configuration */
+               adc_config = inb(priv->base + 11);
+               adbu = !(adc_config & BIT(2));
+               gain = adc_config & 0x3;
+
+               *val = 5;
+               *val2 = 15 - adbu + gain;
+               return IIO_VAL_FRACTIONAL_LOG2;
+       }
+
+       return -EINVAL;
+}
+
+static int stx104_write_raw(struct iio_dev *indio_dev,
+       struct iio_chan_spec const *chan, int val, int val2, long mask)
+{
+       struct stx104_iio *const priv = iio_priv(indio_dev);
+
+       switch (mask) {
+       case IIO_CHAN_INFO_HARDWAREGAIN:
+               /* Only four gain states (x1, x2, x4, x8) */
+               switch (val) {
+               case 1:
+                       outb(0, priv->base + 11);
+                       break;
+               case 2:
+                       outb(1, priv->base + 11);
+                       break;
+               case 4:
+                       outb(2, priv->base + 11);
+                       break;
+               case 8:
+                       outb(3, priv->base + 11);
+                       break;
+               default:
+                       return -EINVAL;
+               }
+
+               return 0;
+       case IIO_CHAN_INFO_RAW:
+               if (chan->output) {
+                       /* DAC can only accept up to a 16-bit value */
+                       if ((unsigned int)val > 65535)
+                               return -EINVAL;
+
+                       priv->chan_out_states[chan->channel] = val;
+                       outw(val, priv->base + 4 + 2 * chan->channel);
+
+                       return 0;
+               }
+               return -EINVAL;
+       }
+
+       return -EINVAL;
+}
+
+static const struct iio_info stx104_info = {
+       .driver_module = THIS_MODULE,
+       .read_raw = stx104_read_raw,
+       .write_raw = stx104_write_raw
+};
+
+/* single-ended input channels configuration */
+static const struct iio_chan_spec stx104_channels_sing[] = {
+       STX104_OUT_CHAN(0), STX104_OUT_CHAN(1),
+       STX104_IN_CHAN(0, 0), STX104_IN_CHAN(1, 0), STX104_IN_CHAN(2, 0),
+       STX104_IN_CHAN(3, 0), STX104_IN_CHAN(4, 0), STX104_IN_CHAN(5, 0),
+       STX104_IN_CHAN(6, 0), STX104_IN_CHAN(7, 0), STX104_IN_CHAN(8, 0),
+       STX104_IN_CHAN(9, 0), STX104_IN_CHAN(10, 0), STX104_IN_CHAN(11, 0),
+       STX104_IN_CHAN(12, 0), STX104_IN_CHAN(13, 0), STX104_IN_CHAN(14, 0),
+       STX104_IN_CHAN(15, 0)
+};
+/* differential input channels configuration */
+static const struct iio_chan_spec stx104_channels_diff[] = {
+       STX104_OUT_CHAN(0), STX104_OUT_CHAN(1),
+       STX104_IN_CHAN(0, 1), STX104_IN_CHAN(1, 1), STX104_IN_CHAN(2, 1),
+       STX104_IN_CHAN(3, 1), STX104_IN_CHAN(4, 1), STX104_IN_CHAN(5, 1),
+       STX104_IN_CHAN(6, 1), STX104_IN_CHAN(7, 1)
+};
+
+static int stx104_gpio_get_direction(struct gpio_chip *chip,
+       unsigned int offset)
+{
+       /* GPIO 0-3 are input only, while the rest are output only */
+       if (offset < 4)
+               return 1;
+
+       return 0;
+}
+
+static int stx104_gpio_direction_input(struct gpio_chip *chip,
+       unsigned int offset)
+{
+       if (offset >= 4)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int stx104_gpio_direction_output(struct gpio_chip *chip,
+       unsigned int offset, int value)
+{
+       if (offset < 4)
+               return -EINVAL;
+
+       chip->set(chip, offset, value);
+       return 0;
+}
+
+static int stx104_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+       struct stx104_gpio *const stx104gpio = gpiochip_get_data(chip);
+
+       if (offset >= 4)
+               return -EINVAL;
+
+       return !!(inb(stx104gpio->base) & BIT(offset));
+}
+
+static void stx104_gpio_set(struct gpio_chip *chip, unsigned int offset,
+       int value)
+{
+       struct stx104_gpio *const stx104gpio = gpiochip_get_data(chip);
+       const unsigned int mask = BIT(offset) >> 4;
+       unsigned long flags;
+
+       if (offset < 4)
+               return;
+
+       spin_lock_irqsave(&stx104gpio->lock, flags);
+
+       if (value)
+               stx104gpio->out_state |= mask;
+       else
+               stx104gpio->out_state &= ~mask;
+
+       outb(stx104gpio->out_state, stx104gpio->base);
+
+       spin_unlock_irqrestore(&stx104gpio->lock, flags);
+}
+
+static int stx104_probe(struct device *dev, unsigned int id)
+{
+       struct iio_dev *indio_dev;
+       struct stx104_iio *priv;
+       struct stx104_gpio *stx104gpio;
+       struct stx104_dev *stx104dev;
+       int err;
+
+       indio_dev = devm_iio_device_alloc(dev, sizeof(*priv));
+       if (!indio_dev)
+               return -ENOMEM;
+
+       stx104gpio = devm_kzalloc(dev, sizeof(*stx104gpio), GFP_KERNEL);
+       if (!stx104gpio)
+               return -ENOMEM;
+
+       stx104dev = devm_kzalloc(dev, sizeof(*stx104dev), GFP_KERNEL);
+       if (!stx104dev)
+               return -ENOMEM;
+
+       if (!devm_request_region(dev, base[id], STX104_EXTENT,
+               dev_name(dev))) {
+               dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
+                       base[id], base[id] + STX104_EXTENT);
+               return -EBUSY;
+       }
+
+       indio_dev->info = &stx104_info;
+       indio_dev->modes = INDIO_DIRECT_MODE;
+
+       /* determine if differential inputs */
+       if (inb(base[id] + 8) & BIT(5)) {
+               indio_dev->num_channels = ARRAY_SIZE(stx104_channels_diff);
+               indio_dev->channels = stx104_channels_diff;
+       } else {
+               indio_dev->num_channels = ARRAY_SIZE(stx104_channels_sing);
+               indio_dev->channels = stx104_channels_sing;
+       }
+
+       indio_dev->name = dev_name(dev);
+
+       priv = iio_priv(indio_dev);
+       priv->base = base[id];
+
+       /* configure device for software trigger operation */
+       outb(0, base[id] + 9);
+
+       /* initialize gain setting to x1 */
+       outb(0, base[id] + 11);
+
+       /* initialize DAC output to 0V */
+       outw(0, base[id] + 4);
+       outw(0, base[id] + 6);
+
+       stx104gpio->chip.label = dev_name(dev);
+       stx104gpio->chip.parent = dev;
+       stx104gpio->chip.owner = THIS_MODULE;
+       stx104gpio->chip.base = -1;
+       stx104gpio->chip.ngpio = 8;
+       stx104gpio->chip.get_direction = stx104_gpio_get_direction;
+       stx104gpio->chip.direction_input = stx104_gpio_direction_input;
+       stx104gpio->chip.direction_output = stx104_gpio_direction_output;
+       stx104gpio->chip.get = stx104_gpio_get;
+       stx104gpio->chip.set = stx104_gpio_set;
+       stx104gpio->base = base[id] + 3;
+       stx104gpio->out_state = 0x0;
+
+       spin_lock_init(&stx104gpio->lock);
+
+       stx104dev->indio_dev = indio_dev;
+       stx104dev->chip = &stx104gpio->chip;
+       dev_set_drvdata(dev, stx104dev);
+
+       err = gpiochip_add_data(&stx104gpio->chip, stx104gpio);
+       if (err) {
+               dev_err(dev, "GPIO registering failed (%d)\n", err);
+               return err;
+       }
+
+       err = iio_device_register(indio_dev);
+       if (err) {
+               dev_err(dev, "IIO device registering failed (%d)\n", err);
+               gpiochip_remove(&stx104gpio->chip);
+               return err;
+       }
+
+       return 0;
+}
+
+static int stx104_remove(struct device *dev, unsigned int id)
+{
+       struct stx104_dev *const stx104dev = dev_get_drvdata(dev);
+
+       iio_device_unregister(stx104dev->indio_dev);
+       gpiochip_remove(stx104dev->chip);
+
+       return 0;
+}
+
+static struct isa_driver stx104_driver = {
+       .probe = stx104_probe,
+       .driver = {
+               .name = "stx104"
+       },
+       .remove = stx104_remove
+};
+
+module_isa_driver(stx104_driver, num_stx104);
+
+MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
+MODULE_DESCRIPTION("Apex Embedded Systems STX104 IIO driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/ti-adc12138.c b/drivers/iio/adc/ti-adc12138.c
new file mode 100644 (file)
index 0000000..072f03b
--- /dev/null
@@ -0,0 +1,552 @@
+/*
+ * ADC12130/ADC12132/ADC12138 12-bit plus sign ADC driver
+ *
+ * Copyright (c) 2016 Akinobu Mita <akinobu.mita@gmail.com>
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License.  See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * Datasheet: http://www.ti.com/lit/ds/symlink/adc12138.pdf
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+#include <linux/clk.h>
+#include <linux/spi/spi.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/regulator/consumer.h>
+
+#define ADC12138_MODE_AUTO_CAL                 0x08
+#define ADC12138_MODE_READ_STATUS              0x0c
+#define ADC12138_MODE_ACQUISITION_TIME_6       0x0e
+#define ADC12138_MODE_ACQUISITION_TIME_10      0x4e
+#define ADC12138_MODE_ACQUISITION_TIME_18      0x8e
+#define ADC12138_MODE_ACQUISITION_TIME_34      0xce
+
+#define ADC12138_STATUS_CAL                    BIT(6)
+
+enum {
+       adc12130,
+       adc12132,
+       adc12138,
+};
+
+struct adc12138 {
+       struct spi_device *spi;
+       unsigned int id;
+       /* conversion clock */
+       struct clk *cclk;
+       /* positive analog voltage reference */
+       struct regulator *vref_p;
+       /* negative analog voltage reference */
+       struct regulator *vref_n;
+       struct mutex lock;
+       struct completion complete;
+       /* The number of cclk periods for the S/H's acquisition time */
+       unsigned int acquisition_time;
+
+       u8 tx_buf[2] ____cacheline_aligned;
+       u8 rx_buf[2];
+};
+
+#define ADC12138_VOLTAGE_CHANNEL(chan)                                 \
+       {                                                               \
+               .type = IIO_VOLTAGE,                                    \
+               .indexed = 1,                                           \
+               .channel = chan,                                        \
+               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),           \
+               .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE)    \
+                                       | BIT(IIO_CHAN_INFO_OFFSET),    \
+               .scan_index = chan,                                     \
+               .scan_type = {                                          \
+                       .sign = 's',                                    \
+                       .realbits = 13,                                 \
+                       .storagebits = 16,                              \
+                       .shift = 3,                                     \
+                       .endianness = IIO_BE,                           \
+               },                                                      \
+       }
+
+#define ADC12138_VOLTAGE_CHANNEL_DIFF(chan1, chan2, si)                        \
+       {                                                               \
+               .type = IIO_VOLTAGE,                                    \
+               .indexed = 1,                                           \
+               .channel = (chan1),                                     \
+               .channel2 = (chan2),                                    \
+               .differential = 1,                                      \
+               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),           \
+               .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE)    \
+                                       | BIT(IIO_CHAN_INFO_OFFSET),    \
+               .scan_index = si,                                       \
+               .scan_type = {                                          \
+                       .sign = 's',                                    \
+                       .realbits = 13,                                 \
+                       .storagebits = 16,                              \
+                       .shift = 3,                                     \
+                       .endianness = IIO_BE,                           \
+               },                                                      \
+       }
+
+static const struct iio_chan_spec adc12132_channels[] = {
+       ADC12138_VOLTAGE_CHANNEL(0),
+       ADC12138_VOLTAGE_CHANNEL(1),
+       ADC12138_VOLTAGE_CHANNEL_DIFF(0, 1, 2),
+       ADC12138_VOLTAGE_CHANNEL_DIFF(1, 0, 3),
+       IIO_CHAN_SOFT_TIMESTAMP(4),
+};
+
+static const struct iio_chan_spec adc12138_channels[] = {
+       ADC12138_VOLTAGE_CHANNEL(0),
+       ADC12138_VOLTAGE_CHANNEL(1),
+       ADC12138_VOLTAGE_CHANNEL(2),
+       ADC12138_VOLTAGE_CHANNEL(3),
+       ADC12138_VOLTAGE_CHANNEL(4),
+       ADC12138_VOLTAGE_CHANNEL(5),
+       ADC12138_VOLTAGE_CHANNEL(6),
+       ADC12138_VOLTAGE_CHANNEL(7),
+       ADC12138_VOLTAGE_CHANNEL_DIFF(0, 1, 8),
+       ADC12138_VOLTAGE_CHANNEL_DIFF(1, 0, 9),
+       ADC12138_VOLTAGE_CHANNEL_DIFF(2, 3, 10),
+       ADC12138_VOLTAGE_CHANNEL_DIFF(3, 2, 11),
+       ADC12138_VOLTAGE_CHANNEL_DIFF(4, 5, 12),
+       ADC12138_VOLTAGE_CHANNEL_DIFF(5, 4, 13),
+       ADC12138_VOLTAGE_CHANNEL_DIFF(6, 7, 14),
+       ADC12138_VOLTAGE_CHANNEL_DIFF(7, 6, 15),
+       IIO_CHAN_SOFT_TIMESTAMP(16),
+};
+
+static int adc12138_mode_programming(struct adc12138 *adc, u8 mode,
+                                    void *rx_buf, int len)
+{
+       struct spi_transfer xfer = {
+               .tx_buf = adc->tx_buf,
+               .rx_buf = adc->rx_buf,
+               .len = len,
+       };
+       int ret;
+
+       /* Skip unused bits for ADC12130 and ADC12132 */
+       if (adc->id != adc12138)
+               mode = (mode & 0xc0) | ((mode & 0x0f) << 2);
+
+       adc->tx_buf[0] = mode;
+
+       ret = spi_sync_transfer(adc->spi, &xfer, 1);
+       if (ret)
+               return ret;
+
+       memcpy(rx_buf, adc->rx_buf, len);
+
+       return 0;
+}
+
+static int adc12138_read_status(struct adc12138 *adc)
+{
+       u8 rx_buf[2];
+       int ret;
+
+       ret = adc12138_mode_programming(adc, ADC12138_MODE_READ_STATUS,
+                                       rx_buf, 2);
+       if (ret)
+               return ret;
+
+       return (rx_buf[0] << 1) | (rx_buf[1] >> 7);
+}
+
+static int __adc12138_start_conv(struct adc12138 *adc,
+                                struct iio_chan_spec const *channel,
+                                void *data, int len)
+
+{
+       const u8 ch_to_mux[] = { 0, 4, 1, 5, 2, 6, 3, 7 };
+       u8 mode = (ch_to_mux[channel->channel] << 4) |
+                 (channel->differential ? 0 : 0x80);
+
+       return adc12138_mode_programming(adc, mode, data, len);
+}
+
+static int adc12138_start_conv(struct adc12138 *adc,
+                              struct iio_chan_spec const *channel)
+{
+       u8 trash;
+
+       return __adc12138_start_conv(adc, channel, &trash, 1);
+}
+
+static int adc12138_start_and_read_conv(struct adc12138 *adc,
+                                       struct iio_chan_spec const *channel,
+                                       __be16 *data)
+{
+       return __adc12138_start_conv(adc, channel, data, 2);
+}
+
+static int adc12138_read_conv_data(struct adc12138 *adc, __be16 *value)
+{
+       /* Issue a read status instruction and read previous conversion data */
+       return adc12138_mode_programming(adc, ADC12138_MODE_READ_STATUS,
+                                        value, sizeof(*value));
+}
+
+static int adc12138_wait_eoc(struct adc12138 *adc, unsigned long timeout)
+{
+       if (!wait_for_completion_timeout(&adc->complete, timeout))
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
+static int adc12138_adc_conversion(struct adc12138 *adc,
+                                  struct iio_chan_spec const *channel,
+                                  __be16 *value)
+{
+       int ret;
+
+       reinit_completion(&adc->complete);
+
+       ret = adc12138_start_conv(adc, channel);
+       if (ret)
+               return ret;
+
+       ret = adc12138_wait_eoc(adc, msecs_to_jiffies(100));
+       if (ret)
+               return ret;
+
+       return adc12138_read_conv_data(adc, value);
+}
+
+static int adc12138_read_raw(struct iio_dev *iio,
+                            struct iio_chan_spec const *channel, int *value,
+                            int *shift, long mask)
+{
+       struct adc12138 *adc = iio_priv(iio);
+       int ret;
+       __be16 data;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+               mutex_lock(&adc->lock);
+               ret = adc12138_adc_conversion(adc, channel, &data);
+               mutex_unlock(&adc->lock);
+               if (ret)
+                       return ret;
+
+               *value = sign_extend32(be16_to_cpu(data) >> 3, 12);
+
+               return IIO_VAL_INT;
+       case IIO_CHAN_INFO_SCALE:
+               ret = regulator_get_voltage(adc->vref_p);
+               if (ret < 0)
+                       return ret;
+               *value = ret;
+
+               if (!IS_ERR(adc->vref_n)) {
+                       ret = regulator_get_voltage(adc->vref_n);
+                       if (ret < 0)
+                               return ret;
+                       *value -= ret;
+               }
+
+               /* convert regulator output voltage to mV */
+               *value /= 1000;
+               *shift = channel->scan_type.realbits - 1;
+
+               return IIO_VAL_FRACTIONAL_LOG2;
+       case IIO_CHAN_INFO_OFFSET:
+               if (!IS_ERR(adc->vref_n)) {
+                       *value = regulator_get_voltage(adc->vref_n);
+                       if (*value < 0)
+                               return *value;
+               } else {
+                       *value = 0;
+               }
+
+               /* convert regulator output voltage to mV */
+               *value /= 1000;
+
+               return IIO_VAL_INT;
+       }
+
+       return -EINVAL;
+}
+
+static const struct iio_info adc12138_info = {
+       .read_raw = adc12138_read_raw,
+       .driver_module = THIS_MODULE,
+};
+
+static int adc12138_init(struct adc12138 *adc)
+{
+       int ret;
+       int status;
+       u8 mode;
+       u8 trash;
+
+       reinit_completion(&adc->complete);
+
+       ret = adc12138_mode_programming(adc, ADC12138_MODE_AUTO_CAL, &trash, 1);
+       if (ret)
+               return ret;
+
+       /* data output at this time has no significance */
+       status = adc12138_read_status(adc);
+       if (status < 0)
+               return status;
+
+       adc12138_wait_eoc(adc, msecs_to_jiffies(100));
+
+       status = adc12138_read_status(adc);
+       if (status & ADC12138_STATUS_CAL) {
+               dev_warn(&adc->spi->dev,
+                       "Auto Cal sequence is still in progress: %#x\n",
+                       status);
+               return -EIO;
+       }
+
+       switch (adc->acquisition_time) {
+       case 6:
+               mode = ADC12138_MODE_ACQUISITION_TIME_6;
+               break;
+       case 10:
+               mode = ADC12138_MODE_ACQUISITION_TIME_10;
+               break;
+       case 18:
+               mode = ADC12138_MODE_ACQUISITION_TIME_18;
+               break;
+       case 34:
+               mode = ADC12138_MODE_ACQUISITION_TIME_34;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return adc12138_mode_programming(adc, mode, &trash, 1);
+}
+
+static irqreturn_t adc12138_trigger_handler(int irq, void *p)
+{
+       struct iio_poll_func *pf = p;
+       struct iio_dev *indio_dev = pf->indio_dev;
+       struct adc12138 *adc = iio_priv(indio_dev);
+       __be16 data[20] = { }; /* 16x 2 bytes ADC data + 8 bytes timestamp */
+       __be16 trash;
+       int ret;
+       int scan_index;
+       int i = 0;
+
+       mutex_lock(&adc->lock);
+
+       for_each_set_bit(scan_index, indio_dev->active_scan_mask,
+                        indio_dev->masklength) {
+               const struct iio_chan_spec *scan_chan =
+                               &indio_dev->channels[scan_index];
+
+               reinit_completion(&adc->complete);
+
+               ret = adc12138_start_and_read_conv(adc, scan_chan,
+                                                  i ? &data[i - 1] : &trash);
+               if (ret) {
+                       dev_warn(&adc->spi->dev,
+                                "failed to start conversion\n");
+                       goto out;
+               }
+
+               ret = adc12138_wait_eoc(adc, msecs_to_jiffies(100));
+               if (ret) {
+                       dev_warn(&adc->spi->dev, "wait eoc timeout\n");
+                       goto out;
+               }
+
+               i++;
+       }
+
+       if (i) {
+               ret = adc12138_read_conv_data(adc, &data[i - 1]);
+               if (ret) {
+                       dev_warn(&adc->spi->dev,
+                                "failed to get conversion data\n");
+                       goto out;
+               }
+       }
+
+       iio_push_to_buffers_with_timestamp(indio_dev, data,
+                                          iio_get_time_ns(indio_dev));
+out:
+       mutex_unlock(&adc->lock);
+
+       iio_trigger_notify_done(indio_dev->trig);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t adc12138_eoc_handler(int irq, void *p)
+{
+       struct iio_dev *indio_dev = p;
+       struct adc12138 *adc = iio_priv(indio_dev);
+
+       complete(&adc->complete);
+
+       return IRQ_HANDLED;
+}
+
+static int adc12138_probe(struct spi_device *spi)
+{
+       struct iio_dev *indio_dev;
+       struct adc12138 *adc;
+       int ret;
+
+       indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc));
+       if (!indio_dev)
+               return -ENOMEM;
+
+       adc = iio_priv(indio_dev);
+       adc->spi = spi;
+       adc->id = spi_get_device_id(spi)->driver_data;
+       mutex_init(&adc->lock);
+       init_completion(&adc->complete);
+
+       indio_dev->name = spi_get_device_id(spi)->name;
+       indio_dev->dev.parent = &spi->dev;
+       indio_dev->info = &adc12138_info;
+       indio_dev->modes = INDIO_DIRECT_MODE;
+
+       switch (adc->id) {
+       case adc12130:
+       case adc12132:
+               indio_dev->channels = adc12132_channels;
+               indio_dev->num_channels = ARRAY_SIZE(adc12132_channels);
+               break;
+       case adc12138:
+               indio_dev->channels = adc12138_channels;
+               indio_dev->num_channels = ARRAY_SIZE(adc12138_channels);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       ret = of_property_read_u32(spi->dev.of_node, "ti,acquisition-time",
+                                  &adc->acquisition_time);
+       if (ret)
+               adc->acquisition_time = 10;
+
+       adc->cclk = devm_clk_get(&spi->dev, NULL);
+       if (IS_ERR(adc->cclk))
+               return PTR_ERR(adc->cclk);
+
+       adc->vref_p = devm_regulator_get(&spi->dev, "vref-p");
+       if (IS_ERR(adc->vref_p))
+               return PTR_ERR(adc->vref_p);
+
+       adc->vref_n = devm_regulator_get_optional(&spi->dev, "vref-n");
+       if (IS_ERR(adc->vref_n)) {
+               /*
+                * Assume vref_n is 0V if an optional regulator is not
+                * specified, otherwise return the error code.
+                */
+               ret = PTR_ERR(adc->vref_n);
+               if (ret != -ENODEV)
+                       return ret;
+       }
+
+       ret = devm_request_irq(&spi->dev, spi->irq, adc12138_eoc_handler,
+                              IRQF_TRIGGER_RISING, indio_dev->name, indio_dev);
+       if (ret)
+               return ret;
+
+       ret = clk_prepare_enable(adc->cclk);
+       if (ret)
+               return ret;
+
+       ret = regulator_enable(adc->vref_p);
+       if (ret)
+               goto err_clk_disable;
+
+       if (!IS_ERR(adc->vref_n)) {
+               ret = regulator_enable(adc->vref_n);
+               if (ret)
+                       goto err_vref_p_disable;
+       }
+
+       ret = adc12138_init(adc);
+       if (ret)
+               goto err_vref_n_disable;
+
+       spi_set_drvdata(spi, indio_dev);
+
+       ret = iio_triggered_buffer_setup(indio_dev, NULL,
+                                        adc12138_trigger_handler, NULL);
+       if (ret)
+               goto err_vref_n_disable;
+
+       ret = iio_device_register(indio_dev);
+       if (ret)
+               goto err_buffer_cleanup;
+
+       return 0;
+err_buffer_cleanup:
+       iio_triggered_buffer_cleanup(indio_dev);
+err_vref_n_disable:
+       if (!IS_ERR(adc->vref_n))
+               regulator_disable(adc->vref_n);
+err_vref_p_disable:
+       regulator_disable(adc->vref_p);
+err_clk_disable:
+       clk_disable_unprepare(adc->cclk);
+
+       return ret;
+}
+
+static int adc12138_remove(struct spi_device *spi)
+{
+       struct iio_dev *indio_dev = spi_get_drvdata(spi);
+       struct adc12138 *adc = iio_priv(indio_dev);
+
+       iio_device_unregister(indio_dev);
+       iio_triggered_buffer_cleanup(indio_dev);
+       if (!IS_ERR(adc->vref_n))
+               regulator_disable(adc->vref_n);
+       regulator_disable(adc->vref_p);
+       clk_disable_unprepare(adc->cclk);
+
+       return 0;
+}
+
+#ifdef CONFIG_OF
+
+static const struct of_device_id adc12138_dt_ids[] = {
+       { .compatible = "ti,adc12130", },
+       { .compatible = "ti,adc12132", },
+       { .compatible = "ti,adc12138", },
+       {}
+};
+MODULE_DEVICE_TABLE(of, adc12138_dt_ids);
+
+#endif
+
+static const struct spi_device_id adc12138_id[] = {
+       { "adc12130", adc12130 },
+       { "adc12132", adc12132 },
+       { "adc12138", adc12138 },
+       {}
+};
+MODULE_DEVICE_TABLE(spi, adc12138_id);
+
+static struct spi_driver adc12138_driver = {
+       .driver = {
+               .name = "adc12138",
+               .of_match_table = of_match_ptr(adc12138_dt_ids),
+       },
+       .probe = adc12138_probe,
+       .remove = adc12138_remove,
+       .id_table = adc12138_id,
+};
+module_spi_driver(adc12138_driver);
+
+MODULE_AUTHOR("Akinobu Mita <akinobu.mita@gmail.com>");
+MODULE_DESCRIPTION("ADC12130/ADC12132/ADC12138 driver");
+MODULE_LICENSE("GPL v2");
index 066abaf..cde6f13 100644 (file)
@@ -522,6 +522,7 @@ static int ads1015_get_channels_config_of(struct i2c_client *client)
                        if (pga > 6) {
                                dev_err(&client->dev, "invalid gain on %s\n",
                                        node->full_name);
+                               of_node_put(node);
                                return -EINVAL;
                        }
                }
@@ -532,6 +533,7 @@ static int ads1015_get_channels_config_of(struct i2c_client *client)
                                dev_err(&client->dev,
                                        "invalid data_rate on %s\n",
                                        node->full_name);
+                               of_node_put(node);
                                return -EINVAL;
                        }
                }
index c400439..4a16349 100644 (file)
@@ -438,7 +438,7 @@ static int ads8688_probe(struct spi_device *spi)
        return 0;
 
 error_out:
-       if (!IS_ERR_OR_NULL(st->reg))
+       if (!IS_ERR(st->reg))
                regulator_disable(st->reg);
 
        return ret;
@@ -451,7 +451,7 @@ static int ads8688_remove(struct spi_device *spi)
 
        iio_device_unregister(indio_dev);
 
-       if (!IS_ERR_OR_NULL(st->reg))
+       if (!IS_ERR(st->reg))
                regulator_disable(st->reg);
 
        return 0;
index 4b2858b..d3db1fc 100644 (file)
@@ -98,6 +98,48 @@ void iio_triggered_buffer_cleanup(struct iio_dev *indio_dev)
 }
 EXPORT_SYMBOL(iio_triggered_buffer_cleanup);
 
+static void devm_iio_triggered_buffer_clean(struct device *dev, void *res)
+{
+       iio_triggered_buffer_cleanup(*(struct iio_dev **)res);
+}
+
+int devm_iio_triggered_buffer_setup(struct device *dev,
+                                   struct iio_dev *indio_dev,
+                                   irqreturn_t (*h)(int irq, void *p),
+                                   irqreturn_t (*thread)(int irq, void *p),
+                                   const struct iio_buffer_setup_ops *ops)
+{
+       struct iio_dev **ptr;
+       int ret;
+
+       ptr = devres_alloc(devm_iio_triggered_buffer_clean, sizeof(*ptr),
+                          GFP_KERNEL);
+       if (!ptr)
+               return -ENOMEM;
+
+       *ptr = indio_dev;
+
+       ret = iio_triggered_buffer_setup(indio_dev, h, thread, ops);
+       if (!ret)
+               devres_add(dev, ptr);
+       else
+               devres_free(ptr);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(devm_iio_triggered_buffer_setup);
+
+void devm_iio_triggered_buffer_cleanup(struct device *dev,
+                                      struct iio_dev *indio_dev)
+{
+       int rc;
+
+       rc = devres_release(dev, devm_iio_triggered_buffer_clean,
+                           devm_iio_device_match, indio_dev);
+       WARN_ON(rc);
+}
+EXPORT_SYMBOL_GPL(devm_iio_triggered_buffer_cleanup);
+
 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
 MODULE_DESCRIPTION("IIO helper functions for setting up triggered buffers");
 MODULE_LICENSE("GPL");
index 652649d..8e0e441 100644 (file)
 #include <linux/mutex.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 
 #define VZ89X_REG_MEASUREMENT          0x09
-#define VZ89X_REG_MEASUREMENT_SIZE     6
+#define VZ89X_REG_MEASUREMENT_RD_SIZE  6
+#define VZ89X_REG_MEASUREMENT_WR_SIZE  3
 
 #define VZ89X_VOC_CO2_IDX              0
 #define VZ89X_VOC_SHORT_IDX            1
 #define VZ89X_VOC_TVOC_IDX             2
 #define VZ89X_VOC_RESISTANCE_IDX       3
 
+#define VZ89TE_REG_MEASUREMENT         0x0c
+#define VZ89TE_REG_MEASUREMENT_RD_SIZE 7
+#define VZ89TE_REG_MEASUREMENT_WR_SIZE 6
+
+#define VZ89TE_VOC_TVOC_IDX            0
+#define VZ89TE_VOC_CO2_IDX             1
+#define VZ89TE_VOC_RESISTANCE_IDX      2
+
+enum {
+       VZ89X,
+       VZ89TE,
+};
+
+struct vz89x_chip_data;
+
 struct vz89x_data {
        struct i2c_client *client;
+       const struct vz89x_chip_data *chip;
        struct mutex lock;
        int (*xfer)(struct vz89x_data *data, u8 cmd);
 
+       bool is_valid;
        unsigned long last_update;
-       u8 buffer[VZ89X_REG_MEASUREMENT_SIZE];
+       u8 buffer[VZ89TE_REG_MEASUREMENT_RD_SIZE];
+};
+
+struct vz89x_chip_data {
+       bool (*valid)(struct vz89x_data *data);
+       const struct iio_chan_spec *channels;
+       u8 num_channels;
+
+       u8 cmd;
+       u8 read_size;
+       u8 write_size;
 };
 
 static const struct iio_chan_spec vz89x_channels[] = {
@@ -70,6 +100,40 @@ static const struct iio_chan_spec vz89x_channels[] = {
                .info_mask_separate =
                        BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
                .address = VZ89X_VOC_RESISTANCE_IDX,
+               .scan_index = -1,
+               .scan_type = {
+                       .endianness = IIO_LE,
+               },
+       },
+};
+
+static const struct iio_chan_spec vz89te_channels[] = {
+       {
+               .type = IIO_CONCENTRATION,
+               .channel2 = IIO_MOD_VOC,
+               .modified = 1,
+               .info_mask_separate =
+                       BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_RAW),
+               .address = VZ89TE_VOC_TVOC_IDX,
+       },
+
+       {
+               .type = IIO_CONCENTRATION,
+               .channel2 = IIO_MOD_CO2,
+               .modified = 1,
+               .info_mask_separate =
+                       BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_RAW),
+               .address = VZ89TE_VOC_CO2_IDX,
+       },
+       {
+               .type = IIO_RESISTANCE,
+               .info_mask_separate =
+                       BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
+               .address = VZ89TE_VOC_RESISTANCE_IDX,
+               .scan_index = -1,
+               .scan_type = {
+                       .endianness = IIO_BE,
+               },
        },
 };
 
@@ -93,29 +157,45 @@ static const struct attribute_group vz89x_attrs_group = {
  * always zero, and by also confirming the VOC_short isn't zero.
  */
 
-static int vz89x_measurement_is_valid(struct vz89x_data *data)
+static bool vz89x_measurement_is_valid(struct vz89x_data *data)
 {
        if (data->buffer[VZ89X_VOC_SHORT_IDX] == 0)
-               return 1;
+               return true;
 
-       return !!(data->buffer[VZ89X_REG_MEASUREMENT_SIZE - 1] > 0);
+       return !!(data->buffer[data->chip->read_size - 1] > 0);
+}
+
+/* VZ89TE device has a modified CRC-8 two complement check */
+static bool vz89te_measurement_is_valid(struct vz89x_data *data)
+{
+       u8 crc = 0;
+       int i, sum = 0;
+
+       for (i = 0; i < (data->chip->read_size - 1); i++) {
+               sum = crc + data->buffer[i];
+               crc = sum;
+               crc += sum / 256;
+       }
+
+       return !((0xff - crc) == data->buffer[data->chip->read_size - 1]);
 }
 
 static int vz89x_i2c_xfer(struct vz89x_data *data, u8 cmd)
 {
+       const struct vz89x_chip_data *chip = data->chip;
        struct i2c_client *client = data->client;
        struct i2c_msg msg[2];
        int ret;
-       u8 buf[3] = { cmd, 0, 0};
+       u8 buf[6] = { cmd, 0, 0, 0, 0, 0xf3 };
 
        msg[0].addr = client->addr;
        msg[0].flags = client->flags;
-       msg[0].len = 3;
+       msg[0].len = chip->write_size;
        msg[0].buf  = (char *) &buf;
 
        msg[1].addr = client->addr;
        msg[1].flags = client->flags | I2C_M_RD;
-       msg[1].len = VZ89X_REG_MEASUREMENT_SIZE;
+       msg[1].len = chip->read_size;
        msg[1].buf = (char *) &data->buffer;
 
        ret = i2c_transfer(client->adapter, msg, 2);
@@ -133,7 +213,7 @@ static int vz89x_smbus_xfer(struct vz89x_data *data, u8 cmd)
        if (ret < 0)
                return ret;
 
-       for (i = 0; i < VZ89X_REG_MEASUREMENT_SIZE; i++) {
+       for (i = 0; i < data->chip->read_size; i++) {
                ret = i2c_smbus_read_byte(client);
                if (ret < 0)
                        return ret;
@@ -145,30 +225,47 @@ static int vz89x_smbus_xfer(struct vz89x_data *data, u8 cmd)
 
 static int vz89x_get_measurement(struct vz89x_data *data)
 {
+       const struct vz89x_chip_data *chip = data->chip;
        int ret;
 
        /* sensor can only be polled once a second max per datasheet */
        if (!time_after(jiffies, data->last_update + HZ))
-               return 0;
+               return data->is_valid ? 0 : -EAGAIN;
+
+       data->is_valid = false;
+       data->last_update = jiffies;
 
-       ret = data->xfer(data, VZ89X_REG_MEASUREMENT);
+       ret = data->xfer(data, chip->cmd);
        if (ret < 0)
                return ret;
 
-       ret = vz89x_measurement_is_valid(data);
+       ret = chip->valid(data);
        if (ret)
                return -EAGAIN;
 
-       data->last_update = jiffies;
+       data->is_valid = true;
 
        return 0;
 }
 
-static int vz89x_get_resistance_reading(struct vz89x_data *data)
+static int vz89x_get_resistance_reading(struct vz89x_data *data,
+                                       struct iio_chan_spec const *chan,
+                                       int *val)
 {
-       u8 *buf = &data->buffer[VZ89X_VOC_RESISTANCE_IDX];
+       u8 *tmp = (u8 *) &data->buffer[chan->address];
 
-       return buf[0] | (buf[1] << 8);
+       switch (chan->scan_type.endianness) {
+       case IIO_LE:
+               *val = le32_to_cpup((__le32 *) tmp) & GENMASK(23, 0);
+               break;
+       case IIO_BE:
+               *val = be32_to_cpup((__be32 *) tmp) >> 8;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
 }
 
 static int vz89x_read_raw(struct iio_dev *indio_dev,
@@ -187,15 +284,15 @@ static int vz89x_read_raw(struct iio_dev *indio_dev,
                if (ret)
                        return ret;
 
-               switch (chan->address) {
-               case VZ89X_VOC_CO2_IDX:
-               case VZ89X_VOC_SHORT_IDX:
-               case VZ89X_VOC_TVOC_IDX:
+               switch (chan->type) {
+               case IIO_CONCENTRATION:
                        *val = data->buffer[chan->address];
                        return IIO_VAL_INT;
-               case VZ89X_VOC_RESISTANCE_IDX:
-                       *val = vz89x_get_resistance_reading(data);
-                       return IIO_VAL_INT;
+               case IIO_RESISTANCE:
+                       ret = vz89x_get_resistance_reading(data, chan, val);
+                       if (!ret)
+                               return IIO_VAL_INT;
+                       break;
                default:
                        return -EINVAL;
                }
@@ -210,12 +307,12 @@ static int vz89x_read_raw(struct iio_dev *indio_dev,
                }
                break;
        case IIO_CHAN_INFO_OFFSET:
-               switch (chan->address) {
-               case VZ89X_VOC_CO2_IDX:
+               switch (chan->channel2) {
+               case IIO_MOD_CO2:
                        *val = 44;
                        *val2 = 250000;
                        return IIO_VAL_INT_PLUS_MICRO;
-               case VZ89X_VOC_TVOC_IDX:
+               case IIO_MOD_VOC:
                        *val = -13;
                        return IIO_VAL_INT;
                default:
@@ -232,11 +329,43 @@ static const struct iio_info vz89x_info = {
        .driver_module  = THIS_MODULE,
 };
 
+static const struct vz89x_chip_data vz89x_chips[] = {
+       {
+               .valid = vz89x_measurement_is_valid,
+
+               .cmd = VZ89X_REG_MEASUREMENT,
+               .read_size = VZ89X_REG_MEASUREMENT_RD_SIZE,
+               .write_size = VZ89X_REG_MEASUREMENT_WR_SIZE,
+
+               .channels = vz89x_channels,
+               .num_channels = ARRAY_SIZE(vz89x_channels),
+       },
+       {
+               .valid = vz89te_measurement_is_valid,
+
+               .cmd = VZ89TE_REG_MEASUREMENT,
+               .read_size = VZ89TE_REG_MEASUREMENT_RD_SIZE,
+               .write_size = VZ89TE_REG_MEASUREMENT_WR_SIZE,
+
+               .channels = vz89te_channels,
+               .num_channels = ARRAY_SIZE(vz89te_channels),
+       },
+};
+
+static const struct of_device_id vz89x_dt_ids[] = {
+       { .compatible = "sgx,vz89x", .data = (void *) VZ89X },
+       { .compatible = "sgx,vz89te", .data = (void *) VZ89TE },
+       { }
+};
+MODULE_DEVICE_TABLE(of, vz89x_dt_ids);
+
 static int vz89x_probe(struct i2c_client *client,
                       const struct i2c_device_id *id)
 {
        struct iio_dev *indio_dev;
        struct vz89x_data *data;
+       const struct of_device_id *of_id;
+       int chip_id;
 
        indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
        if (!indio_dev)
@@ -251,8 +380,15 @@ static int vz89x_probe(struct i2c_client *client,
        else
                return -EOPNOTSUPP;
 
+       of_id = of_match_device(vz89x_dt_ids, &client->dev);
+       if (!of_id)
+               chip_id = id->driver_data;
+       else
+               chip_id = (unsigned long)of_id->data;
+
        i2c_set_clientdata(client, indio_dev);
        data->client = client;
+       data->chip = &vz89x_chips[chip_id];
        data->last_update = jiffies - HZ;
        mutex_init(&data->lock);
 
@@ -261,24 +397,19 @@ static int vz89x_probe(struct i2c_client *client,
        indio_dev->name = dev_name(&client->dev);
        indio_dev->modes = INDIO_DIRECT_MODE;
 
-       indio_dev->channels = vz89x_channels;
-       indio_dev->num_channels = ARRAY_SIZE(vz89x_channels);
+       indio_dev->channels = data->chip->channels;
+       indio_dev->num_channels = data->chip->num_channels;
 
        return devm_iio_device_register(&client->dev, indio_dev);
 }
 
 static const struct i2c_device_id vz89x_id[] = {
-       { "vz89x", 0 },
+       { "vz89x", VZ89X },
+       { "vz89te", VZ89TE },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, vz89x_id);
 
-static const struct of_device_id vz89x_dt_ids[] = {
-       { .compatible = "sgx,vz89x" },
-       { }
-};
-MODULE_DEVICE_TABLE(of, vz89x_dt_ids);
-
 static struct i2c_driver vz89x_driver = {
        .driver = {
                .name   = "vz89x",
index 5264ed6..a3cce3a 100644 (file)
@@ -199,8 +199,7 @@ error_ret:
 }
 EXPORT_SYMBOL(hid_sensor_setup_trigger);
 
-#ifdef CONFIG_PM
-static int hid_sensor_suspend(struct device *dev)
+static int __maybe_unused hid_sensor_suspend(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct iio_dev *indio_dev = platform_get_drvdata(pdev);
@@ -209,7 +208,7 @@ static int hid_sensor_suspend(struct device *dev)
        return _hid_sensor_power_state(attrb, false);
 }
 
-static int hid_sensor_resume(struct device *dev)
+static int __maybe_unused hid_sensor_resume(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct iio_dev *indio_dev = platform_get_drvdata(pdev);
@@ -218,7 +217,7 @@ static int hid_sensor_resume(struct device *dev)
        return 0;
 }
 
-static int hid_sensor_runtime_resume(struct device *dev)
+static int __maybe_unused hid_sensor_runtime_resume(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct iio_dev *indio_dev = platform_get_drvdata(pdev);
@@ -226,8 +225,6 @@ static int hid_sensor_runtime_resume(struct device *dev)
        return _hid_sensor_power_state(attrb, true);
 }
 
-#endif
-
 const struct dev_pm_ops hid_sensor_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(hid_sensor_suspend, hid_sensor_resume)
        SET_RUNTIME_PM_OPS(hid_sensor_suspend,
index d06e728..fe7775b 100644 (file)
@@ -63,7 +63,7 @@ irqreturn_t st_sensors_trigger_handler(int irq, void *p)
         * the hardware trigger) and the hw_timestamp may get updated.
         * By storing it in a local variable first, we are safe.
         */
-       if (sdata->hw_irq_trigger)
+       if (iio_trigger_using_own(indio_dev))
                timestamp = sdata->hw_timestamp;
        else
                timestamp = iio_get_time_ns(indio_dev);
index 2d5282e..285a64a 100644 (file)
@@ -234,39 +234,35 @@ int st_sensors_power_enable(struct iio_dev *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");
-                       return err;
-               }
-       } else {
-               err = PTR_ERR(pdata->vdd);
-               if (err != -ENODEV)
-                       return err;
+       pdata->vdd = devm_regulator_get(indio_dev->dev.parent, "vdd");
+       if (IS_ERR(pdata->vdd)) {
+               dev_err(&indio_dev->dev, "unable to get Vdd supply\n");
+               return PTR_ERR(pdata->vdd);
+       }
+       err = regulator_enable(pdata->vdd);
+       if (err != 0) {
+               dev_warn(&indio_dev->dev,
+                        "Failed to enable specified Vdd supply\n");
+               return err;
        }
 
-       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");
-                       goto st_sensors_disable_vdd;
-               }
-       } else {
+       pdata->vdd_io = devm_regulator_get(indio_dev->dev.parent, "vddio");
+       if (IS_ERR(pdata->vdd_io)) {
+               dev_err(&indio_dev->dev, "unable to get Vdd_IO supply\n");
                err = PTR_ERR(pdata->vdd_io);
-               if (err != -ENODEV)
-                       goto st_sensors_disable_vdd;
+               goto st_sensors_disable_vdd;
+       }
+       err = regulator_enable(pdata->vdd_io);
+       if (err != 0) {
+               dev_warn(&indio_dev->dev,
+                        "Failed to enable specified Vdd_IO supply\n");
+               goto st_sensors_disable_vdd;
        }
 
        return 0;
 
 st_sensors_disable_vdd:
-       if (!IS_ERR_OR_NULL(pdata->vdd))
-               regulator_disable(pdata->vdd);
+       regulator_disable(pdata->vdd);
        return err;
 }
 EXPORT_SYMBOL(st_sensors_power_enable);
@@ -275,11 +271,8 @@ void st_sensors_power_disable(struct iio_dev *indio_dev)
 {
        struct st_sensor_data *pdata = iio_priv(indio_dev);
 
-       if (!IS_ERR_OR_NULL(pdata->vdd))
-               regulator_disable(pdata->vdd);
-
-       if (!IS_ERR_OR_NULL(pdata->vdd_io))
-               regulator_disable(pdata->vdd_io);
+       regulator_disable(pdata->vdd);
+       regulator_disable(pdata->vdd_io);
 }
 EXPORT_SYMBOL(st_sensors_power_disable);
 
index e66f12e..fa73e67 100644 (file)
@@ -66,7 +66,7 @@ static int st_sensors_new_samples_available(struct iio_dev *indio_dev,
  * @irq: irq number
  * @p: private handler data
  */
-irqreturn_t st_sensors_irq_handler(int irq, void *p)
+static irqreturn_t st_sensors_irq_handler(int irq, void *p)
 {
        struct iio_trigger *trig = p;
        struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
@@ -82,7 +82,7 @@ irqreturn_t st_sensors_irq_handler(int irq, void *p)
  * @irq: irq number
  * @p: private handler data
  */
-irqreturn_t st_sensors_irq_thread(int irq, void *p)
+static irqreturn_t st_sensors_irq_thread(int irq, void *p)
 {
        struct iio_trigger *trig = p;
        struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
index b9f0442..120b244 100644 (file)
@@ -190,6 +190,16 @@ config CIO_DAC
          base port addresses for the devices may be configured via the base
          array module parameter.
 
+config AD8801
+       tristate "Analog Devices AD8801/AD8803 DAC driver"
+       depends on SPI_MASTER
+       help
+         Say yes here to build support for Analog Devices AD8801, AD8803 Digital to
+         Analog Converters (DAC).
+
+         To compile this driver as a module choose M here: the module will be called
+         ad8801.
+
 config LPC18XX_DAC
        tristate "NXP LPC18xx DAC driver"
        depends on ARCH_LPC18XX || COMPILE_TEST
@@ -254,16 +264,6 @@ config MCP4922
          To compile this driver as a module, choose M here: the module
          will be called mcp4922.
 
-config STX104
-       tristate "Apex Embedded Systems STX104 DAC driver"
-       depends on X86 && ISA_BUS_API
-       select GPIOLIB
-       help
-         Say yes here to build support for the 2-channel DAC and GPIO on the
-         Apex Embedded Systems STX104 integrated analog PC/104 card. The base
-         port addresses for the devices may be configured via the base array
-         module parameter.
-
 config VF610_DAC
        tristate "Vybrid vf610 DAC driver"
        depends on OF
index b1a1206..27642bb 100644 (file)
@@ -20,6 +20,7 @@ obj-$(CONFIG_AD5764) += ad5764.o
 obj-$(CONFIG_AD5791) += ad5791.o
 obj-$(CONFIG_AD5686) += ad5686.o
 obj-$(CONFIG_AD7303) += ad7303.o
+obj-$(CONFIG_AD8801) += ad8801.o
 obj-$(CONFIG_CIO_DAC) += cio-dac.o
 obj-$(CONFIG_LPC18XX_DAC) += lpc18xx_dac.o
 obj-$(CONFIG_M62332) += m62332.o
@@ -27,5 +28,4 @@ obj-$(CONFIG_MAX517) += max517.o
 obj-$(CONFIG_MAX5821) += max5821.o
 obj-$(CONFIG_MCP4725) += mcp4725.o
 obj-$(CONFIG_MCP4922) += mcp4922.o
-obj-$(CONFIG_STX104) += stx104.o
 obj-$(CONFIG_VF610_DAC) += vf610_dac.o
index 0fde593..5f79682 100644 (file)
@@ -655,7 +655,7 @@ static struct ad5755_platform_data *ad5755_parse_dt(struct device *dev)
 
        devnr = 0;
        for_each_child_of_node(np, pp) {
-               if (devnr > AD5755_NUM_CHANNELS) {
+               if (devnr >= AD5755_NUM_CHANNELS) {
                        dev_err(dev,
                                "There is to many channels defined in DT\n");
                        goto error_out;
diff --git a/drivers/iio/dac/ad8801.c b/drivers/iio/dac/ad8801.c
new file mode 100644 (file)
index 0000000..f06faa1
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * IIO DAC driver for Analog Devices AD8801 DAC
+ *
+ * Copyright (C) 2016 Gwenhael Goavec-Merou
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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/iio/iio.h>
+#include <linux/module.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spi/spi.h>
+#include <linux/sysfs.h>
+
+#define AD8801_CFG_ADDR_OFFSET 8
+
+enum ad8801_device_ids {
+       ID_AD8801,
+       ID_AD8803,
+};
+
+struct ad8801_state {
+       struct spi_device *spi;
+       unsigned char dac_cache[8]; /* Value write on each channel */
+       unsigned int vrefh_mv;
+       unsigned int vrefl_mv;
+       struct regulator *vrefh_reg;
+       struct regulator *vrefl_reg;
+
+       __be16 data ____cacheline_aligned;
+};
+
+static int ad8801_spi_write(struct ad8801_state *state,
+       u8 channel, unsigned char value)
+{
+       state->data = cpu_to_be16((channel << AD8801_CFG_ADDR_OFFSET) | value);
+       return spi_write(state->spi, &state->data, sizeof(state->data));
+}
+
+static int ad8801_write_raw(struct iio_dev *indio_dev,
+       struct iio_chan_spec const *chan, int val, int val2, long mask)
+{
+       struct ad8801_state *state = iio_priv(indio_dev);
+       int ret;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+               if (val >= 256 || val < 0)
+                       return -EINVAL;
+
+               ret = ad8801_spi_write(state, chan->channel, val);
+               if (ret == 0)
+                       state->dac_cache[chan->channel] = val;
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+static int ad8801_read_raw(struct iio_dev *indio_dev,
+       struct iio_chan_spec const *chan, int *val, int *val2, long info)
+{
+       struct ad8801_state *state = iio_priv(indio_dev);
+
+       switch (info) {
+       case IIO_CHAN_INFO_RAW:
+               *val = state->dac_cache[chan->channel];
+               return IIO_VAL_INT;
+       case IIO_CHAN_INFO_SCALE:
+               *val = state->vrefh_mv - state->vrefl_mv;
+               *val2 = 8;
+               return IIO_VAL_FRACTIONAL_LOG2;
+       case IIO_CHAN_INFO_OFFSET:
+               *val = state->vrefl_mv;
+               return IIO_VAL_INT;
+       default:
+               return -EINVAL;
+       }
+
+       return -EINVAL;
+}
+
+static const struct iio_info ad8801_info = {
+       .read_raw = ad8801_read_raw,
+       .write_raw = ad8801_write_raw,
+       .driver_module = THIS_MODULE,
+};
+
+#define AD8801_CHANNEL(chan) {         \
+       .type = IIO_VOLTAGE,                    \
+       .indexed = 1,                           \
+       .output = 1,                            \
+       .channel = chan,                        \
+       .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+       .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
+               BIT(IIO_CHAN_INFO_OFFSET), \
+}
+
+static const struct iio_chan_spec ad8801_channels[] = {
+       AD8801_CHANNEL(0),
+       AD8801_CHANNEL(1),
+       AD8801_CHANNEL(2),
+       AD8801_CHANNEL(3),
+       AD8801_CHANNEL(4),
+       AD8801_CHANNEL(5),
+       AD8801_CHANNEL(6),
+       AD8801_CHANNEL(7),
+};
+
+static int ad8801_probe(struct spi_device *spi)
+{
+       struct iio_dev *indio_dev;
+       struct ad8801_state *state;
+       const struct spi_device_id *id;
+       int ret;
+
+       indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*state));
+       if (indio_dev == NULL)
+               return -ENOMEM;
+
+       state = iio_priv(indio_dev);
+       state->spi = spi;
+       id = spi_get_device_id(spi);
+
+       state->vrefh_reg = devm_regulator_get(&spi->dev, "vrefh");
+       if (IS_ERR(state->vrefh_reg)) {
+               dev_err(&spi->dev, "Vrefh regulator not specified\n");
+               return PTR_ERR(state->vrefh_reg);
+       }
+
+       ret = regulator_enable(state->vrefh_reg);
+       if (ret) {
+               dev_err(&spi->dev, "Failed to enable vrefh regulator: %d\n",
+                               ret);
+               return ret;
+       }
+
+       ret = regulator_get_voltage(state->vrefh_reg);
+       if (ret < 0) {
+               dev_err(&spi->dev, "Failed to read vrefh regulator: %d\n",
+                               ret);
+               goto error_disable_vrefh_reg;
+       }
+       state->vrefh_mv = ret / 1000;
+
+       if (id->driver_data == ID_AD8803) {
+               state->vrefl_reg = devm_regulator_get(&spi->dev, "vrefl");
+               if (IS_ERR(state->vrefl_reg)) {
+                       dev_err(&spi->dev, "Vrefl regulator not specified\n");
+                       ret = PTR_ERR(state->vrefl_reg);
+                       goto error_disable_vrefh_reg;
+               }
+
+               ret = regulator_enable(state->vrefl_reg);
+               if (ret) {
+                       dev_err(&spi->dev, "Failed to enable vrefl regulator: %d\n",
+                                       ret);
+                       goto error_disable_vrefh_reg;
+               }
+
+               ret = regulator_get_voltage(state->vrefl_reg);
+               if (ret < 0) {
+                       dev_err(&spi->dev, "Failed to read vrefl regulator: %d\n",
+                                       ret);
+                       goto error_disable_vrefl_reg;
+               }
+               state->vrefl_mv = ret / 1000;
+       } else {
+               state->vrefl_mv = 0;
+               state->vrefl_reg = NULL;
+       }
+
+       spi_set_drvdata(spi, indio_dev);
+       indio_dev->dev.parent = &spi->dev;
+       indio_dev->info = &ad8801_info;
+       indio_dev->modes = INDIO_DIRECT_MODE;
+       indio_dev->channels = ad8801_channels;
+       indio_dev->num_channels = ARRAY_SIZE(ad8801_channels);
+       indio_dev->name = id->name;
+
+       ret = iio_device_register(indio_dev);
+       if (ret) {
+               dev_err(&spi->dev, "Failed to register iio device: %d\n",
+                               ret);
+               goto error_disable_vrefl_reg;
+       }
+
+       return 0;
+
+error_disable_vrefl_reg:
+       if (state->vrefl_reg)
+               regulator_disable(state->vrefl_reg);
+error_disable_vrefh_reg:
+       regulator_disable(state->vrefh_reg);
+       return ret;
+}
+
+static int ad8801_remove(struct spi_device *spi)
+{
+       struct iio_dev *indio_dev = spi_get_drvdata(spi);
+       struct ad8801_state *state = iio_priv(indio_dev);
+
+       iio_device_unregister(indio_dev);
+       if (state->vrefl_reg)
+               regulator_disable(state->vrefl_reg);
+       regulator_disable(state->vrefh_reg);
+
+       return 0;
+}
+
+static const struct spi_device_id ad8801_ids[] = {
+       {"ad8801", ID_AD8801},
+       {"ad8803", ID_AD8803},
+       {}
+};
+MODULE_DEVICE_TABLE(spi, ad8801_ids);
+
+static struct spi_driver ad8801_driver = {
+       .driver = {
+               .name   = "ad8801",
+       },
+       .probe          = ad8801_probe,
+       .remove         = ad8801_remove,
+       .id_table       = ad8801_ids,
+};
+module_spi_driver(ad8801_driver);
+
+MODULE_AUTHOR("Gwenhael Goavec-Merou <gwenhael.goavec-merou@trabucayre.com>");
+MODULE_DESCRIPTION("Analog Devices AD8801/AD8803 DAC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/dac/stx104.c b/drivers/iio/dac/stx104.c
deleted file mode 100644 (file)
index bebbd00..0000000
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * DAC driver for the Apex Embedded Systems STX104
- * Copyright (C) 2016 William Breathitt Gray
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2, as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-#include <linux/bitops.h>
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <linux/gpio/driver.h>
-#include <linux/iio/iio.h>
-#include <linux/iio/types.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/isa.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/spinlock.h>
-
-#define STX104_NUM_CHAN 2
-
-#define STX104_CHAN(chan) {                            \
-       .type = IIO_VOLTAGE,                            \
-       .channel = chan,                                \
-       .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
-       .indexed = 1,                                   \
-       .output = 1                                     \
-}
-
-#define STX104_EXTENT 16
-
-static unsigned int base[max_num_isa_dev(STX104_EXTENT)];
-static unsigned int num_stx104;
-module_param_array(base, uint, &num_stx104, 0);
-MODULE_PARM_DESC(base, "Apex Embedded Systems STX104 base addresses");
-
-/**
- * struct stx104_iio - IIO device private data structure
- * @chan_out_states:   channels' output states
- * @base:              base port address of the IIO device
- */
-struct stx104_iio {
-       unsigned chan_out_states[STX104_NUM_CHAN];
-       unsigned base;
-};
-
-/**
- * struct stx104_gpio - GPIO device private data structure
- * @chip:      instance of the gpio_chip
- * @lock:      synchronization lock to prevent I/O race conditions
- * @base:      base port address of the GPIO device
- * @out_state: output bits state
- */
-struct stx104_gpio {
-       struct gpio_chip chip;
-       spinlock_t lock;
-       unsigned int base;
-       unsigned int out_state;
-};
-
-/**
- * struct stx104_dev - STX104 device private data structure
- * @indio_dev: IIO device
- * @chip:      instance of the gpio_chip
- */
-struct stx104_dev {
-       struct iio_dev *indio_dev;
-       struct gpio_chip *chip;
-};
-
-static int stx104_read_raw(struct iio_dev *indio_dev,
-       struct iio_chan_spec const *chan, int *val, int *val2, long mask)
-{
-       struct stx104_iio *const priv = iio_priv(indio_dev);
-
-       if (mask != IIO_CHAN_INFO_RAW)
-               return -EINVAL;
-
-       *val = priv->chan_out_states[chan->channel];
-
-       return IIO_VAL_INT;
-}
-
-static int stx104_write_raw(struct iio_dev *indio_dev,
-       struct iio_chan_spec const *chan, int val, int val2, long mask)
-{
-       struct stx104_iio *const priv = iio_priv(indio_dev);
-       const unsigned chan_addr_offset = 2 * chan->channel;
-
-       if (mask != IIO_CHAN_INFO_RAW)
-               return -EINVAL;
-
-       priv->chan_out_states[chan->channel] = val;
-       outw(val, priv->base + 4 + chan_addr_offset);
-
-       return 0;
-}
-
-static const struct iio_info stx104_info = {
-       .driver_module = THIS_MODULE,
-       .read_raw = stx104_read_raw,
-       .write_raw = stx104_write_raw
-};
-
-static const struct iio_chan_spec stx104_channels[STX104_NUM_CHAN] = {
-       STX104_CHAN(0),
-       STX104_CHAN(1)
-};
-
-static int stx104_gpio_get_direction(struct gpio_chip *chip,
-       unsigned int offset)
-{
-       /* GPIO 0-3 are input only, while the rest are output only */
-       if (offset < 4)
-               return 1;
-
-       return 0;
-}
-
-static int stx104_gpio_direction_input(struct gpio_chip *chip,
-       unsigned int offset)
-{
-       if (offset >= 4)
-               return -EINVAL;
-
-       return 0;
-}
-
-static int stx104_gpio_direction_output(struct gpio_chip *chip,
-       unsigned int offset, int value)
-{
-       if (offset < 4)
-               return -EINVAL;
-
-       chip->set(chip, offset, value);
-       return 0;
-}
-
-static int stx104_gpio_get(struct gpio_chip *chip, unsigned int offset)
-{
-       struct stx104_gpio *const stx104gpio = gpiochip_get_data(chip);
-
-       if (offset >= 4)
-               return -EINVAL;
-
-       return !!(inb(stx104gpio->base) & BIT(offset));
-}
-
-static void stx104_gpio_set(struct gpio_chip *chip, unsigned int offset,
-       int value)
-{
-       struct stx104_gpio *const stx104gpio = gpiochip_get_data(chip);
-       const unsigned int mask = BIT(offset) >> 4;
-       unsigned long flags;
-
-       if (offset < 4)
-               return;
-
-       spin_lock_irqsave(&stx104gpio->lock, flags);
-
-       if (value)
-               stx104gpio->out_state |= mask;
-       else
-               stx104gpio->out_state &= ~mask;
-
-       outb(stx104gpio->out_state, stx104gpio->base);
-
-       spin_unlock_irqrestore(&stx104gpio->lock, flags);
-}
-
-static int stx104_probe(struct device *dev, unsigned int id)
-{
-       struct iio_dev *indio_dev;
-       struct stx104_iio *priv;
-       struct stx104_gpio *stx104gpio;
-       struct stx104_dev *stx104dev;
-       int err;
-
-       indio_dev = devm_iio_device_alloc(dev, sizeof(*priv));
-       if (!indio_dev)
-               return -ENOMEM;
-
-       stx104gpio = devm_kzalloc(dev, sizeof(*stx104gpio), GFP_KERNEL);
-       if (!stx104gpio)
-               return -ENOMEM;
-
-       stx104dev = devm_kzalloc(dev, sizeof(*stx104dev), GFP_KERNEL);
-       if (!stx104dev)
-               return -ENOMEM;
-
-       if (!devm_request_region(dev, base[id], STX104_EXTENT,
-               dev_name(dev))) {
-               dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
-                       base[id], base[id] + STX104_EXTENT);
-               return -EBUSY;
-       }
-
-       indio_dev->info = &stx104_info;
-       indio_dev->modes = INDIO_DIRECT_MODE;
-       indio_dev->channels = stx104_channels;
-       indio_dev->num_channels = STX104_NUM_CHAN;
-       indio_dev->name = dev_name(dev);
-
-       priv = iio_priv(indio_dev);
-       priv->base = base[id];
-
-       /* initialize DAC output to 0V */
-       outw(0, base[id] + 4);
-       outw(0, base[id] + 6);
-
-       stx104gpio->chip.label = dev_name(dev);
-       stx104gpio->chip.parent = dev;
-       stx104gpio->chip.owner = THIS_MODULE;
-       stx104gpio->chip.base = -1;
-       stx104gpio->chip.ngpio = 8;
-       stx104gpio->chip.get_direction = stx104_gpio_get_direction;
-       stx104gpio->chip.direction_input = stx104_gpio_direction_input;
-       stx104gpio->chip.direction_output = stx104_gpio_direction_output;
-       stx104gpio->chip.get = stx104_gpio_get;
-       stx104gpio->chip.set = stx104_gpio_set;
-       stx104gpio->base = base[id] + 3;
-       stx104gpio->out_state = 0x0;
-
-       spin_lock_init(&stx104gpio->lock);
-
-       stx104dev->indio_dev = indio_dev;
-       stx104dev->chip = &stx104gpio->chip;
-       dev_set_drvdata(dev, stx104dev);
-
-       err = gpiochip_add_data(&stx104gpio->chip, stx104gpio);
-       if (err) {
-               dev_err(dev, "GPIO registering failed (%d)\n", err);
-               return err;
-       }
-
-       err = iio_device_register(indio_dev);
-       if (err) {
-               dev_err(dev, "IIO device registering failed (%d)\n", err);
-               gpiochip_remove(&stx104gpio->chip);
-               return err;
-       }
-
-       return 0;
-}
-
-static int stx104_remove(struct device *dev, unsigned int id)
-{
-       struct stx104_dev *const stx104dev = dev_get_drvdata(dev);
-
-       iio_device_unregister(stx104dev->indio_dev);
-       gpiochip_remove(stx104dev->chip);
-
-       return 0;
-}
-
-static struct isa_driver stx104_driver = {
-       .probe = stx104_probe,
-       .driver = {
-               .name = "stx104"
-       },
-       .remove = stx104_remove
-};
-
-module_isa_driver(stx104_driver, num_stx104);
-
-MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
-MODULE_DESCRIPTION("Apex Embedded Systems STX104 DAC driver");
-MODULE_LICENSE("GPL v2");
index d2b8899..fc340ed 100644 (file)
@@ -1308,7 +1308,7 @@ static void devm_iio_device_release(struct device *dev, void *res)
        iio_device_free(*(struct iio_dev **)res);
 }
 
-static int devm_iio_device_match(struct device *dev, void *res, void *data)
+int devm_iio_device_match(struct device *dev, void *res, void *data)
 {
        struct iio_dev **r = res;
        if (!r || !*r) {
@@ -1317,6 +1317,7 @@ static int devm_iio_device_match(struct device *dev, void *res, void *data)
        }
        return *r == data;
 }
+EXPORT_SYMBOL_GPL(devm_iio_device_match);
 
 /**
  * devm_iio_device_alloc - Resource-managed iio_device_alloc()
index 0ebfc92..90fac8e 100644 (file)
@@ -57,6 +57,11 @@ bool iio_event_enabled(const struct iio_event_interface *ev_int)
  *
  * Note: The caller must make sure that this function is not running
  * concurrently for the same indio_dev more than once.
+ *
+ * This function may be safely used as soon as a valid reference to iio_dev has
+ * been obtained via iio_device_alloc(), but any events that are submitted
+ * before iio_device_register() has successfully completed will be silently
+ * discarded.
  **/
 int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp)
 {
@@ -64,6 +69,9 @@ int iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp)
        struct iio_event_data ev;
        int copied;
 
+       if (!ev_int)
+               return 0;
+
        /* Does anyone care? */
        if (iio_event_enabled(ev_int)) {
 
index 7ad82fd..e1e1048 100644 (file)
@@ -119,6 +119,22 @@ void iio_trigger_unregister(struct iio_trigger *trig_info)
 }
 EXPORT_SYMBOL(iio_trigger_unregister);
 
+int iio_trigger_set_immutable(struct iio_dev *indio_dev, struct iio_trigger *trig)
+{
+       if (!indio_dev || !trig)
+               return -EINVAL;
+
+       mutex_lock(&indio_dev->mlock);
+       WARN_ON(indio_dev->trig_readonly);
+
+       indio_dev->trig = iio_trigger_get(trig);
+       indio_dev->trig_readonly = true;
+       mutex_unlock(&indio_dev->mlock);
+
+       return 0;
+}
+EXPORT_SYMBOL(iio_trigger_set_immutable);
+
 /* Search for trigger by name, assuming iio_trigger_list_lock held */
 static struct iio_trigger *__iio_trigger_find_by_name(const char *name)
 {
@@ -255,6 +271,14 @@ static int iio_trigger_attach_poll_func(struct iio_trigger *trig,
                        goto out_free_irq;
        }
 
+       /*
+        * Check if we just registered to our own trigger: we determine that
+        * this is the case if the IIO device and the trigger device share the
+        * same parent device.
+        */
+       if (pf->indio_dev->dev.parent == trig->dev.parent)
+               trig->attached_own_device = true;
+
        return ret;
 
 out_free_irq:
@@ -279,6 +303,8 @@ static int iio_trigger_detach_poll_func(struct iio_trigger *trig,
                if (ret)
                        return ret;
        }
+       if (pf->indio_dev->dev.parent == trig->dev.parent)
+               trig->attached_own_device = false;
        iio_trigger_put_irq(trig, pf->irq);
        free_irq(pf->irq, pf);
        module_put(pf->indio_dev->info->driver_module);
@@ -384,6 +410,10 @@ static ssize_t iio_trigger_write_current(struct device *dev,
                mutex_unlock(&indio_dev->mlock);
                return -EBUSY;
        }
+       if (indio_dev->trig_readonly) {
+               mutex_unlock(&indio_dev->mlock);
+               return -EPERM;
+       }
        mutex_unlock(&indio_dev->mlock);
 
        trig = iio_trigger_find_by_name(buf, len);
@@ -622,6 +652,71 @@ void devm_iio_trigger_free(struct device *dev, struct iio_trigger *iio_trig)
 }
 EXPORT_SYMBOL_GPL(devm_iio_trigger_free);
 
+static void devm_iio_trigger_unreg(struct device *dev, void *res)
+{
+       iio_trigger_unregister(*(struct iio_trigger **)res);
+}
+
+/**
+ * devm_iio_trigger_register - Resource-managed iio_trigger_register()
+ * @dev:       device this trigger was allocated for
+ * @trig_info: trigger to register
+ *
+ * Managed iio_trigger_register().  The IIO trigger registered with this
+ * function is automatically unregistered on driver detach. This function
+ * calls iio_trigger_register() internally. Refer to that function for more
+ * information.
+ *
+ * If an iio_trigger registered with this function needs to be unregistered
+ * separately, devm_iio_trigger_unregister() must be used.
+ *
+ * RETURNS:
+ * 0 on success, negative error number on failure.
+ */
+int devm_iio_trigger_register(struct device *dev, struct iio_trigger *trig_info)
+{
+       struct iio_trigger **ptr;
+       int ret;
+
+       ptr = devres_alloc(devm_iio_trigger_unreg, sizeof(*ptr), GFP_KERNEL);
+       if (!ptr)
+               return -ENOMEM;
+
+       *ptr = trig_info;
+       ret = iio_trigger_register(trig_info);
+       if (!ret)
+               devres_add(dev, ptr);
+       else
+               devres_free(ptr);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(devm_iio_trigger_register);
+
+/**
+ * devm_iio_trigger_unregister - Resource-managed iio_trigger_unregister()
+ * @dev:       device this iio_trigger belongs to
+ * @trig_info: the trigger associated with the device
+ *
+ * Unregister trigger registered with devm_iio_trigger_register().
+ */
+void devm_iio_trigger_unregister(struct device *dev,
+                                struct iio_trigger *trig_info)
+{
+       int rc;
+
+       rc = devres_release(dev, devm_iio_trigger_unreg, devm_iio_trigger_match,
+                           trig_info);
+       WARN_ON(rc);
+}
+EXPORT_SYMBOL_GPL(devm_iio_trigger_unregister);
+
+bool iio_trigger_using_own(struct iio_dev *indio_dev)
+{
+       return indio_dev->trig->attached_own_device;
+}
+EXPORT_SYMBOL(iio_trigger_using_own);
+
 void iio_device_register_trigger_consumer(struct iio_dev *indio_dev)
 {
        indio_dev->groups[indio_dev->groupcounter++] =
index e70e4e2..2173531 100644 (file)
@@ -783,8 +783,7 @@ static int __exit ak8974_remove(struct i2c_client *i2c)
        return 0;
 }
 
-#ifdef CONFIG_PM
-static int ak8974_runtime_suspend(struct device *dev)
+static int __maybe_unused ak8974_runtime_suspend(struct device *dev)
 {
        struct ak8974 *ak8974 =
                iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
@@ -795,7 +794,7 @@ static int ak8974_runtime_suspend(struct device *dev)
        return 0;
 }
 
-static int ak8974_runtime_resume(struct device *dev)
+static int __maybe_unused ak8974_runtime_resume(struct device *dev)
 {
        struct ak8974 *ak8974 =
                iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
@@ -822,7 +821,6 @@ out_regulator_disable:
 
        return ret;
 }
-#endif /* CONFIG_PM */
 
 static const struct dev_pm_ops ak8974_dev_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
@@ -847,7 +845,6 @@ MODULE_DEVICE_TABLE(of, ak8974_of_match);
 static struct i2c_driver ak8974_driver = {
        .driver  = {
                .name   = "ak8974",
-               .owner  = THIS_MODULE,
                .pm = &ak8974_dev_pm_ops,
                .of_match_table = of_match_ptr(ak8974_of_match),
        },
index feb41f8..a74ed1f 100644 (file)
@@ -416,8 +416,7 @@ static int ms5611_init(struct iio_dev *indio_dev)
        return 0;
 
 err_regulator_disable:
-       if (!IS_ERR_OR_NULL(st->vdd))
-               regulator_disable(st->vdd);
+       regulator_disable(st->vdd);
        return ret;
 }
 
@@ -425,8 +424,7 @@ static void ms5611_fini(const struct iio_dev *indio_dev)
 {
        const struct ms5611_state *st = iio_priv(indio_dev);
 
-       if (!IS_ERR_OR_NULL(st->vdd))
-               regulator_disable(st->vdd);
+       regulator_disable(st->vdd);
 }
 
 int ms5611_probe(struct iio_dev *indio_dev, struct device *dev,
index 6f84f53..1f06282 100644 (file)
@@ -1025,6 +1025,12 @@ static const struct acpi_device_id sx9500_acpi_match[] = {
 };
 MODULE_DEVICE_TABLE(acpi, sx9500_acpi_match);
 
+static const struct of_device_id sx9500_of_match[] = {
+       { .compatible = "semtech,sx9500", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, sx9500_of_match);
+
 static const struct i2c_device_id sx9500_id[] = {
        {"sx9500", 0},
        { },
@@ -1035,6 +1041,7 @@ static struct i2c_driver sx9500_driver = {
        .driver = {
                .name   = SX9500_DRIVER_NAME,
                .acpi_match_table = ACPI_PTR(sx9500_acpi_match),
+               .of_match_table = of_match_ptr(sx9500_of_match),
                .pm = &sx9500_pm_ops,
        },
        .probe          = sx9500_probe,
index 030827e..39dd202 100644 (file)
@@ -32,7 +32,7 @@ enum {
        MAX31855,
 };
 
-const struct iio_chan_spec max6675_channels[] = {
+static const struct iio_chan_spec max6675_channels[] = {
        {       /* thermocouple temperature */
                .type = IIO_TEMP,
                .info_mask_separate =
@@ -49,7 +49,7 @@ const struct iio_chan_spec max6675_channels[] = {
        IIO_CHAN_SOFT_TIMESTAMP(1),
 };
 
-const struct iio_chan_spec max31855_channels[] = {
+static const struct iio_chan_spec max31855_channels[] = {
        {       /* thermocouple temperature */
                .type = IIO_TEMP,
                .address = 2,
@@ -95,7 +95,7 @@ struct maxim_thermocouple_chip {
        u32 status_bit;
 };
 
-const struct maxim_thermocouple_chip maxim_thermocouple_chips[] = {
+static const struct maxim_thermocouple_chip maxim_thermocouple_chips[] = {
        [MAX6675] = {
                        .channels = max6675_channels,
                        .num_channels = ARRAY_SIZE(max6675_channels),
index b5625f5..61f3241 100644 (file)
@@ -412,7 +412,7 @@ static const struct iio_event_spec sca3000_event = {
                },                                              \
                .event_spec = &sca3000_event,                   \
                .num_event_specs = 1,                           \
-        }
+       }
 
 static const struct iio_chan_spec sca3000_channels[] = {
        SCA3000_CHAN(0, IIO_MOD_X),
index 854e2da..b4a0679 100644 (file)
@@ -483,6 +483,7 @@ struct iio_buffer_setup_ops {
  * @scan_timestamp:    [INTERN] set if any buffers have requested timestamp
  * @scan_index_timestamp:[INTERN] cache of the index to the timestamp
  * @trig:              [INTERN] current device trigger (buffer modes)
+ * @trig_readonly      [INTERN] mark the current trigger immutable
  * @pollfunc:          [DRIVER] function run on trigger being received
  * @pollfunc_event:    [DRIVER] function run on events trigger being received
  * @channels:          [DRIVER] channel specification structure table
@@ -523,6 +524,7 @@ struct iio_dev {
        bool                            scan_timestamp;
        unsigned                        scan_index_timestamp;
        struct iio_trigger              *trig;
+       bool                            trig_readonly;
        struct iio_poll_func            *pollfunc;
        struct iio_poll_func            *pollfunc_event;
 
@@ -642,6 +644,7 @@ static inline struct iio_dev *iio_priv_to_dev(void *priv)
 }
 
 void iio_device_free(struct iio_dev *indio_dev);
+int devm_iio_device_match(struct device *dev, void *res, void *data);
 struct iio_dev *devm_iio_device_alloc(struct device *dev, int sizeof_priv);
 void devm_iio_device_free(struct device *dev, struct iio_dev *indio_dev);
 struct iio_trigger *devm_iio_trigger_alloc(struct device *dev,
index 1c9e028..4f1154f 100644 (file)
@@ -56,6 +56,9 @@ struct iio_trigger_ops {
  * @subirqs:           [INTERN] information about the 'child' irqs.
  * @pool:              [INTERN] bitmap of irqs currently in use.
  * @pool_lock:         [INTERN] protection of the irq pool.
+ * @attached_own_device:[INTERN] if we are using our own device as trigger,
+ *                     i.e. if we registered a poll function to the same
+ *                     device as the one providing the trigger.
  **/
 struct iio_trigger {
        const struct iio_trigger_ops    *ops;
@@ -73,6 +76,7 @@ struct iio_trigger {
        struct iio_subirq subirqs[CONFIG_IIO_CONSUMERS_PER_TRIGGER];
        unsigned long pool[BITS_TO_LONGS(CONFIG_IIO_CONSUMERS_PER_TRIGGER)];
        struct mutex                    pool_lock;
+       bool                            attached_own_device;
 };
 
 
@@ -125,12 +129,27 @@ static inline void *iio_trigger_get_drvdata(struct iio_trigger *trig)
  **/
 int iio_trigger_register(struct iio_trigger *trig_info);
 
+int devm_iio_trigger_register(struct device *dev,
+                             struct iio_trigger *trig_info);
+
 /**
  * iio_trigger_unregister() - unregister a trigger from the core
  * @trig_info: trigger to be unregistered
  **/
 void iio_trigger_unregister(struct iio_trigger *trig_info);
 
+void devm_iio_trigger_unregister(struct device *dev,
+                                struct iio_trigger *trig_info);
+
+/**
+ * iio_trigger_set_immutable() - set an immutable trigger on destination
+ *
+ * @indio_dev - IIO device structure containing the device
+ * @trig - trigger to assign to device
+ *
+ **/
+int iio_trigger_set_immutable(struct iio_dev *indio_dev, struct iio_trigger *trig);
+
 /**
  * iio_trigger_poll() - called on a trigger occurring
  * @trig:      trigger which occurred
@@ -145,6 +164,13 @@ irqreturn_t iio_trigger_generic_data_rdy_poll(int irq, void *private);
 __printf(1, 2) struct iio_trigger *iio_trigger_alloc(const char *fmt, ...);
 void iio_trigger_free(struct iio_trigger *trig);
 
+/**
+ * iio_trigger_using_own() - tells us if we use our own HW trigger ourselves
+ * @indio_dev:  device to check
+ */
+bool iio_trigger_using_own(struct iio_dev *indio_dev);
+
+
 #else
 struct iio_trigger;
 struct iio_trigger_ops;
index f72f70d..3014561 100644 (file)
@@ -12,4 +12,12 @@ int iio_triggered_buffer_setup(struct iio_dev *indio_dev,
        const struct iio_buffer_setup_ops *setup_ops);
 void iio_triggered_buffer_cleanup(struct iio_dev *indio_dev);
 
+int devm_iio_triggered_buffer_setup(struct device *dev,
+                                   struct iio_dev *indio_dev,
+                                   irqreturn_t (*h)(int irq, void *p),
+                                   irqreturn_t (*thread)(int irq, void *p),
+                                   const struct iio_buffer_setup_ops *ops);
+void devm_iio_triggered_buffer_cleanup(struct device *dev,
+                                      struct iio_dev *indio_dev);
+
 #endif
index 5eb6793..7a6d61c 100644 (file)
@@ -121,10 +121,6 @@ int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used,
 
        ret = -ENOENT;
        while (ent = readdir(dp), ent)
-               /*
-                * Do we allow devices to override a generic name with
-                * a specific one?
-                */
                if ((strcmp(builtname, ent->d_name) == 0) ||
                    (strcmp(builtname_generic, ent->d_name) == 0)) {
                        ret = asprintf(&filename,
@@ -178,6 +174,13 @@ int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used,
                        sysfsfp = 0;
                        free(filename);
                        filename = 0;
+
+                       /*
+                        * Avoid having a more generic entry overwriting
+                        * the settings.
+                        */
+                       if (strcmp(builtname, ent->d_name) == 0)
+                               break;
                }
 
 error_close_sysfsfp: