Merge tag 'iio-fixes-for-4.0a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23...
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 28 Feb 2015 15:15:09 +0000 (07:15 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 28 Feb 2015 15:15:09 +0000 (07:15 -0800)
Jonathan writes:

First round of fixes for IIO in the 4.0 cycle. Note a followup
set dependent on patches in the recent merge windows will follow shortly.

* dht11 - fix a read off the end of an array, add some locking to prevent
          the read function being interrupted and make sure gpio/irq lines
  are not enabled for irqs during output.
* iadc - timeout should be in jiffies not msecs
* mpu6050 - avoid a null id from ACPI emumeration being dereferenced.
* mxs-lradc - fix up some interaction issues between the touchscreen driver
              and iio driver.  Mostly about making sure that the adc driver
              only affects channels that are not being used for the
              touchscreen.
* ad2s1200 - sign extension fix for a result of c type promotion.
* adis16400 - sign extension fix for a result of c type promotion.
* mcp3422 - scale table was transposed.
* ad5686 - use _optional regulator get to avoid a dummy reg being allocate
           which would cause the driver to fail to initialize.
* gp2ap020a00f - select REGMAP_I2C
* si7020 - revert an incorrect cleanup up and then fix the issue that made
           that cleanup seem like a good idea.

drivers/iio/adc/mcp3422.c
drivers/iio/adc/qcom-spmi-iadc.c
drivers/iio/dac/ad5686.c
drivers/iio/humidity/dht11.c
drivers/iio/humidity/si7020.c
drivers/iio/imu/adis16400_core.c
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
drivers/iio/light/Kconfig
drivers/staging/iio/adc/mxs-lradc.c
drivers/staging/iio/resolver/ad2s1200.c

index 51672256072bc8db2778e6c60982f320c680f3d4..b96c636470ef504e3b7f3d5612602bcc76a3a3a0 100644 (file)
                .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
        }
 
