Re: [PATCH] drivers: iio: adc: add support for ad777x family

From: Nuno Sá
Date: Wed May 22 2024 - 10:35:47 EST


On Wed, 2024-05-22 at 14:59 +0300, ranechita wrote:
> Added support for ad7770,ad7771,ad7779 ADCs. The
> data is streamed only on the spi-mode, without
> using the data lines.
>
> Signed-off-by: ranechita <ramona.nechita@xxxxxxxxxx>
> ---
>  drivers/iio/adc/Kconfig  |   11 +
>  drivers/iio/adc/Makefile |    1 +
>  drivers/iio/adc/ad7779.c | 1182 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 1194 insertions(+)
>  create mode 100644 drivers/iio/adc/ad7779.c
>
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index 0d9282fa67f5..3e42cbc365d7 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -206,6 +206,17 @@ config AD7768_1
>     To compile this driver as a module, choose M here: the module will be
>     called ad7768-1.
>  
> +config AD7779
> + tristate "Analog Devices AD7779 ADC driver"
> + depends on SPI
> + select IIO_BUFFER
> + help
> +   Say yes here to build support for Analog Devices AD7779 SPI
> +   analog to digital converter (ADC)
> +
> +   To compile this driver as a module, choose M here: the module will be
> +   called ad7779.
> +
>  config AD7780
>   tristate "Analog Devices AD7780 and similar ADCs driver"
>   depends on SPI
> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
> index b3c434722364..e25997e926bb 100644
> --- a/drivers/iio/adc/Makefile
> +++ b/drivers/iio/adc/Makefile
> @@ -24,6 +24,7 @@ obj-$(CONFIG_AD7606_IFACE_SPI) += ad7606_spi.o
>  obj-$(CONFIG_AD7606) += ad7606.o
>  obj-$(CONFIG_AD7766) += ad7766.o
>  obj-$(CONFIG_AD7768_1) += ad7768-1.o
> +obj-$(CONFIG_AD7779) += ad7779.o
>  obj-$(CONFIG_AD7780) += ad7780.o
>  obj-$(CONFIG_AD7791) += ad7791.o
>  obj-$(CONFIG_AD7793) += ad7793.o
> diff --git a/drivers/iio/adc/ad7779.c b/drivers/iio/adc/ad7779.c
> new file mode 100644
> index 000000000000..d2c1b14464ff
> --- /dev/null
> +++ b/drivers/iio/adc/ad7779.c
> @@ -0,0 +1,1182 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * AD777X ADC
> + *
> + * Copyright 2023 Analog Devices Inc.
> + */
> +
> +#include <linux/bitfield.h>
> +#include <linux/bitops.h>
> +#include <linux/clk.h>
> +#include <linux/crc8.h>
> +#include <linux/delay.h>
> +#include <linux/err.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/gpio.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/module.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/spi/spi.h>
> +#include <linux/string.h>
> +
> +#include <linux/iio/iio.h>
> +#include <linux/iio/buffer.h>
> +#include <linux/iio/kfifo_buf.h>
> +#include <linux/iio/sysfs.h>
> +
> +#include "cf_axi_adc.h"
> +
> +#define AD777X_SPI_READ_CMD BIT(7)
> +
> +#define AD777X_DISABLE_SD BIT(7)
> +
> +#define AD777X_REG_CH_DISABLE 0x08
> +#define AD777X_REG_CH_SYNC_OFFSET(ch) (0x09 + (ch))
> +#define AD777X_REG_CH_CONFIG(ch) (0x00 + (ch))
> +#define AD777X_REG_GENERAL_USER_CONFIG_1 0x11
> +#define AD777X_REG_GENERAL_USER_CONFIG_2 0x12
> +#define AD777X_REG_GENERAL_USER_CONFIG_3 0x13
> +#define AD777X_REG_DOUT_FORMAT 0x14
> +#define AD777X_REG_ADC_MUX_CONFIG 0x15
> +#define AD777X_REG_GPIO_CONFIG 0x17
> +#define AD777X_REG_BUFFER_CONFIG_1 0x19
> +#define AD777X_REG_GLOBAL_MUX_CONFIG 0x16
> +#define AD777X_REG_BUFFER_CONFIG_2 0x1A
> +#define AD777X_REG_GPIO_DATA 0x18
> +#define AD777X_REG_CH_OFFSET_UPPER_BYTE(ch) (0x1C + (ch) * 6)
> +#define AD777X_REG_CH_OFFSET_LOWER_BYTE(ch) (0x1E + (ch) * 6)
> +#define AD777X_REG_CH_GAIN_UPPER_BYTE(ch) (0x1F + (ch) * 6)
> +#define AD777X_REG_CH_OFFSET_MID_BYTE(ch) (0x1D + (ch) * 6)
> +#define AD777X_REG_CH_GAIN_MID_BYTE(ch) (0x20 + (ch) * 6)
> +#define AD777X_REG_CH_ERR_REG(ch) (0x4C + (ch))
> +#define AD777X_REG_CH0_1_SAT_ERR 0x54
> +#define AD777X_REG_CH_GAIN_LOWER_BYTE(ch) (0x21 + (ch) * 6)
> +#define AD777X_REG_CH2_3_SAT_ERR 0x55
> +#define AD777X_REG_CH4_5_SAT_ERR 0x56
> +#define AD777X_REG_CH6_7_SAT_ERR 0x57
> +#define AD777X_REG_CHX_ERR_REG_EN 0x58
> +#define AD777X_REG_GEN_ERR_REG_1 0x59
> +#define AD777X_REG_GEN_ERR_REG_1_EN 0x5A
> +#define AD777X_REG_GEN_ERR_REG_2 0x5B
> +#define AD777X_REG_GEN_ERR_REG_2_EN 0x5C
> +#define AD777X_REG_STATUS_REG_1 0x5D
> +#define AD777X_REG_STATUS_REG_2 0x5E
> +#define AD777X_REG_STATUS_REG_3 0x5F
> +#define AD777X_REG_SRC_N_MSB 0x60
> +#define AD777X_REG_SRC_N_LSB 0x61
> +#define AD777X_REG_SRC_IF_MSB 0x62
> +#define AD777X_REG_SRC_IF_LSB 0x63
> +#define AD777X_REG_SRC_UPDATE 0x64
> +
> +#define AD777X_FILTER_MSK BIT(6)
> +#define AD777X_MOD_POWERMODE_MSK BIT(6)
> +#define AD777X_MOD_PDB_REFOUT_MSK BIT(4)
> +#define AD777X_MOD_SPI_EN_MSK BIT(4)
> +
> +/* AD777X_REG_DOUT_FORMAT */
> +#define AD777X_DOUT_FORMAT_MSK GENMASK(7, 6)
> +#define AD777X_DOUT_HEADER_FORMAT BIT(5)
> +#define AD777X_DCLK_CLK_DIV_MSK GENMASK(3, 1)
> +
> +#define AD777X_REFMUX_CTRL_MSK GENMASK(7, 6)
> +#define AD777X_SPI_CRC_EN_MSK BIT(0)
> +
> +#define AD777X_MAXCLK_LOWPOWER 4096000
> +#define AD777X_NUM_CHANNELS 8
> +#define AD777X_RESET_BUF_SIZE 8
> +
> +#define AD777X_LOWPOWER_DIV 512
> +#define AD777X_HIGHPOWER_DIV 2048
> +
> +#define AD777X_SINC3_MAXFREQ 16000
> +#define AD777X_SINC5_MAXFREQ 128000
> +
> +#define AD777X_DEFAULT_SAMPLING_FREQ 8000
> +#define AD777X_DEFAULT_SAMPLING_2LINE 4000
> +#define AD777X_DEFAULT_SAMPLING_1LINE 2000
> +
> +#define AD777X_SPIMODE_MAX_SAMP_FREQ 16000
> +
> +/* AXI CONTROL REGS VALUES FOR DATA LINES */
> +#define AXI_CTRL_4_LINES 0x400
> +#define AXI_CTRL_2_LINES 0x200
> +#define AXI_CTRL_1_LINE 0x100
> +
> +#define DEC3 1000
> +#define DEC6 1000000
> +
> +#define GAIN_REL 0x555555
> +#define AD777X_FREQ_MSB_MSK GENMASK(15, 8)
> +#define AD777X_FREQ_LSB_MSK GENMASK(7, 0)
> +#define AD777X_UPPER GENMASK(23, 16)
> +#define AD777X_MID GENMASK(15, 8)
> +#define AD777X_LOWER GENMASK(7, 0)
> +
> +#define AD777X_CRC8_POLY 0x07
> +DECLARE_CRC8_TABLE(ad777x_crc8_table);
> +
> +enum ad777x_data_lines {
> + AD777x_4LINES,
> + AD777x_2LINES,
> + AD777x_1LINE,
> +};
> +
> +enum ad777x_filter {
> + AD777X_SINC3,
> + AD777X_SINC5,
> +};
> +
> +enum ad777x_variant {
> + ad7770,
> + ad7771,
> + ad7779,
> +};
> +
> +enum ad777x_power_mode {
> + AD777X_LOW_POWER,
> + AD777X_HIGH_POWER,
> +};
> +
> +struct ad777x_chip_info {
> + const char *name;
> +};
> +
> +struct ad777x_state {
> + struct spi_device *spi;
> + const struct ad777x_chip_info *chip_info;
> + struct clk *mclk;
> + struct regulator *vref;
> + unsigned int sampling_freq;
> + enum ad777x_power_mode power_mode;
> + enum ad777x_data_lines data_lines;
> + enum ad777x_filter filter_enabled;
> + unsigned int active_ch;
> + unsigned int spidata_mode;
> + unsigned int crc_enabled;
> +
> + /*
> + * DMA (thus cache coherency maintenance) requires the
> + * transfer buffers to live in their own cache lines.
> + */
> + u8 reg_rx_buf[3] ____cacheline_aligned;
> + u8 reg_tx_buf[3];
> + u8 spidata_rx[32];
> + u8 spidata_tx[32];
> + u8 reset_buf[8];
> +};
> +
> +static const char * const ad777x_filter_type[] = {
> + [AD777X_SINC3] = "sinc3_filter",
> + [AD777X_SINC5] = "sinc5_filter",
> +};
> +
> +static const char * const ad777x_data_lines_modes[] = {
> + [AD777x_4LINES] = "4_data_lines",
> + [AD777x_2LINES] = "2_data_lines",
> + [AD777x_1LINE]  = "1_data_line",
> +};
> +
> +static bool ad777x_has_axi_adc(struct device *dev)
> +{
> + return device_property_present(dev, "spibus-connected");
> +}
> +
> +static struct ad777x_state *ad777x_get_data(struct iio_dev *indio_dev)
> +{
> + struct axiadc_converter *conv;
> +
> + if (ad777x_has_axi_adc(&indio_dev->dev)) {
> + conv = iio_device_get_drvdata(indio_dev);
> + return conv->phy;
> + }
> +
> + return iio_priv(indio_dev);
> +}
> +

Hi Ramona,

Is this even compiling? This is definitely not code to be upstreamed since it relies
on the our out-of-tree/legacy driver for the adi-axi-adc. You need to convert this to
use the IIO backend framework (adding new interfaces if needed).

- Nuno Sá