root/drivers/iio/adc/ad4062.c
// SPDX-License-Identifier: GPL-2.0
/*
 * Analog Devices AD4062 I3C ADC driver
 *
 * Copyright 2025 Analog Devices Inc.
 */
#include <linux/array_size.h>
#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/devm-helpers.h>
#include <linux/err.h>
#include <linux/gpio/driver.h>
#include <linux/i3c/device.h>
#include <linux/i3c/master.h>
#include <linux/iio/buffer.h>
#include <linux/iio/events.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/interrupt.h>
#include <linux/jiffies.h>
#include <linux/math.h>
#include <linux/minmax.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/units.h>
#include <linux/unaligned.h>
#include <linux/util_macros.h>

#define AD4062_REG_INTERFACE_CONFIG_A                   0x00
#define AD4062_REG_DEVICE_CONFIG                        0x02
#define     AD4062_REG_DEVICE_CONFIG_POWER_MODE_MSK     GENMASK(1, 0)
#define     AD4062_REG_DEVICE_CONFIG_LOW_POWER_MODE     3
#define AD4062_REG_PROD_ID_1                            0x05
#define AD4062_REG_DEVICE_GRADE                         0x06
#define AD4062_REG_SCRATCH_PAD                          0x0A
#define AD4062_REG_VENDOR_H                             0x0D
#define AD4062_REG_STREAM_MODE                          0x0E
#define AD4062_REG_INTERFACE_STATUS                     0x11
#define AD4062_REG_MODE_SET                             0x20
#define     AD4062_REG_MODE_SET_ENTER_ADC               BIT(0)
#define AD4062_REG_ADC_MODES                            0x21
#define     AD4062_REG_ADC_MODES_MODE_MSK               GENMASK(1, 0)
#define AD4062_REG_ADC_CONFIG                           0x22
#define     AD4062_REG_ADC_CONFIG_REF_EN_MSK            BIT(5)
#define     AD4062_REG_ADC_CONFIG_SCALE_EN_MSK          BIT(4)
#define AD4062_REG_AVG_CONFIG                           0x23
#define AD4062_REG_GP_CONF                              0x24
#define     AD4062_REG_GP_CONF_MODE_MSK_0               GENMASK(2, 0)
#define     AD4062_REG_GP_CONF_MODE_MSK_1               GENMASK(6, 4)
#define AD4062_REG_INTR_CONF                            0x25
#define     AD4062_REG_INTR_CONF_EN_MSK_0               GENMASK(1, 0)
#define     AD4062_REG_INTR_CONF_EN_MSK_1               GENMASK(5, 4)
#define AD4062_REG_TIMER_CONFIG                         0x27
#define     AD4062_REG_TIMER_CONFIG_FS_MASK             GENMASK(7, 4)
#define AD4062_REG_MAX_LIMIT                            0x29
#define AD4062_REG_MIN_LIMIT                            0x2B
#define AD4062_REG_MAX_HYST                             0x2C
#define AD4062_REG_MIN_HYST                             0x2D
#define AD4062_REG_MON_VAL                              0x2F
#define AD4062_REG_ADC_IBI_EN                           0x31
#define AD4062_REG_ADC_IBI_EN_CONV_TRIGGER              BIT(2)
#define AD4062_REG_ADC_IBI_EN_MAX                       BIT(1)
#define AD4062_REG_ADC_IBI_EN_MIN                       BIT(0)
#define AD4062_REG_FUSE_CRC                             0x40
#define AD4062_REG_DEVICE_STATUS                        0x41
#define     AD4062_REG_DEVICE_STATUS_DEVICE_RESET       BIT(6)
#define AD4062_REG_IBI_STATUS                           0x48
#define AD4062_REG_CONV_READ_LSB                        0x50
#define AD4062_REG_CONV_READ_16BITS                     0x51
#define AD4062_REG_CONV_READ_32BITS                     0x53
#define AD4062_REG_CONV_TRIGGER_16BITS                  0x57
#define AD4062_REG_CONV_TRIGGER_32BITS                  0x59
#define AD4062_REG_CONV_AUTO                            0x61
#define AD4062_MAX_REG                                  AD4062_REG_CONV_AUTO

#define AD4062_MON_VAL_MIDDLE_POINT     0x8000

#define AD4062_I3C_VENDOR       0x0177
#define AD4062_SOFT_RESET       0x81
#define AD4060_PROD_ID          0x7A
#define AD4062_PROD_ID          0x7C

#define AD4062_GP_DISABLED      0x0
#define AD4062_GP_INTR          0x1
#define AD4062_GP_DRDY          0x2
#define AD4062_GP_STATIC_LOW    0x5
#define AD4062_GP_STATIC_HIGH   0x6

#define AD4062_LIMIT_BITS       12

#define AD4062_INTR_EN_NEITHER  0x0
#define AD4062_INTR_EN_EITHER   0x3

#define AD4062_TCONV_NS         270

enum ad4062_operation_mode {
        AD4062_SAMPLE_MODE = 0x0,
        AD4062_BURST_AVERAGING_MODE = 0x1,
        AD4062_MONITOR_MODE = 0x3,
};

struct ad4062_chip_info {
        const struct iio_chan_spec channels[1];
        const char *name;
        u16 prod_id;
        u16 avg_max;
};

enum {
        AD4062_SCAN_TYPE_SAMPLE,
        AD4062_SCAN_TYPE_BURST_AVG,
};

static const struct iio_scan_type ad4062_scan_type_12_s[] = {
        [AD4062_SCAN_TYPE_SAMPLE] = {
                .sign = 's',
                .realbits = 12,
                .storagebits = 16,
                .endianness = IIO_BE,
        },
        [AD4062_SCAN_TYPE_BURST_AVG] = {
                .sign = 's',
                .realbits = 14,
                .storagebits = 16,
                .endianness = IIO_BE,
        },
};

static const struct iio_scan_type ad4062_scan_type_16_s[] = {
        [AD4062_SCAN_TYPE_SAMPLE] = {
                .sign = 's',
                .realbits = 16,
                .storagebits = 16,
                .endianness = IIO_BE,
        },
        [AD4062_SCAN_TYPE_BURST_AVG] = {
                .sign = 's',
                .realbits = 20,
                .storagebits = 32,
                .endianness = IIO_BE,
        },
};

static const unsigned int ad4062_conversion_freqs[] = {
        2000000, 1000000, 300000, 100000,       /*  0 -  3 */
        33300, 10000, 3000, 500,                /*  4 -  7 */
        333, 250, 200, 166,                     /*  8 - 11 */
        140, 124, 111,                          /* 12 - 15 */
};

struct ad4062_state {
        const struct ad4062_chip_info *chip;
        const struct ad4062_bus_ops *ops;
        enum ad4062_operation_mode mode;
        struct work_struct trig_conv;
        struct completion completion;
        struct iio_trigger *trigger;
        struct iio_dev *indio_dev;
        struct i3c_device *i3cdev;
        struct regmap *regmap;
        bool wait_event;
        int vref_uV;
        unsigned int samp_freqs[ARRAY_SIZE(ad4062_conversion_freqs)];
        bool gpo_irq[2];
        u16 sampling_frequency;
        u16 events_frequency;
        u8 oversamp_ratio;
        u8 conv_sizeof;
        u8 conv_addr;
        union {
                __be32 be32;
                __be16 be16;
        } buf __aligned(IIO_DMA_MINALIGN);
};