-/* LSB is in nV to eliminate floating point */
-static const u32 rates_to_lsb[] = {1000000, 250000, 62500, 15625};
-
-/*
- *  scales calculated as:
- *  rates_to_lsb[sample_rate] / (1 << pga);
- *  pga is 1 for 0, 2
- */
-
 static const int mcp3422_scales[4][4] = {
-       { 1000000, 250000, 62500, 15625 },
-       { 500000 , 125000, 31250, 7812 },
-       { 250000 , 62500 , 15625, 3906 },
-       { 125000 , 31250 , 7812 , 1953 } };
+       { 1000000, 500000, 250000, 125000 },
+       { 250000 , 125000, 62500 , 31250  },
+       { 62500  , 31250 , 15625 , 7812   },
+       { 15625  , 7812  , 3906  , 1953   } };
 
 /* Constant msleep times for data acquisitions */
 static const int mcp3422_read_times[4] = {
index b9666f2f5e514f8d3a66a0a192b190bcbd2a44d5..fabd24edc2a1d07534d2a67e9a1c8e78ef353cae 100644 (file)
@@ -296,7 +296,8 @@ static int iadc_do_conversion(struct iadc_chip *iadc, int chan, u16 *data)
        if (iadc->poll_eoc) {
                ret = iadc_poll_wait_eoc(iadc, wait);
        } else {
-               ret = wait_for_completion_timeout(&iadc->complete, wait);
+               ret = wait_for_completion_timeout(&iadc->complete,
+                       usecs_to_jiffies(wait));
                if (!ret)
                        ret = -ETIMEDOUT;
                else
index f57562aa396f44462a9fdc822741d09bf37531f4..15c73e20272d874655e544366e2a8d6f1c24912a 100644 (file)
@@ -322,7 +322,7 @@ static int ad5686_probe(struct spi_device *spi)
        st = iio_priv(indio_dev);
        spi_set_drvdata(spi, indio_dev);
 
-       st->reg = devm_regulator_get(&spi->dev, "vcc");
+       st->reg = devm_regulator_get_optional(&spi->dev, "vcc");
        if (!IS_ERR(st->reg)) {
                ret = regulator_enable(st->reg);
                if (ret)
index 623c145d8a97241bd0c2e284d9bb273dfcfb72da..7d79a1ac5f5f09ba332fee3ebb94c486280ce024 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/wait.h>
 #include <linux/bitops.h>
 #include <linux/completion.h>
+#include <linux/mutex.h>
 #include <linux/delay.h>
 #include <linux/gpio.h>
 #include <linux/of_gpio.h>
 
 #define DHT11_DATA_VALID_TIME  2000000000  /* 2s in ns */
 
-#define DHT11_EDGES_PREAMBLE 4
+#define DHT11_EDGES_PREAMBLE 2
 #define DHT11_BITS_PER_READ 40
+/*
+ * Note that when reading the sensor actually 84 edges are detected, but
+ * since the last edge is not significant, we only store 83:
+ */
 #define DHT11_EDGES_PER_READ (2*DHT11_BITS_PER_READ + DHT11_EDGES_PREAMBLE + 1)
 
 /* Data transmission timing (nano seconds) */
@@ -57,6 +62,7 @@ struct dht11 {
        int                             irq;
 
        struct completion               completion;
+       struct mutex                    lock;
 
        s64                             timestamp;
        int                             temperature;
@@ -88,7 +94,7 @@ static int dht11_decode(struct dht11 *dht11, int offset)
        unsigned char temp_int, temp_dec, hum_int, hum_dec, checksum;
 
        /* Calculate timestamp resolution */
-       for (i = 0; i < dht11->num_edges; ++i) {
+       for (i = 1; i < dht11->num_edges; ++i) {
                t = dht11->edges[i].ts - dht11->edges[i-1].ts;
                if (t > 0 && t < timeres)
                        timeres = t;
@@ -138,6 +144,27 @@ static int dht11_decode(struct dht11 *dht11, int offset)
        return 0;
 }
 
+/*
+ * IRQ handler called on GPIO edges
+ */
+static irqreturn_t dht11_handle_irq(int irq, void *data)
+{
+       struct iio_dev *iio = data;
+       struct dht11 *dht11 = iio_priv(iio);
+
+       /* TODO: Consider making the handler safe for IRQ sharing */
+       if (dht11->num_edges < DHT11_EDGES_PER_READ && dht11->num_edges >= 0) {
+               dht11->edges[dht11->num_edges].ts = iio_get_time_ns();
+               dht11->edges[dht11->num_edges++].value =
+                                               gpio_get_value(dht11->gpio);
+
+               if (dht11->num_edges >= DHT11_EDGES_PER_READ)
+                       complete(&dht11->completion);
+       }
+
+       return IRQ_HANDLED;
+}
+
 static int dht11_read_raw(struct iio_dev *iio_dev,
                        const struct iio_chan_spec *chan,
                        int *val, int *val2, long m)
@@ -145,6 +172,7 @@ static int dht11_read_raw(struct iio_dev *iio_dev,
        struct dht11 *dht11 = iio_priv(iio_dev);
        int ret;
 
+       mutex_lock(&dht11->lock);
        if (dht11->timestamp + DHT11_DATA_VALID_TIME < iio_get_time_ns()) {
                reinit_completion(&dht11->completion);
 
@@ -157,8 +185,17 @@ static int dht11_read_raw(struct iio_dev *iio_dev,
                if (ret)
                        goto err;
 
+               ret = request_irq(dht11->irq, dht11_handle_irq,
+                                 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+                                 iio_dev->name, iio_dev);
+               if (ret)
+                       goto err;
+
                ret = wait_for_completion_killable_timeout(&dht11->completion,
                                                                 HZ);
+
+               free_irq(dht11->irq, iio_dev);
+
                if (ret == 0 && dht11->num_edges < DHT11_EDGES_PER_READ - 1) {
                        dev_err(&iio_dev->dev,
                                        "Only %d signal edges detected\n",
@@ -185,6 +222,7 @@ static int dht11_read_raw(struct iio_dev *iio_dev,
                ret = -EINVAL;
 err:
        dht11->num_edges = -1;
+       mutex_unlock(&dht11->lock);
        return ret;
 }
 
@@ -193,27 +231,6 @@ static const struct iio_info dht11_iio_info = {
        .read_raw               = dht11_read_raw,
 };
 
-/*
- * IRQ handler called on GPIO edges
-*/
-static irqreturn_t dht11_handle_irq(int irq, void *data)
-{
-       struct iio_dev *iio = data;
-       struct dht11 *dht11 = iio_priv(iio);
-
-       /* TODO: Consider making the handler safe for IRQ sharing */
-       if (dht11->num_edges < DHT11_EDGES_PER_READ && dht11->num_edges >= 0) {
-               dht11->edges[dht11->num_edges].ts = iio_get_time_ns();
-               dht11->edges[dht11->num_edges++].value =
-                                               gpio_get_value(dht11->gpio);
-
-               if (dht11->num_edges >= DHT11_EDGES_PER_READ)
-                       complete(&dht11->completion);
-       }
-
-       return IRQ_HANDLED;
-}
-
 static const struct iio_chan_spec dht11_chan_spec[] = {
        { .type = IIO_TEMP,
                .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), },
@@ -256,11 +273,6 @@ static int dht11_probe(struct platform_device *pdev)
                dev_err(dev, "GPIO %d has no interrupt\n", dht11->gpio);
                return -EINVAL;
        }
-       ret = devm_request_irq(dev, dht11->irq, dht11_handle_irq,
-                               IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
-                               pdev->name, iio);
-       if (ret)
-               return ret;
 
        dht11->timestamp = iio_get_time_ns() - DHT11_DATA_VALID_TIME - 1;
        dht11->num_edges = -1;
@@ -268,6 +280,7 @@ static int dht11_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, iio);
 
        init_completion(&dht11->completion);
+       mutex_init(&dht11->lock);
        iio->name = pdev->name;
        iio->dev.parent = &pdev->dev;
        iio->info = &dht11_iio_info;
index b54164677b898d5c9e5b4b9983fe61271f3c80b5..fa3b809aff5efd425ce96031aec1c066b644feb2 100644 (file)
@@ -45,12 +45,12 @@ static int si7020_read_raw(struct iio_dev *indio_dev,
                           struct iio_chan_spec const *chan, int *val,
                           int *val2, long mask)
 {
-       struct i2c_client *client = iio_priv(indio_dev);
+       struct i2c_client **client = iio_priv(indio_dev);
        int ret;
 
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
-               ret = i2c_smbus_read_word_data(client,
+               ret = i2c_smbus_read_word_data(*client,
                                               chan->type == IIO_TEMP ?
                                               SI7020CMD_TEMP_HOLD :
                                               SI7020CMD_RH_HOLD);
@@ -126,7 +126,7 @@ static int si7020_probe(struct i2c_client *client,
        /* Wait the maximum power-up time after software reset. */
        msleep(15);
 
-       indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*client));
+       indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
        if (!indio_dev)
                return -ENOMEM;
 
index b70873de04ea50a7cb73f34835f15c43ceff9eb1..fa795dcd5f75ec0a1e8de143bc0122ef36bf9409 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/debugfs.h>
+#include <linux/bitops.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
@@ -414,7 +415,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
                mutex_unlock(&indio_dev->mlock);
                if (ret)
                        return ret;
-               val16 = ((val16 & 0xFFF) << 4) >> 4;
+               val16 = sign_extend32(val16, 11);
                *val = val16;
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_OFFSET:
index f73e60b7a79611b8825bfe90ea3ba5a5e1b253b1..d8d5bed65e072cae577968edb78e2e592c2a5bfa 100644 (file)
@@ -780,7 +780,11 @@ static int inv_mpu_probe(struct i2c_client *client,
 
        i2c_set_clientdata(client, indio_dev);
        indio_dev->dev.parent = &client->dev;
-       indio_dev->name = id->name;
+       /* id will be NULL when enumerated via ACPI */
+       if (id)
+               indio_dev->name = (char *)id->name;
+       else
+               indio_dev->name = (char *)dev_name(&client->dev);
        indio_dev->channels = inv_mpu_channels;
        indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels);
 
index ae68c64bdad3ef7480d15da5d1187c1fd4f7ba4f..de1d8af0008739d3cf2c73c6bd4f748a699c3b64 100644 (file)
@@ -73,6 +73,7 @@ config CM36651
 config GP2AP020A00F
        tristate "Sharp GP2AP020A00F Proximity/ALS sensor"
        depends on I2C
+       select REGMAP_I2C
        select IIO_BUFFER
        select IIO_TRIGGERED_BUFFER
        select IRQ_WORK
index d9d6fad7cb00725f43142967bad4ca6b39a32b06..816174388f13347447c495700e3dad85e7c269db 100644 (file)
@@ -214,11 +214,17 @@ struct mxs_lradc {
        unsigned long           is_divided;
 
        /*
-        * Touchscreen LRADC channels receives a private slot in the CTRL4
-        * register, the slot #7. Therefore only 7 slots instead of 8 in the
-        * CTRL4 register can be mapped to LRADC channels when using the
-        * touchscreen.
-        *
+        * When the touchscreen is enabled, we give it two private virtual
+        * channels: #6 and #7. This means that only 6 virtual channels (instead
+        * of 8) will be available for buffered capture.
+        */
+#define TOUCHSCREEN_VCHANNEL1          7
+#define TOUCHSCREEN_VCHANNEL2          6
+#define BUFFER_VCHANS_LIMITED          0x3f
+#define BUFFER_VCHANS_ALL              0xff
+       u8                      buffer_vchans;
+
+       /*
         * Furthermore, certain LRADC channels are shared between touchscreen
         * and/or touch-buttons and generic LRADC block. Therefore when using
         * either of these, these channels are not available for the regular
@@ -342,6 +348,9 @@ struct mxs_lradc {
 #define        LRADC_CTRL4                             0x140
 #define        LRADC_CTRL4_LRADCSELECT_MASK(n)         (0xf << ((n) * 4))
 #define        LRADC_CTRL4_LRADCSELECT_OFFSET(n)       ((n) * 4)
+#define        LRADC_CTRL4_LRADCSELECT(n, x) \
+                               (((x) << LRADC_CTRL4_LRADCSELECT_OFFSET(n)) & \
+                               LRADC_CTRL4_LRADCSELECT_MASK(n))
 
 #define LRADC_RESOLUTION                       12
 #define LRADC_SINGLE_SAMPLE_MASK               ((1 << LRADC_RESOLUTION) - 1)
@@ -416,6 +425,14 @@ static bool mxs_lradc_check_touch_event(struct mxs_lradc *lradc)
                                        LRADC_STATUS_TOUCH_DETECT_RAW);
 }
 
+static void mxs_lradc_map_channel(struct mxs_lradc *lradc, unsigned vch,
+                                 unsigned ch)
+{
+       mxs_lradc_reg_clear(lradc, LRADC_CTRL4_LRADCSELECT_MASK(vch),
+                               LRADC_CTRL4);
+       mxs_lradc_reg_set(lradc, LRADC_CTRL4_LRADCSELECT(vch, ch), LRADC_CTRL4);
+}
+
 static void mxs_lradc_setup_ts_channel(struct mxs_lradc *lradc, unsigned ch)
 {
        /*
@@ -450,12 +467,8 @@ static void mxs_lradc_setup_ts_channel(struct mxs_lradc *lradc, unsigned ch)
                LRADC_DELAY_DELAY(lradc->over_sample_delay - 1),
                        LRADC_DELAY(3));
 
-       mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(2) |
-                       LRADC_CTRL1_LRADC_IRQ(3) | LRADC_CTRL1_LRADC_IRQ(4) |
-                       LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1);
+       mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(ch), LRADC_CTRL1);
 
-       /* wake us again, when the complete conversion is done */
-       mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch), LRADC_CTRL1);
        /*
         * after changing the touchscreen plates setting
         * the signals need some initial time to settle. Start the
@@ -509,12 +522,8 @@ static void mxs_lradc_setup_ts_pressure(struct mxs_lradc *lradc, unsigned ch1,
                LRADC_DELAY_DELAY(lradc->over_sample_delay - 1),
                                        LRADC_DELAY(3));
 
-       mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(2) |
-                       LRADC_CTRL1_LRADC_IRQ(3) | LRADC_CTRL1_LRADC_IRQ(4) |
-                       LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1);
+       mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(ch2), LRADC_CTRL1);
 
-       /* wake us again, when the conversions are done */
-       mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch2), LRADC_CTRL1);
        /*
         * after changing the touchscreen plates setting
         * the signals need some initial time to settle. Start the
@@ -580,36 +589,6 @@ static unsigned mxs_lradc_read_ts_pressure(struct mxs_lradc *lradc,
 #define TS_CH_XM 4
 #define TS_CH_YM 5
 
-static int mxs_lradc_read_ts_channel(struct mxs_lradc *lradc)
-{
-       u32 reg;
-       int val;
-
-       reg = readl(lradc->base + LRADC_CTRL1);
-
-       /* only channels 3 to 5 are of interest here */
-       if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_YP)) {
-               mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_YP) |
-                       LRADC_CTRL1_LRADC_IRQ(TS_CH_YP), LRADC_CTRL1);
-               val = mxs_lradc_read_raw_channel(lradc, TS_CH_YP);
-       } else if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_XM)) {
-               mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_XM) |
-                       LRADC_CTRL1_LRADC_IRQ(TS_CH_XM), LRADC_CTRL1);
-               val = mxs_lradc_read_raw_channel(lradc, TS_CH_XM);
-       } else if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_YM)) {
-               mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_YM) |
-                       LRADC_CTRL1_LRADC_IRQ(TS_CH_YM), LRADC_CTRL1);
-               val = mxs_lradc_read_raw_channel(lradc, TS_CH_YM);
-       } else {
-               return -EIO;
-       }
-
-       mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2));
-       mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3));
-
-       return val;
-}
-
 /*
  * YP(open)--+-------------+
  *           |             |--+
@@ -653,7 +632,8 @@ static void mxs_lradc_prepare_x_pos(struct mxs_lradc *lradc)
        mxs_lradc_reg_set(lradc, mxs_lradc_drive_x_plate(lradc), LRADC_CTRL0);
 
        lradc->cur_plate = LRADC_SAMPLE_X;
-       mxs_lradc_setup_ts_channel(lradc, TS_CH_YP);
+       mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL1, TS_CH_YP);
+       mxs_lradc_setup_ts_channel(lradc, TOUCHSCREEN_VCHANNEL1);
 }
 
 /*
@@ -674,7 +654,8 @@ static void mxs_lradc_prepare_y_pos(struct mxs_lradc *lradc)
        mxs_lradc_reg_set(lradc, mxs_lradc_drive_y_plate(lradc), LRADC_CTRL0);
 
        lradc->cur_plate = LRADC_SAMPLE_Y;
-       mxs_lradc_setup_ts_channel(lradc, TS_CH_XM);
+       mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL1, TS_CH_XM);
+       mxs_lradc_setup_ts_channel(lradc, TOUCHSCREEN_VCHANNEL1);
 }
 
 /*
@@ -695,7 +676,10 @@ static void mxs_lradc_prepare_pressure(struct mxs_lradc *lradc)
        mxs_lradc_reg_set(lradc, mxs_lradc_drive_pressure(lradc), LRADC_CTRL0);
 
        lradc->cur_plate = LRADC_SAMPLE_PRESSURE;
-       mxs_lradc_setup_ts_pressure(lradc, TS_CH_XP, TS_CH_YM);
+       mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL1, TS_CH_YM);
+       mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL2, TS_CH_XP);
+       mxs_lradc_setup_ts_pressure(lradc, TOUCHSCREEN_VCHANNEL2,
+                                               TOUCHSCREEN_VCHANNEL1);
 }
 
 static void mxs_lradc_enable_touch_detection(struct mxs_lradc *lradc)
@@ -708,6 +692,19 @@ static void mxs_lradc_enable_touch_detection(struct mxs_lradc *lradc)
        mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1);
 }
 
+static void mxs_lradc_start_touch_event(struct mxs_lradc *lradc)
+{
+       mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
+                               LRADC_CTRL1);
+       mxs_lradc_reg_set(lradc,
+               LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL1), LRADC_CTRL1);
+       /*
+        * start with the Y-pos, because it uses nearly the same plate
+        * settings like the touch detection
+        */
+       mxs_lradc_prepare_y_pos(lradc);
+}
+
 static void mxs_lradc_report_ts_event(struct mxs_lradc *lradc)
 {
        input_report_abs(lradc->ts_input, ABS_X, lradc->ts_x_pos);
@@ -725,10 +722,12 @@ static void mxs_lradc_complete_touch_event(struct mxs_lradc *lradc)
         * start a dummy conversion to burn time to settle the signals
         * note: we are not interested in the conversion's value
         */
-       mxs_lradc_reg_wrt(lradc, 0, LRADC_CH(5));
-       mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1);
-       mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(5), LRADC_CTRL1);
-       mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << 5) |
+       mxs_lradc_reg_wrt(lradc, 0, LRADC_CH(TOUCHSCREEN_VCHANNEL1));
+       mxs_lradc_reg_clear(lradc,
+               LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1) |
+               LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2), LRADC_CTRL1);
+       mxs_lradc_reg_wrt(lradc,
+               LRADC_DELAY_TRIGGER(1 << TOUCHSCREEN_VCHANNEL1) |
                LRADC_DELAY_KICK | LRADC_DELAY_DELAY(10), /* waste 5 ms */
                        LRADC_DELAY(2));
 }
