xref: /kernel/linux/linux-6.6/drivers/iio/dac/ad3552r.c (revision 62306a36)
162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Analog Devices AD3552R
462306a36Sopenharmony_ci * Digital to Analog converter driver
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright 2021 Analog Devices Inc.
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci#include <asm/unaligned.h>
962306a36Sopenharmony_ci#include <linux/device.h>
1062306a36Sopenharmony_ci#include <linux/iio/triggered_buffer.h>
1162306a36Sopenharmony_ci#include <linux/iio/trigger_consumer.h>
1262306a36Sopenharmony_ci#include <linux/iopoll.h>
1362306a36Sopenharmony_ci#include <linux/kernel.h>
1462306a36Sopenharmony_ci#include <linux/regulator/consumer.h>
1562306a36Sopenharmony_ci#include <linux/spi/spi.h>
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci/* Register addresses */
1862306a36Sopenharmony_ci/* Primary address space */
1962306a36Sopenharmony_ci#define AD3552R_REG_ADDR_INTERFACE_CONFIG_A		0x00
2062306a36Sopenharmony_ci#define   AD3552R_MASK_SOFTWARE_RESET			(BIT(7) | BIT(0))
2162306a36Sopenharmony_ci#define   AD3552R_MASK_ADDR_ASCENSION			BIT(5)
2262306a36Sopenharmony_ci#define   AD3552R_MASK_SDO_ACTIVE			BIT(4)
2362306a36Sopenharmony_ci#define AD3552R_REG_ADDR_INTERFACE_CONFIG_B		0x01
2462306a36Sopenharmony_ci#define   AD3552R_MASK_SINGLE_INST			BIT(7)
2562306a36Sopenharmony_ci#define   AD3552R_MASK_SHORT_INSTRUCTION		BIT(3)
2662306a36Sopenharmony_ci#define AD3552R_REG_ADDR_DEVICE_CONFIG			0x02
2762306a36Sopenharmony_ci#define   AD3552R_MASK_DEVICE_STATUS(n)			BIT(4 + (n))
2862306a36Sopenharmony_ci#define   AD3552R_MASK_CUSTOM_MODES			GENMASK(3, 2)
2962306a36Sopenharmony_ci#define   AD3552R_MASK_OPERATING_MODES			GENMASK(1, 0)
3062306a36Sopenharmony_ci#define AD3552R_REG_ADDR_CHIP_TYPE			0x03
3162306a36Sopenharmony_ci#define   AD3552R_MASK_CLASS				GENMASK(7, 0)
3262306a36Sopenharmony_ci#define AD3552R_REG_ADDR_PRODUCT_ID_L			0x04
3362306a36Sopenharmony_ci#define AD3552R_REG_ADDR_PRODUCT_ID_H			0x05
3462306a36Sopenharmony_ci#define AD3552R_REG_ADDR_CHIP_GRADE			0x06
3562306a36Sopenharmony_ci#define   AD3552R_MASK_GRADE				GENMASK(7, 4)
3662306a36Sopenharmony_ci#define   AD3552R_MASK_DEVICE_REVISION			GENMASK(3, 0)
3762306a36Sopenharmony_ci#define AD3552R_REG_ADDR_SCRATCH_PAD			0x0A
3862306a36Sopenharmony_ci#define AD3552R_REG_ADDR_SPI_REVISION			0x0B
3962306a36Sopenharmony_ci#define AD3552R_REG_ADDR_VENDOR_L			0x0C
4062306a36Sopenharmony_ci#define AD3552R_REG_ADDR_VENDOR_H			0x0D
4162306a36Sopenharmony_ci#define AD3552R_REG_ADDR_STREAM_MODE			0x0E
4262306a36Sopenharmony_ci#define   AD3552R_MASK_LENGTH				GENMASK(7, 0)
4362306a36Sopenharmony_ci#define AD3552R_REG_ADDR_TRANSFER_REGISTER		0x0F
4462306a36Sopenharmony_ci#define   AD3552R_MASK_MULTI_IO_MODE			GENMASK(7, 6)
4562306a36Sopenharmony_ci#define   AD3552R_MASK_STREAM_LENGTH_KEEP_VALUE		BIT(2)
4662306a36Sopenharmony_ci#define AD3552R_REG_ADDR_INTERFACE_CONFIG_C		0x10
4762306a36Sopenharmony_ci#define   AD3552R_MASK_CRC_ENABLE			(GENMASK(7, 6) |\
4862306a36Sopenharmony_ci							 GENMASK(1, 0))
4962306a36Sopenharmony_ci#define   AD3552R_MASK_STRICT_REGISTER_ACCESS		BIT(5)
5062306a36Sopenharmony_ci#define AD3552R_REG_ADDR_INTERFACE_STATUS_A		0x11
5162306a36Sopenharmony_ci#define   AD3552R_MASK_INTERFACE_NOT_READY		BIT(7)
5262306a36Sopenharmony_ci#define   AD3552R_MASK_CLOCK_COUNTING_ERROR		BIT(5)
5362306a36Sopenharmony_ci#define   AD3552R_MASK_INVALID_OR_NO_CRC		BIT(3)
5462306a36Sopenharmony_ci#define   AD3552R_MASK_WRITE_TO_READ_ONLY_REGISTER	BIT(2)
5562306a36Sopenharmony_ci#define   AD3552R_MASK_PARTIAL_REGISTER_ACCESS		BIT(1)
5662306a36Sopenharmony_ci#define   AD3552R_MASK_REGISTER_ADDRESS_INVALID		BIT(0)
5762306a36Sopenharmony_ci#define AD3552R_REG_ADDR_INTERFACE_CONFIG_D		0x14
5862306a36Sopenharmony_ci#define   AD3552R_MASK_ALERT_ENABLE_PULLUP		BIT(6)
5962306a36Sopenharmony_ci#define   AD3552R_MASK_MEM_CRC_EN			BIT(4)
6062306a36Sopenharmony_ci#define   AD3552R_MASK_SDO_DRIVE_STRENGTH		GENMASK(3, 2)
6162306a36Sopenharmony_ci#define   AD3552R_MASK_DUAL_SPI_SYNCHROUNOUS_EN		BIT(1)
6262306a36Sopenharmony_ci#define   AD3552R_MASK_SPI_CONFIG_DDR			BIT(0)
6362306a36Sopenharmony_ci#define AD3552R_REG_ADDR_SH_REFERENCE_CONFIG		0x15
6462306a36Sopenharmony_ci#define   AD3552R_MASK_IDUMP_FAST_MODE			BIT(6)
6562306a36Sopenharmony_ci#define   AD3552R_MASK_SAMPLE_HOLD_DIFFERENTIAL_USER_EN	BIT(5)
6662306a36Sopenharmony_ci#define   AD3552R_MASK_SAMPLE_HOLD_USER_TRIM		GENMASK(4, 3)
6762306a36Sopenharmony_ci#define   AD3552R_MASK_SAMPLE_HOLD_USER_ENABLE		BIT(2)
6862306a36Sopenharmony_ci#define   AD3552R_MASK_REFERENCE_VOLTAGE_SEL		GENMASK(1, 0)
6962306a36Sopenharmony_ci#define AD3552R_REG_ADDR_ERR_ALARM_MASK			0x16
7062306a36Sopenharmony_ci#define   AD3552R_MASK_REF_RANGE_ALARM			BIT(6)
7162306a36Sopenharmony_ci#define   AD3552R_MASK_CLOCK_COUNT_ERR_ALARM		BIT(5)
7262306a36Sopenharmony_ci#define   AD3552R_MASK_MEM_CRC_ERR_ALARM		BIT(4)
7362306a36Sopenharmony_ci#define   AD3552R_MASK_SPI_CRC_ERR_ALARM		BIT(3)
7462306a36Sopenharmony_ci#define   AD3552R_MASK_WRITE_TO_READ_ONLY_ALARM		BIT(2)
7562306a36Sopenharmony_ci#define   AD3552R_MASK_PARTIAL_REGISTER_ACCESS_ALARM	BIT(1)
7662306a36Sopenharmony_ci#define   AD3552R_MASK_REGISTER_ADDRESS_INVALID_ALARM	BIT(0)
7762306a36Sopenharmony_ci#define AD3552R_REG_ADDR_ERR_STATUS			0x17
7862306a36Sopenharmony_ci#define   AD3552R_MASK_REF_RANGE_ERR_STATUS			BIT(6)
7962306a36Sopenharmony_ci#define   AD3552R_MASK_DUAL_SPI_STREAM_EXCEEDS_DAC_ERR_STATUS	BIT(5)
8062306a36Sopenharmony_ci#define   AD3552R_MASK_MEM_CRC_ERR_STATUS			BIT(4)
8162306a36Sopenharmony_ci#define   AD3552R_MASK_RESET_STATUS				BIT(0)
8262306a36Sopenharmony_ci#define AD3552R_REG_ADDR_POWERDOWN_CONFIG		0x18
8362306a36Sopenharmony_ci#define   AD3552R_MASK_CH_DAC_POWERDOWN(ch)		BIT(4 + (ch))
8462306a36Sopenharmony_ci#define   AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(ch)	BIT(ch)
8562306a36Sopenharmony_ci#define AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE		0x19
8662306a36Sopenharmony_ci#define   AD3552R_MASK_CH_OUTPUT_RANGE_SEL(ch)		((ch) ? GENMASK(7, 4) :\
8762306a36Sopenharmony_ci							 GENMASK(3, 0))
8862306a36Sopenharmony_ci#define AD3552R_REG_ADDR_CH_OFFSET(ch)			(0x1B + (ch) * 2)
8962306a36Sopenharmony_ci#define   AD3552R_MASK_CH_OFFSET_BITS_0_7		GENMASK(7, 0)
9062306a36Sopenharmony_ci#define AD3552R_REG_ADDR_CH_GAIN(ch)			(0x1C + (ch) * 2)
9162306a36Sopenharmony_ci#define   AD3552R_MASK_CH_RANGE_OVERRIDE		BIT(7)
9262306a36Sopenharmony_ci#define   AD3552R_MASK_CH_GAIN_SCALING_N		GENMASK(6, 5)
9362306a36Sopenharmony_ci#define   AD3552R_MASK_CH_GAIN_SCALING_P		GENMASK(4, 3)
9462306a36Sopenharmony_ci#define   AD3552R_MASK_CH_OFFSET_POLARITY		BIT(2)
9562306a36Sopenharmony_ci#define   AD3552R_MASK_CH_OFFSET_BIT_8			BIT(0)
9662306a36Sopenharmony_ci/*
9762306a36Sopenharmony_ci * Secondary region
9862306a36Sopenharmony_ci * For multibyte registers specify the highest address because the access is
9962306a36Sopenharmony_ci * done in descending order
10062306a36Sopenharmony_ci */
10162306a36Sopenharmony_ci#define AD3552R_SECONDARY_REGION_START			0x28
10262306a36Sopenharmony_ci#define AD3552R_REG_ADDR_HW_LDAC_16B			0x28
10362306a36Sopenharmony_ci#define AD3552R_REG_ADDR_CH_DAC_16B(ch)			(0x2C - (1 - ch) * 2)
10462306a36Sopenharmony_ci#define AD3552R_REG_ADDR_DAC_PAGE_MASK_16B		0x2E
10562306a36Sopenharmony_ci#define AD3552R_REG_ADDR_CH_SELECT_16B			0x2F
10662306a36Sopenharmony_ci#define AD3552R_REG_ADDR_INPUT_PAGE_MASK_16B		0x31
10762306a36Sopenharmony_ci#define AD3552R_REG_ADDR_SW_LDAC_16B			0x32
10862306a36Sopenharmony_ci#define AD3552R_REG_ADDR_CH_INPUT_16B(ch)		(0x36 - (1 - ch) * 2)
10962306a36Sopenharmony_ci/* 3 bytes registers */
11062306a36Sopenharmony_ci#define AD3552R_REG_START_24B				0x37
11162306a36Sopenharmony_ci#define AD3552R_REG_ADDR_HW_LDAC_24B			0x37
11262306a36Sopenharmony_ci#define AD3552R_REG_ADDR_CH_DAC_24B(ch)			(0x3D - (1 - ch) * 3)
11362306a36Sopenharmony_ci#define AD3552R_REG_ADDR_DAC_PAGE_MASK_24B		0x40
11462306a36Sopenharmony_ci#define AD3552R_REG_ADDR_CH_SELECT_24B			0x41
11562306a36Sopenharmony_ci#define AD3552R_REG_ADDR_INPUT_PAGE_MASK_24B		0x44
11662306a36Sopenharmony_ci#define AD3552R_REG_ADDR_SW_LDAC_24B			0x45
11762306a36Sopenharmony_ci#define AD3552R_REG_ADDR_CH_INPUT_24B(ch)		(0x4B - (1 - ch) * 3)
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci/* Useful defines */
12062306a36Sopenharmony_ci#define AD3552R_NUM_CH					2
12162306a36Sopenharmony_ci#define AD3552R_MASK_CH(ch)				BIT(ch)
12262306a36Sopenharmony_ci#define AD3552R_MASK_ALL_CH				GENMASK(1, 0)
12362306a36Sopenharmony_ci#define AD3552R_MAX_REG_SIZE				3
12462306a36Sopenharmony_ci#define AD3552R_READ_BIT				BIT(7)
12562306a36Sopenharmony_ci#define AD3552R_ADDR_MASK				GENMASK(6, 0)
12662306a36Sopenharmony_ci#define AD3552R_MASK_DAC_12B				0xFFF0
12762306a36Sopenharmony_ci#define AD3552R_DEFAULT_CONFIG_B_VALUE			0x8
12862306a36Sopenharmony_ci#define AD3552R_SCRATCH_PAD_TEST_VAL1			0x34
12962306a36Sopenharmony_ci#define AD3552R_SCRATCH_PAD_TEST_VAL2			0xB2
13062306a36Sopenharmony_ci#define AD3552R_GAIN_SCALE				1000
13162306a36Sopenharmony_ci#define AD3552R_LDAC_PULSE_US				100
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_cienum ad3552r_ch_vref_select {
13462306a36Sopenharmony_ci	/* Internal source with Vref I/O floating */
13562306a36Sopenharmony_ci	AD3552R_INTERNAL_VREF_PIN_FLOATING,
13662306a36Sopenharmony_ci	/* Internal source with Vref I/O at 2.5V */
13762306a36Sopenharmony_ci	AD3552R_INTERNAL_VREF_PIN_2P5V,
13862306a36Sopenharmony_ci	/* External source with Vref I/O as input */
13962306a36Sopenharmony_ci	AD3552R_EXTERNAL_VREF_PIN_INPUT
14062306a36Sopenharmony_ci};
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_cienum ad3542r_id {
14362306a36Sopenharmony_ci	AD3542R_ID = 0x4009,
14462306a36Sopenharmony_ci	AD3552R_ID = 0x4008,
14562306a36Sopenharmony_ci};
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_cienum ad3552r_ch_output_range {
14862306a36Sopenharmony_ci	/* Range from 0 V to 2.5 V. Requires Rfb1x connection */
14962306a36Sopenharmony_ci	AD3552R_CH_OUTPUT_RANGE_0__2P5V,
15062306a36Sopenharmony_ci	/* Range from 0 V to 5 V. Requires Rfb1x connection  */
15162306a36Sopenharmony_ci	AD3552R_CH_OUTPUT_RANGE_0__5V,
15262306a36Sopenharmony_ci	/* Range from 0 V to 10 V. Requires Rfb2x connection  */
15362306a36Sopenharmony_ci	AD3552R_CH_OUTPUT_RANGE_0__10V,
15462306a36Sopenharmony_ci	/* Range from -5 V to 5 V. Requires Rfb2x connection  */
15562306a36Sopenharmony_ci	AD3552R_CH_OUTPUT_RANGE_NEG_5__5V,
15662306a36Sopenharmony_ci	/* Range from -10 V to 10 V. Requires Rfb4x connection  */
15762306a36Sopenharmony_ci	AD3552R_CH_OUTPUT_RANGE_NEG_10__10V,
15862306a36Sopenharmony_ci};
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_cistatic const s32 ad3552r_ch_ranges[][2] = {
16162306a36Sopenharmony_ci	[AD3552R_CH_OUTPUT_RANGE_0__2P5V]	= {0, 2500},
16262306a36Sopenharmony_ci	[AD3552R_CH_OUTPUT_RANGE_0__5V]		= {0, 5000},
16362306a36Sopenharmony_ci	[AD3552R_CH_OUTPUT_RANGE_0__10V]	= {0, 10000},
16462306a36Sopenharmony_ci	[AD3552R_CH_OUTPUT_RANGE_NEG_5__5V]	= {-5000, 5000},
16562306a36Sopenharmony_ci	[AD3552R_CH_OUTPUT_RANGE_NEG_10__10V]	= {-10000, 10000}
16662306a36Sopenharmony_ci};
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_cienum ad3542r_ch_output_range {
16962306a36Sopenharmony_ci	/* Range from 0 V to 2.5 V. Requires Rfb1x connection */
17062306a36Sopenharmony_ci	AD3542R_CH_OUTPUT_RANGE_0__2P5V,
17162306a36Sopenharmony_ci	/* Range from 0 V to 3 V. Requires Rfb1x connection  */
17262306a36Sopenharmony_ci	AD3542R_CH_OUTPUT_RANGE_0__3V,
17362306a36Sopenharmony_ci	/* Range from 0 V to 5 V. Requires Rfb1x connection  */
17462306a36Sopenharmony_ci	AD3542R_CH_OUTPUT_RANGE_0__5V,
17562306a36Sopenharmony_ci	/* Range from 0 V to 10 V. Requires Rfb2x connection  */
17662306a36Sopenharmony_ci	AD3542R_CH_OUTPUT_RANGE_0__10V,
17762306a36Sopenharmony_ci	/* Range from -2.5 V to 7.5 V. Requires Rfb2x connection  */
17862306a36Sopenharmony_ci	AD3542R_CH_OUTPUT_RANGE_NEG_2P5__7P5V,
17962306a36Sopenharmony_ci	/* Range from -5 V to 5 V. Requires Rfb2x connection  */
18062306a36Sopenharmony_ci	AD3542R_CH_OUTPUT_RANGE_NEG_5__5V,
18162306a36Sopenharmony_ci};
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_cistatic const s32 ad3542r_ch_ranges[][2] = {
18462306a36Sopenharmony_ci	[AD3542R_CH_OUTPUT_RANGE_0__2P5V]	= {0, 2500},
18562306a36Sopenharmony_ci	[AD3542R_CH_OUTPUT_RANGE_0__3V]		= {0, 3000},
18662306a36Sopenharmony_ci	[AD3542R_CH_OUTPUT_RANGE_0__5V]		= {0, 5000},
18762306a36Sopenharmony_ci	[AD3542R_CH_OUTPUT_RANGE_0__10V]	= {0, 10000},
18862306a36Sopenharmony_ci	[AD3542R_CH_OUTPUT_RANGE_NEG_2P5__7P5V]	= {-2500, 7500},
18962306a36Sopenharmony_ci	[AD3542R_CH_OUTPUT_RANGE_NEG_5__5V]	= {-5000, 5000}
19062306a36Sopenharmony_ci};
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_cienum ad3552r_ch_gain_scaling {
19362306a36Sopenharmony_ci	/* Gain scaling of 1 */
19462306a36Sopenharmony_ci	AD3552R_CH_GAIN_SCALING_1,
19562306a36Sopenharmony_ci	/* Gain scaling of 0.5 */
19662306a36Sopenharmony_ci	AD3552R_CH_GAIN_SCALING_0_5,
19762306a36Sopenharmony_ci	/* Gain scaling of 0.25 */
19862306a36Sopenharmony_ci	AD3552R_CH_GAIN_SCALING_0_25,
19962306a36Sopenharmony_ci	/* Gain scaling of 0.125 */
20062306a36Sopenharmony_ci	AD3552R_CH_GAIN_SCALING_0_125,
20162306a36Sopenharmony_ci};
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci/* Gain * AD3552R_GAIN_SCALE */
20462306a36Sopenharmony_cistatic const s32 gains_scaling_table[] = {
20562306a36Sopenharmony_ci	[AD3552R_CH_GAIN_SCALING_1]		= 1000,
20662306a36Sopenharmony_ci	[AD3552R_CH_GAIN_SCALING_0_5]		= 500,
20762306a36Sopenharmony_ci	[AD3552R_CH_GAIN_SCALING_0_25]		= 250,
20862306a36Sopenharmony_ci	[AD3552R_CH_GAIN_SCALING_0_125]		= 125
20962306a36Sopenharmony_ci};
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_cienum ad3552r_dev_attributes {
21262306a36Sopenharmony_ci	/* - Direct register values */
21362306a36Sopenharmony_ci	/* From 0-3 */
21462306a36Sopenharmony_ci	AD3552R_SDO_DRIVE_STRENGTH,
21562306a36Sopenharmony_ci	/*
21662306a36Sopenharmony_ci	 * 0 -> Internal Vref, vref_io pin floating (default)
21762306a36Sopenharmony_ci	 * 1 -> Internal Vref, vref_io driven by internal vref
21862306a36Sopenharmony_ci	 * 2 or 3 -> External Vref
21962306a36Sopenharmony_ci	 */
22062306a36Sopenharmony_ci	AD3552R_VREF_SELECT,
22162306a36Sopenharmony_ci	/* Read registers in ascending order if set. Else descending */
22262306a36Sopenharmony_ci	AD3552R_ADDR_ASCENSION,
22362306a36Sopenharmony_ci};
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_cienum ad3552r_ch_attributes {
22662306a36Sopenharmony_ci	/* DAC powerdown */
22762306a36Sopenharmony_ci	AD3552R_CH_DAC_POWERDOWN,
22862306a36Sopenharmony_ci	/* DAC amplifier powerdown */
22962306a36Sopenharmony_ci	AD3552R_CH_AMPLIFIER_POWERDOWN,
23062306a36Sopenharmony_ci	/* Select the output range. Select from enum ad3552r_ch_output_range */
23162306a36Sopenharmony_ci	AD3552R_CH_OUTPUT_RANGE_SEL,
23262306a36Sopenharmony_ci	/*
23362306a36Sopenharmony_ci	 * Over-rider the range selector in order to manually set the output
23462306a36Sopenharmony_ci	 * voltage range
23562306a36Sopenharmony_ci	 */
23662306a36Sopenharmony_ci	AD3552R_CH_RANGE_OVERRIDE,
23762306a36Sopenharmony_ci	/* Manually set the offset voltage */
23862306a36Sopenharmony_ci	AD3552R_CH_GAIN_OFFSET,
23962306a36Sopenharmony_ci	/* Sets the polarity of the offset. */
24062306a36Sopenharmony_ci	AD3552R_CH_GAIN_OFFSET_POLARITY,
24162306a36Sopenharmony_ci	/* PDAC gain scaling */
24262306a36Sopenharmony_ci	AD3552R_CH_GAIN_SCALING_P,
24362306a36Sopenharmony_ci	/* NDAC gain scaling */
24462306a36Sopenharmony_ci	AD3552R_CH_GAIN_SCALING_N,
24562306a36Sopenharmony_ci	/* Rfb value */
24662306a36Sopenharmony_ci	AD3552R_CH_RFB,
24762306a36Sopenharmony_ci	/* Channel select. When set allow Input -> DAC and Mask -> DAC */
24862306a36Sopenharmony_ci	AD3552R_CH_SELECT,
24962306a36Sopenharmony_ci};
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_cistruct ad3552r_ch_data {
25262306a36Sopenharmony_ci	s32	scale_int;
25362306a36Sopenharmony_ci	s32	scale_dec;
25462306a36Sopenharmony_ci	s32	offset_int;
25562306a36Sopenharmony_ci	s32	offset_dec;
25662306a36Sopenharmony_ci	s16	gain_offset;
25762306a36Sopenharmony_ci	u16	rfb;
25862306a36Sopenharmony_ci	u8	n;
25962306a36Sopenharmony_ci	u8	p;
26062306a36Sopenharmony_ci	u8	range;
26162306a36Sopenharmony_ci	bool	range_override;
26262306a36Sopenharmony_ci};
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_cistruct ad3552r_desc {
26562306a36Sopenharmony_ci	/* Used to look the spi bus for atomic operations where needed */
26662306a36Sopenharmony_ci	struct mutex		lock;
26762306a36Sopenharmony_ci	struct gpio_desc	*gpio_reset;
26862306a36Sopenharmony_ci	struct gpio_desc	*gpio_ldac;
26962306a36Sopenharmony_ci	struct spi_device	*spi;
27062306a36Sopenharmony_ci	struct ad3552r_ch_data	ch_data[AD3552R_NUM_CH];
27162306a36Sopenharmony_ci	struct iio_chan_spec	channels[AD3552R_NUM_CH + 1];
27262306a36Sopenharmony_ci	unsigned long		enabled_ch;
27362306a36Sopenharmony_ci	unsigned int		num_ch;
27462306a36Sopenharmony_ci	enum ad3542r_id		chip_id;
27562306a36Sopenharmony_ci};
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_cistatic const u16 addr_mask_map[][2] = {
27862306a36Sopenharmony_ci	[AD3552R_ADDR_ASCENSION] = {
27962306a36Sopenharmony_ci			AD3552R_REG_ADDR_INTERFACE_CONFIG_A,
28062306a36Sopenharmony_ci			AD3552R_MASK_ADDR_ASCENSION
28162306a36Sopenharmony_ci	},
28262306a36Sopenharmony_ci	[AD3552R_SDO_DRIVE_STRENGTH] = {
28362306a36Sopenharmony_ci			AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
28462306a36Sopenharmony_ci			AD3552R_MASK_SDO_DRIVE_STRENGTH
28562306a36Sopenharmony_ci	},
28662306a36Sopenharmony_ci	[AD3552R_VREF_SELECT] = {
28762306a36Sopenharmony_ci			AD3552R_REG_ADDR_SH_REFERENCE_CONFIG,
28862306a36Sopenharmony_ci			AD3552R_MASK_REFERENCE_VOLTAGE_SEL
28962306a36Sopenharmony_ci	},
29062306a36Sopenharmony_ci};
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci/* 0 -> reg addr, 1->ch0 mask, 2->ch1 mask */
29362306a36Sopenharmony_cistatic const u16 addr_mask_map_ch[][3] = {
29462306a36Sopenharmony_ci	[AD3552R_CH_DAC_POWERDOWN] = {
29562306a36Sopenharmony_ci			AD3552R_REG_ADDR_POWERDOWN_CONFIG,
29662306a36Sopenharmony_ci			AD3552R_MASK_CH_DAC_POWERDOWN(0),
29762306a36Sopenharmony_ci			AD3552R_MASK_CH_DAC_POWERDOWN(1)
29862306a36Sopenharmony_ci	},
29962306a36Sopenharmony_ci	[AD3552R_CH_AMPLIFIER_POWERDOWN] = {
30062306a36Sopenharmony_ci			AD3552R_REG_ADDR_POWERDOWN_CONFIG,
30162306a36Sopenharmony_ci			AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(0),
30262306a36Sopenharmony_ci			AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(1)
30362306a36Sopenharmony_ci	},
30462306a36Sopenharmony_ci	[AD3552R_CH_OUTPUT_RANGE_SEL] = {
30562306a36Sopenharmony_ci			AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE,
30662306a36Sopenharmony_ci			AD3552R_MASK_CH_OUTPUT_RANGE_SEL(0),
30762306a36Sopenharmony_ci			AD3552R_MASK_CH_OUTPUT_RANGE_SEL(1)
30862306a36Sopenharmony_ci	},
30962306a36Sopenharmony_ci	[AD3552R_CH_SELECT] = {
31062306a36Sopenharmony_ci			AD3552R_REG_ADDR_CH_SELECT_16B,
31162306a36Sopenharmony_ci			AD3552R_MASK_CH(0),
31262306a36Sopenharmony_ci			AD3552R_MASK_CH(1)
31362306a36Sopenharmony_ci	}
31462306a36Sopenharmony_ci};
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_cistatic u8 _ad3552r_reg_len(u8 addr)
31762306a36Sopenharmony_ci{
31862306a36Sopenharmony_ci	switch (addr) {
31962306a36Sopenharmony_ci	case AD3552R_REG_ADDR_HW_LDAC_16B:
32062306a36Sopenharmony_ci	case AD3552R_REG_ADDR_CH_SELECT_16B:
32162306a36Sopenharmony_ci	case AD3552R_REG_ADDR_SW_LDAC_16B:
32262306a36Sopenharmony_ci	case AD3552R_REG_ADDR_HW_LDAC_24B:
32362306a36Sopenharmony_ci	case AD3552R_REG_ADDR_CH_SELECT_24B:
32462306a36Sopenharmony_ci	case AD3552R_REG_ADDR_SW_LDAC_24B:
32562306a36Sopenharmony_ci		return 1;
32662306a36Sopenharmony_ci	default:
32762306a36Sopenharmony_ci		break;
32862306a36Sopenharmony_ci	}
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci	if (addr > AD3552R_REG_ADDR_HW_LDAC_24B)
33162306a36Sopenharmony_ci		return 3;
33262306a36Sopenharmony_ci	if (addr > AD3552R_REG_ADDR_HW_LDAC_16B)
33362306a36Sopenharmony_ci		return 2;
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	return 1;
33662306a36Sopenharmony_ci}
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci/* SPI transfer to device */
33962306a36Sopenharmony_cistatic int ad3552r_transfer(struct ad3552r_desc *dac, u8 addr, u32 len,
34062306a36Sopenharmony_ci			    u8 *data, bool is_read)
34162306a36Sopenharmony_ci{
34262306a36Sopenharmony_ci	/* Maximum transfer: Addr (1B) + 2 * (Data Reg (3B)) + SW LDAC(1B) */
34362306a36Sopenharmony_ci	u8 buf[8];
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci	buf[0] = addr & AD3552R_ADDR_MASK;
34662306a36Sopenharmony_ci	buf[0] |= is_read ? AD3552R_READ_BIT : 0;
34762306a36Sopenharmony_ci	if (is_read)
34862306a36Sopenharmony_ci		return spi_write_then_read(dac->spi, buf, 1, data, len);
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	memcpy(buf + 1, data, len);
35162306a36Sopenharmony_ci	return spi_write_then_read(dac->spi, buf, len + 1, NULL, 0);
35262306a36Sopenharmony_ci}
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_cistatic int ad3552r_write_reg(struct ad3552r_desc *dac, u8 addr, u16 val)
35562306a36Sopenharmony_ci{
35662306a36Sopenharmony_ci	u8 reg_len;
35762306a36Sopenharmony_ci	u8 buf[AD3552R_MAX_REG_SIZE] = { 0 };
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci	reg_len = _ad3552r_reg_len(addr);
36062306a36Sopenharmony_ci	if (reg_len == 2)
36162306a36Sopenharmony_ci		/* Only DAC register are 2 bytes wide */
36262306a36Sopenharmony_ci		val &= AD3552R_MASK_DAC_12B;
36362306a36Sopenharmony_ci	if (reg_len == 1)
36462306a36Sopenharmony_ci		buf[0] = val & 0xFF;
36562306a36Sopenharmony_ci	else
36662306a36Sopenharmony_ci		/* reg_len can be 2 or 3, but 3rd bytes needs to be set to 0 */
36762306a36Sopenharmony_ci		put_unaligned_be16(val, buf);
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci	return ad3552r_transfer(dac, addr, reg_len, buf, false);
37062306a36Sopenharmony_ci}
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_cistatic int ad3552r_read_reg(struct ad3552r_desc *dac, u8 addr, u16 *val)
37362306a36Sopenharmony_ci{
37462306a36Sopenharmony_ci	int err;
37562306a36Sopenharmony_ci	u8  reg_len, buf[AD3552R_MAX_REG_SIZE] = { 0 };
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	reg_len = _ad3552r_reg_len(addr);
37862306a36Sopenharmony_ci	err = ad3552r_transfer(dac, addr, reg_len, buf, true);
37962306a36Sopenharmony_ci	if (err)
38062306a36Sopenharmony_ci		return err;
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci	if (reg_len == 1)
38362306a36Sopenharmony_ci		*val = buf[0];
38462306a36Sopenharmony_ci	else
38562306a36Sopenharmony_ci		/* reg_len can be 2 or 3, but only first 2 bytes are relevant */
38662306a36Sopenharmony_ci		*val = get_unaligned_be16(buf);
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci	return 0;
38962306a36Sopenharmony_ci}
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_cistatic u16 ad3552r_field_prep(u16 val, u16 mask)
39262306a36Sopenharmony_ci{
39362306a36Sopenharmony_ci	return (val << __ffs(mask)) & mask;
39462306a36Sopenharmony_ci}
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci/* Update field of a register, shift val if needed */
39762306a36Sopenharmony_cistatic int ad3552r_update_reg_field(struct ad3552r_desc *dac, u8 addr, u16 mask,
39862306a36Sopenharmony_ci				    u16 val)
39962306a36Sopenharmony_ci{
40062306a36Sopenharmony_ci	int ret;
40162306a36Sopenharmony_ci	u16 reg;
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci	ret = ad3552r_read_reg(dac, addr, &reg);
40462306a36Sopenharmony_ci	if (ret < 0)
40562306a36Sopenharmony_ci		return ret;
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci	reg &= ~mask;
40862306a36Sopenharmony_ci	reg |= ad3552r_field_prep(val, mask);
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci	return ad3552r_write_reg(dac, addr, reg);
41162306a36Sopenharmony_ci}
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_cistatic int ad3552r_set_ch_value(struct ad3552r_desc *dac,
41462306a36Sopenharmony_ci				enum ad3552r_ch_attributes attr,
41562306a36Sopenharmony_ci				u8 ch,
41662306a36Sopenharmony_ci				u16 val)
41762306a36Sopenharmony_ci{
41862306a36Sopenharmony_ci	/* Update register related to attributes in chip */
41962306a36Sopenharmony_ci	return ad3552r_update_reg_field(dac, addr_mask_map_ch[attr][0],
42062306a36Sopenharmony_ci				       addr_mask_map_ch[attr][ch + 1], val);
42162306a36Sopenharmony_ci}
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci#define AD3552R_CH_DAC(_idx) ((struct iio_chan_spec) {		\
42462306a36Sopenharmony_ci	.type = IIO_VOLTAGE,					\
42562306a36Sopenharmony_ci	.output = true,						\
42662306a36Sopenharmony_ci	.indexed = true,					\
42762306a36Sopenharmony_ci	.channel = _idx,					\
42862306a36Sopenharmony_ci	.scan_index = _idx,					\
42962306a36Sopenharmony_ci	.scan_type = {						\
43062306a36Sopenharmony_ci		.sign = 'u',					\
43162306a36Sopenharmony_ci		.realbits = 16,					\
43262306a36Sopenharmony_ci		.storagebits = 16,				\
43362306a36Sopenharmony_ci		.endianness = IIO_BE,				\
43462306a36Sopenharmony_ci	},							\
43562306a36Sopenharmony_ci	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |		\
43662306a36Sopenharmony_ci				BIT(IIO_CHAN_INFO_SCALE) |	\
43762306a36Sopenharmony_ci				BIT(IIO_CHAN_INFO_ENABLE) |	\
43862306a36Sopenharmony_ci				BIT(IIO_CHAN_INFO_OFFSET),	\
43962306a36Sopenharmony_ci})
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_cistatic int ad3552r_read_raw(struct iio_dev *indio_dev,
44262306a36Sopenharmony_ci			    struct iio_chan_spec const *chan,
44362306a36Sopenharmony_ci			    int *val,
44462306a36Sopenharmony_ci			    int *val2,
44562306a36Sopenharmony_ci			    long mask)
44662306a36Sopenharmony_ci{
44762306a36Sopenharmony_ci	struct ad3552r_desc *dac = iio_priv(indio_dev);
44862306a36Sopenharmony_ci	u16 tmp_val;
44962306a36Sopenharmony_ci	int err;
45062306a36Sopenharmony_ci	u8 ch = chan->channel;
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci	switch (mask) {
45362306a36Sopenharmony_ci	case IIO_CHAN_INFO_RAW:
45462306a36Sopenharmony_ci		mutex_lock(&dac->lock);
45562306a36Sopenharmony_ci		err = ad3552r_read_reg(dac, AD3552R_REG_ADDR_CH_DAC_24B(ch),
45662306a36Sopenharmony_ci				       &tmp_val);
45762306a36Sopenharmony_ci		mutex_unlock(&dac->lock);
45862306a36Sopenharmony_ci		if (err < 0)
45962306a36Sopenharmony_ci			return err;
46062306a36Sopenharmony_ci		*val = tmp_val;
46162306a36Sopenharmony_ci		return IIO_VAL_INT;
46262306a36Sopenharmony_ci	case IIO_CHAN_INFO_ENABLE:
46362306a36Sopenharmony_ci		mutex_lock(&dac->lock);
46462306a36Sopenharmony_ci		err = ad3552r_read_reg(dac, AD3552R_REG_ADDR_POWERDOWN_CONFIG,
46562306a36Sopenharmony_ci				       &tmp_val);
46662306a36Sopenharmony_ci		mutex_unlock(&dac->lock);
46762306a36Sopenharmony_ci		if (err < 0)
46862306a36Sopenharmony_ci			return err;
46962306a36Sopenharmony_ci		*val = !((tmp_val & AD3552R_MASK_CH_DAC_POWERDOWN(ch)) >>
47062306a36Sopenharmony_ci			  __ffs(AD3552R_MASK_CH_DAC_POWERDOWN(ch)));
47162306a36Sopenharmony_ci		return IIO_VAL_INT;
47262306a36Sopenharmony_ci	case IIO_CHAN_INFO_SCALE:
47362306a36Sopenharmony_ci		*val = dac->ch_data[ch].scale_int;
47462306a36Sopenharmony_ci		*val2 = dac->ch_data[ch].scale_dec;
47562306a36Sopenharmony_ci		return IIO_VAL_INT_PLUS_MICRO;
47662306a36Sopenharmony_ci	case IIO_CHAN_INFO_OFFSET:
47762306a36Sopenharmony_ci		*val = dac->ch_data[ch].offset_int;
47862306a36Sopenharmony_ci		*val2 = dac->ch_data[ch].offset_dec;
47962306a36Sopenharmony_ci		return IIO_VAL_INT_PLUS_MICRO;
48062306a36Sopenharmony_ci	default:
48162306a36Sopenharmony_ci		return -EINVAL;
48262306a36Sopenharmony_ci	}
48362306a36Sopenharmony_ci}
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_cistatic int ad3552r_write_raw(struct iio_dev *indio_dev,
48662306a36Sopenharmony_ci			     struct iio_chan_spec const *chan,
48762306a36Sopenharmony_ci			     int val,
48862306a36Sopenharmony_ci			     int val2,
48962306a36Sopenharmony_ci			     long mask)
49062306a36Sopenharmony_ci{
49162306a36Sopenharmony_ci	struct ad3552r_desc *dac = iio_priv(indio_dev);
49262306a36Sopenharmony_ci	int err;
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci	mutex_lock(&dac->lock);
49562306a36Sopenharmony_ci	switch (mask) {
49662306a36Sopenharmony_ci	case IIO_CHAN_INFO_RAW:
49762306a36Sopenharmony_ci		err = ad3552r_write_reg(dac,
49862306a36Sopenharmony_ci					AD3552R_REG_ADDR_CH_DAC_24B(chan->channel),
49962306a36Sopenharmony_ci					val);
50062306a36Sopenharmony_ci		break;
50162306a36Sopenharmony_ci	case IIO_CHAN_INFO_ENABLE:
50262306a36Sopenharmony_ci		err = ad3552r_set_ch_value(dac, AD3552R_CH_DAC_POWERDOWN,
50362306a36Sopenharmony_ci					   chan->channel, !val);
50462306a36Sopenharmony_ci		break;
50562306a36Sopenharmony_ci	default:
50662306a36Sopenharmony_ci		err = -EINVAL;
50762306a36Sopenharmony_ci		break;
50862306a36Sopenharmony_ci	}
50962306a36Sopenharmony_ci	mutex_unlock(&dac->lock);
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ci	return err;
51262306a36Sopenharmony_ci}
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_cistatic const struct iio_info ad3552r_iio_info = {
51562306a36Sopenharmony_ci	.read_raw = ad3552r_read_raw,
51662306a36Sopenharmony_ci	.write_raw = ad3552r_write_raw
51762306a36Sopenharmony_ci};
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_cistatic int32_t ad3552r_trigger_hw_ldac(struct gpio_desc *ldac)
52062306a36Sopenharmony_ci{
52162306a36Sopenharmony_ci	gpiod_set_value_cansleep(ldac, 0);
52262306a36Sopenharmony_ci	usleep_range(AD3552R_LDAC_PULSE_US, AD3552R_LDAC_PULSE_US + 10);
52362306a36Sopenharmony_ci	gpiod_set_value_cansleep(ldac, 1);
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_ci	return 0;
52662306a36Sopenharmony_ci}
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_cistatic int ad3552r_write_all_channels(struct ad3552r_desc *dac, u8 *data)
52962306a36Sopenharmony_ci{
53062306a36Sopenharmony_ci	int err, len;
53162306a36Sopenharmony_ci	u8 addr, buff[AD3552R_NUM_CH * AD3552R_MAX_REG_SIZE + 1];
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci	addr = AD3552R_REG_ADDR_CH_INPUT_24B(1);
53462306a36Sopenharmony_ci	/* CH1 */
53562306a36Sopenharmony_ci	memcpy(buff, data + 2, 2);
53662306a36Sopenharmony_ci	buff[2] = 0;
53762306a36Sopenharmony_ci	/* CH0 */
53862306a36Sopenharmony_ci	memcpy(buff + 3, data, 2);
53962306a36Sopenharmony_ci	buff[5] = 0;
54062306a36Sopenharmony_ci	len = 6;
54162306a36Sopenharmony_ci	if (!dac->gpio_ldac) {
54262306a36Sopenharmony_ci		/* Software LDAC */
54362306a36Sopenharmony_ci		buff[6] = AD3552R_MASK_ALL_CH;
54462306a36Sopenharmony_ci		++len;
54562306a36Sopenharmony_ci	}
54662306a36Sopenharmony_ci	err = ad3552r_transfer(dac, addr, len, buff, false);
54762306a36Sopenharmony_ci	if (err)
54862306a36Sopenharmony_ci		return err;
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_ci	if (dac->gpio_ldac)
55162306a36Sopenharmony_ci		return ad3552r_trigger_hw_ldac(dac->gpio_ldac);
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci	return 0;
55462306a36Sopenharmony_ci}
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_cistatic int ad3552r_write_codes(struct ad3552r_desc *dac, u32 mask, u8 *data)
55762306a36Sopenharmony_ci{
55862306a36Sopenharmony_ci	int err;
55962306a36Sopenharmony_ci	u8 addr, buff[AD3552R_MAX_REG_SIZE];
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_ci	if (mask == AD3552R_MASK_ALL_CH) {
56262306a36Sopenharmony_ci		if (memcmp(data, data + 2, 2) != 0)
56362306a36Sopenharmony_ci			return ad3552r_write_all_channels(dac, data);
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci		addr = AD3552R_REG_ADDR_INPUT_PAGE_MASK_24B;
56662306a36Sopenharmony_ci	} else {
56762306a36Sopenharmony_ci		addr = AD3552R_REG_ADDR_CH_INPUT_24B(__ffs(mask));
56862306a36Sopenharmony_ci	}
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_ci	memcpy(buff, data, 2);
57162306a36Sopenharmony_ci	buff[2] = 0;
57262306a36Sopenharmony_ci	err = ad3552r_transfer(dac, addr, 3, data, false);
57362306a36Sopenharmony_ci	if (err)
57462306a36Sopenharmony_ci		return err;
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci	if (dac->gpio_ldac)
57762306a36Sopenharmony_ci		return ad3552r_trigger_hw_ldac(dac->gpio_ldac);
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_ci	return ad3552r_write_reg(dac, AD3552R_REG_ADDR_SW_LDAC_24B, mask);
58062306a36Sopenharmony_ci}
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_cistatic irqreturn_t ad3552r_trigger_handler(int irq, void *p)
58362306a36Sopenharmony_ci{
58462306a36Sopenharmony_ci	struct iio_poll_func *pf = p;
58562306a36Sopenharmony_ci	struct iio_dev *indio_dev = pf->indio_dev;
58662306a36Sopenharmony_ci	struct iio_buffer *buf = indio_dev->buffer;
58762306a36Sopenharmony_ci	struct ad3552r_desc *dac = iio_priv(indio_dev);
58862306a36Sopenharmony_ci	/* Maximum size of a scan */
58962306a36Sopenharmony_ci	u8 buff[AD3552R_NUM_CH * AD3552R_MAX_REG_SIZE];
59062306a36Sopenharmony_ci	int err;
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ci	memset(buff, 0, sizeof(buff));
59362306a36Sopenharmony_ci	err = iio_pop_from_buffer(buf, buff);
59462306a36Sopenharmony_ci	if (err)
59562306a36Sopenharmony_ci		goto end;
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci	mutex_lock(&dac->lock);
59862306a36Sopenharmony_ci	ad3552r_write_codes(dac, *indio_dev->active_scan_mask, buff);
59962306a36Sopenharmony_ci	mutex_unlock(&dac->lock);
60062306a36Sopenharmony_ciend:
60162306a36Sopenharmony_ci	iio_trigger_notify_done(indio_dev->trig);
60262306a36Sopenharmony_ci
60362306a36Sopenharmony_ci	return IRQ_HANDLED;
60462306a36Sopenharmony_ci}
60562306a36Sopenharmony_ci
60662306a36Sopenharmony_cistatic int ad3552r_check_scratch_pad(struct ad3552r_desc *dac)
60762306a36Sopenharmony_ci{
60862306a36Sopenharmony_ci	const u16 val1 = AD3552R_SCRATCH_PAD_TEST_VAL1;
60962306a36Sopenharmony_ci	const u16 val2 = AD3552R_SCRATCH_PAD_TEST_VAL2;
61062306a36Sopenharmony_ci	u16 val;
61162306a36Sopenharmony_ci	int err;
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_ci	err = ad3552r_write_reg(dac, AD3552R_REG_ADDR_SCRATCH_PAD, val1);
61462306a36Sopenharmony_ci	if (err < 0)
61562306a36Sopenharmony_ci		return err;
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci	err = ad3552r_read_reg(dac, AD3552R_REG_ADDR_SCRATCH_PAD, &val);
61862306a36Sopenharmony_ci	if (err < 0)
61962306a36Sopenharmony_ci		return err;
62062306a36Sopenharmony_ci
62162306a36Sopenharmony_ci	if (val1 != val)
62262306a36Sopenharmony_ci		return -ENODEV;
62362306a36Sopenharmony_ci
62462306a36Sopenharmony_ci	err = ad3552r_write_reg(dac, AD3552R_REG_ADDR_SCRATCH_PAD, val2);
62562306a36Sopenharmony_ci	if (err < 0)
62662306a36Sopenharmony_ci		return err;
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci	err = ad3552r_read_reg(dac, AD3552R_REG_ADDR_SCRATCH_PAD, &val);
62962306a36Sopenharmony_ci	if (err < 0)
63062306a36Sopenharmony_ci		return err;
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_ci	if (val2 != val)
63362306a36Sopenharmony_ci		return -ENODEV;
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_ci	return 0;
63662306a36Sopenharmony_ci}
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_cistruct reg_addr_pool {
63962306a36Sopenharmony_ci	struct ad3552r_desc *dac;
64062306a36Sopenharmony_ci	u8		    addr;
64162306a36Sopenharmony_ci};
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_cistatic int ad3552r_read_reg_wrapper(struct reg_addr_pool *addr)
64462306a36Sopenharmony_ci{
64562306a36Sopenharmony_ci	int err;
64662306a36Sopenharmony_ci	u16 val;
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci	err = ad3552r_read_reg(addr->dac, addr->addr, &val);
64962306a36Sopenharmony_ci	if (err)
65062306a36Sopenharmony_ci		return err;
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci	return val;
65362306a36Sopenharmony_ci}
65462306a36Sopenharmony_ci
65562306a36Sopenharmony_cistatic int ad3552r_reset(struct ad3552r_desc *dac)
65662306a36Sopenharmony_ci{
65762306a36Sopenharmony_ci	struct reg_addr_pool addr;
65862306a36Sopenharmony_ci	int ret;
65962306a36Sopenharmony_ci	int val;
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci	dac->gpio_reset = devm_gpiod_get_optional(&dac->spi->dev, "reset",
66262306a36Sopenharmony_ci						  GPIOD_OUT_LOW);
66362306a36Sopenharmony_ci	if (IS_ERR(dac->gpio_reset))
66462306a36Sopenharmony_ci		return dev_err_probe(&dac->spi->dev, PTR_ERR(dac->gpio_reset),
66562306a36Sopenharmony_ci				     "Error while getting gpio reset");
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_ci	if (dac->gpio_reset) {
66862306a36Sopenharmony_ci		/* Perform hardware reset */
66962306a36Sopenharmony_ci		usleep_range(10, 20);
67062306a36Sopenharmony_ci		gpiod_set_value_cansleep(dac->gpio_reset, 1);
67162306a36Sopenharmony_ci	} else {
67262306a36Sopenharmony_ci		/* Perform software reset if no GPIO provided */
67362306a36Sopenharmony_ci		ret = ad3552r_update_reg_field(dac,
67462306a36Sopenharmony_ci					       AD3552R_REG_ADDR_INTERFACE_CONFIG_A,
67562306a36Sopenharmony_ci					       AD3552R_MASK_SOFTWARE_RESET,
67662306a36Sopenharmony_ci					       AD3552R_MASK_SOFTWARE_RESET);
67762306a36Sopenharmony_ci		if (ret < 0)
67862306a36Sopenharmony_ci			return ret;
67962306a36Sopenharmony_ci
68062306a36Sopenharmony_ci	}
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_ci	addr.dac = dac;
68362306a36Sopenharmony_ci	addr.addr = AD3552R_REG_ADDR_INTERFACE_CONFIG_B;
68462306a36Sopenharmony_ci	ret = readx_poll_timeout(ad3552r_read_reg_wrapper, &addr, val,
68562306a36Sopenharmony_ci				 val == AD3552R_DEFAULT_CONFIG_B_VALUE ||
68662306a36Sopenharmony_ci				 val < 0,
68762306a36Sopenharmony_ci				 5000, 50000);
68862306a36Sopenharmony_ci	if (val < 0)
68962306a36Sopenharmony_ci		ret = val;
69062306a36Sopenharmony_ci	if (ret) {
69162306a36Sopenharmony_ci		dev_err(&dac->spi->dev, "Error while resetting");
69262306a36Sopenharmony_ci		return ret;
69362306a36Sopenharmony_ci	}
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_ci	ret = readx_poll_timeout(ad3552r_read_reg_wrapper, &addr, val,
69662306a36Sopenharmony_ci				 !(val & AD3552R_MASK_INTERFACE_NOT_READY) ||
69762306a36Sopenharmony_ci				 val < 0,
69862306a36Sopenharmony_ci				 5000, 50000);
69962306a36Sopenharmony_ci	if (val < 0)
70062306a36Sopenharmony_ci		ret = val;
70162306a36Sopenharmony_ci	if (ret) {
70262306a36Sopenharmony_ci		dev_err(&dac->spi->dev, "Error while resetting");
70362306a36Sopenharmony_ci		return ret;
70462306a36Sopenharmony_ci	}
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_ci	return ad3552r_update_reg_field(dac,
70762306a36Sopenharmony_ci					addr_mask_map[AD3552R_ADDR_ASCENSION][0],
70862306a36Sopenharmony_ci					addr_mask_map[AD3552R_ADDR_ASCENSION][1],
70962306a36Sopenharmony_ci					val);
71062306a36Sopenharmony_ci}
71162306a36Sopenharmony_ci
71262306a36Sopenharmony_cistatic void ad3552r_get_custom_range(struct ad3552r_desc *dac, s32 i, s32 *v_min,
71362306a36Sopenharmony_ci				     s32 *v_max)
71462306a36Sopenharmony_ci{
71562306a36Sopenharmony_ci	s64 vref, tmp, common, offset, gn, gp;
71662306a36Sopenharmony_ci	/*
71762306a36Sopenharmony_ci	 * From datasheet formula (In Volts):
71862306a36Sopenharmony_ci	 *	Vmin = 2.5 + [(GainN + Offset / 1024) * 2.5 * Rfb * 1.03]
71962306a36Sopenharmony_ci	 *	Vmax = 2.5 - [(GainP + Offset / 1024) * 2.5 * Rfb * 1.03]
72062306a36Sopenharmony_ci	 * Calculus are converted to milivolts
72162306a36Sopenharmony_ci	 */
72262306a36Sopenharmony_ci	vref = 2500;
72362306a36Sopenharmony_ci	/* 2.5 * 1.03 * 1000 (To mV) */
72462306a36Sopenharmony_ci	common = 2575 * dac->ch_data[i].rfb;
72562306a36Sopenharmony_ci	offset = dac->ch_data[i].gain_offset;
72662306a36Sopenharmony_ci
72762306a36Sopenharmony_ci	gn = gains_scaling_table[dac->ch_data[i].n];
72862306a36Sopenharmony_ci	tmp = (1024 * gn + AD3552R_GAIN_SCALE * offset) * common;
72962306a36Sopenharmony_ci	tmp = div_s64(tmp, 1024  * AD3552R_GAIN_SCALE);
73062306a36Sopenharmony_ci	*v_max = vref + tmp;
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci	gp = gains_scaling_table[dac->ch_data[i].p];
73362306a36Sopenharmony_ci	tmp = (1024 * gp - AD3552R_GAIN_SCALE * offset) * common;
73462306a36Sopenharmony_ci	tmp = div_s64(tmp, 1024 * AD3552R_GAIN_SCALE);
73562306a36Sopenharmony_ci	*v_min = vref - tmp;
73662306a36Sopenharmony_ci}
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_cistatic void ad3552r_calc_gain_and_offset(struct ad3552r_desc *dac, s32 ch)
73962306a36Sopenharmony_ci{
74062306a36Sopenharmony_ci	s32 idx, v_max, v_min, span, rem;
74162306a36Sopenharmony_ci	s64 tmp;
74262306a36Sopenharmony_ci
74362306a36Sopenharmony_ci	if (dac->ch_data[ch].range_override) {
74462306a36Sopenharmony_ci		ad3552r_get_custom_range(dac, ch, &v_min, &v_max);
74562306a36Sopenharmony_ci	} else {
74662306a36Sopenharmony_ci		/* Normal range */
74762306a36Sopenharmony_ci		idx = dac->ch_data[ch].range;
74862306a36Sopenharmony_ci		if (dac->chip_id == AD3542R_ID) {
74962306a36Sopenharmony_ci			v_min = ad3542r_ch_ranges[idx][0];
75062306a36Sopenharmony_ci			v_max = ad3542r_ch_ranges[idx][1];
75162306a36Sopenharmony_ci		} else {
75262306a36Sopenharmony_ci			v_min = ad3552r_ch_ranges[idx][0];
75362306a36Sopenharmony_ci			v_max = ad3552r_ch_ranges[idx][1];
75462306a36Sopenharmony_ci		}
75562306a36Sopenharmony_ci	}
75662306a36Sopenharmony_ci
75762306a36Sopenharmony_ci	/*
75862306a36Sopenharmony_ci	 * From datasheet formula:
75962306a36Sopenharmony_ci	 *	Vout = Span * (D / 65536) + Vmin
76062306a36Sopenharmony_ci	 * Converted to scale and offset:
76162306a36Sopenharmony_ci	 *	Scale = Span / 65536
76262306a36Sopenharmony_ci	 *	Offset = 65536 * Vmin / Span
76362306a36Sopenharmony_ci	 *
76462306a36Sopenharmony_ci	 * Reminders are in micros in order to be printed as
76562306a36Sopenharmony_ci	 * IIO_VAL_INT_PLUS_MICRO
76662306a36Sopenharmony_ci	 */
76762306a36Sopenharmony_ci	span = v_max - v_min;
76862306a36Sopenharmony_ci	dac->ch_data[ch].scale_int = div_s64_rem(span, 65536, &rem);
76962306a36Sopenharmony_ci	/* Do operations in microvolts */
77062306a36Sopenharmony_ci	dac->ch_data[ch].scale_dec = DIV_ROUND_CLOSEST((s64)rem * 1000000,
77162306a36Sopenharmony_ci							65536);
77262306a36Sopenharmony_ci
77362306a36Sopenharmony_ci	dac->ch_data[ch].offset_int = div_s64_rem(v_min * 65536, span, &rem);
77462306a36Sopenharmony_ci	tmp = (s64)rem * 1000000;
77562306a36Sopenharmony_ci	dac->ch_data[ch].offset_dec = div_s64(tmp, span);
77662306a36Sopenharmony_ci}
77762306a36Sopenharmony_ci
77862306a36Sopenharmony_cistatic int ad3552r_find_range(u16 id, s32 *vals)
77962306a36Sopenharmony_ci{
78062306a36Sopenharmony_ci	int i, len;
78162306a36Sopenharmony_ci	const s32 (*ranges)[2];
78262306a36Sopenharmony_ci
78362306a36Sopenharmony_ci	if (id == AD3542R_ID) {
78462306a36Sopenharmony_ci		len = ARRAY_SIZE(ad3542r_ch_ranges);
78562306a36Sopenharmony_ci		ranges = ad3542r_ch_ranges;
78662306a36Sopenharmony_ci	} else {
78762306a36Sopenharmony_ci		len = ARRAY_SIZE(ad3552r_ch_ranges);
78862306a36Sopenharmony_ci		ranges = ad3552r_ch_ranges;
78962306a36Sopenharmony_ci	}
79062306a36Sopenharmony_ci
79162306a36Sopenharmony_ci	for (i = 0; i < len; i++)
79262306a36Sopenharmony_ci		if (vals[0] == ranges[i][0] * 1000 &&
79362306a36Sopenharmony_ci		    vals[1] == ranges[i][1] * 1000)
79462306a36Sopenharmony_ci			return i;
79562306a36Sopenharmony_ci
79662306a36Sopenharmony_ci	return -EINVAL;
79762306a36Sopenharmony_ci}
79862306a36Sopenharmony_ci
79962306a36Sopenharmony_cistatic int ad3552r_configure_custom_gain(struct ad3552r_desc *dac,
80062306a36Sopenharmony_ci					 struct fwnode_handle *child,
80162306a36Sopenharmony_ci					 u32 ch)
80262306a36Sopenharmony_ci{
80362306a36Sopenharmony_ci	struct device *dev = &dac->spi->dev;
80462306a36Sopenharmony_ci	struct fwnode_handle *gain_child;
80562306a36Sopenharmony_ci	u32 val;
80662306a36Sopenharmony_ci	int err;
80762306a36Sopenharmony_ci	u8 addr;
80862306a36Sopenharmony_ci	u16 reg = 0, offset;
80962306a36Sopenharmony_ci
81062306a36Sopenharmony_ci	gain_child = fwnode_get_named_child_node(child,
81162306a36Sopenharmony_ci						 "custom-output-range-config");
81262306a36Sopenharmony_ci	if (!gain_child) {
81362306a36Sopenharmony_ci		dev_err(dev,
81462306a36Sopenharmony_ci			"mandatory custom-output-range-config property missing\n");
81562306a36Sopenharmony_ci		return -EINVAL;
81662306a36Sopenharmony_ci	}
81762306a36Sopenharmony_ci
81862306a36Sopenharmony_ci	dac->ch_data[ch].range_override = 1;
81962306a36Sopenharmony_ci	reg |= ad3552r_field_prep(1, AD3552R_MASK_CH_RANGE_OVERRIDE);
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_ci	err = fwnode_property_read_u32(gain_child, "adi,gain-scaling-p", &val);
82262306a36Sopenharmony_ci	if (err) {
82362306a36Sopenharmony_ci		dev_err(dev, "mandatory adi,gain-scaling-p property missing\n");
82462306a36Sopenharmony_ci		goto put_child;
82562306a36Sopenharmony_ci	}
82662306a36Sopenharmony_ci	reg |= ad3552r_field_prep(val, AD3552R_MASK_CH_GAIN_SCALING_P);
82762306a36Sopenharmony_ci	dac->ch_data[ch].p = val;
82862306a36Sopenharmony_ci
82962306a36Sopenharmony_ci	err = fwnode_property_read_u32(gain_child, "adi,gain-scaling-n", &val);
83062306a36Sopenharmony_ci	if (err) {
83162306a36Sopenharmony_ci		dev_err(dev, "mandatory adi,gain-scaling-n property missing\n");
83262306a36Sopenharmony_ci		goto put_child;
83362306a36Sopenharmony_ci	}
83462306a36Sopenharmony_ci	reg |= ad3552r_field_prep(val, AD3552R_MASK_CH_GAIN_SCALING_N);
83562306a36Sopenharmony_ci	dac->ch_data[ch].n = val;
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_ci	err = fwnode_property_read_u32(gain_child, "adi,rfb-ohms", &val);
83862306a36Sopenharmony_ci	if (err) {
83962306a36Sopenharmony_ci		dev_err(dev, "mandatory adi,rfb-ohms property missing\n");
84062306a36Sopenharmony_ci		goto put_child;
84162306a36Sopenharmony_ci	}
84262306a36Sopenharmony_ci	dac->ch_data[ch].rfb = val;
84362306a36Sopenharmony_ci
84462306a36Sopenharmony_ci	err = fwnode_property_read_u32(gain_child, "adi,gain-offset", &val);
84562306a36Sopenharmony_ci	if (err) {
84662306a36Sopenharmony_ci		dev_err(dev, "mandatory adi,gain-offset property missing\n");
84762306a36Sopenharmony_ci		goto put_child;
84862306a36Sopenharmony_ci	}
84962306a36Sopenharmony_ci	dac->ch_data[ch].gain_offset = val;
85062306a36Sopenharmony_ci
85162306a36Sopenharmony_ci	offset = abs((s32)val);
85262306a36Sopenharmony_ci	reg |= ad3552r_field_prep((offset >> 8), AD3552R_MASK_CH_OFFSET_BIT_8);
85362306a36Sopenharmony_ci
85462306a36Sopenharmony_ci	reg |= ad3552r_field_prep((s32)val < 0, AD3552R_MASK_CH_OFFSET_POLARITY);
85562306a36Sopenharmony_ci	addr = AD3552R_REG_ADDR_CH_GAIN(ch);
85662306a36Sopenharmony_ci	err = ad3552r_write_reg(dac, addr,
85762306a36Sopenharmony_ci				offset & AD3552R_MASK_CH_OFFSET_BITS_0_7);
85862306a36Sopenharmony_ci	if (err) {
85962306a36Sopenharmony_ci		dev_err(dev, "Error writing register\n");
86062306a36Sopenharmony_ci		goto put_child;
86162306a36Sopenharmony_ci	}
86262306a36Sopenharmony_ci
86362306a36Sopenharmony_ci	err = ad3552r_write_reg(dac, addr, reg);
86462306a36Sopenharmony_ci	if (err) {
86562306a36Sopenharmony_ci		dev_err(dev, "Error writing register\n");
86662306a36Sopenharmony_ci		goto put_child;
86762306a36Sopenharmony_ci	}
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_ciput_child:
87062306a36Sopenharmony_ci	fwnode_handle_put(gain_child);
87162306a36Sopenharmony_ci
87262306a36Sopenharmony_ci	return err;
87362306a36Sopenharmony_ci}
87462306a36Sopenharmony_ci
87562306a36Sopenharmony_cistatic void ad3552r_reg_disable(void *reg)
87662306a36Sopenharmony_ci{
87762306a36Sopenharmony_ci	regulator_disable(reg);
87862306a36Sopenharmony_ci}
87962306a36Sopenharmony_ci
88062306a36Sopenharmony_cistatic int ad3552r_configure_device(struct ad3552r_desc *dac)
88162306a36Sopenharmony_ci{
88262306a36Sopenharmony_ci	struct device *dev = &dac->spi->dev;
88362306a36Sopenharmony_ci	struct fwnode_handle *child;
88462306a36Sopenharmony_ci	struct regulator *vref;
88562306a36Sopenharmony_ci	int err, cnt = 0, voltage, delta = 100000;
88662306a36Sopenharmony_ci	u32 vals[2], val, ch;
88762306a36Sopenharmony_ci
88862306a36Sopenharmony_ci	dac->gpio_ldac = devm_gpiod_get_optional(dev, "ldac", GPIOD_OUT_HIGH);
88962306a36Sopenharmony_ci	if (IS_ERR(dac->gpio_ldac))
89062306a36Sopenharmony_ci		return dev_err_probe(dev, PTR_ERR(dac->gpio_ldac),
89162306a36Sopenharmony_ci				     "Error getting gpio ldac");
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_ci	vref = devm_regulator_get_optional(dev, "vref");
89462306a36Sopenharmony_ci	if (IS_ERR(vref)) {
89562306a36Sopenharmony_ci		if (PTR_ERR(vref) != -ENODEV)
89662306a36Sopenharmony_ci			return dev_err_probe(dev, PTR_ERR(vref),
89762306a36Sopenharmony_ci					     "Error getting vref");
89862306a36Sopenharmony_ci
89962306a36Sopenharmony_ci		if (device_property_read_bool(dev, "adi,vref-out-en"))
90062306a36Sopenharmony_ci			val = AD3552R_INTERNAL_VREF_PIN_2P5V;
90162306a36Sopenharmony_ci		else
90262306a36Sopenharmony_ci			val = AD3552R_INTERNAL_VREF_PIN_FLOATING;
90362306a36Sopenharmony_ci	} else {
90462306a36Sopenharmony_ci		err = regulator_enable(vref);
90562306a36Sopenharmony_ci		if (err) {
90662306a36Sopenharmony_ci			dev_err(dev, "Failed to enable external vref supply\n");
90762306a36Sopenharmony_ci			return err;
90862306a36Sopenharmony_ci		}
90962306a36Sopenharmony_ci
91062306a36Sopenharmony_ci		err = devm_add_action_or_reset(dev, ad3552r_reg_disable, vref);
91162306a36Sopenharmony_ci		if (err) {
91262306a36Sopenharmony_ci			regulator_disable(vref);
91362306a36Sopenharmony_ci			return err;
91462306a36Sopenharmony_ci		}
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_ci		voltage = regulator_get_voltage(vref);
91762306a36Sopenharmony_ci		if (voltage > 2500000 + delta || voltage < 2500000 - delta) {
91862306a36Sopenharmony_ci			dev_warn(dev, "vref-supply must be 2.5V");
91962306a36Sopenharmony_ci			return -EINVAL;
92062306a36Sopenharmony_ci		}
92162306a36Sopenharmony_ci		val = AD3552R_EXTERNAL_VREF_PIN_INPUT;
92262306a36Sopenharmony_ci	}
92362306a36Sopenharmony_ci
92462306a36Sopenharmony_ci	err = ad3552r_update_reg_field(dac,
92562306a36Sopenharmony_ci				       addr_mask_map[AD3552R_VREF_SELECT][0],
92662306a36Sopenharmony_ci				       addr_mask_map[AD3552R_VREF_SELECT][1],
92762306a36Sopenharmony_ci				       val);
92862306a36Sopenharmony_ci	if (err)
92962306a36Sopenharmony_ci		return err;
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_ci	err = device_property_read_u32(dev, "adi,sdo-drive-strength", &val);
93262306a36Sopenharmony_ci	if (!err) {
93362306a36Sopenharmony_ci		if (val > 3) {
93462306a36Sopenharmony_ci			dev_err(dev, "adi,sdo-drive-strength must be less than 4\n");
93562306a36Sopenharmony_ci			return -EINVAL;
93662306a36Sopenharmony_ci		}
93762306a36Sopenharmony_ci
93862306a36Sopenharmony_ci		err = ad3552r_update_reg_field(dac,
93962306a36Sopenharmony_ci					       addr_mask_map[AD3552R_SDO_DRIVE_STRENGTH][0],
94062306a36Sopenharmony_ci					       addr_mask_map[AD3552R_SDO_DRIVE_STRENGTH][1],
94162306a36Sopenharmony_ci					       val);
94262306a36Sopenharmony_ci		if (err)
94362306a36Sopenharmony_ci			return err;
94462306a36Sopenharmony_ci	}
94562306a36Sopenharmony_ci
94662306a36Sopenharmony_ci	dac->num_ch = device_get_child_node_count(dev);
94762306a36Sopenharmony_ci	if (!dac->num_ch) {
94862306a36Sopenharmony_ci		dev_err(dev, "No channels defined\n");
94962306a36Sopenharmony_ci		return -ENODEV;
95062306a36Sopenharmony_ci	}
95162306a36Sopenharmony_ci
95262306a36Sopenharmony_ci	device_for_each_child_node(dev, child) {
95362306a36Sopenharmony_ci		err = fwnode_property_read_u32(child, "reg", &ch);
95462306a36Sopenharmony_ci		if (err) {
95562306a36Sopenharmony_ci			dev_err(dev, "mandatory reg property missing\n");
95662306a36Sopenharmony_ci			goto put_child;
95762306a36Sopenharmony_ci		}
95862306a36Sopenharmony_ci		if (ch >= AD3552R_NUM_CH) {
95962306a36Sopenharmony_ci			dev_err(dev, "reg must be less than %d\n",
96062306a36Sopenharmony_ci				AD3552R_NUM_CH);
96162306a36Sopenharmony_ci			err = -EINVAL;
96262306a36Sopenharmony_ci			goto put_child;
96362306a36Sopenharmony_ci		}
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci		if (fwnode_property_present(child, "adi,output-range-microvolt")) {
96662306a36Sopenharmony_ci			err = fwnode_property_read_u32_array(child,
96762306a36Sopenharmony_ci							     "adi,output-range-microvolt",
96862306a36Sopenharmony_ci							     vals,
96962306a36Sopenharmony_ci							     2);
97062306a36Sopenharmony_ci			if (err) {
97162306a36Sopenharmony_ci				dev_err(dev,
97262306a36Sopenharmony_ci					"adi,output-range-microvolt property could not be parsed\n");
97362306a36Sopenharmony_ci				goto put_child;
97462306a36Sopenharmony_ci			}
97562306a36Sopenharmony_ci
97662306a36Sopenharmony_ci			err = ad3552r_find_range(dac->chip_id, vals);
97762306a36Sopenharmony_ci			if (err < 0) {
97862306a36Sopenharmony_ci				dev_err(dev,
97962306a36Sopenharmony_ci					"Invalid adi,output-range-microvolt value\n");
98062306a36Sopenharmony_ci				goto put_child;
98162306a36Sopenharmony_ci			}
98262306a36Sopenharmony_ci			val = err;
98362306a36Sopenharmony_ci			err = ad3552r_set_ch_value(dac,
98462306a36Sopenharmony_ci						   AD3552R_CH_OUTPUT_RANGE_SEL,
98562306a36Sopenharmony_ci						   ch, val);
98662306a36Sopenharmony_ci			if (err)
98762306a36Sopenharmony_ci				goto put_child;
98862306a36Sopenharmony_ci
98962306a36Sopenharmony_ci			dac->ch_data[ch].range = val;
99062306a36Sopenharmony_ci		} else if (dac->chip_id == AD3542R_ID) {
99162306a36Sopenharmony_ci			dev_err(dev,
99262306a36Sopenharmony_ci				"adi,output-range-microvolt is required for ad3542r\n");
99362306a36Sopenharmony_ci			err = -EINVAL;
99462306a36Sopenharmony_ci			goto put_child;
99562306a36Sopenharmony_ci		} else {
99662306a36Sopenharmony_ci			err = ad3552r_configure_custom_gain(dac, child, ch);
99762306a36Sopenharmony_ci			if (err)
99862306a36Sopenharmony_ci				goto put_child;
99962306a36Sopenharmony_ci		}
100062306a36Sopenharmony_ci
100162306a36Sopenharmony_ci		ad3552r_calc_gain_and_offset(dac, ch);
100262306a36Sopenharmony_ci		dac->enabled_ch |= BIT(ch);
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_ci		err = ad3552r_set_ch_value(dac, AD3552R_CH_SELECT, ch, 1);
100562306a36Sopenharmony_ci		if (err < 0)
100662306a36Sopenharmony_ci			goto put_child;
100762306a36Sopenharmony_ci
100862306a36Sopenharmony_ci		dac->channels[cnt] = AD3552R_CH_DAC(ch);
100962306a36Sopenharmony_ci		++cnt;
101062306a36Sopenharmony_ci
101162306a36Sopenharmony_ci	}
101262306a36Sopenharmony_ci
101362306a36Sopenharmony_ci	/* Disable unused channels */
101462306a36Sopenharmony_ci	for_each_clear_bit(ch, &dac->enabled_ch, AD3552R_NUM_CH) {
101562306a36Sopenharmony_ci		err = ad3552r_set_ch_value(dac, AD3552R_CH_AMPLIFIER_POWERDOWN,
101662306a36Sopenharmony_ci					   ch, 1);
101762306a36Sopenharmony_ci		if (err)
101862306a36Sopenharmony_ci			return err;
101962306a36Sopenharmony_ci	}
102062306a36Sopenharmony_ci
102162306a36Sopenharmony_ci	dac->num_ch = cnt;
102262306a36Sopenharmony_ci
102362306a36Sopenharmony_ci	return 0;
102462306a36Sopenharmony_ciput_child:
102562306a36Sopenharmony_ci	fwnode_handle_put(child);
102662306a36Sopenharmony_ci
102762306a36Sopenharmony_ci	return err;
102862306a36Sopenharmony_ci}
102962306a36Sopenharmony_ci
103062306a36Sopenharmony_cistatic int ad3552r_init(struct ad3552r_desc *dac)
103162306a36Sopenharmony_ci{
103262306a36Sopenharmony_ci	int err;
103362306a36Sopenharmony_ci	u16 val, id;
103462306a36Sopenharmony_ci
103562306a36Sopenharmony_ci	err = ad3552r_reset(dac);
103662306a36Sopenharmony_ci	if (err) {
103762306a36Sopenharmony_ci		dev_err(&dac->spi->dev, "Reset failed\n");
103862306a36Sopenharmony_ci		return err;
103962306a36Sopenharmony_ci	}
104062306a36Sopenharmony_ci
104162306a36Sopenharmony_ci	err = ad3552r_check_scratch_pad(dac);
104262306a36Sopenharmony_ci	if (err) {
104362306a36Sopenharmony_ci		dev_err(&dac->spi->dev, "Scratch pad test failed\n");
104462306a36Sopenharmony_ci		return err;
104562306a36Sopenharmony_ci	}
104662306a36Sopenharmony_ci
104762306a36Sopenharmony_ci	err = ad3552r_read_reg(dac, AD3552R_REG_ADDR_PRODUCT_ID_L, &val);
104862306a36Sopenharmony_ci	if (err) {
104962306a36Sopenharmony_ci		dev_err(&dac->spi->dev, "Fail read PRODUCT_ID_L\n");
105062306a36Sopenharmony_ci		return err;
105162306a36Sopenharmony_ci	}
105262306a36Sopenharmony_ci
105362306a36Sopenharmony_ci	id = val;
105462306a36Sopenharmony_ci	err = ad3552r_read_reg(dac, AD3552R_REG_ADDR_PRODUCT_ID_H, &val);
105562306a36Sopenharmony_ci	if (err) {
105662306a36Sopenharmony_ci		dev_err(&dac->spi->dev, "Fail read PRODUCT_ID_H\n");
105762306a36Sopenharmony_ci		return err;
105862306a36Sopenharmony_ci	}
105962306a36Sopenharmony_ci
106062306a36Sopenharmony_ci	id |= val << 8;
106162306a36Sopenharmony_ci	if (id != dac->chip_id) {
106262306a36Sopenharmony_ci		dev_err(&dac->spi->dev, "Product id not matching\n");
106362306a36Sopenharmony_ci		return -ENODEV;
106462306a36Sopenharmony_ci	}
106562306a36Sopenharmony_ci
106662306a36Sopenharmony_ci	return ad3552r_configure_device(dac);
106762306a36Sopenharmony_ci}
106862306a36Sopenharmony_ci
106962306a36Sopenharmony_cistatic int ad3552r_probe(struct spi_device *spi)
107062306a36Sopenharmony_ci{
107162306a36Sopenharmony_ci	const struct spi_device_id *id = spi_get_device_id(spi);
107262306a36Sopenharmony_ci	struct ad3552r_desc *dac;
107362306a36Sopenharmony_ci	struct iio_dev *indio_dev;
107462306a36Sopenharmony_ci	int err;
107562306a36Sopenharmony_ci
107662306a36Sopenharmony_ci	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*dac));
107762306a36Sopenharmony_ci	if (!indio_dev)
107862306a36Sopenharmony_ci		return -ENOMEM;
107962306a36Sopenharmony_ci
108062306a36Sopenharmony_ci	dac = iio_priv(indio_dev);
108162306a36Sopenharmony_ci	dac->spi = spi;
108262306a36Sopenharmony_ci	dac->chip_id = id->driver_data;
108362306a36Sopenharmony_ci
108462306a36Sopenharmony_ci	mutex_init(&dac->lock);
108562306a36Sopenharmony_ci
108662306a36Sopenharmony_ci	err = ad3552r_init(dac);
108762306a36Sopenharmony_ci	if (err)
108862306a36Sopenharmony_ci		return err;
108962306a36Sopenharmony_ci
109062306a36Sopenharmony_ci	/* Config triggered buffer device */
109162306a36Sopenharmony_ci	if (dac->chip_id == AD3552R_ID)
109262306a36Sopenharmony_ci		indio_dev->name = "ad3552r";
109362306a36Sopenharmony_ci	else
109462306a36Sopenharmony_ci		indio_dev->name = "ad3542r";
109562306a36Sopenharmony_ci	indio_dev->dev.parent = &spi->dev;
109662306a36Sopenharmony_ci	indio_dev->info = &ad3552r_iio_info;
109762306a36Sopenharmony_ci	indio_dev->num_channels = dac->num_ch;
109862306a36Sopenharmony_ci	indio_dev->channels = dac->channels;
109962306a36Sopenharmony_ci	indio_dev->modes = INDIO_DIRECT_MODE;
110062306a36Sopenharmony_ci
110162306a36Sopenharmony_ci	err = devm_iio_triggered_buffer_setup_ext(&indio_dev->dev, indio_dev, NULL,
110262306a36Sopenharmony_ci						  &ad3552r_trigger_handler,
110362306a36Sopenharmony_ci						  IIO_BUFFER_DIRECTION_OUT,
110462306a36Sopenharmony_ci						  NULL,
110562306a36Sopenharmony_ci						  NULL);
110662306a36Sopenharmony_ci	if (err)
110762306a36Sopenharmony_ci		return err;
110862306a36Sopenharmony_ci
110962306a36Sopenharmony_ci	return devm_iio_device_register(&spi->dev, indio_dev);
111062306a36Sopenharmony_ci}
111162306a36Sopenharmony_ci
111262306a36Sopenharmony_cistatic const struct spi_device_id ad3552r_id[] = {
111362306a36Sopenharmony_ci	{ "ad3542r", AD3542R_ID },
111462306a36Sopenharmony_ci	{ "ad3552r", AD3552R_ID },
111562306a36Sopenharmony_ci	{ }
111662306a36Sopenharmony_ci};
111762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(spi, ad3552r_id);
111862306a36Sopenharmony_ci
111962306a36Sopenharmony_cistatic const struct of_device_id ad3552r_of_match[] = {
112062306a36Sopenharmony_ci	{ .compatible = "adi,ad3542r"},
112162306a36Sopenharmony_ci	{ .compatible = "adi,ad3552r"},
112262306a36Sopenharmony_ci	{ }
112362306a36Sopenharmony_ci};
112462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, ad3552r_of_match);
112562306a36Sopenharmony_ci
112662306a36Sopenharmony_cistatic struct spi_driver ad3552r_driver = {
112762306a36Sopenharmony_ci	.driver = {
112862306a36Sopenharmony_ci		.name = "ad3552r",
112962306a36Sopenharmony_ci		.of_match_table = ad3552r_of_match,
113062306a36Sopenharmony_ci	},
113162306a36Sopenharmony_ci	.probe = ad3552r_probe,
113262306a36Sopenharmony_ci	.id_table = ad3552r_id
113362306a36Sopenharmony_ci};
113462306a36Sopenharmony_cimodule_spi_driver(ad3552r_driver);
113562306a36Sopenharmony_ci
113662306a36Sopenharmony_ciMODULE_AUTHOR("Mihail Chindris <mihail.chindris@analog.com>");
113762306a36Sopenharmony_ciMODULE_DESCRIPTION("Analog Device AD3552R DAC");
113862306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
1139