OSDN Git Service

Merge tag 'iio-fixes-for-4.0a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23...
[android-x86/kernel.git] / drivers / staging / iio / adc / mxs-lradc.c
index 653af03..8161743 100644 (file)
@@ -453,7 +453,14 @@ static void mxs_lradc_setup_ts_channel(struct mxs_lradc *lradc, unsigned ch)
         */
        mxs_lradc_reg_clear(lradc, LRADC_CH_VALUE_MASK, LRADC_CH(ch));
 
-       /* prepare the delay/loop unit according to the oversampling count */
+       /*
+        * prepare the delay/loop unit according to the oversampling count
+        *
+        * from the datasheet:
+        * "The DELAY fields in HW_LRADC_DELAY0, HW_LRADC_DELAY1,
+        * HW_LRADC_DELAY2, and HW_LRADC_DELAY3 must be non-zero; otherwise,
+        * the LRADC will not trigger the delay group."
+        */
        mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << ch) |
                LRADC_DELAY_TRIGGER_DELAYS(0) |
                LRADC_DELAY_LOOP(lradc->over_sample_cnt - 1) |
@@ -824,7 +831,7 @@ static int mxs_lradc_read_single(struct iio_dev *iio_dev, int chan, int *val)
        if (lradc->soc == IMX28_LRADC)
                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))
@@ -1152,10 +1159,12 @@ static irqreturn_t mxs_lradc_handle_irq(int irq, void *data)
                                LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2));
        }
 
-       if (iio_buffer_enabled(iio))
-               iio_trigger_poll(iio->trig);
-       else if (reg & LRADC_CTRL1_LRADC_IRQ(0))
+       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 & clr_irq, LRADC_CTRL1);
 
@@ -1272,7 +1281,7 @@ static int mxs_lradc_buffer_preenable(struct iio_dev *iio)
                mxs_lradc_reg_clear(lradc,
                        lradc->buffer_vchans << LRADC_CTRL1_LRADC_IRQ_EN_OFFSET,
                        LRADC_CTRL1);
-       mxs_lradc_reg_clear(lradc, 0xff, LRADC_CTRL0);
+       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);
@@ -1305,7 +1314,7 @@ 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->buffer_vchans << LRADC_CTRL1_LRADC_IRQ_EN_OFFSET,
@@ -1395,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 */
@@ -1484,20 +1500,38 @@ static int mxs_lradc_probe_touchscreen(struct mxs_lradc *lradc,
                return -EINVAL;
        }
 
-       lradc->over_sample_cnt = 4;
-       ret = of_property_read_u32(lradc_node, "fsl,ave-ctrl", &adapt);
-       if (ret == 0)
+       if (of_property_read_u32(lradc_node, "fsl,ave-ctrl", &adapt)) {
+               lradc->over_sample_cnt = 4;
+       } else {
+               if (adapt < 1 || adapt > 32) {
+                       dev_err(lradc->dev, "Invalid sample count (%u)\n",
+                               adapt);
+                       return -EINVAL;
+               }
                lradc->over_sample_cnt = adapt;
+       }
 
-       lradc->over_sample_delay = 2;
-       ret = of_property_read_u32(lradc_node, "fsl,ave-delay", &adapt);
-       if (ret == 0)
+       if (of_property_read_u32(lradc_node, "fsl,ave-delay", &adapt)) {
+               lradc->over_sample_delay = 2;
+       } else {
+               if (adapt < 2 || adapt > LRADC_DELAY_DELAY_MASK + 1) {
+                       dev_err(lradc->dev, "Invalid sample delay (%u)\n",
+                               adapt);
+                       return -EINVAL;
+               }
                lradc->over_sample_delay = adapt;
+       }
 
-       lradc->settling_delay = 10;
-       ret = of_property_read_u32(lradc_node, "fsl,settling", &adapt);
-       if (ret == 0)
+       if (of_property_read_u32(lradc_node, "fsl,settling", &adapt)) {
+               lradc->settling_delay = 10;
+       } else {
+               if (adapt < 1 || adapt > LRADC_DELAY_DELAY_MASK) {
+                       dev_err(lradc->dev, "Invalid settling delay (%u)\n",
+                               adapt);
+                       return -EINVAL;
+               }
                lradc->settling_delay = adapt;
+       }
 
        return 0;
 }