@@ -760,59 +759,45 @@ static void mxs_lradc_finish_touch_event(struct mxs_lradc *lradc, bool valid)
 
        /* if it is released, wait for the next touch via IRQ */
        lradc->cur_plate = LRADC_TOUCH;
-       mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, LRADC_CTRL1);
+       mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2));
+       mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3));
+       mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ |
+               LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL1) |
+               LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1), LRADC_CTRL1);
        mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1);
 }
 
 /* touchscreen's state machine */
 static void mxs_lradc_handle_touch(struct mxs_lradc *lradc)
 {
-       int val;
-
        switch (lradc->cur_plate) {
        case LRADC_TOUCH:
-               /*
-                * start with the Y-pos, because it uses nearly the same plate
-                * settings like the touch detection
-                */
-               if (mxs_lradc_check_touch_event(lradc)) {
-                       mxs_lradc_reg_clear(lradc,
-                                       LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
-                                       LRADC_CTRL1);
-                       mxs_lradc_prepare_y_pos(lradc);
-               }
+               if (mxs_lradc_check_touch_event(lradc))
+                       mxs_lradc_start_touch_event(lradc);
                mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ,
                                        LRADC_CTRL1);
                return;
 
        case LRADC_SAMPLE_Y:
-               val = mxs_lradc_read_ts_channel(lradc);
-               if (val < 0) {
-                       mxs_lradc_enable_touch_detection(lradc); /* re-start */
-                       return;
-               }
-               lradc->ts_y_pos = val;
+               lradc->ts_y_pos = mxs_lradc_read_raw_channel(lradc,
+                                                       TOUCHSCREEN_VCHANNEL1);
                mxs_lradc_prepare_x_pos(lradc);
                return;
 
        case LRADC_SAMPLE_X:
-               val = mxs_lradc_read_ts_channel(lradc);
-               if (val < 0) {
-                       mxs_lradc_enable_touch_detection(lradc); /* re-start */
-                       return;
-               }
-               lradc->ts_x_pos = val;
+               lradc->ts_x_pos = mxs_lradc_read_raw_channel(lradc,
+                                                       TOUCHSCREEN_VCHANNEL1);
                mxs_lradc_prepare_pressure(lradc);
                return;
 
        case LRADC_SAMPLE_PRESSURE:
-               lradc->ts_pressure =
-                       mxs_lradc_read_ts_pressure(lradc, TS_CH_XP, TS_CH_YM);
+               lradc->ts_pressure = mxs_lradc_read_ts_pressure(lradc,
+                                                       TOUCHSCREEN_VCHANNEL2,
+                                                       TOUCHSCREEN_VCHANNEL1);
                mxs_lradc_complete_touch_event(lradc);
                return;
 
        case LRADC_SAMPLE_VALID:
-               val = mxs_lradc_read_ts_channel(lradc); /* ignore the value */
                mxs_lradc_finish_touch_event(lradc, 1);
                break;
        }
