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
ltc2632_spi_write(struct spi_device * spi,u8 cmd,u8 addr,u16 val,u8 shift)51 static int ltc2632_spi_write(struct spi_device *spi,
52 u8 cmd, u8 addr, u16 val, u8 shift)
53 {
54 u32 data;
55 u8 msg[3];
56
57 /*
58 * The input shift register is 24 bits wide.
59 * The next four are the command bits, C3 to C0,
60 * followed by the 4-bit DAC address, A3 to A0, and then the
61 * 16-, 12-, 10-, 8-bit data-word. The data-word comprises the
62 * 16-, 12-, 10-, 8-bit input code followed by 0, 4, 6, or 8
63 * don't care bits.
64 */
65 data = (cmd << 20) | (addr << 16) | (val << shift);
66 put_unaligned_be24(data, &msg[0]);
67
68 return spi_write(spi, msg, sizeof(msg));
69 }
70
ltc2632_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long m)71 static int ltc2632_read_raw(struct iio_dev *indio_dev,
72 struct iio_chan_spec const *chan,
73 int *val,
74 int *val2,
75 long m)
76 {
77 const struct ltc2632_state *st = iio_priv(indio_dev);
78
79 switch (m) {
80 case IIO_CHAN_INFO_SCALE:
81 *val = st->vref_mv;
82 *val2 = chan->scan_type.realbits;
83 return IIO_VAL_FRACTIONAL_LOG2;
84 }
85 return -EINVAL;
86 }
87
ltc2632_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)88 static int ltc2632_write_raw(struct iio_dev *indio_dev,
89 struct iio_chan_spec const *chan,
90 int val,
91 int val2,
92 long mask)
93 {
94 struct ltc2632_state *st = iio_priv(indio_dev);
95
96 switch (mask) {
97 case IIO_CHAN_INFO_RAW:
98 if (val >= (1 << chan->scan_type.realbits) || val < 0)
99 return -EINVAL;
100
101 return ltc2632_spi_write(st->spi_dev,
102 LTC2632_CMD_WRITE_INPUT_N_UPDATE_N,
103 chan->address, val,
104 chan->scan_type.shift);
105 default:
106 return -EINVAL;
107 }
108 }
109
ltc2632_read_dac_powerdown(struct iio_dev * indio_dev,uintptr_t private,const struct iio_chan_spec * chan,char * buf)110 static ssize_t ltc2632_read_dac_powerdown(struct iio_dev *indio_dev,
111 uintptr_t private,
112 const struct iio_chan_spec *chan,
113 char *buf)
114 {
115 struct ltc2632_state *st = iio_priv(indio_dev);
116
117 return sysfs_emit(buf, "%d\n",
118 !!(st->powerdown_cache_mask & (1 << chan->channel)));
119 }
120
ltc2632_write_dac_powerdown(struct iio_dev * indio_dev,uintptr_t private,const struct iio_chan_spec * chan,const char * buf,size_t len)121 static ssize_t ltc2632_write_dac_powerdown(struct iio_dev *indio_dev,
122 uintptr_t private,
123 const struct iio_chan_spec *chan,
124 const char *buf,
125 size_t len)
126 {
127 bool pwr_down;
128 int ret;
129 struct ltc2632_state *st = iio_priv(indio_dev);
130
131 ret = kstrtobool(buf, &pwr_down);
132 if (ret)
133 return ret;
134
135 if (pwr_down)
136 st->powerdown_cache_mask |= (1 << chan->channel);
137 else
138 st->powerdown_cache_mask &= ~(1 << chan->channel);
139
140 ret = ltc2632_spi_write(st->spi_dev,
141 LTC2632_CMD_POWERDOWN_DAC_N,
142 chan->channel, 0, 0);
143
144 return ret ? ret : len;
145 }
146
147 static const struct iio_info ltc2632_info = {
148 .write_raw = ltc2632_write_raw,
149 .read_raw = ltc2632_read_raw,
150 };
151
152 static const struct iio_chan_spec_ext_info ltc2632_ext_info[] = {
153 {
154 .name = "powerdown",
155 .read = ltc2632_read_dac_powerdown,
156 .write = ltc2632_write_dac_powerdown,
157 .shared = IIO_SEPARATE,
158 },
159 { }
160 };
161
162 #define LTC2632_CHANNEL(_chan, _bits) { \
163 .type = IIO_VOLTAGE, \
164 .indexed = 1, \
165 .output = 1, \
166 .channel = (_chan), \
167 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
168 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
169 .address = (_chan), \
170 .scan_type = { \
171 .realbits = (_bits), \
172 .shift = 16 - (_bits), \
173 }, \
174 .ext_info = ltc2632_ext_info, \
175 }
176
177 #define DECLARE_LTC2632_CHANNELS(_name, _bits) \
178 const struct iio_chan_spec _name ## _channels[] = { \
179 LTC2632_CHANNEL(0, _bits), \
180 LTC2632_CHANNEL(1, _bits), \
181 LTC2632_CHANNEL(2, _bits), \
182 LTC2632_CHANNEL(3, _bits), \
183 LTC2632_CHANNEL(4, _bits), \
184 LTC2632_CHANNEL(5, _bits), \
185 LTC2632_CHANNEL(6, _bits), \
186 LTC2632_CHANNEL(7, _bits), \
187 }
188
189 static DECLARE_LTC2632_CHANNELS(ltc2632x16, 16);
190 static DECLARE_LTC2632_CHANNELS(ltc2632x12, 12);
191 static DECLARE_LTC2632_CHANNELS(ltc2632x10, 10);
192 static DECLARE_LTC2632_CHANNELS(ltc2632x8, 8);
193
194 static const struct ltc2632_chip_info ltc2632l12_chip_info = {
195 .channels = ltc2632x12_channels,
196 .num_channels = 2,
197 .vref_mv = 2500,
198 };
199
200 static const struct ltc2632_chip_info ltc2632l10_chip_info = {
201 .channels = ltc2632x10_channels,
202 .num_channels = 2,
203 .vref_mv = 2500,
204 };
205
206 static const struct ltc2632_chip_info ltc2632l8_chip_info = {
207 .channels = ltc2632x8_channels,
208 .num_channels = 2,
209 .vref_mv = 2500,
210 };
211
212 static const struct ltc2632_chip_info ltc2632h12_chip_info = {
213 .channels = ltc2632x12_channels,
214 .num_channels = 2,
215 .vref_mv = 4096,
216 };
217
218 static const struct ltc2632_chip_info ltc2632h10_chip_info = {
219 .channels = ltc2632x10_channels,
220 .num_channels = 2,
221 .vref_mv = 4096,
222 };
223
224 static const struct ltc2632_chip_info ltc2632h8_chip_info = {
225 .channels = ltc2632x8_channels,
226 .num_channels = 2,
227 .vref_mv = 4096,
228 };
229
230 static const struct ltc2632_chip_info ltc2634l12_chip_info = {
231 .channels = ltc2632x12_channels,
232 .num_channels = 4,
233 .vref_mv = 2500,
234 };
235
236 static const struct ltc2632_chip_info ltc2634l10_chip_info = {
237 .channels = ltc2632x10_channels,
238 .num_channels = 4,
239 .vref_mv = 2500,
240 };
241
242 static const struct ltc2632_chip_info ltc2634l8_chip_info = {
243 .channels = ltc2632x8_channels,
244 .num_channels = 4,
245 .vref_mv = 2500,
246 };
247
248 static const struct ltc2632_chip_info ltc2634h12_chip_info = {
249 .channels = ltc2632x12_channels,
250 .num_channels = 4,
251 .vref_mv = 4096,
252 };
253
254 static const struct ltc2632_chip_info ltc2634h10_chip_info = {
255 .channels = ltc2632x10_channels,
256 .num_channels = 4,
257 .vref_mv = 4096,
258 };
259
260 static const struct ltc2632_chip_info ltc2634h8_chip_info = {
261 .channels = ltc2632x8_channels,
262 .num_channels = 4,
263 .vref_mv = 4096,
264 };
265
266 static const struct ltc2632_chip_info ltc2636l12_chip_info = {
267 .channels = ltc2632x12_channels,
268 .num_channels = 8,
269 .vref_mv = 2500,
270 };
271
272 static const struct ltc2632_chip_info ltc2636l10_chip_info = {
273 .channels = ltc2632x10_channels,
274 .num_channels = 8,
275 .vref_mv = 2500,
276 };
277
278 static const struct ltc2632_chip_info ltc2636l8_chip_info = {
279 .channels = ltc2632x8_channels,
280 .num_channels = 8,
281 .vref_mv = 2500,
282 };
283
284 static const struct ltc2632_chip_info ltc2636h12_chip_info = {
285 .channels = ltc2632x12_channels,
286 .num_channels = 8,
287 .vref_mv = 4096,
288 };
289
290 static const struct ltc2632_chip_info ltc2636h10_chip_info = {
291 .channels = ltc2632x10_channels,
292 .num_channels = 8,
293 .vref_mv = 4096,
294 };
295
296 static const struct ltc2632_chip_info ltc2636h8_chip_info = {
297 .channels = ltc2632x8_channels,
298 .num_channels = 8,
299 .vref_mv = 4096,
300 };
301
302 static const struct ltc2632_chip_info ltc2654l16_chip_info = {
303 .channels = ltc2632x16_channels,
304 .num_channels = 4,
305 .vref_mv = 2500,
306 };
307
308 static const struct ltc2632_chip_info ltc2654h16_chip_info = {
309 .channels = ltc2632x16_channels,
310 .num_channels = 4,
311 .vref_mv = 4096,
312 };
313
ltc2632_probe(struct spi_device * spi)314 static int ltc2632_probe(struct spi_device *spi)
315 {
316 struct ltc2632_state *st;
317 struct iio_dev *indio_dev;
318 struct ltc2632_chip_info *chip_info;
319 bool has_external_vref;
320 int ret;
321
322 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
323 if (!indio_dev)
324 return -ENOMEM;
325
326 st = iio_priv(indio_dev);
327
328 st->spi_dev = spi;
329
330 chip_info = (struct ltc2632_chip_info *)
331 spi_get_device_id(spi)->driver_data;
332
333 ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vref");
334 if (ret < 0 && ret != -ENODEV)
335 return dev_err_probe(&spi->dev, ret,
336 "Failed to get vref regulator voltage\n");
337
338 has_external_vref = ret != -ENODEV;
339 st->vref_mv = has_external_vref ? ret / 1000 : chip_info->vref_mv;
340
341 if (has_external_vref) {
342 ret = ltc2632_spi_write(spi, LTC2632_CMD_EXTERNAL_REFER,
343 0, 0, 0);
344 if (ret)
345 return dev_err_probe(&spi->dev, ret,
346 "Set external reference command failed\n");
347 } else {
348 ret = ltc2632_spi_write(spi, LTC2632_CMD_INTERNAL_REFER,
349 0, 0, 0);
350 if (ret)
351 return dev_err_probe(&spi->dev, ret,
352 "Set internal reference command failed\n");
353 }
354
355 indio_dev->name = fwnode_get_name(dev_fwnode(&spi->dev)) ?: spi_get_device_id(spi)->name;
356 indio_dev->info = <c2632_info;
357 indio_dev->modes = INDIO_DIRECT_MODE;
358 indio_dev->channels = chip_info->channels;
359 indio_dev->num_channels = chip_info->num_channels;
360
361 return devm_iio_device_register(&spi->dev, indio_dev);
362 }
363
364 static const struct spi_device_id ltc2632_id[] = {
365 { "ltc2632-l12", (kernel_ulong_t)<c2632l12_chip_info },
366 { "ltc2632-l10", (kernel_ulong_t)<c2632l10_chip_info },
367 { "ltc2632-l8", (kernel_ulong_t)<c2632l8_chip_info },
368 { "ltc2632-h12", (kernel_ulong_t)<c2632h12_chip_info },
369 { "ltc2632-h10", (kernel_ulong_t)<c2632h10_chip_info },
370 { "ltc2632-h8", (kernel_ulong_t)<c2632h8_chip_info },
371 { "ltc2634-l12", (kernel_ulong_t)<c2634l12_chip_info },
372 { "ltc2634-l10", (kernel_ulong_t)<c2634l10_chip_info },
373 { "ltc2634-l8", (kernel_ulong_t)<c2634l8_chip_info },
374 { "ltc2634-h12", (kernel_ulong_t)<c2634h12_chip_info },
375 { "ltc2634-h10", (kernel_ulong_t)<c2634h10_chip_info },
376 { "ltc2634-h8", (kernel_ulong_t)<c2634h8_chip_info },
377 { "ltc2636-l12", (kernel_ulong_t)<c2636l12_chip_info },
378 { "ltc2636-l10", (kernel_ulong_t)<c2636l10_chip_info },
379 { "ltc2636-l8", (kernel_ulong_t)<c2636l8_chip_info },
380 { "ltc2636-h12", (kernel_ulong_t)<c2636h12_chip_info },
381 { "ltc2636-h10", (kernel_ulong_t)<c2636h10_chip_info },
382 { "ltc2636-h8", (kernel_ulong_t)<c2636h8_chip_info },
383 { "ltc2654-l16", (kernel_ulong_t)<c2654l16_chip_info },
384 { "ltc2654-l12", (kernel_ulong_t)<c2634l12_chip_info },
385 { "ltc2654-h16", (kernel_ulong_t)<c2654h16_chip_info },
386 { "ltc2654-h12", (kernel_ulong_t)<c2634h12_chip_info },
387 { }
388 };
389 MODULE_DEVICE_TABLE(spi, ltc2632_id);
390
391 static const struct of_device_id ltc2632_of_match[] = {
392 { .compatible = "lltc,ltc2632-l12", .data = <c2632l12_chip_info },
393 { .compatible = "lltc,ltc2632-l10", .data = <c2632l10_chip_info },
394 { .compatible = "lltc,ltc2632-l8", .data = <c2632l8_chip_info },
395 { .compatible = "lltc,ltc2632-h12", .data = <c2632h12_chip_info },
396 { .compatible = "lltc,ltc2632-h10", .data = <c2632h10_chip_info },
397 { .compatible = "lltc,ltc2632-h8", .data = <c2632h8_chip_info },
398 { .compatible = "lltc,ltc2634-l12", .data = <c2634l12_chip_info },
399 { .compatible = "lltc,ltc2634-l10", .data = <c2634l10_chip_info },
400 { .compatible = "lltc,ltc2634-l8", .data = <c2634l8_chip_info },
401 { .compatible = "lltc,ltc2634-h12", .data = <c2634h12_chip_info },
402 { .compatible = "lltc,ltc2634-h10", .data = <c2634h10_chip_info },
403 { .compatible = "lltc,ltc2634-h8", .data = <c2634h8_chip_info },
404 { .compatible = "lltc,ltc2636-l12", .data = <c2636l12_chip_info },
405 { .compatible = "lltc,ltc2636-l10", .data = <c2636l10_chip_info },
406 { .compatible = "lltc,ltc2636-l8", .data = <c2636l8_chip_info },
407 { .compatible = "lltc,ltc2636-h12", .data = <c2636h12_chip_info },
408 { .compatible = "lltc,ltc2636-h10", .data = <c2636h10_chip_info },
409 { .compatible = "lltc,ltc2636-h8", .data = <c2636h8_chip_info },
410 { .compatible = "lltc,ltc2654-l16", .data = <c2654l16_chip_info },
411 { .compatible = "lltc,ltc2654-h16", .data = <c2654h16_chip_info },
412 { }
413 };
414 MODULE_DEVICE_TABLE(of, ltc2632_of_match);
415
416 static struct spi_driver ltc2632_driver = {
417 .driver = {
418 .name = "ltc2632",
419 .of_match_table = ltc2632_of_match,
420 },
421 .probe = ltc2632_probe,
422 .id_table = ltc2632_id,
423 };
424 module_spi_driver(ltc2632_driver);
425
426 MODULE_AUTHOR("Maxime Roussin-Belanger <maxime.roussinbelanger@gmail.com>");
427 MODULE_DESCRIPTION("LTC2632 and similar DAC SPI driver");
428 MODULE_LICENSE("GPL v2");
429