These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / iio / adc / ti_am335x_adc.c
index a0e7161..c1e0553 100644 (file)
@@ -37,6 +37,7 @@ struct tiadc_device {
        u8 channel_step[8];
        int buffer_en_ch_steps;
        u16 data[8];
+       u32 open_delay[8], sample_delay[8], step_avg[8];
 };
 
 static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg)
@@ -85,6 +86,7 @@ static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan)
 static void tiadc_step_config(struct iio_dev *indio_dev)
 {
        struct tiadc_device *adc_dev = iio_priv(indio_dev);
+       struct device *dev = adc_dev->mfd_tscadc->dev;
        unsigned int stepconfig;
        int i, steps = 0;
 
@@ -98,20 +100,47 @@ static void tiadc_step_config(struct iio_dev *indio_dev)
         * needs to be given to ADC to digitalize data.
         */
 
-       if (iio_buffer_enabled(indio_dev))
-               stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1
-                                       | STEPCONFIG_MODE_SWCNT;
-       else
-               stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
 
        for (i = 0; i < adc_dev->channels; i++) {
                int chan;
 
                chan = adc_dev->channel_line[i];
+
+               if (adc_dev->step_avg[i] > STEPCONFIG_AVG_16) {
+                       dev_warn(dev, "chan %d step_avg truncating to %d\n",
+                                chan, STEPCONFIG_AVG_16);
+                       adc_dev->step_avg[i] = STEPCONFIG_AVG_16;
+               }
+
+               if (adc_dev->step_avg[i])
+                       stepconfig =
+                       STEPCONFIG_AVG(ffs(adc_dev->step_avg[i]) - 1) |
+                       STEPCONFIG_FIFO1;
+               else
+                       stepconfig = STEPCONFIG_FIFO1;
+
+               if (iio_buffer_enabled(indio_dev))
+                       stepconfig |= STEPCONFIG_MODE_SWCNT;
+
                tiadc_writel(adc_dev, REG_STEPCONFIG(steps),
                                stepconfig | STEPCONFIG_INP(chan));
+
+               if (adc_dev->open_delay[i] > STEPDELAY_OPEN_MASK) {
+                       dev_warn(dev, "chan %d open delay truncating to 0x3FFFF\n",
+                                chan);
+                       adc_dev->open_delay[i] = STEPDELAY_OPEN_MASK;
+               }
+
+               if (adc_dev->sample_delay[i] > 0xFF) {
+                       dev_warn(dev, "chan %d sample delay truncating to 0xFF\n",
+                                chan);
+                       adc_dev->sample_delay[i] = 0xFF;
+               }
+
                tiadc_writel(adc_dev, REG_STEPDELAY(steps),
-                               STEPCONFIG_OPENDLY);
+                               STEPDELAY_OPEN(adc_dev->open_delay[i]) |
+                               STEPDELAY_SAMPLE(adc_dev->sample_delay[i]));
+
                adc_dev->channel_step[i] = steps;
                steps++;
        }
@@ -260,7 +289,7 @@ static int tiadc_iio_buffered_hardware_setup(struct iio_dev *indio_dev,
                goto error_kfifo_free;
 
        indio_dev->setup_ops = setup_ops;
-       indio_dev->modes |= INDIO_BUFFER_HARDWARE;
+       indio_dev->modes |= INDIO_BUFFER_SOFTWARE;
 
        return 0;
 
@@ -395,16 +424,43 @@ static const struct iio_info tiadc_info = {
        .driver_module = THIS_MODULE,
 };
 
+static int tiadc_parse_dt(struct platform_device *pdev,
+                         struct tiadc_device *adc_dev)
+{
+       struct device_node *node = pdev->dev.of_node;
+       struct property *prop;
+       const __be32 *cur;
+       int channels = 0;
+       u32 val;
+
+       of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) {
+               adc_dev->channel_line[channels] = val;
+
+               /* Set Default values for optional DT parameters */
+               adc_dev->open_delay[channels] = STEPCONFIG_OPENDLY;
+               adc_dev->sample_delay[channels] = STEPCONFIG_SAMPLEDLY;
+               adc_dev->step_avg[channels] = 16;
+
+               channels++;
+       }
+
+       of_property_read_u32_array(node, "ti,chan-step-avg",
+                                  adc_dev->step_avg, channels);
+       of_property_read_u32_array(node, "ti,chan-step-opendelay",
+                                  adc_dev->open_delay, channels);
+       of_property_read_u32_array(node, "ti,chan-step-sampledelay",
+                                  adc_dev->sample_delay, channels);
+
+       adc_dev->channels = channels;
+       return 0;
+}
+
 static int tiadc_probe(struct platform_device *pdev)
 {
        struct iio_dev          *indio_dev;
        struct tiadc_device     *adc_dev;
        struct device_node      *node = pdev->dev.of_node;
-       struct property         *prop;
-       const __be32            *cur;
        int                     err;
-       u32                     val;
-       int                     channels = 0;
 
        if (!node) {
                dev_err(&pdev->dev, "Could not find valid DT data.\n");
@@ -420,12 +476,7 @@ static int tiadc_probe(struct platform_device *pdev)
        adc_dev = iio_priv(indio_dev);
 
        adc_dev->mfd_tscadc = ti_tscadc_dev_get(pdev);
-
-       of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) {
-               adc_dev->channel_line[channels] = val;
-               channels++;
-       }
-       adc_dev->channels = channels;
+       tiadc_parse_dt(pdev, adc_dev);
 
        indio_dev->dev.parent = &pdev->dev;
        indio_dev->name = dev_name(&pdev->dev);