@@ -844,9 +829,9 @@ static int mxs_lradc_read_single(struct iio_dev *iio_dev, int chan, int *val)
         * used if doing raw sampling.
         */
        if (lradc->soc == IMX28_LRADC)
-               mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
+               mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(0),
                        LRADC_CTRL1);
-       mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0);
+       mxs_lradc_reg_clear(lradc, 0x1, LRADC_CTRL0);
 
        /* Enable / disable the divider per requirement */
        if (test_bit(chan, &lradc->is_divided))
@@ -1090,9 +1075,8 @@ static void mxs_lradc_disable_ts(struct mxs_lradc *lradc)
 {
        /* stop all interrupts from firing */
        mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN |
-               LRADC_CTRL1_LRADC_IRQ_EN(2) | LRADC_CTRL1_LRADC_IRQ_EN(3) |
-               LRADC_CTRL1_LRADC_IRQ_EN(4) | LRADC_CTRL1_LRADC_IRQ_EN(5),
-               LRADC_CTRL1);
+               LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL1) |
+               LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL2), LRADC_CTRL1);
 
        /* Power-down touchscreen touch-detect circuitry. */
        mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0);
@@ -1158,26 +1142,31 @@ static irqreturn_t mxs_lradc_handle_irq(int irq, void *data)
        struct iio_dev *iio = data;
        struct mxs_lradc *lradc = iio_priv(iio);
        unsigned long reg = readl(lradc->base + LRADC_CTRL1);