static const struct regmap_range ad4062_regmap_rd_ranges[] = {
        regmap_reg_range(AD4062_REG_INTERFACE_CONFIG_A, AD4062_REG_DEVICE_GRADE),
        regmap_reg_range(AD4062_REG_SCRATCH_PAD, AD4062_REG_INTERFACE_STATUS),
        regmap_reg_range(AD4062_REG_MODE_SET, AD4062_REG_ADC_IBI_EN),
        regmap_reg_range(AD4062_REG_FUSE_CRC, AD4062_REG_IBI_STATUS),
        regmap_reg_range(AD4062_REG_CONV_READ_LSB, AD4062_REG_CONV_AUTO),
};

static const struct regmap_access_table ad4062_regmap_rd_table = {
        .yes_ranges = ad4062_regmap_rd_ranges,
        .n_yes_ranges = ARRAY_SIZE(ad4062_regmap_rd_ranges),
};

static const struct regmap_range ad4062_regmap_wr_ranges[] = {
        regmap_reg_range(AD4062_REG_INTERFACE_CONFIG_A, AD4062_REG_DEVICE_CONFIG),
        regmap_reg_range(AD4062_REG_SCRATCH_PAD, AD4062_REG_SCRATCH_PAD),
        regmap_reg_range(AD4062_REG_STREAM_MODE, AD4062_REG_INTERFACE_STATUS),
        regmap_reg_range(AD4062_REG_MODE_SET, AD4062_REG_ADC_IBI_EN),
        regmap_reg_range(AD4062_REG_FUSE_CRC, AD4062_REG_DEVICE_STATUS),
};

static const struct regmap_access_table ad4062_regmap_wr_table = {
        .yes_ranges = ad4062_regmap_wr_ranges,
        .n_yes_ranges = ARRAY_SIZE(ad4062_regmap_wr_ranges),
};

static const struct iio_event_spec ad4062_events[] = {
        {
                .type = IIO_EV_TYPE_THRESH,
                .dir = IIO_EV_DIR_EITHER,
                .mask_shared_by_all = BIT(IIO_EV_INFO_ENABLE),
        },
        {
                .type = IIO_EV_TYPE_THRESH,
                .dir = IIO_EV_DIR_RISING,
                .mask_shared_by_all = BIT(IIO_EV_INFO_VALUE) |
                                      BIT(IIO_EV_INFO_HYSTERESIS),
        },
        {
                .type = IIO_EV_TYPE_THRESH,
                .dir = IIO_EV_DIR_FALLING,
                .mask_shared_by_all = BIT(IIO_EV_INFO_VALUE) |
                                      BIT(IIO_EV_INFO_HYSTERESIS),
        },
};

#define AD4062_CHAN(bits) {                                                             \
        .type = IIO_VOLTAGE,                                                            \
        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_RAW) |                            \
                                    BIT(IIO_CHAN_INFO_SCALE) |                          \
                                    BIT(IIO_CHAN_INFO_CALIBSCALE) |                     \
                                    BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),              \
        .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),                        \
        .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),    \
        .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_SAMP_FREQ),              \
        .indexed = 1,                                                                   \
        .channel = 0,                                                                   \
        .event_spec = ad4062_events,                                                    \
        .num_event_specs = ARRAY_SIZE(ad4062_events),                                   \
        .has_ext_scan_type = 1,                                                         \
        .ext_scan_type = ad4062_scan_type_##bits##_s,                                   \
        .num_ext_scan_type = ARRAY_SIZE(ad4062_scan_type_##bits##_s),                   \
}

static const struct ad4062_chip_info ad4060_chip_info = {
        .name = "ad4060",
        .channels = { AD4062_CHAN(12) },
        .prod_id = AD4060_PROD_ID,
        .avg_max = 256,
};

static const struct ad4062_chip_info ad4062_chip_info = {
        .name = "ad4062",
        .channels = { AD4062_CHAN(16) },
        .prod_id = AD4062_PROD_ID,
        .avg_max = 4096,
};

static ssize_t sampling_frequency_show(struct device *dev,
                                       struct device_attribute *attr, char *buf)
{
        struct ad4062_state *st = iio_priv(dev_to_iio_dev(dev));

        return sysfs_emit(buf, "%d\n", ad4062_conversion_freqs[st->events_frequency]);
}

static int sampling_frequency_store_dispatch(struct iio_dev *indio_dev,
                                             const char *buf)
{
        struct ad4062_state *st = iio_priv(indio_dev);
        int val, ret;

        if (st->wait_event)
                return -EBUSY;

        ret = kstrtoint(buf, 10, &val);
        if (ret)
                return ret;

        st->events_frequency = find_closest_descending(val, ad4062_conversion_freqs,
                                                       ARRAY_SIZE(ad4062_conversion_freqs));
        return 0;
}

static ssize_t sampling_frequency_store(struct device *dev,
                                        struct device_attribute *attr,
                                        const char *buf, size_t len)
{
        struct iio_dev *indio_dev = dev_to_iio_dev(dev);
        int ret;

        if (!iio_device_claim_direct(indio_dev))
                return -EBUSY;

        ret = sampling_frequency_store_dispatch(indio_dev, buf);
        iio_device_release_direct(indio_dev);
        return ret ?: len;
}

static IIO_DEVICE_ATTR_RW(sampling_frequency, 0);

static ssize_t sampling_frequency_available_show(struct device *dev,
                                                 struct device_attribute *attr,
                                                 char *buf)
{
        int ret = 0;

        for (u8 i = 0; i < ARRAY_SIZE(ad4062_conversion_freqs); i++)
                ret += sysfs_emit_at(buf, ret, "%d%s", ad4062_conversion_freqs[i],
                                     i != (ARRAY_SIZE(ad4062_conversion_freqs) - 1) ? " " : "\n");
        return ret;
}

static IIO_DEVICE_ATTR_RO(sampling_frequency_available, 0);

static struct attribute *ad4062_event_attributes[] = {
        &iio_dev_attr_sampling_frequency.dev_attr.attr,
        &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
        NULL
};

static const struct attribute_group ad4062_event_attribute_group = {
        .attrs = ad4062_event_attributes,
};

static int ad4062_set_oversampling_ratio(struct ad4062_state *st, int val, int val2)
{
        const u32 _max = st->chip->avg_max;
        const u32 _min = 1;
        int ret;

        if (!in_range(val, _min, _max) || val2 != 0)
                return -EINVAL;

        /* 1 disables oversampling */
        val = ilog2(val);
        if (val == 0) {
                st->mode = AD4062_SAMPLE_MODE;
        } else {
                st->mode = AD4062_BURST_AVERAGING_MODE;
                ret = regmap_write(st->regmap, AD4062_REG_AVG_CONFIG, val - 1);
                if (ret)
                        return ret;
        }
        st->oversamp_ratio = val;

        return 0;
}

