xref: /linux/drivers/iio/dac/ltc2632.c (revision 13845bdc869f136f92ad3d40ea09b867bb4ce467)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * LTC2632 Digital to analog convertors spi driver
4  *
5  * Copyright 2017 Maxime Roussin-Bélanger
6  * expanded by Silvan Murer <silvan.murer@gmail.com>
7  */
8 
9 #include <linux/device.h>
10 #include <linux/spi/spi.h>
11 #include <linux/module.h>
12 #include <linux/iio/iio.h>
13 #include <linux/property.h>
14 #include <linux/regulator/consumer.h>
15 
16 #include <linux/unaligned.h>
17 
18 #define LTC2632_CMD_WRITE_INPUT_N               0x0
19 #define LTC2632_CMD_UPDATE_DAC_N                0x1
20 #define LTC2632_CMD_WRITE_INPUT_N_UPDATE_ALL    0x2
21 #define LTC2632_CMD_WRITE_INPUT_N_UPDATE_N      0x3
22 #define LTC2632_CMD_POWERDOWN_DAC_N             0x4
23 #define LTC2632_CMD_POWERDOWN_CHIP              0x5
24 #define LTC2632_CMD_INTERNAL_REFER              0x6
25 #define LTC2632_CMD_EXTERNAL_REFER              0x7
26 
27 /**
28  * struct ltc2632_chip_info - chip specific information
29  * @channels:		channel spec for the DAC
30  * @num_channels:	DAC channel count of the chip
31  * @vref_mv:		internal reference voltage
32  */
33 struct ltc2632_chip_info {
34 	const struct iio_chan_spec *channels;
35 	const size_t num_channels;
36 	const int vref_mv;
37 };
38 
39 /**
40  * struct ltc2632_state - driver instance specific data
41  * @spi_dev:			pointer to the spi_device struct
42  * @powerdown_cache_mask:	used to show current channel powerdown state
43  * @vref_mv:			used reference voltage (internal or external)
44  */
45 struct ltc2632_state {
46 	struct spi_device *spi_dev;
47 	unsigned int powerdown_cache_mask;
48 	int vref_mv;
49 };
50 
51 enum ltc2632_supported_device_ids {
52 	ID_LTC2632L12,
53 	ID_LTC2632L10,
54 	ID_LTC2632L8,
55 	ID_LTC2632H12,
56 	ID_LTC2632H10,
57 	ID_LTC2632H8,
58 	ID_LTC2634L12,
59 	ID_LTC2634L10,
60 	ID_LTC2634L8,
61 	ID_LTC2634H12,
62 	ID_LTC2634H10,
63 	ID_LTC2634H8,
64 	ID_LTC2636L12,
65 	ID_LTC2636L10,
66 	ID_LTC2636L8,
67 	ID_LTC2636H12,
68 	ID_LTC2636H10,
69 	ID_LTC2636H8,
70 };
71 
72 static int ltc2632_spi_write(struct spi_device *spi,
73 			     u8 cmd, u8 addr, u16 val, u8 shift)
74 {
75 	u32 data;
76 	u8 msg[3];
77 
78 	/*
79 	 * The input shift register is 24 bits wide.
80 	 * The next four are the command bits, C3 to C0,
81 	 * followed by the 4-bit DAC address, A3 to A0, and then the
82 	 * 12-, 10-, 8-bit data-word. The data-word comprises the 12-,
83 	 * 10-, 8-bit input code followed by 4, 6, or 8 don't care bits.
84 	 */
85 	data = (cmd << 20) | (addr << 16) | (val << shift);
86 	put_unaligned_be24(data, &msg[0]);
87 
88 	return spi_write(spi, msg, sizeof(msg));
89 }
90 
91 static int ltc2632_read_raw(struct iio_dev *indio_dev,
92 			    struct iio_chan_spec const *chan,
93 			    int *val,
94 			    int *val2,
95 			    long m)
96 {
97 	const struct ltc2632_state *st = iio_priv(indio_dev);
98 
99 	switch (m) {
100 	case IIO_CHAN_INFO_SCALE:
101 		*val = st->vref_mv;
102 		*val2 = chan->scan_type.realbits;
103 		return IIO_VAL_FRACTIONAL_LOG2;
104 	}
105 	return -EINVAL;
106 }
107 
108 static int ltc2632_write_raw(struct iio_dev *indio_dev,
109 			     struct iio_chan_spec const *chan,
110 			     int val,
111 			     int val2,
112 			     long mask)
113 {
114 	struct ltc2632_state *st = iio_priv(indio_dev);
115 
116 	switch (mask) {
117 	case IIO_CHAN_INFO_RAW:
118 		if (val >= (1 << chan->scan_type.realbits) || val < 0)
119 			return -EINVAL;
120 
121 		return ltc2632_spi_write(st->spi_dev,
122 					 LTC2632_CMD_WRITE_INPUT_N_UPDATE_N,
123 					 chan->address, val,
124 					 chan->scan_type.shift);
125 	default:
126 		return -EINVAL;
127 	}
128 }
129 
130 static ssize_t ltc2632_read_dac_powerdown(struct iio_dev *indio_dev,
131 					  uintptr_t private,
132 					  const struct iio_chan_spec *chan,
133 					  char *buf)
134 {
135 	struct ltc2632_state *st = iio_priv(indio_dev);
136 
137 	return sysfs_emit(buf, "%d\n",
138 			  !!(st->powerdown_cache_mask & (1 << chan->channel)));
139 }
140 
141 static ssize_t ltc2632_write_dac_powerdown(struct iio_dev *indio_dev,
142 					   uintptr_t private,
143 					   const struct iio_chan_spec *chan,
144 					   const char *buf,
145 					   size_t len)
146 {
147 	bool pwr_down;
148 	int ret;
149 	struct ltc2632_state *st = iio_priv(indio_dev);
150 
151 	ret = kstrtobool(buf, &pwr_down);
152 	if (ret)
153 		return ret;
154 
155 	if (pwr_down)
156 		st->powerdown_cache_mask |= (1 << chan->channel);
157 	else
158 		st->powerdown_cache_mask &= ~(1 << chan->channel);
159 
160 	ret = ltc2632_spi_write(st->spi_dev,
161 				LTC2632_CMD_POWERDOWN_DAC_N,
162 				chan->channel, 0, 0);
163 
164 	return ret ? ret : len;
165 }
166 
167 static const struct iio_info ltc2632_info = {
168 	.write_raw	= ltc2632_write_raw,
169 	.read_raw	= ltc2632_read_raw,
170 };
171 
172 static const struct iio_chan_spec_ext_info ltc2632_ext_info[] = {
173 	{
174 		.name = "powerdown",
175 		.read = ltc2632_read_dac_powerdown,
176 		.write = ltc2632_write_dac_powerdown,
177 		.shared = IIO_SEPARATE,
178 	},
179 	{ },
180 };
181 
182 #define LTC2632_CHANNEL(_chan, _bits) { \
183 		.type = IIO_VOLTAGE, \
184 		.indexed = 1, \
185 		.output = 1, \
186 		.channel = (_chan), \
187 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
188 		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
189 		.address = (_chan), \
190 		.scan_type = { \
191 			.realbits	= (_bits), \
192 			.shift		= 16 - (_bits), \
193 		}, \
194 		.ext_info = ltc2632_ext_info, \
195 }
196 
197 #define DECLARE_LTC2632_CHANNELS(_name, _bits) \
198 	const struct iio_chan_spec _name ## _channels[] = { \
199 		LTC2632_CHANNEL(0, _bits), \
200 		LTC2632_CHANNEL(1, _bits), \
201 		LTC2632_CHANNEL(2, _bits), \
202 		LTC2632_CHANNEL(3, _bits), \
203 		LTC2632_CHANNEL(4, _bits), \
204 		LTC2632_CHANNEL(5, _bits), \
205 		LTC2632_CHANNEL(6, _bits), \
206 		LTC2632_CHANNEL(7, _bits), \
207 	}
208 
209 static DECLARE_LTC2632_CHANNELS(ltc2632x12, 12);
210 static DECLARE_LTC2632_CHANNELS(ltc2632x10, 10);
211 static DECLARE_LTC2632_CHANNELS(ltc2632x8, 8);
212 
213 static const struct ltc2632_chip_info ltc2632_chip_info_tbl[] = {
214 	[ID_LTC2632L12] = {
215 		.channels	= ltc2632x12_channels,
216 		.num_channels	= 2,
217 		.vref_mv	= 2500,
218 	},
219 	[ID_LTC2632L10] = {
220 		.channels	= ltc2632x10_channels,
221 		.num_channels	= 2,
222 		.vref_mv	= 2500,
223 	},
224 	[ID_LTC2632L8] =  {
225 		.channels	= ltc2632x8_channels,
226 		.num_channels	= 2,
227 		.vref_mv	= 2500,
228 	},
229 	[ID_LTC2632H12] = {
230 		.channels	= ltc2632x12_channels,
231 		.num_channels	= 2,
232 		.vref_mv	= 4096,
233 	},
234 	[ID_LTC2632H10] = {
235 		.channels	= ltc2632x10_channels,
236 		.num_channels	= 2,
237 		.vref_mv	= 4096,
238 	},
239 	[ID_LTC2632H8] =  {
240 		.channels	= ltc2632x8_channels,
241 		.num_channels	= 2,
242 		.vref_mv	= 4096,
243 	},
244 	[ID_LTC2634L12] = {
245 		.channels	= ltc2632x12_channels,
246 		.num_channels	= 4,
247 		.vref_mv	= 2500,
248 	},
249 	[ID_LTC2634L10] = {
250 		.channels	= ltc2632x10_channels,
251 		.num_channels	= 4,
252 		.vref_mv	= 2500,
253 	},
254 	[ID_LTC2634L8] =  {
255 		.channels	= ltc2632x8_channels,
256 		.num_channels	= 4,
257 		.vref_mv	= 2500,
258 	},
259 	[ID_LTC2634H12] = {
260 		.channels	= ltc2632x12_channels,
261 		.num_channels	= 4,
262 		.vref_mv	= 4096,
263 	},
264 	[ID_LTC2634H10] = {
265 		.channels	= ltc2632x10_channels,
266 		.num_channels	= 4,
267 		.vref_mv	= 4096,
268 	},
269 	[ID_LTC2634H8] =  {
270 		.channels	= ltc2632x8_channels,
271 		.num_channels	= 4,
272 		.vref_mv	= 4096,
273 	},
274 	[ID_LTC2636L12] = {
275 		.channels	= ltc2632x12_channels,
276 		.num_channels	= 8,
277 		.vref_mv	= 2500,
278 	},
279 	[ID_LTC2636L10] = {
280 		.channels	= ltc2632x10_channels,
281 		.num_channels	= 8,
282 		.vref_mv	= 2500,
283 	},
284 	[ID_LTC2636L8] =  {
285 		.channels	= ltc2632x8_channels,
286 		.num_channels	= 8,
287 		.vref_mv	= 2500,
288 	},
289 	[ID_LTC2636H12] = {
290 		.channels	= ltc2632x12_channels,
291 		.num_channels	= 8,
292 		.vref_mv	= 4096,
293 	},
294 	[ID_LTC2636H10] = {
295 		.channels	= ltc2632x10_channels,
296 		.num_channels	= 8,
297 		.vref_mv	= 4096,
298 	},
299 	[ID_LTC2636H8] =  {
300 		.channels	= ltc2632x8_channels,
301 		.num_channels	= 8,
302 		.vref_mv	= 4096,
303 	},
304 };
305 
306 static int ltc2632_probe(struct spi_device *spi)
307 {
308 	struct ltc2632_state *st;
309 	struct iio_dev *indio_dev;
310 	struct ltc2632_chip_info *chip_info;
311 	bool has_external_vref;
312 	int ret;
313 
314 	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
315 	if (!indio_dev)
316 		return -ENOMEM;
317 
318 	st = iio_priv(indio_dev);
319 
320 	st->spi_dev = spi;
321 
322 	chip_info = (struct ltc2632_chip_info *)
323 			spi_get_device_id(spi)->driver_data;
324 
325 	ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vref");
326 	if (ret < 0 && ret != -ENODEV)
327 		return dev_err_probe(&spi->dev, ret,
328 				     "Failed to get vref regulator voltage\n");
329 
330 	has_external_vref = ret != -ENODEV;
331 	st->vref_mv = has_external_vref ? ret / 1000 : chip_info->vref_mv;
332 
333 	if (has_external_vref) {
334 		ret = ltc2632_spi_write(spi, LTC2632_CMD_EXTERNAL_REFER,
335 					0, 0, 0);
336 		if (ret)
337 			return dev_err_probe(&spi->dev, ret,
338 				"Set external reference command failed\n");
339 	} else {
340 		ret = ltc2632_spi_write(spi, LTC2632_CMD_INTERNAL_REFER,
341 					0, 0, 0);
342 		if (ret)
343 			return dev_err_probe(&spi->dev, ret,
344 				"Set internal reference command failed\n");
345 	}
346 
347 	indio_dev->name = fwnode_get_name(dev_fwnode(&spi->dev)) ?: spi_get_device_id(spi)->name;
348 	indio_dev->info = &ltc2632_info;
349 	indio_dev->modes = INDIO_DIRECT_MODE;
350 	indio_dev->channels = chip_info->channels;
351 	indio_dev->num_channels = chip_info->num_channels;
352 
353 	return devm_iio_device_register(&spi->dev, indio_dev);
354 }
355 
356 static const struct spi_device_id ltc2632_id[] = {
357 	{ "ltc2632-l12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632L12] },
358 	{ "ltc2632-l10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632L10] },
359 	{ "ltc2632-l8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632L8] },
360 	{ "ltc2632-h12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632H12] },
361 	{ "ltc2632-h10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632H10] },
362 	{ "ltc2632-h8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2632H8] },
363 	{ "ltc2634-l12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2634L12] },
364 	{ "ltc2634-l10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2634L10] },
365 	{ "ltc2634-l8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2634L8] },
366 	{ "ltc2634-h12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2634H12] },
367 	{ "ltc2634-h10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2634H10] },
368 	{ "ltc2634-h8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2634H8] },
369 	{ "ltc2636-l12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2636L12] },
370 	{ "ltc2636-l10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2636L10] },
371 	{ "ltc2636-l8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2636L8] },
372 	{ "ltc2636-h12", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2636H12] },
373 	{ "ltc2636-h10", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2636H10] },
374 	{ "ltc2636-h8", (kernel_ulong_t)&ltc2632_chip_info_tbl[ID_LTC2636H8] },
375 	{}
376 };
377 MODULE_DEVICE_TABLE(spi, ltc2632_id);
378 
379 static const struct of_device_id ltc2632_of_match[] = {
380 	{
381 		.compatible = "lltc,ltc2632-l12",
382 		.data = &ltc2632_chip_info_tbl[ID_LTC2632L12]
383 	}, {
384 		.compatible = "lltc,ltc2632-l10",
385 		.data = &ltc2632_chip_info_tbl[ID_LTC2632L10]
386 	}, {
387 		.compatible = "lltc,ltc2632-l8",
388 		.data = &ltc2632_chip_info_tbl[ID_LTC2632L8]
389 	}, {
390 		.compatible = "lltc,ltc2632-h12",
391 		.data = &ltc2632_chip_info_tbl[ID_LTC2632H12]
392 	}, {
393 		.compatible = "lltc,ltc2632-h10",
394 		.data = &ltc2632_chip_info_tbl[ID_LTC2632H10]
395 	}, {
396 		.compatible = "lltc,ltc2632-h8",
397 		.data = &ltc2632_chip_info_tbl[ID_LTC2632H8]
398 	}, {
399 		.compatible = "lltc,ltc2634-l12",
400 		.data = &ltc2632_chip_info_tbl[ID_LTC2634L12]
401 	}, {
402 		.compatible = "lltc,ltc2634-l10",
403 		.data = &ltc2632_chip_info_tbl[ID_LTC2634L10]
404 	}, {
405 		.compatible = "lltc,ltc2634-l8",
406 		.data = &ltc2632_chip_info_tbl[ID_LTC2634L8]
407 	}, {
408 		.compatible = "lltc,ltc2634-h12",
409 		.data = &ltc2632_chip_info_tbl[ID_LTC2634H12]
410 	}, {
411 		.compatible = "lltc,ltc2634-h10",
412 		.data = &ltc2632_chip_info_tbl[ID_LTC2634H10]
413 	}, {
414 		.compatible = "lltc,ltc2634-h8",
415 		.data = &ltc2632_chip_info_tbl[ID_LTC2634H8]
416 	}, {
417 		.compatible = "lltc,ltc2636-l12",
418 		.data = &ltc2632_chip_info_tbl[ID_LTC2636L12]
419 	}, {
420 		.compatible = "lltc,ltc2636-l10",
421 		.data = &ltc2632_chip_info_tbl[ID_LTC2636L10]
422 	}, {
423 		.compatible = "lltc,ltc2636-l8",
424 		.data = &ltc2632_chip_info_tbl[ID_LTC2636L8]
425 	}, {
426 		.compatible = "lltc,ltc2636-h12",
427 		.data = &ltc2632_chip_info_tbl[ID_LTC2636H12]
428 	}, {
429 		.compatible = "lltc,ltc2636-h10",
430 		.data = &ltc2632_chip_info_tbl[ID_LTC2636H10]
431 	}, {
432 		.compatible = "lltc,ltc2636-h8",
433 		.data = &ltc2632_chip_info_tbl[ID_LTC2636H8]
434 	},
435 	{}
436 };
437 MODULE_DEVICE_TABLE(of, ltc2632_of_match);
438 
439 static struct spi_driver ltc2632_driver = {
440 	.driver		= {
441 		.name	= "ltc2632",
442 		.of_match_table = ltc2632_of_match,
443 	},
444 	.probe		= ltc2632_probe,
445 	.id_table	= ltc2632_id,
446 };
447 module_spi_driver(ltc2632_driver);
448 
449 MODULE_AUTHOR("Maxime Roussin-Belanger <maxime.roussinbelanger@gmail.com>");
450 MODULE_DESCRIPTION("LTC2632 DAC SPI driver");
451 MODULE_LICENSE("GPL v2");
452