+       uint32_t clr_irq = mxs_lradc_irq_mask(lradc);
        const uint32_t ts_irq_mask =
                LRADC_CTRL1_TOUCH_DETECT_IRQ |
-               LRADC_CTRL1_LRADC_IRQ(2) |
-               LRADC_CTRL1_LRADC_IRQ(3) |
-               LRADC_CTRL1_LRADC_IRQ(4) |
-               LRADC_CTRL1_LRADC_IRQ(5);
+               LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1) |
+               LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2);
 
        if (!(reg & mxs_lradc_irq_mask(lradc)))
                return IRQ_NONE;
 
-       if (lradc->use_touchscreen && (reg & ts_irq_mask))
+       if (lradc->use_touchscreen && (reg & ts_irq_mask)) {
                mxs_lradc_handle_touch(lradc);
 
-       if (iio_buffer_enabled(iio))
-               iio_trigger_poll(iio->trig);
-       else if (reg & LRADC_CTRL1_LRADC_IRQ(0))
+               /* Make sure we don't clear the next conversion's interrupt. */
+               clr_irq &= ~(LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1) |
+                               LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2));
+       }
+
+       if (iio_buffer_enabled(iio)) {
+               if (reg & lradc->buffer_vchans)
+                       iio_trigger_poll(iio->trig);
+       } else if (reg & LRADC_CTRL1_LRADC_IRQ(0)) {
                complete(&lradc->completion);
+       }
 