static int ad4062_get_oversampling_ratio(struct ad4062_state *st, int *val)
{
        int ret, buf;

        if (st->mode == AD4062_SAMPLE_MODE) {
                *val = 1;
                return 0;
        }

        ret = regmap_read(st->regmap, AD4062_REG_AVG_CONFIG, &buf);
        if (ret)
                return ret;

        *val = BIT(buf + 1);
        return 0;
}

static int ad4062_calc_sampling_frequency(unsigned int fosc, unsigned int oversamp_ratio)
{
        /* From datasheet p.31: (n_avg - 1)/fosc + tconv */
        u32 n_avg = BIT(oversamp_ratio) - 1;
        u32 period_ns = NSEC_PER_SEC / fosc;

        /* Result is less than 1 Hz */
        if (n_avg >= fosc)
                return 1;

        return NSEC_PER_SEC / (n_avg * period_ns + AD4062_TCONV_NS);
}

static int ad4062_populate_sampling_frequency(struct ad4062_state *st)
{
        for (u8 i = 0; i < ARRAY_SIZE(ad4062_conversion_freqs); i++)
                st->samp_freqs[i] =
                        ad4062_calc_sampling_frequency(ad4062_conversion_freqs[i],
                                                       st->oversamp_ratio);
        return 0;
}

static int ad4062_get_sampling_frequency(struct ad4062_state *st, int *val)
{
        int freq = ad4062_conversion_freqs[st->sampling_frequency];

        *val = ad4062_calc_sampling_frequency(freq, st->oversamp_ratio);
        return IIO_VAL_INT;
}

static int ad4062_set_sampling_frequency(struct ad4062_state *st, int val, int val2)
{
        int ret;

        if (val2 != 0)
                return -EINVAL;

        ret = ad4062_populate_sampling_frequency(st);
        if (ret)
                return ret;

        st->sampling_frequency =
                find_closest_descending(val, st->samp_freqs,
                                        ARRAY_SIZE(ad4062_conversion_freqs));
        return 0;
}

static int ad4062_check_ids(struct ad4062_state *st)
{
        struct device *dev = &st->i3cdev->dev;
        int ret;
        u16 val;

        ret = regmap_bulk_read(st->regmap, AD4062_REG_PROD_ID_1,
                               &st->buf.be16, sizeof(st->buf.be16));
        if (ret)
                return ret;

        val = be16_to_cpu(st->buf.be16);
        if (val != st->chip->prod_id)
                dev_warn(dev, "Production ID x%x does not match known values", val);

        ret = regmap_bulk_read(st->regmap, AD4062_REG_VENDOR_H,
                               &st->buf.be16, sizeof(st->buf.be16));
        if (ret)
                return ret;

        val = be16_to_cpu(st->buf.be16);
        if (val != AD4062_I3C_VENDOR) {
                dev_err(dev, "Vendor ID x%x does not match expected value\n", val);
                return -ENODEV;
        }

        return 0;
}

static int ad4062_conversion_frequency_set(struct ad4062_state *st, u8 val)
{
        return regmap_write(st->regmap, AD4062_REG_TIMER_CONFIG,
                            FIELD_PREP(AD4062_REG_TIMER_CONFIG_FS_MASK, val));
}

static int ad4062_set_operation_mode(struct ad4062_state *st,
                                     enum ad4062_operation_mode mode)
{
        const unsigned int samp_freq = mode == AD4062_MONITOR_MODE ?
                                       st->events_frequency : st->sampling_frequency;
        int ret;

        ret = ad4062_conversion_frequency_set(st, samp_freq);
        if (ret)
                return ret;

        ret = regmap_update_bits(st->regmap, AD4062_REG_ADC_MODES,
                                 AD4062_REG_ADC_MODES_MODE_MSK, mode);
        if (ret)
                return ret;

        if (mode == AD4062_MONITOR_MODE) {
                /* Change address pointer to enter monitor mode */
                struct i3c_xfer xfer_trigger = {
                        .data.out = &st->conv_addr,
                        .len = sizeof(st->conv_addr),
                        .rnw = false,
                };
                st->conv_addr = AD4062_REG_CONV_TRIGGER_32BITS;
                return i3c_device_do_xfers(st->i3cdev, &xfer_trigger, 1, I3C_SDR);
        }

        return regmap_write(st->regmap, AD4062_REG_MODE_SET,
                            AD4062_REG_MODE_SET_ENTER_ADC);
}

static int ad4062_soft_reset(struct ad4062_state *st)
{
        u8 val = AD4062_SOFT_RESET;
        int ret;

        ret = regmap_write(st->regmap, AD4062_REG_INTERFACE_CONFIG_A, val);
        if (ret)
                return ret;

        /* Wait AD4062 treset time, datasheet p8 */
        ndelay(60);

        return 0;
}

static int ad4062_setup(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
                        const bool *ref_sel)
{
        struct ad4062_state *st = iio_priv(indio_dev);
        const struct iio_scan_type *scan_type;
        int ret;

        scan_type = iio_get_current_scan_type(indio_dev, chan);
        if (IS_ERR(scan_type))
                return PTR_ERR(scan_type);

        ret = regmap_update_bits(st->regmap, AD4062_REG_GP_CONF,
                                 AD4062_REG_GP_CONF_MODE_MSK_0,
                                 FIELD_PREP(AD4062_REG_GP_CONF_MODE_MSK_0,
                                            AD4062_GP_INTR));
        if (ret)
                return ret;

        ret = regmap_update_bits(st->regmap, AD4062_REG_GP_CONF,
                                 AD4062_REG_GP_CONF_MODE_MSK_1,
                                 FIELD_PREP(AD4062_REG_GP_CONF_MODE_MSK_1,
                                            AD4062_GP_DRDY));
        if (ret)
                return ret;

        ret = regmap_update_bits(st->regmap, AD4062_REG_ADC_CONFIG,
                                 AD4062_REG_ADC_CONFIG_REF_EN_MSK,
                                 FIELD_PREP(AD4062_REG_ADC_CONFIG_REF_EN_MSK,
                                            *ref_sel));
        if (ret)
                return ret;

        ret = regmap_write(st->regmap, AD4062_REG_DEVICE_STATUS,
                           AD4062_REG_DEVICE_STATUS_DEVICE_RESET);
        if (ret)
                return ret;

        ret = regmap_update_bits(st->regmap, AD4062_REG_INTR_CONF,
                                 AD4062_REG_INTR_CONF_EN_MSK_0,
                                 FIELD_PREP(AD4062_REG_INTR_CONF_EN_MSK_0,
                                            AD4062_INTR_EN_EITHER));
        if (ret)
                return ret;

        ret = regmap_update_bits(st->regmap, AD4062_REG_INTR_CONF,
                                 AD4062_REG_INTR_CONF_EN_MSK_1,
                                 FIELD_PREP(AD4062_REG_INTR_CONF_EN_MSK_1,
                                            AD4062_INTR_EN_NEITHER));
        if (ret)
                return ret;

        st->buf.be16 = cpu_to_be16(AD4062_MON_VAL_MIDDLE_POINT);
        return regmap_bulk_write(st->regmap, AD4062_REG_MON_VAL,
                                 &st->buf.be16, sizeof(st->buf.be16));
}

