1*c9a3f8c7SRamona Alexandra Nechita // SPDX-License-Identifier: GPL-2.0+ 2*c9a3f8c7SRamona Alexandra Nechita /* 3*c9a3f8c7SRamona Alexandra Nechita * AD7770, AD7771, AD7779 ADC 4*c9a3f8c7SRamona Alexandra Nechita * 5*c9a3f8c7SRamona Alexandra Nechita * Copyright 2023-2024 Analog Devices Inc. 6*c9a3f8c7SRamona Alexandra Nechita */ 7*c9a3f8c7SRamona Alexandra Nechita 8*c9a3f8c7SRamona Alexandra Nechita #include <linux/bitfield.h> 9*c9a3f8c7SRamona Alexandra Nechita #include <linux/bitmap.h> 10*c9a3f8c7SRamona Alexandra Nechita #include <linux/clk.h> 11*c9a3f8c7SRamona Alexandra Nechita #include <linux/crc8.h> 12*c9a3f8c7SRamona Alexandra Nechita #include <linux/delay.h> 13*c9a3f8c7SRamona Alexandra Nechita #include <linux/err.h> 14*c9a3f8c7SRamona Alexandra Nechita #include <linux/gpio/consumer.h> 15*c9a3f8c7SRamona Alexandra Nechita #include <linux/interrupt.h> 16*c9a3f8c7SRamona Alexandra Nechita #include <linux/irq.h> 17*c9a3f8c7SRamona Alexandra Nechita #include <linux/math.h> 18*c9a3f8c7SRamona Alexandra Nechita #include <linux/module.h> 19*c9a3f8c7SRamona Alexandra Nechita #include <linux/mod_devicetable.h> 20*c9a3f8c7SRamona Alexandra Nechita #include <linux/regulator/consumer.h> 21*c9a3f8c7SRamona Alexandra Nechita #include <linux/spi/spi.h> 22*c9a3f8c7SRamona Alexandra Nechita #include <linux/string.h> 23*c9a3f8c7SRamona Alexandra Nechita #include <linux/types.h> 24*c9a3f8c7SRamona Alexandra Nechita #include <linux/unaligned.h> 25*c9a3f8c7SRamona Alexandra Nechita #include <linux/units.h> 26*c9a3f8c7SRamona Alexandra Nechita 27*c9a3f8c7SRamona Alexandra Nechita #include <linux/iio/iio.h> 28*c9a3f8c7SRamona Alexandra Nechita #include <linux/iio/buffer.h> 29*c9a3f8c7SRamona Alexandra Nechita #include <linux/iio/sysfs.h> 30*c9a3f8c7SRamona Alexandra Nechita #include <linux/iio/trigger.h> 31*c9a3f8c7SRamona Alexandra Nechita #include <linux/iio/triggered_buffer.h> 32*c9a3f8c7SRamona Alexandra Nechita #include <linux/iio/trigger_consumer.h> 33*c9a3f8c7SRamona Alexandra Nechita 34*c9a3f8c7SRamona Alexandra Nechita #define AD7779_SPI_READ_CMD BIT(7) 35*c9a3f8c7SRamona Alexandra Nechita 36*c9a3f8c7SRamona Alexandra Nechita #define AD7779_DISABLE_SD BIT(7) 37*c9a3f8c7SRamona Alexandra Nechita 38*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_CH_DISABLE 0x08 39*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_CH_SYNC_OFFSET(ch) (0x09 + (ch)) 40*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_CH_CONFIG(ch) (0x00 + (ch)) 41*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_GENERAL_USER_CONFIG_1 0x11 42*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_GENERAL_USER_CONFIG_2 0x12 43*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_GENERAL_USER_CONFIG_3 0x13 44*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_DOUT_FORMAT 0x14 45*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_ADC_MUX_CONFIG 0x15 46*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_GPIO_CONFIG 0x17 47*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_BUFFER_CONFIG_1 0x19 48*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_GLOBAL_MUX_CONFIG 0x16 49*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_BUFFER_CONFIG_2 0x1A 50*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_GPIO_DATA 0x18 51*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_CH_OFFSET_UPPER_BYTE(ch) (0x1C + (ch) * 6) 52*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_CH_OFFSET_LOWER_BYTE(ch) (0x1E + (ch) * 6) 53*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_CH_GAIN_UPPER_BYTE(ch) (0x1F + (ch) * 6) 54*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_CH_OFFSET_MID_BYTE(ch) (0x1D + (ch) * 6) 55*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_CH_GAIN_MID_BYTE(ch) (0x20 + (ch) * 6) 56*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_CH_ERR_REG(ch) (0x4C + (ch)) 57*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_CH0_1_SAT_ERR 0x54 58*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_CH_GAIN_LOWER_BYTE(ch) (0x21 + (ch) * 6) 59*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_CH2_3_SAT_ERR 0x55 60*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_CH4_5_SAT_ERR 0x56 61*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_CH6_7_SAT_ERR 0x57 62*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_CHX_ERR_REG_EN 0x58 63*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_GEN_ERR_REG_1 0x59 64*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_GEN_ERR_REG_1_EN 0x5A 65*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_GEN_ERR_REG_2 0x5B 66*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_GEN_ERR_REG_2_EN 0x5C 67*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_STATUS_REG_1 0x5D 68*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_STATUS_REG_2 0x5E 69*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_STATUS_REG_3 0x5F 70*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_SRC_N_MSB 0x60 71*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_SRC_N_LSB 0x61 72*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_SRC_IF_MSB 0x62 73*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_SRC_IF_LSB 0x63 74*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_SRC_UPDATE 0x64 75*c9a3f8c7SRamona Alexandra Nechita 76*c9a3f8c7SRamona Alexandra Nechita #define AD7779_FILTER_MSK BIT(6) 77*c9a3f8c7SRamona Alexandra Nechita #define AD7779_MOD_POWERMODE_MSK BIT(6) 78*c9a3f8c7SRamona Alexandra Nechita #define AD7779_MOD_PDB_REFOUT_MSK BIT(4) 79*c9a3f8c7SRamona Alexandra Nechita #define AD7779_MOD_SPI_EN_MSK BIT(4) 80*c9a3f8c7SRamona Alexandra Nechita #define AD7779_USRMOD_INIT_MSK GENMASK(6, 4) 81*c9a3f8c7SRamona Alexandra Nechita 82*c9a3f8c7SRamona Alexandra Nechita /* AD7779_REG_DOUT_FORMAT */ 83*c9a3f8c7SRamona Alexandra Nechita #define AD7779_DOUT_FORMAT_MSK GENMASK(7, 6) 84*c9a3f8c7SRamona Alexandra Nechita #define AD7779_DOUT_HEADER_FORMAT BIT(5) 85*c9a3f8c7SRamona Alexandra Nechita #define AD7779_DCLK_CLK_DIV_MSK GENMASK(3, 1) 86*c9a3f8c7SRamona Alexandra Nechita 87*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REFMUX_CTRL_MSK GENMASK(7, 6) 88*c9a3f8c7SRamona Alexandra Nechita #define AD7779_SPI_CRC_EN_MSK BIT(0) 89*c9a3f8c7SRamona Alexandra Nechita 90*c9a3f8c7SRamona Alexandra Nechita #define AD7779_MAXCLK_LOWPOWER (4096 * HZ_PER_KHZ) 91*c9a3f8c7SRamona Alexandra Nechita #define AD7779_NUM_CHANNELS 8 92*c9a3f8c7SRamona Alexandra Nechita #define AD7779_RESET_BUF_SIZE 8 93*c9a3f8c7SRamona Alexandra Nechita #define AD7779_CHAN_DATA_SIZE 4 94*c9a3f8c7SRamona Alexandra Nechita 95*c9a3f8c7SRamona Alexandra Nechita #define AD7779_LOWPOWER_DIV 512 96*c9a3f8c7SRamona Alexandra Nechita #define AD7779_HIGHPOWER_DIV 2048 97*c9a3f8c7SRamona Alexandra Nechita 98*c9a3f8c7SRamona Alexandra Nechita #define AD7779_SINC3_MAXFREQ (16 * HZ_PER_KHZ) 99*c9a3f8c7SRamona Alexandra Nechita #define AD7779_SINC5_MAXFREQ (128 * HZ_PER_KHZ) 100*c9a3f8c7SRamona Alexandra Nechita 101*c9a3f8c7SRamona Alexandra Nechita #define AD7779_DEFAULT_SAMPLING_FREQ (8 * HZ_PER_KHZ) 102*c9a3f8c7SRamona Alexandra Nechita #define AD7779_DEFAULT_SAMPLING_2LINE (4 * HZ_PER_KHZ) 103*c9a3f8c7SRamona Alexandra Nechita #define AD7779_DEFAULT_SAMPLING_1LINE (2 * HZ_PER_KHZ) 104*c9a3f8c7SRamona Alexandra Nechita 105*c9a3f8c7SRamona Alexandra Nechita #define AD7779_SPIMODE_MAX_SAMP_FREQ (16 * HZ_PER_KHZ) 106*c9a3f8c7SRamona Alexandra Nechita 107*c9a3f8c7SRamona Alexandra Nechita #define GAIN_REL 0x555555 108*c9a3f8c7SRamona Alexandra Nechita #define AD7779_FREQ_MSB_MSK GENMASK(15, 8) 109*c9a3f8c7SRamona Alexandra Nechita #define AD7779_FREQ_LSB_MSK GENMASK(7, 0) 110*c9a3f8c7SRamona Alexandra Nechita #define AD7779_UPPER GENMASK(23, 16) 111*c9a3f8c7SRamona Alexandra Nechita #define AD7779_MID GENMASK(15, 8) 112*c9a3f8c7SRamona Alexandra Nechita #define AD7779_LOWER GENMASK(7, 0) 113*c9a3f8c7SRamona Alexandra Nechita 114*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_MSK GENMASK(6, 0) 115*c9a3f8c7SRamona Alexandra Nechita 116*c9a3f8c7SRamona Alexandra Nechita #define AD7779_CRC8_POLY 0x07 117*c9a3f8c7SRamona Alexandra Nechita DECLARE_CRC8_TABLE(ad7779_crc8_table); 118*c9a3f8c7SRamona Alexandra Nechita 119*c9a3f8c7SRamona Alexandra Nechita enum ad7779_filter { 120*c9a3f8c7SRamona Alexandra Nechita AD7779_SINC3, 121*c9a3f8c7SRamona Alexandra Nechita AD7779_SINC5, 122*c9a3f8c7SRamona Alexandra Nechita }; 123*c9a3f8c7SRamona Alexandra Nechita 124*c9a3f8c7SRamona Alexandra Nechita enum ad7779_variant { 125*c9a3f8c7SRamona Alexandra Nechita ad7770, 126*c9a3f8c7SRamona Alexandra Nechita ad7771, 127*c9a3f8c7SRamona Alexandra Nechita ad7779, 128*c9a3f8c7SRamona Alexandra Nechita }; 129*c9a3f8c7SRamona Alexandra Nechita 130*c9a3f8c7SRamona Alexandra Nechita enum ad7779_power_mode { 131*c9a3f8c7SRamona Alexandra Nechita AD7779_LOW_POWER, 132*c9a3f8c7SRamona Alexandra Nechita AD7779_HIGH_POWER, 133*c9a3f8c7SRamona Alexandra Nechita }; 134*c9a3f8c7SRamona Alexandra Nechita 135*c9a3f8c7SRamona Alexandra Nechita struct ad7779_chip_info { 136*c9a3f8c7SRamona Alexandra Nechita const char *name; 137*c9a3f8c7SRamona Alexandra Nechita struct iio_chan_spec const *channels; 138*c9a3f8c7SRamona Alexandra Nechita }; 139*c9a3f8c7SRamona Alexandra Nechita 140*c9a3f8c7SRamona Alexandra Nechita struct ad7779_state { 141*c9a3f8c7SRamona Alexandra Nechita struct spi_device *spi; 142*c9a3f8c7SRamona Alexandra Nechita const struct ad7779_chip_info *chip_info; 143*c9a3f8c7SRamona Alexandra Nechita struct clk *mclk; 144*c9a3f8c7SRamona Alexandra Nechita struct iio_trigger *trig; 145*c9a3f8c7SRamona Alexandra Nechita struct completion completion; 146*c9a3f8c7SRamona Alexandra Nechita unsigned int sampling_freq; 147*c9a3f8c7SRamona Alexandra Nechita enum ad7779_filter filter_enabled; 148*c9a3f8c7SRamona Alexandra Nechita /* 149*c9a3f8c7SRamona Alexandra Nechita * DMA (thus cache coherency maintenance) requires the 150*c9a3f8c7SRamona Alexandra Nechita * transfer buffers to live in their own cache lines. 151*c9a3f8c7SRamona Alexandra Nechita */ 152*c9a3f8c7SRamona Alexandra Nechita struct { 153*c9a3f8c7SRamona Alexandra Nechita u32 chans[8]; 154*c9a3f8c7SRamona Alexandra Nechita aligned_s64 timestamp; 155*c9a3f8c7SRamona Alexandra Nechita } data __aligned(IIO_DMA_MINALIGN); 156*c9a3f8c7SRamona Alexandra Nechita u32 spidata_tx[8]; 157*c9a3f8c7SRamona Alexandra Nechita u8 reg_rx_buf[3]; 158*c9a3f8c7SRamona Alexandra Nechita u8 reg_tx_buf[3]; 159*c9a3f8c7SRamona Alexandra Nechita u8 reset_buf[8]; 160*c9a3f8c7SRamona Alexandra Nechita }; 161*c9a3f8c7SRamona Alexandra Nechita 162*c9a3f8c7SRamona Alexandra Nechita static const char * const ad7779_filter_type[] = { 163*c9a3f8c7SRamona Alexandra Nechita [AD7779_SINC3] = "sinc3", 164*c9a3f8c7SRamona Alexandra Nechita [AD7779_SINC5] = "sinc5", 165*c9a3f8c7SRamona Alexandra Nechita }; 166*c9a3f8c7SRamona Alexandra Nechita 167*c9a3f8c7SRamona Alexandra Nechita static const char * const ad7779_power_supplies[] = { 168*c9a3f8c7SRamona Alexandra Nechita "avdd1", "avdd2", "avdd4", 169*c9a3f8c7SRamona Alexandra Nechita }; 170*c9a3f8c7SRamona Alexandra Nechita 171*c9a3f8c7SRamona Alexandra Nechita static int ad7779_spi_read(struct ad7779_state *st, u8 reg, u8 *rbuf) 172*c9a3f8c7SRamona Alexandra Nechita { 173*c9a3f8c7SRamona Alexandra Nechita int ret; 174*c9a3f8c7SRamona Alexandra Nechita u8 crc_buf[2]; 175*c9a3f8c7SRamona Alexandra Nechita u8 exp_crc; 176*c9a3f8c7SRamona Alexandra Nechita struct spi_transfer t = { 177*c9a3f8c7SRamona Alexandra Nechita .tx_buf = st->reg_tx_buf, 178*c9a3f8c7SRamona Alexandra Nechita .rx_buf = st->reg_rx_buf, 179*c9a3f8c7SRamona Alexandra Nechita }; 180*c9a3f8c7SRamona Alexandra Nechita 181*c9a3f8c7SRamona Alexandra Nechita st->reg_tx_buf[0] = AD7779_SPI_READ_CMD | FIELD_GET(AD7779_REG_MSK, reg); 182*c9a3f8c7SRamona Alexandra Nechita st->reg_tx_buf[1] = 0; 183*c9a3f8c7SRamona Alexandra Nechita 184*c9a3f8c7SRamona Alexandra Nechita if (reg == AD7779_REG_GEN_ERR_REG_1_EN) { 185*c9a3f8c7SRamona Alexandra Nechita t.len = 2; 186*c9a3f8c7SRamona Alexandra Nechita } else { 187*c9a3f8c7SRamona Alexandra Nechita t.len = 3; 188*c9a3f8c7SRamona Alexandra Nechita st->reg_tx_buf[2] = crc8(ad7779_crc8_table, st->reg_tx_buf, 189*c9a3f8c7SRamona Alexandra Nechita t.len - 1, 0); 190*c9a3f8c7SRamona Alexandra Nechita } 191*c9a3f8c7SRamona Alexandra Nechita 192*c9a3f8c7SRamona Alexandra Nechita ret = spi_sync_transfer(st->spi, &t, 1); 193*c9a3f8c7SRamona Alexandra Nechita if (ret) 194*c9a3f8c7SRamona Alexandra Nechita return ret; 195*c9a3f8c7SRamona Alexandra Nechita 196*c9a3f8c7SRamona Alexandra Nechita crc_buf[0] = AD7779_SPI_READ_CMD | FIELD_GET(AD7779_REG_MSK, reg); 197*c9a3f8c7SRamona Alexandra Nechita crc_buf[1] = st->reg_rx_buf[1]; 198*c9a3f8c7SRamona Alexandra Nechita exp_crc = crc8(ad7779_crc8_table, crc_buf, ARRAY_SIZE(crc_buf), 0); 199*c9a3f8c7SRamona Alexandra Nechita if (reg != AD7779_REG_GEN_ERR_REG_1_EN && exp_crc != st->reg_rx_buf[2]) { 200*c9a3f8c7SRamona Alexandra Nechita dev_err(&st->spi->dev, "Bad CRC %x, expected %x", 201*c9a3f8c7SRamona Alexandra Nechita st->reg_rx_buf[2], exp_crc); 202*c9a3f8c7SRamona Alexandra Nechita return -EINVAL; 203*c9a3f8c7SRamona Alexandra Nechita } 204*c9a3f8c7SRamona Alexandra Nechita *rbuf = st->reg_rx_buf[1]; 205*c9a3f8c7SRamona Alexandra Nechita 206*c9a3f8c7SRamona Alexandra Nechita return 0; 207*c9a3f8c7SRamona Alexandra Nechita } 208*c9a3f8c7SRamona Alexandra Nechita 209*c9a3f8c7SRamona Alexandra Nechita static int ad7779_spi_write(struct ad7779_state *st, u8 reg, u8 val) 210*c9a3f8c7SRamona Alexandra Nechita { 211*c9a3f8c7SRamona Alexandra Nechita u8 length = 3; 212*c9a3f8c7SRamona Alexandra Nechita 213*c9a3f8c7SRamona Alexandra Nechita st->reg_tx_buf[0] = FIELD_GET(AD7779_REG_MSK, reg); 214*c9a3f8c7SRamona Alexandra Nechita st->reg_tx_buf[1] = val; 215*c9a3f8c7SRamona Alexandra Nechita if (reg == AD7779_REG_GEN_ERR_REG_1_EN) 216*c9a3f8c7SRamona Alexandra Nechita length = 2; 217*c9a3f8c7SRamona Alexandra Nechita else 218*c9a3f8c7SRamona Alexandra Nechita st->reg_tx_buf[2] = crc8(ad7779_crc8_table, st->reg_tx_buf, 219*c9a3f8c7SRamona Alexandra Nechita length - 1, 0); 220*c9a3f8c7SRamona Alexandra Nechita 221*c9a3f8c7SRamona Alexandra Nechita return spi_write(st->spi, st->reg_tx_buf, length); 222*c9a3f8c7SRamona Alexandra Nechita } 223*c9a3f8c7SRamona Alexandra Nechita 224*c9a3f8c7SRamona Alexandra Nechita static int ad7779_spi_write_mask(struct ad7779_state *st, u8 reg, u8 mask, 225*c9a3f8c7SRamona Alexandra Nechita u8 val) 226*c9a3f8c7SRamona Alexandra Nechita { 227*c9a3f8c7SRamona Alexandra Nechita int ret; 228*c9a3f8c7SRamona Alexandra Nechita u8 regval, data; 229*c9a3f8c7SRamona Alexandra Nechita 230*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_spi_read(st, reg, &data); 231*c9a3f8c7SRamona Alexandra Nechita if (ret) 232*c9a3f8c7SRamona Alexandra Nechita return ret; 233*c9a3f8c7SRamona Alexandra Nechita 234*c9a3f8c7SRamona Alexandra Nechita regval = (data & ~mask) | (val & mask); 235*c9a3f8c7SRamona Alexandra Nechita 236*c9a3f8c7SRamona Alexandra Nechita if (regval == data) 237*c9a3f8c7SRamona Alexandra Nechita return 0; 238*c9a3f8c7SRamona Alexandra Nechita 239*c9a3f8c7SRamona Alexandra Nechita return ad7779_spi_write(st, reg, regval); 240*c9a3f8c7SRamona Alexandra Nechita } 241*c9a3f8c7SRamona Alexandra Nechita 242*c9a3f8c7SRamona Alexandra Nechita static int ad7779_reg_access(struct iio_dev *indio_dev, 243*c9a3f8c7SRamona Alexandra Nechita unsigned int reg, 244*c9a3f8c7SRamona Alexandra Nechita unsigned int writeval, 245*c9a3f8c7SRamona Alexandra Nechita unsigned int *readval) 246*c9a3f8c7SRamona Alexandra Nechita { 247*c9a3f8c7SRamona Alexandra Nechita struct ad7779_state *st = iio_priv(indio_dev); 248*c9a3f8c7SRamona Alexandra Nechita u8 rval; 249*c9a3f8c7SRamona Alexandra Nechita int ret; 250*c9a3f8c7SRamona Alexandra Nechita 251*c9a3f8c7SRamona Alexandra Nechita if (readval) { 252*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_spi_read(st, reg, &rval); 253*c9a3f8c7SRamona Alexandra Nechita *readval = rval; 254*c9a3f8c7SRamona Alexandra Nechita return ret; 255*c9a3f8c7SRamona Alexandra Nechita } 256*c9a3f8c7SRamona Alexandra Nechita 257*c9a3f8c7SRamona Alexandra Nechita return ad7779_spi_write(st, reg, writeval); 258*c9a3f8c7SRamona Alexandra Nechita } 259*c9a3f8c7SRamona Alexandra Nechita 260*c9a3f8c7SRamona Alexandra Nechita static int ad7779_set_sampling_frequency(struct ad7779_state *st, 261*c9a3f8c7SRamona Alexandra Nechita unsigned int sampling_freq) 262*c9a3f8c7SRamona Alexandra Nechita { 263*c9a3f8c7SRamona Alexandra Nechita int ret; 264*c9a3f8c7SRamona Alexandra Nechita unsigned int dec; 265*c9a3f8c7SRamona Alexandra Nechita unsigned int frac; 266*c9a3f8c7SRamona Alexandra Nechita unsigned int div; 267*c9a3f8c7SRamona Alexandra Nechita unsigned int decimal; 268*c9a3f8c7SRamona Alexandra Nechita unsigned int freq_khz; 269*c9a3f8c7SRamona Alexandra Nechita 270*c9a3f8c7SRamona Alexandra Nechita if (st->filter_enabled == AD7779_SINC3 && 271*c9a3f8c7SRamona Alexandra Nechita sampling_freq > AD7779_SINC3_MAXFREQ) 272*c9a3f8c7SRamona Alexandra Nechita return -EINVAL; 273*c9a3f8c7SRamona Alexandra Nechita 274*c9a3f8c7SRamona Alexandra Nechita if (st->filter_enabled == AD7779_SINC5 && 275*c9a3f8c7SRamona Alexandra Nechita sampling_freq > AD7779_SINC5_MAXFREQ) 276*c9a3f8c7SRamona Alexandra Nechita return -EINVAL; 277*c9a3f8c7SRamona Alexandra Nechita 278*c9a3f8c7SRamona Alexandra Nechita if (sampling_freq > AD7779_SPIMODE_MAX_SAMP_FREQ) 279*c9a3f8c7SRamona Alexandra Nechita return -EINVAL; 280*c9a3f8c7SRamona Alexandra Nechita 281*c9a3f8c7SRamona Alexandra Nechita div = AD7779_HIGHPOWER_DIV; 282*c9a3f8c7SRamona Alexandra Nechita 283*c9a3f8c7SRamona Alexandra Nechita freq_khz = sampling_freq / HZ_PER_KHZ; 284*c9a3f8c7SRamona Alexandra Nechita dec = div / freq_khz; 285*c9a3f8c7SRamona Alexandra Nechita frac = div % freq_khz; 286*c9a3f8c7SRamona Alexandra Nechita 287*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_spi_write(st, AD7779_REG_SRC_N_MSB, 288*c9a3f8c7SRamona Alexandra Nechita FIELD_GET(AD7779_FREQ_MSB_MSK, dec)); 289*c9a3f8c7SRamona Alexandra Nechita if (ret) 290*c9a3f8c7SRamona Alexandra Nechita return ret; 291*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_spi_write(st, AD7779_REG_SRC_N_LSB, 292*c9a3f8c7SRamona Alexandra Nechita FIELD_GET(AD7779_FREQ_LSB_MSK, dec)); 293*c9a3f8c7SRamona Alexandra Nechita if (ret) 294*c9a3f8c7SRamona Alexandra Nechita return ret; 295*c9a3f8c7SRamona Alexandra Nechita 296*c9a3f8c7SRamona Alexandra Nechita if (frac) { 297*c9a3f8c7SRamona Alexandra Nechita /* 298*c9a3f8c7SRamona Alexandra Nechita * In order to obtain the first three decimals of the decimation 299*c9a3f8c7SRamona Alexandra Nechita * the initial number is multiplied with 10^3 prior to the 300*c9a3f8c7SRamona Alexandra Nechita * division, then the original division result is subtracted and 301*c9a3f8c7SRamona Alexandra Nechita * the number is divided by 10^3. 302*c9a3f8c7SRamona Alexandra Nechita */ 303*c9a3f8c7SRamona Alexandra Nechita decimal = ((mult_frac(div, KILO, freq_khz) - dec * KILO) << 16) 304*c9a3f8c7SRamona Alexandra Nechita / KILO; 305*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_spi_write(st, AD7779_REG_SRC_N_MSB, 306*c9a3f8c7SRamona Alexandra Nechita FIELD_GET(AD7779_FREQ_MSB_MSK, decimal)); 307*c9a3f8c7SRamona Alexandra Nechita if (ret) 308*c9a3f8c7SRamona Alexandra Nechita return ret; 309*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_spi_write(st, AD7779_REG_SRC_N_LSB, 310*c9a3f8c7SRamona Alexandra Nechita FIELD_GET(AD7779_FREQ_LSB_MSK, decimal)); 311*c9a3f8c7SRamona Alexandra Nechita if (ret) 312*c9a3f8c7SRamona Alexandra Nechita return ret; 313*c9a3f8c7SRamona Alexandra Nechita } else { 314*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_spi_write(st, AD7779_REG_SRC_N_MSB, 315*c9a3f8c7SRamona Alexandra Nechita FIELD_GET(AD7779_FREQ_MSB_MSK, 0x0)); 316*c9a3f8c7SRamona Alexandra Nechita if (ret) 317*c9a3f8c7SRamona Alexandra Nechita return ret; 318*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_spi_write(st, AD7779_REG_SRC_N_LSB, 319*c9a3f8c7SRamona Alexandra Nechita FIELD_GET(AD7779_FREQ_LSB_MSK, 0x0)); 320*c9a3f8c7SRamona Alexandra Nechita if (ret) 321*c9a3f8c7SRamona Alexandra Nechita return ret; 322*c9a3f8c7SRamona Alexandra Nechita } 323*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_spi_write(st, AD7779_REG_SRC_UPDATE, BIT(0)); 324*c9a3f8c7SRamona Alexandra Nechita if (ret) 325*c9a3f8c7SRamona Alexandra Nechita return ret; 326*c9a3f8c7SRamona Alexandra Nechita 327*c9a3f8c7SRamona Alexandra Nechita /* SRC update settling time */ 328*c9a3f8c7SRamona Alexandra Nechita fsleep(15); 329*c9a3f8c7SRamona Alexandra Nechita 330*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_spi_write(st, AD7779_REG_SRC_UPDATE, 0x0); 331*c9a3f8c7SRamona Alexandra Nechita if (ret) 332*c9a3f8c7SRamona Alexandra Nechita return ret; 333*c9a3f8c7SRamona Alexandra Nechita 334*c9a3f8c7SRamona Alexandra Nechita /* SRC update settling time */ 335*c9a3f8c7SRamona Alexandra Nechita fsleep(15); 336*c9a3f8c7SRamona Alexandra Nechita 337*c9a3f8c7SRamona Alexandra Nechita st->sampling_freq = sampling_freq; 338*c9a3f8c7SRamona Alexandra Nechita 339*c9a3f8c7SRamona Alexandra Nechita return 0; 340*c9a3f8c7SRamona Alexandra Nechita } 341*c9a3f8c7SRamona Alexandra Nechita 342*c9a3f8c7SRamona Alexandra Nechita static int ad7779_get_filter(struct iio_dev *indio_dev, 343*c9a3f8c7SRamona Alexandra Nechita struct iio_chan_spec const *chan) 344*c9a3f8c7SRamona Alexandra Nechita { 345*c9a3f8c7SRamona Alexandra Nechita struct ad7779_state *st = iio_priv(indio_dev); 346*c9a3f8c7SRamona Alexandra Nechita u8 temp; 347*c9a3f8c7SRamona Alexandra Nechita int ret; 348*c9a3f8c7SRamona Alexandra Nechita 349*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_spi_read(st, AD7779_REG_GENERAL_USER_CONFIG_2, &temp); 350*c9a3f8c7SRamona Alexandra Nechita if (ret) 351*c9a3f8c7SRamona Alexandra Nechita return ret; 352*c9a3f8c7SRamona Alexandra Nechita 353*c9a3f8c7SRamona Alexandra Nechita return FIELD_GET(AD7779_FILTER_MSK, temp); 354*c9a3f8c7SRamona Alexandra Nechita } 355*c9a3f8c7SRamona Alexandra Nechita 356*c9a3f8c7SRamona Alexandra Nechita static int ad7779_set_filter(struct iio_dev *indio_dev, 357*c9a3f8c7SRamona Alexandra Nechita struct iio_chan_spec const *chan, 358*c9a3f8c7SRamona Alexandra Nechita unsigned int mode) 359*c9a3f8c7SRamona Alexandra Nechita { 360*c9a3f8c7SRamona Alexandra Nechita struct ad7779_state *st = iio_priv(indio_dev); 361*c9a3f8c7SRamona Alexandra Nechita int ret; 362*c9a3f8c7SRamona Alexandra Nechita 363*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_spi_write_mask(st, 364*c9a3f8c7SRamona Alexandra Nechita AD7779_REG_GENERAL_USER_CONFIG_2, 365*c9a3f8c7SRamona Alexandra Nechita AD7779_FILTER_MSK, 366*c9a3f8c7SRamona Alexandra Nechita FIELD_PREP(AD7779_FILTER_MSK, mode)); 367*c9a3f8c7SRamona Alexandra Nechita if (ret) 368*c9a3f8c7SRamona Alexandra Nechita return ret; 369*c9a3f8c7SRamona Alexandra Nechita 370*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_set_sampling_frequency(st, st->sampling_freq); 371*c9a3f8c7SRamona Alexandra Nechita if (ret) 372*c9a3f8c7SRamona Alexandra Nechita return ret; 373*c9a3f8c7SRamona Alexandra Nechita 374*c9a3f8c7SRamona Alexandra Nechita st->filter_enabled = mode; 375*c9a3f8c7SRamona Alexandra Nechita 376*c9a3f8c7SRamona Alexandra Nechita return 0; 377*c9a3f8c7SRamona Alexandra Nechita } 378*c9a3f8c7SRamona Alexandra Nechita 379*c9a3f8c7SRamona Alexandra Nechita static int ad7779_get_calibscale(struct ad7779_state *st, int channel) 380*c9a3f8c7SRamona Alexandra Nechita { 381*c9a3f8c7SRamona Alexandra Nechita int ret; 382*c9a3f8c7SRamona Alexandra Nechita u8 calibscale[3]; 383*c9a3f8c7SRamona Alexandra Nechita 384*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_spi_read(st, AD7779_REG_CH_GAIN_LOWER_BYTE(channel), 385*c9a3f8c7SRamona Alexandra Nechita &calibscale[0]); 386*c9a3f8c7SRamona Alexandra Nechita if (ret) 387*c9a3f8c7SRamona Alexandra Nechita return ret; 388*c9a3f8c7SRamona Alexandra Nechita 389*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_spi_read(st, AD7779_REG_CH_GAIN_MID_BYTE(channel), 390*c9a3f8c7SRamona Alexandra Nechita &calibscale[1]); 391*c9a3f8c7SRamona Alexandra Nechita if (ret) 392*c9a3f8c7SRamona Alexandra Nechita return ret; 393*c9a3f8c7SRamona Alexandra Nechita 394*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_spi_read(st, AD7779_REG_CH_GAIN_UPPER_BYTE(channel), 395*c9a3f8c7SRamona Alexandra Nechita &calibscale[2]); 396*c9a3f8c7SRamona Alexandra Nechita if (ret) 397*c9a3f8c7SRamona Alexandra Nechita return ret; 398*c9a3f8c7SRamona Alexandra Nechita 399*c9a3f8c7SRamona Alexandra Nechita return get_unaligned_be24(calibscale); 400*c9a3f8c7SRamona Alexandra Nechita } 401*c9a3f8c7SRamona Alexandra Nechita 402*c9a3f8c7SRamona Alexandra Nechita static int ad7779_set_calibscale(struct ad7779_state *st, int channel, int val) 403*c9a3f8c7SRamona Alexandra Nechita { 404*c9a3f8c7SRamona Alexandra Nechita int ret; 405*c9a3f8c7SRamona Alexandra Nechita unsigned int gain; 406*c9a3f8c7SRamona Alexandra Nechita u8 gain_bytes[3]; 407*c9a3f8c7SRamona Alexandra Nechita 408*c9a3f8c7SRamona Alexandra Nechita /* 409*c9a3f8c7SRamona Alexandra Nechita * The gain value is relative to 0x555555, which represents a gain of 1 410*c9a3f8c7SRamona Alexandra Nechita */ 411*c9a3f8c7SRamona Alexandra Nechita gain = DIV_ROUND_CLOSEST_ULL((u64)val * 5592405LL, MEGA); 412*c9a3f8c7SRamona Alexandra Nechita put_unaligned_be24(gain, gain_bytes); 413*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_spi_write(st, AD7779_REG_CH_GAIN_UPPER_BYTE(channel), 414*c9a3f8c7SRamona Alexandra Nechita gain_bytes[0]); 415*c9a3f8c7SRamona Alexandra Nechita if (ret) 416*c9a3f8c7SRamona Alexandra Nechita return ret; 417*c9a3f8c7SRamona Alexandra Nechita 418*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_spi_write(st, AD7779_REG_CH_GAIN_MID_BYTE(channel), 419*c9a3f8c7SRamona Alexandra Nechita gain_bytes[1]); 420*c9a3f8c7SRamona Alexandra Nechita if (ret) 421*c9a3f8c7SRamona Alexandra Nechita return ret; 422*c9a3f8c7SRamona Alexandra Nechita 423*c9a3f8c7SRamona Alexandra Nechita return ad7779_spi_write(st, AD7779_REG_CH_GAIN_LOWER_BYTE(channel), 424*c9a3f8c7SRamona Alexandra Nechita gain_bytes[2]); 425*c9a3f8c7SRamona Alexandra Nechita } 426*c9a3f8c7SRamona Alexandra Nechita 427*c9a3f8c7SRamona Alexandra Nechita static int ad7779_get_calibbias(struct ad7779_state *st, int channel) 428*c9a3f8c7SRamona Alexandra Nechita { 429*c9a3f8c7SRamona Alexandra Nechita int ret; 430*c9a3f8c7SRamona Alexandra Nechita u8 calibbias[3]; 431*c9a3f8c7SRamona Alexandra Nechita 432*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_spi_read(st, AD7779_REG_CH_OFFSET_LOWER_BYTE(channel), 433*c9a3f8c7SRamona Alexandra Nechita &calibbias[0]); 434*c9a3f8c7SRamona Alexandra Nechita if (ret) 435*c9a3f8c7SRamona Alexandra Nechita return ret; 436*c9a3f8c7SRamona Alexandra Nechita 437*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_spi_read(st, AD7779_REG_CH_OFFSET_MID_BYTE(channel), 438*c9a3f8c7SRamona Alexandra Nechita &calibbias[1]); 439*c9a3f8c7SRamona Alexandra Nechita if (ret) 440*c9a3f8c7SRamona Alexandra Nechita return ret; 441*c9a3f8c7SRamona Alexandra Nechita 442*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_spi_read(st, AD7779_REG_CH_OFFSET_UPPER_BYTE(channel), 443*c9a3f8c7SRamona Alexandra Nechita &calibbias[2]); 444*c9a3f8c7SRamona Alexandra Nechita if (ret) 445*c9a3f8c7SRamona Alexandra Nechita return ret; 446*c9a3f8c7SRamona Alexandra Nechita 447*c9a3f8c7SRamona Alexandra Nechita return get_unaligned_be24(calibbias); 448*c9a3f8c7SRamona Alexandra Nechita } 449*c9a3f8c7SRamona Alexandra Nechita 450*c9a3f8c7SRamona Alexandra Nechita static int ad7779_set_calibbias(struct ad7779_state *st, int channel, int val) 451*c9a3f8c7SRamona Alexandra Nechita { 452*c9a3f8c7SRamona Alexandra Nechita int ret; 453*c9a3f8c7SRamona Alexandra Nechita u8 calibbias[3]; 454*c9a3f8c7SRamona Alexandra Nechita 455*c9a3f8c7SRamona Alexandra Nechita put_unaligned_be24(val, calibbias); 456*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_spi_write(st, AD7779_REG_CH_OFFSET_UPPER_BYTE(channel), 457*c9a3f8c7SRamona Alexandra Nechita calibbias[0]); 458*c9a3f8c7SRamona Alexandra Nechita if (ret) 459*c9a3f8c7SRamona Alexandra Nechita return ret; 460*c9a3f8c7SRamona Alexandra Nechita 461*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_spi_write(st, AD7779_REG_CH_OFFSET_MID_BYTE(channel), 462*c9a3f8c7SRamona Alexandra Nechita calibbias[1]); 463*c9a3f8c7SRamona Alexandra Nechita if (ret) 464*c9a3f8c7SRamona Alexandra Nechita return ret; 465*c9a3f8c7SRamona Alexandra Nechita 466*c9a3f8c7SRamona Alexandra Nechita return ad7779_spi_write(st, AD7779_REG_CH_OFFSET_LOWER_BYTE(channel), 467*c9a3f8c7SRamona Alexandra Nechita calibbias[2]); 468*c9a3f8c7SRamona Alexandra Nechita } 469*c9a3f8c7SRamona Alexandra Nechita 470*c9a3f8c7SRamona Alexandra Nechita static int ad7779_read_raw(struct iio_dev *indio_dev, 471*c9a3f8c7SRamona Alexandra Nechita struct iio_chan_spec const *chan, int *val, 472*c9a3f8c7SRamona Alexandra Nechita int *val2, long mask) 473*c9a3f8c7SRamona Alexandra Nechita { 474*c9a3f8c7SRamona Alexandra Nechita struct ad7779_state *st = iio_priv(indio_dev); 475*c9a3f8c7SRamona Alexandra Nechita int ret; 476*c9a3f8c7SRamona Alexandra Nechita 477*c9a3f8c7SRamona Alexandra Nechita iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { 478*c9a3f8c7SRamona Alexandra Nechita switch (mask) { 479*c9a3f8c7SRamona Alexandra Nechita case IIO_CHAN_INFO_CALIBSCALE: 480*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_get_calibscale(st, chan->channel); 481*c9a3f8c7SRamona Alexandra Nechita if (ret < 0) 482*c9a3f8c7SRamona Alexandra Nechita return ret; 483*c9a3f8c7SRamona Alexandra Nechita *val = ret; 484*c9a3f8c7SRamona Alexandra Nechita *val2 = GAIN_REL; 485*c9a3f8c7SRamona Alexandra Nechita return IIO_VAL_FRACTIONAL; 486*c9a3f8c7SRamona Alexandra Nechita case IIO_CHAN_INFO_CALIBBIAS: 487*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_get_calibbias(st, chan->channel); 488*c9a3f8c7SRamona Alexandra Nechita if (ret < 0) 489*c9a3f8c7SRamona Alexandra Nechita return ret; 490*c9a3f8c7SRamona Alexandra Nechita *val = ret; 491*c9a3f8c7SRamona Alexandra Nechita return IIO_VAL_INT; 492*c9a3f8c7SRamona Alexandra Nechita case IIO_CHAN_INFO_SAMP_FREQ: 493*c9a3f8c7SRamona Alexandra Nechita *val = st->sampling_freq; 494*c9a3f8c7SRamona Alexandra Nechita if (*val < 0) 495*c9a3f8c7SRamona Alexandra Nechita return -EINVAL; 496*c9a3f8c7SRamona Alexandra Nechita return IIO_VAL_INT; 497*c9a3f8c7SRamona Alexandra Nechita default: 498*c9a3f8c7SRamona Alexandra Nechita return -EINVAL; 499*c9a3f8c7SRamona Alexandra Nechita } 500*c9a3f8c7SRamona Alexandra Nechita } 501*c9a3f8c7SRamona Alexandra Nechita unreachable(); 502*c9a3f8c7SRamona Alexandra Nechita } 503*c9a3f8c7SRamona Alexandra Nechita 504*c9a3f8c7SRamona Alexandra Nechita static int ad7779_write_raw(struct iio_dev *indio_dev, 505*c9a3f8c7SRamona Alexandra Nechita struct iio_chan_spec const *chan, int val, int val2, 506*c9a3f8c7SRamona Alexandra Nechita long mask) 507*c9a3f8c7SRamona Alexandra Nechita { 508*c9a3f8c7SRamona Alexandra Nechita struct ad7779_state *st = iio_priv(indio_dev); 509*c9a3f8c7SRamona Alexandra Nechita 510*c9a3f8c7SRamona Alexandra Nechita iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { 511*c9a3f8c7SRamona Alexandra Nechita switch (mask) { 512*c9a3f8c7SRamona Alexandra Nechita case IIO_CHAN_INFO_CALIBSCALE: 513*c9a3f8c7SRamona Alexandra Nechita return ad7779_set_calibscale(st, chan->channel, val2); 514*c9a3f8c7SRamona Alexandra Nechita case IIO_CHAN_INFO_CALIBBIAS: 515*c9a3f8c7SRamona Alexandra Nechita return ad7779_set_calibbias(st, chan->channel, val); 516*c9a3f8c7SRamona Alexandra Nechita case IIO_CHAN_INFO_SAMP_FREQ: 517*c9a3f8c7SRamona Alexandra Nechita return ad7779_set_sampling_frequency(st, val); 518*c9a3f8c7SRamona Alexandra Nechita default: 519*c9a3f8c7SRamona Alexandra Nechita return -EINVAL; 520*c9a3f8c7SRamona Alexandra Nechita } 521*c9a3f8c7SRamona Alexandra Nechita } 522*c9a3f8c7SRamona Alexandra Nechita unreachable(); 523*c9a3f8c7SRamona Alexandra Nechita } 524*c9a3f8c7SRamona Alexandra Nechita 525*c9a3f8c7SRamona Alexandra Nechita static int ad7779_buffer_preenable(struct iio_dev *indio_dev) 526*c9a3f8c7SRamona Alexandra Nechita { 527*c9a3f8c7SRamona Alexandra Nechita int ret; 528*c9a3f8c7SRamona Alexandra Nechita struct ad7779_state *st = iio_priv(indio_dev); 529*c9a3f8c7SRamona Alexandra Nechita 530*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_spi_write_mask(st, 531*c9a3f8c7SRamona Alexandra Nechita AD7779_REG_GENERAL_USER_CONFIG_3, 532*c9a3f8c7SRamona Alexandra Nechita AD7779_MOD_SPI_EN_MSK, 533*c9a3f8c7SRamona Alexandra Nechita FIELD_PREP(AD7779_MOD_SPI_EN_MSK, 1)); 534*c9a3f8c7SRamona Alexandra Nechita if (ret) 535*c9a3f8c7SRamona Alexandra Nechita return ret; 536*c9a3f8c7SRamona Alexandra Nechita 537*c9a3f8c7SRamona Alexandra Nechita /* 538*c9a3f8c7SRamona Alexandra Nechita * DRDY output cannot be disabled at device level therefore we mask 539*c9a3f8c7SRamona Alexandra Nechita * the irq at host end. 540*c9a3f8c7SRamona Alexandra Nechita */ 541*c9a3f8c7SRamona Alexandra Nechita enable_irq(st->spi->irq); 542*c9a3f8c7SRamona Alexandra Nechita 543*c9a3f8c7SRamona Alexandra Nechita return 0; 544*c9a3f8c7SRamona Alexandra Nechita } 545*c9a3f8c7SRamona Alexandra Nechita 546*c9a3f8c7SRamona Alexandra Nechita static int ad7779_buffer_postdisable(struct iio_dev *indio_dev) 547*c9a3f8c7SRamona Alexandra Nechita { 548*c9a3f8c7SRamona Alexandra Nechita struct ad7779_state *st = iio_priv(indio_dev); 549*c9a3f8c7SRamona Alexandra Nechita 550*c9a3f8c7SRamona Alexandra Nechita disable_irq(st->spi->irq); 551*c9a3f8c7SRamona Alexandra Nechita 552*c9a3f8c7SRamona Alexandra Nechita return ad7779_spi_write(st, AD7779_REG_GENERAL_USER_CONFIG_3, 553*c9a3f8c7SRamona Alexandra Nechita AD7779_DISABLE_SD); 554*c9a3f8c7SRamona Alexandra Nechita } 555*c9a3f8c7SRamona Alexandra Nechita 556*c9a3f8c7SRamona Alexandra Nechita static irqreturn_t ad7779_trigger_handler(int irq, void *p) 557*c9a3f8c7SRamona Alexandra Nechita { 558*c9a3f8c7SRamona Alexandra Nechita struct iio_poll_func *pf = p; 559*c9a3f8c7SRamona Alexandra Nechita struct iio_dev *indio_dev = pf->indio_dev; 560*c9a3f8c7SRamona Alexandra Nechita struct ad7779_state *st = iio_priv(indio_dev); 561*c9a3f8c7SRamona Alexandra Nechita int ret; 562*c9a3f8c7SRamona Alexandra Nechita struct spi_transfer t = { 563*c9a3f8c7SRamona Alexandra Nechita .rx_buf = st->data.chans, 564*c9a3f8c7SRamona Alexandra Nechita .tx_buf = st->spidata_tx, 565*c9a3f8c7SRamona Alexandra Nechita .len = AD7779_NUM_CHANNELS * AD7779_CHAN_DATA_SIZE, 566*c9a3f8c7SRamona Alexandra Nechita }; 567*c9a3f8c7SRamona Alexandra Nechita 568*c9a3f8c7SRamona Alexandra Nechita st->spidata_tx[0] = AD7779_SPI_READ_CMD; 569*c9a3f8c7SRamona Alexandra Nechita ret = spi_sync_transfer(st->spi, &t, 1); 570*c9a3f8c7SRamona Alexandra Nechita if (ret) { 571*c9a3f8c7SRamona Alexandra Nechita dev_err(&st->spi->dev, "SPI transfer error in IRQ handler"); 572*c9a3f8c7SRamona Alexandra Nechita goto exit_handler; 573*c9a3f8c7SRamona Alexandra Nechita } 574*c9a3f8c7SRamona Alexandra Nechita 575*c9a3f8c7SRamona Alexandra Nechita iio_push_to_buffers_with_timestamp(indio_dev, &st->data, pf->timestamp); 576*c9a3f8c7SRamona Alexandra Nechita 577*c9a3f8c7SRamona Alexandra Nechita exit_handler: 578*c9a3f8c7SRamona Alexandra Nechita iio_trigger_notify_done(indio_dev->trig); 579*c9a3f8c7SRamona Alexandra Nechita return IRQ_HANDLED; 580*c9a3f8c7SRamona Alexandra Nechita } 581*c9a3f8c7SRamona Alexandra Nechita 582*c9a3f8c7SRamona Alexandra Nechita static int ad7779_reset(struct iio_dev *indio_dev, struct gpio_desc *reset_gpio) 583*c9a3f8c7SRamona Alexandra Nechita { 584*c9a3f8c7SRamona Alexandra Nechita struct ad7779_state *st = iio_priv(indio_dev); 585*c9a3f8c7SRamona Alexandra Nechita int ret; 586*c9a3f8c7SRamona Alexandra Nechita struct spi_transfer t = { 587*c9a3f8c7SRamona Alexandra Nechita .tx_buf = st->reset_buf, 588*c9a3f8c7SRamona Alexandra Nechita .len = 8, 589*c9a3f8c7SRamona Alexandra Nechita }; 590*c9a3f8c7SRamona Alexandra Nechita 591*c9a3f8c7SRamona Alexandra Nechita if (reset_gpio) { 592*c9a3f8c7SRamona Alexandra Nechita gpiod_set_value(reset_gpio, 1); 593*c9a3f8c7SRamona Alexandra Nechita /* Delay for reset to occur is 225 microseconds */ 594*c9a3f8c7SRamona Alexandra Nechita fsleep(230); 595*c9a3f8c7SRamona Alexandra Nechita ret = 0; 596*c9a3f8c7SRamona Alexandra Nechita } else { 597*c9a3f8c7SRamona Alexandra Nechita memset(st->reset_buf, 0xff, sizeof(st->reset_buf)); 598*c9a3f8c7SRamona Alexandra Nechita ret = spi_sync_transfer(st->spi, &t, 1); 599*c9a3f8c7SRamona Alexandra Nechita if (ret) 600*c9a3f8c7SRamona Alexandra Nechita return ret; 601*c9a3f8c7SRamona Alexandra Nechita } 602*c9a3f8c7SRamona Alexandra Nechita 603*c9a3f8c7SRamona Alexandra Nechita /* Delay for reset to occur is 225 microseconds */ 604*c9a3f8c7SRamona Alexandra Nechita fsleep(230); 605*c9a3f8c7SRamona Alexandra Nechita 606*c9a3f8c7SRamona Alexandra Nechita return ret; 607*c9a3f8c7SRamona Alexandra Nechita } 608*c9a3f8c7SRamona Alexandra Nechita 609*c9a3f8c7SRamona Alexandra Nechita static const struct iio_info ad7779_info = { 610*c9a3f8c7SRamona Alexandra Nechita .read_raw = ad7779_read_raw, 611*c9a3f8c7SRamona Alexandra Nechita .write_raw = ad7779_write_raw, 612*c9a3f8c7SRamona Alexandra Nechita .debugfs_reg_access = &ad7779_reg_access, 613*c9a3f8c7SRamona Alexandra Nechita }; 614*c9a3f8c7SRamona Alexandra Nechita 615*c9a3f8c7SRamona Alexandra Nechita static const struct iio_enum ad7779_filter_enum = { 616*c9a3f8c7SRamona Alexandra Nechita .items = ad7779_filter_type, 617*c9a3f8c7SRamona Alexandra Nechita .num_items = ARRAY_SIZE(ad7779_filter_type), 618*c9a3f8c7SRamona Alexandra Nechita .get = ad7779_get_filter, 619*c9a3f8c7SRamona Alexandra Nechita .set = ad7779_set_filter, 620*c9a3f8c7SRamona Alexandra Nechita }; 621*c9a3f8c7SRamona Alexandra Nechita 622*c9a3f8c7SRamona Alexandra Nechita static const struct iio_chan_spec_ext_info ad7779_ext_filter[] = { 623*c9a3f8c7SRamona Alexandra Nechita IIO_ENUM("filter_type", IIO_SHARED_BY_ALL, &ad7779_filter_enum), 624*c9a3f8c7SRamona Alexandra Nechita IIO_ENUM_AVAILABLE("filter_type", IIO_SHARED_BY_ALL, 625*c9a3f8c7SRamona Alexandra Nechita &ad7779_filter_enum), 626*c9a3f8c7SRamona Alexandra Nechita { } 627*c9a3f8c7SRamona Alexandra Nechita }; 628*c9a3f8c7SRamona Alexandra Nechita 629*c9a3f8c7SRamona Alexandra Nechita #define AD777x_CHAN_S(index, _ext_info) \ 630*c9a3f8c7SRamona Alexandra Nechita { \ 631*c9a3f8c7SRamona Alexandra Nechita .type = IIO_VOLTAGE, \ 632*c9a3f8c7SRamona Alexandra Nechita .info_mask_separate = BIT(IIO_CHAN_INFO_CALIBSCALE) | \ 633*c9a3f8c7SRamona Alexandra Nechita BIT(IIO_CHAN_INFO_CALIBBIAS), \ 634*c9a3f8c7SRamona Alexandra Nechita .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\ 635*c9a3f8c7SRamona Alexandra Nechita .address = (index), \ 636*c9a3f8c7SRamona Alexandra Nechita .indexed = 1, \ 637*c9a3f8c7SRamona Alexandra Nechita .channel = (index), \ 638*c9a3f8c7SRamona Alexandra Nechita .scan_index = (index), \ 639*c9a3f8c7SRamona Alexandra Nechita .ext_info = (_ext_info), \ 640*c9a3f8c7SRamona Alexandra Nechita .scan_type = { \ 641*c9a3f8c7SRamona Alexandra Nechita .sign = 's', \ 642*c9a3f8c7SRamona Alexandra Nechita .realbits = 24, \ 643*c9a3f8c7SRamona Alexandra Nechita .storagebits = 32, \ 644*c9a3f8c7SRamona Alexandra Nechita .endianness = IIO_BE, \ 645*c9a3f8c7SRamona Alexandra Nechita }, \ 646*c9a3f8c7SRamona Alexandra Nechita } 647*c9a3f8c7SRamona Alexandra Nechita 648*c9a3f8c7SRamona Alexandra Nechita #define AD777x_CHAN_NO_FILTER_S(index) \ 649*c9a3f8c7SRamona Alexandra Nechita AD777x_CHAN_S(index, NULL) 650*c9a3f8c7SRamona Alexandra Nechita 651*c9a3f8c7SRamona Alexandra Nechita #define AD777x_CHAN_FILTER_S(index) \ 652*c9a3f8c7SRamona Alexandra Nechita AD777x_CHAN_S(index, ad7779_ext_filter) 653*c9a3f8c7SRamona Alexandra Nechita static const struct iio_chan_spec ad7779_channels[] = { 654*c9a3f8c7SRamona Alexandra Nechita AD777x_CHAN_NO_FILTER_S(0), 655*c9a3f8c7SRamona Alexandra Nechita AD777x_CHAN_NO_FILTER_S(1), 656*c9a3f8c7SRamona Alexandra Nechita AD777x_CHAN_NO_FILTER_S(2), 657*c9a3f8c7SRamona Alexandra Nechita AD777x_CHAN_NO_FILTER_S(3), 658*c9a3f8c7SRamona Alexandra Nechita AD777x_CHAN_NO_FILTER_S(4), 659*c9a3f8c7SRamona Alexandra Nechita AD777x_CHAN_NO_FILTER_S(5), 660*c9a3f8c7SRamona Alexandra Nechita AD777x_CHAN_NO_FILTER_S(6), 661*c9a3f8c7SRamona Alexandra Nechita AD777x_CHAN_NO_FILTER_S(7), 662*c9a3f8c7SRamona Alexandra Nechita IIO_CHAN_SOFT_TIMESTAMP(8), 663*c9a3f8c7SRamona Alexandra Nechita }; 664*c9a3f8c7SRamona Alexandra Nechita 665*c9a3f8c7SRamona Alexandra Nechita static const struct iio_chan_spec ad7779_channels_filter[] = { 666*c9a3f8c7SRamona Alexandra Nechita AD777x_CHAN_FILTER_S(0), 667*c9a3f8c7SRamona Alexandra Nechita AD777x_CHAN_FILTER_S(1), 668*c9a3f8c7SRamona Alexandra Nechita AD777x_CHAN_FILTER_S(2), 669*c9a3f8c7SRamona Alexandra Nechita AD777x_CHAN_FILTER_S(3), 670*c9a3f8c7SRamona Alexandra Nechita AD777x_CHAN_FILTER_S(4), 671*c9a3f8c7SRamona Alexandra Nechita AD777x_CHAN_FILTER_S(5), 672*c9a3f8c7SRamona Alexandra Nechita AD777x_CHAN_FILTER_S(6), 673*c9a3f8c7SRamona Alexandra Nechita AD777x_CHAN_FILTER_S(7), 674*c9a3f8c7SRamona Alexandra Nechita IIO_CHAN_SOFT_TIMESTAMP(8), 675*c9a3f8c7SRamona Alexandra Nechita }; 676*c9a3f8c7SRamona Alexandra Nechita 677*c9a3f8c7SRamona Alexandra Nechita static const struct iio_buffer_setup_ops ad7779_buffer_setup_ops = { 678*c9a3f8c7SRamona Alexandra Nechita .preenable = ad7779_buffer_preenable, 679*c9a3f8c7SRamona Alexandra Nechita .postdisable = ad7779_buffer_postdisable, 680*c9a3f8c7SRamona Alexandra Nechita }; 681*c9a3f8c7SRamona Alexandra Nechita 682*c9a3f8c7SRamona Alexandra Nechita static const struct iio_trigger_ops ad7779_trigger_ops = { 683*c9a3f8c7SRamona Alexandra Nechita .validate_device = iio_trigger_validate_own_device, 684*c9a3f8c7SRamona Alexandra Nechita }; 685*c9a3f8c7SRamona Alexandra Nechita 686*c9a3f8c7SRamona Alexandra Nechita static int ad7779_conf(struct ad7779_state *st, struct gpio_desc *start_gpio) 687*c9a3f8c7SRamona Alexandra Nechita { 688*c9a3f8c7SRamona Alexandra Nechita int ret; 689*c9a3f8c7SRamona Alexandra Nechita 690*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_spi_write_mask(st, AD7779_REG_GEN_ERR_REG_1_EN, 691*c9a3f8c7SRamona Alexandra Nechita AD7779_SPI_CRC_EN_MSK, 692*c9a3f8c7SRamona Alexandra Nechita FIELD_PREP(AD7779_SPI_CRC_EN_MSK, 1)); 693*c9a3f8c7SRamona Alexandra Nechita if (ret) 694*c9a3f8c7SRamona Alexandra Nechita return ret; 695*c9a3f8c7SRamona Alexandra Nechita 696*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_spi_write_mask(st, AD7779_REG_GENERAL_USER_CONFIG_1, 697*c9a3f8c7SRamona Alexandra Nechita AD7779_USRMOD_INIT_MSK, 698*c9a3f8c7SRamona Alexandra Nechita FIELD_PREP(AD7779_USRMOD_INIT_MSK, 5)); 699*c9a3f8c7SRamona Alexandra Nechita if (ret) 700*c9a3f8c7SRamona Alexandra Nechita return ret; 701*c9a3f8c7SRamona Alexandra Nechita 702*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_spi_write_mask(st, AD7779_REG_DOUT_FORMAT, 703*c9a3f8c7SRamona Alexandra Nechita AD7779_DCLK_CLK_DIV_MSK, 704*c9a3f8c7SRamona Alexandra Nechita FIELD_PREP(AD7779_DCLK_CLK_DIV_MSK, 1)); 705*c9a3f8c7SRamona Alexandra Nechita if (ret) 706*c9a3f8c7SRamona Alexandra Nechita return ret; 707*c9a3f8c7SRamona Alexandra Nechita 708*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_spi_write_mask(st, AD7779_REG_ADC_MUX_CONFIG, 709*c9a3f8c7SRamona Alexandra Nechita AD7779_REFMUX_CTRL_MSK, 710*c9a3f8c7SRamona Alexandra Nechita FIELD_PREP(AD7779_REFMUX_CTRL_MSK, 1)); 711*c9a3f8c7SRamona Alexandra Nechita if (ret) 712*c9a3f8c7SRamona Alexandra Nechita return ret; 713*c9a3f8c7SRamona Alexandra Nechita 714*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_set_sampling_frequency(st, AD7779_DEFAULT_SAMPLING_FREQ); 715*c9a3f8c7SRamona Alexandra Nechita if (ret) 716*c9a3f8c7SRamona Alexandra Nechita return ret; 717*c9a3f8c7SRamona Alexandra Nechita 718*c9a3f8c7SRamona Alexandra Nechita gpiod_set_value(start_gpio, 0); 719*c9a3f8c7SRamona Alexandra Nechita /* Start setup time */ 720*c9a3f8c7SRamona Alexandra Nechita fsleep(15); 721*c9a3f8c7SRamona Alexandra Nechita gpiod_set_value(start_gpio, 1); 722*c9a3f8c7SRamona Alexandra Nechita /* Start setup time */ 723*c9a3f8c7SRamona Alexandra Nechita fsleep(15); 724*c9a3f8c7SRamona Alexandra Nechita gpiod_set_value(start_gpio, 0); 725*c9a3f8c7SRamona Alexandra Nechita /* Start setup time */ 726*c9a3f8c7SRamona Alexandra Nechita fsleep(15); 727*c9a3f8c7SRamona Alexandra Nechita 728*c9a3f8c7SRamona Alexandra Nechita return 0; 729*c9a3f8c7SRamona Alexandra Nechita } 730*c9a3f8c7SRamona Alexandra Nechita 731*c9a3f8c7SRamona Alexandra Nechita static int ad7779_probe(struct spi_device *spi) 732*c9a3f8c7SRamona Alexandra Nechita { 733*c9a3f8c7SRamona Alexandra Nechita struct iio_dev *indio_dev; 734*c9a3f8c7SRamona Alexandra Nechita struct ad7779_state *st; 735*c9a3f8c7SRamona Alexandra Nechita struct gpio_desc *reset_gpio, *start_gpio; 736*c9a3f8c7SRamona Alexandra Nechita struct device *dev = &spi->dev; 737*c9a3f8c7SRamona Alexandra Nechita int ret = -EINVAL; 738*c9a3f8c7SRamona Alexandra Nechita 739*c9a3f8c7SRamona Alexandra Nechita if (!spi->irq) 740*c9a3f8c7SRamona Alexandra Nechita return dev_err_probe(dev, ret, "DRDY irq not present\n"); 741*c9a3f8c7SRamona Alexandra Nechita 742*c9a3f8c7SRamona Alexandra Nechita indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); 743*c9a3f8c7SRamona Alexandra Nechita if (!indio_dev) 744*c9a3f8c7SRamona Alexandra Nechita return -ENOMEM; 745*c9a3f8c7SRamona Alexandra Nechita 746*c9a3f8c7SRamona Alexandra Nechita st = iio_priv(indio_dev); 747*c9a3f8c7SRamona Alexandra Nechita 748*c9a3f8c7SRamona Alexandra Nechita ret = devm_regulator_bulk_get_enable(dev, 749*c9a3f8c7SRamona Alexandra Nechita ARRAY_SIZE(ad7779_power_supplies), 750*c9a3f8c7SRamona Alexandra Nechita ad7779_power_supplies); 751*c9a3f8c7SRamona Alexandra Nechita if (ret) 752*c9a3f8c7SRamona Alexandra Nechita return dev_err_probe(dev, ret, 753*c9a3f8c7SRamona Alexandra Nechita "failed to get and enable supplies\n"); 754*c9a3f8c7SRamona Alexandra Nechita 755*c9a3f8c7SRamona Alexandra Nechita st->mclk = devm_clk_get_enabled(dev, "mclk"); 756*c9a3f8c7SRamona Alexandra Nechita if (IS_ERR(st->mclk)) 757*c9a3f8c7SRamona Alexandra Nechita return PTR_ERR(st->mclk); 758*c9a3f8c7SRamona Alexandra Nechita 759*c9a3f8c7SRamona Alexandra Nechita reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); 760*c9a3f8c7SRamona Alexandra Nechita if (IS_ERR(reset_gpio)) 761*c9a3f8c7SRamona Alexandra Nechita return PTR_ERR(reset_gpio); 762*c9a3f8c7SRamona Alexandra Nechita 763*c9a3f8c7SRamona Alexandra Nechita start_gpio = devm_gpiod_get(dev, "start", GPIOD_OUT_HIGH); 764*c9a3f8c7SRamona Alexandra Nechita if (IS_ERR(start_gpio)) 765*c9a3f8c7SRamona Alexandra Nechita return PTR_ERR(start_gpio); 766*c9a3f8c7SRamona Alexandra Nechita 767*c9a3f8c7SRamona Alexandra Nechita crc8_populate_msb(ad7779_crc8_table, AD7779_CRC8_POLY); 768*c9a3f8c7SRamona Alexandra Nechita st->spi = spi; 769*c9a3f8c7SRamona Alexandra Nechita 770*c9a3f8c7SRamona Alexandra Nechita st->chip_info = spi_get_device_match_data(spi); 771*c9a3f8c7SRamona Alexandra Nechita if (!st->chip_info) 772*c9a3f8c7SRamona Alexandra Nechita return -ENODEV; 773*c9a3f8c7SRamona Alexandra Nechita 774*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_reset(indio_dev, reset_gpio); 775*c9a3f8c7SRamona Alexandra Nechita if (ret) 776*c9a3f8c7SRamona Alexandra Nechita return ret; 777*c9a3f8c7SRamona Alexandra Nechita 778*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_conf(st, start_gpio); 779*c9a3f8c7SRamona Alexandra Nechita if (ret) 780*c9a3f8c7SRamona Alexandra Nechita return ret; 781*c9a3f8c7SRamona Alexandra Nechita 782*c9a3f8c7SRamona Alexandra Nechita indio_dev->name = st->chip_info->name; 783*c9a3f8c7SRamona Alexandra Nechita indio_dev->info = &ad7779_info; 784*c9a3f8c7SRamona Alexandra Nechita indio_dev->modes = INDIO_DIRECT_MODE; 785*c9a3f8c7SRamona Alexandra Nechita indio_dev->channels = st->chip_info->channels; 786*c9a3f8c7SRamona Alexandra Nechita indio_dev->num_channels = ARRAY_SIZE(ad7779_channels); 787*c9a3f8c7SRamona Alexandra Nechita 788*c9a3f8c7SRamona Alexandra Nechita st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, 789*c9a3f8c7SRamona Alexandra Nechita iio_device_id(indio_dev)); 790*c9a3f8c7SRamona Alexandra Nechita if (!st->trig) 791*c9a3f8c7SRamona Alexandra Nechita return -ENOMEM; 792*c9a3f8c7SRamona Alexandra Nechita 793*c9a3f8c7SRamona Alexandra Nechita st->trig->ops = &ad7779_trigger_ops; 794*c9a3f8c7SRamona Alexandra Nechita 795*c9a3f8c7SRamona Alexandra Nechita iio_trigger_set_drvdata(st->trig, st); 796*c9a3f8c7SRamona Alexandra Nechita 797*c9a3f8c7SRamona Alexandra Nechita ret = devm_request_irq(dev, spi->irq, iio_trigger_generic_data_rdy_poll, 798*c9a3f8c7SRamona Alexandra Nechita IRQF_ONESHOT | IRQF_NO_AUTOEN, indio_dev->name, 799*c9a3f8c7SRamona Alexandra Nechita st->trig); 800*c9a3f8c7SRamona Alexandra Nechita if (ret) 801*c9a3f8c7SRamona Alexandra Nechita return dev_err_probe(dev, ret, "request IRQ %d failed\n", 802*c9a3f8c7SRamona Alexandra Nechita st->spi->irq); 803*c9a3f8c7SRamona Alexandra Nechita 804*c9a3f8c7SRamona Alexandra Nechita ret = devm_iio_trigger_register(dev, st->trig); 805*c9a3f8c7SRamona Alexandra Nechita if (ret) 806*c9a3f8c7SRamona Alexandra Nechita return ret; 807*c9a3f8c7SRamona Alexandra Nechita 808*c9a3f8c7SRamona Alexandra Nechita indio_dev->trig = iio_trigger_get(st->trig); 809*c9a3f8c7SRamona Alexandra Nechita 810*c9a3f8c7SRamona Alexandra Nechita init_completion(&st->completion); 811*c9a3f8c7SRamona Alexandra Nechita 812*c9a3f8c7SRamona Alexandra Nechita ret = devm_iio_triggered_buffer_setup(dev, indio_dev, 813*c9a3f8c7SRamona Alexandra Nechita &iio_pollfunc_store_time, 814*c9a3f8c7SRamona Alexandra Nechita &ad7779_trigger_handler, 815*c9a3f8c7SRamona Alexandra Nechita &ad7779_buffer_setup_ops); 816*c9a3f8c7SRamona Alexandra Nechita if (ret) 817*c9a3f8c7SRamona Alexandra Nechita return ret; 818*c9a3f8c7SRamona Alexandra Nechita 819*c9a3f8c7SRamona Alexandra Nechita ret = ad7779_spi_write_mask(st, AD7779_REG_DOUT_FORMAT, 820*c9a3f8c7SRamona Alexandra Nechita AD7779_DCLK_CLK_DIV_MSK, 821*c9a3f8c7SRamona Alexandra Nechita FIELD_PREP(AD7779_DCLK_CLK_DIV_MSK, 7)); 822*c9a3f8c7SRamona Alexandra Nechita if (ret) 823*c9a3f8c7SRamona Alexandra Nechita return ret; 824*c9a3f8c7SRamona Alexandra Nechita 825*c9a3f8c7SRamona Alexandra Nechita return devm_iio_device_register(dev, indio_dev); 826*c9a3f8c7SRamona Alexandra Nechita } 827*c9a3f8c7SRamona Alexandra Nechita 828*c9a3f8c7SRamona Alexandra Nechita static int ad7779_suspend(struct device *dev) 829*c9a3f8c7SRamona Alexandra Nechita { 830*c9a3f8c7SRamona Alexandra Nechita struct iio_dev *indio_dev = dev_get_drvdata(dev); 831*c9a3f8c7SRamona Alexandra Nechita struct ad7779_state *st = iio_priv(indio_dev); 832*c9a3f8c7SRamona Alexandra Nechita 833*c9a3f8c7SRamona Alexandra Nechita return ad7779_spi_write_mask(st, AD7779_REG_GENERAL_USER_CONFIG_1, 834*c9a3f8c7SRamona Alexandra Nechita AD7779_MOD_POWERMODE_MSK, 835*c9a3f8c7SRamona Alexandra Nechita FIELD_PREP(AD7779_MOD_POWERMODE_MSK, 836*c9a3f8c7SRamona Alexandra Nechita AD7779_LOW_POWER)); 837*c9a3f8c7SRamona Alexandra Nechita } 838*c9a3f8c7SRamona Alexandra Nechita 839*c9a3f8c7SRamona Alexandra Nechita static int ad7779_resume(struct device *dev) 840*c9a3f8c7SRamona Alexandra Nechita { 841*c9a3f8c7SRamona Alexandra Nechita struct iio_dev *indio_dev = dev_get_drvdata(dev); 842*c9a3f8c7SRamona Alexandra Nechita struct ad7779_state *st = iio_priv(indio_dev); 843*c9a3f8c7SRamona Alexandra Nechita 844*c9a3f8c7SRamona Alexandra Nechita return ad7779_spi_write_mask(st, AD7779_REG_GENERAL_USER_CONFIG_1, 845*c9a3f8c7SRamona Alexandra Nechita AD7779_MOD_POWERMODE_MSK, 846*c9a3f8c7SRamona Alexandra Nechita FIELD_PREP(AD7779_MOD_POWERMODE_MSK, 847*c9a3f8c7SRamona Alexandra Nechita AD7779_HIGH_POWER)); 848*c9a3f8c7SRamona Alexandra Nechita } 849*c9a3f8c7SRamona Alexandra Nechita 850*c9a3f8c7SRamona Alexandra Nechita static DEFINE_SIMPLE_DEV_PM_OPS(ad7779_pm_ops, ad7779_suspend, ad7779_resume); 851*c9a3f8c7SRamona Alexandra Nechita 852*c9a3f8c7SRamona Alexandra Nechita static const struct ad7779_chip_info ad7770_chip_info = { 853*c9a3f8c7SRamona Alexandra Nechita .name = "ad7770", 854*c9a3f8c7SRamona Alexandra Nechita .channels = ad7779_channels, 855*c9a3f8c7SRamona Alexandra Nechita }; 856*c9a3f8c7SRamona Alexandra Nechita 857*c9a3f8c7SRamona Alexandra Nechita static const struct ad7779_chip_info ad7771_chip_info = { 858*c9a3f8c7SRamona Alexandra Nechita .name = "ad7771", 859*c9a3f8c7SRamona Alexandra Nechita .channels = ad7779_channels_filter, 860*c9a3f8c7SRamona Alexandra Nechita }; 861*c9a3f8c7SRamona Alexandra Nechita 862*c9a3f8c7SRamona Alexandra Nechita static const struct ad7779_chip_info ad7779_chip_info = { 863*c9a3f8c7SRamona Alexandra Nechita .name = "ad7779", 864*c9a3f8c7SRamona Alexandra Nechita .channels = ad7779_channels, 865*c9a3f8c7SRamona Alexandra Nechita }; 866*c9a3f8c7SRamona Alexandra Nechita 867*c9a3f8c7SRamona Alexandra Nechita static const struct spi_device_id ad7779_id[] = { 868*c9a3f8c7SRamona Alexandra Nechita { 869*c9a3f8c7SRamona Alexandra Nechita .name = "ad7770", 870*c9a3f8c7SRamona Alexandra Nechita .driver_data = (kernel_ulong_t)&ad7770_chip_info, 871*c9a3f8c7SRamona Alexandra Nechita }, 872*c9a3f8c7SRamona Alexandra Nechita { 873*c9a3f8c7SRamona Alexandra Nechita .name = "ad7771", 874*c9a3f8c7SRamona Alexandra Nechita .driver_data = (kernel_ulong_t)&ad7771_chip_info, 875*c9a3f8c7SRamona Alexandra Nechita }, 876*c9a3f8c7SRamona Alexandra Nechita { 877*c9a3f8c7SRamona Alexandra Nechita .name = "ad7779", 878*c9a3f8c7SRamona Alexandra Nechita .driver_data = (kernel_ulong_t)&ad7779_chip_info, 879*c9a3f8c7SRamona Alexandra Nechita }, 880*c9a3f8c7SRamona Alexandra Nechita { } 881*c9a3f8c7SRamona Alexandra Nechita }; 882*c9a3f8c7SRamona Alexandra Nechita MODULE_DEVICE_TABLE(spi, ad7779_id); 883*c9a3f8c7SRamona Alexandra Nechita 884*c9a3f8c7SRamona Alexandra Nechita static const struct of_device_id ad7779_of_table[] = { 885*c9a3f8c7SRamona Alexandra Nechita { 886*c9a3f8c7SRamona Alexandra Nechita .compatible = "adi,ad7770", 887*c9a3f8c7SRamona Alexandra Nechita .data = &ad7770_chip_info, 888*c9a3f8c7SRamona Alexandra Nechita }, 889*c9a3f8c7SRamona Alexandra Nechita { 890*c9a3f8c7SRamona Alexandra Nechita .compatible = "adi,ad7771", 891*c9a3f8c7SRamona Alexandra Nechita .data = &ad7771_chip_info, 892*c9a3f8c7SRamona Alexandra Nechita }, 893*c9a3f8c7SRamona Alexandra Nechita { 894*c9a3f8c7SRamona Alexandra Nechita .compatible = "adi,ad7779", 895*c9a3f8c7SRamona Alexandra Nechita .data = &ad7779_chip_info, 896*c9a3f8c7SRamona Alexandra Nechita }, 897*c9a3f8c7SRamona Alexandra Nechita { } 898*c9a3f8c7SRamona Alexandra Nechita }; 899*c9a3f8c7SRamona Alexandra Nechita MODULE_DEVICE_TABLE(of, ad7779_of_table); 900*c9a3f8c7SRamona Alexandra Nechita 901*c9a3f8c7SRamona Alexandra Nechita static struct spi_driver ad7779_driver = { 902*c9a3f8c7SRamona Alexandra Nechita .driver = { 903*c9a3f8c7SRamona Alexandra Nechita .name = "ad7779", 904*c9a3f8c7SRamona Alexandra Nechita .pm = pm_sleep_ptr(&ad7779_pm_ops), 905*c9a3f8c7SRamona Alexandra Nechita .of_match_table = ad7779_of_table, 906*c9a3f8c7SRamona Alexandra Nechita }, 907*c9a3f8c7SRamona Alexandra Nechita .probe = ad7779_probe, 908*c9a3f8c7SRamona Alexandra Nechita .id_table = ad7779_id, 909*c9a3f8c7SRamona Alexandra Nechita }; 910*c9a3f8c7SRamona Alexandra Nechita module_spi_driver(ad7779_driver); 911*c9a3f8c7SRamona Alexandra Nechita 912*c9a3f8c7SRamona Alexandra Nechita MODULE_AUTHOR("Ramona Alexandra Nechita <ramona.nechita@analog.com>"); 913*c9a3f8c7SRamona Alexandra Nechita MODULE_DESCRIPTION("Analog Devices AD7779 ADC"); 914*c9a3f8c7SRamona Alexandra Nechita MODULE_LICENSE("GPL"); 915