// SPDX-License-Identifier: GPL-2.0-only
/*
* Analog Devices AD4030 and AD4630 ADC family driver.
*
* Copyright 2024 Analog Devices, Inc.
* Copyright 2024 BayLibre, SAS
*
* based on code from:
* Analog Devices, Inc.
* Sergiu Cuciurean <sergiu.cuciurean@analog.com>
* Nuno Sa <nuno.sa@analog.com>
* Marcelo Schmitt <marcelo.schmitt@analog.com>
* Liviu Adace <liviu.adace@analog.com>
*/
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/iio/iio.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
#include <linux/unaligned.h>
#include <linux/units.h>
#define AD4030_REG_INTERFACE_CONFIG_A 0x00
#define AD4030_REG_INTERFACE_CONFIG_A_SW_RESET (BIT(0) | BIT(7))
#define AD4030_REG_INTERFACE_CONFIG_B 0x01
#define AD4030_REG_DEVICE_CONFIG 0x02
#define AD4030_REG_CHIP_TYPE 0x03
#define AD4030_REG_PRODUCT_ID_L 0x04
#define AD4030_REG_PRODUCT_ID_H 0x05
#define AD4030_REG_CHIP_GRADE 0x06
#define AD4030_REG_CHIP_GRADE_AD4030_24_GRADE 0x10
#define AD4030_REG_CHIP_GRADE_AD4630_16_GRADE 0x03
#define AD4030_REG_CHIP_GRADE_AD4630_24_GRADE 0x00
#define AD4030_REG_CHIP_GRADE_AD4632_16_GRADE 0x05
#define AD4030_REG_CHIP_GRADE_AD4632_24_GRADE 0x02
#define AD4030_REG_CHIP_GRADE_MASK_CHIP_GRADE GENMASK(7, 3)
#define AD4030_REG_SCRATCH_PAD 0x0A
#define AD4030_REG_SPI_REVISION 0x0B
#define AD4030_REG_VENDOR_L 0x0C
#define AD4030_REG_VENDOR_H 0x0D
#define AD4030_REG_STREAM_MODE 0x0E
#define AD4030_REG_INTERFACE_CONFIG_C 0x10
#define AD4030_REG_INTERFACE_STATUS_A 0x11
#define AD4030_REG_EXIT_CFG_MODE 0x14
#define AD4030_REG_EXIT_CFG_MODE_EXIT_MSK BIT(0)
#define AD4030_REG_AVG 0x15
#define AD4030_REG_AVG_MASK_AVG_SYNC BIT(7)
#define AD4030_REG_AVG_MASK_AVG_VAL GENMASK(4, 0)
#define AD4030_REG_OFFSET_X0_0 0x16
#define AD4030_REG_OFFSET_X0_1 0x17
#define AD4030_REG_OFFSET_X0_2 0x18
#define AD4030_REG_OFFSET_X1_0 0x19
#define AD4030_REG_OFFSET_X1_1 0x1A
#define AD4030_REG_OFFSET_X1_2 0x1B
#define AD4030_REG_OFFSET_BYTES_NB 3
#define AD4030_REG_OFFSET_CHAN(ch) \
(AD4030_REG_OFFSET_X0_2 + (AD4030_REG_OFFSET_BYTES_NB * (ch)))
#define AD4030_REG_GAIN_X0_LSB 0x1C
#define AD4030_REG_GAIN_X0_MSB 0x1D
#define AD4030_REG_GAIN_X1_LSB 0x1E
#define AD4030_REG_GAIN_X1_MSB 0x1F
#define AD4030_REG_GAIN_MAX_GAIN 1999970
#define AD4030_REG_GAIN_BYTES_NB 2
#define AD4030_REG_GAIN_CHAN(ch) \
(AD4030_REG_GAIN_X0_MSB + (AD4030_REG_GAIN_BYTES_NB * (ch)))
#define AD4030_REG_MODES 0x20
#define AD4030_REG_MODES_MASK_OUT_DATA_MODE GENMASK(2, 0)
#define AD4030_REG_MODES_MASK_LANE_MODE GENMASK(7, 6)
#define AD4030_REG_OSCILATOR 0x21
#define AD4030_REG_IO 0x22
#define AD4030_REG_IO_MASK_IO2X BIT(1)
#define AD4030_REG_PAT0 0x23
#define AD4030_REG_PAT1 0x24
#define AD4030_REG_PAT2 0x25
#define AD4030_REG_PAT3 0x26
#define AD4030_REG_DIG_DIAG 0x34
#define AD4030_REG_DIG_ERR 0x35
/* Sequence starting with "1 0 1" to enable reg access */
#define AD4030_REG_ACCESS 0xA0
#define AD4030_MAX_IIO_SAMPLE_SIZE_BUFFERED BITS_TO_BYTES(64)
#define AD4030_MAX_HARDWARE_CHANNEL_NB 2
#define AD4030_MAX_IIO_CHANNEL_NB 5
#define AD4030_SINGLE_COMMON_BYTE_CHANNELS_MASK 0b10
#define AD4030_DUAL_COMMON_BYTE_CHANNELS_MASK 0b1100
#define AD4030_GAIN_MIDLE_POINT 0x8000
/*
* This accounts for 1 sample per channel plus one s64 for the timestamp,
* aligned on a s64 boundary
*/
#define AD4030_MAXIMUM_RX_BUFFER_SIZE \
(ALIGN(AD4030_MAX_IIO_SAMPLE_SIZE_BUFFERED * \
AD4030_MAX_HARDWARE_CHANNEL_NB, \
sizeof(s64)) + sizeof(s64))
#define AD4030_VREF_MIN_UV (4096 * MILLI)
#define AD4030_VREF_MAX_UV (5000 * MILLI)
#define AD4030_VIO_THRESHOLD_UV (1400 * MILLI)
#define AD4030_SPI_MAX_XFER_LEN 8
#define AD4030_SPI_MAX_REG_XFER_SPEED (80 * MEGA)
#define AD4030_TCNVH_NS 10
#define AD4030_TCNVL_NS 20
#define AD4030_TCYC_NS 500
#define AD4030_TCYC_ADJUSTED_NS (AD4030_TCYC_NS - AD4030_TCNVL_NS)
#define AD4030_TRESET_PW_NS 50
#define AD4632_TCYC_NS 2000
#define AD4632_TCYC_ADJUSTED_NS (AD4632_TCYC_NS - AD4030_TCNVL_NS)
#define AD4030_TRESET_COM_DELAY_MS 750
enum ad4030_out_mode {
AD4030_OUT_DATA_MD_DIFF,
AD4030_OUT_DATA_MD_16_DIFF_8_COM,
AD4030_OUT_DATA_MD_24_DIFF_8_COM,
AD4030_OUT_DATA_MD_30_AVERAGED_DIFF,
AD4030_OUT_DATA_MD_32_PATTERN,
};
enum {
AD4030_LANE_MD_1_PER_CH,
AD4030_LANE_MD_2_PER_CH,
AD4030_LANE_MD_4_PER_CH,
AD4030_LANE_MD_INTERLEAVED,
};
enum {
AD4030_SCAN_TYPE_NORMAL,
AD4030_SCAN_TYPE_AVG,
};
struct ad4030_chip_info {
const char *name;
const unsigned long *available_masks;
const struct iio_chan_spec channels[AD4030_MAX_IIO_CHANNEL_NB];
u8 grade;
u8 precision_bits;
/* Number of hardware channels */
int num_voltage_inputs;
unsigned int tcyc_ns;
};
struct ad4030_state {
struct spi_device *spi;
struct regmap *regmap;
const struct ad4030_chip_info *chip;
struct gpio_desc *cnv_gpio;
int vref_uv;
int vio_uv;
int offset_avail[3];
unsigned int avg_log2;
enum ad4030_out_mode mode;
/*
* DMA (thus cache coherency maintenance) requires the transfer buffers
* to live in their own cache lines.
*/
u8 tx_data[AD4030_SPI_MAX_XFER_LEN] __aligned(IIO_DMA_MINALIGN);
union {
u8 raw[AD4030_MAXIMUM_RX_BUFFER_SIZE];
struct {
s32 diff;
u8 common;
} single;
struct {
s32