static irqreturn_t ad4062_irq_handler_thresh(int irq, void *private)
{
        struct iio_dev *indio_dev = private;

        iio_push_event(indio_dev,
                       IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 0,
                                            IIO_EV_TYPE_THRESH,
                                            IIO_EV_DIR_EITHER),
                       iio_get_time_ns(indio_dev));

        return IRQ_HANDLED;
}

static irqreturn_t ad4062_irq_handler_drdy(int irq, void *private)
{
        struct iio_dev *indio_dev = private;
        struct ad4062_state *st = iio_priv(indio_dev);

        if (iio_buffer_enabled(indio_dev) && iio_trigger_using_own(indio_dev))
                iio_trigger_poll(st->trigger);
        else
                complete(&st->completion);

        return IRQ_HANDLED;
}

static void ad4062_ibi_handler(struct i3c_device *i3cdev,
                               const struct i3c_ibi_payload *payload)
{
        struct ad4062_state *st = i3cdev_get_drvdata(i3cdev);

        if (st->wait_event) {
                iio_push_event(st->indio_dev,
                               IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 0,
                                                    IIO_EV_TYPE_THRESH,
                                                    IIO_EV_DIR_EITHER),
                               iio_get_time_ns(st->indio_dev));
                return;
        }
        if (iio_buffer_enabled(st->indio_dev))
                iio_trigger_poll_nested(st->trigger);
        else
                complete(&st->completion);
}

static void ad4062_trigger_work(struct work_struct *work)
{
        struct ad4062_state *st =
                container_of(work, struct ad4062_state, trig_conv);
        int ret;

        /*
         * Read current conversion, if at reg CONV_READ, stop bit triggers
         * next sample and does not need writing the address.
         */
        struct i3c_xfer xfer_sample = {
                .data.in = &st->buf.be32,
                .len = st->conv_sizeof,
                .rnw = true,
        };
        struct i3c_xfer xfer_trigger = {
                .data.out = &st->conv_addr,
                .len = sizeof(st->conv_addr),
                .rnw = false,
        };

        ret = i3c_device_do_xfers(st->i3cdev, &xfer_sample, 1, I3C_SDR);
        if (ret)
                return;

        iio_push_to_buffers_with_ts(st->indio_dev, &st->buf.be32, st->conv_sizeof,
                                    iio_get_time_ns(st->indio_dev));
        if (st->gpo_irq[1])
                return;

        i3c_device_do_xfers(st->i3cdev, &xfer_trigger, 1, I3C_SDR);
}

static irqreturn_t ad4062_poll_handler(int irq, void *p)
{
        struct iio_poll_func *pf = p;
        struct iio_dev *indio_dev = pf->indio_dev;
        struct ad4062_state *st = iio_priv(indio_dev);

        iio_trigger_notify_done(indio_dev->trig);
        schedule_work(&st->trig_conv);

        return IRQ_HANDLED;
}

static void ad4062_disable_ibi(void *data)
{
        struct i3c_device *i3cdev = data;

        i3c_device_disable_ibi(i3cdev);
}

static void ad4062_free_ibi(void *data)
{
        struct i3c_device *i3cdev = data;

        i3c_device_free_ibi(i3cdev);
}

static int ad4062_request_ibi(struct i3c_device *i3cdev)
{
        const struct i3c_ibi_setup ibireq = {
                .max_payload_len = 1,
                .num_slots = 1,
                .handler = ad4062_ibi_handler,
        };
        int ret;

        ret = i3c_device_request_ibi(i3cdev, &ibireq);
        if (ret)
                return ret;

        ret = devm_add_action_or_reset(&i3cdev->dev, ad4062_free_ibi, i3cdev);
        if (ret)
                return ret;

        ret = i3c_device_enable_ibi(i3cdev);
        if (ret)
                return ret;

        return devm_add_action_or_reset(&i3cdev->dev, ad4062_disable_ibi, i3cdev);
}

static int ad4062_request_irq(struct iio_dev *indio_dev)
{
        struct ad4062_state *st = iio_priv(indio_dev);
        struct device *dev = &st->i3cdev->dev;
        int ret;

        ret = fwnode_irq_get_byname(dev_fwnode(&st->i3cdev->dev), "gp0");
        if (ret == -EPROBE_DEFER)
                return ret;

        if (ret < 0) {
                st->gpo_irq[0] = false;
                ret = regmap_update_bits(st->regmap, AD4062_REG_ADC_IBI_EN,
                                         AD4062_REG_ADC_IBI_EN_MAX | AD4062_REG_ADC_IBI_EN_MIN,
                                         AD4062_REG_ADC_IBI_EN_MAX | AD4062_REG_ADC_IBI_EN_MIN);
                if (ret)
                        return ret;
        } else {
                st->gpo_irq[0] = true;
                ret = devm_request_threaded_irq(dev, ret, NULL,
                                                ad4062_irq_handler_thresh,
                                                IRQF_ONESHOT, indio_dev->name,
                                                indio_dev);
                if (ret)
                        return ret;
        }

        ret = fwnode_irq_get_byname(dev_fwnode(&st->i3cdev->dev), "gp1");
        if (ret == -EPROBE_DEFER)
                return ret;

        if (ret < 0) {
                st->gpo_irq[1] = false;
                return regmap_update_bits(st->regmap, AD4062_REG_ADC_IBI_EN,
                                          AD4062_REG_ADC_IBI_EN_CONV_TRIGGER,
                                          AD4062_REG_ADC_IBI_EN_CONV_TRIGGER);
        }
        st->gpo_irq[1] = true;

        return devm_request_irq(dev, ret, ad4062_irq_handler_drdy,
                                IRQF_NO_THREAD, indio_dev->name, indio_dev);
}

static const struct iio_trigger_ops ad4062_trigger_ops = {
        .validate_device = &iio_trigger_validate_own_device,
};

static int ad4062_request_trigger(struct iio_dev *indio_dev)
{
        struct ad4062_state *st = iio_priv(indio_dev);
        struct device *dev = &st->i3cdev->dev;
        int ret;

        st->trigger = devm_iio_trigger_alloc(dev, "%s-dev%d",
                                             indio_dev->name,
                                             iio_device_id(indio_dev));
        if (!st->trigger)
                return -ENOMEM;

        st->trigger->ops = &ad4062_trigger_ops;
        iio_trigger_set_drvdata(st->trigger, indio_dev);

        ret = devm_iio_trigger_register(dev, st->trigger);
        if (ret)
                return ret;

        indio_dev->trig = iio_trigger_get(st->trigger);

        return 0;
}

static const int ad4062_oversampling_avail[] = {
        1, 2, 4, 8, 16, 32, 64, 128,            /*  0 -  7 */
        256, 512, 1024, 2048, 4096,             /*  8 - 12 */
};