-       mxs_lradc_reg_clear(lradc, reg & mxs_lradc_irq_mask(lradc),
-                       LRADC_CTRL1);
+       mxs_lradc_reg_clear(lradc, reg & clr_irq, LRADC_CTRL1);
 
        return IRQ_HANDLED;
 }
@@ -1289,9 +1278,10 @@ static int mxs_lradc_buffer_preenable(struct iio_dev *iio)
        }
 
        if (lradc->soc == IMX28_LRADC)
-               mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
-                                                       LRADC_CTRL1);
-       mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0);
+               mxs_lradc_reg_clear(lradc,
+                       lradc->buffer_vchans << LRADC_CTRL1_LRADC_IRQ_EN_OFFSET,
+                       LRADC_CTRL1);
+       mxs_lradc_reg_clear(lradc, lradc->buffer_vchans, LRADC_CTRL0);
 
        for_each_set_bit(chan, iio->active_scan_mask, LRADC_MAX_TOTAL_CHANS) {
                ctrl4_set |= chan << LRADC_CTRL4_LRADCSELECT_OFFSET(ofs);
@@ -1324,10 +1314,11 @@ static int mxs_lradc_buffer_postdisable(struct iio_dev *iio)
        mxs_lradc_reg_clear(lradc, LRADC_DELAY_TRIGGER_LRADCS_MASK |
                                        LRADC_DELAY_KICK, LRADC_DELAY(0));
 
-       mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0);
+       mxs_lradc_reg_clear(lradc, lradc->buffer_vchans, LRADC_CTRL0);
        if (lradc->soc == IMX28_LRADC)
