Merge branch 'ib-5.8-jz47xx-ts' into HEAD
[platform/kernel/linux-rpi.git] / drivers / iio / adc / ingenic-adc.c
index 39c0a60..92b2508 100644 (file)
@@ -8,11 +8,14 @@
 
 #include <dt-bindings/iio/adc/ingenic,adc.h>
 #include <linux/clk.h>
+#include <linux/iio/buffer.h>
 #include <linux/iio/iio.h>
+#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/mod_devicetable.h>
 #include <linux/mutex.h>
 #include <linux/platform_device.h>
 
 #define JZ_ADC_REG_CFG                 0x04
 #define JZ_ADC_REG_CTRL                        0x08
 #define JZ_ADC_REG_STATUS              0x0c
+#define JZ_ADC_REG_ADSAME              0x10
+#define JZ_ADC_REG_ADWAIT              0x14
 #define JZ_ADC_REG_ADTCH               0x18
 #define JZ_ADC_REG_ADBDAT              0x1c
 #define JZ_ADC_REG_ADSDAT              0x20
+#define JZ_ADC_REG_ADCMD               0x24
 #define JZ_ADC_REG_ADCLK               0x28
 
 #define JZ_ADC_REG_ENABLE_PD           BIT(7)
 #define JZ_ADC_REG_CFG_AUX_MD          (BIT(0) | BIT(1))
 #define JZ_ADC_REG_CFG_BAT_MD          BIT(4)
+#define JZ_ADC_REG_CFG_SAMPLE_NUM(n)   ((n) << 10)
+#define JZ_ADC_REG_CFG_PULL_UP(n)      ((n) << 16)
+#define JZ_ADC_REG_CFG_CMD_SEL         BIT(22)
+#define JZ_ADC_REG_CFG_TOUCH_OPS_MASK  (BIT(31) | GENMASK(23, 10))
 #define JZ_ADC_REG_ADCLK_CLKDIV_LSB    0
 #define JZ4725B_ADC_REG_ADCLK_CLKDIV10US_LSB   16
 #define JZ4770_ADC_REG_ADCLK_CLKDIV10US_LSB    8
 #define JZ4770_ADC_REG_ADCLK_CLKDIVMS_LSB      16
 
+#define JZ_ADC_REG_ADCMD_YNADC         BIT(7)
+#define JZ_ADC_REG_ADCMD_YPADC         BIT(8)
+#define JZ_ADC_REG_ADCMD_XNADC         BIT(9)
+#define JZ_ADC_REG_ADCMD_XPADC         BIT(10)
+#define JZ_ADC_REG_ADCMD_VREFPYP       BIT(11)
+#define JZ_ADC_REG_ADCMD_VREFPXP       BIT(12)
+#define JZ_ADC_REG_ADCMD_VREFPXN       BIT(13)
+#define JZ_ADC_REG_ADCMD_VREFPAUX      BIT(14)
+#define JZ_ADC_REG_ADCMD_VREFPVDD33    BIT(15)
+#define JZ_ADC_REG_ADCMD_VREFNYN       BIT(16)
+#define JZ_ADC_REG_ADCMD_VREFNXP       BIT(17)
+#define JZ_ADC_REG_ADCMD_VREFNXN       BIT(18)
+#define JZ_ADC_REG_ADCMD_VREFAUX       BIT(19)
+#define JZ_ADC_REG_ADCMD_YNGRU         BIT(20)
+#define JZ_ADC_REG_ADCMD_XNGRU         BIT(21)
+#define JZ_ADC_REG_ADCMD_XPGRU         BIT(22)
+#define JZ_ADC_REG_ADCMD_YPSUP         BIT(23)
+#define JZ_ADC_REG_ADCMD_XNSUP         BIT(24)
+#define JZ_ADC_REG_ADCMD_XPSUP         BIT(25)
+
 #define JZ_ADC_AUX_VREF                                3300
 #define JZ_ADC_AUX_VREF_BITS                   12
 #define JZ_ADC_BATTERY_LOW_VREF                        2500
 #define JZ4770_ADC_BATTERY_VREF                        6600
 #define JZ4770_ADC_BATTERY_VREF_BITS           12
 