static int ad4062_read_avail(struct iio_dev *indio_dev,
                             struct iio_chan_spec const *chan, const int **vals,
                             int *type, int *len, long mask)
{
        struct ad4062_state *st = iio_priv(indio_dev);
        int ret;

        switch (mask) {
        case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
                *vals = ad4062_oversampling_avail;
                *len = ARRAY_SIZE(ad4062_oversampling_avail);
                *len -= st->chip->avg_max == 256 ? 4 : 0;
                *type = IIO_VAL_INT;

                return IIO_AVAIL_LIST;
        case IIO_CHAN_INFO_SAMP_FREQ:
                ret = ad4062_populate_sampling_frequency(st);
                if (ret)
                        return ret;
                *vals = st->samp_freqs;
                *len = st->oversamp_ratio ? ARRAY_SIZE(ad4062_conversion_freqs) : 1;
                *type = IIO_VAL_INT;

                return IIO_AVAIL_LIST;
        default:
                return -EINVAL;
        }
}

static int ad4062_get_chan_scale(struct iio_dev *indio_dev, int *val, int *val2)
{
        struct ad4062_state *st = iio_priv(indio_dev);
        const struct iio_scan_type *scan_type;

        /*
         * In burst averaging mode the averaging filter accumulates resulting
         * in a sample with increased precision.
         */
        scan_type = iio_get_current_scan_type(indio_dev, st->chip->channels);
        if (IS_ERR(scan_type))
                return PTR_ERR(scan_type);

        *val = (st->vref_uV * 2) / (MICRO / MILLI); /* signed */
        *val2 = scan_type->realbits - 1;

        return IIO_VAL_FRACTIONAL_LOG2;
}

static int ad4062_get_chan_calibscale(struct ad4062_state *st, int *val, int *val2)
{
        int ret;

        ret = regmap_bulk_read(st->regmap, AD4062_REG_MON_VAL,
                               &st->buf.be16, sizeof(st->buf.be16));
        if (ret)
                return ret;

        /* From datasheet: code out = code in × mon_val/0x8000 */
        *val = be16_to_cpu(st->buf.be16) * 2;
        *val2 = 16;

        return IIO_VAL_FRACTIONAL_LOG2;
}

static int ad4062_set_chan_calibscale(struct ad4062_state *st, int gain_int,
                                      int gain_frac)
{
        /* Divide numerator and denumerator by known great common divider */
        const u32 mon_val = AD4062_MON_VAL_MIDDLE_POINT / 64;
        const u32 micro = MICRO / 64;
        const u32 gain_fp = gain_int * MICRO + gain_frac;
        const u32 reg_val = DIV_ROUND_CLOSEST(gain_fp * mon_val, micro);
        int ret;

        /* Checks if the gain is in range and the value fits the field */
        if (gain_int < 0 || gain_int > 1 || reg_val > BIT(16) - 1)
                return -EINVAL;

        st->buf.be16 = cpu_to_be16(reg_val);
        ret = regmap_bulk_write(st->regmap, AD4062_REG_MON_VAL,
                                &st->buf.be16, sizeof(st->buf.be16));
        if (ret)
                return ret;

        /* Enable scale if gain is not equal to one */
        return regmap_update_bits(st->regmap, AD4062_REG_ADC_CONFIG,
                                  AD4062_REG_ADC_CONFIG_SCALE_EN_MSK,
                                  FIELD_PREP(AD4062_REG_ADC_CONFIG_SCALE_EN_MSK,
                                             !(gain_int == 1 && gain_frac == 0)));
}

static int ad4062_read_chan_raw(struct ad4062_state *st, int *val)
{
        struct i3c_device *i3cdev = st->i3cdev;
        struct i3c_xfer xfer_trigger = {
                .data.out = &st->conv_addr,
                .len = sizeof(st->conv_addr),
                .rnw = false,
        };
        struct i3c_xfer xfer_sample = {
                .data.in = &st->buf.be32,
                .len = sizeof(st->buf.be32),
                .rnw = true,
        };
        int ret;

        PM_RUNTIME_ACQUIRE(&st->i3cdev->dev, pm);
        ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
        if (ret)
                return ret;

        ret = ad4062_set_operation_mode(st, st->mode);
        if (ret)
                return ret;

        reinit_completion(&st->completion);
        /* Change address pointer to trigger conversion */
        st->conv_addr = AD4062_REG_CONV_TRIGGER_32BITS;
        ret = i3c_device_do_xfers(i3cdev, &xfer_trigger, 1, I3C_SDR);
        if (ret)
                return ret;
        /*
         * Single sample read should be used only for oversampling and
         * sampling frequency pairs that take less than 1 sec.
         */
        ret = wait_for_completion_timeout(&st->completion,
                                          msecs_to_jiffies(1000));
        if (!ret)
                return -ETIMEDOUT;

        ret = i3c_device_do_xfers(i3cdev, &xfer_sample, 1, I3C_SDR);
        if (ret)
                return ret;
        *val = be32_to_cpu(st->buf.be32);
        return 0;
}

static int ad4062_read_raw_dispatch(struct ad4062_state *st,
                                    int *val, int *val2, long info)
{
        if (st->wait_event)
                return -EBUSY;

        switch (info) {
        case IIO_CHAN_INFO_RAW:
                return ad4062_read_chan_raw(st, val);

        case IIO_CHAN_INFO_CALIBSCALE:
                return ad4062_get_chan_calibscale(st, val, val2);

        case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
                return ad4062_get_oversampling_ratio(st, val);

        default:
                return -EINVAL;
        }
}

static int ad4062_read_raw(struct iio_dev *indio_dev,
                           struct iio_chan_spec const *chan,
                           int *val, int *val2, long info)
{
        struct ad4062_state *st = iio_priv(indio_dev);
        int ret;

        switch (info) {
        case IIO_CHAN_INFO_SCALE:
                return ad4062_get_chan_scale(indio_dev, val, val2);

        case IIO_CHAN_INFO_SAMP_FREQ:
                return ad4062_get_sampling_frequency(st, val);
        }

        if (!iio_device_claim_direct(indio_dev))
                return -EBUSY;

        ret = ad4062_read_raw_dispatch(st, val, val2, info);
        iio_device_release_direct(indio_dev);
        return ret ?: IIO_VAL_INT;
}

static int ad4062_write_raw_dispatch(struct ad4062_state *st, int val, int val2,
                                     long info)
{
        if (st->wait_event)
                return -EBUSY;

        switch (info) {
        case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
                return ad4062_set_oversampling_ratio(st, val, val2);

        case IIO_CHAN_INFO_CALIBSCALE:
                return ad4062_set_chan_calibscale(st, val, val2);

        default:
                return -EINVAL;
        }
}

static int ad4062_write_raw(struct iio_dev *indio_dev,
                            struct iio_chan_spec const *chan, int val,
                            int val2, long info)
{
        struct ad4062_state *st = iio_priv(indio_dev);
        int ret;

        switch (info) {
        case IIO_CHAN_INFO_SAMP_FREQ:
                return ad4062_set_sampling_frequency(st, val, val2);
        }

        if (!iio_device_claim_direct(indio_dev))
                return -EBUSY;

        ret = ad4062_write_raw_dispatch(st, val, val2, info);
        iio_device_release_direct(indio_dev);
        return ret;
}

