162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2022 Analog Devices, Inc.
462306a36Sopenharmony_ci * Author: Cosmin Tanislav <cosmin.tanislav@analog.com>
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <linux/bitfield.h>
862306a36Sopenharmony_ci#include <linux/bitops.h>
962306a36Sopenharmony_ci#include <linux/clk.h>
1062306a36Sopenharmony_ci#include <linux/clk-provider.h>
1162306a36Sopenharmony_ci#include <linux/delay.h>
1262306a36Sopenharmony_ci#include <linux/device.h>
1362306a36Sopenharmony_ci#include <linux/err.h>
1462306a36Sopenharmony_ci#include <linux/gpio/driver.h>
1562306a36Sopenharmony_ci#include <linux/interrupt.h>
1662306a36Sopenharmony_ci#include <linux/irq.h>
1762306a36Sopenharmony_ci#include <linux/kernel.h>
1862306a36Sopenharmony_ci#include <linux/module.h>
1962306a36Sopenharmony_ci#include <linux/property.h>
2062306a36Sopenharmony_ci#include <linux/regmap.h>
2162306a36Sopenharmony_ci#include <linux/regulator/consumer.h>
2262306a36Sopenharmony_ci#include <linux/spi/spi.h>
2362306a36Sopenharmony_ci#include <linux/units.h>
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#include <asm/div64.h>
2662306a36Sopenharmony_ci#include <asm/unaligned.h>
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#include <linux/iio/buffer.h>
2962306a36Sopenharmony_ci#include <linux/iio/iio.h>
3062306a36Sopenharmony_ci#include <linux/iio/kfifo_buf.h>
3162306a36Sopenharmony_ci#include <linux/iio/sysfs.h>
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci#define AD4130_NAME				"ad4130"
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci#define AD4130_COMMS_READ_MASK			BIT(6)
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci#define AD4130_STATUS_REG			0x00
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci#define AD4130_ADC_CONTROL_REG			0x01
4062306a36Sopenharmony_ci#define AD4130_ADC_CONTROL_BIPOLAR_MASK		BIT(14)
4162306a36Sopenharmony_ci#define AD4130_ADC_CONTROL_INT_REF_VAL_MASK	BIT(13)
4262306a36Sopenharmony_ci#define AD4130_INT_REF_2_5V			2500000
4362306a36Sopenharmony_ci#define AD4130_INT_REF_1_25V			1250000
4462306a36Sopenharmony_ci#define AD4130_ADC_CONTROL_CSB_EN_MASK		BIT(9)
4562306a36Sopenharmony_ci#define AD4130_ADC_CONTROL_INT_REF_EN_MASK	BIT(8)
4662306a36Sopenharmony_ci#define AD4130_ADC_CONTROL_MODE_MASK		GENMASK(5, 2)
4762306a36Sopenharmony_ci#define AD4130_ADC_CONTROL_MCLK_SEL_MASK	GENMASK(1, 0)
4862306a36Sopenharmony_ci#define AD4130_MCLK_FREQ_76_8KHZ		76800
4962306a36Sopenharmony_ci#define AD4130_MCLK_FREQ_153_6KHZ		153600
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci#define AD4130_DATA_REG				0x02
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci#define AD4130_IO_CONTROL_REG			0x03
5462306a36Sopenharmony_ci#define AD4130_IO_CONTROL_INT_PIN_SEL_MASK	GENMASK(9, 8)
5562306a36Sopenharmony_ci#define AD4130_IO_CONTROL_GPIO_DATA_MASK	GENMASK(7, 4)
5662306a36Sopenharmony_ci#define AD4130_IO_CONTROL_GPIO_CTRL_MASK	GENMASK(3, 0)
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci#define AD4130_VBIAS_REG			0x04
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci#define AD4130_ID_REG				0x05
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci#define AD4130_ERROR_REG			0x06
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci#define AD4130_ERROR_EN_REG			0x07
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci#define AD4130_MCLK_COUNT_REG			0x08
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci#define AD4130_CHANNEL_X_REG(x)			(0x09 + (x))
6962306a36Sopenharmony_ci#define AD4130_CHANNEL_EN_MASK			BIT(23)
7062306a36Sopenharmony_ci#define AD4130_CHANNEL_SETUP_MASK		GENMASK(22, 20)
7162306a36Sopenharmony_ci#define AD4130_CHANNEL_AINP_MASK		GENMASK(17, 13)
7262306a36Sopenharmony_ci#define AD4130_CHANNEL_AINM_MASK		GENMASK(12, 8)
7362306a36Sopenharmony_ci#define AD4130_CHANNEL_IOUT1_MASK		GENMASK(7, 4)
7462306a36Sopenharmony_ci#define AD4130_CHANNEL_IOUT2_MASK		GENMASK(3, 0)
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci#define AD4130_CONFIG_X_REG(x)			(0x19 + (x))
7762306a36Sopenharmony_ci#define AD4130_CONFIG_IOUT1_VAL_MASK		GENMASK(15, 13)
7862306a36Sopenharmony_ci#define AD4130_CONFIG_IOUT2_VAL_MASK		GENMASK(12, 10)
7962306a36Sopenharmony_ci#define AD4130_CONFIG_BURNOUT_MASK		GENMASK(9, 8)
8062306a36Sopenharmony_ci#define AD4130_CONFIG_REF_BUFP_MASK		BIT(7)
8162306a36Sopenharmony_ci#define AD4130_CONFIG_REF_BUFM_MASK		BIT(6)
8262306a36Sopenharmony_ci#define AD4130_CONFIG_REF_SEL_MASK		GENMASK(5, 4)
8362306a36Sopenharmony_ci#define AD4130_CONFIG_PGA_MASK			GENMASK(3, 1)
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci#define AD4130_FILTER_X_REG(x)			(0x21 + (x))
8662306a36Sopenharmony_ci#define AD4130_FILTER_MODE_MASK			GENMASK(15, 12)
8762306a36Sopenharmony_ci#define AD4130_FILTER_SELECT_MASK		GENMASK(10, 0)
8862306a36Sopenharmony_ci#define AD4130_FILTER_SELECT_MIN		1
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci#define AD4130_OFFSET_X_REG(x)			(0x29 + (x))
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci#define AD4130_GAIN_X_REG(x)			(0x31 + (x))
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci#define AD4130_MISC_REG				0x39
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci#define AD4130_FIFO_CONTROL_REG			0x3a
9762306a36Sopenharmony_ci#define AD4130_FIFO_CONTROL_HEADER_MASK		BIT(18)
9862306a36Sopenharmony_ci#define AD4130_FIFO_CONTROL_MODE_MASK		GENMASK(17, 16)
9962306a36Sopenharmony_ci#define AD4130_FIFO_CONTROL_WM_INT_EN_MASK	BIT(9)
10062306a36Sopenharmony_ci#define AD4130_FIFO_CONTROL_WM_MASK		GENMASK(7, 0)
10162306a36Sopenharmony_ci#define AD4130_WATERMARK_256			0
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci#define AD4130_FIFO_STATUS_REG			0x3b
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci#define AD4130_FIFO_THRESHOLD_REG		0x3c
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci#define AD4130_FIFO_DATA_REG			0x3d
10862306a36Sopenharmony_ci#define AD4130_FIFO_SIZE			256
10962306a36Sopenharmony_ci#define AD4130_FIFO_MAX_SAMPLE_SIZE		3
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci#define AD4130_MAX_ANALOG_PINS			16
11262306a36Sopenharmony_ci#define AD4130_MAX_CHANNELS			16
11362306a36Sopenharmony_ci#define AD4130_MAX_DIFF_INPUTS			30
11462306a36Sopenharmony_ci#define AD4130_MAX_GPIOS			4
11562306a36Sopenharmony_ci#define AD4130_MAX_ODR				2400
11662306a36Sopenharmony_ci#define AD4130_MAX_PGA				8
11762306a36Sopenharmony_ci#define AD4130_MAX_SETUPS			8
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci#define AD4130_AIN2_P1				0x2
12062306a36Sopenharmony_ci#define AD4130_AIN3_P2				0x3
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci#define AD4130_RESET_BUF_SIZE			8
12362306a36Sopenharmony_ci#define AD4130_RESET_SLEEP_US			(160 * MICRO / AD4130_MCLK_FREQ_76_8KHZ)
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci#define AD4130_INVALID_SLOT			-1
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_cistatic const unsigned int ad4130_reg_size[] = {
12862306a36Sopenharmony_ci	[AD4130_STATUS_REG] = 1,
12962306a36Sopenharmony_ci	[AD4130_ADC_CONTROL_REG] = 2,
13062306a36Sopenharmony_ci	[AD4130_DATA_REG] = 3,
13162306a36Sopenharmony_ci	[AD4130_IO_CONTROL_REG] = 2,
13262306a36Sopenharmony_ci	[AD4130_VBIAS_REG] = 2,
13362306a36Sopenharmony_ci	[AD4130_ID_REG] = 1,
13462306a36Sopenharmony_ci	[AD4130_ERROR_REG] = 2,
13562306a36Sopenharmony_ci	[AD4130_ERROR_EN_REG] = 2,
13662306a36Sopenharmony_ci	[AD4130_MCLK_COUNT_REG] = 1,
13762306a36Sopenharmony_ci	[AD4130_CHANNEL_X_REG(0) ... AD4130_CHANNEL_X_REG(AD4130_MAX_CHANNELS - 1)] = 3,
13862306a36Sopenharmony_ci	[AD4130_CONFIG_X_REG(0) ... AD4130_CONFIG_X_REG(AD4130_MAX_SETUPS - 1)] = 2,
13962306a36Sopenharmony_ci	[AD4130_FILTER_X_REG(0) ... AD4130_FILTER_X_REG(AD4130_MAX_SETUPS - 1)] = 3,
14062306a36Sopenharmony_ci	[AD4130_OFFSET_X_REG(0) ... AD4130_OFFSET_X_REG(AD4130_MAX_SETUPS - 1)] = 3,
14162306a36Sopenharmony_ci	[AD4130_GAIN_X_REG(0) ... AD4130_GAIN_X_REG(AD4130_MAX_SETUPS - 1)] = 3,
14262306a36Sopenharmony_ci	[AD4130_MISC_REG] = 2,
14362306a36Sopenharmony_ci	[AD4130_FIFO_CONTROL_REG] = 3,
14462306a36Sopenharmony_ci	[AD4130_FIFO_STATUS_REG] = 1,
14562306a36Sopenharmony_ci	[AD4130_FIFO_THRESHOLD_REG] = 3,
14662306a36Sopenharmony_ci	[AD4130_FIFO_DATA_REG] = 3,
14762306a36Sopenharmony_ci};
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_cienum ad4130_int_ref_val {
15062306a36Sopenharmony_ci	AD4130_INT_REF_VAL_2_5V,
15162306a36Sopenharmony_ci	AD4130_INT_REF_VAL_1_25V,
15262306a36Sopenharmony_ci};
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_cienum ad4130_mclk_sel {
15562306a36Sopenharmony_ci	AD4130_MCLK_76_8KHZ,
15662306a36Sopenharmony_ci	AD4130_MCLK_76_8KHZ_OUT,
15762306a36Sopenharmony_ci	AD4130_MCLK_76_8KHZ_EXT,
15862306a36Sopenharmony_ci	AD4130_MCLK_153_6KHZ_EXT,
15962306a36Sopenharmony_ci};
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_cienum ad4130_int_pin_sel {
16262306a36Sopenharmony_ci	AD4130_INT_PIN_INT,
16362306a36Sopenharmony_ci	AD4130_INT_PIN_CLK,
16462306a36Sopenharmony_ci	AD4130_INT_PIN_P2,
16562306a36Sopenharmony_ci	AD4130_INT_PIN_DOUT,
16662306a36Sopenharmony_ci};
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_cienum ad4130_iout {
16962306a36Sopenharmony_ci	AD4130_IOUT_OFF,
17062306a36Sopenharmony_ci	AD4130_IOUT_10000NA,
17162306a36Sopenharmony_ci	AD4130_IOUT_20000NA,
17262306a36Sopenharmony_ci	AD4130_IOUT_50000NA,
17362306a36Sopenharmony_ci	AD4130_IOUT_100000NA,
17462306a36Sopenharmony_ci	AD4130_IOUT_150000NA,
17562306a36Sopenharmony_ci	AD4130_IOUT_200000NA,
17662306a36Sopenharmony_ci	AD4130_IOUT_100NA,
17762306a36Sopenharmony_ci	AD4130_IOUT_MAX
17862306a36Sopenharmony_ci};
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_cienum ad4130_burnout {
18162306a36Sopenharmony_ci	AD4130_BURNOUT_OFF,
18262306a36Sopenharmony_ci	AD4130_BURNOUT_500NA,
18362306a36Sopenharmony_ci	AD4130_BURNOUT_2000NA,
18462306a36Sopenharmony_ci	AD4130_BURNOUT_4000NA,
18562306a36Sopenharmony_ci	AD4130_BURNOUT_MAX
18662306a36Sopenharmony_ci};
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_cienum ad4130_ref_sel {
18962306a36Sopenharmony_ci	AD4130_REF_REFIN1,
19062306a36Sopenharmony_ci	AD4130_REF_REFIN2,
19162306a36Sopenharmony_ci	AD4130_REF_REFOUT_AVSS,
19262306a36Sopenharmony_ci	AD4130_REF_AVDD_AVSS,
19362306a36Sopenharmony_ci	AD4130_REF_SEL_MAX
19462306a36Sopenharmony_ci};
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_cienum ad4130_fifo_mode {
19762306a36Sopenharmony_ci	AD4130_FIFO_MODE_DISABLED = 0b00,
19862306a36Sopenharmony_ci	AD4130_FIFO_MODE_WM = 0b01,
19962306a36Sopenharmony_ci};
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_cienum ad4130_mode {
20262306a36Sopenharmony_ci	AD4130_MODE_CONTINUOUS = 0b0000,
20362306a36Sopenharmony_ci	AD4130_MODE_IDLE = 0b0100,
20462306a36Sopenharmony_ci};
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_cienum ad4130_filter_mode {
20762306a36Sopenharmony_ci	AD4130_FILTER_SINC4,
20862306a36Sopenharmony_ci	AD4130_FILTER_SINC4_SINC1,
20962306a36Sopenharmony_ci	AD4130_FILTER_SINC3,
21062306a36Sopenharmony_ci	AD4130_FILTER_SINC3_REJ60,
21162306a36Sopenharmony_ci	AD4130_FILTER_SINC3_SINC1,
21262306a36Sopenharmony_ci	AD4130_FILTER_SINC3_PF1,
21362306a36Sopenharmony_ci	AD4130_FILTER_SINC3_PF2,
21462306a36Sopenharmony_ci	AD4130_FILTER_SINC3_PF3,
21562306a36Sopenharmony_ci	AD4130_FILTER_SINC3_PF4,
21662306a36Sopenharmony_ci};
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_cienum ad4130_pin_function {
21962306a36Sopenharmony_ci	AD4130_PIN_FN_NONE,
22062306a36Sopenharmony_ci	AD4130_PIN_FN_SPECIAL = BIT(0),
22162306a36Sopenharmony_ci	AD4130_PIN_FN_DIFF = BIT(1),
22262306a36Sopenharmony_ci	AD4130_PIN_FN_EXCITATION = BIT(2),
22362306a36Sopenharmony_ci	AD4130_PIN_FN_VBIAS = BIT(3),
22462306a36Sopenharmony_ci};
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_cistruct ad4130_setup_info {
22762306a36Sopenharmony_ci	unsigned int			iout0_val;
22862306a36Sopenharmony_ci	unsigned int			iout1_val;
22962306a36Sopenharmony_ci	unsigned int			burnout;
23062306a36Sopenharmony_ci	unsigned int			pga;
23162306a36Sopenharmony_ci	unsigned int			fs;
23262306a36Sopenharmony_ci	u32				ref_sel;
23362306a36Sopenharmony_ci	enum ad4130_filter_mode		filter_mode;
23462306a36Sopenharmony_ci	bool				ref_bufp;
23562306a36Sopenharmony_ci	bool				ref_bufm;
23662306a36Sopenharmony_ci};
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_cistruct ad4130_slot_info {
23962306a36Sopenharmony_ci	struct ad4130_setup_info	setup;
24062306a36Sopenharmony_ci	unsigned int			enabled_channels;
24162306a36Sopenharmony_ci	unsigned int			channels;
24262306a36Sopenharmony_ci};
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_cistruct ad4130_chan_info {
24562306a36Sopenharmony_ci	struct ad4130_setup_info	setup;
24662306a36Sopenharmony_ci	u32				iout0;
24762306a36Sopenharmony_ci	u32				iout1;
24862306a36Sopenharmony_ci	int				slot;
24962306a36Sopenharmony_ci	bool				enabled;
25062306a36Sopenharmony_ci	bool				initialized;
25162306a36Sopenharmony_ci};
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_cistruct ad4130_filter_config {
25462306a36Sopenharmony_ci	enum ad4130_filter_mode		filter_mode;
25562306a36Sopenharmony_ci	unsigned int			odr_div;
25662306a36Sopenharmony_ci	unsigned int			fs_max;
25762306a36Sopenharmony_ci	enum iio_available_type		samp_freq_avail_type;
25862306a36Sopenharmony_ci	int				samp_freq_avail_len;
25962306a36Sopenharmony_ci	int				samp_freq_avail[3][2];
26062306a36Sopenharmony_ci};
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_cistruct ad4130_state {
26362306a36Sopenharmony_ci	struct regmap			*regmap;
26462306a36Sopenharmony_ci	struct spi_device		*spi;
26562306a36Sopenharmony_ci	struct clk			*mclk;
26662306a36Sopenharmony_ci	struct regulator_bulk_data	regulators[4];
26762306a36Sopenharmony_ci	u32				irq_trigger;
26862306a36Sopenharmony_ci	u32				inv_irq_trigger;
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	/*
27162306a36Sopenharmony_ci	 * Synchronize access to members the of driver state, and ensure
27262306a36Sopenharmony_ci	 * atomicity of consecutive regmap operations.
27362306a36Sopenharmony_ci	 */
27462306a36Sopenharmony_ci	struct mutex			lock;
27562306a36Sopenharmony_ci	struct completion		completion;
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci	struct iio_chan_spec		chans[AD4130_MAX_CHANNELS];
27862306a36Sopenharmony_ci	struct ad4130_chan_info		chans_info[AD4130_MAX_CHANNELS];
27962306a36Sopenharmony_ci	struct ad4130_slot_info		slots_info[AD4130_MAX_SETUPS];
28062306a36Sopenharmony_ci	enum ad4130_pin_function	pins_fn[AD4130_MAX_ANALOG_PINS];
28162306a36Sopenharmony_ci	u32				vbias_pins[AD4130_MAX_ANALOG_PINS];
28262306a36Sopenharmony_ci	u32				num_vbias_pins;
28362306a36Sopenharmony_ci	int				scale_tbls[AD4130_REF_SEL_MAX][AD4130_MAX_PGA][2];
28462306a36Sopenharmony_ci	struct gpio_chip		gc;
28562306a36Sopenharmony_ci	struct clk_hw			int_clk_hw;
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	u32			int_pin_sel;
28862306a36Sopenharmony_ci	u32			int_ref_uv;
28962306a36Sopenharmony_ci	u32			mclk_sel;
29062306a36Sopenharmony_ci	bool			int_ref_en;
29162306a36Sopenharmony_ci	bool			bipolar;
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	unsigned int		num_enabled_channels;
29462306a36Sopenharmony_ci	unsigned int		effective_watermark;
29562306a36Sopenharmony_ci	unsigned int		watermark;
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	struct spi_message	fifo_msg;
29862306a36Sopenharmony_ci	struct spi_transfer	fifo_xfer[2];
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	/*
30162306a36Sopenharmony_ci	 * DMA (thus cache coherency maintenance) requires any transfer
30262306a36Sopenharmony_ci	 * buffers to live in their own cache lines. As the use of these
30362306a36Sopenharmony_ci	 * buffers is synchronous, all of the buffers used for DMA in this
30462306a36Sopenharmony_ci	 * driver may share a cache line.
30562306a36Sopenharmony_ci	 */
30662306a36Sopenharmony_ci	u8			reset_buf[AD4130_RESET_BUF_SIZE] __aligned(IIO_DMA_MINALIGN);
30762306a36Sopenharmony_ci	u8			reg_write_tx_buf[4];
30862306a36Sopenharmony_ci	u8			reg_read_tx_buf[1];
30962306a36Sopenharmony_ci	u8			reg_read_rx_buf[3];
31062306a36Sopenharmony_ci	u8			fifo_tx_buf[2];
31162306a36Sopenharmony_ci	u8			fifo_rx_buf[AD4130_FIFO_SIZE *
31262306a36Sopenharmony_ci					    AD4130_FIFO_MAX_SAMPLE_SIZE];
31362306a36Sopenharmony_ci};
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_cistatic const char * const ad4130_int_pin_names[] = {
31662306a36Sopenharmony_ci	[AD4130_INT_PIN_INT] = "int",
31762306a36Sopenharmony_ci	[AD4130_INT_PIN_CLK] = "clk",
31862306a36Sopenharmony_ci	[AD4130_INT_PIN_P2] = "p2",
31962306a36Sopenharmony_ci	[AD4130_INT_PIN_DOUT] = "dout",
32062306a36Sopenharmony_ci};
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_cistatic const unsigned int ad4130_iout_current_na_tbl[AD4130_IOUT_MAX] = {
32362306a36Sopenharmony_ci	[AD4130_IOUT_OFF] = 0,
32462306a36Sopenharmony_ci	[AD4130_IOUT_100NA] = 100,
32562306a36Sopenharmony_ci	[AD4130_IOUT_10000NA] = 10000,
32662306a36Sopenharmony_ci	[AD4130_IOUT_20000NA] = 20000,
32762306a36Sopenharmony_ci	[AD4130_IOUT_50000NA] = 50000,
32862306a36Sopenharmony_ci	[AD4130_IOUT_100000NA] = 100000,
32962306a36Sopenharmony_ci	[AD4130_IOUT_150000NA] = 150000,
33062306a36Sopenharmony_ci	[AD4130_IOUT_200000NA] = 200000,
33162306a36Sopenharmony_ci};
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_cistatic const unsigned int ad4130_burnout_current_na_tbl[AD4130_BURNOUT_MAX] = {
33462306a36Sopenharmony_ci	[AD4130_BURNOUT_OFF] = 0,
33562306a36Sopenharmony_ci	[AD4130_BURNOUT_500NA] = 500,
33662306a36Sopenharmony_ci	[AD4130_BURNOUT_2000NA] = 2000,
33762306a36Sopenharmony_ci	[AD4130_BURNOUT_4000NA] = 4000,
33862306a36Sopenharmony_ci};
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci#define AD4130_VARIABLE_ODR_CONFIG(_filter_mode, _odr_div, _fs_max)	\
34162306a36Sopenharmony_ci{									\
34262306a36Sopenharmony_ci		.filter_mode = (_filter_mode),				\
34362306a36Sopenharmony_ci		.odr_div = (_odr_div),					\
34462306a36Sopenharmony_ci		.fs_max = (_fs_max),					\
34562306a36Sopenharmony_ci		.samp_freq_avail_type = IIO_AVAIL_RANGE,		\
34662306a36Sopenharmony_ci		.samp_freq_avail = {					\
34762306a36Sopenharmony_ci			{ AD4130_MAX_ODR, (_odr_div) * (_fs_max) },	\
34862306a36Sopenharmony_ci			{ AD4130_MAX_ODR, (_odr_div) * (_fs_max) },	\
34962306a36Sopenharmony_ci			{ AD4130_MAX_ODR, (_odr_div) },			\
35062306a36Sopenharmony_ci		},							\
35162306a36Sopenharmony_ci}
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci#define AD4130_FIXED_ODR_CONFIG(_filter_mode, _odr_div)			\
35462306a36Sopenharmony_ci{									\
35562306a36Sopenharmony_ci		.filter_mode = (_filter_mode),				\
35662306a36Sopenharmony_ci		.odr_div = (_odr_div),					\
35762306a36Sopenharmony_ci		.fs_max = AD4130_FILTER_SELECT_MIN,			\
35862306a36Sopenharmony_ci		.samp_freq_avail_type = IIO_AVAIL_LIST,			\
35962306a36Sopenharmony_ci		.samp_freq_avail_len = 1,				\
36062306a36Sopenharmony_ci		.samp_freq_avail = {					\
36162306a36Sopenharmony_ci			{ AD4130_MAX_ODR, (_odr_div) },			\
36262306a36Sopenharmony_ci		},							\
36362306a36Sopenharmony_ci}
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_cistatic const struct ad4130_filter_config ad4130_filter_configs[] = {
36662306a36Sopenharmony_ci	AD4130_VARIABLE_ODR_CONFIG(AD4130_FILTER_SINC4,       1,  10),
36762306a36Sopenharmony_ci	AD4130_VARIABLE_ODR_CONFIG(AD4130_FILTER_SINC4_SINC1, 11, 10),
36862306a36Sopenharmony_ci	AD4130_VARIABLE_ODR_CONFIG(AD4130_FILTER_SINC3,       1,  2047),
36962306a36Sopenharmony_ci	AD4130_VARIABLE_ODR_CONFIG(AD4130_FILTER_SINC3_REJ60, 1,  2047),
37062306a36Sopenharmony_ci	AD4130_VARIABLE_ODR_CONFIG(AD4130_FILTER_SINC3_SINC1, 10, 2047),
37162306a36Sopenharmony_ci	AD4130_FIXED_ODR_CONFIG(AD4130_FILTER_SINC3_PF1,      92),
37262306a36Sopenharmony_ci	AD4130_FIXED_ODR_CONFIG(AD4130_FILTER_SINC3_PF2,      100),
37362306a36Sopenharmony_ci	AD4130_FIXED_ODR_CONFIG(AD4130_FILTER_SINC3_PF3,      124),
37462306a36Sopenharmony_ci	AD4130_FIXED_ODR_CONFIG(AD4130_FILTER_SINC3_PF4,      148),
37562306a36Sopenharmony_ci};
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_cistatic const char * const ad4130_filter_modes_str[] = {
37862306a36Sopenharmony_ci	[AD4130_FILTER_SINC4] = "sinc4",
37962306a36Sopenharmony_ci	[AD4130_FILTER_SINC4_SINC1] = "sinc4+sinc1",
38062306a36Sopenharmony_ci	[AD4130_FILTER_SINC3] = "sinc3",
38162306a36Sopenharmony_ci	[AD4130_FILTER_SINC3_REJ60] = "sinc3+rej60",
38262306a36Sopenharmony_ci	[AD4130_FILTER_SINC3_SINC1] = "sinc3+sinc1",
38362306a36Sopenharmony_ci	[AD4130_FILTER_SINC3_PF1] = "sinc3+pf1",
38462306a36Sopenharmony_ci	[AD4130_FILTER_SINC3_PF2] = "sinc3+pf2",
38562306a36Sopenharmony_ci	[AD4130_FILTER_SINC3_PF3] = "sinc3+pf3",
38662306a36Sopenharmony_ci	[AD4130_FILTER_SINC3_PF4] = "sinc3+pf4",
38762306a36Sopenharmony_ci};
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_cistatic int ad4130_get_reg_size(struct ad4130_state *st, unsigned int reg,
39062306a36Sopenharmony_ci			       unsigned int *size)
39162306a36Sopenharmony_ci{
39262306a36Sopenharmony_ci	if (reg >= ARRAY_SIZE(ad4130_reg_size))
39362306a36Sopenharmony_ci		return -EINVAL;
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_ci	*size = ad4130_reg_size[reg];
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci	return 0;
39862306a36Sopenharmony_ci}
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_cistatic unsigned int ad4130_data_reg_size(struct ad4130_state *st)
40162306a36Sopenharmony_ci{
40262306a36Sopenharmony_ci	unsigned int data_reg_size;
40362306a36Sopenharmony_ci	int ret;
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ci	ret = ad4130_get_reg_size(st, AD4130_DATA_REG, &data_reg_size);
40662306a36Sopenharmony_ci	if (ret)
40762306a36Sopenharmony_ci		return 0;
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci	return data_reg_size;
41062306a36Sopenharmony_ci}
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_cistatic unsigned int ad4130_resolution(struct ad4130_state *st)
41362306a36Sopenharmony_ci{
41462306a36Sopenharmony_ci	return ad4130_data_reg_size(st) * BITS_PER_BYTE;
41562306a36Sopenharmony_ci}
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_cistatic int ad4130_reg_write(void *context, unsigned int reg, unsigned int val)
41862306a36Sopenharmony_ci{
41962306a36Sopenharmony_ci	struct ad4130_state *st = context;
42062306a36Sopenharmony_ci	unsigned int size;
42162306a36Sopenharmony_ci	int ret;
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	ret = ad4130_get_reg_size(st, reg, &size);
42462306a36Sopenharmony_ci	if (ret)
42562306a36Sopenharmony_ci		return ret;
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ci	st->reg_write_tx_buf[0] = reg;
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci	switch (size) {
43062306a36Sopenharmony_ci	case 3:
43162306a36Sopenharmony_ci		put_unaligned_be24(val, &st->reg_write_tx_buf[1]);
43262306a36Sopenharmony_ci		break;
43362306a36Sopenharmony_ci	case 2:
43462306a36Sopenharmony_ci		put_unaligned_be16(val, &st->reg_write_tx_buf[1]);
43562306a36Sopenharmony_ci		break;
43662306a36Sopenharmony_ci	case 1:
43762306a36Sopenharmony_ci		st->reg_write_tx_buf[1] = val;
43862306a36Sopenharmony_ci		break;
43962306a36Sopenharmony_ci	default:
44062306a36Sopenharmony_ci		return -EINVAL;
44162306a36Sopenharmony_ci	}
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ci	return spi_write(st->spi, st->reg_write_tx_buf, size + 1);
44462306a36Sopenharmony_ci}
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_cistatic int ad4130_reg_read(void *context, unsigned int reg, unsigned int *val)
44762306a36Sopenharmony_ci{
44862306a36Sopenharmony_ci	struct ad4130_state *st = context;
44962306a36Sopenharmony_ci	struct spi_transfer t[] = {
45062306a36Sopenharmony_ci		{
45162306a36Sopenharmony_ci			.tx_buf = st->reg_read_tx_buf,
45262306a36Sopenharmony_ci			.len = sizeof(st->reg_read_tx_buf),
45362306a36Sopenharmony_ci		},
45462306a36Sopenharmony_ci		{
45562306a36Sopenharmony_ci			.rx_buf = st->reg_read_rx_buf,
45662306a36Sopenharmony_ci		},
45762306a36Sopenharmony_ci	};
45862306a36Sopenharmony_ci	unsigned int size;
45962306a36Sopenharmony_ci	int ret;
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci	ret = ad4130_get_reg_size(st, reg, &size);
46262306a36Sopenharmony_ci	if (ret)
46362306a36Sopenharmony_ci		return ret;
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_ci	st->reg_read_tx_buf[0] = AD4130_COMMS_READ_MASK | reg;
46662306a36Sopenharmony_ci	t[1].len = size;
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_ci	ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t));
46962306a36Sopenharmony_ci	if (ret)
47062306a36Sopenharmony_ci		return ret;
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci	switch (size) {
47362306a36Sopenharmony_ci	case 3:
47462306a36Sopenharmony_ci		*val = get_unaligned_be24(st->reg_read_rx_buf);
47562306a36Sopenharmony_ci		break;
47662306a36Sopenharmony_ci	case 2:
47762306a36Sopenharmony_ci		*val = get_unaligned_be16(st->reg_read_rx_buf);
47862306a36Sopenharmony_ci		break;
47962306a36Sopenharmony_ci	case 1:
48062306a36Sopenharmony_ci		*val = st->reg_read_rx_buf[0];
48162306a36Sopenharmony_ci		break;
48262306a36Sopenharmony_ci	default:
48362306a36Sopenharmony_ci		return -EINVAL;
48462306a36Sopenharmony_ci	}
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_ci	return 0;
48762306a36Sopenharmony_ci}
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_cistatic const struct regmap_config ad4130_regmap_config = {
49062306a36Sopenharmony_ci	.reg_read = ad4130_reg_read,
49162306a36Sopenharmony_ci	.reg_write = ad4130_reg_write,
49262306a36Sopenharmony_ci};
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_cistatic int ad4130_gpio_init_valid_mask(struct gpio_chip *gc,
49562306a36Sopenharmony_ci				       unsigned long *valid_mask,
49662306a36Sopenharmony_ci				       unsigned int ngpios)
49762306a36Sopenharmony_ci{
49862306a36Sopenharmony_ci	struct ad4130_state *st = gpiochip_get_data(gc);
49962306a36Sopenharmony_ci	unsigned int i;
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci	/*
50262306a36Sopenharmony_ci	 * Output-only GPIO functionality is available on pins AIN2 through
50362306a36Sopenharmony_ci	 * AIN5. If these pins are used for anything else, do not expose them.
50462306a36Sopenharmony_ci	 */
50562306a36Sopenharmony_ci	for (i = 0; i < ngpios; i++) {
50662306a36Sopenharmony_ci		unsigned int pin = i + AD4130_AIN2_P1;
50762306a36Sopenharmony_ci		bool valid = st->pins_fn[pin] == AD4130_PIN_FN_NONE;
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_ci		__assign_bit(i, valid_mask, valid);
51062306a36Sopenharmony_ci	}
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_ci	return 0;
51362306a36Sopenharmony_ci}
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_cistatic int ad4130_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
51662306a36Sopenharmony_ci{
51762306a36Sopenharmony_ci	return GPIO_LINE_DIRECTION_OUT;
51862306a36Sopenharmony_ci}
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_cistatic void ad4130_gpio_set(struct gpio_chip *gc, unsigned int offset,
52162306a36Sopenharmony_ci			    int value)
52262306a36Sopenharmony_ci{
52362306a36Sopenharmony_ci	struct ad4130_state *st = gpiochip_get_data(gc);
52462306a36Sopenharmony_ci	unsigned int mask = FIELD_PREP(AD4130_IO_CONTROL_GPIO_DATA_MASK,
52562306a36Sopenharmony_ci				       BIT(offset));
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci	regmap_update_bits(st->regmap, AD4130_IO_CONTROL_REG, mask,
52862306a36Sopenharmony_ci			   value ? mask : 0);
52962306a36Sopenharmony_ci}
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_cistatic int ad4130_set_mode(struct ad4130_state *st, enum ad4130_mode mode)
53262306a36Sopenharmony_ci{
53362306a36Sopenharmony_ci	return regmap_update_bits(st->regmap, AD4130_ADC_CONTROL_REG,
53462306a36Sopenharmony_ci				  AD4130_ADC_CONTROL_MODE_MASK,
53562306a36Sopenharmony_ci				  FIELD_PREP(AD4130_ADC_CONTROL_MODE_MASK, mode));
53662306a36Sopenharmony_ci}
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_cistatic int ad4130_set_watermark_interrupt_en(struct ad4130_state *st, bool en)
53962306a36Sopenharmony_ci{
54062306a36Sopenharmony_ci	return regmap_update_bits(st->regmap, AD4130_FIFO_CONTROL_REG,
54162306a36Sopenharmony_ci				  AD4130_FIFO_CONTROL_WM_INT_EN_MASK,
54262306a36Sopenharmony_ci				  FIELD_PREP(AD4130_FIFO_CONTROL_WM_INT_EN_MASK, en));
54362306a36Sopenharmony_ci}
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_cistatic unsigned int ad4130_watermark_reg_val(unsigned int val)
54662306a36Sopenharmony_ci{
54762306a36Sopenharmony_ci	if (val == AD4130_FIFO_SIZE)
54862306a36Sopenharmony_ci		val = AD4130_WATERMARK_256;
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_ci	return val;
55162306a36Sopenharmony_ci}
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_cistatic int ad4130_set_fifo_mode(struct ad4130_state *st,
55462306a36Sopenharmony_ci				enum ad4130_fifo_mode mode)
55562306a36Sopenharmony_ci{
55662306a36Sopenharmony_ci	return regmap_update_bits(st->regmap, AD4130_FIFO_CONTROL_REG,
55762306a36Sopenharmony_ci				  AD4130_FIFO_CONTROL_MODE_MASK,
55862306a36Sopenharmony_ci				  FIELD_PREP(AD4130_FIFO_CONTROL_MODE_MASK, mode));
55962306a36Sopenharmony_ci}
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_cistatic void ad4130_push_fifo_data(struct iio_dev *indio_dev)
56262306a36Sopenharmony_ci{
56362306a36Sopenharmony_ci	struct ad4130_state *st = iio_priv(indio_dev);
56462306a36Sopenharmony_ci	unsigned int data_reg_size = ad4130_data_reg_size(st);
56562306a36Sopenharmony_ci	unsigned int transfer_len = st->effective_watermark * data_reg_size;
56662306a36Sopenharmony_ci	unsigned int set_size = st->num_enabled_channels * data_reg_size;
56762306a36Sopenharmony_ci	unsigned int i;
56862306a36Sopenharmony_ci	int ret;
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_ci	st->fifo_tx_buf[1] = ad4130_watermark_reg_val(st->effective_watermark);
57162306a36Sopenharmony_ci	st->fifo_xfer[1].len = transfer_len;
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_ci	ret = spi_sync(st->spi, &st->fifo_msg);
57462306a36Sopenharmony_ci	if (ret)
57562306a36Sopenharmony_ci		return;
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci	for (i = 0; i < transfer_len; i += set_size)
57862306a36Sopenharmony_ci		iio_push_to_buffers(indio_dev, &st->fifo_rx_buf[i]);
57962306a36Sopenharmony_ci}
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_cistatic irqreturn_t ad4130_irq_handler(int irq, void *private)
58262306a36Sopenharmony_ci{
58362306a36Sopenharmony_ci	struct iio_dev *indio_dev = private;
58462306a36Sopenharmony_ci	struct ad4130_state *st = iio_priv(indio_dev);
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ci	if (iio_buffer_enabled(indio_dev))
58762306a36Sopenharmony_ci		ad4130_push_fifo_data(indio_dev);
58862306a36Sopenharmony_ci	else
58962306a36Sopenharmony_ci		complete(&st->completion);
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci	return IRQ_HANDLED;
59262306a36Sopenharmony_ci}
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_cistatic int ad4130_find_slot(struct ad4130_state *st,
59562306a36Sopenharmony_ci			    struct ad4130_setup_info *target_setup_info,
59662306a36Sopenharmony_ci			    unsigned int *slot, bool *overwrite)
59762306a36Sopenharmony_ci{
59862306a36Sopenharmony_ci	unsigned int i;
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	*slot = AD4130_INVALID_SLOT;
60162306a36Sopenharmony_ci	*overwrite = false;
60262306a36Sopenharmony_ci
60362306a36Sopenharmony_ci	for (i = 0; i < AD4130_MAX_SETUPS; i++) {
60462306a36Sopenharmony_ci		struct ad4130_slot_info *slot_info = &st->slots_info[i];
60562306a36Sopenharmony_ci
60662306a36Sopenharmony_ci		/* Immediately accept a matching setup info. */
60762306a36Sopenharmony_ci		if (!memcmp(target_setup_info, &slot_info->setup,
60862306a36Sopenharmony_ci			    sizeof(*target_setup_info))) {
60962306a36Sopenharmony_ci			*slot = i;
61062306a36Sopenharmony_ci			return 0;
61162306a36Sopenharmony_ci		}
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_ci		/* Ignore all setups which are used by enabled channels. */
61462306a36Sopenharmony_ci		if (slot_info->enabled_channels)
61562306a36Sopenharmony_ci			continue;
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci		/* Find the least used slot. */
61862306a36Sopenharmony_ci		if (*slot == AD4130_INVALID_SLOT ||
61962306a36Sopenharmony_ci		    slot_info->channels < st->slots_info[*slot].channels)
62062306a36Sopenharmony_ci			*slot = i;
62162306a36Sopenharmony_ci	}
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ci	if (*slot == AD4130_INVALID_SLOT)
62462306a36Sopenharmony_ci		return -EINVAL;
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci	*overwrite = true;
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci	return 0;
62962306a36Sopenharmony_ci}
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_cistatic void ad4130_unlink_channel(struct ad4130_state *st, unsigned int channel)
63262306a36Sopenharmony_ci{
63362306a36Sopenharmony_ci	struct ad4130_chan_info *chan_info = &st->chans_info[channel];
63462306a36Sopenharmony_ci	struct ad4130_slot_info *slot_info = &st->slots_info[chan_info->slot];
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_ci	chan_info->slot = AD4130_INVALID_SLOT;
63762306a36Sopenharmony_ci	slot_info->channels--;
63862306a36Sopenharmony_ci}
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_cistatic int ad4130_unlink_slot(struct ad4130_state *st, unsigned int slot)
64162306a36Sopenharmony_ci{
64262306a36Sopenharmony_ci	unsigned int i;
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	for (i = 0; i < AD4130_MAX_CHANNELS; i++) {
64562306a36Sopenharmony_ci		struct ad4130_chan_info *chan_info = &st->chans_info[i];
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_ci		if (!chan_info->initialized || chan_info->slot != slot)
64862306a36Sopenharmony_ci			continue;
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci		ad4130_unlink_channel(st, i);
65162306a36Sopenharmony_ci	}
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_ci	return 0;
65462306a36Sopenharmony_ci}
65562306a36Sopenharmony_ci
65662306a36Sopenharmony_cistatic int ad4130_link_channel_slot(struct ad4130_state *st,
65762306a36Sopenharmony_ci				    unsigned int channel, unsigned int slot)
65862306a36Sopenharmony_ci{
65962306a36Sopenharmony_ci	struct ad4130_slot_info *slot_info = &st->slots_info[slot];
66062306a36Sopenharmony_ci	struct ad4130_chan_info *chan_info = &st->chans_info[channel];
66162306a36Sopenharmony_ci	int ret;
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci	ret = regmap_update_bits(st->regmap, AD4130_CHANNEL_X_REG(channel),
66462306a36Sopenharmony_ci				 AD4130_CHANNEL_SETUP_MASK,
66562306a36Sopenharmony_ci				 FIELD_PREP(AD4130_CHANNEL_SETUP_MASK, slot));
66662306a36Sopenharmony_ci	if (ret)
66762306a36Sopenharmony_ci		return ret;
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ci	chan_info->slot = slot;
67062306a36Sopenharmony_ci	slot_info->channels++;
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci	return 0;
67362306a36Sopenharmony_ci}
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_cistatic int ad4130_write_slot_setup(struct ad4130_state *st,
67662306a36Sopenharmony_ci				   unsigned int slot,
67762306a36Sopenharmony_ci				   struct ad4130_setup_info *setup_info)
67862306a36Sopenharmony_ci{
67962306a36Sopenharmony_ci	unsigned int val;
68062306a36Sopenharmony_ci	int ret;
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_ci	val = FIELD_PREP(AD4130_CONFIG_IOUT1_VAL_MASK, setup_info->iout0_val) |
68362306a36Sopenharmony_ci	      FIELD_PREP(AD4130_CONFIG_IOUT1_VAL_MASK, setup_info->iout1_val) |
68462306a36Sopenharmony_ci	      FIELD_PREP(AD4130_CONFIG_BURNOUT_MASK, setup_info->burnout) |
68562306a36Sopenharmony_ci	      FIELD_PREP(AD4130_CONFIG_REF_BUFP_MASK, setup_info->ref_bufp) |
68662306a36Sopenharmony_ci	      FIELD_PREP(AD4130_CONFIG_REF_BUFM_MASK, setup_info->ref_bufm) |
68762306a36Sopenharmony_ci	      FIELD_PREP(AD4130_CONFIG_REF_SEL_MASK, setup_info->ref_sel) |
68862306a36Sopenharmony_ci	      FIELD_PREP(AD4130_CONFIG_PGA_MASK, setup_info->pga);
68962306a36Sopenharmony_ci
69062306a36Sopenharmony_ci	ret = regmap_write(st->regmap, AD4130_CONFIG_X_REG(slot), val);
69162306a36Sopenharmony_ci	if (ret)
69262306a36Sopenharmony_ci		return ret;
69362306a36Sopenharmony_ci
69462306a36Sopenharmony_ci	val = FIELD_PREP(AD4130_FILTER_MODE_MASK, setup_info->filter_mode) |
69562306a36Sopenharmony_ci	      FIELD_PREP(AD4130_FILTER_SELECT_MASK, setup_info->fs);
69662306a36Sopenharmony_ci
69762306a36Sopenharmony_ci	ret = regmap_write(st->regmap, AD4130_FILTER_X_REG(slot), val);
69862306a36Sopenharmony_ci	if (ret)
69962306a36Sopenharmony_ci		return ret;
70062306a36Sopenharmony_ci
70162306a36Sopenharmony_ci	memcpy(&st->slots_info[slot].setup, setup_info, sizeof(*setup_info));
70262306a36Sopenharmony_ci
70362306a36Sopenharmony_ci	return 0;
70462306a36Sopenharmony_ci}
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_cistatic int ad4130_write_channel_setup(struct ad4130_state *st,
70762306a36Sopenharmony_ci				      unsigned int channel, bool on_enable)
70862306a36Sopenharmony_ci{
70962306a36Sopenharmony_ci	struct ad4130_chan_info *chan_info = &st->chans_info[channel];
71062306a36Sopenharmony_ci	struct ad4130_setup_info *setup_info = &chan_info->setup;
71162306a36Sopenharmony_ci	bool overwrite;
71262306a36Sopenharmony_ci	int slot;
71362306a36Sopenharmony_ci	int ret;
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_ci	/*
71662306a36Sopenharmony_ci	 * The following cases need to be handled.
71762306a36Sopenharmony_ci	 *
71862306a36Sopenharmony_ci	 * 1. Enabled and linked channel with setup changes:
71962306a36Sopenharmony_ci	 *    - Find a slot. If not possible, return error.
72062306a36Sopenharmony_ci	 *    - Unlink channel from current slot.
72162306a36Sopenharmony_ci	 *    - If the slot has channels linked to it, unlink all channels, and
72262306a36Sopenharmony_ci	 *      write the new setup to it.
72362306a36Sopenharmony_ci	 *    - Link channel to new slot.
72462306a36Sopenharmony_ci	 *
72562306a36Sopenharmony_ci	 * 2. Soon to be enabled and unlinked channel:
72662306a36Sopenharmony_ci	 *    - Find a slot. If not possible, return error.
72762306a36Sopenharmony_ci	 *    - If the slot has channels linked to it, unlink all channels, and
72862306a36Sopenharmony_ci	 *      write the new setup to it.
72962306a36Sopenharmony_ci	 *    - Link channel to the slot.
73062306a36Sopenharmony_ci	 *
73162306a36Sopenharmony_ci	 * 3. Disabled and linked channel with setup changes:
73262306a36Sopenharmony_ci	 *    - Unlink channel from current slot.
73362306a36Sopenharmony_ci	 *
73462306a36Sopenharmony_ci	 * 4. Soon to be enabled and linked channel:
73562306a36Sopenharmony_ci	 * 5. Disabled and unlinked channel with setup changes:
73662306a36Sopenharmony_ci	 *    - Do nothing.
73762306a36Sopenharmony_ci	 */
73862306a36Sopenharmony_ci
73962306a36Sopenharmony_ci	/* Case 4 */
74062306a36Sopenharmony_ci	if (on_enable && chan_info->slot != AD4130_INVALID_SLOT)
74162306a36Sopenharmony_ci		return 0;
74262306a36Sopenharmony_ci
74362306a36Sopenharmony_ci	if (!on_enable && !chan_info->enabled) {
74462306a36Sopenharmony_ci		if (chan_info->slot != AD4130_INVALID_SLOT)
74562306a36Sopenharmony_ci			/* Case 3 */
74662306a36Sopenharmony_ci			ad4130_unlink_channel(st, channel);
74762306a36Sopenharmony_ci
74862306a36Sopenharmony_ci		/* Cases 3 & 5 */
74962306a36Sopenharmony_ci		return 0;
75062306a36Sopenharmony_ci	}
75162306a36Sopenharmony_ci
75262306a36Sopenharmony_ci	/* Cases 1 & 2 */
75362306a36Sopenharmony_ci	ret = ad4130_find_slot(st, setup_info, &slot, &overwrite);
75462306a36Sopenharmony_ci	if (ret)
75562306a36Sopenharmony_ci		return ret;
75662306a36Sopenharmony_ci
75762306a36Sopenharmony_ci	if (chan_info->slot != AD4130_INVALID_SLOT)
75862306a36Sopenharmony_ci		/* Case 1 */
75962306a36Sopenharmony_ci		ad4130_unlink_channel(st, channel);
76062306a36Sopenharmony_ci
76162306a36Sopenharmony_ci	if (overwrite) {
76262306a36Sopenharmony_ci		ret = ad4130_unlink_slot(st, slot);
76362306a36Sopenharmony_ci		if (ret)
76462306a36Sopenharmony_ci			return ret;
76562306a36Sopenharmony_ci
76662306a36Sopenharmony_ci		ret = ad4130_write_slot_setup(st, slot, setup_info);
76762306a36Sopenharmony_ci		if (ret)
76862306a36Sopenharmony_ci			return ret;
76962306a36Sopenharmony_ci	}
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ci	return ad4130_link_channel_slot(st, channel, slot);
77262306a36Sopenharmony_ci}
77362306a36Sopenharmony_ci
77462306a36Sopenharmony_cistatic int ad4130_set_channel_enable(struct ad4130_state *st,
77562306a36Sopenharmony_ci				     unsigned int channel, bool status)
77662306a36Sopenharmony_ci{
77762306a36Sopenharmony_ci	struct ad4130_chan_info *chan_info = &st->chans_info[channel];
77862306a36Sopenharmony_ci	struct ad4130_slot_info *slot_info;
77962306a36Sopenharmony_ci	int ret;
78062306a36Sopenharmony_ci
78162306a36Sopenharmony_ci	if (chan_info->enabled == status)
78262306a36Sopenharmony_ci		return 0;
78362306a36Sopenharmony_ci
78462306a36Sopenharmony_ci	if (status) {
78562306a36Sopenharmony_ci		ret = ad4130_write_channel_setup(st, channel, true);
78662306a36Sopenharmony_ci		if (ret)
78762306a36Sopenharmony_ci			return ret;
78862306a36Sopenharmony_ci	}
78962306a36Sopenharmony_ci
79062306a36Sopenharmony_ci	slot_info = &st->slots_info[chan_info->slot];
79162306a36Sopenharmony_ci
79262306a36Sopenharmony_ci	ret = regmap_update_bits(st->regmap, AD4130_CHANNEL_X_REG(channel),
79362306a36Sopenharmony_ci				 AD4130_CHANNEL_EN_MASK,
79462306a36Sopenharmony_ci				 FIELD_PREP(AD4130_CHANNEL_EN_MASK, status));
79562306a36Sopenharmony_ci	if (ret)
79662306a36Sopenharmony_ci		return ret;
79762306a36Sopenharmony_ci
79862306a36Sopenharmony_ci	slot_info->enabled_channels += status ? 1 : -1;
79962306a36Sopenharmony_ci	chan_info->enabled = status;
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_ci	return 0;
80262306a36Sopenharmony_ci}
80362306a36Sopenharmony_ci
80462306a36Sopenharmony_ci/*
80562306a36Sopenharmony_ci * Table 58. FILTER_MODE_n bits and Filter Types of the datasheet describes
80662306a36Sopenharmony_ci * the relation between filter mode, ODR and FS.
80762306a36Sopenharmony_ci *
80862306a36Sopenharmony_ci * Notice that the max ODR of each filter mode is not necessarily the
80962306a36Sopenharmony_ci * absolute max ODR supported by the chip.
81062306a36Sopenharmony_ci *
81162306a36Sopenharmony_ci * The ODR divider is not explicitly specified, but it can be deduced based
81262306a36Sopenharmony_ci * on the ODR range of each filter mode.
81362306a36Sopenharmony_ci *
81462306a36Sopenharmony_ci * For example, for Sinc4+Sinc1, max ODR is 218.18. That means that the
81562306a36Sopenharmony_ci * absolute max ODR is divided by 11 to achieve the max ODR of this filter
81662306a36Sopenharmony_ci * mode.
81762306a36Sopenharmony_ci *
81862306a36Sopenharmony_ci * The formulas for converting between ODR and FS for a specific filter
81962306a36Sopenharmony_ci * mode can be deduced from the same table.
82062306a36Sopenharmony_ci *
82162306a36Sopenharmony_ci * Notice that FS = 1 actually means max ODR, and that ODR decreases by
82262306a36Sopenharmony_ci * (maximum ODR / maximum FS) for each increment of FS.
82362306a36Sopenharmony_ci *
82462306a36Sopenharmony_ci * odr = MAX_ODR / odr_div * (1 - (fs - 1) / fs_max) <=>
82562306a36Sopenharmony_ci * odr = MAX_ODR * (1 - (fs - 1) / fs_max) / odr_div <=>
82662306a36Sopenharmony_ci * odr = MAX_ODR * (1 - (fs - 1) / fs_max) / odr_div <=>
82762306a36Sopenharmony_ci * odr = MAX_ODR * (fs_max - fs + 1) / (fs_max * odr_div)
82862306a36Sopenharmony_ci * (used in ad4130_fs_to_freq)
82962306a36Sopenharmony_ci *
83062306a36Sopenharmony_ci * For the opposite formula, FS can be extracted from the last one.
83162306a36Sopenharmony_ci *
83262306a36Sopenharmony_ci * MAX_ODR * (fs_max - fs + 1) = fs_max * odr_div * odr <=>
83362306a36Sopenharmony_ci * fs_max - fs + 1 = fs_max * odr_div * odr / MAX_ODR <=>
83462306a36Sopenharmony_ci * fs = 1 + fs_max - fs_max * odr_div * odr / MAX_ODR
83562306a36Sopenharmony_ci * (used in ad4130_fs_to_freq)
83662306a36Sopenharmony_ci */
83762306a36Sopenharmony_ci
83862306a36Sopenharmony_cistatic void ad4130_freq_to_fs(enum ad4130_filter_mode filter_mode,
83962306a36Sopenharmony_ci			      int val, int val2, unsigned int *fs)
84062306a36Sopenharmony_ci{
84162306a36Sopenharmony_ci	const struct ad4130_filter_config *filter_config =
84262306a36Sopenharmony_ci		&ad4130_filter_configs[filter_mode];
84362306a36Sopenharmony_ci	u64 dividend, divisor;
84462306a36Sopenharmony_ci	int temp;
84562306a36Sopenharmony_ci
84662306a36Sopenharmony_ci	dividend = filter_config->fs_max * filter_config->odr_div *
84762306a36Sopenharmony_ci		   ((u64)val * NANO + val2);
84862306a36Sopenharmony_ci	divisor = (u64)AD4130_MAX_ODR * NANO;
84962306a36Sopenharmony_ci
85062306a36Sopenharmony_ci	temp = AD4130_FILTER_SELECT_MIN + filter_config->fs_max -
85162306a36Sopenharmony_ci	       DIV64_U64_ROUND_CLOSEST(dividend, divisor);
85262306a36Sopenharmony_ci
85362306a36Sopenharmony_ci	if (temp < AD4130_FILTER_SELECT_MIN)
85462306a36Sopenharmony_ci		temp = AD4130_FILTER_SELECT_MIN;
85562306a36Sopenharmony_ci	else if (temp > filter_config->fs_max)
85662306a36Sopenharmony_ci		temp = filter_config->fs_max;
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_ci	*fs = temp;
85962306a36Sopenharmony_ci}
86062306a36Sopenharmony_ci
86162306a36Sopenharmony_cistatic void ad4130_fs_to_freq(enum ad4130_filter_mode filter_mode,
86262306a36Sopenharmony_ci			      unsigned int fs, int *val, int *val2)
86362306a36Sopenharmony_ci{
86462306a36Sopenharmony_ci	const struct ad4130_filter_config *filter_config =
86562306a36Sopenharmony_ci		&ad4130_filter_configs[filter_mode];
86662306a36Sopenharmony_ci	unsigned int dividend, divisor;
86762306a36Sopenharmony_ci	u64 temp;
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_ci	dividend = (filter_config->fs_max - fs + AD4130_FILTER_SELECT_MIN) *
87062306a36Sopenharmony_ci		   AD4130_MAX_ODR;
87162306a36Sopenharmony_ci	divisor = filter_config->fs_max * filter_config->odr_div;
87262306a36Sopenharmony_ci
87362306a36Sopenharmony_ci	temp = div_u64((u64)dividend * NANO, divisor);
87462306a36Sopenharmony_ci	*val = div_u64_rem(temp, NANO, val2);
87562306a36Sopenharmony_ci}
87662306a36Sopenharmony_ci
87762306a36Sopenharmony_cistatic int ad4130_set_filter_mode(struct iio_dev *indio_dev,
87862306a36Sopenharmony_ci				  const struct iio_chan_spec *chan,
87962306a36Sopenharmony_ci				  unsigned int val)
88062306a36Sopenharmony_ci{
88162306a36Sopenharmony_ci	struct ad4130_state *st = iio_priv(indio_dev);
88262306a36Sopenharmony_ci	unsigned int channel = chan->scan_index;
88362306a36Sopenharmony_ci	struct ad4130_chan_info *chan_info = &st->chans_info[channel];
88462306a36Sopenharmony_ci	struct ad4130_setup_info *setup_info = &chan_info->setup;
88562306a36Sopenharmony_ci	enum ad4130_filter_mode old_filter_mode;
88662306a36Sopenharmony_ci	int freq_val, freq_val2;
88762306a36Sopenharmony_ci	unsigned int old_fs;
88862306a36Sopenharmony_ci	int ret = 0;
88962306a36Sopenharmony_ci
89062306a36Sopenharmony_ci	mutex_lock(&st->lock);
89162306a36Sopenharmony_ci	if (setup_info->filter_mode == val)
89262306a36Sopenharmony_ci		goto out;
89362306a36Sopenharmony_ci
89462306a36Sopenharmony_ci	old_fs = setup_info->fs;
89562306a36Sopenharmony_ci	old_filter_mode = setup_info->filter_mode;
89662306a36Sopenharmony_ci
89762306a36Sopenharmony_ci	/*
89862306a36Sopenharmony_ci	 * When switching between filter modes, try to match the ODR as
89962306a36Sopenharmony_ci	 * close as possible. To do this, convert the current FS into ODR
90062306a36Sopenharmony_ci	 * using the old filter mode, then convert it back into FS using
90162306a36Sopenharmony_ci	 * the new filter mode.
90262306a36Sopenharmony_ci	 */
90362306a36Sopenharmony_ci	ad4130_fs_to_freq(setup_info->filter_mode, setup_info->fs,
90462306a36Sopenharmony_ci			  &freq_val, &freq_val2);
90562306a36Sopenharmony_ci
90662306a36Sopenharmony_ci	ad4130_freq_to_fs(val, freq_val, freq_val2, &setup_info->fs);
90762306a36Sopenharmony_ci
90862306a36Sopenharmony_ci	setup_info->filter_mode = val;
90962306a36Sopenharmony_ci
91062306a36Sopenharmony_ci	ret = ad4130_write_channel_setup(st, channel, false);
91162306a36Sopenharmony_ci	if (ret) {
91262306a36Sopenharmony_ci		setup_info->fs = old_fs;
91362306a36Sopenharmony_ci		setup_info->filter_mode = old_filter_mode;
91462306a36Sopenharmony_ci	}
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_ci out:
91762306a36Sopenharmony_ci	mutex_unlock(&st->lock);
91862306a36Sopenharmony_ci
91962306a36Sopenharmony_ci	return ret;
92062306a36Sopenharmony_ci}
92162306a36Sopenharmony_ci
92262306a36Sopenharmony_cistatic int ad4130_get_filter_mode(struct iio_dev *indio_dev,
92362306a36Sopenharmony_ci				  const struct iio_chan_spec *chan)
92462306a36Sopenharmony_ci{
92562306a36Sopenharmony_ci	struct ad4130_state *st = iio_priv(indio_dev);
92662306a36Sopenharmony_ci	unsigned int channel = chan->scan_index;
92762306a36Sopenharmony_ci	struct ad4130_setup_info *setup_info = &st->chans_info[channel].setup;
92862306a36Sopenharmony_ci	enum ad4130_filter_mode filter_mode;
92962306a36Sopenharmony_ci
93062306a36Sopenharmony_ci	mutex_lock(&st->lock);
93162306a36Sopenharmony_ci	filter_mode = setup_info->filter_mode;
93262306a36Sopenharmony_ci	mutex_unlock(&st->lock);
93362306a36Sopenharmony_ci
93462306a36Sopenharmony_ci	return filter_mode;
93562306a36Sopenharmony_ci}
93662306a36Sopenharmony_ci
93762306a36Sopenharmony_cistatic const struct iio_enum ad4130_filter_mode_enum = {
93862306a36Sopenharmony_ci	.items = ad4130_filter_modes_str,
93962306a36Sopenharmony_ci	.num_items = ARRAY_SIZE(ad4130_filter_modes_str),
94062306a36Sopenharmony_ci	.set = ad4130_set_filter_mode,
94162306a36Sopenharmony_ci	.get = ad4130_get_filter_mode,
94262306a36Sopenharmony_ci};
94362306a36Sopenharmony_ci
94462306a36Sopenharmony_cistatic const struct iio_chan_spec_ext_info ad4130_filter_mode_ext_info[] = {
94562306a36Sopenharmony_ci	IIO_ENUM("filter_mode", IIO_SEPARATE, &ad4130_filter_mode_enum),
94662306a36Sopenharmony_ci	IIO_ENUM_AVAILABLE("filter_mode", IIO_SHARED_BY_TYPE,
94762306a36Sopenharmony_ci			   &ad4130_filter_mode_enum),
94862306a36Sopenharmony_ci	{ }
94962306a36Sopenharmony_ci};
95062306a36Sopenharmony_ci
95162306a36Sopenharmony_cistatic const struct iio_chan_spec ad4130_channel_template = {
95262306a36Sopenharmony_ci	.type = IIO_VOLTAGE,
95362306a36Sopenharmony_ci	.indexed = 1,
95462306a36Sopenharmony_ci	.differential = 1,
95562306a36Sopenharmony_ci	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
95662306a36Sopenharmony_ci			      BIT(IIO_CHAN_INFO_SCALE) |
95762306a36Sopenharmony_ci			      BIT(IIO_CHAN_INFO_OFFSET) |
95862306a36Sopenharmony_ci			      BIT(IIO_CHAN_INFO_SAMP_FREQ),
95962306a36Sopenharmony_ci	.info_mask_separate_available = BIT(IIO_CHAN_INFO_SCALE) |
96062306a36Sopenharmony_ci					BIT(IIO_CHAN_INFO_SAMP_FREQ),
96162306a36Sopenharmony_ci	.ext_info = ad4130_filter_mode_ext_info,
96262306a36Sopenharmony_ci	.scan_type = {
96362306a36Sopenharmony_ci		.sign = 'u',
96462306a36Sopenharmony_ci		.endianness = IIO_BE,
96562306a36Sopenharmony_ci	},
96662306a36Sopenharmony_ci};
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_cistatic int ad4130_set_channel_pga(struct ad4130_state *st, unsigned int channel,
96962306a36Sopenharmony_ci				  int val, int val2)
97062306a36Sopenharmony_ci{
97162306a36Sopenharmony_ci	struct ad4130_chan_info *chan_info = &st->chans_info[channel];
97262306a36Sopenharmony_ci	struct ad4130_setup_info *setup_info = &chan_info->setup;
97362306a36Sopenharmony_ci	unsigned int pga, old_pga;
97462306a36Sopenharmony_ci	int ret = 0;
97562306a36Sopenharmony_ci
97662306a36Sopenharmony_ci	for (pga = 0; pga < AD4130_MAX_PGA; pga++)
97762306a36Sopenharmony_ci		if (val == st->scale_tbls[setup_info->ref_sel][pga][0] &&
97862306a36Sopenharmony_ci		    val2 == st->scale_tbls[setup_info->ref_sel][pga][1])
97962306a36Sopenharmony_ci			break;
98062306a36Sopenharmony_ci
98162306a36Sopenharmony_ci	if (pga == AD4130_MAX_PGA)
98262306a36Sopenharmony_ci		return -EINVAL;
98362306a36Sopenharmony_ci
98462306a36Sopenharmony_ci	mutex_lock(&st->lock);
98562306a36Sopenharmony_ci	if (pga == setup_info->pga)
98662306a36Sopenharmony_ci		goto out;
98762306a36Sopenharmony_ci
98862306a36Sopenharmony_ci	old_pga = setup_info->pga;
98962306a36Sopenharmony_ci	setup_info->pga = pga;
99062306a36Sopenharmony_ci
99162306a36Sopenharmony_ci	ret = ad4130_write_channel_setup(st, channel, false);
99262306a36Sopenharmony_ci	if (ret)
99362306a36Sopenharmony_ci		setup_info->pga = old_pga;
99462306a36Sopenharmony_ci
99562306a36Sopenharmony_ciout:
99662306a36Sopenharmony_ci	mutex_unlock(&st->lock);
99762306a36Sopenharmony_ci
99862306a36Sopenharmony_ci	return ret;
99962306a36Sopenharmony_ci}
100062306a36Sopenharmony_ci
100162306a36Sopenharmony_cistatic int ad4130_set_channel_freq(struct ad4130_state *st,
100262306a36Sopenharmony_ci				   unsigned int channel, int val, int val2)
100362306a36Sopenharmony_ci{
100462306a36Sopenharmony_ci	struct ad4130_chan_info *chan_info = &st->chans_info[channel];
100562306a36Sopenharmony_ci	struct ad4130_setup_info *setup_info = &chan_info->setup;
100662306a36Sopenharmony_ci	unsigned int fs, old_fs;
100762306a36Sopenharmony_ci	int ret = 0;
100862306a36Sopenharmony_ci
100962306a36Sopenharmony_ci	mutex_lock(&st->lock);
101062306a36Sopenharmony_ci	old_fs = setup_info->fs;
101162306a36Sopenharmony_ci
101262306a36Sopenharmony_ci	ad4130_freq_to_fs(setup_info->filter_mode, val, val2, &fs);
101362306a36Sopenharmony_ci
101462306a36Sopenharmony_ci	if (fs == setup_info->fs)
101562306a36Sopenharmony_ci		goto out;
101662306a36Sopenharmony_ci
101762306a36Sopenharmony_ci	setup_info->fs = fs;
101862306a36Sopenharmony_ci
101962306a36Sopenharmony_ci	ret = ad4130_write_channel_setup(st, channel, false);
102062306a36Sopenharmony_ci	if (ret)
102162306a36Sopenharmony_ci		setup_info->fs = old_fs;
102262306a36Sopenharmony_ci
102362306a36Sopenharmony_ciout:
102462306a36Sopenharmony_ci	mutex_unlock(&st->lock);
102562306a36Sopenharmony_ci
102662306a36Sopenharmony_ci	return ret;
102762306a36Sopenharmony_ci}
102862306a36Sopenharmony_ci
102962306a36Sopenharmony_cistatic int _ad4130_read_sample(struct iio_dev *indio_dev, unsigned int channel,
103062306a36Sopenharmony_ci			       int *val)
103162306a36Sopenharmony_ci{
103262306a36Sopenharmony_ci	struct ad4130_state *st = iio_priv(indio_dev);
103362306a36Sopenharmony_ci	int ret;
103462306a36Sopenharmony_ci
103562306a36Sopenharmony_ci	ret = ad4130_set_channel_enable(st, channel, true);
103662306a36Sopenharmony_ci	if (ret)
103762306a36Sopenharmony_ci		return ret;
103862306a36Sopenharmony_ci
103962306a36Sopenharmony_ci	reinit_completion(&st->completion);
104062306a36Sopenharmony_ci
104162306a36Sopenharmony_ci	ret = ad4130_set_mode(st, AD4130_MODE_CONTINUOUS);
104262306a36Sopenharmony_ci	if (ret)
104362306a36Sopenharmony_ci		return ret;
104462306a36Sopenharmony_ci
104562306a36Sopenharmony_ci	ret = wait_for_completion_timeout(&st->completion,
104662306a36Sopenharmony_ci					  msecs_to_jiffies(1000));
104762306a36Sopenharmony_ci	if (!ret)
104862306a36Sopenharmony_ci		return -ETIMEDOUT;
104962306a36Sopenharmony_ci
105062306a36Sopenharmony_ci	ret = ad4130_set_mode(st, AD4130_MODE_IDLE);
105162306a36Sopenharmony_ci	if (ret)
105262306a36Sopenharmony_ci		return ret;
105362306a36Sopenharmony_ci
105462306a36Sopenharmony_ci	ret = regmap_read(st->regmap, AD4130_DATA_REG, val);
105562306a36Sopenharmony_ci	if (ret)
105662306a36Sopenharmony_ci		return ret;
105762306a36Sopenharmony_ci
105862306a36Sopenharmony_ci	ret = ad4130_set_channel_enable(st, channel, false);
105962306a36Sopenharmony_ci	if (ret)
106062306a36Sopenharmony_ci		return ret;
106162306a36Sopenharmony_ci
106262306a36Sopenharmony_ci	return IIO_VAL_INT;
106362306a36Sopenharmony_ci}
106462306a36Sopenharmony_ci
106562306a36Sopenharmony_cistatic int ad4130_read_sample(struct iio_dev *indio_dev, unsigned int channel,
106662306a36Sopenharmony_ci			      int *val)
106762306a36Sopenharmony_ci{
106862306a36Sopenharmony_ci	struct ad4130_state *st = iio_priv(indio_dev);
106962306a36Sopenharmony_ci	int ret;
107062306a36Sopenharmony_ci
107162306a36Sopenharmony_ci	ret = iio_device_claim_direct_mode(indio_dev);
107262306a36Sopenharmony_ci	if (ret)
107362306a36Sopenharmony_ci		return ret;
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_ci	mutex_lock(&st->lock);
107662306a36Sopenharmony_ci	ret = _ad4130_read_sample(indio_dev, channel, val);
107762306a36Sopenharmony_ci	mutex_unlock(&st->lock);
107862306a36Sopenharmony_ci
107962306a36Sopenharmony_ci	iio_device_release_direct_mode(indio_dev);
108062306a36Sopenharmony_ci
108162306a36Sopenharmony_ci	return ret;
108262306a36Sopenharmony_ci}
108362306a36Sopenharmony_ci
108462306a36Sopenharmony_cistatic int ad4130_read_raw(struct iio_dev *indio_dev,
108562306a36Sopenharmony_ci			   struct iio_chan_spec const *chan,
108662306a36Sopenharmony_ci			   int *val, int *val2, long info)
108762306a36Sopenharmony_ci{
108862306a36Sopenharmony_ci	struct ad4130_state *st = iio_priv(indio_dev);
108962306a36Sopenharmony_ci	unsigned int channel = chan->scan_index;
109062306a36Sopenharmony_ci	struct ad4130_setup_info *setup_info = &st->chans_info[channel].setup;
109162306a36Sopenharmony_ci
109262306a36Sopenharmony_ci	switch (info) {
109362306a36Sopenharmony_ci	case IIO_CHAN_INFO_RAW:
109462306a36Sopenharmony_ci		return ad4130_read_sample(indio_dev, channel, val);
109562306a36Sopenharmony_ci	case IIO_CHAN_INFO_SCALE:
109662306a36Sopenharmony_ci		mutex_lock(&st->lock);
109762306a36Sopenharmony_ci		*val = st->scale_tbls[setup_info->ref_sel][setup_info->pga][0];
109862306a36Sopenharmony_ci		*val2 = st->scale_tbls[setup_info->ref_sel][setup_info->pga][1];
109962306a36Sopenharmony_ci		mutex_unlock(&st->lock);
110062306a36Sopenharmony_ci
110162306a36Sopenharmony_ci		return IIO_VAL_INT_PLUS_NANO;
110262306a36Sopenharmony_ci	case IIO_CHAN_INFO_OFFSET:
110362306a36Sopenharmony_ci		*val = st->bipolar ? -BIT(chan->scan_type.realbits - 1) : 0;
110462306a36Sopenharmony_ci
110562306a36Sopenharmony_ci		return IIO_VAL_INT;
110662306a36Sopenharmony_ci	case IIO_CHAN_INFO_SAMP_FREQ:
110762306a36Sopenharmony_ci		mutex_lock(&st->lock);
110862306a36Sopenharmony_ci		ad4130_fs_to_freq(setup_info->filter_mode, setup_info->fs,
110962306a36Sopenharmony_ci				  val, val2);
111062306a36Sopenharmony_ci		mutex_unlock(&st->lock);
111162306a36Sopenharmony_ci
111262306a36Sopenharmony_ci		return IIO_VAL_INT_PLUS_NANO;
111362306a36Sopenharmony_ci	default:
111462306a36Sopenharmony_ci		return -EINVAL;
111562306a36Sopenharmony_ci	}
111662306a36Sopenharmony_ci}
111762306a36Sopenharmony_ci
111862306a36Sopenharmony_cistatic int ad4130_read_avail(struct iio_dev *indio_dev,
111962306a36Sopenharmony_ci			     struct iio_chan_spec const *chan,
112062306a36Sopenharmony_ci			     const int **vals, int *type, int *length,
112162306a36Sopenharmony_ci			     long info)
112262306a36Sopenharmony_ci{
112362306a36Sopenharmony_ci	struct ad4130_state *st = iio_priv(indio_dev);
112462306a36Sopenharmony_ci	unsigned int channel = chan->scan_index;
112562306a36Sopenharmony_ci	struct ad4130_setup_info *setup_info = &st->chans_info[channel].setup;
112662306a36Sopenharmony_ci	const struct ad4130_filter_config *filter_config;
112762306a36Sopenharmony_ci
112862306a36Sopenharmony_ci	switch (info) {
112962306a36Sopenharmony_ci	case IIO_CHAN_INFO_SCALE:
113062306a36Sopenharmony_ci		*vals = (int *)st->scale_tbls[setup_info->ref_sel];
113162306a36Sopenharmony_ci		*length = ARRAY_SIZE(st->scale_tbls[setup_info->ref_sel]) * 2;
113262306a36Sopenharmony_ci
113362306a36Sopenharmony_ci		*type = IIO_VAL_INT_PLUS_NANO;
113462306a36Sopenharmony_ci
113562306a36Sopenharmony_ci		return IIO_AVAIL_LIST;
113662306a36Sopenharmony_ci	case IIO_CHAN_INFO_SAMP_FREQ:
113762306a36Sopenharmony_ci		mutex_lock(&st->lock);
113862306a36Sopenharmony_ci		filter_config = &ad4130_filter_configs[setup_info->filter_mode];
113962306a36Sopenharmony_ci		mutex_unlock(&st->lock);
114062306a36Sopenharmony_ci
114162306a36Sopenharmony_ci		*vals = (int *)filter_config->samp_freq_avail;
114262306a36Sopenharmony_ci		*length = filter_config->samp_freq_avail_len * 2;
114362306a36Sopenharmony_ci		*type = IIO_VAL_FRACTIONAL;
114462306a36Sopenharmony_ci
114562306a36Sopenharmony_ci		return filter_config->samp_freq_avail_type;
114662306a36Sopenharmony_ci	default:
114762306a36Sopenharmony_ci		return -EINVAL;
114862306a36Sopenharmony_ci	}
114962306a36Sopenharmony_ci}
115062306a36Sopenharmony_ci
115162306a36Sopenharmony_cistatic int ad4130_write_raw_get_fmt(struct iio_dev *indio_dev,
115262306a36Sopenharmony_ci				    struct iio_chan_spec const *chan,
115362306a36Sopenharmony_ci				    long info)
115462306a36Sopenharmony_ci{
115562306a36Sopenharmony_ci	switch (info) {
115662306a36Sopenharmony_ci	case IIO_CHAN_INFO_SCALE:
115762306a36Sopenharmony_ci	case IIO_CHAN_INFO_SAMP_FREQ:
115862306a36Sopenharmony_ci		return IIO_VAL_INT_PLUS_NANO;
115962306a36Sopenharmony_ci	default:
116062306a36Sopenharmony_ci		return -EINVAL;
116162306a36Sopenharmony_ci	}
116262306a36Sopenharmony_ci}
116362306a36Sopenharmony_ci
116462306a36Sopenharmony_cistatic int ad4130_write_raw(struct iio_dev *indio_dev,
116562306a36Sopenharmony_ci			    struct iio_chan_spec const *chan,
116662306a36Sopenharmony_ci			    int val, int val2, long info)
116762306a36Sopenharmony_ci{
116862306a36Sopenharmony_ci	struct ad4130_state *st = iio_priv(indio_dev);
116962306a36Sopenharmony_ci	unsigned int channel = chan->scan_index;
117062306a36Sopenharmony_ci
117162306a36Sopenharmony_ci	switch (info) {
117262306a36Sopenharmony_ci	case IIO_CHAN_INFO_SCALE:
117362306a36Sopenharmony_ci		return ad4130_set_channel_pga(st, channel, val, val2);
117462306a36Sopenharmony_ci	case IIO_CHAN_INFO_SAMP_FREQ:
117562306a36Sopenharmony_ci		return ad4130_set_channel_freq(st, channel, val, val2);
117662306a36Sopenharmony_ci	default:
117762306a36Sopenharmony_ci		return -EINVAL;
117862306a36Sopenharmony_ci	}
117962306a36Sopenharmony_ci}
118062306a36Sopenharmony_ci
118162306a36Sopenharmony_cistatic int ad4130_reg_access(struct iio_dev *indio_dev, unsigned int reg,
118262306a36Sopenharmony_ci			     unsigned int writeval, unsigned int *readval)
118362306a36Sopenharmony_ci{
118462306a36Sopenharmony_ci	struct ad4130_state *st = iio_priv(indio_dev);
118562306a36Sopenharmony_ci
118662306a36Sopenharmony_ci	if (readval)
118762306a36Sopenharmony_ci		return regmap_read(st->regmap, reg, readval);
118862306a36Sopenharmony_ci
118962306a36Sopenharmony_ci	return regmap_write(st->regmap, reg, writeval);
119062306a36Sopenharmony_ci}
119162306a36Sopenharmony_ci
119262306a36Sopenharmony_cistatic int ad4130_update_scan_mode(struct iio_dev *indio_dev,
119362306a36Sopenharmony_ci				   const unsigned long *scan_mask)
119462306a36Sopenharmony_ci{
119562306a36Sopenharmony_ci	struct ad4130_state *st = iio_priv(indio_dev);
119662306a36Sopenharmony_ci	unsigned int channel;
119762306a36Sopenharmony_ci	unsigned int val = 0;
119862306a36Sopenharmony_ci	int ret;
119962306a36Sopenharmony_ci
120062306a36Sopenharmony_ci	mutex_lock(&st->lock);
120162306a36Sopenharmony_ci
120262306a36Sopenharmony_ci	for_each_set_bit(channel, scan_mask, indio_dev->num_channels) {
120362306a36Sopenharmony_ci		ret = ad4130_set_channel_enable(st, channel, true);
120462306a36Sopenharmony_ci		if (ret)
120562306a36Sopenharmony_ci			goto out;
120662306a36Sopenharmony_ci
120762306a36Sopenharmony_ci		val++;
120862306a36Sopenharmony_ci	}
120962306a36Sopenharmony_ci
121062306a36Sopenharmony_ci	st->num_enabled_channels = val;
121162306a36Sopenharmony_ci
121262306a36Sopenharmony_ciout:
121362306a36Sopenharmony_ci	mutex_unlock(&st->lock);
121462306a36Sopenharmony_ci
121562306a36Sopenharmony_ci	return 0;
121662306a36Sopenharmony_ci}
121762306a36Sopenharmony_ci
121862306a36Sopenharmony_cistatic int ad4130_set_fifo_watermark(struct iio_dev *indio_dev, unsigned int val)
121962306a36Sopenharmony_ci{
122062306a36Sopenharmony_ci	struct ad4130_state *st = iio_priv(indio_dev);
122162306a36Sopenharmony_ci	unsigned int eff;
122262306a36Sopenharmony_ci	int ret;
122362306a36Sopenharmony_ci
122462306a36Sopenharmony_ci	if (val > AD4130_FIFO_SIZE)
122562306a36Sopenharmony_ci		return -EINVAL;
122662306a36Sopenharmony_ci
122762306a36Sopenharmony_ci	eff = val * st->num_enabled_channels;
122862306a36Sopenharmony_ci	if (eff > AD4130_FIFO_SIZE)
122962306a36Sopenharmony_ci		/*
123062306a36Sopenharmony_ci		 * Always set watermark to a multiple of the number of
123162306a36Sopenharmony_ci		 * enabled channels to avoid making the FIFO unaligned.
123262306a36Sopenharmony_ci		 */
123362306a36Sopenharmony_ci		eff = rounddown(AD4130_FIFO_SIZE, st->num_enabled_channels);
123462306a36Sopenharmony_ci
123562306a36Sopenharmony_ci	mutex_lock(&st->lock);
123662306a36Sopenharmony_ci
123762306a36Sopenharmony_ci	ret = regmap_update_bits(st->regmap, AD4130_FIFO_CONTROL_REG,
123862306a36Sopenharmony_ci				 AD4130_FIFO_CONTROL_WM_MASK,
123962306a36Sopenharmony_ci				 FIELD_PREP(AD4130_FIFO_CONTROL_WM_MASK,
124062306a36Sopenharmony_ci					    ad4130_watermark_reg_val(eff)));
124162306a36Sopenharmony_ci	if (ret)
124262306a36Sopenharmony_ci		goto out;
124362306a36Sopenharmony_ci
124462306a36Sopenharmony_ci	st->effective_watermark = eff;
124562306a36Sopenharmony_ci	st->watermark = val;
124662306a36Sopenharmony_ci
124762306a36Sopenharmony_ciout:
124862306a36Sopenharmony_ci	mutex_unlock(&st->lock);
124962306a36Sopenharmony_ci
125062306a36Sopenharmony_ci	return ret;
125162306a36Sopenharmony_ci}
125262306a36Sopenharmony_ci
125362306a36Sopenharmony_cistatic const struct iio_info ad4130_info = {
125462306a36Sopenharmony_ci	.read_raw = ad4130_read_raw,
125562306a36Sopenharmony_ci	.read_avail = ad4130_read_avail,
125662306a36Sopenharmony_ci	.write_raw_get_fmt = ad4130_write_raw_get_fmt,
125762306a36Sopenharmony_ci	.write_raw = ad4130_write_raw,
125862306a36Sopenharmony_ci	.update_scan_mode = ad4130_update_scan_mode,
125962306a36Sopenharmony_ci	.hwfifo_set_watermark = ad4130_set_fifo_watermark,
126062306a36Sopenharmony_ci	.debugfs_reg_access = ad4130_reg_access,
126162306a36Sopenharmony_ci};
126262306a36Sopenharmony_ci
126362306a36Sopenharmony_cistatic int ad4130_buffer_postenable(struct iio_dev *indio_dev)
126462306a36Sopenharmony_ci{
126562306a36Sopenharmony_ci	struct ad4130_state *st = iio_priv(indio_dev);
126662306a36Sopenharmony_ci	int ret;
126762306a36Sopenharmony_ci
126862306a36Sopenharmony_ci	mutex_lock(&st->lock);
126962306a36Sopenharmony_ci
127062306a36Sopenharmony_ci	ret = ad4130_set_watermark_interrupt_en(st, true);
127162306a36Sopenharmony_ci	if (ret)
127262306a36Sopenharmony_ci		goto out;
127362306a36Sopenharmony_ci
127462306a36Sopenharmony_ci	ret = irq_set_irq_type(st->spi->irq, st->inv_irq_trigger);
127562306a36Sopenharmony_ci	if (ret)
127662306a36Sopenharmony_ci		goto out;
127762306a36Sopenharmony_ci
127862306a36Sopenharmony_ci	ret = ad4130_set_fifo_mode(st, AD4130_FIFO_MODE_WM);
127962306a36Sopenharmony_ci	if (ret)
128062306a36Sopenharmony_ci		goto out;
128162306a36Sopenharmony_ci
128262306a36Sopenharmony_ci	ret = ad4130_set_mode(st, AD4130_MODE_CONTINUOUS);
128362306a36Sopenharmony_ci
128462306a36Sopenharmony_ciout:
128562306a36Sopenharmony_ci	mutex_unlock(&st->lock);
128662306a36Sopenharmony_ci
128762306a36Sopenharmony_ci	return ret;
128862306a36Sopenharmony_ci}
128962306a36Sopenharmony_ci
129062306a36Sopenharmony_cistatic int ad4130_buffer_predisable(struct iio_dev *indio_dev)
129162306a36Sopenharmony_ci{
129262306a36Sopenharmony_ci	struct ad4130_state *st = iio_priv(indio_dev);
129362306a36Sopenharmony_ci	unsigned int i;
129462306a36Sopenharmony_ci	int ret;
129562306a36Sopenharmony_ci
129662306a36Sopenharmony_ci	mutex_lock(&st->lock);
129762306a36Sopenharmony_ci
129862306a36Sopenharmony_ci	ret = ad4130_set_mode(st, AD4130_MODE_IDLE);
129962306a36Sopenharmony_ci	if (ret)
130062306a36Sopenharmony_ci		goto out;
130162306a36Sopenharmony_ci
130262306a36Sopenharmony_ci	ret = irq_set_irq_type(st->spi->irq, st->irq_trigger);
130362306a36Sopenharmony_ci	if (ret)
130462306a36Sopenharmony_ci		goto out;
130562306a36Sopenharmony_ci
130662306a36Sopenharmony_ci	ret = ad4130_set_fifo_mode(st, AD4130_FIFO_MODE_DISABLED);
130762306a36Sopenharmony_ci	if (ret)
130862306a36Sopenharmony_ci		goto out;
130962306a36Sopenharmony_ci
131062306a36Sopenharmony_ci	ret = ad4130_set_watermark_interrupt_en(st, false);
131162306a36Sopenharmony_ci	if (ret)
131262306a36Sopenharmony_ci		goto out;
131362306a36Sopenharmony_ci
131462306a36Sopenharmony_ci	/*
131562306a36Sopenharmony_ci	 * update_scan_mode() is not called in the disable path, disable all
131662306a36Sopenharmony_ci	 * channels here.
131762306a36Sopenharmony_ci	 */
131862306a36Sopenharmony_ci	for (i = 0; i < indio_dev->num_channels; i++) {
131962306a36Sopenharmony_ci		ret = ad4130_set_channel_enable(st, i, false);
132062306a36Sopenharmony_ci		if (ret)
132162306a36Sopenharmony_ci			goto out;
132262306a36Sopenharmony_ci	}
132362306a36Sopenharmony_ci
132462306a36Sopenharmony_ciout:
132562306a36Sopenharmony_ci	mutex_unlock(&st->lock);
132662306a36Sopenharmony_ci
132762306a36Sopenharmony_ci	return ret;
132862306a36Sopenharmony_ci}
132962306a36Sopenharmony_ci
133062306a36Sopenharmony_cistatic const struct iio_buffer_setup_ops ad4130_buffer_ops = {
133162306a36Sopenharmony_ci	.postenable = ad4130_buffer_postenable,
133262306a36Sopenharmony_ci	.predisable = ad4130_buffer_predisable,
133362306a36Sopenharmony_ci};
133462306a36Sopenharmony_ci
133562306a36Sopenharmony_cistatic ssize_t hwfifo_watermark_show(struct device *dev,
133662306a36Sopenharmony_ci				     struct device_attribute *attr, char *buf)
133762306a36Sopenharmony_ci{
133862306a36Sopenharmony_ci	struct ad4130_state *st = iio_priv(dev_to_iio_dev(dev));
133962306a36Sopenharmony_ci	unsigned int val;
134062306a36Sopenharmony_ci
134162306a36Sopenharmony_ci	mutex_lock(&st->lock);
134262306a36Sopenharmony_ci	val = st->watermark;
134362306a36Sopenharmony_ci	mutex_unlock(&st->lock);
134462306a36Sopenharmony_ci
134562306a36Sopenharmony_ci	return sysfs_emit(buf, "%d\n", val);
134662306a36Sopenharmony_ci}
134762306a36Sopenharmony_ci
134862306a36Sopenharmony_cistatic ssize_t hwfifo_enabled_show(struct device *dev,
134962306a36Sopenharmony_ci				   struct device_attribute *attr, char *buf)
135062306a36Sopenharmony_ci{
135162306a36Sopenharmony_ci	struct ad4130_state *st = iio_priv(dev_to_iio_dev(dev));
135262306a36Sopenharmony_ci	unsigned int val;
135362306a36Sopenharmony_ci	int ret;
135462306a36Sopenharmony_ci
135562306a36Sopenharmony_ci	ret = regmap_read(st->regmap, AD4130_FIFO_CONTROL_REG, &val);
135662306a36Sopenharmony_ci	if (ret)
135762306a36Sopenharmony_ci		return ret;
135862306a36Sopenharmony_ci
135962306a36Sopenharmony_ci	val = FIELD_GET(AD4130_FIFO_CONTROL_MODE_MASK, val);
136062306a36Sopenharmony_ci
136162306a36Sopenharmony_ci	return sysfs_emit(buf, "%d\n", val != AD4130_FIFO_MODE_DISABLED);
136262306a36Sopenharmony_ci}
136362306a36Sopenharmony_ci
136462306a36Sopenharmony_cistatic ssize_t hwfifo_watermark_min_show(struct device *dev,
136562306a36Sopenharmony_ci					 struct device_attribute *attr,
136662306a36Sopenharmony_ci					 char *buf)
136762306a36Sopenharmony_ci{
136862306a36Sopenharmony_ci	return sysfs_emit(buf, "%s\n", "1");
136962306a36Sopenharmony_ci}
137062306a36Sopenharmony_ci
137162306a36Sopenharmony_cistatic ssize_t hwfifo_watermark_max_show(struct device *dev,
137262306a36Sopenharmony_ci					 struct device_attribute *attr,
137362306a36Sopenharmony_ci					 char *buf)
137462306a36Sopenharmony_ci{
137562306a36Sopenharmony_ci	return sysfs_emit(buf, "%s\n", __stringify(AD4130_FIFO_SIZE));
137662306a36Sopenharmony_ci}
137762306a36Sopenharmony_ci
137862306a36Sopenharmony_cistatic IIO_DEVICE_ATTR_RO(hwfifo_watermark_min, 0);
137962306a36Sopenharmony_cistatic IIO_DEVICE_ATTR_RO(hwfifo_watermark_max, 0);
138062306a36Sopenharmony_cistatic IIO_DEVICE_ATTR_RO(hwfifo_watermark, 0);
138162306a36Sopenharmony_cistatic IIO_DEVICE_ATTR_RO(hwfifo_enabled, 0);
138262306a36Sopenharmony_ci
138362306a36Sopenharmony_cistatic const struct iio_dev_attr *ad4130_fifo_attributes[] = {
138462306a36Sopenharmony_ci	&iio_dev_attr_hwfifo_watermark_min,
138562306a36Sopenharmony_ci	&iio_dev_attr_hwfifo_watermark_max,
138662306a36Sopenharmony_ci	&iio_dev_attr_hwfifo_watermark,
138762306a36Sopenharmony_ci	&iio_dev_attr_hwfifo_enabled,
138862306a36Sopenharmony_ci	NULL
138962306a36Sopenharmony_ci};
139062306a36Sopenharmony_ci
139162306a36Sopenharmony_cistatic int _ad4130_find_table_index(const unsigned int *tbl, size_t len,
139262306a36Sopenharmony_ci				    unsigned int val)
139362306a36Sopenharmony_ci{
139462306a36Sopenharmony_ci	unsigned int i;
139562306a36Sopenharmony_ci
139662306a36Sopenharmony_ci	for (i = 0; i < len; i++)
139762306a36Sopenharmony_ci		if (tbl[i] == val)
139862306a36Sopenharmony_ci			return i;
139962306a36Sopenharmony_ci
140062306a36Sopenharmony_ci	return -EINVAL;
140162306a36Sopenharmony_ci}
140262306a36Sopenharmony_ci
140362306a36Sopenharmony_ci#define ad4130_find_table_index(table, val) \
140462306a36Sopenharmony_ci	_ad4130_find_table_index(table, ARRAY_SIZE(table), val)
140562306a36Sopenharmony_ci
140662306a36Sopenharmony_cistatic int ad4130_get_ref_voltage(struct ad4130_state *st,
140762306a36Sopenharmony_ci				  enum ad4130_ref_sel ref_sel)
140862306a36Sopenharmony_ci{
140962306a36Sopenharmony_ci	switch (ref_sel) {
141062306a36Sopenharmony_ci	case AD4130_REF_REFIN1:
141162306a36Sopenharmony_ci		return regulator_get_voltage(st->regulators[2].consumer);
141262306a36Sopenharmony_ci	case AD4130_REF_REFIN2:
141362306a36Sopenharmony_ci		return regulator_get_voltage(st->regulators[3].consumer);
141462306a36Sopenharmony_ci	case AD4130_REF_AVDD_AVSS:
141562306a36Sopenharmony_ci		return regulator_get_voltage(st->regulators[0].consumer);
141662306a36Sopenharmony_ci	case AD4130_REF_REFOUT_AVSS:
141762306a36Sopenharmony_ci		return st->int_ref_uv;
141862306a36Sopenharmony_ci	default:
141962306a36Sopenharmony_ci		return -EINVAL;
142062306a36Sopenharmony_ci	}
142162306a36Sopenharmony_ci}
142262306a36Sopenharmony_ci
142362306a36Sopenharmony_cistatic int ad4130_parse_fw_setup(struct ad4130_state *st,
142462306a36Sopenharmony_ci				 struct fwnode_handle *child,
142562306a36Sopenharmony_ci				 struct ad4130_setup_info *setup_info)
142662306a36Sopenharmony_ci{
142762306a36Sopenharmony_ci	struct device *dev = &st->spi->dev;
142862306a36Sopenharmony_ci	u32 tmp;
142962306a36Sopenharmony_ci	int ret;
143062306a36Sopenharmony_ci
143162306a36Sopenharmony_ci	tmp = 0;
143262306a36Sopenharmony_ci	fwnode_property_read_u32(child, "adi,excitation-current-0-nanoamp", &tmp);
143362306a36Sopenharmony_ci	ret = ad4130_find_table_index(ad4130_iout_current_na_tbl, tmp);
143462306a36Sopenharmony_ci	if (ret < 0)
143562306a36Sopenharmony_ci		return dev_err_probe(dev, ret,
143662306a36Sopenharmony_ci				     "Invalid excitation current %unA\n", tmp);
143762306a36Sopenharmony_ci	setup_info->iout0_val = ret;
143862306a36Sopenharmony_ci
143962306a36Sopenharmony_ci	tmp = 0;
144062306a36Sopenharmony_ci	fwnode_property_read_u32(child, "adi,excitation-current-1-nanoamp", &tmp);
144162306a36Sopenharmony_ci	ret = ad4130_find_table_index(ad4130_iout_current_na_tbl, tmp);
144262306a36Sopenharmony_ci	if (ret < 0)
144362306a36Sopenharmony_ci		return dev_err_probe(dev, ret,
144462306a36Sopenharmony_ci				     "Invalid excitation current %unA\n", tmp);
144562306a36Sopenharmony_ci	setup_info->iout1_val = ret;
144662306a36Sopenharmony_ci
144762306a36Sopenharmony_ci	tmp = 0;
144862306a36Sopenharmony_ci	fwnode_property_read_u32(child, "adi,burnout-current-nanoamp", &tmp);
144962306a36Sopenharmony_ci	ret = ad4130_find_table_index(ad4130_burnout_current_na_tbl, tmp);
145062306a36Sopenharmony_ci	if (ret < 0)
145162306a36Sopenharmony_ci		return dev_err_probe(dev, ret,
145262306a36Sopenharmony_ci				     "Invalid burnout current %unA\n", tmp);
145362306a36Sopenharmony_ci	setup_info->burnout = ret;
145462306a36Sopenharmony_ci
145562306a36Sopenharmony_ci	setup_info->ref_bufp = fwnode_property_read_bool(child, "adi,buffered-positive");
145662306a36Sopenharmony_ci	setup_info->ref_bufm = fwnode_property_read_bool(child, "adi,buffered-negative");
145762306a36Sopenharmony_ci
145862306a36Sopenharmony_ci	setup_info->ref_sel = AD4130_REF_REFIN1;
145962306a36Sopenharmony_ci	fwnode_property_read_u32(child, "adi,reference-select",
146062306a36Sopenharmony_ci				 &setup_info->ref_sel);
146162306a36Sopenharmony_ci	if (setup_info->ref_sel >= AD4130_REF_SEL_MAX)
146262306a36Sopenharmony_ci		return dev_err_probe(dev, -EINVAL,
146362306a36Sopenharmony_ci				     "Invalid reference selected %u\n",
146462306a36Sopenharmony_ci				     setup_info->ref_sel);
146562306a36Sopenharmony_ci
146662306a36Sopenharmony_ci	if (setup_info->ref_sel == AD4130_REF_REFOUT_AVSS)
146762306a36Sopenharmony_ci		st->int_ref_en = true;
146862306a36Sopenharmony_ci
146962306a36Sopenharmony_ci	ret = ad4130_get_ref_voltage(st, setup_info->ref_sel);
147062306a36Sopenharmony_ci	if (ret < 0)
147162306a36Sopenharmony_ci		return dev_err_probe(dev, ret, "Cannot use reference %u\n",
147262306a36Sopenharmony_ci				     setup_info->ref_sel);
147362306a36Sopenharmony_ci
147462306a36Sopenharmony_ci	return 0;
147562306a36Sopenharmony_ci}
147662306a36Sopenharmony_ci
147762306a36Sopenharmony_cistatic int ad4130_validate_diff_channel(struct ad4130_state *st, u32 pin)
147862306a36Sopenharmony_ci{
147962306a36Sopenharmony_ci	struct device *dev = &st->spi->dev;
148062306a36Sopenharmony_ci
148162306a36Sopenharmony_ci	if (pin >= AD4130_MAX_DIFF_INPUTS)
148262306a36Sopenharmony_ci		return dev_err_probe(dev, -EINVAL,
148362306a36Sopenharmony_ci				     "Invalid differential channel %u\n", pin);
148462306a36Sopenharmony_ci
148562306a36Sopenharmony_ci	if (pin >= AD4130_MAX_ANALOG_PINS)
148662306a36Sopenharmony_ci		return 0;
148762306a36Sopenharmony_ci
148862306a36Sopenharmony_ci	if (st->pins_fn[pin] == AD4130_PIN_FN_SPECIAL)
148962306a36Sopenharmony_ci		return dev_err_probe(dev, -EINVAL,
149062306a36Sopenharmony_ci				     "Pin %u already used with fn %u\n", pin,
149162306a36Sopenharmony_ci				     st->pins_fn[pin]);
149262306a36Sopenharmony_ci
149362306a36Sopenharmony_ci	st->pins_fn[pin] |= AD4130_PIN_FN_DIFF;
149462306a36Sopenharmony_ci
149562306a36Sopenharmony_ci	return 0;
149662306a36Sopenharmony_ci}
149762306a36Sopenharmony_ci
149862306a36Sopenharmony_cistatic int ad4130_validate_diff_channels(struct ad4130_state *st,
149962306a36Sopenharmony_ci					 u32 *pins, unsigned int len)
150062306a36Sopenharmony_ci{
150162306a36Sopenharmony_ci	unsigned int i;
150262306a36Sopenharmony_ci	int ret;
150362306a36Sopenharmony_ci
150462306a36Sopenharmony_ci	for (i = 0; i < len; i++) {
150562306a36Sopenharmony_ci		ret = ad4130_validate_diff_channel(st, pins[i]);
150662306a36Sopenharmony_ci		if (ret)
150762306a36Sopenharmony_ci			return ret;
150862306a36Sopenharmony_ci	}
150962306a36Sopenharmony_ci
151062306a36Sopenharmony_ci	return 0;
151162306a36Sopenharmony_ci}
151262306a36Sopenharmony_ci
151362306a36Sopenharmony_cistatic int ad4130_validate_excitation_pin(struct ad4130_state *st, u32 pin)
151462306a36Sopenharmony_ci{
151562306a36Sopenharmony_ci	struct device *dev = &st->spi->dev;
151662306a36Sopenharmony_ci
151762306a36Sopenharmony_ci	if (pin >= AD4130_MAX_ANALOG_PINS)
151862306a36Sopenharmony_ci		return dev_err_probe(dev, -EINVAL,
151962306a36Sopenharmony_ci				     "Invalid excitation pin %u\n", pin);
152062306a36Sopenharmony_ci
152162306a36Sopenharmony_ci	if (st->pins_fn[pin] == AD4130_PIN_FN_SPECIAL)
152262306a36Sopenharmony_ci		return dev_err_probe(dev, -EINVAL,
152362306a36Sopenharmony_ci				     "Pin %u already used with fn %u\n", pin,
152462306a36Sopenharmony_ci				     st->pins_fn[pin]);
152562306a36Sopenharmony_ci
152662306a36Sopenharmony_ci	st->pins_fn[pin] |= AD4130_PIN_FN_EXCITATION;
152762306a36Sopenharmony_ci
152862306a36Sopenharmony_ci	return 0;
152962306a36Sopenharmony_ci}
153062306a36Sopenharmony_ci
153162306a36Sopenharmony_cistatic int ad4130_validate_vbias_pin(struct ad4130_state *st, u32 pin)
153262306a36Sopenharmony_ci{
153362306a36Sopenharmony_ci	struct device *dev = &st->spi->dev;
153462306a36Sopenharmony_ci
153562306a36Sopenharmony_ci	if (pin >= AD4130_MAX_ANALOG_PINS)
153662306a36Sopenharmony_ci		return dev_err_probe(dev, -EINVAL, "Invalid vbias pin %u\n",
153762306a36Sopenharmony_ci				     pin);
153862306a36Sopenharmony_ci
153962306a36Sopenharmony_ci	if (st->pins_fn[pin] == AD4130_PIN_FN_SPECIAL)
154062306a36Sopenharmony_ci		return dev_err_probe(dev, -EINVAL,
154162306a36Sopenharmony_ci				     "Pin %u already used with fn %u\n", pin,
154262306a36Sopenharmony_ci				     st->pins_fn[pin]);
154362306a36Sopenharmony_ci
154462306a36Sopenharmony_ci	st->pins_fn[pin] |= AD4130_PIN_FN_VBIAS;
154562306a36Sopenharmony_ci
154662306a36Sopenharmony_ci	return 0;
154762306a36Sopenharmony_ci}
154862306a36Sopenharmony_ci
154962306a36Sopenharmony_cistatic int ad4130_validate_vbias_pins(struct ad4130_state *st,
155062306a36Sopenharmony_ci				      u32 *pins, unsigned int len)
155162306a36Sopenharmony_ci{
155262306a36Sopenharmony_ci	unsigned int i;
155362306a36Sopenharmony_ci	int ret;
155462306a36Sopenharmony_ci
155562306a36Sopenharmony_ci	for (i = 0; i < st->num_vbias_pins; i++) {
155662306a36Sopenharmony_ci		ret = ad4130_validate_vbias_pin(st, pins[i]);
155762306a36Sopenharmony_ci		if (ret)
155862306a36Sopenharmony_ci			return ret;
155962306a36Sopenharmony_ci	}
156062306a36Sopenharmony_ci
156162306a36Sopenharmony_ci	return 0;
156262306a36Sopenharmony_ci}
156362306a36Sopenharmony_ci
156462306a36Sopenharmony_cistatic int ad4130_parse_fw_channel(struct iio_dev *indio_dev,
156562306a36Sopenharmony_ci				   struct fwnode_handle *child)
156662306a36Sopenharmony_ci{
156762306a36Sopenharmony_ci	struct ad4130_state *st = iio_priv(indio_dev);
156862306a36Sopenharmony_ci	unsigned int resolution = ad4130_resolution(st);
156962306a36Sopenharmony_ci	unsigned int index = indio_dev->num_channels++;
157062306a36Sopenharmony_ci	struct device *dev = &st->spi->dev;
157162306a36Sopenharmony_ci	struct ad4130_chan_info *chan_info;
157262306a36Sopenharmony_ci	struct iio_chan_spec *chan;
157362306a36Sopenharmony_ci	u32 pins[2];
157462306a36Sopenharmony_ci	int ret;
157562306a36Sopenharmony_ci
157662306a36Sopenharmony_ci	if (index >= AD4130_MAX_CHANNELS)
157762306a36Sopenharmony_ci		return dev_err_probe(dev, -EINVAL, "Too many channels\n");
157862306a36Sopenharmony_ci
157962306a36Sopenharmony_ci	chan = &st->chans[index];
158062306a36Sopenharmony_ci	chan_info = &st->chans_info[index];
158162306a36Sopenharmony_ci
158262306a36Sopenharmony_ci	*chan = ad4130_channel_template;
158362306a36Sopenharmony_ci	chan->scan_type.realbits = resolution;
158462306a36Sopenharmony_ci	chan->scan_type.storagebits = resolution;
158562306a36Sopenharmony_ci	chan->scan_index = index;
158662306a36Sopenharmony_ci
158762306a36Sopenharmony_ci	chan_info->slot = AD4130_INVALID_SLOT;
158862306a36Sopenharmony_ci	chan_info->setup.fs = AD4130_FILTER_SELECT_MIN;
158962306a36Sopenharmony_ci	chan_info->initialized = true;
159062306a36Sopenharmony_ci
159162306a36Sopenharmony_ci	ret = fwnode_property_read_u32_array(child, "diff-channels", pins,
159262306a36Sopenharmony_ci					     ARRAY_SIZE(pins));
159362306a36Sopenharmony_ci	if (ret)
159462306a36Sopenharmony_ci		return ret;
159562306a36Sopenharmony_ci
159662306a36Sopenharmony_ci	ret = ad4130_validate_diff_channels(st, pins, ARRAY_SIZE(pins));
159762306a36Sopenharmony_ci	if (ret)
159862306a36Sopenharmony_ci		return ret;
159962306a36Sopenharmony_ci
160062306a36Sopenharmony_ci	chan->channel = pins[0];
160162306a36Sopenharmony_ci	chan->channel2 = pins[1];
160262306a36Sopenharmony_ci
160362306a36Sopenharmony_ci	ret = ad4130_parse_fw_setup(st, child, &chan_info->setup);
160462306a36Sopenharmony_ci	if (ret)
160562306a36Sopenharmony_ci		return ret;
160662306a36Sopenharmony_ci
160762306a36Sopenharmony_ci	fwnode_property_read_u32(child, "adi,excitation-pin-0",
160862306a36Sopenharmony_ci				 &chan_info->iout0);
160962306a36Sopenharmony_ci	if (chan_info->setup.iout0_val != AD4130_IOUT_OFF) {
161062306a36Sopenharmony_ci		ret = ad4130_validate_excitation_pin(st, chan_info->iout0);
161162306a36Sopenharmony_ci		if (ret)
161262306a36Sopenharmony_ci			return ret;
161362306a36Sopenharmony_ci	}
161462306a36Sopenharmony_ci
161562306a36Sopenharmony_ci	fwnode_property_read_u32(child, "adi,excitation-pin-1",
161662306a36Sopenharmony_ci				 &chan_info->iout1);
161762306a36Sopenharmony_ci	if (chan_info->setup.iout1_val != AD4130_IOUT_OFF) {
161862306a36Sopenharmony_ci		ret = ad4130_validate_excitation_pin(st, chan_info->iout1);
161962306a36Sopenharmony_ci		if (ret)
162062306a36Sopenharmony_ci			return ret;
162162306a36Sopenharmony_ci	}
162262306a36Sopenharmony_ci
162362306a36Sopenharmony_ci	return 0;
162462306a36Sopenharmony_ci}
162562306a36Sopenharmony_ci
162662306a36Sopenharmony_cistatic int ad4130_parse_fw_children(struct iio_dev *indio_dev)
162762306a36Sopenharmony_ci{
162862306a36Sopenharmony_ci	struct ad4130_state *st = iio_priv(indio_dev);
162962306a36Sopenharmony_ci	struct device *dev = &st->spi->dev;
163062306a36Sopenharmony_ci	struct fwnode_handle *child;
163162306a36Sopenharmony_ci	int ret;
163262306a36Sopenharmony_ci
163362306a36Sopenharmony_ci	indio_dev->channels = st->chans;
163462306a36Sopenharmony_ci
163562306a36Sopenharmony_ci	device_for_each_child_node(dev, child) {
163662306a36Sopenharmony_ci		ret = ad4130_parse_fw_channel(indio_dev, child);
163762306a36Sopenharmony_ci		if (ret) {
163862306a36Sopenharmony_ci			fwnode_handle_put(child);
163962306a36Sopenharmony_ci			return ret;
164062306a36Sopenharmony_ci		}
164162306a36Sopenharmony_ci	}
164262306a36Sopenharmony_ci
164362306a36Sopenharmony_ci	return 0;
164462306a36Sopenharmony_ci}
164562306a36Sopenharmony_ci
164662306a36Sopenharmony_cistatic int ad4310_parse_fw(struct iio_dev *indio_dev)
164762306a36Sopenharmony_ci{
164862306a36Sopenharmony_ci	struct ad4130_state *st = iio_priv(indio_dev);
164962306a36Sopenharmony_ci	struct device *dev = &st->spi->dev;
165062306a36Sopenharmony_ci	u32 ext_clk_freq = AD4130_MCLK_FREQ_76_8KHZ;
165162306a36Sopenharmony_ci	unsigned int i;
165262306a36Sopenharmony_ci	int avdd_uv;
165362306a36Sopenharmony_ci	int irq;
165462306a36Sopenharmony_ci	int ret;
165562306a36Sopenharmony_ci
165662306a36Sopenharmony_ci	st->mclk = devm_clk_get_optional(dev, "mclk");
165762306a36Sopenharmony_ci	if (IS_ERR(st->mclk))
165862306a36Sopenharmony_ci		return dev_err_probe(dev, PTR_ERR(st->mclk),
165962306a36Sopenharmony_ci				     "Failed to get mclk\n");
166062306a36Sopenharmony_ci
166162306a36Sopenharmony_ci	st->int_pin_sel = AD4130_INT_PIN_INT;
166262306a36Sopenharmony_ci
166362306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(ad4130_int_pin_names); i++) {
166462306a36Sopenharmony_ci		irq = fwnode_irq_get_byname(dev_fwnode(dev),
166562306a36Sopenharmony_ci					    ad4130_int_pin_names[i]);
166662306a36Sopenharmony_ci		if (irq > 0) {
166762306a36Sopenharmony_ci			st->int_pin_sel = i;
166862306a36Sopenharmony_ci			break;
166962306a36Sopenharmony_ci		}
167062306a36Sopenharmony_ci	}
167162306a36Sopenharmony_ci
167262306a36Sopenharmony_ci	if (st->int_pin_sel == AD4130_INT_PIN_DOUT)
167362306a36Sopenharmony_ci		return dev_err_probe(dev, -EINVAL,
167462306a36Sopenharmony_ci				     "Cannot use DOUT as interrupt pin\n");
167562306a36Sopenharmony_ci
167662306a36Sopenharmony_ci	if (st->int_pin_sel == AD4130_INT_PIN_P2)
167762306a36Sopenharmony_ci		st->pins_fn[AD4130_AIN3_P2] = AD4130_PIN_FN_SPECIAL;
167862306a36Sopenharmony_ci
167962306a36Sopenharmony_ci	device_property_read_u32(dev, "adi,ext-clk-freq-hz", &ext_clk_freq);
168062306a36Sopenharmony_ci	if (ext_clk_freq != AD4130_MCLK_FREQ_153_6KHZ &&
168162306a36Sopenharmony_ci	    ext_clk_freq != AD4130_MCLK_FREQ_76_8KHZ)
168262306a36Sopenharmony_ci		return dev_err_probe(dev, -EINVAL,
168362306a36Sopenharmony_ci				     "Invalid external clock frequency %u\n",
168462306a36Sopenharmony_ci				     ext_clk_freq);
168562306a36Sopenharmony_ci
168662306a36Sopenharmony_ci	if (st->mclk && ext_clk_freq == AD4130_MCLK_FREQ_153_6KHZ)
168762306a36Sopenharmony_ci		st->mclk_sel = AD4130_MCLK_153_6KHZ_EXT;
168862306a36Sopenharmony_ci	else if (st->mclk)
168962306a36Sopenharmony_ci		st->mclk_sel = AD4130_MCLK_76_8KHZ_EXT;
169062306a36Sopenharmony_ci	else
169162306a36Sopenharmony_ci		st->mclk_sel = AD4130_MCLK_76_8KHZ;
169262306a36Sopenharmony_ci
169362306a36Sopenharmony_ci	if (st->int_pin_sel == AD4130_INT_PIN_CLK &&
169462306a36Sopenharmony_ci	    st->mclk_sel != AD4130_MCLK_76_8KHZ)
169562306a36Sopenharmony_ci		return dev_err_probe(dev, -EINVAL,
169662306a36Sopenharmony_ci				     "Invalid clock %u for interrupt pin %u\n",
169762306a36Sopenharmony_ci				     st->mclk_sel, st->int_pin_sel);
169862306a36Sopenharmony_ci
169962306a36Sopenharmony_ci	st->int_ref_uv = AD4130_INT_REF_2_5V;
170062306a36Sopenharmony_ci
170162306a36Sopenharmony_ci	/*
170262306a36Sopenharmony_ci	 * When the AVDD supply is set to below 2.5V the internal reference of
170362306a36Sopenharmony_ci	 * 1.25V should be selected.
170462306a36Sopenharmony_ci	 * See datasheet page 37, section ADC REFERENCE.
170562306a36Sopenharmony_ci	 */
170662306a36Sopenharmony_ci	avdd_uv = regulator_get_voltage(st->regulators[0].consumer);
170762306a36Sopenharmony_ci	if (avdd_uv > 0 && avdd_uv < AD4130_INT_REF_2_5V)
170862306a36Sopenharmony_ci		st->int_ref_uv = AD4130_INT_REF_1_25V;
170962306a36Sopenharmony_ci
171062306a36Sopenharmony_ci	st->bipolar = device_property_read_bool(dev, "adi,bipolar");
171162306a36Sopenharmony_ci
171262306a36Sopenharmony_ci	ret = device_property_count_u32(dev, "adi,vbias-pins");
171362306a36Sopenharmony_ci	if (ret > 0) {
171462306a36Sopenharmony_ci		if (ret > AD4130_MAX_ANALOG_PINS)
171562306a36Sopenharmony_ci			return dev_err_probe(dev, -EINVAL,
171662306a36Sopenharmony_ci					     "Too many vbias pins %u\n", ret);
171762306a36Sopenharmony_ci
171862306a36Sopenharmony_ci		st->num_vbias_pins = ret;
171962306a36Sopenharmony_ci
172062306a36Sopenharmony_ci		ret = device_property_read_u32_array(dev, "adi,vbias-pins",
172162306a36Sopenharmony_ci						     st->vbias_pins,
172262306a36Sopenharmony_ci						     st->num_vbias_pins);
172362306a36Sopenharmony_ci		if (ret)
172462306a36Sopenharmony_ci			return dev_err_probe(dev, ret,
172562306a36Sopenharmony_ci					     "Failed to read vbias pins\n");
172662306a36Sopenharmony_ci
172762306a36Sopenharmony_ci		ret = ad4130_validate_vbias_pins(st, st->vbias_pins,
172862306a36Sopenharmony_ci						 st->num_vbias_pins);
172962306a36Sopenharmony_ci		if (ret)
173062306a36Sopenharmony_ci			return ret;
173162306a36Sopenharmony_ci	}
173262306a36Sopenharmony_ci
173362306a36Sopenharmony_ci	ret = ad4130_parse_fw_children(indio_dev);
173462306a36Sopenharmony_ci	if (ret)
173562306a36Sopenharmony_ci		return ret;
173662306a36Sopenharmony_ci
173762306a36Sopenharmony_ci	return 0;
173862306a36Sopenharmony_ci}
173962306a36Sopenharmony_ci
174062306a36Sopenharmony_cistatic void ad4130_fill_scale_tbls(struct ad4130_state *st)
174162306a36Sopenharmony_ci{
174262306a36Sopenharmony_ci	unsigned int pow = ad4130_resolution(st) - st->bipolar;
174362306a36Sopenharmony_ci	unsigned int i, j;
174462306a36Sopenharmony_ci
174562306a36Sopenharmony_ci	for (i = 0; i < AD4130_REF_SEL_MAX; i++) {
174662306a36Sopenharmony_ci		int ret;
174762306a36Sopenharmony_ci		u64 nv;
174862306a36Sopenharmony_ci
174962306a36Sopenharmony_ci		ret = ad4130_get_ref_voltage(st, i);
175062306a36Sopenharmony_ci		if (ret < 0)
175162306a36Sopenharmony_ci			continue;
175262306a36Sopenharmony_ci
175362306a36Sopenharmony_ci		nv = (u64)ret * NANO;
175462306a36Sopenharmony_ci
175562306a36Sopenharmony_ci		for (j = 0; j < AD4130_MAX_PGA; j++)
175662306a36Sopenharmony_ci			st->scale_tbls[i][j][1] = div_u64(nv >> (pow + j), MILLI);
175762306a36Sopenharmony_ci	}
175862306a36Sopenharmony_ci}
175962306a36Sopenharmony_ci
176062306a36Sopenharmony_cistatic void ad4130_clk_disable_unprepare(void *clk)
176162306a36Sopenharmony_ci{
176262306a36Sopenharmony_ci	clk_disable_unprepare(clk);
176362306a36Sopenharmony_ci}
176462306a36Sopenharmony_ci
176562306a36Sopenharmony_cistatic int ad4130_set_mclk_sel(struct ad4130_state *st,
176662306a36Sopenharmony_ci			       enum ad4130_mclk_sel mclk_sel)
176762306a36Sopenharmony_ci{
176862306a36Sopenharmony_ci	return regmap_update_bits(st->regmap, AD4130_ADC_CONTROL_REG,
176962306a36Sopenharmony_ci				 AD4130_ADC_CONTROL_MCLK_SEL_MASK,
177062306a36Sopenharmony_ci				 FIELD_PREP(AD4130_ADC_CONTROL_MCLK_SEL_MASK,
177162306a36Sopenharmony_ci					    mclk_sel));
177262306a36Sopenharmony_ci}
177362306a36Sopenharmony_ci
177462306a36Sopenharmony_cistatic unsigned long ad4130_int_clk_recalc_rate(struct clk_hw *hw,
177562306a36Sopenharmony_ci						unsigned long parent_rate)
177662306a36Sopenharmony_ci{
177762306a36Sopenharmony_ci	return AD4130_MCLK_FREQ_76_8KHZ;
177862306a36Sopenharmony_ci}
177962306a36Sopenharmony_ci
178062306a36Sopenharmony_cistatic int ad4130_int_clk_is_enabled(struct clk_hw *hw)
178162306a36Sopenharmony_ci{
178262306a36Sopenharmony_ci	struct ad4130_state *st = container_of(hw, struct ad4130_state, int_clk_hw);
178362306a36Sopenharmony_ci
178462306a36Sopenharmony_ci	return st->mclk_sel == AD4130_MCLK_76_8KHZ_OUT;
178562306a36Sopenharmony_ci}
178662306a36Sopenharmony_ci
178762306a36Sopenharmony_cistatic int ad4130_int_clk_prepare(struct clk_hw *hw)
178862306a36Sopenharmony_ci{
178962306a36Sopenharmony_ci	struct ad4130_state *st = container_of(hw, struct ad4130_state, int_clk_hw);
179062306a36Sopenharmony_ci	int ret;
179162306a36Sopenharmony_ci
179262306a36Sopenharmony_ci	ret = ad4130_set_mclk_sel(st, AD4130_MCLK_76_8KHZ_OUT);
179362306a36Sopenharmony_ci	if (ret)
179462306a36Sopenharmony_ci		return ret;
179562306a36Sopenharmony_ci
179662306a36Sopenharmony_ci	st->mclk_sel = AD4130_MCLK_76_8KHZ_OUT;
179762306a36Sopenharmony_ci
179862306a36Sopenharmony_ci	return 0;
179962306a36Sopenharmony_ci}
180062306a36Sopenharmony_ci
180162306a36Sopenharmony_cistatic void ad4130_int_clk_unprepare(struct clk_hw *hw)
180262306a36Sopenharmony_ci{
180362306a36Sopenharmony_ci	struct ad4130_state *st = container_of(hw, struct ad4130_state, int_clk_hw);
180462306a36Sopenharmony_ci	int ret;
180562306a36Sopenharmony_ci
180662306a36Sopenharmony_ci	ret = ad4130_set_mclk_sel(st, AD4130_MCLK_76_8KHZ);
180762306a36Sopenharmony_ci	if (ret)
180862306a36Sopenharmony_ci		return;
180962306a36Sopenharmony_ci
181062306a36Sopenharmony_ci	st->mclk_sel = AD4130_MCLK_76_8KHZ;
181162306a36Sopenharmony_ci}
181262306a36Sopenharmony_ci
181362306a36Sopenharmony_cistatic const struct clk_ops ad4130_int_clk_ops = {
181462306a36Sopenharmony_ci	.recalc_rate = ad4130_int_clk_recalc_rate,
181562306a36Sopenharmony_ci	.is_enabled = ad4130_int_clk_is_enabled,
181662306a36Sopenharmony_ci	.prepare = ad4130_int_clk_prepare,
181762306a36Sopenharmony_ci	.unprepare = ad4130_int_clk_unprepare,
181862306a36Sopenharmony_ci};
181962306a36Sopenharmony_ci
182062306a36Sopenharmony_cistatic void ad4130_clk_del_provider(void *of_node)
182162306a36Sopenharmony_ci{
182262306a36Sopenharmony_ci	of_clk_del_provider(of_node);
182362306a36Sopenharmony_ci}
182462306a36Sopenharmony_ci
182562306a36Sopenharmony_cistatic int ad4130_setup_int_clk(struct ad4130_state *st)
182662306a36Sopenharmony_ci{
182762306a36Sopenharmony_ci	struct device *dev = &st->spi->dev;
182862306a36Sopenharmony_ci	struct device_node *of_node = dev_of_node(dev);
182962306a36Sopenharmony_ci	struct clk_init_data init = {};
183062306a36Sopenharmony_ci	const char *clk_name;
183162306a36Sopenharmony_ci	struct clk *clk;
183262306a36Sopenharmony_ci	int ret;
183362306a36Sopenharmony_ci
183462306a36Sopenharmony_ci	if (st->int_pin_sel == AD4130_INT_PIN_CLK ||
183562306a36Sopenharmony_ci	    st->mclk_sel != AD4130_MCLK_76_8KHZ)
183662306a36Sopenharmony_ci		return 0;
183762306a36Sopenharmony_ci
183862306a36Sopenharmony_ci	if (!of_node)
183962306a36Sopenharmony_ci		return 0;
184062306a36Sopenharmony_ci
184162306a36Sopenharmony_ci	clk_name = of_node->name;
184262306a36Sopenharmony_ci	of_property_read_string(of_node, "clock-output-names", &clk_name);
184362306a36Sopenharmony_ci
184462306a36Sopenharmony_ci	init.name = clk_name;
184562306a36Sopenharmony_ci	init.ops = &ad4130_int_clk_ops;
184662306a36Sopenharmony_ci
184762306a36Sopenharmony_ci	st->int_clk_hw.init = &init;
184862306a36Sopenharmony_ci	clk = devm_clk_register(dev, &st->int_clk_hw);
184962306a36Sopenharmony_ci	if (IS_ERR(clk))
185062306a36Sopenharmony_ci		return PTR_ERR(clk);
185162306a36Sopenharmony_ci
185262306a36Sopenharmony_ci	ret = of_clk_add_provider(of_node, of_clk_src_simple_get, clk);
185362306a36Sopenharmony_ci	if (ret)
185462306a36Sopenharmony_ci		return ret;
185562306a36Sopenharmony_ci
185662306a36Sopenharmony_ci	return devm_add_action_or_reset(dev, ad4130_clk_del_provider, of_node);
185762306a36Sopenharmony_ci}
185862306a36Sopenharmony_ci
185962306a36Sopenharmony_cistatic int ad4130_setup(struct iio_dev *indio_dev)
186062306a36Sopenharmony_ci{
186162306a36Sopenharmony_ci	struct ad4130_state *st = iio_priv(indio_dev);
186262306a36Sopenharmony_ci	struct device *dev = &st->spi->dev;
186362306a36Sopenharmony_ci	unsigned int int_ref_val;
186462306a36Sopenharmony_ci	unsigned long rate = AD4130_MCLK_FREQ_76_8KHZ;
186562306a36Sopenharmony_ci	unsigned int val;
186662306a36Sopenharmony_ci	unsigned int i;
186762306a36Sopenharmony_ci	int ret;
186862306a36Sopenharmony_ci
186962306a36Sopenharmony_ci	if (st->mclk_sel == AD4130_MCLK_153_6KHZ_EXT)
187062306a36Sopenharmony_ci		rate = AD4130_MCLK_FREQ_153_6KHZ;
187162306a36Sopenharmony_ci
187262306a36Sopenharmony_ci	ret = clk_set_rate(st->mclk, rate);
187362306a36Sopenharmony_ci	if (ret)
187462306a36Sopenharmony_ci		return ret;
187562306a36Sopenharmony_ci
187662306a36Sopenharmony_ci	ret = clk_prepare_enable(st->mclk);
187762306a36Sopenharmony_ci	if (ret)
187862306a36Sopenharmony_ci		return ret;
187962306a36Sopenharmony_ci
188062306a36Sopenharmony_ci	ret = devm_add_action_or_reset(dev, ad4130_clk_disable_unprepare,
188162306a36Sopenharmony_ci				       st->mclk);
188262306a36Sopenharmony_ci	if (ret)
188362306a36Sopenharmony_ci		return ret;
188462306a36Sopenharmony_ci
188562306a36Sopenharmony_ci	if (st->int_ref_uv == AD4130_INT_REF_2_5V)
188662306a36Sopenharmony_ci		int_ref_val = AD4130_INT_REF_VAL_2_5V;
188762306a36Sopenharmony_ci	else
188862306a36Sopenharmony_ci		int_ref_val = AD4130_INT_REF_VAL_1_25V;
188962306a36Sopenharmony_ci
189062306a36Sopenharmony_ci	/* Switch to SPI 4-wire mode. */
189162306a36Sopenharmony_ci	val =  FIELD_PREP(AD4130_ADC_CONTROL_CSB_EN_MASK, 1);
189262306a36Sopenharmony_ci	val |= FIELD_PREP(AD4130_ADC_CONTROL_BIPOLAR_MASK, st->bipolar);
189362306a36Sopenharmony_ci	val |= FIELD_PREP(AD4130_ADC_CONTROL_INT_REF_EN_MASK, st->int_ref_en);
189462306a36Sopenharmony_ci	val |= FIELD_PREP(AD4130_ADC_CONTROL_MODE_MASK, AD4130_MODE_IDLE);
189562306a36Sopenharmony_ci	val |= FIELD_PREP(AD4130_ADC_CONTROL_MCLK_SEL_MASK, st->mclk_sel);
189662306a36Sopenharmony_ci	val |= FIELD_PREP(AD4130_ADC_CONTROL_INT_REF_VAL_MASK, int_ref_val);
189762306a36Sopenharmony_ci
189862306a36Sopenharmony_ci	ret = regmap_write(st->regmap, AD4130_ADC_CONTROL_REG, val);
189962306a36Sopenharmony_ci	if (ret)
190062306a36Sopenharmony_ci		return ret;
190162306a36Sopenharmony_ci
190262306a36Sopenharmony_ci	/*
190362306a36Sopenharmony_ci	 * Configure unused GPIOs for output. If configured, the interrupt
190462306a36Sopenharmony_ci	 * function of P2 takes priority over the GPIO out function.
190562306a36Sopenharmony_ci	 */
190662306a36Sopenharmony_ci	val = 0;
190762306a36Sopenharmony_ci	for (i = 0; i < AD4130_MAX_GPIOS; i++)
190862306a36Sopenharmony_ci		if (st->pins_fn[i + AD4130_AIN2_P1] == AD4130_PIN_FN_NONE)
190962306a36Sopenharmony_ci			val |= FIELD_PREP(AD4130_IO_CONTROL_GPIO_CTRL_MASK, BIT(i));
191062306a36Sopenharmony_ci
191162306a36Sopenharmony_ci	val |= FIELD_PREP(AD4130_IO_CONTROL_INT_PIN_SEL_MASK, st->int_pin_sel);
191262306a36Sopenharmony_ci
191362306a36Sopenharmony_ci	ret = regmap_write(st->regmap, AD4130_IO_CONTROL_REG, val);
191462306a36Sopenharmony_ci	if (ret)
191562306a36Sopenharmony_ci		return ret;
191662306a36Sopenharmony_ci
191762306a36Sopenharmony_ci	val = 0;
191862306a36Sopenharmony_ci	for (i = 0; i < st->num_vbias_pins; i++)
191962306a36Sopenharmony_ci		val |= BIT(st->vbias_pins[i]);
192062306a36Sopenharmony_ci
192162306a36Sopenharmony_ci	ret = regmap_write(st->regmap, AD4130_VBIAS_REG, val);
192262306a36Sopenharmony_ci	if (ret)
192362306a36Sopenharmony_ci		return ret;
192462306a36Sopenharmony_ci
192562306a36Sopenharmony_ci	ret = regmap_update_bits(st->regmap, AD4130_FIFO_CONTROL_REG,
192662306a36Sopenharmony_ci				 AD4130_FIFO_CONTROL_HEADER_MASK, 0);
192762306a36Sopenharmony_ci	if (ret)
192862306a36Sopenharmony_ci		return ret;
192962306a36Sopenharmony_ci
193062306a36Sopenharmony_ci	/* FIFO watermark interrupt starts out as enabled, disable it. */
193162306a36Sopenharmony_ci	ret = ad4130_set_watermark_interrupt_en(st, false);
193262306a36Sopenharmony_ci	if (ret)
193362306a36Sopenharmony_ci		return ret;
193462306a36Sopenharmony_ci
193562306a36Sopenharmony_ci	/* Setup channels. */
193662306a36Sopenharmony_ci	for (i = 0; i < indio_dev->num_channels; i++) {
193762306a36Sopenharmony_ci		struct ad4130_chan_info *chan_info = &st->chans_info[i];
193862306a36Sopenharmony_ci		struct iio_chan_spec *chan = &st->chans[i];
193962306a36Sopenharmony_ci		unsigned int val;
194062306a36Sopenharmony_ci
194162306a36Sopenharmony_ci		val = FIELD_PREP(AD4130_CHANNEL_AINP_MASK, chan->channel) |
194262306a36Sopenharmony_ci		      FIELD_PREP(AD4130_CHANNEL_AINM_MASK, chan->channel2) |
194362306a36Sopenharmony_ci		      FIELD_PREP(AD4130_CHANNEL_IOUT1_MASK, chan_info->iout0) |
194462306a36Sopenharmony_ci		      FIELD_PREP(AD4130_CHANNEL_IOUT2_MASK, chan_info->iout1);
194562306a36Sopenharmony_ci
194662306a36Sopenharmony_ci		ret = regmap_write(st->regmap, AD4130_CHANNEL_X_REG(i), val);
194762306a36Sopenharmony_ci		if (ret)
194862306a36Sopenharmony_ci			return ret;
194962306a36Sopenharmony_ci	}
195062306a36Sopenharmony_ci
195162306a36Sopenharmony_ci	return 0;
195262306a36Sopenharmony_ci}
195362306a36Sopenharmony_ci
195462306a36Sopenharmony_cistatic int ad4130_soft_reset(struct ad4130_state *st)
195562306a36Sopenharmony_ci{
195662306a36Sopenharmony_ci	int ret;
195762306a36Sopenharmony_ci
195862306a36Sopenharmony_ci	ret = spi_write(st->spi, st->reset_buf, sizeof(st->reset_buf));
195962306a36Sopenharmony_ci	if (ret)
196062306a36Sopenharmony_ci		return ret;
196162306a36Sopenharmony_ci
196262306a36Sopenharmony_ci	fsleep(AD4130_RESET_SLEEP_US);
196362306a36Sopenharmony_ci
196462306a36Sopenharmony_ci	return 0;
196562306a36Sopenharmony_ci}
196662306a36Sopenharmony_ci
196762306a36Sopenharmony_cistatic void ad4130_disable_regulators(void *data)
196862306a36Sopenharmony_ci{
196962306a36Sopenharmony_ci	struct ad4130_state *st = data;
197062306a36Sopenharmony_ci
197162306a36Sopenharmony_ci	regulator_bulk_disable(ARRAY_SIZE(st->regulators), st->regulators);
197262306a36Sopenharmony_ci}
197362306a36Sopenharmony_ci
197462306a36Sopenharmony_cistatic int ad4130_probe(struct spi_device *spi)
197562306a36Sopenharmony_ci{
197662306a36Sopenharmony_ci	struct device *dev = &spi->dev;
197762306a36Sopenharmony_ci	struct iio_dev *indio_dev;
197862306a36Sopenharmony_ci	struct ad4130_state *st;
197962306a36Sopenharmony_ci	int ret;
198062306a36Sopenharmony_ci
198162306a36Sopenharmony_ci	indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
198262306a36Sopenharmony_ci	if (!indio_dev)
198362306a36Sopenharmony_ci		return -ENOMEM;
198462306a36Sopenharmony_ci
198562306a36Sopenharmony_ci	st = iio_priv(indio_dev);
198662306a36Sopenharmony_ci
198762306a36Sopenharmony_ci	memset(st->reset_buf, 0xff, sizeof(st->reset_buf));
198862306a36Sopenharmony_ci	init_completion(&st->completion);
198962306a36Sopenharmony_ci	mutex_init(&st->lock);
199062306a36Sopenharmony_ci	st->spi = spi;
199162306a36Sopenharmony_ci
199262306a36Sopenharmony_ci	/*
199362306a36Sopenharmony_ci	 * Xfer:   [ XFR1 ] [         XFR2         ]
199462306a36Sopenharmony_ci	 * Master:  0x7D N   ......................
199562306a36Sopenharmony_ci	 * Slave:   ......   DATA1 DATA2 ... DATAN
199662306a36Sopenharmony_ci	 */
199762306a36Sopenharmony_ci	st->fifo_tx_buf[0] = AD4130_COMMS_READ_MASK | AD4130_FIFO_DATA_REG;
199862306a36Sopenharmony_ci	st->fifo_xfer[0].tx_buf = st->fifo_tx_buf;
199962306a36Sopenharmony_ci	st->fifo_xfer[0].len = sizeof(st->fifo_tx_buf);
200062306a36Sopenharmony_ci	st->fifo_xfer[1].rx_buf = st->fifo_rx_buf;
200162306a36Sopenharmony_ci	spi_message_init_with_transfers(&st->fifo_msg, st->fifo_xfer,
200262306a36Sopenharmony_ci					ARRAY_SIZE(st->fifo_xfer));
200362306a36Sopenharmony_ci
200462306a36Sopenharmony_ci	indio_dev->name = AD4130_NAME;
200562306a36Sopenharmony_ci	indio_dev->modes = INDIO_DIRECT_MODE;
200662306a36Sopenharmony_ci	indio_dev->info = &ad4130_info;
200762306a36Sopenharmony_ci
200862306a36Sopenharmony_ci	st->regmap = devm_regmap_init(dev, NULL, st, &ad4130_regmap_config);
200962306a36Sopenharmony_ci	if (IS_ERR(st->regmap))
201062306a36Sopenharmony_ci		return PTR_ERR(st->regmap);
201162306a36Sopenharmony_ci
201262306a36Sopenharmony_ci	st->regulators[0].supply = "avdd";
201362306a36Sopenharmony_ci	st->regulators[1].supply = "iovdd";
201462306a36Sopenharmony_ci	st->regulators[2].supply = "refin1";
201562306a36Sopenharmony_ci	st->regulators[3].supply = "refin2";
201662306a36Sopenharmony_ci
201762306a36Sopenharmony_ci	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(st->regulators),
201862306a36Sopenharmony_ci				      st->regulators);
201962306a36Sopenharmony_ci	if (ret)
202062306a36Sopenharmony_ci		return dev_err_probe(dev, ret, "Failed to get regulators\n");
202162306a36Sopenharmony_ci
202262306a36Sopenharmony_ci	ret = regulator_bulk_enable(ARRAY_SIZE(st->regulators), st->regulators);
202362306a36Sopenharmony_ci	if (ret)
202462306a36Sopenharmony_ci		return dev_err_probe(dev, ret, "Failed to enable regulators\n");
202562306a36Sopenharmony_ci
202662306a36Sopenharmony_ci	ret = devm_add_action_or_reset(dev, ad4130_disable_regulators, st);
202762306a36Sopenharmony_ci	if (ret)
202862306a36Sopenharmony_ci		return dev_err_probe(dev, ret,
202962306a36Sopenharmony_ci				     "Failed to add regulators disable action\n");
203062306a36Sopenharmony_ci
203162306a36Sopenharmony_ci	ret = ad4130_soft_reset(st);
203262306a36Sopenharmony_ci	if (ret)
203362306a36Sopenharmony_ci		return ret;
203462306a36Sopenharmony_ci
203562306a36Sopenharmony_ci	ret = ad4310_parse_fw(indio_dev);
203662306a36Sopenharmony_ci	if (ret)
203762306a36Sopenharmony_ci		return ret;
203862306a36Sopenharmony_ci
203962306a36Sopenharmony_ci	ret = ad4130_setup(indio_dev);
204062306a36Sopenharmony_ci	if (ret)
204162306a36Sopenharmony_ci		return ret;
204262306a36Sopenharmony_ci
204362306a36Sopenharmony_ci	ret = ad4130_setup_int_clk(st);
204462306a36Sopenharmony_ci	if (ret)
204562306a36Sopenharmony_ci		return ret;
204662306a36Sopenharmony_ci
204762306a36Sopenharmony_ci	ad4130_fill_scale_tbls(st);
204862306a36Sopenharmony_ci
204962306a36Sopenharmony_ci	st->gc.owner = THIS_MODULE;
205062306a36Sopenharmony_ci	st->gc.label = AD4130_NAME;
205162306a36Sopenharmony_ci	st->gc.base = -1;
205262306a36Sopenharmony_ci	st->gc.ngpio = AD4130_MAX_GPIOS;
205362306a36Sopenharmony_ci	st->gc.parent = dev;
205462306a36Sopenharmony_ci	st->gc.can_sleep = true;
205562306a36Sopenharmony_ci	st->gc.init_valid_mask = ad4130_gpio_init_valid_mask;
205662306a36Sopenharmony_ci	st->gc.get_direction = ad4130_gpio_get_direction;
205762306a36Sopenharmony_ci	st->gc.set = ad4130_gpio_set;
205862306a36Sopenharmony_ci
205962306a36Sopenharmony_ci	ret = devm_gpiochip_add_data(dev, &st->gc, st);
206062306a36Sopenharmony_ci	if (ret)
206162306a36Sopenharmony_ci		return ret;
206262306a36Sopenharmony_ci
206362306a36Sopenharmony_ci	ret = devm_iio_kfifo_buffer_setup_ext(dev, indio_dev,
206462306a36Sopenharmony_ci					      &ad4130_buffer_ops,
206562306a36Sopenharmony_ci					      ad4130_fifo_attributes);
206662306a36Sopenharmony_ci	if (ret)
206762306a36Sopenharmony_ci		return ret;
206862306a36Sopenharmony_ci
206962306a36Sopenharmony_ci	ret = devm_request_threaded_irq(dev, spi->irq, NULL,
207062306a36Sopenharmony_ci					ad4130_irq_handler, IRQF_ONESHOT,
207162306a36Sopenharmony_ci					indio_dev->name, indio_dev);
207262306a36Sopenharmony_ci	if (ret)
207362306a36Sopenharmony_ci		return dev_err_probe(dev, ret, "Failed to request irq\n");
207462306a36Sopenharmony_ci
207562306a36Sopenharmony_ci	/*
207662306a36Sopenharmony_ci	 * When the chip enters FIFO mode, IRQ polarity is inverted.
207762306a36Sopenharmony_ci	 * When the chip exits FIFO mode, IRQ polarity returns to normal.
207862306a36Sopenharmony_ci	 * See datasheet pages: 65, FIFO Watermark Interrupt section,
207962306a36Sopenharmony_ci	 * and 71, Bit Descriptions for STATUS Register, RDYB.
208062306a36Sopenharmony_ci	 * Cache the normal and inverted IRQ triggers to set them when
208162306a36Sopenharmony_ci	 * entering and exiting FIFO mode.
208262306a36Sopenharmony_ci	 */
208362306a36Sopenharmony_ci	st->irq_trigger = irq_get_trigger_type(spi->irq);
208462306a36Sopenharmony_ci	if (st->irq_trigger & IRQF_TRIGGER_RISING)
208562306a36Sopenharmony_ci		st->inv_irq_trigger = IRQF_TRIGGER_FALLING;
208662306a36Sopenharmony_ci	else if (st->irq_trigger & IRQF_TRIGGER_FALLING)
208762306a36Sopenharmony_ci		st->inv_irq_trigger = IRQF_TRIGGER_RISING;
208862306a36Sopenharmony_ci	else
208962306a36Sopenharmony_ci		return dev_err_probe(dev, -EINVAL, "Invalid irq flags: %u\n",
209062306a36Sopenharmony_ci				     st->irq_trigger);
209162306a36Sopenharmony_ci
209262306a36Sopenharmony_ci	return devm_iio_device_register(dev, indio_dev);
209362306a36Sopenharmony_ci}
209462306a36Sopenharmony_ci
209562306a36Sopenharmony_cistatic const struct of_device_id ad4130_of_match[] = {
209662306a36Sopenharmony_ci	{
209762306a36Sopenharmony_ci		.compatible = "adi,ad4130",
209862306a36Sopenharmony_ci	},
209962306a36Sopenharmony_ci	{ }
210062306a36Sopenharmony_ci};
210162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, ad4130_of_match);
210262306a36Sopenharmony_ci
210362306a36Sopenharmony_cistatic struct spi_driver ad4130_driver = {
210462306a36Sopenharmony_ci	.driver = {
210562306a36Sopenharmony_ci		.name = AD4130_NAME,
210662306a36Sopenharmony_ci		.of_match_table = ad4130_of_match,
210762306a36Sopenharmony_ci	},
210862306a36Sopenharmony_ci	.probe = ad4130_probe,
210962306a36Sopenharmony_ci};
211062306a36Sopenharmony_cimodule_spi_driver(ad4130_driver);
211162306a36Sopenharmony_ci
211262306a36Sopenharmony_ciMODULE_AUTHOR("Cosmin Tanislav <cosmin.tanislav@analog.com>");
211362306a36Sopenharmony_ciMODULE_DESCRIPTION("Analog Devices AD4130 SPI driver");
211462306a36Sopenharmony_ciMODULE_LICENSE("GPL");
2115