+#define JZ_ADC_IRQ_AUX                 BIT(0)
+#define JZ_ADC_IRQ_BATTERY             BIT(1)
+#define JZ_ADC_IRQ_TOUCH               BIT(2)
+#define JZ_ADC_IRQ_PEN_DOWN            BIT(3)
+#define JZ_ADC_IRQ_PEN_UP              BIT(4)
+#define JZ_ADC_IRQ_PEN_DOWN_SLEEP      BIT(5)
+#define JZ_ADC_IRQ_SLEEP               BIT(7)
+
 struct ingenic_adc;
 
 struct ingenic_adc_soc_data {
@@ -55,6 +93,8 @@ struct ingenic_adc_soc_data {
        size_t battery_scale_avail_size;
        unsigned int battery_vref_mode: 1;
        unsigned int has_aux2: 1;
+       const struct iio_chan_spec *channels;
+       unsigned int num_channels;
        int (*init_clk_div)(struct device *dev, struct ingenic_adc *adc);
 };
 
@@ -67,13 +107,67 @@ struct ingenic_adc {
        bool low_vref_mode;
 };
 
+static void ingenic_adc_set_adcmd(struct iio_dev *iio_dev, unsigned long mask)
+{
+       struct ingenic_adc *adc = iio_priv(iio_dev);
+
+       mutex_lock(&adc->lock);
+
+       /* Init ADCMD */
+       readl(adc->base + JZ_ADC_REG_ADCMD);
+
+       if (mask & 0x3) {
+               /* Second channel (INGENIC_ADC_TOUCH_YP): sample YP vs. GND */
+               writel(JZ_ADC_REG_ADCMD_XNGRU
+                      | JZ_ADC_REG_ADCMD_VREFNXN | JZ_ADC_REG_ADCMD_VREFPVDD33
+                      | JZ_ADC_REG_ADCMD_YPADC,
+                      adc->base + JZ_ADC_REG_ADCMD);
+
+               /* First channel (INGENIC_ADC_TOUCH_XP): sample XP vs. GND */
+               writel(JZ_ADC_REG_ADCMD_YNGRU
+                      | JZ_ADC_REG_ADCMD_VREFNYN | JZ_ADC_REG_ADCMD_VREFPVDD33
+                      | JZ_ADC_REG_ADCMD_XPADC,
+                      adc->base + JZ_ADC_REG_ADCMD);
+       }
+
+       if (mask & 0xc) {
+               /* Fourth channel (INGENIC_ADC_TOUCH_YN): sample YN vs. GND */
+               writel(JZ_ADC_REG_ADCMD_XNGRU
+                      | JZ_ADC_REG_ADCMD_VREFNXN | JZ_ADC_REG_ADCMD_VREFPVDD33
+                      | JZ_ADC_REG_ADCMD_YNADC,
+                      adc->base + JZ_ADC_REG_ADCMD);
+
+               /* Third channel (INGENIC_ADC_TOUCH_XN): sample XN vs. GND */
+               writel(JZ_ADC_REG_ADCMD_YNGRU
+                      | JZ_ADC_REG_ADCMD_VREFNYN | JZ_ADC_REG_ADCMD_VREFPVDD33
+                      | JZ_ADC_REG_ADCMD_XNADC,
+                      adc->base + JZ_ADC_REG_ADCMD);
+       }
+
+       if (mask & 0x30) {
+               /* Sixth channel (INGENIC_ADC_TOUCH_YD): sample YP vs. YN */
+               writel(JZ_ADC_REG_ADCMD_VREFNYN | JZ_ADC_REG_ADCMD_VREFPVDD33
+                      | JZ_ADC_REG_ADCMD_YPADC,
+                      adc->base + JZ_ADC_REG_ADCMD);
+
+               /* Fifth channel (INGENIC_ADC_TOUCH_XD): sample XP vs. XN */
+               writel(JZ_ADC_REG_ADCMD_VREFNXN | JZ_ADC_REG_ADCMD_VREFPVDD33
+                      | JZ_ADC_REG_ADCMD_XPADC,
+                      adc->base + JZ_ADC_REG_ADCMD);
+       }
+
+       /* We're done */
+       writel(0, adc->base + JZ_ADC_REG_ADCMD);
+
+       mutex_unlock(&adc->lock);
+}
+
 static void ingenic_adc_set_config(struct ingenic_adc *adc,
                                   uint32_t mask,
                                   uint32_t val)
 {
        uint32_t cfg;
 
-       clk_enable(adc->clk);
        mutex_lock(&adc->lock);
 
        cfg = readl(adc->base + JZ_ADC_REG_CFG) & ~mask;
@@ -81,7 +175,6 @@ static void ingenic_adc_set_config(struct ingenic_adc *adc,
        writel(cfg, adc->base + JZ_ADC_REG_CFG);
 
        mutex_unlock(&adc->lock);
-       clk_disable(adc->clk);
 }
 
 static void ingenic_adc_enable(struct ingenic_adc *adc,
@@ -124,6 +217,8 @@ static int ingenic_adc_write_raw(struct iio_dev *iio_dev,
                                 long m)
 {
        struct ingenic_adc *adc = iio_priv(iio_dev);
+       struct device *dev = iio_dev->dev.parent;
+       int ret;
 
        switch (m) {
        case IIO_CHAN_INFO_SCALE:
@@ -131,6 +226,14 @@ static int ingenic_adc_write_raw(struct iio_dev *iio_dev,
                case INGENIC_ADC_BATTERY:
                        if (!adc->soc_data->battery_vref_mode)
                                return -EINVAL;
+
+                       ret = clk_enable(adc->clk);
+                       if (ret) {
+                               dev_err(dev, "Failed to enable clock: %d\n",
+                                       ret);
+                               return ret;
+                       }
+
                        if (val > JZ_ADC_BATTERY_LOW_VREF) {
                                ingenic_adc_set_config(adc,
                                                       JZ_ADC_REG_CFG_BAT_MD,
@@ -142,6 +245,9 @@ static int ingenic_adc_write_raw(struct iio_dev *iio_dev,
                                                       JZ_ADC_REG_CFG_BAT_MD);
                                adc->low_vref_mode = true;
                        }
+
+                       clk_disable(adc->clk);
+
                        return 0;
                default:
                        return -EINVAL;
@@ -251,6 +357,127 @@ static int jz4770_adc_init_clk_div(struct device *dev, struct ingenic_adc *adc)
        return 0;
 }
 
+static const struct iio_chan_spec jz4740_channels[] = {
+       {
+               .extend_name = "aux",
+               .type = IIO_VOLTAGE,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+                                     BIT(IIO_CHAN_INFO_SCALE),
+               .indexed = 1,
+               .channel = INGENIC_ADC_AUX,
+               .scan_index = -1,
+       },
+       {
+               .extend_name = "battery",
+               .type = IIO_VOLTAGE,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+                                     BIT(IIO_CHAN_INFO_SCALE),
+               .info_mask_separate_available = BIT(IIO_CHAN_INFO_RAW) |
+                                               BIT(IIO_CHAN_INFO_SCALE),
+               .indexed = 1,
+               .channel = INGENIC_ADC_BATTERY,
+               .scan_index = -1,
+       },
+};
+
+static const struct iio_chan_spec jz4770_channels[] = {
+       {
+               .type = IIO_VOLTAGE,
+               .indexed = 1,
+               .channel = INGENIC_ADC_TOUCH_XP,
+               .scan_index = 0,
+               .scan_type = {
+                       .sign = 'u',
+                       .realbits = 12,
+                       .storagebits = 16,
+               },
+       },
+       {
+               .type = IIO_VOLTAGE,
+               .indexed = 1,
+               .channel = INGENIC_ADC_TOUCH_YP,
+               .scan_index = 1,
+               .scan_type = {
+                       .sign = 'u',
+                       .realbits = 12,
+                       .storagebits = 16,
+               },
+       },
+       {
+               .type = IIO_VOLTAGE,
+               .indexed = 1,
+               .channel = INGENIC_ADC_TOUCH_XN,
+               .scan_index = 2,
+               .scan_type = {
+                       .sign = 'u',
+                       .realbits = 12,
+                       .storagebits = 16,
+               },
+       },
+       {
+               .type = IIO_VOLTAGE,
+               .indexed = 1,
+               .channel = INGENIC_ADC_TOUCH_YN,
+               .scan_index = 3,
+               .scan_type = {
+                       .sign = 'u',
+                       .realbits = 12,
+                       .storagebits = 16,
+               },
+       },
+       {
+               .type = IIO_VOLTAGE,
+               .indexed = 1,
+               .channel = INGENIC_ADC_TOUCH_XD,
+               .scan_index = 4,
+               .scan_type = {
+                       .sign = 'u',
+                       .realbits = 12,
+                       .storagebits = 16,
+               },
+       },
+       {
+               .type = IIO_VOLTAGE,
+               .indexed = 1,
+               .channel = INGENIC_ADC_TOUCH_YD,
+               .scan_index = 5,
+               .scan_type = {
+                       .sign = 'u',
+                       .realbits = 12,
+                       .storagebits = 16,
+               },
+       },
+       {
+               .extend_name = "aux",
+               .type = IIO_VOLTAGE,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+                                     BIT(IIO_CHAN_INFO_SCALE),
+               .indexed = 1,
+               .channel = INGENIC_ADC_AUX,
+               .scan_index = -1,
+       },
+       {
+               .extend_name = "battery",
+               .type = IIO_VOLTAGE,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+                                     BIT(IIO_CHAN_INFO_SCALE),
+               .info_mask_separate_available = BIT(IIO_CHAN_INFO_RAW) |
+                                               BIT(IIO_CHAN_INFO_SCALE),
+               .indexed = 1,
+               .channel = INGENIC_ADC_BATTERY,
+               .scan_index = -1,
+       },
+       {
+               .extend_name = "aux2",
+               .type = IIO_VOLTAGE,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+                                     BIT(IIO_CHAN_INFO_SCALE),
+               .indexed = 1,
+               .channel = INGENIC_ADC_AUX2,
+               .scan_index = -1,
+       },
+};
+
 static const struct ingenic_adc_soc_data jz4725b_adc_soc_data = {
        .battery_high_vref = JZ4725B_ADC_BATTERY_HIGH_VREF,
        .battery_high_vref_bits = JZ4725B_ADC_BATTERY_HIGH_VREF_BITS,
@@ -260,6 +487,8 @@ static const struct ingenic_adc_soc_data jz4725b_adc_soc_data = {
        .battery_scale_avail_size = ARRAY_SIZE(jz4725b_adc_battery_scale_avail),
        .battery_vref_mode = true,
        .has_aux2 = false,
+       .channels = jz4740_channels,
+       .num_channels = ARRAY_SIZE(jz4740_channels),
        .init_clk_div = jz4725b_adc_init_clk_div,
 };
 
@@ -272,6 +501,8 @@ static const struct ingenic_adc_soc_data jz4740_adc_soc_data = {
        .battery_scale_avail_size = ARRAY_SIZE(jz4740_adc_battery_scale_avail),
        .battery_vref_mode = true,
        .has_aux2 = false,
+       .channels = jz4740_channels,
+       .num_channels = ARRAY_SIZE(jz4740_channels),
        .init_clk_div = NULL, /* no ADCLK register on JZ4740 */
 };
 
@@ -284,6 +515,8 @@ static const struct ingenic_adc_soc_data jz4770_adc_soc_data = {
        .battery_scale_avail_size = ARRAY_SIZE(jz4770_adc_battery_scale_avail),
        .battery_vref_mode = false,
        .has_aux2 = true,
+       .channels = jz4770_channels,
+       .num_channels = ARRAY_SIZE(jz4770_channels),
        .init_clk_div = jz4770_adc_init_clk_div,
 };
 
@@ -312,11 +545,19 @@ static int ingenic_adc_read_avail(struct iio_dev *iio_dev,
        };
 }
 
-static int ingenic_adc_read_chan_info_raw(struct ingenic_adc *adc,
+static int ingenic_adc_read_chan_info_raw(struct iio_dev *iio_dev,
                                          struct iio_chan_spec const *chan,
                                          int *val)
 {
        int bit, ret, engine = (chan->channel == INGENIC_ADC_BATTERY);
+       struct ingenic_adc *adc = iio_priv(iio_dev);
+
+       ret = clk_enable(adc->clk);
+       if (ret) {
+               dev_err(iio_dev->dev.parent, "Failed to enable clock: %d\n",
+                       ret);
+               return ret;
+       }
 
        /* We cannot sample AUX/AUX2 in parallel. */
        mutex_lock(&adc->aux_lock);
@@ -325,7 +566,6 @@ static int ingenic_adc_read_chan_info_raw(struct ingenic_adc *adc,
                ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_AUX_MD, bit);
        }
 
-       clk_enable(adc->clk);
        ret = ingenic_adc_capture(adc, engine);
        if (ret)
                goto out;
@@ -342,8 +582,8 @@ static int ingenic_adc_read_chan_info_raw(struct ingenic_adc *adc,
 
        ret = IIO_VAL_INT;
 out:
-       clk_disable(adc->clk);
        mutex_unlock(&adc->aux_lock);
+       clk_disable(adc->clk);
 
        return ret;
 }
@@ -358,7 +598,7 @@ static int ingenic_adc_read_raw(struct iio_dev *iio_dev,
 
        switch (m) {
        case IIO_CHAN_INFO_RAW:
-               return ingenic_adc_read_chan_info_raw(adc, chan, val);
+               return ingenic_adc_read_chan_info_raw(iio_dev, chan, val);
        case IIO_CHAN_INFO_SCALE:
                switch (chan->channel) {
                case INGENIC_ADC_AUX:
@@ -383,6 +623,21 @@ static int ingenic_adc_read_raw(struct iio_dev *iio_dev,
        }
 }
 
+static int ingenic_adc_of_xlate(struct iio_dev *iio_dev,
+                               const struct of_phandle_args *iiospec)
+{
+       int i;
+
+       if (!iiospec->args_count)
+               return -EINVAL;
+
+       for (i = 0; i < iio_dev->num_channels; ++i)
+               if (iio_dev->channels[i].channel == iiospec->args[0])
+                       return i;
+
+       return -EINVAL;
+}
+
 static void ingenic_adc_clk_cleanup(void *data)
 {
        clk_unprepare(data);
@@ -392,44 +647,92 @@ static const struct iio_info ingenic_adc_info = {
        .write_raw = ingenic_adc_write_raw,
        .read_raw = ingenic_adc_read_raw,
        .read_avail = ingenic_adc_read_avail,
+       .of_xlate = ingenic_adc_of_xlate,
 };
 
-static const struct iio_chan_spec ingenic_channels[] = {
-       {
-               .extend_name = "aux",
-               .type = IIO_VOLTAGE,
-               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
-                                     BIT(IIO_CHAN_INFO_SCALE),
-               .indexed = 1,
-               .channel = INGENIC_ADC_AUX,
-       },
-       {
-               .extend_name = "battery",
-               .type = IIO_VOLTAGE,
-               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
-                                     BIT(IIO_CHAN_INFO_SCALE),
-               .info_mask_separate_available = BIT(IIO_CHAN_INFO_RAW) |
-                                               BIT(IIO_CHAN_INFO_SCALE),
-               .indexed = 1,
-               .channel = INGENIC_ADC_BATTERY,
-       },
-       { /* Must always be last in the array. */
-               .extend_name = "aux2",
-               .type = IIO_VOLTAGE,
-               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
-                                     BIT(IIO_CHAN_INFO_SCALE),
-               .indexed = 1,
-               .channel = INGENIC_ADC_AUX2,
-       },
+static int ingenic_adc_buffer_enable(struct iio_dev *iio_dev)
+{
+       struct ingenic_adc *adc = iio_priv(iio_dev);
+       int ret;
+
+       ret = clk_enable(adc->clk);
+       if (ret) {
+               dev_err(iio_dev->dev.parent, "Failed to enable clock: %d\n",
+                       ret);
+               return ret;
+       }
+
+       /* It takes significant time for the touchscreen hw to stabilize. */
+       msleep(50);
+       ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_TOUCH_OPS_MASK,
+                              JZ_ADC_REG_CFG_SAMPLE_NUM(4) |
+                              JZ_ADC_REG_CFG_PULL_UP(4));
+
+       writew(80, adc->base + JZ_ADC_REG_ADWAIT);
+       writew(2, adc->base + JZ_ADC_REG_ADSAME);
+       writeb((u8)~JZ_ADC_IRQ_TOUCH, adc->base + JZ_ADC_REG_CTRL);
+       writel(0, adc->base + JZ_ADC_REG_ADTCH);
+
+       ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_CMD_SEL,
+                              JZ_ADC_REG_CFG_CMD_SEL);
+       ingenic_adc_set_adcmd(iio_dev, iio_dev->active_scan_mask[0]);
+
+       ingenic_adc_enable(adc, 2, true);
+
+       return 0;
+}
+
+static int ingenic_adc_buffer_disable(struct iio_dev *iio_dev)
+{
+       struct ingenic_adc *adc = iio_priv(iio_dev);
+
+       ingenic_adc_enable(adc, 2, false);
+
+       ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_CMD_SEL, 0);
+
+       writeb(0xff, adc->base + JZ_ADC_REG_CTRL);
+       writeb(0xff, adc->base + JZ_ADC_REG_STATUS);
+       ingenic_adc_set_config(adc, JZ_ADC_REG_CFG_TOUCH_OPS_MASK, 0);
+       writew(0, adc->base + JZ_ADC_REG_ADSAME);
+       writew(0, adc->base + JZ_ADC_REG_ADWAIT);
+       clk_disable(adc->clk);
+
+       return 0;
+}
+
+static const struct iio_buffer_setup_ops ingenic_buffer_setup_ops = {
+       .postenable = &ingenic_adc_buffer_enable,
+       .predisable = &ingenic_adc_buffer_disable
 };
 
+static irqreturn_t ingenic_adc_irq(int irq, void *data)
+{
+       struct iio_dev *iio_dev = data;
+       struct ingenic_adc *adc = iio_priv(iio_dev);
+       unsigned long mask = iio_dev->active_scan_mask[0];
+       unsigned int i;
+       u32 tdat[3];
+
+       for (i = 0; i < ARRAY_SIZE(tdat); mask >>= 2, i++) {
+               if (mask & 0x3)
+                       tdat[i] = readl(adc->base + JZ_ADC_REG_ADTCH);
+               else
+                       tdat[i] = 0;
+       }
+
+       iio_push_to_buffers(iio_dev, tdat);
+       writeb(JZ_ADC_IRQ_TOUCH, adc->base + JZ_ADC_REG_STATUS);
+
+       return IRQ_HANDLED;
+}
+
 static int ingenic_adc_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct iio_dev *iio_dev;
        struct ingenic_adc *adc;
        const struct ingenic_adc_soc_data *soc_data;
-       int ret;
+       int irq, ret;
 
        soc_data = device_get_match_data(dev);
        if (!soc_data)
@@ -444,6 +747,17 @@ static int ingenic_adc_probe(struct platform_device *pdev)
        mutex_init(&adc->aux_lock);
        adc->soc_data = soc_data;
 
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0)
+               return irq;
+
+       ret = devm_request_irq(dev, irq, ingenic_adc_irq, 0,
+                              dev_name(dev), iio_dev);
+       if (ret < 0) {
+               dev_err(dev, "Failed to request irq: %d\n", ret);
+               return ret;
+       }
+
        adc->base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(adc->base))
                return PTR_ERR(adc->base);
@@ -481,14 +795,11 @@ static int ingenic_adc_probe(struct platform_device *pdev)
                return ret;
        }
 
-       iio_dev->dev.parent = dev;
        iio_dev->name = "jz-adc";
-       iio_dev->modes = INDIO_DIRECT_MODE;
-       iio_dev->channels = ingenic_channels;
-       iio_dev->num_channels = ARRAY_SIZE(ingenic_channels);
-       /* Remove AUX2 from the list of supported channels. */
-       if (!adc->soc_data->has_aux2)
-               iio_dev->num_channels -= 1;
+       iio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
+       iio_dev->setup_ops = &ingenic_buffer_setup_ops;
+       iio_dev->channels = soc_data->channels;
+       iio_dev->num_channels = soc_data->num_channels;
        iio_dev->info = &ingenic_adc_info;
 
        ret = devm_iio_device_register(dev, iio_dev);
@@ -498,7 +809,6 @@ static int ingenic_adc_probe(struct platform_device *pdev)
        return ret;
 }
 
-#ifdef CONFIG_OF
 static const struct of_device_id ingenic_adc_of_match[] = {
        { .compatible = "ingenic,jz4725b-adc", .data = &jz4725b_adc_soc_data, },
        { .compatible = "ingenic,jz4740-adc", .data = &jz4740_adc_soc_data, },
@@ -506,12 +816,11 @@ static const struct of_device_id ingenic_adc_of_match[] = {
        { },
 };
 MODULE_DEVICE_TABLE(of, ingenic_adc_of_match);
-#endif
 
 static struct platform_driver ingenic_adc_driver = {
        .driver = {
                .name = "ingenic-adc",
-               .of_match_table = of_match_ptr(ingenic_adc_of_match),
+               .of_match_table = ingenic_adc_of_match,
        },
        .probe = ingenic_adc_probe,
 };