162094060SCosmin Tanislav // SPDX-License-Identifier: GPL-2.0+
262094060SCosmin Tanislav /*
362094060SCosmin Tanislav * Copyright (C) 2022 Analog Devices, Inc.
462094060SCosmin Tanislav * Author: Cosmin Tanislav <cosmin.tanislav@analog.com>
562094060SCosmin Tanislav */
662094060SCosmin Tanislav
762094060SCosmin Tanislav #include <linux/bitfield.h>
862094060SCosmin Tanislav #include <linux/bitops.h>
962094060SCosmin Tanislav #include <linux/clk.h>
1062094060SCosmin Tanislav #include <linux/clk-provider.h>
1162094060SCosmin Tanislav #include <linux/delay.h>
1262094060SCosmin Tanislav #include <linux/device.h>
1362094060SCosmin Tanislav #include <linux/err.h>
1462094060SCosmin Tanislav #include <linux/gpio/driver.h>
1562094060SCosmin Tanislav #include <linux/interrupt.h>
1662094060SCosmin Tanislav #include <linux/irq.h>
1762094060SCosmin Tanislav #include <linux/kernel.h>
1862094060SCosmin Tanislav #include <linux/module.h>
1962094060SCosmin Tanislav #include <linux/property.h>
2062094060SCosmin Tanislav #include <linux/regmap.h>
2162094060SCosmin Tanislav #include <linux/regulator/consumer.h>
2262094060SCosmin Tanislav #include <linux/spi/spi.h>
2362094060SCosmin Tanislav #include <linux/units.h>
2462094060SCosmin Tanislav
2562094060SCosmin Tanislav #include <asm/div64.h>
2662094060SCosmin Tanislav #include <asm/unaligned.h>
2762094060SCosmin Tanislav
2862094060SCosmin Tanislav #include <linux/iio/buffer.h>
2962094060SCosmin Tanislav #include <linux/iio/iio.h>
3062094060SCosmin Tanislav #include <linux/iio/kfifo_buf.h>
3162094060SCosmin Tanislav #include <linux/iio/sysfs.h>
3262094060SCosmin Tanislav
3362094060SCosmin Tanislav #define AD4130_NAME "ad4130"
3462094060SCosmin Tanislav
3562094060SCosmin Tanislav #define AD4130_COMMS_READ_MASK BIT(6)
3662094060SCosmin Tanislav
3762094060SCosmin Tanislav #define AD4130_STATUS_REG 0x00
3862094060SCosmin Tanislav
3962094060SCosmin Tanislav #define AD4130_ADC_CONTROL_REG 0x01
4062094060SCosmin Tanislav #define AD4130_ADC_CONTROL_BIPOLAR_MASK BIT(14)
4162094060SCosmin Tanislav #define AD4130_ADC_CONTROL_INT_REF_VAL_MASK BIT(13)
4262094060SCosmin Tanislav #define AD4130_INT_REF_2_5V 2500000
4362094060SCosmin Tanislav #define AD4130_INT_REF_1_25V 1250000
4462094060SCosmin Tanislav #define AD4130_ADC_CONTROL_CSB_EN_MASK BIT(9)
4562094060SCosmin Tanislav #define AD4130_ADC_CONTROL_INT_REF_EN_MASK BIT(8)
4662094060SCosmin Tanislav #define AD4130_ADC_CONTROL_MODE_MASK GENMASK(5, 2)
4762094060SCosmin Tanislav #define AD4130_ADC_CONTROL_MCLK_SEL_MASK GENMASK(1, 0)
4862094060SCosmin Tanislav #define AD4130_MCLK_FREQ_76_8KHZ 76800
4962094060SCosmin Tanislav #define AD4130_MCLK_FREQ_153_6KHZ 153600
5062094060SCosmin Tanislav
5162094060SCosmin Tanislav #define AD4130_DATA_REG 0x02
5262094060SCosmin Tanislav
5362094060SCosmin Tanislav #define AD4130_IO_CONTROL_REG 0x03
5462094060SCosmin Tanislav #define AD4130_IO_CONTROL_INT_PIN_SEL_MASK GENMASK(9, 8)
5562094060SCosmin Tanislav #define AD4130_IO_CONTROL_GPIO_DATA_MASK GENMASK(7, 4)
5662094060SCosmin Tanislav #define AD4130_IO_CONTROL_GPIO_CTRL_MASK GENMASK(3, 0)
5762094060SCosmin Tanislav
5862094060SCosmin Tanislav #define AD4130_VBIAS_REG 0x04
5962094060SCosmin Tanislav
6062094060SCosmin Tanislav #define AD4130_ID_REG 0x05
6162094060SCosmin Tanislav
6262094060SCosmin Tanislav #define AD4130_ERROR_REG 0x06
6362094060SCosmin Tanislav
6462094060SCosmin Tanislav #define AD4130_ERROR_EN_REG 0x07
6562094060SCosmin Tanislav
6662094060SCosmin Tanislav #define AD4130_MCLK_COUNT_REG 0x08
6762094060SCosmin Tanislav
6862094060SCosmin Tanislav #define AD4130_CHANNEL_X_REG(x) (0x09 + (x))
6962094060SCosmin Tanislav #define AD4130_CHANNEL_EN_MASK BIT(23)
7062094060SCosmin Tanislav #define AD4130_CHANNEL_SETUP_MASK GENMASK(22, 20)
7162094060SCosmin Tanislav #define AD4130_CHANNEL_AINP_MASK GENMASK(17, 13)
7262094060SCosmin Tanislav #define AD4130_CHANNEL_AINM_MASK GENMASK(12, 8)
7362094060SCosmin Tanislav #define AD4130_CHANNEL_IOUT1_MASK GENMASK(7, 4)
7462094060SCosmin Tanislav #define AD4130_CHANNEL_IOUT2_MASK GENMASK(3, 0)
7562094060SCosmin Tanislav
7662094060SCosmin Tanislav #define AD4130_CONFIG_X_REG(x) (0x19 + (x))
7762094060SCosmin Tanislav #define AD4130_CONFIG_IOUT1_VAL_MASK GENMASK(15, 13)
7862094060SCosmin Tanislav #define AD4130_CONFIG_IOUT2_VAL_MASK GENMASK(12, 10)
7962094060SCosmin Tanislav #define AD4130_CONFIG_BURNOUT_MASK GENMASK(9, 8)
8062094060SCosmin Tanislav #define AD4130_CONFIG_REF_BUFP_MASK BIT(7)
8162094060SCosmin Tanislav #define AD4130_CONFIG_REF_BUFM_MASK BIT(6)
8262094060SCosmin Tanislav #define AD4130_CONFIG_REF_SEL_MASK GENMASK(5, 4)
8362094060SCosmin Tanislav #define AD4130_CONFIG_PGA_MASK GENMASK(3, 1)
8462094060SCosmin Tanislav
8562094060SCosmin Tanislav #define AD4130_FILTER_X_REG(x) (0x21 + (x))
8662094060SCosmin Tanislav #define AD4130_FILTER_MODE_MASK GENMASK(15, 12)
8762094060SCosmin Tanislav #define AD4130_FILTER_SELECT_MASK GENMASK(10, 0)
8862094060SCosmin Tanislav #define AD4130_FILTER_SELECT_MIN 1
8962094060SCosmin Tanislav
9062094060SCosmin Tanislav #define AD4130_OFFSET_X_REG(x) (0x29 + (x))
9162094060SCosmin Tanislav
9262094060SCosmin Tanislav #define AD4130_GAIN_X_REG(x) (0x31 + (x))
9362094060SCosmin Tanislav
9462094060SCosmin Tanislav #define AD4130_MISC_REG 0x39
9562094060SCosmin Tanislav
9662094060SCosmin Tanislav #define AD4130_FIFO_CONTROL_REG 0x3a
9762094060SCosmin Tanislav #define AD4130_FIFO_CONTROL_HEADER_MASK BIT(18)
9862094060SCosmin Tanislav #define AD4130_FIFO_CONTROL_MODE_MASK GENMASK(17, 16)
9962094060SCosmin Tanislav #define AD4130_FIFO_CONTROL_WM_INT_EN_MASK BIT(9)
10062094060SCosmin Tanislav #define AD4130_FIFO_CONTROL_WM_MASK GENMASK(7, 0)
10162094060SCosmin Tanislav #define AD4130_WATERMARK_256 0
10262094060SCosmin Tanislav
10362094060SCosmin Tanislav #define AD4130_FIFO_STATUS_REG 0x3b
10462094060SCosmin Tanislav
10562094060SCosmin Tanislav #define AD4130_FIFO_THRESHOLD_REG 0x3c
10662094060SCosmin Tanislav
10762094060SCosmin Tanislav #define AD4130_FIFO_DATA_REG 0x3d
10862094060SCosmin Tanislav #define AD4130_FIFO_SIZE 256
10962094060SCosmin Tanislav #define AD4130_FIFO_MAX_SAMPLE_SIZE 3
11062094060SCosmin Tanislav
11162094060SCosmin Tanislav #define AD4130_MAX_ANALOG_PINS 16
11262094060SCosmin Tanislav #define AD4130_MAX_CHANNELS 16
11362094060SCosmin Tanislav #define AD4130_MAX_DIFF_INPUTS 30
11462094060SCosmin Tanislav #define AD4130_MAX_GPIOS 4
11562094060SCosmin Tanislav #define AD4130_MAX_ODR 2400
11662094060SCosmin Tanislav #define AD4130_MAX_PGA 8
11762094060SCosmin Tanislav #define AD4130_MAX_SETUPS 8
11862094060SCosmin Tanislav
11962094060SCosmin Tanislav #define AD4130_AIN2_P1 0x2
12062094060SCosmin Tanislav #define AD4130_AIN3_P2 0x3
12162094060SCosmin Tanislav
12262094060SCosmin Tanislav #define AD4130_RESET_BUF_SIZE 8
12362094060SCosmin Tanislav #define AD4130_RESET_SLEEP_US (160 * MICRO / AD4130_MCLK_FREQ_76_8KHZ)
12462094060SCosmin Tanislav
12562094060SCosmin Tanislav #define AD4130_INVALID_SLOT -1
12662094060SCosmin Tanislav
12762094060SCosmin Tanislav static const unsigned int ad4130_reg_size[] = {
12862094060SCosmin Tanislav [AD4130_STATUS_REG] = 1,
12962094060SCosmin Tanislav [AD4130_ADC_CONTROL_REG] = 2,
13062094060SCosmin Tanislav [AD4130_DATA_REG] = 3,
13162094060SCosmin Tanislav [AD4130_IO_CONTROL_REG] = 2,
13262094060SCosmin Tanislav [AD4130_VBIAS_REG] = 2,
13362094060SCosmin Tanislav [AD4130_ID_REG] = 1,
13462094060SCosmin Tanislav [AD4130_ERROR_REG] = 2,
13562094060SCosmin Tanislav [AD4130_ERROR_EN_REG] = 2,
13662094060SCosmin Tanislav [AD4130_MCLK_COUNT_REG] = 1,
13762094060SCosmin Tanislav [AD4130_CHANNEL_X_REG(0) ... AD4130_CHANNEL_X_REG(AD4130_MAX_CHANNELS - 1)] = 3,
13862094060SCosmin Tanislav [AD4130_CONFIG_X_REG(0) ... AD4130_CONFIG_X_REG(AD4130_MAX_SETUPS - 1)] = 2,
13962094060SCosmin Tanislav [AD4130_FILTER_X_REG(0) ... AD4130_FILTER_X_REG(AD4130_MAX_SETUPS - 1)] = 3,
14062094060SCosmin Tanislav [AD4130_OFFSET_X_REG(0) ... AD4130_OFFSET_X_REG(AD4130_MAX_SETUPS - 1)] = 3,
14162094060SCosmin Tanislav [AD4130_GAIN_X_REG(0) ... AD4130_GAIN_X_REG(AD4130_MAX_SETUPS - 1)] = 3,
14262094060SCosmin Tanislav [AD4130_MISC_REG] = 2,
14362094060SCosmin Tanislav [AD4130_FIFO_CONTROL_REG] = 3,
14462094060SCosmin Tanislav [AD4130_FIFO_STATUS_REG] = 1,
14562094060SCosmin Tanislav [AD4130_FIFO_THRESHOLD_REG] = 3,
14662094060SCosmin Tanislav [AD4130_FIFO_DATA_REG] = 3,
14762094060SCosmin Tanislav };
14862094060SCosmin Tanislav
14962094060SCosmin Tanislav enum ad4130_int_ref_val {
15062094060SCosmin Tanislav AD4130_INT_REF_VAL_2_5V,
15162094060SCosmin Tanislav AD4130_INT_REF_VAL_1_25V,
15262094060SCosmin Tanislav };
15362094060SCosmin Tanislav
15462094060SCosmin Tanislav enum ad4130_mclk_sel {
15562094060SCosmin Tanislav AD4130_MCLK_76_8KHZ,
15662094060SCosmin Tanislav AD4130_MCLK_76_8KHZ_OUT,
15762094060SCosmin Tanislav AD4130_MCLK_76_8KHZ_EXT,
15862094060SCosmin Tanislav AD4130_MCLK_153_6KHZ_EXT,
15962094060SCosmin Tanislav };
16062094060SCosmin Tanislav
16162094060SCosmin Tanislav enum ad4130_int_pin_sel {
16262094060SCosmin Tanislav AD4130_INT_PIN_INT,
16362094060SCosmin Tanislav AD4130_INT_PIN_CLK,
16462094060SCosmin Tanislav AD4130_INT_PIN_P2,
16562094060SCosmin Tanislav AD4130_INT_PIN_DOUT,
16662094060SCosmin Tanislav };
16762094060SCosmin Tanislav
16862094060SCosmin Tanislav enum ad4130_iout {
16962094060SCosmin Tanislav AD4130_IOUT_OFF,
17062094060SCosmin Tanislav AD4130_IOUT_10000NA,
17162094060SCosmin Tanislav AD4130_IOUT_20000NA,
17262094060SCosmin Tanislav AD4130_IOUT_50000NA,
17362094060SCosmin Tanislav AD4130_IOUT_100000NA,
17462094060SCosmin Tanislav AD4130_IOUT_150000NA,
17562094060SCosmin Tanislav AD4130_IOUT_200000NA,
17662094060SCosmin Tanislav AD4130_IOUT_100NA,
17762094060SCosmin Tanislav AD4130_IOUT_MAX
17862094060SCosmin Tanislav };
17962094060SCosmin Tanislav
18062094060SCosmin Tanislav enum ad4130_burnout {
18162094060SCosmin Tanislav AD4130_BURNOUT_OFF,
18262094060SCosmin Tanislav AD4130_BURNOUT_500NA,
18362094060SCosmin Tanislav AD4130_BURNOUT_2000NA,
18462094060SCosmin Tanislav AD4130_BURNOUT_4000NA,
18562094060SCosmin Tanislav AD4130_BURNOUT_MAX
18662094060SCosmin Tanislav };
18762094060SCosmin Tanislav
18862094060SCosmin Tanislav enum ad4130_ref_sel {
18962094060SCosmin Tanislav AD4130_REF_REFIN1,
19062094060SCosmin Tanislav AD4130_REF_REFIN2,
19162094060SCosmin Tanislav AD4130_REF_REFOUT_AVSS,
19262094060SCosmin Tanislav AD4130_REF_AVDD_AVSS,
19362094060SCosmin Tanislav AD4130_REF_SEL_MAX
19462094060SCosmin Tanislav };
19562094060SCosmin Tanislav
19662094060SCosmin Tanislav enum ad4130_fifo_mode {
19762094060SCosmin Tanislav AD4130_FIFO_MODE_DISABLED = 0b00,
19862094060SCosmin Tanislav AD4130_FIFO_MODE_WM = 0b01,
19962094060SCosmin Tanislav };
20062094060SCosmin Tanislav
20162094060SCosmin Tanislav enum ad4130_mode {
20262094060SCosmin Tanislav AD4130_MODE_CONTINUOUS = 0b0000,
20362094060SCosmin Tanislav AD4130_MODE_IDLE = 0b0100,
20462094060SCosmin Tanislav };
20562094060SCosmin Tanislav
20662094060SCosmin Tanislav enum ad4130_filter_mode {
20762094060SCosmin Tanislav AD4130_FILTER_SINC4,
20862094060SCosmin Tanislav AD4130_FILTER_SINC4_SINC1,
20962094060SCosmin Tanislav AD4130_FILTER_SINC3,
21062094060SCosmin Tanislav AD4130_FILTER_SINC3_REJ60,
21162094060SCosmin Tanislav AD4130_FILTER_SINC3_SINC1,
21262094060SCosmin Tanislav AD4130_FILTER_SINC3_PF1,
21362094060SCosmin Tanislav AD4130_FILTER_SINC3_PF2,
21462094060SCosmin Tanislav AD4130_FILTER_SINC3_PF3,
21562094060SCosmin Tanislav AD4130_FILTER_SINC3_PF4,
21662094060SCosmin Tanislav };
21762094060SCosmin Tanislav
21862094060SCosmin Tanislav enum ad4130_pin_function {
21962094060SCosmin Tanislav AD4130_PIN_FN_NONE,
22062094060SCosmin Tanislav AD4130_PIN_FN_SPECIAL = BIT(0),
22162094060SCosmin Tanislav AD4130_PIN_FN_DIFF = BIT(1),
22262094060SCosmin Tanislav AD4130_PIN_FN_EXCITATION = BIT(2),
22362094060SCosmin Tanislav AD4130_PIN_FN_VBIAS = BIT(3),
22462094060SCosmin Tanislav };
22562094060SCosmin Tanislav
22662094060SCosmin Tanislav struct ad4130_setup_info {
22762094060SCosmin Tanislav unsigned int iout0_val;
22862094060SCosmin Tanislav unsigned int iout1_val;
22962094060SCosmin Tanislav unsigned int burnout;
23062094060SCosmin Tanislav unsigned int pga;
23162094060SCosmin Tanislav unsigned int fs;
23262094060SCosmin Tanislav u32 ref_sel;
23362094060SCosmin Tanislav enum ad4130_filter_mode filter_mode;
23462094060SCosmin Tanislav bool ref_bufp;
23562094060SCosmin Tanislav bool ref_bufm;
23662094060SCosmin Tanislav };
23762094060SCosmin Tanislav
23862094060SCosmin Tanislav struct ad4130_slot_info {
23962094060SCosmin Tanislav struct ad4130_setup_info setup;
24062094060SCosmin Tanislav unsigned int enabled_channels;
24162094060SCosmin Tanislav unsigned int channels;
24262094060SCosmin Tanislav };
24362094060SCosmin Tanislav
24462094060SCosmin Tanislav struct ad4130_chan_info {
24562094060SCosmin Tanislav struct ad4130_setup_info setup;
24662094060SCosmin Tanislav u32 iout0;
24762094060SCosmin Tanislav u32 iout1;
24862094060SCosmin Tanislav int slot;
24962094060SCosmin Tanislav bool enabled;
25062094060SCosmin Tanislav bool initialized;
25162094060SCosmin Tanislav };
25262094060SCosmin Tanislav
25362094060SCosmin Tanislav struct ad4130_filter_config {
25462094060SCosmin Tanislav enum ad4130_filter_mode filter_mode;
25562094060SCosmin Tanislav unsigned int odr_div;
25662094060SCosmin Tanislav unsigned int fs_max;
25762094060SCosmin Tanislav enum iio_available_type samp_freq_avail_type;
25862094060SCosmin Tanislav int samp_freq_avail_len;
25962094060SCosmin Tanislav int samp_freq_avail[3][2];
26062094060SCosmin Tanislav };
26162094060SCosmin Tanislav
26262094060SCosmin Tanislav struct ad4130_state {
26362094060SCosmin Tanislav struct regmap *regmap;
26462094060SCosmin Tanislav struct spi_device *spi;
26562094060SCosmin Tanislav struct clk *mclk;
26662094060SCosmin Tanislav struct regulator_bulk_data regulators[4];
26762094060SCosmin Tanislav u32 irq_trigger;
26862094060SCosmin Tanislav u32 inv_irq_trigger;
26962094060SCosmin Tanislav
27062094060SCosmin Tanislav /*
27162094060SCosmin Tanislav * Synchronize access to members the of driver state, and ensure
27262094060SCosmin Tanislav * atomicity of consecutive regmap operations.
27362094060SCosmin Tanislav */
27462094060SCosmin Tanislav struct mutex lock;
27562094060SCosmin Tanislav struct completion completion;
27662094060SCosmin Tanislav
27762094060SCosmin Tanislav struct iio_chan_spec chans[AD4130_MAX_CHANNELS];
27862094060SCosmin Tanislav struct ad4130_chan_info chans_info[AD4130_MAX_CHANNELS];
27962094060SCosmin Tanislav struct ad4130_slot_info slots_info[AD4130_MAX_SETUPS];
28062094060SCosmin Tanislav enum ad4130_pin_function pins_fn[AD4130_MAX_ANALOG_PINS];
28162094060SCosmin Tanislav u32 vbias_pins[AD4130_MAX_ANALOG_PINS];
28262094060SCosmin Tanislav u32 num_vbias_pins;
28362094060SCosmin Tanislav int scale_tbls[AD4130_REF_SEL_MAX][AD4130_MAX_PGA][2];
28462094060SCosmin Tanislav struct gpio_chip gc;
28562094060SCosmin Tanislav struct clk_hw int_clk_hw;
28662094060SCosmin Tanislav
28762094060SCosmin Tanislav u32 int_pin_sel;
28862094060SCosmin Tanislav u32 int_ref_uv;
28962094060SCosmin Tanislav u32 mclk_sel;
29062094060SCosmin Tanislav bool int_ref_en;
29162094060SCosmin Tanislav bool bipolar;
29262094060SCosmin Tanislav
29362094060SCosmin Tanislav unsigned int num_enabled_channels;
29462094060SCosmin Tanislav unsigned int effective_watermark;
29562094060SCosmin Tanislav unsigned int watermark;
29662094060SCosmin Tanislav
29762094060SCosmin Tanislav struct spi_message fifo_msg;
29862094060SCosmin Tanislav struct spi_transfer fifo_xfer[2];
29962094060SCosmin Tanislav
30062094060SCosmin Tanislav /*
30162094060SCosmin Tanislav * DMA (thus cache coherency maintenance) requires any transfer
30262094060SCosmin Tanislav * buffers to live in their own cache lines. As the use of these
30362094060SCosmin Tanislav * buffers is synchronous, all of the buffers used for DMA in this
30462094060SCosmin Tanislav * driver may share a cache line.
30562094060SCosmin Tanislav */
30662094060SCosmin Tanislav u8 reset_buf[AD4130_RESET_BUF_SIZE] __aligned(IIO_DMA_MINALIGN);
30762094060SCosmin Tanislav u8 reg_write_tx_buf[4];
30862094060SCosmin Tanislav u8 reg_read_tx_buf[1];
30962094060SCosmin Tanislav u8 reg_read_rx_buf[3];
31062094060SCosmin Tanislav u8 fifo_tx_buf[2];
31162094060SCosmin Tanislav u8 fifo_rx_buf[AD4130_FIFO_SIZE *
31262094060SCosmin Tanislav AD4130_FIFO_MAX_SAMPLE_SIZE];
31362094060SCosmin Tanislav };
31462094060SCosmin Tanislav
31562094060SCosmin Tanislav static const char * const ad4130_int_pin_names[] = {
31662094060SCosmin Tanislav [AD4130_INT_PIN_INT] = "int",
31762094060SCosmin Tanislav [AD4130_INT_PIN_CLK] = "clk",
31862094060SCosmin Tanislav [AD4130_INT_PIN_P2] = "p2",
31962094060SCosmin Tanislav [AD4130_INT_PIN_DOUT] = "dout",
32062094060SCosmin Tanislav };
32162094060SCosmin Tanislav
32262094060SCosmin Tanislav static const unsigned int ad4130_iout_current_na_tbl[AD4130_IOUT_MAX] = {
32362094060SCosmin Tanislav [AD4130_IOUT_OFF] = 0,
32462094060SCosmin Tanislav [AD4130_IOUT_100NA] = 100,
32562094060SCosmin Tanislav [AD4130_IOUT_10000NA] = 10000,
32662094060SCosmin Tanislav [AD4130_IOUT_20000NA] = 20000,
32762094060SCosmin Tanislav [AD4130_IOUT_50000NA] = 50000,
32862094060SCosmin Tanislav [AD4130_IOUT_100000NA] = 100000,
32962094060SCosmin Tanislav [AD4130_IOUT_150000NA] = 150000,
33062094060SCosmin Tanislav [AD4130_IOUT_200000NA] = 200000,
33162094060SCosmin Tanislav };
33262094060SCosmin Tanislav
33362094060SCosmin Tanislav static const unsigned int ad4130_burnout_current_na_tbl[AD4130_BURNOUT_MAX] = {
33462094060SCosmin Tanislav [AD4130_BURNOUT_OFF] = 0,
33562094060SCosmin Tanislav [AD4130_BURNOUT_500NA] = 500,
33662094060SCosmin Tanislav [AD4130_BURNOUT_2000NA] = 2000,
33762094060SCosmin Tanislav [AD4130_BURNOUT_4000NA] = 4000,
33862094060SCosmin Tanislav };
33962094060SCosmin Tanislav
34062094060SCosmin Tanislav #define AD4130_VARIABLE_ODR_CONFIG(_filter_mode, _odr_div, _fs_max) \
34162094060SCosmin Tanislav { \
34262094060SCosmin Tanislav .filter_mode = (_filter_mode), \
34362094060SCosmin Tanislav .odr_div = (_odr_div), \
34462094060SCosmin Tanislav .fs_max = (_fs_max), \
34562094060SCosmin Tanislav .samp_freq_avail_type = IIO_AVAIL_RANGE, \
34662094060SCosmin Tanislav .samp_freq_avail = { \
34762094060SCosmin Tanislav { AD4130_MAX_ODR, (_odr_div) * (_fs_max) }, \
34862094060SCosmin Tanislav { AD4130_MAX_ODR, (_odr_div) * (_fs_max) }, \
34962094060SCosmin Tanislav { AD4130_MAX_ODR, (_odr_div) }, \
35062094060SCosmin Tanislav }, \
35162094060SCosmin Tanislav }
35262094060SCosmin Tanislav
35362094060SCosmin Tanislav #define AD4130_FIXED_ODR_CONFIG(_filter_mode, _odr_div) \
35462094060SCosmin Tanislav { \
35562094060SCosmin Tanislav .filter_mode = (_filter_mode), \
35662094060SCosmin Tanislav .odr_div = (_odr_div), \
35762094060SCosmin Tanislav .fs_max = AD4130_FILTER_SELECT_MIN, \
35862094060SCosmin Tanislav .samp_freq_avail_type = IIO_AVAIL_LIST, \
35962094060SCosmin Tanislav .samp_freq_avail_len = 1, \
36062094060SCosmin Tanislav .samp_freq_avail = { \
36162094060SCosmin Tanislav { AD4130_MAX_ODR, (_odr_div) }, \
36262094060SCosmin Tanislav }, \
36362094060SCosmin Tanislav }
36462094060SCosmin Tanislav
36562094060SCosmin Tanislav static const struct ad4130_filter_config ad4130_filter_configs[] = {
36662094060SCosmin Tanislav AD4130_VARIABLE_ODR_CONFIG(AD4130_FILTER_SINC4, 1, 10),
36762094060SCosmin Tanislav AD4130_VARIABLE_ODR_CONFIG(AD4130_FILTER_SINC4_SINC1, 11, 10),
36862094060SCosmin Tanislav AD4130_VARIABLE_ODR_CONFIG(AD4130_FILTER_SINC3, 1, 2047),
36962094060SCosmin Tanislav AD4130_VARIABLE_ODR_CONFIG(AD4130_FILTER_SINC3_REJ60, 1, 2047),
37062094060SCosmin Tanislav AD4130_VARIABLE_ODR_CONFIG(AD4130_FILTER_SINC3_SINC1, 10, 2047),
37162094060SCosmin Tanislav AD4130_FIXED_ODR_CONFIG(AD4130_FILTER_SINC3_PF1, 92),
37262094060SCosmin Tanislav AD4130_FIXED_ODR_CONFIG(AD4130_FILTER_SINC3_PF2, 100),
37362094060SCosmin Tanislav AD4130_FIXED_ODR_CONFIG(AD4130_FILTER_SINC3_PF3, 124),
37462094060SCosmin Tanislav AD4130_FIXED_ODR_CONFIG(AD4130_FILTER_SINC3_PF4, 148),
37562094060SCosmin Tanislav };
37662094060SCosmin Tanislav
37762094060SCosmin Tanislav static const char * const ad4130_filter_modes_str[] = {
37862094060SCosmin Tanislav [AD4130_FILTER_SINC4] = "sinc4",
37962094060SCosmin Tanislav [AD4130_FILTER_SINC4_SINC1] = "sinc4+sinc1",
38062094060SCosmin Tanislav [AD4130_FILTER_SINC3] = "sinc3",
38162094060SCosmin Tanislav [AD4130_FILTER_SINC3_REJ60] = "sinc3+rej60",
38262094060SCosmin Tanislav [AD4130_FILTER_SINC3_SINC1] = "sinc3+sinc1",
38362094060SCosmin Tanislav [AD4130_FILTER_SINC3_PF1] = "sinc3+pf1",
38462094060SCosmin Tanislav [AD4130_FILTER_SINC3_PF2] = "sinc3+pf2",
38562094060SCosmin Tanislav [AD4130_FILTER_SINC3_PF3] = "sinc3+pf3",
38662094060SCosmin Tanislav [AD4130_FILTER_SINC3_PF4] = "sinc3+pf4",
38762094060SCosmin Tanislav };
38862094060SCosmin Tanislav
ad4130_get_reg_size(struct ad4130_state * st,unsigned int reg,unsigned int * size)38962094060SCosmin Tanislav static int ad4130_get_reg_size(struct ad4130_state *st, unsigned int reg,
39062094060SCosmin Tanislav unsigned int *size)
39162094060SCosmin Tanislav {
39262094060SCosmin Tanislav if (reg >= ARRAY_SIZE(ad4130_reg_size))
39362094060SCosmin Tanislav return -EINVAL;
39462094060SCosmin Tanislav
39562094060SCosmin Tanislav *size = ad4130_reg_size[reg];
39662094060SCosmin Tanislav
39762094060SCosmin Tanislav return 0;
39862094060SCosmin Tanislav }
39962094060SCosmin Tanislav
ad4130_data_reg_size(struct ad4130_state * st)40062094060SCosmin Tanislav static unsigned int ad4130_data_reg_size(struct ad4130_state *st)
40162094060SCosmin Tanislav {
40262094060SCosmin Tanislav unsigned int data_reg_size;
40362094060SCosmin Tanislav int ret;
40462094060SCosmin Tanislav
40562094060SCosmin Tanislav ret = ad4130_get_reg_size(st, AD4130_DATA_REG, &data_reg_size);
40662094060SCosmin Tanislav if (ret)
40762094060SCosmin Tanislav return 0;
40862094060SCosmin Tanislav
40962094060SCosmin Tanislav return data_reg_size;
41062094060SCosmin Tanislav }
41162094060SCosmin Tanislav
ad4130_resolution(struct ad4130_state * st)41262094060SCosmin Tanislav static unsigned int ad4130_resolution(struct ad4130_state *st)
41362094060SCosmin Tanislav {
41462094060SCosmin Tanislav return ad4130_data_reg_size(st) * BITS_PER_BYTE;
41562094060SCosmin Tanislav }
41662094060SCosmin Tanislav
ad4130_reg_write(void * context,unsigned int reg,unsigned int val)41762094060SCosmin Tanislav static int ad4130_reg_write(void *context, unsigned int reg, unsigned int val)
41862094060SCosmin Tanislav {
41962094060SCosmin Tanislav struct ad4130_state *st = context;
42062094060SCosmin Tanislav unsigned int size;
42162094060SCosmin Tanislav int ret;
42262094060SCosmin Tanislav
42362094060SCosmin Tanislav ret = ad4130_get_reg_size(st, reg, &size);
42462094060SCosmin Tanislav if (ret)
42562094060SCosmin Tanislav return ret;
42662094060SCosmin Tanislav
42762094060SCosmin Tanislav st->reg_write_tx_buf[0] = reg;
42862094060SCosmin Tanislav
42962094060SCosmin Tanislav switch (size) {
43062094060SCosmin Tanislav case 3:
43162094060SCosmin Tanislav put_unaligned_be24(val, &st->reg_write_tx_buf[1]);
43262094060SCosmin Tanislav break;
43362094060SCosmin Tanislav case 2:
43462094060SCosmin Tanislav put_unaligned_be16(val, &st->reg_write_tx_buf[1]);
43562094060SCosmin Tanislav break;
43662094060SCosmin Tanislav case 1:
43762094060SCosmin Tanislav st->reg_write_tx_buf[1] = val;
43862094060SCosmin Tanislav break;
43962094060SCosmin Tanislav default:
44062094060SCosmin Tanislav return -EINVAL;
44162094060SCosmin Tanislav }
44262094060SCosmin Tanislav
44362094060SCosmin Tanislav return spi_write(st->spi, st->reg_write_tx_buf, size + 1);
44462094060SCosmin Tanislav }
44562094060SCosmin Tanislav
ad4130_reg_read(void * context,unsigned int reg,unsigned int * val)44662094060SCosmin Tanislav static int ad4130_reg_read(void *context, unsigned int reg, unsigned int *val)
44762094060SCosmin Tanislav {
44862094060SCosmin Tanislav struct ad4130_state *st = context;
44962094060SCosmin Tanislav struct spi_transfer t[] = {
45062094060SCosmin Tanislav {
45162094060SCosmin Tanislav .tx_buf = st->reg_read_tx_buf,
45262094060SCosmin Tanislav .len = sizeof(st->reg_read_tx_buf),
45362094060SCosmin Tanislav },
45462094060SCosmin Tanislav {
45562094060SCosmin Tanislav .rx_buf = st->reg_read_rx_buf,
45662094060SCosmin Tanislav },
45762094060SCosmin Tanislav };
45862094060SCosmin Tanislav unsigned int size;
45962094060SCosmin Tanislav int ret;
46062094060SCosmin Tanislav
46162094060SCosmin Tanislav ret = ad4130_get_reg_size(st, reg, &size);
46262094060SCosmin Tanislav if (ret)
46362094060SCosmin Tanislav return ret;
46462094060SCosmin Tanislav
46562094060SCosmin Tanislav st->reg_read_tx_buf[0] = AD4130_COMMS_READ_MASK | reg;
46662094060SCosmin Tanislav t[1].len = size;
46762094060SCosmin Tanislav
46862094060SCosmin Tanislav ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t));
46962094060SCosmin Tanislav if (ret)
47062094060SCosmin Tanislav return ret;
47162094060SCosmin Tanislav
47262094060SCosmin Tanislav switch (size) {
47362094060SCosmin Tanislav case 3:
47462094060SCosmin Tanislav *val = get_unaligned_be24(st->reg_read_rx_buf);
47562094060SCosmin Tanislav break;
47662094060SCosmin Tanislav case 2:
47762094060SCosmin Tanislav *val = get_unaligned_be16(st->reg_read_rx_buf);
47862094060SCosmin Tanislav break;
47962094060SCosmin Tanislav case 1:
48062094060SCosmin Tanislav *val = st->reg_read_rx_buf[0];
48162094060SCosmin Tanislav break;
48262094060SCosmin Tanislav default:
48362094060SCosmin Tanislav return -EINVAL;
48462094060SCosmin Tanislav }
48562094060SCosmin Tanislav
48662094060SCosmin Tanislav return 0;
48762094060SCosmin Tanislav }
48862094060SCosmin Tanislav
48962094060SCosmin Tanislav static const struct regmap_config ad4130_regmap_config = {
49062094060SCosmin Tanislav .reg_read = ad4130_reg_read,
49162094060SCosmin Tanislav .reg_write = ad4130_reg_write,
49262094060SCosmin Tanislav };
49362094060SCosmin Tanislav
ad4130_gpio_init_valid_mask(struct gpio_chip * gc,unsigned long * valid_mask,unsigned int ngpios)49462094060SCosmin Tanislav static int ad4130_gpio_init_valid_mask(struct gpio_chip *gc,
49562094060SCosmin Tanislav unsigned long *valid_mask,
49662094060SCosmin Tanislav unsigned int ngpios)
49762094060SCosmin Tanislav {
49862094060SCosmin Tanislav struct ad4130_state *st = gpiochip_get_data(gc);
49962094060SCosmin Tanislav unsigned int i;
50062094060SCosmin Tanislav
50162094060SCosmin Tanislav /*
50262094060SCosmin Tanislav * Output-only GPIO functionality is available on pins AIN2 through
50362094060SCosmin Tanislav * AIN5. If these pins are used for anything else, do not expose them.
50462094060SCosmin Tanislav */
50562094060SCosmin Tanislav for (i = 0; i < ngpios; i++) {
50662094060SCosmin Tanislav unsigned int pin = i + AD4130_AIN2_P1;
50762094060SCosmin Tanislav bool valid = st->pins_fn[pin] == AD4130_PIN_FN_NONE;
50862094060SCosmin Tanislav
50962094060SCosmin Tanislav __assign_bit(i, valid_mask, valid);
51062094060SCosmin Tanislav }
51162094060SCosmin Tanislav
51262094060SCosmin Tanislav return 0;
51362094060SCosmin Tanislav }
51462094060SCosmin Tanislav
ad4130_gpio_get_direction(struct gpio_chip * gc,unsigned int offset)51562094060SCosmin Tanislav static int ad4130_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
51662094060SCosmin Tanislav {
51762094060SCosmin Tanislav return GPIO_LINE_DIRECTION_OUT;
51862094060SCosmin Tanislav }
51962094060SCosmin Tanislav
ad4130_gpio_set(struct gpio_chip * gc,unsigned int offset,int value)52062094060SCosmin Tanislav static void ad4130_gpio_set(struct gpio_chip *gc, unsigned int offset,
52162094060SCosmin Tanislav int value)
52262094060SCosmin Tanislav {
52362094060SCosmin Tanislav struct ad4130_state *st = gpiochip_get_data(gc);
52462094060SCosmin Tanislav unsigned int mask = FIELD_PREP(AD4130_IO_CONTROL_GPIO_DATA_MASK,
52562094060SCosmin Tanislav BIT(offset));
52662094060SCosmin Tanislav
52762094060SCosmin Tanislav regmap_update_bits(st->regmap, AD4130_IO_CONTROL_REG, mask,
52862094060SCosmin Tanislav value ? mask : 0);
52962094060SCosmin Tanislav }
53062094060SCosmin Tanislav
ad4130_set_mode(struct ad4130_state * st,enum ad4130_mode mode)53162094060SCosmin Tanislav static int ad4130_set_mode(struct ad4130_state *st, enum ad4130_mode mode)
53262094060SCosmin Tanislav {
53362094060SCosmin Tanislav return regmap_update_bits(st->regmap, AD4130_ADC_CONTROL_REG,
53462094060SCosmin Tanislav AD4130_ADC_CONTROL_MODE_MASK,
53562094060SCosmin Tanislav FIELD_PREP(AD4130_ADC_CONTROL_MODE_MASK, mode));
53662094060SCosmin Tanislav }
53762094060SCosmin Tanislav
ad4130_set_watermark_interrupt_en(struct ad4130_state * st,bool en)53862094060SCosmin Tanislav static int ad4130_set_watermark_interrupt_en(struct ad4130_state *st, bool en)
53962094060SCosmin Tanislav {
54062094060SCosmin Tanislav return regmap_update_bits(st->regmap, AD4130_FIFO_CONTROL_REG,
54162094060SCosmin Tanislav AD4130_FIFO_CONTROL_WM_INT_EN_MASK,
54262094060SCosmin Tanislav FIELD_PREP(AD4130_FIFO_CONTROL_WM_INT_EN_MASK, en));
54362094060SCosmin Tanislav }
54462094060SCosmin Tanislav
ad4130_watermark_reg_val(unsigned int val)54562094060SCosmin Tanislav static unsigned int ad4130_watermark_reg_val(unsigned int val)
54662094060SCosmin Tanislav {
54762094060SCosmin Tanislav if (val == AD4130_FIFO_SIZE)
54862094060SCosmin Tanislav val = AD4130_WATERMARK_256;
54962094060SCosmin Tanislav
55062094060SCosmin Tanislav return val;
55162094060SCosmin Tanislav }
55262094060SCosmin Tanislav
ad4130_set_fifo_mode(struct ad4130_state * st,enum ad4130_fifo_mode mode)55362094060SCosmin Tanislav static int ad4130_set_fifo_mode(struct ad4130_state *st,
55462094060SCosmin Tanislav enum ad4130_fifo_mode mode)
55562094060SCosmin Tanislav {
55662094060SCosmin Tanislav return regmap_update_bits(st->regmap, AD4130_FIFO_CONTROL_REG,
55762094060SCosmin Tanislav AD4130_FIFO_CONTROL_MODE_MASK,
55862094060SCosmin Tanislav FIELD_PREP(AD4130_FIFO_CONTROL_MODE_MASK, mode));
55962094060SCosmin Tanislav }
56062094060SCosmin Tanislav
ad4130_push_fifo_data(struct iio_dev * indio_dev)56162094060SCosmin Tanislav static void ad4130_push_fifo_data(struct iio_dev *indio_dev)
56262094060SCosmin Tanislav {
56362094060SCosmin Tanislav struct ad4130_state *st = iio_priv(indio_dev);
56462094060SCosmin Tanislav unsigned int data_reg_size = ad4130_data_reg_size(st);
56562094060SCosmin Tanislav unsigned int transfer_len = st->effective_watermark * data_reg_size;
56662094060SCosmin Tanislav unsigned int set_size = st->num_enabled_channels * data_reg_size;
56762094060SCosmin Tanislav unsigned int i;
56862094060SCosmin Tanislav int ret;
56962094060SCosmin Tanislav
57062094060SCosmin Tanislav st->fifo_tx_buf[1] = ad4130_watermark_reg_val(st->effective_watermark);
57162094060SCosmin Tanislav st->fifo_xfer[1].len = transfer_len;
57262094060SCosmin Tanislav
57362094060SCosmin Tanislav ret = spi_sync(st->spi, &st->fifo_msg);
57462094060SCosmin Tanislav if (ret)
57562094060SCosmin Tanislav return;
57662094060SCosmin Tanislav
57762094060SCosmin Tanislav for (i = 0; i < transfer_len; i += set_size)
57862094060SCosmin Tanislav iio_push_to_buffers(indio_dev, &st->fifo_rx_buf[i]);
57962094060SCosmin Tanislav }
58062094060SCosmin Tanislav
ad4130_irq_handler(int irq,void * private)58162094060SCosmin Tanislav static irqreturn_t ad4130_irq_handler(int irq, void *private)
58262094060SCosmin Tanislav {
58362094060SCosmin Tanislav struct iio_dev *indio_dev = private;
58462094060SCosmin Tanislav struct ad4130_state *st = iio_priv(indio_dev);
58562094060SCosmin Tanislav
58662094060SCosmin Tanislav if (iio_buffer_enabled(indio_dev))
58762094060SCosmin Tanislav ad4130_push_fifo_data(indio_dev);
58862094060SCosmin Tanislav else
58962094060SCosmin Tanislav complete(&st->completion);
59062094060SCosmin Tanislav
59162094060SCosmin Tanislav return IRQ_HANDLED;
59262094060SCosmin Tanislav }
59362094060SCosmin Tanislav
ad4130_find_slot(struct ad4130_state * st,struct ad4130_setup_info * target_setup_info,unsigned int * slot,bool * overwrite)59462094060SCosmin Tanislav static int ad4130_find_slot(struct ad4130_state *st,
59562094060SCosmin Tanislav struct ad4130_setup_info *target_setup_info,
59662094060SCosmin Tanislav unsigned int *slot, bool *overwrite)
59762094060SCosmin Tanislav {
59862094060SCosmin Tanislav unsigned int i;
59962094060SCosmin Tanislav
60062094060SCosmin Tanislav *slot = AD4130_INVALID_SLOT;
60162094060SCosmin Tanislav *overwrite = false;
60262094060SCosmin Tanislav
60362094060SCosmin Tanislav for (i = 0; i < AD4130_MAX_SETUPS; i++) {
60462094060SCosmin Tanislav struct ad4130_slot_info *slot_info = &st->slots_info[i];
60562094060SCosmin Tanislav
60662094060SCosmin Tanislav /* Immediately accept a matching setup info. */
60762094060SCosmin Tanislav if (!memcmp(target_setup_info, &slot_info->setup,
60862094060SCosmin Tanislav sizeof(*target_setup_info))) {
60962094060SCosmin Tanislav *slot = i;
61062094060SCosmin Tanislav return 0;
61162094060SCosmin Tanislav }
61262094060SCosmin Tanislav
61362094060SCosmin Tanislav /* Ignore all setups which are used by enabled channels. */
61462094060SCosmin Tanislav if (slot_info->enabled_channels)
61562094060SCosmin Tanislav continue;
61662094060SCosmin Tanislav
61762094060SCosmin Tanislav /* Find the least used slot. */
61862094060SCosmin Tanislav if (*slot == AD4130_INVALID_SLOT ||
61962094060SCosmin Tanislav slot_info->channels < st->slots_info[*slot].channels)
62062094060SCosmin Tanislav *slot = i;
62162094060SCosmin Tanislav }
62262094060SCosmin Tanislav
62362094060SCosmin Tanislav if (*slot == AD4130_INVALID_SLOT)
62462094060SCosmin Tanislav return -EINVAL;
62562094060SCosmin Tanislav
62662094060SCosmin Tanislav *overwrite = true;
62762094060SCosmin Tanislav
62862094060SCosmin Tanislav return 0;
62962094060SCosmin Tanislav }
63062094060SCosmin Tanislav
ad4130_unlink_channel(struct ad4130_state * st,unsigned int channel)63162094060SCosmin Tanislav static void ad4130_unlink_channel(struct ad4130_state *st, unsigned int channel)
63262094060SCosmin Tanislav {
63362094060SCosmin Tanislav struct ad4130_chan_info *chan_info = &st->chans_info[channel];
63462094060SCosmin Tanislav struct ad4130_slot_info *slot_info = &st->slots_info[chan_info->slot];
63562094060SCosmin Tanislav
63662094060SCosmin Tanislav chan_info->slot = AD4130_INVALID_SLOT;
63762094060SCosmin Tanislav slot_info->channels--;
63862094060SCosmin Tanislav }
63962094060SCosmin Tanislav
ad4130_unlink_slot(struct ad4130_state * st,unsigned int slot)64062094060SCosmin Tanislav static int ad4130_unlink_slot(struct ad4130_state *st, unsigned int slot)
64162094060SCosmin Tanislav {
64262094060SCosmin Tanislav unsigned int i;
64362094060SCosmin Tanislav
64462094060SCosmin Tanislav for (i = 0; i < AD4130_MAX_CHANNELS; i++) {
64562094060SCosmin Tanislav struct ad4130_chan_info *chan_info = &st->chans_info[i];
64662094060SCosmin Tanislav
64762094060SCosmin Tanislav if (!chan_info->initialized || chan_info->slot != slot)
64862094060SCosmin Tanislav continue;
64962094060SCosmin Tanislav
65062094060SCosmin Tanislav ad4130_unlink_channel(st, i);
65162094060SCosmin Tanislav }
65262094060SCosmin Tanislav
65362094060SCosmin Tanislav return 0;
65462094060SCosmin Tanislav }
65562094060SCosmin Tanislav
ad4130_link_channel_slot(struct ad4130_state * st,unsigned int channel,unsigned int slot)65662094060SCosmin Tanislav static int ad4130_link_channel_slot(struct ad4130_state *st,
65762094060SCosmin Tanislav unsigned int channel, unsigned int slot)
65862094060SCosmin Tanislav {
65962094060SCosmin Tanislav struct ad4130_slot_info *slot_info = &st->slots_info[slot];
66062094060SCosmin Tanislav struct ad4130_chan_info *chan_info = &st->chans_info[channel];
66162094060SCosmin Tanislav int ret;
66262094060SCosmin Tanislav
66362094060SCosmin Tanislav ret = regmap_update_bits(st->regmap, AD4130_CHANNEL_X_REG(channel),
66462094060SCosmin Tanislav AD4130_CHANNEL_SETUP_MASK,
66562094060SCosmin Tanislav FIELD_PREP(AD4130_CHANNEL_SETUP_MASK, slot));
66662094060SCosmin Tanislav if (ret)
66762094060SCosmin Tanislav return ret;
66862094060SCosmin Tanislav
66962094060SCosmin Tanislav chan_info->slot = slot;
67062094060SCosmin Tanislav slot_info->channels++;
67162094060SCosmin Tanislav
67262094060SCosmin Tanislav return 0;
67362094060SCosmin Tanislav }
67462094060SCosmin Tanislav
ad4130_write_slot_setup(struct ad4130_state * st,unsigned int slot,struct ad4130_setup_info * setup_info)67562094060SCosmin Tanislav static int ad4130_write_slot_setup(struct ad4130_state *st,
67662094060SCosmin Tanislav unsigned int slot,
67762094060SCosmin Tanislav struct ad4130_setup_info *setup_info)
67862094060SCosmin Tanislav {
67962094060SCosmin Tanislav unsigned int val;
68062094060SCosmin Tanislav int ret;
68162094060SCosmin Tanislav
68262094060SCosmin Tanislav val = FIELD_PREP(AD4130_CONFIG_IOUT1_VAL_MASK, setup_info->iout0_val) |
68362094060SCosmin Tanislav FIELD_PREP(AD4130_CONFIG_IOUT1_VAL_MASK, setup_info->iout1_val) |
68462094060SCosmin Tanislav FIELD_PREP(AD4130_CONFIG_BURNOUT_MASK, setup_info->burnout) |
68562094060SCosmin Tanislav FIELD_PREP(AD4130_CONFIG_REF_BUFP_MASK, setup_info->ref_bufp) |
68662094060SCosmin Tanislav FIELD_PREP(AD4130_CONFIG_REF_BUFM_MASK, setup_info->ref_bufm) |
68762094060SCosmin Tanislav FIELD_PREP(AD4130_CONFIG_REF_SEL_MASK, setup_info->ref_sel) |
68862094060SCosmin Tanislav FIELD_PREP(AD4130_CONFIG_PGA_MASK, setup_info->pga);
68962094060SCosmin Tanislav
69062094060SCosmin Tanislav ret = regmap_write(st->regmap, AD4130_CONFIG_X_REG(slot), val);
69162094060SCosmin Tanislav if (ret)
69262094060SCosmin Tanislav return ret;
69362094060SCosmin Tanislav
69462094060SCosmin Tanislav val = FIELD_PREP(AD4130_FILTER_MODE_MASK, setup_info->filter_mode) |
69562094060SCosmin Tanislav FIELD_PREP(AD4130_FILTER_SELECT_MASK, setup_info->fs);
69662094060SCosmin Tanislav
69762094060SCosmin Tanislav ret = regmap_write(st->regmap, AD4130_FILTER_X_REG(slot), val);
69862094060SCosmin Tanislav if (ret)
69962094060SCosmin Tanislav return ret;
70062094060SCosmin Tanislav
70162094060SCosmin Tanislav memcpy(&st->slots_info[slot].setup, setup_info, sizeof(*setup_info));
70262094060SCosmin Tanislav
70362094060SCosmin Tanislav return 0;
70462094060SCosmin Tanislav }
70562094060SCosmin Tanislav
ad4130_write_channel_setup(struct ad4130_state * st,unsigned int channel,bool on_enable)70662094060SCosmin Tanislav static int ad4130_write_channel_setup(struct ad4130_state *st,
70762094060SCosmin Tanislav unsigned int channel, bool on_enable)
70862094060SCosmin Tanislav {
70962094060SCosmin Tanislav struct ad4130_chan_info *chan_info = &st->chans_info[channel];
71062094060SCosmin Tanislav struct ad4130_setup_info *setup_info = &chan_info->setup;
71162094060SCosmin Tanislav bool overwrite;
71262094060SCosmin Tanislav int slot;
71362094060SCosmin Tanislav int ret;
71462094060SCosmin Tanislav
71562094060SCosmin Tanislav /*
71662094060SCosmin Tanislav * The following cases need to be handled.
71762094060SCosmin Tanislav *
71862094060SCosmin Tanislav * 1. Enabled and linked channel with setup changes:
71962094060SCosmin Tanislav * - Find a slot. If not possible, return error.
72062094060SCosmin Tanislav * - Unlink channel from current slot.
72162094060SCosmin Tanislav * - If the slot has channels linked to it, unlink all channels, and
72262094060SCosmin Tanislav * write the new setup to it.
72362094060SCosmin Tanislav * - Link channel to new slot.
72462094060SCosmin Tanislav *
72562094060SCosmin Tanislav * 2. Soon to be enabled and unlinked channel:
72662094060SCosmin Tanislav * - Find a slot. If not possible, return error.
72762094060SCosmin Tanislav * - If the slot has channels linked to it, unlink all channels, and
72862094060SCosmin Tanislav * write the new setup to it.
72962094060SCosmin Tanislav * - Link channel to the slot.
73062094060SCosmin Tanislav *
73162094060SCosmin Tanislav * 3. Disabled and linked channel with setup changes:
73262094060SCosmin Tanislav * - Unlink channel from current slot.
73362094060SCosmin Tanislav *
73462094060SCosmin Tanislav * 4. Soon to be enabled and linked channel:
73562094060SCosmin Tanislav * 5. Disabled and unlinked channel with setup changes:
73662094060SCosmin Tanislav * - Do nothing.
73762094060SCosmin Tanislav */
73862094060SCosmin Tanislav
73962094060SCosmin Tanislav /* Case 4 */
74062094060SCosmin Tanislav if (on_enable && chan_info->slot != AD4130_INVALID_SLOT)
74162094060SCosmin Tanislav return 0;
74262094060SCosmin Tanislav
74362094060SCosmin Tanislav if (!on_enable && !chan_info->enabled) {
74462094060SCosmin Tanislav if (chan_info->slot != AD4130_INVALID_SLOT)
74562094060SCosmin Tanislav /* Case 3 */
74662094060SCosmin Tanislav ad4130_unlink_channel(st, channel);
74762094060SCosmin Tanislav
74862094060SCosmin Tanislav /* Cases 3 & 5 */
74962094060SCosmin Tanislav return 0;
75062094060SCosmin Tanislav }
75162094060SCosmin Tanislav
75262094060SCosmin Tanislav /* Cases 1 & 2 */
75362094060SCosmin Tanislav ret = ad4130_find_slot(st, setup_info, &slot, &overwrite);
75462094060SCosmin Tanislav if (ret)
75562094060SCosmin Tanislav return ret;
75662094060SCosmin Tanislav
75762094060SCosmin Tanislav if (chan_info->slot != AD4130_INVALID_SLOT)
75862094060SCosmin Tanislav /* Case 1 */
75962094060SCosmin Tanislav ad4130_unlink_channel(st, channel);
76062094060SCosmin Tanislav
76162094060SCosmin Tanislav if (overwrite) {
76262094060SCosmin Tanislav ret = ad4130_unlink_slot(st, slot);
76362094060SCosmin Tanislav if (ret)
76462094060SCosmin Tanislav return ret;
76562094060SCosmin Tanislav
76662094060SCosmin Tanislav ret = ad4130_write_slot_setup(st, slot, setup_info);
76762094060SCosmin Tanislav if (ret)
76862094060SCosmin Tanislav return ret;
76962094060SCosmin Tanislav }
77062094060SCosmin Tanislav
77162094060SCosmin Tanislav return ad4130_link_channel_slot(st, channel, slot);
77262094060SCosmin Tanislav }
77362094060SCosmin Tanislav
ad4130_set_channel_enable(struct ad4130_state * st,unsigned int channel,bool status)77462094060SCosmin Tanislav static int ad4130_set_channel_enable(struct ad4130_state *st,
77562094060SCosmin Tanislav unsigned int channel, bool status)
77662094060SCosmin Tanislav {
77762094060SCosmin Tanislav struct ad4130_chan_info *chan_info = &st->chans_info[channel];
77862094060SCosmin Tanislav struct ad4130_slot_info *slot_info;
77962094060SCosmin Tanislav int ret;
78062094060SCosmin Tanislav
78162094060SCosmin Tanislav if (chan_info->enabled == status)
78262094060SCosmin Tanislav return 0;
78362094060SCosmin Tanislav
78462094060SCosmin Tanislav if (status) {
78562094060SCosmin Tanislav ret = ad4130_write_channel_setup(st, channel, true);
78662094060SCosmin Tanislav if (ret)
78762094060SCosmin Tanislav return ret;
78862094060SCosmin Tanislav }
78962094060SCosmin Tanislav
79062094060SCosmin Tanislav slot_info = &st->slots_info[chan_info->slot];
79162094060SCosmin Tanislav
79262094060SCosmin Tanislav ret = regmap_update_bits(st->regmap, AD4130_CHANNEL_X_REG(channel),
79362094060SCosmin Tanislav AD4130_CHANNEL_EN_MASK,
79462094060SCosmin Tanislav FIELD_PREP(AD4130_CHANNEL_EN_MASK, status));
79562094060SCosmin Tanislav if (ret)
79662094060SCosmin Tanislav return ret;
79762094060SCosmin Tanislav
79862094060SCosmin Tanislav slot_info->enabled_channels += status ? 1 : -1;
79962094060SCosmin Tanislav chan_info->enabled = status;
80062094060SCosmin Tanislav
80162094060SCosmin Tanislav return 0;
80262094060SCosmin Tanislav }
80362094060SCosmin Tanislav
80462094060SCosmin Tanislav /*
80562094060SCosmin Tanislav * Table 58. FILTER_MODE_n bits and Filter Types of the datasheet describes
80662094060SCosmin Tanislav * the relation between filter mode, ODR and FS.
80762094060SCosmin Tanislav *
80862094060SCosmin Tanislav * Notice that the max ODR of each filter mode is not necessarily the
80962094060SCosmin Tanislav * absolute max ODR supported by the chip.
81062094060SCosmin Tanislav *
81162094060SCosmin Tanislav * The ODR divider is not explicitly specified, but it can be deduced based
81262094060SCosmin Tanislav * on the ODR range of each filter mode.
81362094060SCosmin Tanislav *
81462094060SCosmin Tanislav * For example, for Sinc4+Sinc1, max ODR is 218.18. That means that the
81562094060SCosmin Tanislav * absolute max ODR is divided by 11 to achieve the max ODR of this filter
81662094060SCosmin Tanislav * mode.
81762094060SCosmin Tanislav *
81862094060SCosmin Tanislav * The formulas for converting between ODR and FS for a specific filter
81962094060SCosmin Tanislav * mode can be deduced from the same table.
82062094060SCosmin Tanislav *
82162094060SCosmin Tanislav * Notice that FS = 1 actually means max ODR, and that ODR decreases by
82262094060SCosmin Tanislav * (maximum ODR / maximum FS) for each increment of FS.
82362094060SCosmin Tanislav *
82462094060SCosmin Tanislav * odr = MAX_ODR / odr_div * (1 - (fs - 1) / fs_max) <=>
82562094060SCosmin Tanislav * odr = MAX_ODR * (1 - (fs - 1) / fs_max) / odr_div <=>
82662094060SCosmin Tanislav * odr = MAX_ODR * (1 - (fs - 1) / fs_max) / odr_div <=>
82762094060SCosmin Tanislav * odr = MAX_ODR * (fs_max - fs + 1) / (fs_max * odr_div)
82862094060SCosmin Tanislav * (used in ad4130_fs_to_freq)
82962094060SCosmin Tanislav *
83062094060SCosmin Tanislav * For the opposite formula, FS can be extracted from the last one.
83162094060SCosmin Tanislav *
83262094060SCosmin Tanislav * MAX_ODR * (fs_max - fs + 1) = fs_max * odr_div * odr <=>
83362094060SCosmin Tanislav * fs_max - fs + 1 = fs_max * odr_div * odr / MAX_ODR <=>
83462094060SCosmin Tanislav * fs = 1 + fs_max - fs_max * odr_div * odr / MAX_ODR
83562094060SCosmin Tanislav * (used in ad4130_fs_to_freq)
83662094060SCosmin Tanislav */
83762094060SCosmin Tanislav
ad4130_freq_to_fs(enum ad4130_filter_mode filter_mode,int val,int val2,unsigned int * fs)83862094060SCosmin Tanislav static void ad4130_freq_to_fs(enum ad4130_filter_mode filter_mode,
83962094060SCosmin Tanislav int val, int val2, unsigned int *fs)
84062094060SCosmin Tanislav {
84162094060SCosmin Tanislav const struct ad4130_filter_config *filter_config =
84262094060SCosmin Tanislav &ad4130_filter_configs[filter_mode];
84362094060SCosmin Tanislav u64 dividend, divisor;
84462094060SCosmin Tanislav int temp;
84562094060SCosmin Tanislav
84662094060SCosmin Tanislav dividend = filter_config->fs_max * filter_config->odr_div *
84762094060SCosmin Tanislav ((u64)val * NANO + val2);
84862094060SCosmin Tanislav divisor = (u64)AD4130_MAX_ODR * NANO;
84962094060SCosmin Tanislav
85062094060SCosmin Tanislav temp = AD4130_FILTER_SELECT_MIN + filter_config->fs_max -
85162094060SCosmin Tanislav DIV64_U64_ROUND_CLOSEST(dividend, divisor);
85262094060SCosmin Tanislav
85362094060SCosmin Tanislav if (temp < AD4130_FILTER_SELECT_MIN)
85462094060SCosmin Tanislav temp = AD4130_FILTER_SELECT_MIN;
85562094060SCosmin Tanislav else if (temp > filter_config->fs_max)
85662094060SCosmin Tanislav temp = filter_config->fs_max;
85762094060SCosmin Tanislav
85862094060SCosmin Tanislav *fs = temp;
85962094060SCosmin Tanislav }
86062094060SCosmin Tanislav
ad4130_fs_to_freq(enum ad4130_filter_mode filter_mode,unsigned int fs,int * val,int * val2)86162094060SCosmin Tanislav static void ad4130_fs_to_freq(enum ad4130_filter_mode filter_mode,
86262094060SCosmin Tanislav unsigned int fs, int *val, int *val2)
86362094060SCosmin Tanislav {
86462094060SCosmin Tanislav const struct ad4130_filter_config *filter_config =
86562094060SCosmin Tanislav &ad4130_filter_configs[filter_mode];
86662094060SCosmin Tanislav unsigned int dividend, divisor;
86762094060SCosmin Tanislav u64 temp;
86862094060SCosmin Tanislav
86962094060SCosmin Tanislav dividend = (filter_config->fs_max - fs + AD4130_FILTER_SELECT_MIN) *
87062094060SCosmin Tanislav AD4130_MAX_ODR;
87162094060SCosmin Tanislav divisor = filter_config->fs_max * filter_config->odr_div;
87262094060SCosmin Tanislav
87362094060SCosmin Tanislav temp = div_u64((u64)dividend * NANO, divisor);
87462094060SCosmin Tanislav *val = div_u64_rem(temp, NANO, val2);
87562094060SCosmin Tanislav }
87662094060SCosmin Tanislav
ad4130_set_filter_mode(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,unsigned int val)87762094060SCosmin Tanislav static int ad4130_set_filter_mode(struct iio_dev *indio_dev,
87862094060SCosmin Tanislav const struct iio_chan_spec *chan,
87962094060SCosmin Tanislav unsigned int val)
88062094060SCosmin Tanislav {
88162094060SCosmin Tanislav struct ad4130_state *st = iio_priv(indio_dev);
88262094060SCosmin Tanislav unsigned int channel = chan->scan_index;
88362094060SCosmin Tanislav struct ad4130_chan_info *chan_info = &st->chans_info[channel];
88462094060SCosmin Tanislav struct ad4130_setup_info *setup_info = &chan_info->setup;
88562094060SCosmin Tanislav enum ad4130_filter_mode old_filter_mode;
88662094060SCosmin Tanislav int freq_val, freq_val2;
88762094060SCosmin Tanislav unsigned int old_fs;
88862094060SCosmin Tanislav int ret = 0;
88962094060SCosmin Tanislav
89062094060SCosmin Tanislav mutex_lock(&st->lock);
89162094060SCosmin Tanislav if (setup_info->filter_mode == val)
89262094060SCosmin Tanislav goto out;
89362094060SCosmin Tanislav
89462094060SCosmin Tanislav old_fs = setup_info->fs;
89562094060SCosmin Tanislav old_filter_mode = setup_info->filter_mode;
89662094060SCosmin Tanislav
89762094060SCosmin Tanislav /*
89862094060SCosmin Tanislav * When switching between filter modes, try to match the ODR as
89962094060SCosmin Tanislav * close as possible. To do this, convert the current FS into ODR
90062094060SCosmin Tanislav * using the old filter mode, then convert it back into FS using
90162094060SCosmin Tanislav * the new filter mode.
90262094060SCosmin Tanislav */
90362094060SCosmin Tanislav ad4130_fs_to_freq(setup_info->filter_mode, setup_info->fs,
90462094060SCosmin Tanislav &freq_val, &freq_val2);
90562094060SCosmin Tanislav
90662094060SCosmin Tanislav ad4130_freq_to_fs(val, freq_val, freq_val2, &setup_info->fs);
90762094060SCosmin Tanislav
90862094060SCosmin Tanislav setup_info->filter_mode = val;
90962094060SCosmin Tanislav
91062094060SCosmin Tanislav ret = ad4130_write_channel_setup(st, channel, false);
91162094060SCosmin Tanislav if (ret) {
91262094060SCosmin Tanislav setup_info->fs = old_fs;
91362094060SCosmin Tanislav setup_info->filter_mode = old_filter_mode;
91462094060SCosmin Tanislav }
91562094060SCosmin Tanislav
91662094060SCosmin Tanislav out:
91762094060SCosmin Tanislav mutex_unlock(&st->lock);
91862094060SCosmin Tanislav
91962094060SCosmin Tanislav return ret;
92062094060SCosmin Tanislav }
92162094060SCosmin Tanislav
ad4130_get_filter_mode(struct iio_dev * indio_dev,const struct iio_chan_spec * chan)92262094060SCosmin Tanislav static int ad4130_get_filter_mode(struct iio_dev *indio_dev,
92362094060SCosmin Tanislav const struct iio_chan_spec *chan)
92462094060SCosmin Tanislav {
92562094060SCosmin Tanislav struct ad4130_state *st = iio_priv(indio_dev);
92662094060SCosmin Tanislav unsigned int channel = chan->scan_index;
92762094060SCosmin Tanislav struct ad4130_setup_info *setup_info = &st->chans_info[channel].setup;
92862094060SCosmin Tanislav enum ad4130_filter_mode filter_mode;
92962094060SCosmin Tanislav
93062094060SCosmin Tanislav mutex_lock(&st->lock);
93162094060SCosmin Tanislav filter_mode = setup_info->filter_mode;
93262094060SCosmin Tanislav mutex_unlock(&st->lock);
93362094060SCosmin Tanislav
93462094060SCosmin Tanislav return filter_mode;
93562094060SCosmin Tanislav }
93662094060SCosmin Tanislav
93762094060SCosmin Tanislav static const struct iio_enum ad4130_filter_mode_enum = {
93862094060SCosmin Tanislav .items = ad4130_filter_modes_str,
93962094060SCosmin Tanislav .num_items = ARRAY_SIZE(ad4130_filter_modes_str),
94062094060SCosmin Tanislav .set = ad4130_set_filter_mode,
94162094060SCosmin Tanislav .get = ad4130_get_filter_mode,
94262094060SCosmin Tanislav };
94362094060SCosmin Tanislav
94462094060SCosmin Tanislav static const struct iio_chan_spec_ext_info ad4130_filter_mode_ext_info[] = {
94562094060SCosmin Tanislav IIO_ENUM("filter_mode", IIO_SEPARATE, &ad4130_filter_mode_enum),
94662094060SCosmin Tanislav IIO_ENUM_AVAILABLE("filter_mode", IIO_SHARED_BY_TYPE,
94762094060SCosmin Tanislav &ad4130_filter_mode_enum),
94862094060SCosmin Tanislav { }
94962094060SCosmin Tanislav };
95062094060SCosmin Tanislav
95162094060SCosmin Tanislav static const struct iio_chan_spec ad4130_channel_template = {
95262094060SCosmin Tanislav .type = IIO_VOLTAGE,
95362094060SCosmin Tanislav .indexed = 1,
95462094060SCosmin Tanislav .differential = 1,
95562094060SCosmin Tanislav .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
95662094060SCosmin Tanislav BIT(IIO_CHAN_INFO_SCALE) |
95762094060SCosmin Tanislav BIT(IIO_CHAN_INFO_OFFSET) |
95862094060SCosmin Tanislav BIT(IIO_CHAN_INFO_SAMP_FREQ),
95962094060SCosmin Tanislav .info_mask_separate_available = BIT(IIO_CHAN_INFO_SCALE) |
96062094060SCosmin Tanislav BIT(IIO_CHAN_INFO_SAMP_FREQ),
96162094060SCosmin Tanislav .ext_info = ad4130_filter_mode_ext_info,
96262094060SCosmin Tanislav .scan_type = {
96362094060SCosmin Tanislav .sign = 'u',
96462094060SCosmin Tanislav .endianness = IIO_BE,
96562094060SCosmin Tanislav },
96662094060SCosmin Tanislav };
96762094060SCosmin Tanislav
ad4130_set_channel_pga(struct ad4130_state * st,unsigned int channel,int val,int val2)96862094060SCosmin Tanislav static int ad4130_set_channel_pga(struct ad4130_state *st, unsigned int channel,
96962094060SCosmin Tanislav int val, int val2)
97062094060SCosmin Tanislav {
97162094060SCosmin Tanislav struct ad4130_chan_info *chan_info = &st->chans_info[channel];
97262094060SCosmin Tanislav struct ad4130_setup_info *setup_info = &chan_info->setup;
97362094060SCosmin Tanislav unsigned int pga, old_pga;
97462094060SCosmin Tanislav int ret = 0;
97562094060SCosmin Tanislav
97662094060SCosmin Tanislav for (pga = 0; pga < AD4130_MAX_PGA; pga++)
97762094060SCosmin Tanislav if (val == st->scale_tbls[setup_info->ref_sel][pga][0] &&
97862094060SCosmin Tanislav val2 == st->scale_tbls[setup_info->ref_sel][pga][1])
97962094060SCosmin Tanislav break;
98062094060SCosmin Tanislav
98162094060SCosmin Tanislav if (pga == AD4130_MAX_PGA)
98262094060SCosmin Tanislav return -EINVAL;
98362094060SCosmin Tanislav
98462094060SCosmin Tanislav mutex_lock(&st->lock);
98562094060SCosmin Tanislav if (pga == setup_info->pga)
98662094060SCosmin Tanislav goto out;
98762094060SCosmin Tanislav
98862094060SCosmin Tanislav old_pga = setup_info->pga;
98962094060SCosmin Tanislav setup_info->pga = pga;
99062094060SCosmin Tanislav
99162094060SCosmin Tanislav ret = ad4130_write_channel_setup(st, channel, false);
99262094060SCosmin Tanislav if (ret)
99362094060SCosmin Tanislav setup_info->pga = old_pga;
99462094060SCosmin Tanislav
99562094060SCosmin Tanislav out:
99662094060SCosmin Tanislav mutex_unlock(&st->lock);
99762094060SCosmin Tanislav
99862094060SCosmin Tanislav return ret;
99962094060SCosmin Tanislav }
100062094060SCosmin Tanislav
ad4130_set_channel_freq(struct ad4130_state * st,unsigned int channel,int val,int val2)100162094060SCosmin Tanislav static int ad4130_set_channel_freq(struct ad4130_state *st,
100262094060SCosmin Tanislav unsigned int channel, int val, int val2)
100362094060SCosmin Tanislav {
100462094060SCosmin Tanislav struct ad4130_chan_info *chan_info = &st->chans_info[channel];
100562094060SCosmin Tanislav struct ad4130_setup_info *setup_info = &chan_info->setup;
100662094060SCosmin Tanislav unsigned int fs, old_fs;
100762094060SCosmin Tanislav int ret = 0;
100862094060SCosmin Tanislav
100962094060SCosmin Tanislav mutex_lock(&st->lock);
101062094060SCosmin Tanislav old_fs = setup_info->fs;
101162094060SCosmin Tanislav
101262094060SCosmin Tanislav ad4130_freq_to_fs(setup_info->filter_mode, val, val2, &fs);
101362094060SCosmin Tanislav
101462094060SCosmin Tanislav if (fs == setup_info->fs)
101562094060SCosmin Tanislav goto out;
101662094060SCosmin Tanislav
101762094060SCosmin Tanislav setup_info->fs = fs;
101862094060SCosmin Tanislav
101962094060SCosmin Tanislav ret = ad4130_write_channel_setup(st, channel, false);
102062094060SCosmin Tanislav if (ret)
102162094060SCosmin Tanislav setup_info->fs = old_fs;
102262094060SCosmin Tanislav
102362094060SCosmin Tanislav out:
102462094060SCosmin Tanislav mutex_unlock(&st->lock);
102562094060SCosmin Tanislav
102662094060SCosmin Tanislav return ret;
102762094060SCosmin Tanislav }
102862094060SCosmin Tanislav
_ad4130_read_sample(struct iio_dev * indio_dev,unsigned int channel,int * val)102962094060SCosmin Tanislav static int _ad4130_read_sample(struct iio_dev *indio_dev, unsigned int channel,
103062094060SCosmin Tanislav int *val)
103162094060SCosmin Tanislav {
103262094060SCosmin Tanislav struct ad4130_state *st = iio_priv(indio_dev);
103362094060SCosmin Tanislav int ret;
103462094060SCosmin Tanislav
103562094060SCosmin Tanislav ret = ad4130_set_channel_enable(st, channel, true);
103662094060SCosmin Tanislav if (ret)
103762094060SCosmin Tanislav return ret;
103862094060SCosmin Tanislav
103962094060SCosmin Tanislav reinit_completion(&st->completion);
104062094060SCosmin Tanislav
104162094060SCosmin Tanislav ret = ad4130_set_mode(st, AD4130_MODE_CONTINUOUS);
104262094060SCosmin Tanislav if (ret)
104362094060SCosmin Tanislav return ret;
104462094060SCosmin Tanislav
104562094060SCosmin Tanislav ret = wait_for_completion_timeout(&st->completion,
104662094060SCosmin Tanislav msecs_to_jiffies(1000));
104762094060SCosmin Tanislav if (!ret)
104862094060SCosmin Tanislav return -ETIMEDOUT;
104962094060SCosmin Tanislav
105062094060SCosmin Tanislav ret = ad4130_set_mode(st, AD4130_MODE_IDLE);
105162094060SCosmin Tanislav if (ret)
105262094060SCosmin Tanislav return ret;
105362094060SCosmin Tanislav
105462094060SCosmin Tanislav ret = regmap_read(st->regmap, AD4130_DATA_REG, val);
105562094060SCosmin Tanislav if (ret)
105662094060SCosmin Tanislav return ret;
105762094060SCosmin Tanislav
105862094060SCosmin Tanislav ret = ad4130_set_channel_enable(st, channel, false);
105962094060SCosmin Tanislav if (ret)
106062094060SCosmin Tanislav return ret;
106162094060SCosmin Tanislav
106262094060SCosmin Tanislav return IIO_VAL_INT;
106362094060SCosmin Tanislav }
106462094060SCosmin Tanislav
ad4130_read_sample(struct iio_dev * indio_dev,unsigned int channel,int * val)106562094060SCosmin Tanislav static int ad4130_read_sample(struct iio_dev *indio_dev, unsigned int channel,
106662094060SCosmin Tanislav int *val)
106762094060SCosmin Tanislav {
106862094060SCosmin Tanislav struct ad4130_state *st = iio_priv(indio_dev);
106962094060SCosmin Tanislav int ret;
107062094060SCosmin Tanislav
107162094060SCosmin Tanislav ret = iio_device_claim_direct_mode(indio_dev);
107262094060SCosmin Tanislav if (ret)
107362094060SCosmin Tanislav return ret;
107462094060SCosmin Tanislav
107562094060SCosmin Tanislav mutex_lock(&st->lock);
107662094060SCosmin Tanislav ret = _ad4130_read_sample(indio_dev, channel, val);
107762094060SCosmin Tanislav mutex_unlock(&st->lock);
107862094060SCosmin Tanislav
107962094060SCosmin Tanislav iio_device_release_direct_mode(indio_dev);
108062094060SCosmin Tanislav
108162094060SCosmin Tanislav return ret;
108262094060SCosmin Tanislav }
108362094060SCosmin Tanislav
ad4130_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long info)108462094060SCosmin Tanislav static int ad4130_read_raw(struct iio_dev *indio_dev,
108562094060SCosmin Tanislav struct iio_chan_spec const *chan,
108662094060SCosmin Tanislav int *val, int *val2, long info)
108762094060SCosmin Tanislav {
108862094060SCosmin Tanislav struct ad4130_state *st = iio_priv(indio_dev);
108962094060SCosmin Tanislav unsigned int channel = chan->scan_index;
109062094060SCosmin Tanislav struct ad4130_setup_info *setup_info = &st->chans_info[channel].setup;
109162094060SCosmin Tanislav
109262094060SCosmin Tanislav switch (info) {
109362094060SCosmin Tanislav case IIO_CHAN_INFO_RAW:
109462094060SCosmin Tanislav return ad4130_read_sample(indio_dev, channel, val);
109562094060SCosmin Tanislav case IIO_CHAN_INFO_SCALE:
109662094060SCosmin Tanislav mutex_lock(&st->lock);
109762094060SCosmin Tanislav *val = st->scale_tbls[setup_info->ref_sel][setup_info->pga][0];
109862094060SCosmin Tanislav *val2 = st->scale_tbls[setup_info->ref_sel][setup_info->pga][1];
109962094060SCosmin Tanislav mutex_unlock(&st->lock);
110062094060SCosmin Tanislav
110162094060SCosmin Tanislav return IIO_VAL_INT_PLUS_NANO;
110262094060SCosmin Tanislav case IIO_CHAN_INFO_OFFSET:
110362094060SCosmin Tanislav *val = st->bipolar ? -BIT(chan->scan_type.realbits - 1) : 0;
110462094060SCosmin Tanislav
110562094060SCosmin Tanislav return IIO_VAL_INT;
110662094060SCosmin Tanislav case IIO_CHAN_INFO_SAMP_FREQ:
110762094060SCosmin Tanislav mutex_lock(&st->lock);
110862094060SCosmin Tanislav ad4130_fs_to_freq(setup_info->filter_mode, setup_info->fs,
110962094060SCosmin Tanislav val, val2);
111062094060SCosmin Tanislav mutex_unlock(&st->lock);
111162094060SCosmin Tanislav
111262094060SCosmin Tanislav return IIO_VAL_INT_PLUS_NANO;
111362094060SCosmin Tanislav default:
111462094060SCosmin Tanislav return -EINVAL;
111562094060SCosmin Tanislav }
111662094060SCosmin Tanislav }
111762094060SCosmin Tanislav
ad4130_read_avail(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,const int ** vals,int * type,int * length,long info)111862094060SCosmin Tanislav static int ad4130_read_avail(struct iio_dev *indio_dev,
111962094060SCosmin Tanislav struct iio_chan_spec const *chan,
112062094060SCosmin Tanislav const int **vals, int *type, int *length,
112162094060SCosmin Tanislav long info)
112262094060SCosmin Tanislav {
112362094060SCosmin Tanislav struct ad4130_state *st = iio_priv(indio_dev);
112462094060SCosmin Tanislav unsigned int channel = chan->scan_index;
112562094060SCosmin Tanislav struct ad4130_setup_info *setup_info = &st->chans_info[channel].setup;
112662094060SCosmin Tanislav const struct ad4130_filter_config *filter_config;
112762094060SCosmin Tanislav
112862094060SCosmin Tanislav switch (info) {
112962094060SCosmin Tanislav case IIO_CHAN_INFO_SCALE:
113062094060SCosmin Tanislav *vals = (int *)st->scale_tbls[setup_info->ref_sel];
113162094060SCosmin Tanislav *length = ARRAY_SIZE(st->scale_tbls[setup_info->ref_sel]) * 2;
113262094060SCosmin Tanislav
113362094060SCosmin Tanislav *type = IIO_VAL_INT_PLUS_NANO;
113462094060SCosmin Tanislav
113562094060SCosmin Tanislav return IIO_AVAIL_LIST;
113662094060SCosmin Tanislav case IIO_CHAN_INFO_SAMP_FREQ:
113762094060SCosmin Tanislav mutex_lock(&st->lock);
113862094060SCosmin Tanislav filter_config = &ad4130_filter_configs[setup_info->filter_mode];
113962094060SCosmin Tanislav mutex_unlock(&st->lock);
114062094060SCosmin Tanislav
114162094060SCosmin Tanislav *vals = (int *)filter_config->samp_freq_avail;
114262094060SCosmin Tanislav *length = filter_config->samp_freq_avail_len * 2;
114362094060SCosmin Tanislav *type = IIO_VAL_FRACTIONAL;
114462094060SCosmin Tanislav
114562094060SCosmin Tanislav return filter_config->samp_freq_avail_type;
114662094060SCosmin Tanislav default:
114762094060SCosmin Tanislav return -EINVAL;
114862094060SCosmin Tanislav }
114962094060SCosmin Tanislav }
115062094060SCosmin Tanislav
ad4130_write_raw_get_fmt(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,long info)115162094060SCosmin Tanislav static int ad4130_write_raw_get_fmt(struct iio_dev *indio_dev,
115262094060SCosmin Tanislav struct iio_chan_spec const *chan,
115362094060SCosmin Tanislav long info)
115462094060SCosmin Tanislav {
115562094060SCosmin Tanislav switch (info) {
115662094060SCosmin Tanislav case IIO_CHAN_INFO_SCALE:
115762094060SCosmin Tanislav case IIO_CHAN_INFO_SAMP_FREQ:
115862094060SCosmin Tanislav return IIO_VAL_INT_PLUS_NANO;
115962094060SCosmin Tanislav default:
116062094060SCosmin Tanislav return -EINVAL;
116162094060SCosmin Tanislav }
116262094060SCosmin Tanislav }
116362094060SCosmin Tanislav
ad4130_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long info)116462094060SCosmin Tanislav static int ad4130_write_raw(struct iio_dev *indio_dev,
116562094060SCosmin Tanislav struct iio_chan_spec const *chan,
116662094060SCosmin Tanislav int val, int val2, long info)
116762094060SCosmin Tanislav {
116862094060SCosmin Tanislav struct ad4130_state *st = iio_priv(indio_dev);
116962094060SCosmin Tanislav unsigned int channel = chan->scan_index;
117062094060SCosmin Tanislav
117162094060SCosmin Tanislav switch (info) {
117262094060SCosmin Tanislav case IIO_CHAN_INFO_SCALE:
117362094060SCosmin Tanislav return ad4130_set_channel_pga(st, channel, val, val2);
117462094060SCosmin Tanislav case IIO_CHAN_INFO_SAMP_FREQ:
117562094060SCosmin Tanislav return ad4130_set_channel_freq(st, channel, val, val2);
117662094060SCosmin Tanislav default:
117762094060SCosmin Tanislav return -EINVAL;
117862094060SCosmin Tanislav }
117962094060SCosmin Tanislav }
118062094060SCosmin Tanislav
ad4130_reg_access(struct iio_dev * indio_dev,unsigned int reg,unsigned int writeval,unsigned int * readval)118162094060SCosmin Tanislav static int ad4130_reg_access(struct iio_dev *indio_dev, unsigned int reg,
118262094060SCosmin Tanislav unsigned int writeval, unsigned int *readval)
118362094060SCosmin Tanislav {
118462094060SCosmin Tanislav struct ad4130_state *st = iio_priv(indio_dev);
118562094060SCosmin Tanislav
118662094060SCosmin Tanislav if (readval)
118762094060SCosmin Tanislav return regmap_read(st->regmap, reg, readval);
118862094060SCosmin Tanislav
118962094060SCosmin Tanislav return regmap_write(st->regmap, reg, writeval);
119062094060SCosmin Tanislav }
119162094060SCosmin Tanislav
ad4130_update_scan_mode(struct iio_dev * indio_dev,const unsigned long * scan_mask)119262094060SCosmin Tanislav static int ad4130_update_scan_mode(struct iio_dev *indio_dev,
119362094060SCosmin Tanislav const unsigned long *scan_mask)
119462094060SCosmin Tanislav {
119562094060SCosmin Tanislav struct ad4130_state *st = iio_priv(indio_dev);
119662094060SCosmin Tanislav unsigned int channel;
119762094060SCosmin Tanislav unsigned int val = 0;
119862094060SCosmin Tanislav int ret;
119962094060SCosmin Tanislav
120062094060SCosmin Tanislav mutex_lock(&st->lock);
120162094060SCosmin Tanislav
120262094060SCosmin Tanislav for_each_set_bit(channel, scan_mask, indio_dev->num_channels) {
120362094060SCosmin Tanislav ret = ad4130_set_channel_enable(st, channel, true);
120462094060SCosmin Tanislav if (ret)
120562094060SCosmin Tanislav goto out;
120662094060SCosmin Tanislav
120762094060SCosmin Tanislav val++;
120862094060SCosmin Tanislav }
120962094060SCosmin Tanislav
121062094060SCosmin Tanislav st->num_enabled_channels = val;
121162094060SCosmin Tanislav
121262094060SCosmin Tanislav out:
121362094060SCosmin Tanislav mutex_unlock(&st->lock);
121462094060SCosmin Tanislav
121562094060SCosmin Tanislav return 0;
121662094060SCosmin Tanislav }
121762094060SCosmin Tanislav
ad4130_set_fifo_watermark(struct iio_dev * indio_dev,unsigned int val)121862094060SCosmin Tanislav static int ad4130_set_fifo_watermark(struct iio_dev *indio_dev, unsigned int val)
121962094060SCosmin Tanislav {
122062094060SCosmin Tanislav struct ad4130_state *st = iio_priv(indio_dev);
122162094060SCosmin Tanislav unsigned int eff;
122262094060SCosmin Tanislav int ret;
122362094060SCosmin Tanislav
122462094060SCosmin Tanislav if (val > AD4130_FIFO_SIZE)
122562094060SCosmin Tanislav return -EINVAL;
122662094060SCosmin Tanislav
122762094060SCosmin Tanislav eff = val * st->num_enabled_channels;
122862094060SCosmin Tanislav if (eff > AD4130_FIFO_SIZE)
122962094060SCosmin Tanislav /*
123062094060SCosmin Tanislav * Always set watermark to a multiple of the number of
123162094060SCosmin Tanislav * enabled channels to avoid making the FIFO unaligned.
123262094060SCosmin Tanislav */
123362094060SCosmin Tanislav eff = rounddown(AD4130_FIFO_SIZE, st->num_enabled_channels);
123462094060SCosmin Tanislav
123562094060SCosmin Tanislav mutex_lock(&st->lock);
123662094060SCosmin Tanislav
123762094060SCosmin Tanislav ret = regmap_update_bits(st->regmap, AD4130_FIFO_CONTROL_REG,
123862094060SCosmin Tanislav AD4130_FIFO_CONTROL_WM_MASK,
123962094060SCosmin Tanislav FIELD_PREP(AD4130_FIFO_CONTROL_WM_MASK,
124062094060SCosmin Tanislav ad4130_watermark_reg_val(eff)));
124162094060SCosmin Tanislav if (ret)
124262094060SCosmin Tanislav goto out;
124362094060SCosmin Tanislav
124462094060SCosmin Tanislav st->effective_watermark = eff;
124562094060SCosmin Tanislav st->watermark = val;
124662094060SCosmin Tanislav
124762094060SCosmin Tanislav out:
124862094060SCosmin Tanislav mutex_unlock(&st->lock);
124962094060SCosmin Tanislav
125062094060SCosmin Tanislav return ret;
125162094060SCosmin Tanislav }
125262094060SCosmin Tanislav
125362094060SCosmin Tanislav static const struct iio_info ad4130_info = {
125462094060SCosmin Tanislav .read_raw = ad4130_read_raw,
125562094060SCosmin Tanislav .read_avail = ad4130_read_avail,
125662094060SCosmin Tanislav .write_raw_get_fmt = ad4130_write_raw_get_fmt,
125762094060SCosmin Tanislav .write_raw = ad4130_write_raw,
125862094060SCosmin Tanislav .update_scan_mode = ad4130_update_scan_mode,
125962094060SCosmin Tanislav .hwfifo_set_watermark = ad4130_set_fifo_watermark,
126062094060SCosmin Tanislav .debugfs_reg_access = ad4130_reg_access,
126162094060SCosmin Tanislav };
126262094060SCosmin Tanislav
ad4130_buffer_postenable(struct iio_dev * indio_dev)126362094060SCosmin Tanislav static int ad4130_buffer_postenable(struct iio_dev *indio_dev)
126462094060SCosmin Tanislav {
126562094060SCosmin Tanislav struct ad4130_state *st = iio_priv(indio_dev);
126662094060SCosmin Tanislav int ret;
126762094060SCosmin Tanislav
126862094060SCosmin Tanislav mutex_lock(&st->lock);
126962094060SCosmin Tanislav
127062094060SCosmin Tanislav ret = ad4130_set_watermark_interrupt_en(st, true);
127162094060SCosmin Tanislav if (ret)
127262094060SCosmin Tanislav goto out;
127362094060SCosmin Tanislav
127462094060SCosmin Tanislav ret = irq_set_irq_type(st->spi->irq, st->inv_irq_trigger);
127562094060SCosmin Tanislav if (ret)
127662094060SCosmin Tanislav goto out;
127762094060SCosmin Tanislav
127862094060SCosmin Tanislav ret = ad4130_set_fifo_mode(st, AD4130_FIFO_MODE_WM);
127962094060SCosmin Tanislav if (ret)
128062094060SCosmin Tanislav goto out;
128162094060SCosmin Tanislav
128262094060SCosmin Tanislav ret = ad4130_set_mode(st, AD4130_MODE_CONTINUOUS);
128362094060SCosmin Tanislav
128462094060SCosmin Tanislav out:
128562094060SCosmin Tanislav mutex_unlock(&st->lock);
128662094060SCosmin Tanislav
128762094060SCosmin Tanislav return ret;
128862094060SCosmin Tanislav }
128962094060SCosmin Tanislav
ad4130_buffer_predisable(struct iio_dev * indio_dev)129062094060SCosmin Tanislav static int ad4130_buffer_predisable(struct iio_dev *indio_dev)
129162094060SCosmin Tanislav {
129262094060SCosmin Tanislav struct ad4130_state *st = iio_priv(indio_dev);
129362094060SCosmin Tanislav unsigned int i;
129462094060SCosmin Tanislav int ret;
129562094060SCosmin Tanislav
129662094060SCosmin Tanislav mutex_lock(&st->lock);
129762094060SCosmin Tanislav
129862094060SCosmin Tanislav ret = ad4130_set_mode(st, AD4130_MODE_IDLE);
129962094060SCosmin Tanislav if (ret)
130062094060SCosmin Tanislav goto out;
130162094060SCosmin Tanislav
130262094060SCosmin Tanislav ret = irq_set_irq_type(st->spi->irq, st->irq_trigger);
130362094060SCosmin Tanislav if (ret)
130462094060SCosmin Tanislav goto out;
130562094060SCosmin Tanislav
130662094060SCosmin Tanislav ret = ad4130_set_fifo_mode(st, AD4130_FIFO_MODE_DISABLED);
130762094060SCosmin Tanislav if (ret)
130862094060SCosmin Tanislav goto out;
130962094060SCosmin Tanislav
131062094060SCosmin Tanislav ret = ad4130_set_watermark_interrupt_en(st, false);
131162094060SCosmin Tanislav if (ret)
131262094060SCosmin Tanislav goto out;
131362094060SCosmin Tanislav
131462094060SCosmin Tanislav /*
131562094060SCosmin Tanislav * update_scan_mode() is not called in the disable path, disable all
131662094060SCosmin Tanislav * channels here.
131762094060SCosmin Tanislav */
131862094060SCosmin Tanislav for (i = 0; i < indio_dev->num_channels; i++) {
131962094060SCosmin Tanislav ret = ad4130_set_channel_enable(st, i, false);
132062094060SCosmin Tanislav if (ret)
132162094060SCosmin Tanislav goto out;
132262094060SCosmin Tanislav }
132362094060SCosmin Tanislav
132462094060SCosmin Tanislav out:
132562094060SCosmin Tanislav mutex_unlock(&st->lock);
132662094060SCosmin Tanislav
132762094060SCosmin Tanislav return ret;
132862094060SCosmin Tanislav }
132962094060SCosmin Tanislav
133062094060SCosmin Tanislav static const struct iio_buffer_setup_ops ad4130_buffer_ops = {
133162094060SCosmin Tanislav .postenable = ad4130_buffer_postenable,
133262094060SCosmin Tanislav .predisable = ad4130_buffer_predisable,
133362094060SCosmin Tanislav };
133462094060SCosmin Tanislav
hwfifo_watermark_show(struct device * dev,struct device_attribute * attr,char * buf)133562094060SCosmin Tanislav static ssize_t hwfifo_watermark_show(struct device *dev,
133662094060SCosmin Tanislav struct device_attribute *attr, char *buf)
133762094060SCosmin Tanislav {
133862094060SCosmin Tanislav struct ad4130_state *st = iio_priv(dev_to_iio_dev(dev));
133962094060SCosmin Tanislav unsigned int val;
134062094060SCosmin Tanislav
134162094060SCosmin Tanislav mutex_lock(&st->lock);
134262094060SCosmin Tanislav val = st->watermark;
134362094060SCosmin Tanislav mutex_unlock(&st->lock);
134462094060SCosmin Tanislav
134562094060SCosmin Tanislav return sysfs_emit(buf, "%d\n", val);
134662094060SCosmin Tanislav }
134762094060SCosmin Tanislav
hwfifo_enabled_show(struct device * dev,struct device_attribute * attr,char * buf)134862094060SCosmin Tanislav static ssize_t hwfifo_enabled_show(struct device *dev,
134962094060SCosmin Tanislav struct device_attribute *attr, char *buf)
135062094060SCosmin Tanislav {
135162094060SCosmin Tanislav struct ad4130_state *st = iio_priv(dev_to_iio_dev(dev));
135262094060SCosmin Tanislav unsigned int val;
135362094060SCosmin Tanislav int ret;
135462094060SCosmin Tanislav
135562094060SCosmin Tanislav ret = regmap_read(st->regmap, AD4130_FIFO_CONTROL_REG, &val);
135662094060SCosmin Tanislav if (ret)
135762094060SCosmin Tanislav return ret;
135862094060SCosmin Tanislav
135962094060SCosmin Tanislav val = FIELD_GET(AD4130_FIFO_CONTROL_MODE_MASK, val);
136062094060SCosmin Tanislav
136162094060SCosmin Tanislav return sysfs_emit(buf, "%d\n", val != AD4130_FIFO_MODE_DISABLED);
136262094060SCosmin Tanislav }
136362094060SCosmin Tanislav
hwfifo_watermark_min_show(struct device * dev,struct device_attribute * attr,char * buf)136462094060SCosmin Tanislav static ssize_t hwfifo_watermark_min_show(struct device *dev,
136562094060SCosmin Tanislav struct device_attribute *attr,
136662094060SCosmin Tanislav char *buf)
136762094060SCosmin Tanislav {
136862094060SCosmin Tanislav return sysfs_emit(buf, "%s\n", "1");
136962094060SCosmin Tanislav }
137062094060SCosmin Tanislav
hwfifo_watermark_max_show(struct device * dev,struct device_attribute * attr,char * buf)137162094060SCosmin Tanislav static ssize_t hwfifo_watermark_max_show(struct device *dev,
137262094060SCosmin Tanislav struct device_attribute *attr,
137362094060SCosmin Tanislav char *buf)
137462094060SCosmin Tanislav {
137562094060SCosmin Tanislav return sysfs_emit(buf, "%s\n", __stringify(AD4130_FIFO_SIZE));
137662094060SCosmin Tanislav }
137762094060SCosmin Tanislav
137862094060SCosmin Tanislav static IIO_DEVICE_ATTR_RO(hwfifo_watermark_min, 0);
137962094060SCosmin Tanislav static IIO_DEVICE_ATTR_RO(hwfifo_watermark_max, 0);
138062094060SCosmin Tanislav static IIO_DEVICE_ATTR_RO(hwfifo_watermark, 0);
138162094060SCosmin Tanislav static IIO_DEVICE_ATTR_RO(hwfifo_enabled, 0);
138262094060SCosmin Tanislav
13830a33755cSMatti Vaittinen static const struct iio_dev_attr *ad4130_fifo_attributes[] = {
13840a33755cSMatti Vaittinen &iio_dev_attr_hwfifo_watermark_min,
13850a33755cSMatti Vaittinen &iio_dev_attr_hwfifo_watermark_max,
13860a33755cSMatti Vaittinen &iio_dev_attr_hwfifo_watermark,
13870a33755cSMatti Vaittinen &iio_dev_attr_hwfifo_enabled,
138862094060SCosmin Tanislav NULL
138962094060SCosmin Tanislav };
139062094060SCosmin Tanislav
_ad4130_find_table_index(const unsigned int * tbl,size_t len,unsigned int val)139162094060SCosmin Tanislav static int _ad4130_find_table_index(const unsigned int *tbl, size_t len,
139262094060SCosmin Tanislav unsigned int val)
139362094060SCosmin Tanislav {
139462094060SCosmin Tanislav unsigned int i;
139562094060SCosmin Tanislav
139662094060SCosmin Tanislav for (i = 0; i < len; i++)
139762094060SCosmin Tanislav if (tbl[i] == val)
139862094060SCosmin Tanislav return i;
139962094060SCosmin Tanislav
140062094060SCosmin Tanislav return -EINVAL;
140162094060SCosmin Tanislav }
140262094060SCosmin Tanislav
140362094060SCosmin Tanislav #define ad4130_find_table_index(table, val) \
140462094060SCosmin Tanislav _ad4130_find_table_index(table, ARRAY_SIZE(table), val)
140562094060SCosmin Tanislav
ad4130_get_ref_voltage(struct ad4130_state * st,enum ad4130_ref_sel ref_sel)140662094060SCosmin Tanislav static int ad4130_get_ref_voltage(struct ad4130_state *st,
140762094060SCosmin Tanislav enum ad4130_ref_sel ref_sel)
140862094060SCosmin Tanislav {
140962094060SCosmin Tanislav switch (ref_sel) {
141062094060SCosmin Tanislav case AD4130_REF_REFIN1:
141162094060SCosmin Tanislav return regulator_get_voltage(st->regulators[2].consumer);
141262094060SCosmin Tanislav case AD4130_REF_REFIN2:
141362094060SCosmin Tanislav return regulator_get_voltage(st->regulators[3].consumer);
141462094060SCosmin Tanislav case AD4130_REF_AVDD_AVSS:
141562094060SCosmin Tanislav return regulator_get_voltage(st->regulators[0].consumer);
141662094060SCosmin Tanislav case AD4130_REF_REFOUT_AVSS:
141762094060SCosmin Tanislav return st->int_ref_uv;
141862094060SCosmin Tanislav default:
141962094060SCosmin Tanislav return -EINVAL;
142062094060SCosmin Tanislav }
142162094060SCosmin Tanislav }
142262094060SCosmin Tanislav
ad4130_parse_fw_setup(struct ad4130_state * st,struct fwnode_handle * child,struct ad4130_setup_info * setup_info)142362094060SCosmin Tanislav static int ad4130_parse_fw_setup(struct ad4130_state *st,
142462094060SCosmin Tanislav struct fwnode_handle *child,
142562094060SCosmin Tanislav struct ad4130_setup_info *setup_info)
142662094060SCosmin Tanislav {
142762094060SCosmin Tanislav struct device *dev = &st->spi->dev;
142862094060SCosmin Tanislav u32 tmp;
142962094060SCosmin Tanislav int ret;
143062094060SCosmin Tanislav
143162094060SCosmin Tanislav tmp = 0;
143262094060SCosmin Tanislav fwnode_property_read_u32(child, "adi,excitation-current-0-nanoamp", &tmp);
143362094060SCosmin Tanislav ret = ad4130_find_table_index(ad4130_iout_current_na_tbl, tmp);
143462094060SCosmin Tanislav if (ret < 0)
143562094060SCosmin Tanislav return dev_err_probe(dev, ret,
143662094060SCosmin Tanislav "Invalid excitation current %unA\n", tmp);
143762094060SCosmin Tanislav setup_info->iout0_val = ret;
143862094060SCosmin Tanislav
143962094060SCosmin Tanislav tmp = 0;
144062094060SCosmin Tanislav fwnode_property_read_u32(child, "adi,excitation-current-1-nanoamp", &tmp);
144162094060SCosmin Tanislav ret = ad4130_find_table_index(ad4130_iout_current_na_tbl, tmp);
144262094060SCosmin Tanislav if (ret < 0)
144362094060SCosmin Tanislav return dev_err_probe(dev, ret,
144462094060SCosmin Tanislav "Invalid excitation current %unA\n", tmp);
144562094060SCosmin Tanislav setup_info->iout1_val = ret;
144662094060SCosmin Tanislav
144762094060SCosmin Tanislav tmp = 0;
144862094060SCosmin Tanislav fwnode_property_read_u32(child, "adi,burnout-current-nanoamp", &tmp);
144962094060SCosmin Tanislav ret = ad4130_find_table_index(ad4130_burnout_current_na_tbl, tmp);
145062094060SCosmin Tanislav if (ret < 0)
145162094060SCosmin Tanislav return dev_err_probe(dev, ret,
145262094060SCosmin Tanislav "Invalid burnout current %unA\n", tmp);
145362094060SCosmin Tanislav setup_info->burnout = ret;
145462094060SCosmin Tanislav
145562094060SCosmin Tanislav setup_info->ref_bufp = fwnode_property_read_bool(child, "adi,buffered-positive");
145662094060SCosmin Tanislav setup_info->ref_bufm = fwnode_property_read_bool(child, "adi,buffered-negative");
145762094060SCosmin Tanislav
145862094060SCosmin Tanislav setup_info->ref_sel = AD4130_REF_REFIN1;
145962094060SCosmin Tanislav fwnode_property_read_u32(child, "adi,reference-select",
146062094060SCosmin Tanislav &setup_info->ref_sel);
146162094060SCosmin Tanislav if (setup_info->ref_sel >= AD4130_REF_SEL_MAX)
146262094060SCosmin Tanislav return dev_err_probe(dev, -EINVAL,
146362094060SCosmin Tanislav "Invalid reference selected %u\n",
146462094060SCosmin Tanislav setup_info->ref_sel);
146562094060SCosmin Tanislav
146662094060SCosmin Tanislav if (setup_info->ref_sel == AD4130_REF_REFOUT_AVSS)
146762094060SCosmin Tanislav st->int_ref_en = true;
146862094060SCosmin Tanislav
146962094060SCosmin Tanislav ret = ad4130_get_ref_voltage(st, setup_info->ref_sel);
147062094060SCosmin Tanislav if (ret < 0)
147162094060SCosmin Tanislav return dev_err_probe(dev, ret, "Cannot use reference %u\n",
147262094060SCosmin Tanislav setup_info->ref_sel);
147362094060SCosmin Tanislav
147462094060SCosmin Tanislav return 0;
147562094060SCosmin Tanislav }
147662094060SCosmin Tanislav
ad4130_validate_diff_channel(struct ad4130_state * st,u32 pin)147762094060SCosmin Tanislav static int ad4130_validate_diff_channel(struct ad4130_state *st, u32 pin)
147862094060SCosmin Tanislav {
147962094060SCosmin Tanislav struct device *dev = &st->spi->dev;
148062094060SCosmin Tanislav
148162094060SCosmin Tanislav if (pin >= AD4130_MAX_DIFF_INPUTS)
148262094060SCosmin Tanislav return dev_err_probe(dev, -EINVAL,
14836abcb19eSColin Ian King "Invalid differential channel %u\n", pin);
148462094060SCosmin Tanislav
148562094060SCosmin Tanislav if (pin >= AD4130_MAX_ANALOG_PINS)
148662094060SCosmin Tanislav return 0;
148762094060SCosmin Tanislav
148862094060SCosmin Tanislav if (st->pins_fn[pin] == AD4130_PIN_FN_SPECIAL)
148962094060SCosmin Tanislav return dev_err_probe(dev, -EINVAL,
149062094060SCosmin Tanislav "Pin %u already used with fn %u\n", pin,
149162094060SCosmin Tanislav st->pins_fn[pin]);
149262094060SCosmin Tanislav
149362094060SCosmin Tanislav st->pins_fn[pin] |= AD4130_PIN_FN_DIFF;
149462094060SCosmin Tanislav
149562094060SCosmin Tanislav return 0;
149662094060SCosmin Tanislav }
149762094060SCosmin Tanislav
ad4130_validate_diff_channels(struct ad4130_state * st,u32 * pins,unsigned int len)149862094060SCosmin Tanislav static int ad4130_validate_diff_channels(struct ad4130_state *st,
149962094060SCosmin Tanislav u32 *pins, unsigned int len)
150062094060SCosmin Tanislav {
150162094060SCosmin Tanislav unsigned int i;
150262094060SCosmin Tanislav int ret;
150362094060SCosmin Tanislav
150462094060SCosmin Tanislav for (i = 0; i < len; i++) {
150562094060SCosmin Tanislav ret = ad4130_validate_diff_channel(st, pins[i]);
150662094060SCosmin Tanislav if (ret)
150762094060SCosmin Tanislav return ret;
150862094060SCosmin Tanislav }
150962094060SCosmin Tanislav
151062094060SCosmin Tanislav return 0;
151162094060SCosmin Tanislav }
151262094060SCosmin Tanislav
ad4130_validate_excitation_pin(struct ad4130_state * st,u32 pin)151362094060SCosmin Tanislav static int ad4130_validate_excitation_pin(struct ad4130_state *st, u32 pin)
151462094060SCosmin Tanislav {
151562094060SCosmin Tanislav struct device *dev = &st->spi->dev;
151662094060SCosmin Tanislav
151762094060SCosmin Tanislav if (pin >= AD4130_MAX_ANALOG_PINS)
151862094060SCosmin Tanislav return dev_err_probe(dev, -EINVAL,
151962094060SCosmin Tanislav "Invalid excitation pin %u\n", pin);
152062094060SCosmin Tanislav
152162094060SCosmin Tanislav if (st->pins_fn[pin] == AD4130_PIN_FN_SPECIAL)
152262094060SCosmin Tanislav return dev_err_probe(dev, -EINVAL,
152362094060SCosmin Tanislav "Pin %u already used with fn %u\n", pin,
152462094060SCosmin Tanislav st->pins_fn[pin]);
152562094060SCosmin Tanislav
152662094060SCosmin Tanislav st->pins_fn[pin] |= AD4130_PIN_FN_EXCITATION;
152762094060SCosmin Tanislav
152862094060SCosmin Tanislav return 0;
152962094060SCosmin Tanislav }
153062094060SCosmin Tanislav
ad4130_validate_vbias_pin(struct ad4130_state * st,u32 pin)153162094060SCosmin Tanislav static int ad4130_validate_vbias_pin(struct ad4130_state *st, u32 pin)
153262094060SCosmin Tanislav {
153362094060SCosmin Tanislav struct device *dev = &st->spi->dev;
153462094060SCosmin Tanislav
153562094060SCosmin Tanislav if (pin >= AD4130_MAX_ANALOG_PINS)
153662094060SCosmin Tanislav return dev_err_probe(dev, -EINVAL, "Invalid vbias pin %u\n",
153762094060SCosmin Tanislav pin);
153862094060SCosmin Tanislav
153962094060SCosmin Tanislav if (st->pins_fn[pin] == AD4130_PIN_FN_SPECIAL)
154062094060SCosmin Tanislav return dev_err_probe(dev, -EINVAL,
154162094060SCosmin Tanislav "Pin %u already used with fn %u\n", pin,
154262094060SCosmin Tanislav st->pins_fn[pin]);
154362094060SCosmin Tanislav
154462094060SCosmin Tanislav st->pins_fn[pin] |= AD4130_PIN_FN_VBIAS;
154562094060SCosmin Tanislav
154662094060SCosmin Tanislav return 0;
154762094060SCosmin Tanislav }
154862094060SCosmin Tanislav
ad4130_validate_vbias_pins(struct ad4130_state * st,u32 * pins,unsigned int len)154962094060SCosmin Tanislav static int ad4130_validate_vbias_pins(struct ad4130_state *st,
155062094060SCosmin Tanislav u32 *pins, unsigned int len)
155162094060SCosmin Tanislav {
155262094060SCosmin Tanislav unsigned int i;
155362094060SCosmin Tanislav int ret;
155462094060SCosmin Tanislav
155562094060SCosmin Tanislav for (i = 0; i < st->num_vbias_pins; i++) {
155662094060SCosmin Tanislav ret = ad4130_validate_vbias_pin(st, pins[i]);
155762094060SCosmin Tanislav if (ret)
155862094060SCosmin Tanislav return ret;
155962094060SCosmin Tanislav }
156062094060SCosmin Tanislav
156162094060SCosmin Tanislav return 0;
156262094060SCosmin Tanislav }
156362094060SCosmin Tanislav
ad4130_parse_fw_channel(struct iio_dev * indio_dev,struct fwnode_handle * child)156462094060SCosmin Tanislav static int ad4130_parse_fw_channel(struct iio_dev *indio_dev,
156562094060SCosmin Tanislav struct fwnode_handle *child)
156662094060SCosmin Tanislav {
156762094060SCosmin Tanislav struct ad4130_state *st = iio_priv(indio_dev);
156862094060SCosmin Tanislav unsigned int resolution = ad4130_resolution(st);
156962094060SCosmin Tanislav unsigned int index = indio_dev->num_channels++;
157062094060SCosmin Tanislav struct device *dev = &st->spi->dev;
157162094060SCosmin Tanislav struct ad4130_chan_info *chan_info;
157262094060SCosmin Tanislav struct iio_chan_spec *chan;
157362094060SCosmin Tanislav u32 pins[2];
157462094060SCosmin Tanislav int ret;
157562094060SCosmin Tanislav
157662094060SCosmin Tanislav if (index >= AD4130_MAX_CHANNELS)
157762094060SCosmin Tanislav return dev_err_probe(dev, -EINVAL, "Too many channels\n");
157862094060SCosmin Tanislav
157962094060SCosmin Tanislav chan = &st->chans[index];
158062094060SCosmin Tanislav chan_info = &st->chans_info[index];
158162094060SCosmin Tanislav
158262094060SCosmin Tanislav *chan = ad4130_channel_template;
158362094060SCosmin Tanislav chan->scan_type.realbits = resolution;
158462094060SCosmin Tanislav chan->scan_type.storagebits = resolution;
158562094060SCosmin Tanislav chan->scan_index = index;
158662094060SCosmin Tanislav
158762094060SCosmin Tanislav chan_info->slot = AD4130_INVALID_SLOT;
158862094060SCosmin Tanislav chan_info->setup.fs = AD4130_FILTER_SELECT_MIN;
158962094060SCosmin Tanislav chan_info->initialized = true;
159062094060SCosmin Tanislav
159162094060SCosmin Tanislav ret = fwnode_property_read_u32_array(child, "diff-channels", pins,
159262094060SCosmin Tanislav ARRAY_SIZE(pins));
159362094060SCosmin Tanislav if (ret)
159462094060SCosmin Tanislav return ret;
159562094060SCosmin Tanislav
159662094060SCosmin Tanislav ret = ad4130_validate_diff_channels(st, pins, ARRAY_SIZE(pins));
159762094060SCosmin Tanislav if (ret)
159862094060SCosmin Tanislav return ret;
159962094060SCosmin Tanislav
160062094060SCosmin Tanislav chan->channel = pins[0];
160162094060SCosmin Tanislav chan->channel2 = pins[1];
160262094060SCosmin Tanislav
160362094060SCosmin Tanislav ret = ad4130_parse_fw_setup(st, child, &chan_info->setup);
160462094060SCosmin Tanislav if (ret)
160562094060SCosmin Tanislav return ret;
160662094060SCosmin Tanislav
160762094060SCosmin Tanislav fwnode_property_read_u32(child, "adi,excitation-pin-0",
160862094060SCosmin Tanislav &chan_info->iout0);
160962094060SCosmin Tanislav if (chan_info->setup.iout0_val != AD4130_IOUT_OFF) {
161062094060SCosmin Tanislav ret = ad4130_validate_excitation_pin(st, chan_info->iout0);
161162094060SCosmin Tanislav if (ret)
161262094060SCosmin Tanislav return ret;
161362094060SCosmin Tanislav }
161462094060SCosmin Tanislav
161562094060SCosmin Tanislav fwnode_property_read_u32(child, "adi,excitation-pin-1",
161662094060SCosmin Tanislav &chan_info->iout1);
161762094060SCosmin Tanislav if (chan_info->setup.iout1_val != AD4130_IOUT_OFF) {
161862094060SCosmin Tanislav ret = ad4130_validate_excitation_pin(st, chan_info->iout1);
161962094060SCosmin Tanislav if (ret)
162062094060SCosmin Tanislav return ret;
162162094060SCosmin Tanislav }
162262094060SCosmin Tanislav
162362094060SCosmin Tanislav return 0;
162462094060SCosmin Tanislav }
162562094060SCosmin Tanislav
ad4130_parse_fw_children(struct iio_dev * indio_dev)162662094060SCosmin Tanislav static int ad4130_parse_fw_children(struct iio_dev *indio_dev)
162762094060SCosmin Tanislav {
162862094060SCosmin Tanislav struct ad4130_state *st = iio_priv(indio_dev);
162962094060SCosmin Tanislav struct device *dev = &st->spi->dev;
163062094060SCosmin Tanislav struct fwnode_handle *child;
163162094060SCosmin Tanislav int ret;
163262094060SCosmin Tanislav
163362094060SCosmin Tanislav indio_dev->channels = st->chans;
163462094060SCosmin Tanislav
163562094060SCosmin Tanislav device_for_each_child_node(dev, child) {
163662094060SCosmin Tanislav ret = ad4130_parse_fw_channel(indio_dev, child);
163762094060SCosmin Tanislav if (ret) {
163862094060SCosmin Tanislav fwnode_handle_put(child);
163962094060SCosmin Tanislav return ret;
164062094060SCosmin Tanislav }
164162094060SCosmin Tanislav }
164262094060SCosmin Tanislav
164362094060SCosmin Tanislav return 0;
164462094060SCosmin Tanislav }
164562094060SCosmin Tanislav
ad4310_parse_fw(struct iio_dev * indio_dev)164662094060SCosmin Tanislav static int ad4310_parse_fw(struct iio_dev *indio_dev)
164762094060SCosmin Tanislav {
164862094060SCosmin Tanislav struct ad4130_state *st = iio_priv(indio_dev);
164962094060SCosmin Tanislav struct device *dev = &st->spi->dev;
165062094060SCosmin Tanislav u32 ext_clk_freq = AD4130_MCLK_FREQ_76_8KHZ;
165162094060SCosmin Tanislav unsigned int i;
165262094060SCosmin Tanislav int avdd_uv;
165362094060SCosmin Tanislav int irq;
165462094060SCosmin Tanislav int ret;
165562094060SCosmin Tanislav
165662094060SCosmin Tanislav st->mclk = devm_clk_get_optional(dev, "mclk");
165762094060SCosmin Tanislav if (IS_ERR(st->mclk))
165862094060SCosmin Tanislav return dev_err_probe(dev, PTR_ERR(st->mclk),
165962094060SCosmin Tanislav "Failed to get mclk\n");
166062094060SCosmin Tanislav
166162094060SCosmin Tanislav st->int_pin_sel = AD4130_INT_PIN_INT;
166262094060SCosmin Tanislav
166362094060SCosmin Tanislav for (i = 0; i < ARRAY_SIZE(ad4130_int_pin_names); i++) {
166462094060SCosmin Tanislav irq = fwnode_irq_get_byname(dev_fwnode(dev),
166562094060SCosmin Tanislav ad4130_int_pin_names[i]);
166662094060SCosmin Tanislav if (irq > 0) {
166762094060SCosmin Tanislav st->int_pin_sel = i;
166862094060SCosmin Tanislav break;
166962094060SCosmin Tanislav }
167062094060SCosmin Tanislav }
167162094060SCosmin Tanislav
167262094060SCosmin Tanislav if (st->int_pin_sel == AD4130_INT_PIN_DOUT)
167362094060SCosmin Tanislav return dev_err_probe(dev, -EINVAL,
167462094060SCosmin Tanislav "Cannot use DOUT as interrupt pin\n");
167562094060SCosmin Tanislav
167662094060SCosmin Tanislav if (st->int_pin_sel == AD4130_INT_PIN_P2)
167762094060SCosmin Tanislav st->pins_fn[AD4130_AIN3_P2] = AD4130_PIN_FN_SPECIAL;
167862094060SCosmin Tanislav
167962094060SCosmin Tanislav device_property_read_u32(dev, "adi,ext-clk-freq-hz", &ext_clk_freq);
168062094060SCosmin Tanislav if (ext_clk_freq != AD4130_MCLK_FREQ_153_6KHZ &&
168162094060SCosmin Tanislav ext_clk_freq != AD4130_MCLK_FREQ_76_8KHZ)
168262094060SCosmin Tanislav return dev_err_probe(dev, -EINVAL,
168362094060SCosmin Tanislav "Invalid external clock frequency %u\n",
168462094060SCosmin Tanislav ext_clk_freq);
168562094060SCosmin Tanislav
168662094060SCosmin Tanislav if (st->mclk && ext_clk_freq == AD4130_MCLK_FREQ_153_6KHZ)
168762094060SCosmin Tanislav st->mclk_sel = AD4130_MCLK_153_6KHZ_EXT;
168862094060SCosmin Tanislav else if (st->mclk)
168962094060SCosmin Tanislav st->mclk_sel = AD4130_MCLK_76_8KHZ_EXT;
169062094060SCosmin Tanislav else
169162094060SCosmin Tanislav st->mclk_sel = AD4130_MCLK_76_8KHZ;
169262094060SCosmin Tanislav
169362094060SCosmin Tanislav if (st->int_pin_sel == AD4130_INT_PIN_CLK &&
169462094060SCosmin Tanislav st->mclk_sel != AD4130_MCLK_76_8KHZ)
169562094060SCosmin Tanislav return dev_err_probe(dev, -EINVAL,
169662094060SCosmin Tanislav "Invalid clock %u for interrupt pin %u\n",
169762094060SCosmin Tanislav st->mclk_sel, st->int_pin_sel);
169862094060SCosmin Tanislav
169962094060SCosmin Tanislav st->int_ref_uv = AD4130_INT_REF_2_5V;
170062094060SCosmin Tanislav
170162094060SCosmin Tanislav /*
170262094060SCosmin Tanislav * When the AVDD supply is set to below 2.5V the internal reference of
170362094060SCosmin Tanislav * 1.25V should be selected.
170462094060SCosmin Tanislav * See datasheet page 37, section ADC REFERENCE.
170562094060SCosmin Tanislav */
170662094060SCosmin Tanislav avdd_uv = regulator_get_voltage(st->regulators[0].consumer);
170762094060SCosmin Tanislav if (avdd_uv > 0 && avdd_uv < AD4130_INT_REF_2_5V)
170862094060SCosmin Tanislav st->int_ref_uv = AD4130_INT_REF_1_25V;
170962094060SCosmin Tanislav
171062094060SCosmin Tanislav st->bipolar = device_property_read_bool(dev, "adi,bipolar");
171162094060SCosmin Tanislav
171262094060SCosmin Tanislav ret = device_property_count_u32(dev, "adi,vbias-pins");
171362094060SCosmin Tanislav if (ret > 0) {
171462094060SCosmin Tanislav if (ret > AD4130_MAX_ANALOG_PINS)
171562094060SCosmin Tanislav return dev_err_probe(dev, -EINVAL,
171662094060SCosmin Tanislav "Too many vbias pins %u\n", ret);
171762094060SCosmin Tanislav
171862094060SCosmin Tanislav st->num_vbias_pins = ret;
171962094060SCosmin Tanislav
172062094060SCosmin Tanislav ret = device_property_read_u32_array(dev, "adi,vbias-pins",
172162094060SCosmin Tanislav st->vbias_pins,
172262094060SCosmin Tanislav st->num_vbias_pins);
172362094060SCosmin Tanislav if (ret)
172462094060SCosmin Tanislav return dev_err_probe(dev, ret,
172562094060SCosmin Tanislav "Failed to read vbias pins\n");
172662094060SCosmin Tanislav
172762094060SCosmin Tanislav ret = ad4130_validate_vbias_pins(st, st->vbias_pins,
172862094060SCosmin Tanislav st->num_vbias_pins);
172962094060SCosmin Tanislav if (ret)
173062094060SCosmin Tanislav return ret;
173162094060SCosmin Tanislav }
173262094060SCosmin Tanislav
173362094060SCosmin Tanislav ret = ad4130_parse_fw_children(indio_dev);
173462094060SCosmin Tanislav if (ret)
173562094060SCosmin Tanislav return ret;
173662094060SCosmin Tanislav
173762094060SCosmin Tanislav return 0;
173862094060SCosmin Tanislav }
173962094060SCosmin Tanislav
ad4130_fill_scale_tbls(struct ad4130_state * st)174062094060SCosmin Tanislav static void ad4130_fill_scale_tbls(struct ad4130_state *st)
174162094060SCosmin Tanislav {
174262094060SCosmin Tanislav unsigned int pow = ad4130_resolution(st) - st->bipolar;
174362094060SCosmin Tanislav unsigned int i, j;
174462094060SCosmin Tanislav
174562094060SCosmin Tanislav for (i = 0; i < AD4130_REF_SEL_MAX; i++) {
174662094060SCosmin Tanislav int ret;
174762094060SCosmin Tanislav u64 nv;
174862094060SCosmin Tanislav
174962094060SCosmin Tanislav ret = ad4130_get_ref_voltage(st, i);
175062094060SCosmin Tanislav if (ret < 0)
175162094060SCosmin Tanislav continue;
175262094060SCosmin Tanislav
175362094060SCosmin Tanislav nv = (u64)ret * NANO;
175462094060SCosmin Tanislav
175562094060SCosmin Tanislav for (j = 0; j < AD4130_MAX_PGA; j++)
175662094060SCosmin Tanislav st->scale_tbls[i][j][1] = div_u64(nv >> (pow + j), MILLI);
175762094060SCosmin Tanislav }
175862094060SCosmin Tanislav }
175962094060SCosmin Tanislav
ad4130_clk_disable_unprepare(void * clk)176062094060SCosmin Tanislav static void ad4130_clk_disable_unprepare(void *clk)
176162094060SCosmin Tanislav {
176262094060SCosmin Tanislav clk_disable_unprepare(clk);
176362094060SCosmin Tanislav }
176462094060SCosmin Tanislav
ad4130_set_mclk_sel(struct ad4130_state * st,enum ad4130_mclk_sel mclk_sel)176562094060SCosmin Tanislav static int ad4130_set_mclk_sel(struct ad4130_state *st,
176662094060SCosmin Tanislav enum ad4130_mclk_sel mclk_sel)
176762094060SCosmin Tanislav {
176862094060SCosmin Tanislav return regmap_update_bits(st->regmap, AD4130_ADC_CONTROL_REG,
176962094060SCosmin Tanislav AD4130_ADC_CONTROL_MCLK_SEL_MASK,
177062094060SCosmin Tanislav FIELD_PREP(AD4130_ADC_CONTROL_MCLK_SEL_MASK,
177162094060SCosmin Tanislav mclk_sel));
177262094060SCosmin Tanislav }
177362094060SCosmin Tanislav
ad4130_int_clk_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)177462094060SCosmin Tanislav static unsigned long ad4130_int_clk_recalc_rate(struct clk_hw *hw,
177562094060SCosmin Tanislav unsigned long parent_rate)
177662094060SCosmin Tanislav {
177762094060SCosmin Tanislav return AD4130_MCLK_FREQ_76_8KHZ;
177862094060SCosmin Tanislav }
177962094060SCosmin Tanislav
ad4130_int_clk_is_enabled(struct clk_hw * hw)178062094060SCosmin Tanislav static int ad4130_int_clk_is_enabled(struct clk_hw *hw)
178162094060SCosmin Tanislav {
178262094060SCosmin Tanislav struct ad4130_state *st = container_of(hw, struct ad4130_state, int_clk_hw);
178362094060SCosmin Tanislav
178462094060SCosmin Tanislav return st->mclk_sel == AD4130_MCLK_76_8KHZ_OUT;
178562094060SCosmin Tanislav }
178662094060SCosmin Tanislav
ad4130_int_clk_prepare(struct clk_hw * hw)178762094060SCosmin Tanislav static int ad4130_int_clk_prepare(struct clk_hw *hw)
178862094060SCosmin Tanislav {
178962094060SCosmin Tanislav struct ad4130_state *st = container_of(hw, struct ad4130_state, int_clk_hw);
179062094060SCosmin Tanislav int ret;
179162094060SCosmin Tanislav
179262094060SCosmin Tanislav ret = ad4130_set_mclk_sel(st, AD4130_MCLK_76_8KHZ_OUT);
179362094060SCosmin Tanislav if (ret)
179462094060SCosmin Tanislav return ret;
179562094060SCosmin Tanislav
179662094060SCosmin Tanislav st->mclk_sel = AD4130_MCLK_76_8KHZ_OUT;
179762094060SCosmin Tanislav
179862094060SCosmin Tanislav return 0;
179962094060SCosmin Tanislav }
180062094060SCosmin Tanislav
ad4130_int_clk_unprepare(struct clk_hw * hw)180162094060SCosmin Tanislav static void ad4130_int_clk_unprepare(struct clk_hw *hw)
180262094060SCosmin Tanislav {
180362094060SCosmin Tanislav struct ad4130_state *st = container_of(hw, struct ad4130_state, int_clk_hw);
180462094060SCosmin Tanislav int ret;
180562094060SCosmin Tanislav
180662094060SCosmin Tanislav ret = ad4130_set_mclk_sel(st, AD4130_MCLK_76_8KHZ);
180762094060SCosmin Tanislav if (ret)
180862094060SCosmin Tanislav return;
180962094060SCosmin Tanislav
181062094060SCosmin Tanislav st->mclk_sel = AD4130_MCLK_76_8KHZ;
181162094060SCosmin Tanislav }
181262094060SCosmin Tanislav
181362094060SCosmin Tanislav static const struct clk_ops ad4130_int_clk_ops = {
181462094060SCosmin Tanislav .recalc_rate = ad4130_int_clk_recalc_rate,
181562094060SCosmin Tanislav .is_enabled = ad4130_int_clk_is_enabled,
181662094060SCosmin Tanislav .prepare = ad4130_int_clk_prepare,
181762094060SCosmin Tanislav .unprepare = ad4130_int_clk_unprepare,
181862094060SCosmin Tanislav };
181962094060SCosmin Tanislav
ad4130_clk_del_provider(void * of_node)182028f73dedSLars-Peter Clausen static void ad4130_clk_del_provider(void *of_node)
182128f73dedSLars-Peter Clausen {
182228f73dedSLars-Peter Clausen of_clk_del_provider(of_node);
182328f73dedSLars-Peter Clausen }
182428f73dedSLars-Peter Clausen
ad4130_setup_int_clk(struct ad4130_state * st)182562094060SCosmin Tanislav static int ad4130_setup_int_clk(struct ad4130_state *st)
182662094060SCosmin Tanislav {
182762094060SCosmin Tanislav struct device *dev = &st->spi->dev;
182862094060SCosmin Tanislav struct device_node *of_node = dev_of_node(dev);
18290e0dab37SCosmin Tanislav struct clk_init_data init = {};
183062094060SCosmin Tanislav const char *clk_name;
183162094060SCosmin Tanislav struct clk *clk;
183228f73dedSLars-Peter Clausen int ret;
183362094060SCosmin Tanislav
183462094060SCosmin Tanislav if (st->int_pin_sel == AD4130_INT_PIN_CLK ||
183562094060SCosmin Tanislav st->mclk_sel != AD4130_MCLK_76_8KHZ)
183662094060SCosmin Tanislav return 0;
183762094060SCosmin Tanislav
183862094060SCosmin Tanislav if (!of_node)
183962094060SCosmin Tanislav return 0;
184062094060SCosmin Tanislav
184162094060SCosmin Tanislav clk_name = of_node->name;
184262094060SCosmin Tanislav of_property_read_string(of_node, "clock-output-names", &clk_name);
184362094060SCosmin Tanislav
184462094060SCosmin Tanislav init.name = clk_name;
184562094060SCosmin Tanislav init.ops = &ad4130_int_clk_ops;
184662094060SCosmin Tanislav
184762094060SCosmin Tanislav st->int_clk_hw.init = &init;
184862094060SCosmin Tanislav clk = devm_clk_register(dev, &st->int_clk_hw);
184962094060SCosmin Tanislav if (IS_ERR(clk))
185062094060SCosmin Tanislav return PTR_ERR(clk);
185162094060SCosmin Tanislav
185228f73dedSLars-Peter Clausen ret = of_clk_add_provider(of_node, of_clk_src_simple_get, clk);
185328f73dedSLars-Peter Clausen if (ret)
185428f73dedSLars-Peter Clausen return ret;
185528f73dedSLars-Peter Clausen
185628f73dedSLars-Peter Clausen return devm_add_action_or_reset(dev, ad4130_clk_del_provider, of_node);
185762094060SCosmin Tanislav }
185862094060SCosmin Tanislav
ad4130_setup(struct iio_dev * indio_dev)185962094060SCosmin Tanislav static int ad4130_setup(struct iio_dev *indio_dev)
186062094060SCosmin Tanislav {
186162094060SCosmin Tanislav struct ad4130_state *st = iio_priv(indio_dev);
186262094060SCosmin Tanislav struct device *dev = &st->spi->dev;
186362094060SCosmin Tanislav unsigned int int_ref_val;
186462094060SCosmin Tanislav unsigned long rate = AD4130_MCLK_FREQ_76_8KHZ;
186562094060SCosmin Tanislav unsigned int val;
186662094060SCosmin Tanislav unsigned int i;
186762094060SCosmin Tanislav int ret;
186862094060SCosmin Tanislav
186962094060SCosmin Tanislav if (st->mclk_sel == AD4130_MCLK_153_6KHZ_EXT)
187062094060SCosmin Tanislav rate = AD4130_MCLK_FREQ_153_6KHZ;
187162094060SCosmin Tanislav
187262094060SCosmin Tanislav ret = clk_set_rate(st->mclk, rate);
187362094060SCosmin Tanislav if (ret)
187462094060SCosmin Tanislav return ret;
187562094060SCosmin Tanislav
187662094060SCosmin Tanislav ret = clk_prepare_enable(st->mclk);
187762094060SCosmin Tanislav if (ret)
187862094060SCosmin Tanislav return ret;
187962094060SCosmin Tanislav
188062094060SCosmin Tanislav ret = devm_add_action_or_reset(dev, ad4130_clk_disable_unprepare,
188162094060SCosmin Tanislav st->mclk);
188262094060SCosmin Tanislav if (ret)
188362094060SCosmin Tanislav return ret;
188462094060SCosmin Tanislav
188562094060SCosmin Tanislav if (st->int_ref_uv == AD4130_INT_REF_2_5V)
188662094060SCosmin Tanislav int_ref_val = AD4130_INT_REF_VAL_2_5V;
188762094060SCosmin Tanislav else
188862094060SCosmin Tanislav int_ref_val = AD4130_INT_REF_VAL_1_25V;
188962094060SCosmin Tanislav
189062094060SCosmin Tanislav /* Switch to SPI 4-wire mode. */
189162094060SCosmin Tanislav val = FIELD_PREP(AD4130_ADC_CONTROL_CSB_EN_MASK, 1);
189262094060SCosmin Tanislav val |= FIELD_PREP(AD4130_ADC_CONTROL_BIPOLAR_MASK, st->bipolar);
189362094060SCosmin Tanislav val |= FIELD_PREP(AD4130_ADC_CONTROL_INT_REF_EN_MASK, st->int_ref_en);
189462094060SCosmin Tanislav val |= FIELD_PREP(AD4130_ADC_CONTROL_MODE_MASK, AD4130_MODE_IDLE);
189562094060SCosmin Tanislav val |= FIELD_PREP(AD4130_ADC_CONTROL_MCLK_SEL_MASK, st->mclk_sel);
189662094060SCosmin Tanislav val |= FIELD_PREP(AD4130_ADC_CONTROL_INT_REF_VAL_MASK, int_ref_val);
189762094060SCosmin Tanislav
189862094060SCosmin Tanislav ret = regmap_write(st->regmap, AD4130_ADC_CONTROL_REG, val);
189962094060SCosmin Tanislav if (ret)
190062094060SCosmin Tanislav return ret;
190162094060SCosmin Tanislav
190262094060SCosmin Tanislav /*
1903*e7f744f6SCosmin Tanislav * Configure unused GPIOs for output. If configured, the interrupt
1904*e7f744f6SCosmin Tanislav * function of P2 takes priority over the GPIO out function.
190562094060SCosmin Tanislav */
1906*e7f744f6SCosmin Tanislav val = 0;
1907*e7f744f6SCosmin Tanislav for (i = 0; i < AD4130_MAX_GPIOS; i++)
1908*e7f744f6SCosmin Tanislav if (st->pins_fn[i + AD4130_AIN2_P1] == AD4130_PIN_FN_NONE)
1909*e7f744f6SCosmin Tanislav val |= FIELD_PREP(AD4130_IO_CONTROL_GPIO_CTRL_MASK, BIT(i));
1910*e7f744f6SCosmin Tanislav
191162094060SCosmin Tanislav val |= FIELD_PREP(AD4130_IO_CONTROL_INT_PIN_SEL_MASK, st->int_pin_sel);
191262094060SCosmin Tanislav
191362094060SCosmin Tanislav ret = regmap_write(st->regmap, AD4130_IO_CONTROL_REG, val);
191462094060SCosmin Tanislav if (ret)
191562094060SCosmin Tanislav return ret;
191662094060SCosmin Tanislav
191762094060SCosmin Tanislav val = 0;
191862094060SCosmin Tanislav for (i = 0; i < st->num_vbias_pins; i++)
191962094060SCosmin Tanislav val |= BIT(st->vbias_pins[i]);
192062094060SCosmin Tanislav
192162094060SCosmin Tanislav ret = regmap_write(st->regmap, AD4130_VBIAS_REG, val);
192262094060SCosmin Tanislav if (ret)
192362094060SCosmin Tanislav return ret;
192462094060SCosmin Tanislav
192562094060SCosmin Tanislav ret = regmap_update_bits(st->regmap, AD4130_FIFO_CONTROL_REG,
192662094060SCosmin Tanislav AD4130_FIFO_CONTROL_HEADER_MASK, 0);
192762094060SCosmin Tanislav if (ret)
192862094060SCosmin Tanislav return ret;
192962094060SCosmin Tanislav
193062094060SCosmin Tanislav /* FIFO watermark interrupt starts out as enabled, disable it. */
193162094060SCosmin Tanislav ret = ad4130_set_watermark_interrupt_en(st, false);
193262094060SCosmin Tanislav if (ret)
193362094060SCosmin Tanislav return ret;
193462094060SCosmin Tanislav
193562094060SCosmin Tanislav /* Setup channels. */
193662094060SCosmin Tanislav for (i = 0; i < indio_dev->num_channels; i++) {
193762094060SCosmin Tanislav struct ad4130_chan_info *chan_info = &st->chans_info[i];
193862094060SCosmin Tanislav struct iio_chan_spec *chan = &st->chans[i];
193962094060SCosmin Tanislav unsigned int val;
194062094060SCosmin Tanislav
194162094060SCosmin Tanislav val = FIELD_PREP(AD4130_CHANNEL_AINP_MASK, chan->channel) |
194262094060SCosmin Tanislav FIELD_PREP(AD4130_CHANNEL_AINM_MASK, chan->channel2) |
194362094060SCosmin Tanislav FIELD_PREP(AD4130_CHANNEL_IOUT1_MASK, chan_info->iout0) |
194462094060SCosmin Tanislav FIELD_PREP(AD4130_CHANNEL_IOUT2_MASK, chan_info->iout1);
194562094060SCosmin Tanislav
194662094060SCosmin Tanislav ret = regmap_write(st->regmap, AD4130_CHANNEL_X_REG(i), val);
194762094060SCosmin Tanislav if (ret)
194862094060SCosmin Tanislav return ret;
194962094060SCosmin Tanislav }
195062094060SCosmin Tanislav
195162094060SCosmin Tanislav return 0;
195262094060SCosmin Tanislav }
195362094060SCosmin Tanislav
ad4130_soft_reset(struct ad4130_state * st)195462094060SCosmin Tanislav static int ad4130_soft_reset(struct ad4130_state *st)
195562094060SCosmin Tanislav {
195662094060SCosmin Tanislav int ret;
195762094060SCosmin Tanislav
195862094060SCosmin Tanislav ret = spi_write(st->spi, st->reset_buf, sizeof(st->reset_buf));
195962094060SCosmin Tanislav if (ret)
196062094060SCosmin Tanislav return ret;
196162094060SCosmin Tanislav
196262094060SCosmin Tanislav fsleep(AD4130_RESET_SLEEP_US);
196362094060SCosmin Tanislav
196462094060SCosmin Tanislav return 0;
196562094060SCosmin Tanislav }
196662094060SCosmin Tanislav
ad4130_disable_regulators(void * data)196762094060SCosmin Tanislav static void ad4130_disable_regulators(void *data)
196862094060SCosmin Tanislav {
196962094060SCosmin Tanislav struct ad4130_state *st = data;
197062094060SCosmin Tanislav
197162094060SCosmin Tanislav regulator_bulk_disable(ARRAY_SIZE(st->regulators), st->regulators);
197262094060SCosmin Tanislav }
197362094060SCosmin Tanislav
ad4130_probe(struct spi_device * spi)197462094060SCosmin Tanislav static int ad4130_probe(struct spi_device *spi)
197562094060SCosmin Tanislav {
197662094060SCosmin Tanislav struct device *dev = &spi->dev;
197762094060SCosmin Tanislav struct iio_dev *indio_dev;
197862094060SCosmin Tanislav struct ad4130_state *st;
197962094060SCosmin Tanislav int ret;
198062094060SCosmin Tanislav
198162094060SCosmin Tanislav indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
198262094060SCosmin Tanislav if (!indio_dev)
198362094060SCosmin Tanislav return -ENOMEM;
198462094060SCosmin Tanislav
198562094060SCosmin Tanislav st = iio_priv(indio_dev);
198662094060SCosmin Tanislav
198762094060SCosmin Tanislav memset(st->reset_buf, 0xff, sizeof(st->reset_buf));
198862094060SCosmin Tanislav init_completion(&st->completion);
198962094060SCosmin Tanislav mutex_init(&st->lock);
199062094060SCosmin Tanislav st->spi = spi;
199162094060SCosmin Tanislav
199262094060SCosmin Tanislav /*
199362094060SCosmin Tanislav * Xfer: [ XFR1 ] [ XFR2 ]
199462094060SCosmin Tanislav * Master: 0x7D N ......................
199562094060SCosmin Tanislav * Slave: ...... DATA1 DATA2 ... DATAN
199662094060SCosmin Tanislav */
199762094060SCosmin Tanislav st->fifo_tx_buf[0] = AD4130_COMMS_READ_MASK | AD4130_FIFO_DATA_REG;
199862094060SCosmin Tanislav st->fifo_xfer[0].tx_buf = st->fifo_tx_buf;
199962094060SCosmin Tanislav st->fifo_xfer[0].len = sizeof(st->fifo_tx_buf);
200062094060SCosmin Tanislav st->fifo_xfer[1].rx_buf = st->fifo_rx_buf;
200162094060SCosmin Tanislav spi_message_init_with_transfers(&st->fifo_msg, st->fifo_xfer,
200262094060SCosmin Tanislav ARRAY_SIZE(st->fifo_xfer));
200362094060SCosmin Tanislav
200462094060SCosmin Tanislav indio_dev->name = AD4130_NAME;
200562094060SCosmin Tanislav indio_dev->modes = INDIO_DIRECT_MODE;
200662094060SCosmin Tanislav indio_dev->info = &ad4130_info;
200762094060SCosmin Tanislav
200862094060SCosmin Tanislav st->regmap = devm_regmap_init(dev, NULL, st, &ad4130_regmap_config);
200962094060SCosmin Tanislav if (IS_ERR(st->regmap))
201062094060SCosmin Tanislav return PTR_ERR(st->regmap);
201162094060SCosmin Tanislav
201262094060SCosmin Tanislav st->regulators[0].supply = "avdd";
201362094060SCosmin Tanislav st->regulators[1].supply = "iovdd";
201462094060SCosmin Tanislav st->regulators[2].supply = "refin1";
201562094060SCosmin Tanislav st->regulators[3].supply = "refin2";
201662094060SCosmin Tanislav
201762094060SCosmin Tanislav ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(st->regulators),
201862094060SCosmin Tanislav st->regulators);
201962094060SCosmin Tanislav if (ret)
202062094060SCosmin Tanislav return dev_err_probe(dev, ret, "Failed to get regulators\n");
202162094060SCosmin Tanislav
202262094060SCosmin Tanislav ret = regulator_bulk_enable(ARRAY_SIZE(st->regulators), st->regulators);
202362094060SCosmin Tanislav if (ret)
202462094060SCosmin Tanislav return dev_err_probe(dev, ret, "Failed to enable regulators\n");
202562094060SCosmin Tanislav
202662094060SCosmin Tanislav ret = devm_add_action_or_reset(dev, ad4130_disable_regulators, st);
202762094060SCosmin Tanislav if (ret)
202862094060SCosmin Tanislav return dev_err_probe(dev, ret,
202962094060SCosmin Tanislav "Failed to add regulators disable action\n");
203062094060SCosmin Tanislav
203162094060SCosmin Tanislav ret = ad4130_soft_reset(st);
203262094060SCosmin Tanislav if (ret)
203362094060SCosmin Tanislav return ret;
203462094060SCosmin Tanislav
203562094060SCosmin Tanislav ret = ad4310_parse_fw(indio_dev);
203662094060SCosmin Tanislav if (ret)
203762094060SCosmin Tanislav return ret;
203862094060SCosmin Tanislav
203962094060SCosmin Tanislav ret = ad4130_setup(indio_dev);
204062094060SCosmin Tanislav if (ret)
204162094060SCosmin Tanislav return ret;
204262094060SCosmin Tanislav
204362094060SCosmin Tanislav ret = ad4130_setup_int_clk(st);
204462094060SCosmin Tanislav if (ret)
204562094060SCosmin Tanislav return ret;
204662094060SCosmin Tanislav
204762094060SCosmin Tanislav ad4130_fill_scale_tbls(st);
204862094060SCosmin Tanislav
204962094060SCosmin Tanislav st->gc.owner = THIS_MODULE;
205062094060SCosmin Tanislav st->gc.label = AD4130_NAME;
205162094060SCosmin Tanislav st->gc.base = -1;
205262094060SCosmin Tanislav st->gc.ngpio = AD4130_MAX_GPIOS;
205362094060SCosmin Tanislav st->gc.parent = dev;
205462094060SCosmin Tanislav st->gc.can_sleep = true;
205562094060SCosmin Tanislav st->gc.init_valid_mask = ad4130_gpio_init_valid_mask;
205662094060SCosmin Tanislav st->gc.get_direction = ad4130_gpio_get_direction;
205762094060SCosmin Tanislav st->gc.set = ad4130_gpio_set;
205862094060SCosmin Tanislav
205962094060SCosmin Tanislav ret = devm_gpiochip_add_data(dev, &st->gc, st);
206062094060SCosmin Tanislav if (ret)
206162094060SCosmin Tanislav return ret;
206262094060SCosmin Tanislav
206362094060SCosmin Tanislav ret = devm_iio_kfifo_buffer_setup_ext(dev, indio_dev,
206462094060SCosmin Tanislav &ad4130_buffer_ops,
206562094060SCosmin Tanislav ad4130_fifo_attributes);
206662094060SCosmin Tanislav if (ret)
206762094060SCosmin Tanislav return ret;
206862094060SCosmin Tanislav
206962094060SCosmin Tanislav ret = devm_request_threaded_irq(dev, spi->irq, NULL,
207062094060SCosmin Tanislav ad4130_irq_handler, IRQF_ONESHOT,
207162094060SCosmin Tanislav indio_dev->name, indio_dev);
207262094060SCosmin Tanislav if (ret)
207362094060SCosmin Tanislav return dev_err_probe(dev, ret, "Failed to request irq\n");
207462094060SCosmin Tanislav
207562094060SCosmin Tanislav /*
207662094060SCosmin Tanislav * When the chip enters FIFO mode, IRQ polarity is inverted.
207762094060SCosmin Tanislav * When the chip exits FIFO mode, IRQ polarity returns to normal.
207862094060SCosmin Tanislav * See datasheet pages: 65, FIFO Watermark Interrupt section,
207962094060SCosmin Tanislav * and 71, Bit Descriptions for STATUS Register, RDYB.
208062094060SCosmin Tanislav * Cache the normal and inverted IRQ triggers to set them when
208162094060SCosmin Tanislav * entering and exiting FIFO mode.
208262094060SCosmin Tanislav */
208362094060SCosmin Tanislav st->irq_trigger = irq_get_trigger_type(spi->irq);
208462094060SCosmin Tanislav if (st->irq_trigger & IRQF_TRIGGER_RISING)
208562094060SCosmin Tanislav st->inv_irq_trigger = IRQF_TRIGGER_FALLING;
208662094060SCosmin Tanislav else if (st->irq_trigger & IRQF_TRIGGER_FALLING)
208762094060SCosmin Tanislav st->inv_irq_trigger = IRQF_TRIGGER_RISING;
208862094060SCosmin Tanislav else
208962094060SCosmin Tanislav return dev_err_probe(dev, -EINVAL, "Invalid irq flags: %u\n",
209062094060SCosmin Tanislav st->irq_trigger);
209162094060SCosmin Tanislav
209262094060SCosmin Tanislav return devm_iio_device_register(dev, indio_dev);
209362094060SCosmin Tanislav }
209462094060SCosmin Tanislav
209562094060SCosmin Tanislav static const struct of_device_id ad4130_of_match[] = {
209662094060SCosmin Tanislav {
209762094060SCosmin Tanislav .compatible = "adi,ad4130",
209862094060SCosmin Tanislav },
209962094060SCosmin Tanislav { }
210062094060SCosmin Tanislav };
210162094060SCosmin Tanislav MODULE_DEVICE_TABLE(of, ad4130_of_match);
210262094060SCosmin Tanislav
210362094060SCosmin Tanislav static struct spi_driver ad4130_driver = {
210462094060SCosmin Tanislav .driver = {
210562094060SCosmin Tanislav .name = AD4130_NAME,
210662094060SCosmin Tanislav .of_match_table = ad4130_of_match,
210762094060SCosmin Tanislav },
210862094060SCosmin Tanislav .probe = ad4130_probe,
210962094060SCosmin Tanislav };
211062094060SCosmin Tanislav module_spi_driver(ad4130_driver);
211162094060SCosmin Tanislav
211262094060SCosmin Tanislav MODULE_AUTHOR("Cosmin Tanislav <cosmin.tanislav@analog.com>");
211362094060SCosmin Tanislav MODULE_DESCRIPTION("Analog Devices AD4130 SPI driver");
211462094060SCosmin Tanislav MODULE_LICENSE("GPL");
2115