static int pm_ad4062_monitor_mode_enable(struct ad4062_state *st)
{
        int ret;

        PM_RUNTIME_ACQUIRE(&st->i3cdev->dev, pm);
        ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
        if (ret)
                return ret;

        return ad4062_set_operation_mode(st, AD4062_MONITOR_MODE);
}

static int ad4062_monitor_mode_enable(struct ad4062_state *st)
{
        int ret;

        ret = pm_ad4062_monitor_mode_enable(st);
        if (ret)
                return ret;

        pm_runtime_get_noresume(&st->i3cdev->dev);
        return 0;
}

static int ad4062_monitor_mode_disable(struct ad4062_state *st)
{
        pm_runtime_put_autosuspend(&st->i3cdev->dev);
        return 0;
}

static int ad4062_read_event_config(struct iio_dev *indio_dev,
                                    const struct iio_chan_spec *chan,
                                    enum iio_event_type type,
                                    enum iio_event_direction dir)
{
        struct ad4062_state *st = iio_priv(indio_dev);

        return st->wait_event;
}

static int ad4062_write_event_config_dispatch(struct iio_dev *indio_dev,
                                              bool state)
{
        struct ad4062_state *st = iio_priv(indio_dev);
        int ret;

        if (st->wait_event == state)
                ret = 0;
        else if (state)
                ret = ad4062_monitor_mode_enable(st);
        else
                ret = ad4062_monitor_mode_disable(st);
        if (ret)
                return ret;

        st->wait_event = state;
        return 0;
}

static int ad4062_write_event_config(struct iio_dev *indio_dev,
                                     const struct iio_chan_spec *chan,
                                     enum iio_event_type type,
                                     enum iio_event_direction dir,
                                     bool state)
{
        int ret;

        if (!iio_device_claim_direct(indio_dev))
                return -EBUSY;

        ret = ad4062_write_event_config_dispatch(indio_dev, state);
        iio_device_release_direct(indio_dev);
        return ret;
}

static int __ad4062_read_event_info_value(struct ad4062_state *st,
                                          enum iio_event_direction dir, int *val)
{
        int ret;
        u8 reg;

        if (dir == IIO_EV_DIR_RISING)
                reg = AD4062_REG_MAX_LIMIT;
        else
                reg = AD4062_REG_MIN_LIMIT;

        ret = regmap_bulk_read(st->regmap, reg, &st->buf.be16,
                               sizeof(st->buf.be16));
        if (ret)
                return ret;

        *val = sign_extend32(be16_to_cpu(st->buf.be16), AD4062_LIMIT_BITS - 1);

        return 0;
}

static int __ad4062_read_event_info_hysteresis(struct ad4062_state *st,
                                               enum iio_event_direction dir, int *val)
{
        u8 reg;

        if (dir == IIO_EV_DIR_RISING)
                reg = AD4062_REG_MAX_HYST;
        else
                reg = AD4062_REG_MIN_HYST;
        return regmap_read(st->regmap, reg, val);
}

static int ad4062_read_event_config_dispatch(struct iio_dev *indio_dev,
                                             enum iio_event_direction dir,
                                             enum iio_event_info info, int *val)
{
        struct ad4062_state *st = iio_priv(indio_dev);

        if (st->wait_event)
                return -EBUSY;

        switch (info) {
        case IIO_EV_INFO_VALUE:
                return __ad4062_read_event_info_value(st, dir, val);
        case IIO_EV_INFO_HYSTERESIS:
                return __ad4062_read_event_info_hysteresis(st, dir, val);
        default:
                return -EINVAL;
        }
}

static int ad4062_read_event_value(struct iio_dev *indio_dev,
                                   const struct iio_chan_spec *chan,
                                   enum iio_event_type type,
                                   enum iio_event_direction dir,
                                   enum iio_event_info info, int *val,
                                   int *val2)
{
        int ret;

        if (!iio_device_claim_direct(indio_dev))
                return -EBUSY;

        ret = ad4062_read_event_config_dispatch(indio_dev, dir, info, val);
        iio_device_release_direct(indio_dev);
        return ret ?: IIO_VAL_INT;
}

static int __ad4062_write_event_info_value(struct ad4062_state *st,
                                           enum iio_event_direction dir, int val)
{
        u8 reg;

        if (val != sign_extend32(val, AD4062_LIMIT_BITS - 1))
                return -EINVAL;
        if (dir == IIO_EV_DIR_RISING)
                reg = AD4062_REG_MAX_LIMIT;
        else
                reg = AD4062_REG_MIN_LIMIT;
        st->buf.be16 = cpu_to_be16(val);

        return regmap_bulk_write(st->regmap, reg, &st->buf.be16,
                                 sizeof(st->buf.be16));
}

static int __ad4062_write_event_info_hysteresis(struct ad4062_state *st,
                                                enum iio_event_direction dir, int val)
{
        u8 reg;

        if (val > BIT(7) - 1)
                return -EINVAL;
        if (dir == IIO_EV_DIR_RISING)
                reg = AD4062_REG_MAX_HYST;
        else
                reg = AD4062_REG_MIN_HYST;

        return regmap_write(st->regmap, reg, val);
}

static int ad4062_write_event_value_dispatch(struct iio_dev *indio_dev,
                                             enum iio_event_type type,
                                             enum iio_event_direction dir,
                                             enum iio_event_info info, int val)
{
        struct ad4062_state *st = iio_priv(indio_dev);

        if (st->wait_event)
                return -EBUSY;

        switch (type) {
        case IIO_EV_TYPE_THRESH:
                switch (info) {
                case IIO_EV_INFO_VALUE:
                        return __ad4062_write_event_info_value(st, dir, val);
                case IIO_EV_INFO_HYSTERESIS:
                        return __ad4062_write_event_info_hysteresis(st, dir, val);
                default:
                        return -EINVAL;
                }
        default:
                return -EINVAL;
        }
}

static int ad4062_write_event_value(struct iio_dev *indio_dev,
                                    const struct iio_chan_spec *chan,
                                    enum iio_event_type type,
                                    enum iio_event_direction dir,
                                    enum iio_event_info info, int val,
                                    int val2)
{
        int ret;

        if (!iio_device_claim_direct(indio_dev))
                return -EBUSY;

        ret = ad4062_write_event_value_dispatch(indio_dev, type, dir, info, val);
        iio_device_release_direct(indio_dev);
        return ret;
}

/*
 * The AD4062 in burst averaging mode increases realbits from 16-bits to
 * 20-bits, increasing the storagebits from 16-bits to 32-bits.
 */
static inline size_t ad4062_sizeof_storagebits(struct ad4062_state *st)
{
        const struct iio_scan_type *scan_type =
                iio_get_current_scan_type(st->indio_dev, st->chip->channels);

        return BITS_TO_BYTES(scan_type->storagebits);
}

/* Read registers only with realbits (no sign extension bytes) */
static inline size_t ad4062_get_conv_addr(struct ad4062_state *st, size_t _sizeof)
{
        if (st->gpo_irq[1])
                return _sizeof == sizeof(u32) ? AD4062_REG_CONV_READ_32BITS :
                                                AD4062_REG_CONV_READ_16BITS;
        return _sizeof == sizeof(u32) ? AD4062_REG_CONV_TRIGGER_32BITS :
                                        AD4062_REG_CONV_TRIGGER_16BITS;
}

static int pm_ad4062_triggered_buffer_postenable(struct ad4062_state *st)
{
        int ret;

        PM_RUNTIME_ACQUIRE(&st->i3cdev->dev, pm);
        ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
        if (ret)
                return ret;

        if (st->wait_event)
                return -EBUSY;

        ret = ad4062_set_operation_mode(st, st->mode);
        if (ret)
                return ret;

        st->conv_sizeof = ad4062_sizeof_storagebits(st);
        st->conv_addr = ad4062_get_conv_addr(st, st->conv_sizeof);
        /* CONV_READ requires read to trigger first sample. */
        struct i3c_xfer xfer_sample[2] = {
                {
                        .data.out = &st->conv_addr,
                        .len = sizeof(st->conv_addr),
                        .rnw = false,
                },
                {
                        .data.in = &st->buf.be32,
                        .len = sizeof(st->buf.be32),
                        .rnw = true,
                }
        };

        return i3c_device_do_xfers(st->i3cdev, xfer_sample,
                                   st->gpo_irq[1] ? 2 : 1, I3C_SDR);
}

static int ad4062_triggered_buffer_postenable(struct iio_dev *indio_dev)
{
        struct ad4062_state *st = iio_priv(indio_dev);
        int ret;

        ret = pm_ad4062_triggered_buffer_postenable(st);
        if (ret)
                return ret;

        pm_runtime_get_noresume(&st->i3cdev->dev);
        return 0;
}

static int ad4062_triggered_buffer_predisable(struct iio_dev *indio_dev)
{
        struct ad4062_state *st = iio_priv(indio_dev);

        pm_runtime_put_autosuspend(&st->i3cdev->dev);
        return 0;
}

static const struct iio_buffer_setup_ops ad4062_triggered_buffer_setup_ops = {
        .postenable = &ad4062_triggered_buffer_postenable,
        .predisable = &ad4062_triggered_buffer_predisable,
};

static int ad4062_debugfs_reg_access(struct iio_dev *indio_dev, unsigned int reg,
                                     unsigned int writeval, unsigned int *readval)
{
        struct ad4062_state *st = iio_priv(indio_dev);

        if (readval)
                return regmap_read(st->regmap, reg, readval);
        else
                return regmap_write(st->regmap, reg, writeval);
}

static int ad4062_get_current_scan_type(const struct iio_dev *indio_dev,
                                        const struct iio_chan_spec *chan)
{
        struct ad4062_state *st = iio_priv(indio_dev);

        return st->mode == AD4062_BURST_AVERAGING_MODE ?
                           AD4062_SCAN_TYPE_BURST_AVG :
                           AD4062_SCAN_TYPE_SAMPLE;
}

static const struct iio_info ad4062_info = {
        .read_raw = ad4062_read_raw,
        .write_raw = ad4062_write_raw,
        .read_avail = ad4062_read_avail,
        .read_event_config = ad4062_read_event_config,
        .write_event_config = ad4062_write_event_config,
        .read_event_value = ad4062_read_event_value,
        .write_event_value = ad4062_write_event_value,
        .event_attrs = &ad4062_event_attribute_group,
        .get_current_scan_type = ad4062_get_current_scan_type,
        .debugfs_reg_access = ad4062_debugfs_reg_access,
};

static const struct regmap_config ad4062_regmap_config = {
        .name = "ad4062",
        .reg_bits = 8,
        .val_bits = 8,
        .max_register = AD4062_MAX_REG,
        .rd_table = &ad4062_regmap_rd_table,
        .wr_table = &ad4062_regmap_wr_table,
        .can_sleep = true,
};

static int ad4062_regulators_get(struct ad4062_state *st, bool *ref_sel)
{
        struct device *dev = &st->i3cdev->dev;
        int ret;

        ret = devm_regulator_get_enable(dev, "vio");
        if (ret)
                return dev_err_probe(dev, ret, "Failed to enable vio voltage\n");

        st->vref_uV = devm_regulator_get_enable_read_voltage(dev, "ref");
        *ref_sel = st->vref_uV == -ENODEV;
        if (st->vref_uV < 0 && !*ref_sel)
                return dev_err_probe(dev, st->vref_uV,
                                     "Failed to enable and read ref voltage\n");

        if (*ref_sel) {
                st->vref_uV = devm_regulator_get_enable_read_voltage(dev, "vdd");
                if (st->vref_uV < 0)
                        return dev_err_probe(dev, st->vref_uV,
                                             "Failed to enable and read vdd voltage\n");
        } else {
                ret = devm_regulator_get_enable(dev, "vdd");
                if (ret)
                        return dev_err_probe(dev, ret,
                                             "Failed to enable vdd regulator\n");
        }

        return 0;
}

static int ad4062_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
{
        return GPIO_LINE_DIRECTION_OUT;
}

static int ad4062_gpio_set(struct gpio_chip *gc, unsigned int offset, int value)
{
        struct ad4062_state *st = gpiochip_get_data(gc);
        unsigned int reg_val = value ? AD4062_GP_STATIC_HIGH : AD4062_GP_STATIC_LOW;

        if (offset)
                return regmap_update_bits(st->regmap, AD4062_REG_GP_CONF,
                                          AD4062_REG_GP_CONF_MODE_MSK_1,
                                          FIELD_PREP(AD4062_REG_GP_CONF_MODE_MSK_1, reg_val));
        else
                return regmap_update_bits(st->regmap, AD4062_REG_GP_CONF,
                                          AD4062_REG_GP_CONF_MODE_MSK_0,
                                          FIELD_PREP(AD4062_REG_GP_CONF_MODE_MSK_0, reg_val));
}

static int ad4062_gpio_get(struct gpio_chip *gc, unsigned int offset)
{
        struct ad4062_state *st = gpiochip_get_data(gc);
        unsigned int reg_val;
        int ret;

        ret = regmap_read(st->regmap, AD4062_REG_GP_CONF, &reg_val);
        if (ret)
                return ret;

        if (offset)
                reg_val = FIELD_GET(AD4062_REG_GP_CONF_MODE_MSK_1, reg_val);
        else
                reg_val = FIELD_GET(AD4062_REG_GP_CONF_MODE_MSK_0, reg_val);

        return reg_val == AD4062_GP_STATIC_HIGH;
}

static void ad4062_gpio_disable(void *data)
{
        struct ad4062_state *st = data;
        u8 val = FIELD_PREP(AD4062_REG_GP_CONF_MODE_MSK_0, AD4062_GP_DISABLED) |
                 FIELD_PREP(AD4062_REG_GP_CONF_MODE_MSK_1, AD4062_GP_DISABLED);

        regmap_update_bits(st->regmap, AD4062_REG_GP_CONF,
                           AD4062_REG_GP_CONF_MODE_MSK_1 | AD4062_REG_GP_CONF_MODE_MSK_0,
                           val);
}