-               mxs_lradc_reg_clear(lradc, LRADC_CTRL1_MX28_LRADC_IRQ_EN_MASK,
-                                       LRADC_CTRL1);
+               mxs_lradc_reg_clear(lradc,
+                       lradc->buffer_vchans << LRADC_CTRL1_LRADC_IRQ_EN_OFFSET,
+                       LRADC_CTRL1);
 
        kfree(lradc->buffer);
        mutex_unlock(&lradc->lock);
@@ -1353,7 +1344,7 @@ static bool mxs_lradc_validate_scan_mask(struct iio_dev *iio,
        if (lradc->use_touchbutton)
                rsvd_chans++;
        if (lradc->use_touchscreen)
-               rsvd_chans++;
+               rsvd_chans += 2;
 
        /* Test for attempts to map channels with special mode of operation. */
        if (bitmap_intersects(mask, &rsvd_mask, LRADC_MAX_TOTAL_CHANS))
@@ -1413,6 +1404,13 @@ static const struct iio_chan_spec mxs_lradc_chan_spec[] = {
                .channel = 8,
                .scan_type = {.sign = 'u', .realbits = 18, .storagebits = 32,},
        },
+       /* Hidden channel to keep indexes */
+       {
+               .type = IIO_TEMP,
+               .indexed = 1,
+               .scan_index = -1,
+               .channel = 9,
+       },
        MXS_ADC_CHAN(10, IIO_VOLTAGE),  /* VDDIO */
        MXS_ADC_CHAN(11, IIO_VOLTAGE),  /* VTH */
        MXS_ADC_CHAN(12, IIO_VOLTAGE),  /* VDDA */
@@ -1583,6 +1581,11 @@ static int mxs_lradc_probe(struct platform_device *pdev)
 
        touch_ret = mxs_lradc_probe_touchscreen(lradc, node);
 
+       if (touch_ret == 0)
+               lradc->buffer_vchans = BUFFER_VCHANS_LIMITED;
+       else
+               lradc->buffer_vchans = BUFFER_VCHANS_ALL;
+
        /* Grab all IRQ sources */
        for (i = 0; i < of_cfg->irq_count; i++) {
                lradc->irq[i] = platform_get_irq(pdev, i);
index 017d2f8379b78ca86f7e30ed0e85855684c7b6ec..c17893b4918c82bf176e9ecfac235cd6439e7763 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/delay.h>
 #include <linux/gpio.h>
 #include <linux/module.h>
+#include <linux/bitops.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
@@ -68,7 +69,7 @@ static int ad2s1200_read_raw(struct iio_dev *indio_dev,
                break;
        case IIO_ANGL_VEL:
                vel = (((s16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4);
-               vel = (vel << 4) >> 4;
+               vel = sign_extend32(vel, 11);
                *val = vel;
                break;
        default: