#ifndef IIO_ADC_AD7606_H_
 #define IIO_ADC_AD7606_H_
 
-#define AD760X_CHANNEL(num, mask) {                            \
+#define AD760X_CHANNEL(num, mask_sep, mask_type, mask_all) {   \
                .type = IIO_VOLTAGE,                            \
                .indexed = 1,                                   \
                .channel = num,                                 \
                .address = num,                                 \
-               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),   \
-               .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\
-               .info_mask_shared_by_all = mask,                \
+               .info_mask_separate = mask_sep,                 \
+               .info_mask_shared_by_type = mask_type,          \
+               .info_mask_shared_by_all = mask_all,            \
                .scan_index = num,                              \
                .scan_type = {                                  \
                        .sign = 's',                            \
                },                                              \
 }
 
-#define AD7605_CHANNEL(num)    \
-       AD760X_CHANNEL(num, 0)
+#define AD7605_CHANNEL(num)                            \
+       AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW),     \
+               BIT(IIO_CHAN_INFO_SCALE), 0)
 
-#define AD7606_CHANNEL(num)    \
-       AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO))
+#define AD7606_CHANNEL(num)                            \
+       AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW),     \
+               BIT(IIO_CHAN_INFO_SCALE),               \
+               BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO))
+
+#define AD7616_CHANNEL(num)    \
+       AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),\
+               0, BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO))
 
 /**
  * struct ad7606_chip_info - chip specific information
  * @complete           completion to indicate end of conversion
  * @trig               The IIO trigger associated with the device.
  * @data               buffer for reading data from the device
+ * @d16                        be16 buffer for reading data from the device
  */
 struct ad7606_state {
        struct device                   *dev;
         * 16 * 16-bit samples + 64-bit timestamp
         */
        unsigned short                  data[20] ____cacheline_aligned;
+       __be16                          d16[2];
 };
 
 /**
  * @read_block         function pointer for reading blocks of data
  * @sw_mode_config:    pointer to a function which configured the device
  *                     for software mode
+ * @reg_read   function pointer for reading spi register
+ * @reg_write  function pointer for writing spi register
+ * @write_mask function pointer for write spi register with mask
+ * @rd_wr_cmd  pointer to the function which calculates the spi address
  */
 struct ad7606_bus_ops {
        /* more methods added in future? */
        int (*read_block)(struct device *dev, int num, void *data);
        int (*sw_mode_config)(struct iio_dev *indio_dev);
+       int (*reg_read)(struct ad7606_state *st, unsigned int addr);
+       int (*reg_write)(struct ad7606_state *st,
+                               unsigned int addr,
+                               unsigned int val);
+       int (*write_mask)(struct ad7606_state *st,
+                                unsigned int addr,
+                                unsigned long mask,
+                                unsigned int val);
+       u16 (*rd_wr_cmd)(int addr, char isWriteOp);
 };
 
 int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
 
 
 #define MAX_SPI_FREQ_HZ                23500000        /* VDRIVE above 4.75 V */
 
+#define AD7616_CONFIGURATION_REGISTER  0x02
+#define AD7616_OS_MASK                 GENMASK(4, 2)
+#define AD7616_BURST_MODE              BIT(6)
+#define AD7616_SEQEN_MODE              BIT(5)
+#define AD7616_RANGE_CH_A_ADDR_OFF     0x04
+#define AD7616_RANGE_CH_B_ADDR_OFF     0x06
+/*
+ * Range of channels from a group are stored in 2 registers.
+ * 0, 1, 2, 3 in a register followed by 4, 5, 6, 7 in second register.
+ * For channels from second group(8-15) the order is the same, only with
+ * an offset of 2 for register address.
+ */
+#define AD7616_RANGE_CH_ADDR(ch)       ((ch) >> 2)
+/* The range of the channel is stored on 2 bits*/
+#define AD7616_RANGE_CH_MSK(ch)                (0b11 << (((ch) & 0b11) * 2))
+#define AD7616_RANGE_CH_MODE(ch, mode) ((mode) << ((((ch) & 0b11)) * 2))
+static const struct iio_chan_spec ad7616_sw_channels[] = {
+       IIO_CHAN_SOFT_TIMESTAMP(16),
+       AD7616_CHANNEL(0),
+       AD7616_CHANNEL(1),
+       AD7616_CHANNEL(2),
+       AD7616_CHANNEL(3),
+       AD7616_CHANNEL(4),
+       AD7616_CHANNEL(5),
+       AD7616_CHANNEL(6),
+       AD7616_CHANNEL(7),
+       AD7616_CHANNEL(8),
+       AD7616_CHANNEL(9),
+       AD7616_CHANNEL(10),
+       AD7616_CHANNEL(11),
+       AD7616_CHANNEL(12),
+       AD7616_CHANNEL(13),
+       AD7616_CHANNEL(14),
+       AD7616_CHANNEL(15),
+};
+
+static u16 ad7616_spi_rd_wr_cmd(int addr, char isWriteOp)
+{
+       /*
+        * The address of register consist of one w/r bit
+        * 6 bits of address followed by one reserved bit.
+        */
+       return ((addr & 0x7F) << 1) | ((isWriteOp & 0x1) << 7);
+}
+
 static int ad7606_spi_read_block(struct device *dev,
                                 int count, void *buf)
 {
        return 0;
 }
 
