xref: /linux/drivers/iio/dac/max22007.c (revision c17ee635fd3a482b2ad2bf5e269755c2eae5f25e)
1*f52690c5SJanani Sunil // SPDX-License-Identifier: GPL-2.0
2*f52690c5SJanani Sunil /*
3*f52690c5SJanani Sunil  * max22007.c - MAX22007 DAC driver
4*f52690c5SJanani Sunil  *
5*f52690c5SJanani Sunil  * Driver for Analog Devices MAX22007 Digital to Analog Converter.
6*f52690c5SJanani Sunil  *
7*f52690c5SJanani Sunil  * Copyright (c) 2026 Analog Devices Inc.
8*f52690c5SJanani Sunil  */
9*f52690c5SJanani Sunil 
10*f52690c5SJanani Sunil #include <linux/bitfield.h>
11*f52690c5SJanani Sunil #include <linux/bits.h>
12*f52690c5SJanani Sunil #include <linux/crc8.h>
13*f52690c5SJanani Sunil #include <linux/delay.h>
14*f52690c5SJanani Sunil #include <linux/dev_printk.h>
15*f52690c5SJanani Sunil #include <linux/device/devres.h>
16*f52690c5SJanani Sunil #include <linux/err.h>
17*f52690c5SJanani Sunil #include <linux/errno.h>
18*f52690c5SJanani Sunil #include <linux/gpio/consumer.h>
19*f52690c5SJanani Sunil #include <linux/iio/iio.h>
20*f52690c5SJanani Sunil #include <linux/kstrtox.h>
21*f52690c5SJanani Sunil #include <linux/minmax.h>
22*f52690c5SJanani Sunil #include <linux/mod_devicetable.h>
23*f52690c5SJanani Sunil #include <linux/module.h>
24*f52690c5SJanani Sunil #include <linux/property.h>
25*f52690c5SJanani Sunil #include <linux/regmap.h>
26*f52690c5SJanani Sunil #include <linux/regulator/consumer.h>
27*f52690c5SJanani Sunil #include <linux/slab.h>
28*f52690c5SJanani Sunil #include <linux/spi/spi.h>
29*f52690c5SJanani Sunil #include <linux/string.h>
30*f52690c5SJanani Sunil #include <linux/sysfs.h>
31*f52690c5SJanani Sunil #include <linux/types.h>
32*f52690c5SJanani Sunil 
33*f52690c5SJanani Sunil #include <dt-bindings/iio/addac/adi,ad74413r.h>
34*f52690c5SJanani Sunil struct device;
35*f52690c5SJanani Sunil 
36*f52690c5SJanani Sunil #define MAX22007_NUM_CHANNELS				4
37*f52690c5SJanani Sunil #define MAX22007_REV_ID_REG				0x00
38*f52690c5SJanani Sunil #define MAX22007_STAT_INTR_REG				0x01
39*f52690c5SJanani Sunil #define MAX22007_INTERRUPT_EN_REG			0x02
40*f52690c5SJanani Sunil #define MAX22007_CONFIG_REG				0x03
41*f52690c5SJanani Sunil #define MAX22007_CONTROL_REG				0x04
42*f52690c5SJanani Sunil #define MAX22007_CHANNEL_MODE_REG			0x05
43*f52690c5SJanani Sunil #define MAX22007_SOFT_RESET_REG				0x06
44*f52690c5SJanani Sunil #define MAX22007_DAC_CHANNEL_REG(ch)			(0x07 + (ch))
45*f52690c5SJanani Sunil #define MAX22007_GPIO_CTRL_REG				0x0B
46*f52690c5SJanani Sunil #define MAX22007_GPIO_DATA_REG				0x0C
47*f52690c5SJanani Sunil #define MAX22007_GPI_EDGE_INT_CTRL_REG			0x0D
48*f52690c5SJanani Sunil #define MAX22007_GPI_INT_STATUS_REG			0x0E
49*f52690c5SJanani Sunil 
50*f52690c5SJanani Sunil /* Channel mask definitions */
51*f52690c5SJanani Sunil #define     MAX22007_CH_MODE_CH_MASK(ch)		BIT(12 + (ch))
52*f52690c5SJanani Sunil #define     MAX22007_CH_PWRON_CH_MASK(ch)		BIT(8 + (ch))
53*f52690c5SJanani Sunil #define     MAX22007_DAC_LATCH_MODE_MASK(ch)		BIT(12 + (ch))
54*f52690c5SJanani Sunil #define     MAX22007_LDAC_UPDATE_MASK(ch)		BIT(12 + (ch))
55*f52690c5SJanani Sunil #define     MAX22007_SW_RST_MASK			BIT(8)
56*f52690c5SJanani Sunil #define     MAX22007_SW_CLR_MASK			BIT(12)
57*f52690c5SJanani Sunil #define     MAX22007_SOFT_RESET_BITS_MASK		(MAX22007_SW_RST_MASK | \
58*f52690c5SJanani Sunil 							 MAX22007_SW_CLR_MASK)
59*f52690c5SJanani Sunil #define     MAX22007_DAC_DATA_MASK			GENMASK(15, 4)
60*f52690c5SJanani Sunil #define     MAX22007_DAC_MAX_RAW			GENMASK(11, 0)
61*f52690c5SJanani Sunil #define     MAX22007_CRC8_POLYNOMIAL			0x8C
62*f52690c5SJanani Sunil #define     MAX22007_CRC_EN_MASK			BIT(0)
63*f52690c5SJanani Sunil #define     MAX22007_RW_MASK				BIT(0)
64*f52690c5SJanani Sunil #define     MAX22007_CRC_OVERHEAD			1
65*f52690c5SJanani Sunil #define     MAX22007_NUM_SUPPLIES			3
66*f52690c5SJanani Sunil #define     MAX22007_REF_MV				2500
67*f52690c5SJanani Sunil 
68*f52690c5SJanani Sunil /* Field value preparation macros with masking */
69*f52690c5SJanani Sunil #define     MAX22007_CH_PWR_VAL(ch, val)		(((val) & 0x1) << (8 + (ch)))
70*f52690c5SJanani Sunil #define     MAX22007_CH_MODE_VAL(ch, val)		(((val) & 0x1) << (12 + (ch)))
71*f52690c5SJanani Sunil #define     MAX22007_DAC_LATCH_MODE_VAL(ch, val)	(((val) & 0x1) << (12 + (ch)))
72*f52690c5SJanani Sunil 
73*f52690c5SJanani Sunil static u8 max22007_crc8_table[CRC8_TABLE_SIZE];
74*f52690c5SJanani Sunil 
75*f52690c5SJanani Sunil static const char * const max22007_supply_names[MAX22007_NUM_SUPPLIES] = {
76*f52690c5SJanani Sunil 	"vdd",
77*f52690c5SJanani Sunil 	"hvdd",
78*f52690c5SJanani Sunil 	"hvss",
79*f52690c5SJanani Sunil };
80*f52690c5SJanani Sunil 
81*f52690c5SJanani Sunil struct max22007_state {
82*f52690c5SJanani Sunil 	struct spi_device *spi;
83*f52690c5SJanani Sunil 	struct regmap *regmap;
84*f52690c5SJanani Sunil 	struct iio_chan_spec *iio_chans;
85*f52690c5SJanani Sunil 	u8 tx_buf[4] __aligned(IIO_DMA_MINALIGN);
86*f52690c5SJanani Sunil 	u8 rx_buf[4];
87*f52690c5SJanani Sunil };
88*f52690c5SJanani Sunil 
89*f52690c5SJanani Sunil static int max22007_spi_read(void *context, const void *reg, size_t reg_size,
90*f52690c5SJanani Sunil 			     void *val, size_t val_size)
91*f52690c5SJanani Sunil {
92*f52690c5SJanani Sunil 	struct max22007_state *st = context;
93*f52690c5SJanani Sunil 	u8 calculated_crc, received_crc;
94*f52690c5SJanani Sunil 	u8 rx_buf[4];
95*f52690c5SJanani Sunil 	u8 reg_byte;
96*f52690c5SJanani Sunil 	int ret;
97*f52690c5SJanani Sunil 
98*f52690c5SJanani Sunil 	if (reg_size != 1)
99*f52690c5SJanani Sunil 		return -EINVAL;
100*f52690c5SJanani Sunil 
101*f52690c5SJanani Sunil 	if (val_size == 0 || val_size > 3)
102*f52690c5SJanani Sunil 		return -EINVAL;
103*f52690c5SJanani Sunil 
104*f52690c5SJanani Sunil 	memcpy(&reg_byte, reg, 1);
105*f52690c5SJanani Sunil 
106*f52690c5SJanani Sunil 	ret = spi_write_then_read(st->spi, &reg_byte, 1, rx_buf,
107*f52690c5SJanani Sunil 				  val_size + MAX22007_CRC_OVERHEAD);
108*f52690c5SJanani Sunil 	if (ret) {
109*f52690c5SJanani Sunil 		dev_err(&st->spi->dev, "SPI transfer failed: %d\n", ret);
110*f52690c5SJanani Sunil 		return ret;
111*f52690c5SJanani Sunil 	}
112*f52690c5SJanani Sunil 
113*f52690c5SJanani Sunil 	calculated_crc = crc8(max22007_crc8_table, &reg_byte, 1, 0x00);
114*f52690c5SJanani Sunil 	calculated_crc = crc8(max22007_crc8_table, rx_buf, 2, calculated_crc);
115*f52690c5SJanani Sunil 	received_crc = rx_buf[val_size];
116*f52690c5SJanani Sunil 
117*f52690c5SJanani Sunil 	if (calculated_crc != received_crc) {
118*f52690c5SJanani Sunil 		dev_err(&st->spi->dev, "CRC mismatch on read register %02x\n", reg_byte);
119*f52690c5SJanani Sunil 		return -EIO;
120*f52690c5SJanani Sunil 	}
121*f52690c5SJanani Sunil 
122*f52690c5SJanani Sunil 	memcpy(val, rx_buf, val_size);
123*f52690c5SJanani Sunil 
124*f52690c5SJanani Sunil 	return 0;
125*f52690c5SJanani Sunil }
126*f52690c5SJanani Sunil 
127*f52690c5SJanani Sunil static int max22007_spi_write(void *context, const void *data, size_t count)
128*f52690c5SJanani Sunil {
129*f52690c5SJanani Sunil 	struct max22007_state *st = context;
130*f52690c5SJanani Sunil 	struct spi_transfer xfer = {
131*f52690c5SJanani Sunil 		.tx_buf = st->tx_buf,
132*f52690c5SJanani Sunil 		.rx_buf = st->rx_buf,
133*f52690c5SJanani Sunil 	};
134*f52690c5SJanani Sunil 
135*f52690c5SJanani Sunil 	if (count + MAX22007_CRC_OVERHEAD > sizeof(st->tx_buf))
136*f52690c5SJanani Sunil 		return -EINVAL;
137*f52690c5SJanani Sunil 
138*f52690c5SJanani Sunil 	memset(st->tx_buf, 0, sizeof(st->tx_buf));
139*f52690c5SJanani Sunil 
140*f52690c5SJanani Sunil 	xfer.len = count + MAX22007_CRC_OVERHEAD;
141*f52690c5SJanani Sunil 
142*f52690c5SJanani Sunil 	memcpy(st->tx_buf, data, count);
143*f52690c5SJanani Sunil 	st->tx_buf[count] = crc8(max22007_crc8_table, st->tx_buf,
144*f52690c5SJanani Sunil 				 sizeof(st->tx_buf) - 1, 0x00);
145*f52690c5SJanani Sunil 
146*f52690c5SJanani Sunil 	return spi_sync_transfer(st->spi, &xfer, 1);
147*f52690c5SJanani Sunil }
148*f52690c5SJanani Sunil 
149*f52690c5SJanani Sunil static bool max22007_reg_readable(struct device *dev, unsigned int reg)
150*f52690c5SJanani Sunil {
151*f52690c5SJanani Sunil 	switch (reg) {
152*f52690c5SJanani Sunil 	case MAX22007_REV_ID_REG:
153*f52690c5SJanani Sunil 	case MAX22007_STAT_INTR_REG:
154*f52690c5SJanani Sunil 	case MAX22007_CONFIG_REG:
155*f52690c5SJanani Sunil 	case MAX22007_CONTROL_REG:
156*f52690c5SJanani Sunil 	case MAX22007_CHANNEL_MODE_REG:
157*f52690c5SJanani Sunil 	case MAX22007_SOFT_RESET_REG:
158*f52690c5SJanani Sunil 	case MAX22007_GPIO_CTRL_REG:
159*f52690c5SJanani Sunil 	case MAX22007_GPIO_DATA_REG:
160*f52690c5SJanani Sunil 	case MAX22007_GPI_EDGE_INT_CTRL_REG:
161*f52690c5SJanani Sunil 	case MAX22007_GPI_INT_STATUS_REG:
162*f52690c5SJanani Sunil 		return true;
163*f52690c5SJanani Sunil 	case MAX22007_DAC_CHANNEL_REG(0) ... MAX22007_DAC_CHANNEL_REG(MAX22007_NUM_CHANNELS - 1):
164*f52690c5SJanani Sunil 		return true;
165*f52690c5SJanani Sunil 	default:
166*f52690c5SJanani Sunil 		return false;
167*f52690c5SJanani Sunil 	}
168*f52690c5SJanani Sunil }
169*f52690c5SJanani Sunil 
170*f52690c5SJanani Sunil static bool max22007_reg_writable(struct device *dev, unsigned int reg)
171*f52690c5SJanani Sunil {
172*f52690c5SJanani Sunil 	switch (reg) {
173*f52690c5SJanani Sunil 	case MAX22007_CONFIG_REG:
174*f52690c5SJanani Sunil 	case MAX22007_CONTROL_REG:
175*f52690c5SJanani Sunil 	case MAX22007_CHANNEL_MODE_REG:
176*f52690c5SJanani Sunil 	case MAX22007_SOFT_RESET_REG:
177*f52690c5SJanani Sunil 	case MAX22007_GPIO_CTRL_REG:
178*f52690c5SJanani Sunil 	case MAX22007_GPIO_DATA_REG:
179*f52690c5SJanani Sunil 	case MAX22007_GPI_EDGE_INT_CTRL_REG:
180*f52690c5SJanani Sunil 		return true;
181*f52690c5SJanani Sunil 	case MAX22007_DAC_CHANNEL_REG(0) ... MAX22007_DAC_CHANNEL_REG(MAX22007_NUM_CHANNELS - 1):
182*f52690c5SJanani Sunil 		return true;
183*f52690c5SJanani Sunil 	default:
184*f52690c5SJanani Sunil 		return false;
185*f52690c5SJanani Sunil 	}
186*f52690c5SJanani Sunil }
187*f52690c5SJanani Sunil 
188*f52690c5SJanani Sunil static const struct regmap_bus max22007_regmap_bus = {
189*f52690c5SJanani Sunil 	.read = max22007_spi_read,
190*f52690c5SJanani Sunil 	.write = max22007_spi_write,
191*f52690c5SJanani Sunil 	.read_flag_mask = MAX22007_RW_MASK,
192*f52690c5SJanani Sunil 	.reg_format_endian_default = REGMAP_ENDIAN_BIG,
193*f52690c5SJanani Sunil 	.val_format_endian_default = REGMAP_ENDIAN_BIG,
194*f52690c5SJanani Sunil };
195*f52690c5SJanani Sunil 
196*f52690c5SJanani Sunil static const struct regmap_config max22007_regmap_config = {
197*f52690c5SJanani Sunil 	.reg_bits = 8,
198*f52690c5SJanani Sunil 	.val_bits = 16,
199*f52690c5SJanani Sunil 	.reg_shift = -1,
200*f52690c5SJanani Sunil 	.readable_reg = max22007_reg_readable,
201*f52690c5SJanani Sunil 	.writeable_reg = max22007_reg_writable,
202*f52690c5SJanani Sunil 	.max_register = 0x0E,
203*f52690c5SJanani Sunil };
204*f52690c5SJanani Sunil 
205*f52690c5SJanani Sunil static int max22007_write_channel_data(struct max22007_state *st,
206*f52690c5SJanani Sunil 				       unsigned int channel, int data)
207*f52690c5SJanani Sunil {
208*f52690c5SJanani Sunil 	unsigned int reg_val;
209*f52690c5SJanani Sunil 
210*f52690c5SJanani Sunil 	if (data < 0 || data > MAX22007_DAC_MAX_RAW)
211*f52690c5SJanani Sunil 		return -EINVAL;
212*f52690c5SJanani Sunil 
213*f52690c5SJanani Sunil 	reg_val = FIELD_PREP(MAX22007_DAC_DATA_MASK, data);
214*f52690c5SJanani Sunil 
215*f52690c5SJanani Sunil 	return regmap_write(st->regmap, MAX22007_DAC_CHANNEL_REG(channel), reg_val);
216*f52690c5SJanani Sunil }
217*f52690c5SJanani Sunil 
218*f52690c5SJanani Sunil static int max22007_read_channel_data(struct max22007_state *st,
219*f52690c5SJanani Sunil 				      unsigned int channel, int *data)
220*f52690c5SJanani Sunil {
221*f52690c5SJanani Sunil 	unsigned int reg_val;
222*f52690c5SJanani Sunil 	int ret;
223*f52690c5SJanani Sunil 
224*f52690c5SJanani Sunil 	ret = regmap_read(st->regmap, MAX22007_DAC_CHANNEL_REG(channel), &reg_val);
225*f52690c5SJanani Sunil 	if (ret)
226*f52690c5SJanani Sunil 		return ret;
227*f52690c5SJanani Sunil 
228*f52690c5SJanani Sunil 	*data = FIELD_GET(MAX22007_DAC_DATA_MASK, reg_val);
229*f52690c5SJanani Sunil 
230*f52690c5SJanani Sunil 	return 0;
231*f52690c5SJanani Sunil }
232*f52690c5SJanani Sunil 
233*f52690c5SJanani Sunil static int max22007_read_raw(struct iio_dev *indio_dev,
234*f52690c5SJanani Sunil 			     struct iio_chan_spec const *chan,
235*f52690c5SJanani Sunil 			     int *val, int *val2, long mask)
236*f52690c5SJanani Sunil {
237*f52690c5SJanani Sunil 	struct max22007_state *st = iio_priv(indio_dev);
238*f52690c5SJanani Sunil 	int ret;
239*f52690c5SJanani Sunil 
240*f52690c5SJanani Sunil 	switch (mask) {
241*f52690c5SJanani Sunil 	case IIO_CHAN_INFO_RAW:
242*f52690c5SJanani Sunil 		ret = max22007_read_channel_data(st, chan->channel, val);
243*f52690c5SJanani Sunil 		if (ret)
244*f52690c5SJanani Sunil 			return ret;
245*f52690c5SJanani Sunil 		return IIO_VAL_INT;
246*f52690c5SJanani Sunil 	case IIO_CHAN_INFO_SCALE:
247*f52690c5SJanani Sunil 		if (chan->type == IIO_VOLTAGE)
248*f52690c5SJanani Sunil 			*val = 5 * MAX22007_REF_MV;  /* 5 * Vref in mV */
249*f52690c5SJanani Sunil 		else
250*f52690c5SJanani Sunil 			*val = 25;  /* Vref / (2 * Rsense) = MAX22007_REF_MV / 100 */
251*f52690c5SJanani Sunil 		*val2 = 12;  /* 12-bit DAC resolution */
252*f52690c5SJanani Sunil 		return IIO_VAL_FRACTIONAL_LOG2;
253*f52690c5SJanani Sunil 	default:
254*f52690c5SJanani Sunil 		return -EINVAL;
255*f52690c5SJanani Sunil 	}
256*f52690c5SJanani Sunil }
257*f52690c5SJanani Sunil 
258*f52690c5SJanani Sunil static int max22007_write_raw(struct iio_dev *indio_dev,
259*f52690c5SJanani Sunil 			      struct iio_chan_spec const *chan,
260*f52690c5SJanani Sunil 			      int val, int val2, long mask)
261*f52690c5SJanani Sunil {
262*f52690c5SJanani Sunil 	struct max22007_state *st = iio_priv(indio_dev);
263*f52690c5SJanani Sunil 
264*f52690c5SJanani Sunil 	switch (mask) {
265*f52690c5SJanani Sunil 	case IIO_CHAN_INFO_RAW:
266*f52690c5SJanani Sunil 		return max22007_write_channel_data(st, chan->channel, val);
267*f52690c5SJanani Sunil 	default:
268*f52690c5SJanani Sunil 		return -EINVAL;
269*f52690c5SJanani Sunil 	}
270*f52690c5SJanani Sunil }
271*f52690c5SJanani Sunil 
272*f52690c5SJanani Sunil static const struct iio_info max22007_info = {
273*f52690c5SJanani Sunil 	.read_raw = max22007_read_raw,
274*f52690c5SJanani Sunil 	.write_raw = max22007_write_raw,
275*f52690c5SJanani Sunil };
276*f52690c5SJanani Sunil 
277*f52690c5SJanani Sunil static ssize_t max22007_read_dac_powerdown(struct iio_dev *indio_dev,
278*f52690c5SJanani Sunil 					   uintptr_t private,
279*f52690c5SJanani Sunil 					   const struct iio_chan_spec *chan,
280*f52690c5SJanani Sunil 					   char *buf)
281*f52690c5SJanani Sunil {
282*f52690c5SJanani Sunil 	struct max22007_state *st = iio_priv(indio_dev);
283*f52690c5SJanani Sunil 	unsigned int reg_val;
284*f52690c5SJanani Sunil 	bool powerdown;
285*f52690c5SJanani Sunil 	int ret;
286*f52690c5SJanani Sunil 
287*f52690c5SJanani Sunil 	ret = regmap_read(st->regmap, MAX22007_CHANNEL_MODE_REG, &reg_val);
288*f52690c5SJanani Sunil 	if (ret)
289*f52690c5SJanani Sunil 		return ret;
290*f52690c5SJanani Sunil 
291*f52690c5SJanani Sunil 	powerdown = !(reg_val & MAX22007_CH_PWRON_CH_MASK(chan->channel));
292*f52690c5SJanani Sunil 
293*f52690c5SJanani Sunil 	return sysfs_emit(buf, "%d\n", powerdown);
294*f52690c5SJanani Sunil }
295*f52690c5SJanani Sunil 
296*f52690c5SJanani Sunil static ssize_t max22007_write_dac_powerdown(struct iio_dev *indio_dev,
297*f52690c5SJanani Sunil 					    uintptr_t private,
298*f52690c5SJanani Sunil 					    const struct iio_chan_spec *chan,
299*f52690c5SJanani Sunil 					    const char *buf, size_t len)
300*f52690c5SJanani Sunil {
301*f52690c5SJanani Sunil 	struct max22007_state *st = iio_priv(indio_dev);
302*f52690c5SJanani Sunil 	bool powerdown;
303*f52690c5SJanani Sunil 	int ret;
304*f52690c5SJanani Sunil 
305*f52690c5SJanani Sunil 	ret = kstrtobool(buf, &powerdown);
306*f52690c5SJanani Sunil 	if (ret)
307*f52690c5SJanani Sunil 		return ret;
308*f52690c5SJanani Sunil 
309*f52690c5SJanani Sunil 	ret = regmap_update_bits(st->regmap, MAX22007_CHANNEL_MODE_REG,
310*f52690c5SJanani Sunil 				 MAX22007_CH_PWRON_CH_MASK(chan->channel),
311*f52690c5SJanani Sunil 				 MAX22007_CH_PWR_VAL(chan->channel, powerdown ? 0 : 1));
312*f52690c5SJanani Sunil 	if (ret)
313*f52690c5SJanani Sunil 		return ret;
314*f52690c5SJanani Sunil 
315*f52690c5SJanani Sunil 	return len;
316*f52690c5SJanani Sunil }
317*f52690c5SJanani Sunil 
318*f52690c5SJanani Sunil static const struct iio_chan_spec_ext_info max22007_ext_info[] = {
319*f52690c5SJanani Sunil 	{
320*f52690c5SJanani Sunil 		.name = "powerdown",
321*f52690c5SJanani Sunil 		.read = max22007_read_dac_powerdown,
322*f52690c5SJanani Sunil 		.write = max22007_write_dac_powerdown,
323*f52690c5SJanani Sunil 		.shared = IIO_SEPARATE,
324*f52690c5SJanani Sunil 	},
325*f52690c5SJanani Sunil 	{ }
326*f52690c5SJanani Sunil };
327*f52690c5SJanani Sunil 
328*f52690c5SJanani Sunil static int max22007_parse_channel_cfg(struct max22007_state *st, u8 *num_channels)
329*f52690c5SJanani Sunil {
330*f52690c5SJanani Sunil 	struct device *dev = &st->spi->dev;
331*f52690c5SJanani Sunil 	int ret, num_chan;
332*f52690c5SJanani Sunil 	int i = 0;
333*f52690c5SJanani Sunil 	u32 reg;
334*f52690c5SJanani Sunil 
335*f52690c5SJanani Sunil 	num_chan = device_get_child_node_count(dev);
336*f52690c5SJanani Sunil 	if (!num_chan)
337*f52690c5SJanani Sunil 		return dev_err_probe(dev, -ENODEV, "no channels configured\n");
338*f52690c5SJanani Sunil 
339*f52690c5SJanani Sunil 	st->iio_chans = devm_kcalloc(dev, num_chan, sizeof(*st->iio_chans), GFP_KERNEL);
340*f52690c5SJanani Sunil 	if (!st->iio_chans)
341*f52690c5SJanani Sunil 		return -ENOMEM;
342*f52690c5SJanani Sunil 
343*f52690c5SJanani Sunil 	device_for_each_child_node_scoped(dev, child) {
344*f52690c5SJanani Sunil 		u32 ch_func;
345*f52690c5SJanani Sunil 		enum iio_chan_type chan_type;
346*f52690c5SJanani Sunil 
347*f52690c5SJanani Sunil 		ret = fwnode_property_read_u32(child, "reg", &reg);
348*f52690c5SJanani Sunil 		if (ret)
349*f52690c5SJanani Sunil 			return dev_err_probe(dev, ret,
350*f52690c5SJanani Sunil 					     "failed to read reg property of %pfwP\n", child);
351*f52690c5SJanani Sunil 
352*f52690c5SJanani Sunil 		if (reg >= MAX22007_NUM_CHANNELS)
353*f52690c5SJanani Sunil 			return dev_err_probe(dev, -EINVAL,
354*f52690c5SJanani Sunil 					     "reg out of range in %pfwP\n", child);
355*f52690c5SJanani Sunil 
356*f52690c5SJanani Sunil 		ret = fwnode_property_read_u32(child, "adi,ch-func", &ch_func);
357*f52690c5SJanani Sunil 		if (ret)
358*f52690c5SJanani Sunil 			return dev_err_probe(dev, ret,
359*f52690c5SJanani Sunil 					     "missing adi,ch-func property for %pfwP\n", child);
360*f52690c5SJanani Sunil 
361*f52690c5SJanani Sunil 		switch (ch_func) {
362*f52690c5SJanani Sunil 		case CH_FUNC_VOLTAGE_OUTPUT:
363*f52690c5SJanani Sunil 			chan_type = IIO_VOLTAGE;
364*f52690c5SJanani Sunil 			break;
365*f52690c5SJanani Sunil 		case CH_FUNC_CURRENT_OUTPUT:
366*f52690c5SJanani Sunil 			chan_type = IIO_CURRENT;
367*f52690c5SJanani Sunil 			break;
368*f52690c5SJanani Sunil 		default:
369*f52690c5SJanani Sunil 			return dev_err_probe(dev, -EINVAL,
370*f52690c5SJanani Sunil 					     "invalid adi,ch-func %u for %pfwP\n",
371*f52690c5SJanani Sunil 					     ch_func, child);
372*f52690c5SJanani Sunil 		}
373*f52690c5SJanani Sunil 
374*f52690c5SJanani Sunil 		st->iio_chans[i++] = (struct iio_chan_spec) {
375*f52690c5SJanani Sunil 			.output = 1,
376*f52690c5SJanani Sunil 			.indexed = 1,
377*f52690c5SJanani Sunil 			.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
378*f52690c5SJanani Sunil 					      BIT(IIO_CHAN_INFO_SCALE),
379*f52690c5SJanani Sunil 			.ext_info = max22007_ext_info,
380*f52690c5SJanani Sunil 			.channel = reg,
381*f52690c5SJanani Sunil 			.type = chan_type,
382*f52690c5SJanani Sunil 		};
383*f52690c5SJanani Sunil 
384*f52690c5SJanani Sunil 		ret = regmap_update_bits(st->regmap, MAX22007_CHANNEL_MODE_REG,
385*f52690c5SJanani Sunil 					 MAX22007_CH_MODE_CH_MASK(reg),
386*f52690c5SJanani Sunil 					 MAX22007_CH_MODE_VAL(reg, ch_func - 1));
387*f52690c5SJanani Sunil 		if (ret)
388*f52690c5SJanani Sunil 			return ret;
389*f52690c5SJanani Sunil 
390*f52690c5SJanani Sunil 		/* Set DAC to transparent mode (immediate update) */
391*f52690c5SJanani Sunil 		ret = regmap_update_bits(st->regmap, MAX22007_CONFIG_REG,
392*f52690c5SJanani Sunil 					 MAX22007_DAC_LATCH_MODE_MASK(reg),
393*f52690c5SJanani Sunil 					 MAX22007_DAC_LATCH_MODE_VAL(reg, 1));
394*f52690c5SJanani Sunil 		if (ret)
395*f52690c5SJanani Sunil 			return ret;
396*f52690c5SJanani Sunil 	}
397*f52690c5SJanani Sunil 
398*f52690c5SJanani Sunil 	*num_channels = num_chan;
399*f52690c5SJanani Sunil 
400*f52690c5SJanani Sunil 	return 0;
401*f52690c5SJanani Sunil }
402*f52690c5SJanani Sunil 
403*f52690c5SJanani Sunil static int max22007_probe(struct spi_device *spi)
404*f52690c5SJanani Sunil {
405*f52690c5SJanani Sunil 	struct device *dev = &spi->dev;
406*f52690c5SJanani Sunil 	struct gpio_desc *reset_gpio;
407*f52690c5SJanani Sunil 	struct max22007_state *st;
408*f52690c5SJanani Sunil 	struct iio_dev *indio_dev;
409*f52690c5SJanani Sunil 	u8 num_channels;
410*f52690c5SJanani Sunil 	int ret;
411*f52690c5SJanani Sunil 
412*f52690c5SJanani Sunil 	indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
413*f52690c5SJanani Sunil 	if (!indio_dev)
414*f52690c5SJanani Sunil 		return -ENOMEM;
415*f52690c5SJanani Sunil 
416*f52690c5SJanani Sunil 	st = iio_priv(indio_dev);
417*f52690c5SJanani Sunil 	st->spi = spi;
418*f52690c5SJanani Sunil 
419*f52690c5SJanani Sunil 	crc8_populate_lsb(max22007_crc8_table, MAX22007_CRC8_POLYNOMIAL);
420*f52690c5SJanani Sunil 
421*f52690c5SJanani Sunil 	st->regmap = devm_regmap_init(dev, &max22007_regmap_bus, st,
422*f52690c5SJanani Sunil 					 &max22007_regmap_config);
423*f52690c5SJanani Sunil 	if (IS_ERR(st->regmap))
424*f52690c5SJanani Sunil 		return dev_err_probe(dev, PTR_ERR(st->regmap),
425*f52690c5SJanani Sunil 				     "Failed to initialize regmap\n");
426*f52690c5SJanani Sunil 
427*f52690c5SJanani Sunil 	ret = devm_regulator_bulk_get_enable(dev, MAX22007_NUM_SUPPLIES,
428*f52690c5SJanani Sunil 					     max22007_supply_names);
429*f52690c5SJanani Sunil 	if (ret)
430*f52690c5SJanani Sunil 		return dev_err_probe(dev, ret, "Failed to get and enable regulators\n");
431*f52690c5SJanani Sunil 
432*f52690c5SJanani Sunil 	reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
433*f52690c5SJanani Sunil 	if (IS_ERR(reset_gpio))
434*f52690c5SJanani Sunil 		return dev_err_probe(dev, PTR_ERR(reset_gpio),
435*f52690c5SJanani Sunil 				     "Failed to get reset GPIO\n");
436*f52690c5SJanani Sunil 
437*f52690c5SJanani Sunil 	if (reset_gpio) {
438*f52690c5SJanani Sunil 		gpiod_set_value_cansleep(reset_gpio, 1);
439*f52690c5SJanani Sunil 		usleep_range(1000, 5000);
440*f52690c5SJanani Sunil 		gpiod_set_value_cansleep(reset_gpio, 0);
441*f52690c5SJanani Sunil 		usleep_range(1000, 5000);
442*f52690c5SJanani Sunil 	} else {
443*f52690c5SJanani Sunil 		ret = regmap_write(st->regmap, MAX22007_SOFT_RESET_REG,
444*f52690c5SJanani Sunil 				   MAX22007_SOFT_RESET_BITS_MASK);
445*f52690c5SJanani Sunil 		if (ret)
446*f52690c5SJanani Sunil 			return ret;
447*f52690c5SJanani Sunil 	}
448*f52690c5SJanani Sunil 
449*f52690c5SJanani Sunil 	ret = regmap_set_bits(st->regmap, MAX22007_CONFIG_REG,
450*f52690c5SJanani Sunil 			      MAX22007_CRC_EN_MASK);
451*f52690c5SJanani Sunil 	if (ret)
452*f52690c5SJanani Sunil 		return ret;
453*f52690c5SJanani Sunil 
454*f52690c5SJanani Sunil 	ret = max22007_parse_channel_cfg(st, &num_channels);
455*f52690c5SJanani Sunil 	if (ret)
456*f52690c5SJanani Sunil 		return ret;
457*f52690c5SJanani Sunil 
458*f52690c5SJanani Sunil 	indio_dev->info = &max22007_info;
459*f52690c5SJanani Sunil 	indio_dev->modes = INDIO_DIRECT_MODE;
460*f52690c5SJanani Sunil 	indio_dev->channels = st->iio_chans;
461*f52690c5SJanani Sunil 	indio_dev->num_channels = num_channels;
462*f52690c5SJanani Sunil 	indio_dev->name = "max22007";
463*f52690c5SJanani Sunil 
464*f52690c5SJanani Sunil 	return devm_iio_device_register(dev, indio_dev);
465*f52690c5SJanani Sunil }
466*f52690c5SJanani Sunil 
467*f52690c5SJanani Sunil static const struct spi_device_id max22007_id[] = {
468*f52690c5SJanani Sunil 	{ "max22007" },
469*f52690c5SJanani Sunil 	{ }
470*f52690c5SJanani Sunil };
471*f52690c5SJanani Sunil MODULE_DEVICE_TABLE(spi, max22007_id);
472*f52690c5SJanani Sunil 
473*f52690c5SJanani Sunil static const struct of_device_id max22007_of_match[] = {
474*f52690c5SJanani Sunil 	{ .compatible = "adi,max22007" },
475*f52690c5SJanani Sunil 	{ }
476*f52690c5SJanani Sunil };
477*f52690c5SJanani Sunil MODULE_DEVICE_TABLE(of, max22007_of_match);
478*f52690c5SJanani Sunil 
479*f52690c5SJanani Sunil static struct spi_driver max22007_driver = {
480*f52690c5SJanani Sunil 	.driver = {
481*f52690c5SJanani Sunil 		.name = "max22007",
482*f52690c5SJanani Sunil 		.of_match_table = max22007_of_match,
483*f52690c5SJanani Sunil 	},
484*f52690c5SJanani Sunil 	.probe = max22007_probe,
485*f52690c5SJanani Sunil 	.id_table = max22007_id,
486*f52690c5SJanani Sunil };
487*f52690c5SJanani Sunil module_spi_driver(max22007_driver);
488*f52690c5SJanani Sunil 
489*f52690c5SJanani Sunil MODULE_AUTHOR("Janani Sunil <janani.sunil@analog.com>");
490*f52690c5SJanani Sunil MODULE_DESCRIPTION("Analog Devices MAX22007 DAC");
491*f52690c5SJanani Sunil MODULE_LICENSE("GPL");
492