iio: ti_tscadc: provide datasheet_name and scan_type
[firefly-linux-kernel-4.4.55.git] / drivers / iio / adc / ti_am335x_adc.c
index 5f9a7e7d313520c71529ffcea02c6f59cc816a93..9939810954f1d35e73e26707dd222f032f8ffe53 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/iio/iio.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/iio/machine.h>
+#include <linux/iio/driver.h>
 
 #include <linux/mfd/ti_am335x_tscadc.h>
-#include <linux/platform_data/ti_am335x_adc.h>
 
 struct tiadc_device {
        struct ti_tscadc_dev *mfd_tscadc;
@@ -42,10 +45,20 @@ static void tiadc_writel(struct tiadc_device *adc, unsigned int reg,
        writel(val, adc->mfd_tscadc->tscadc_base + reg);
 }
 
+static u32 get_adc_step_mask(struct tiadc_device *adc_dev)
+{
+       u32 step_en;
+
+       step_en = ((1 << adc_dev->channels) - 1);
+       step_en <<= TOTAL_STEPS - adc_dev->channels + 1;
+       return step_en;
+}
+
 static void tiadc_step_config(struct tiadc_device *adc_dev)
 {
        unsigned int stepconfig;
        int i, channels = 0, steps;
+       u32 step_en;
 
        /*
         * There are 16 configurable steps and 8 analog input
@@ -69,32 +82,50 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
                                STEPCONFIG_OPENDLY);
                channels++;
        }
-       tiadc_writel(adc_dev, REG_SE, STPENB_STEPENB);
+       step_en = get_adc_step_mask(adc_dev);
+       am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en);
 }
 
+static const char * const chan_name_ain[] = {
+       "AIN0",
+       "AIN1",
+       "AIN2",
+       "AIN3",
+       "AIN4",
+       "AIN5",
+       "AIN6",
+       "AIN7",
+};
+
 static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
 {
+       struct tiadc_device *adc_dev = iio_priv(indio_dev);
        struct iio_chan_spec *chan_array;
+       struct iio_chan_spec *chan;
        int i;
 
        indio_dev->num_channels = channels;
-       chan_array = kcalloc(indio_dev->num_channels,
+       chan_array = kcalloc(channels,
                        sizeof(struct iio_chan_spec), GFP_KERNEL);
-
        if (chan_array == NULL)
                return -ENOMEM;
 
-       for (i = 0; i < (indio_dev->num_channels); i++) {
-               struct iio_chan_spec *chan = chan_array + i;
+       chan = chan_array;
+       for (i = 0; i < channels; i++, chan++) {
+
                chan->type = IIO_VOLTAGE;
                chan->indexed = 1;
                chan->channel = i;
                chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
+               chan->datasheet_name = chan_name_ain[i];
+               chan->scan_type.sign = 'u';
+               chan->scan_type.realbits = 12;
+               chan->scan_type.storagebits = 32;
        }
 
        indio_dev->channels = chan_array;
 
-       return indio_dev->num_channels;
+       return 0;
 }
 
 static void tiadc_channels_remove(struct iio_dev *indio_dev)
@@ -127,7 +158,7 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
                if (i == chan->channel)
                        *val = readx1 & 0xfff;
        }
-       tiadc_writel(adc_dev, REG_SE, STPENB_STEPENB);
+       am335x_tsc_se_update(adc_dev->mfd_tscadc);
 
        return IIO_VAL_INT;
 }
@@ -140,13 +171,12 @@ static int tiadc_probe(struct platform_device *pdev)
 {
        struct iio_dev          *indio_dev;
        struct tiadc_device     *adc_dev;
-       struct ti_tscadc_dev    *tscadc_dev = pdev->dev.platform_data;
-       struct mfd_tscadc_board *pdata;
+       struct device_node      *node = pdev->dev.of_node;
        int                     err;
+       u32                     val32;
 
-       pdata = tscadc_dev->dev->platform_data;
-       if (!pdata || !pdata->adc_init) {
-               dev_err(&pdev->dev, "Could not find platform data\n");
+       if (!node) {
+               dev_err(&pdev->dev, "Could not find valid DT data.\n");
                return -EINVAL;
        }
 
@@ -158,8 +188,13 @@ static int tiadc_probe(struct platform_device *pdev)
        }
        adc_dev = iio_priv(indio_dev);
 
-       adc_dev->mfd_tscadc = tscadc_dev;
-       adc_dev->channels = pdata->adc_init->adc_channels;
+       adc_dev->mfd_tscadc = ti_tscadc_dev_get(pdev);
+
+       err = of_property_read_u32(node,
+                       "ti,adc-channels", &val32);
+       if (err < 0)
+               goto err_free_device;
+       adc_dev->channels = val32;
 
        indio_dev->dev.parent = &pdev->dev;
        indio_dev->name = dev_name(&pdev->dev);
@@ -191,10 +226,15 @@ err_ret:
 static int tiadc_remove(struct platform_device *pdev)
 {
        struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+       struct tiadc_device *adc_dev = iio_priv(indio_dev);
+       u32 step_en;
 
        iio_device_unregister(indio_dev);
        tiadc_channels_remove(indio_dev);
 
+       step_en = get_adc_step_mask(adc_dev);
+       am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en);
+
        iio_device_free(indio_dev);
 
        return 0;
@@ -205,9 +245,10 @@ static int tiadc_suspend(struct device *dev)
 {
        struct iio_dev *indio_dev = dev_get_drvdata(dev);
        struct tiadc_device *adc_dev = iio_priv(indio_dev);
-       struct ti_tscadc_dev *tscadc_dev = dev->platform_data;
+       struct ti_tscadc_dev *tscadc_dev;
        unsigned int idle;
 
+       tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev));
        if (!device_may_wakeup(tscadc_dev->dev)) {
                idle = tiadc_readl(adc_dev, REG_CTRL);
                idle &= ~(CNTRLREG_TSCSSENB);
@@ -243,11 +284,18 @@ static const struct dev_pm_ops tiadc_pm_ops = {
 #define TIADC_PM_OPS NULL
 #endif
 
+static const struct of_device_id ti_adc_dt_ids[] = {
+       { .compatible = "ti,am3359-adc", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, ti_adc_dt_ids);
+
 static struct platform_driver tiadc_driver = {
        .driver = {
                .name   = "tiadc",
                .owner  = THIS_MODULE,
                .pm     = TIADC_PM_OPS,
+               .of_match_table = of_match_ptr(ti_adc_dt_ids),
        },
        .probe  = tiadc_probe,
        .remove = tiadc_remove,