+static int ad7606_spi_reg_read(struct ad7606_state *st, unsigned int addr)
+{
+       struct spi_device *spi = to_spi_device(st->dev);
+       struct spi_transfer t[] = {
+               {
+                       .tx_buf = &st->d16[0],
+                       .len = 2,
+                       .cs_change = 0,
+               }, {
+                       .rx_buf = &st->d16[1],
+                       .len = 2,
+               },
+       };
+       int ret;
+
+       st->d16[0] = cpu_to_be16(st->bops->rd_wr_cmd(addr, 0) << 8);
+
+       ret = spi_sync_transfer(spi, t, ARRAY_SIZE(t));
+       if (ret < 0)
+               return ret;
+
+       return be16_to_cpu(st->d16[1]);
+}
+
+static int ad7606_spi_reg_write(struct ad7606_state *st,
+                               unsigned int addr,
+                               unsigned int val)
+{
+       struct spi_device *spi = to_spi_device(st->dev);
+
+       st->d16[0] = cpu_to_be16((st->bops->rd_wr_cmd(addr, 1) << 8) |
+                                 (val & 0x1FF));
+
+       return spi_write(spi, &st->d16[0], sizeof(st->d16[0]));
+}
+
+static int ad7606_spi_write_mask(struct ad7606_state *st,
+                                unsigned int addr,
+                                unsigned long mask,
+                                unsigned int val)
+{
+       int readval;
+
+       readval = st->bops->reg_read(st, addr);
+       if (readval < 0)
+               return readval;
+
+       readval &= ~mask;
+       readval |= val;
+
+       return st->bops->reg_write(st, addr, readval);
+}
+
+static int ad7616_write_scale_sw(struct iio_dev *indio_dev, int ch, int val)
+{
+       struct ad7606_state *st = iio_priv(indio_dev);
+       unsigned int ch_addr, mode, ch_index;
+
+
+       /*
+        * Ad7616 has 16 channels divided in group A and group B.
+        * The range of channels from A are stored in registers with address 4
+        * while channels from B are stored in register with address 6.
+        * The last bit from channels determines if it is from group A or B
+        * because the order of channels in iio is 0A, 0B, 1A, 1B...
+        */
+       ch_index = ch >> 1;
+
+       ch_addr = AD7616_RANGE_CH_ADDR(ch_index);
+
+       if ((ch & 0x1) == 0) /* channel A */
+               ch_addr += AD7616_RANGE_CH_A_ADDR_OFF;
+       else    /* channel B */
+               ch_addr += AD7616_RANGE_CH_B_ADDR_OFF;
+
+       /* 0b01 for 2.5v, 0b10 for 5v and 0b11 for 10v */
+       mode = AD7616_RANGE_CH_MODE(ch_index, ((val + 1) & 0b11));
+       return st->bops->write_mask(st, ch_addr, AD7616_RANGE_CH_MSK(ch_index),
+                                    mode);
+}
+
+static int ad7616_write_os_sw(struct iio_dev *indio_dev, int val)
+{
+       struct ad7606_state *st = iio_priv(indio_dev);
+
+       return st->bops->write_mask(st, AD7616_CONFIGURATION_REGISTER,
+                                    AD7616_OS_MASK, val << 2);
+}
+
+static int ad7616_sw_mode_config(struct iio_dev *indio_dev)
+{
+       struct ad7606_state *st = iio_priv(indio_dev);
+
+       /*
+        * Scale can be configured individually for each channel
+        * in software mode.
+        */
+       indio_dev->channels = ad7616_sw_channels;
+
+       st->write_scale = ad7616_write_scale_sw;
+       st->write_os = &ad7616_write_os_sw;
+
+       /* Activate Burst mode and SEQEN MODE */
+       return st->bops->write_mask(st,
+                             AD7616_CONFIGURATION_REGISTER,
+                             AD7616_BURST_MODE | AD7616_SEQEN_MODE,
+                             AD7616_BURST_MODE | AD7616_SEQEN_MODE);
+}
+
 static const struct ad7606_bus_ops ad7606_spi_bops = {
        .read_block = ad7606_spi_read_block,
 };
 
+static const struct ad7606_bus_ops ad7616_spi_bops = {
+       .read_block = ad7606_spi_read_block,
+       .reg_read = ad7606_spi_reg_read,
+       .reg_write = ad7606_spi_reg_write,
+       .write_mask = ad7606_spi_write_mask,
+       .rd_wr_cmd = ad7616_spi_rd_wr_cmd,
+       .sw_mode_config = ad7616_sw_mode_config,
+};
+
 static int ad7606_spi_probe(struct spi_device *spi)
 {
        const struct spi_device_id *id = spi_get_device_id(spi);
+       const struct ad7606_bus_ops *bops;
+
+       switch (id->driver_data) {
+       case ID_AD7616:
+               bops = &ad7616_spi_bops;
+               break;
+       default:
+               bops = &ad7606_spi_bops;
+               break;
+       }
 
        return ad7606_probe(&spi->dev, spi->irq, NULL,
                            id->name, id->driver_data,
-                           &ad7606_spi_bops);
+                           bops);
 }
 
 static const struct spi_device_id ad7606_id_table[] = {