static int ad4062_gpio_init_valid_mask(struct gpio_chip *gc,
                                       unsigned long *valid_mask,
                                       unsigned int ngpios)
{
        struct ad4062_state *st = gpiochip_get_data(gc);

        bitmap_zero(valid_mask, ngpios);

        for (unsigned int i = 0; i < ARRAY_SIZE(st->gpo_irq); i++)
                __assign_bit(i, valid_mask, !st->gpo_irq[i]);

        return 0;
}

static int ad4062_gpio_init(struct ad4062_state *st)
{
        struct device *dev = &st->i3cdev->dev;
        struct gpio_chip *gc;
        u8 val, mask;
        int ret;

        if (!device_property_read_bool(dev, "gpio-controller"))
                return 0;

        gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL);
        if (!gc)
                return -ENOMEM;

        val = 0;
        mask = 0;
        if (!st->gpo_irq[0]) {
                mask |= AD4062_REG_GP_CONF_MODE_MSK_0;
                val |= FIELD_PREP(AD4062_REG_GP_CONF_MODE_MSK_0, AD4062_GP_STATIC_LOW);
        }
        if (!st->gpo_irq[1]) {
                mask |= AD4062_REG_GP_CONF_MODE_MSK_1;
                val |= FIELD_PREP(AD4062_REG_GP_CONF_MODE_MSK_1, AD4062_GP_STATIC_LOW);
        }

        ret = regmap_update_bits(st->regmap, AD4062_REG_GP_CONF,
                                 mask, val);
        if (ret)
                return ret;

        ret = devm_add_action_or_reset(dev, ad4062_gpio_disable, st);
        if (ret)
                return ret;

        gc->parent = dev;
        gc->label = st->chip->name;
        gc->owner = THIS_MODULE;
        gc->base = -1;
        gc->ngpio = 2;
        gc->init_valid_mask = ad4062_gpio_init_valid_mask;
        gc->get_direction = ad4062_gpio_get_direction;
        gc->set = ad4062_gpio_set;
        gc->get = ad4062_gpio_get;
        gc->can_sleep = true;

        ret = devm_gpiochip_add_data(dev, gc, st);
        if (ret)
                return dev_err_probe(dev, ret, "Unable to register GPIO chip\n");

        return 0;
}

static const struct i3c_device_id ad4062_id_table[] = {
        I3C_DEVICE(AD4062_I3C_VENDOR, AD4060_PROD_ID, &ad4060_chip_info),
        I3C_DEVICE(AD4062_I3C_VENDOR, AD4062_PROD_ID, &ad4062_chip_info),
        { }
};
MODULE_DEVICE_TABLE(i3c, ad4062_id_table);

static int ad4062_probe(struct i3c_device *i3cdev)
{
        const struct i3c_device_id *id = i3c_device_match_id(i3cdev, ad4062_id_table);
        const struct ad4062_chip_info *chip = id->data;
        struct device *dev = &i3cdev->dev;
        struct iio_dev *indio_dev;
        struct ad4062_state *st;
        bool ref_sel;
        int ret;

        indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
        if (!indio_dev)
                return -ENOMEM;

        st = iio_priv(indio_dev);
        st->i3cdev = i3cdev;
        i3cdev_set_drvdata(i3cdev, st);
        init_completion(&st->completion);

        ret = ad4062_regulators_get(st, &ref_sel);
        if (ret)
                return ret;

        st->regmap = devm_regmap_init_i3c(i3cdev, &ad4062_regmap_config);
        if (IS_ERR(st->regmap))
                return dev_err_probe(dev, PTR_ERR(st->regmap),
                                     "Failed to initialize regmap\n");

        st->mode = AD4062_SAMPLE_MODE;
        st->wait_event = false;
        st->chip = chip;
        st->sampling_frequency = 0;
        st->events_frequency = 0;
        st->oversamp_ratio = 0;
        st->indio_dev = indio_dev;

        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->num_channels = 1;
        indio_dev->info = &ad4062_info;
        indio_dev->name = chip->name;
        indio_dev->channels = chip->channels;

        ret = ad4062_soft_reset(st);
        if (ret)
                return dev_err_probe(dev, ret, "AD4062 failed to soft reset\n");

        ret = ad4062_check_ids(st);
        if (ret)
                return ret;

        ret = ad4062_setup(indio_dev, indio_dev->channels, &ref_sel);
        if (ret)
                return ret;

        ret = ad4062_request_irq(indio_dev);
        if (ret)
                return ret;

        ret = ad4062_request_trigger(indio_dev);
        if (ret)
                return ret;

        ret = devm_iio_triggered_buffer_setup(&i3cdev->dev, indio_dev,
                                              iio_pollfunc_store_time,
                                              ad4062_poll_handler,
                                              &ad4062_triggered_buffer_setup_ops);
        if (ret)
                return ret;

        pm_runtime_set_active(dev);
        ret = devm_pm_runtime_enable(dev);
        if (ret)
                return dev_err_probe(dev, ret, "Failed to enable pm_runtime\n");

        pm_runtime_set_autosuspend_delay(dev, 1000);
        pm_runtime_use_autosuspend(dev);

        ret = ad4062_request_ibi(i3cdev);
        if (ret)
                return dev_err_probe(dev, ret, "Failed to request i3c ibi\n");

        ret = ad4062_gpio_init(st);
        if (ret)
                return ret;

        ret = devm_work_autocancel(dev, &st->trig_conv, ad4062_trigger_work);
        if (ret)
                return ret;

        return devm_iio_device_register(dev, indio_dev);
}

static int ad4062_runtime_suspend(struct device *dev)
{
        struct ad4062_state *st = dev_get_drvdata(dev);

        return regmap_write(st->regmap, AD4062_REG_DEVICE_CONFIG,
                            FIELD_PREP(AD4062_REG_DEVICE_CONFIG_POWER_MODE_MSK,
                                       AD4062_REG_DEVICE_CONFIG_LOW_POWER_MODE));
}

static int ad4062_runtime_resume(struct device *dev)
{
        struct ad4062_state *st = dev_get_drvdata(dev);
        int ret;

        ret = regmap_clear_bits(st->regmap, AD4062_REG_DEVICE_CONFIG,
                                AD4062_REG_DEVICE_CONFIG_POWER_MODE_MSK);
        if (ret)
                return ret;

        /* Wait device functional blocks to power up */
        fsleep(3 * USEC_PER_MSEC);
        return 0;
}

static DEFINE_RUNTIME_DEV_PM_OPS(ad4062_pm_ops,
                                 ad4062_runtime_suspend, ad4062_runtime_resume, NULL);

static struct i3c_driver ad4062_driver = {
        .driver = {
                .name = "ad4062",
                .pm = pm_ptr(&ad4062_pm_ops),
        },
        .probe = ad4062_probe,
        .id_table = ad4062_id_table,
};
module_i3c_driver(ad4062_driver);

MODULE_AUTHOR("Jorge Marques <jorge.marques@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD4062");
MODULE_LICENSE("GPL");