1 // SPDX-License-Identifier: GPL-2.0-only
3 * ti-dac082s085.c - Texas Instruments 8/10/12-bit 2/4-channel DAC driver
5 * Copyright (C) 2017 KUNBUS GmbH
7 * http://www.ti.com/lit/ds/symlink/dac082s085.pdf
8 * http://www.ti.com/lit/ds/symlink/dac102s085.pdf
9 * http://www.ti.com/lit/ds/symlink/dac122s085.pdf
10 * http://www.ti.com/lit/ds/symlink/dac084s085.pdf
11 * http://www.ti.com/lit/ds/symlink/dac104s085.pdf
12 * http://www.ti.com/lit/ds/symlink/dac124s085.pdf
15 #include <linux/iio/iio.h>
16 #include <linux/module.h>
17 #include <linux/regulator/consumer.h>
18 #include <linux/spi/spi.h>
20 enum { dual_8bit
, dual_10bit
, dual_12bit
, quad_8bit
, quad_10bit
, quad_12bit
};
27 static const struct ti_dac_spec ti_dac_spec
[] = {
28 [dual_8bit
] = { .num_channels
= 2, .resolution
= 8 },
29 [dual_10bit
] = { .num_channels
= 2, .resolution
= 10 },
30 [dual_12bit
] = { .num_channels
= 2, .resolution
= 12 },
31 [quad_8bit
] = { .num_channels
= 4, .resolution
= 8 },
32 [quad_10bit
] = { .num_channels
= 4, .resolution
= 10 },
33 [quad_12bit
] = { .num_channels
= 4, .resolution
= 12 },
37 * struct ti_dac_chip - TI DAC chip
38 * @lock: protects write sequences
39 * @vref: regulator generating Vref
40 * @mesg: SPI message to perform a write
41 * @xfer: SPI transfer used by @mesg
42 * @val: cached value of each output
43 * @powerdown: whether the chip is powered down
44 * @powerdown_mode: selected by the user
45 * @resolution: resolution of the chip
46 * @buf: buffer for @xfer
50 struct regulator
*vref
;
51 struct spi_message mesg
;
52 struct spi_transfer xfer
;
57 u8 buf
[2] ____cacheline_aligned
;
60 #define WRITE_NOT_UPDATE(chan) (0x00 | (chan) << 6)
61 #define WRITE_AND_UPDATE(chan) (0x10 | (chan) << 6)
62 #define WRITE_ALL_UPDATE 0x20
63 #define POWERDOWN(mode) (0x30 | ((mode) + 1) << 6)
65 static int ti_dac_cmd(struct ti_dac_chip
*ti_dac
, u8 cmd
, u16 val
)
67 u8 shift
= 12 - ti_dac
->resolution
;
69 ti_dac
->buf
[0] = cmd
| (val
>> (8 - shift
));
70 ti_dac
->buf
[1] = (val
<< shift
) & 0xff;
71 return spi_sync(ti_dac
->mesg
.spi
, &ti_dac
->mesg
);
74 static const char * const ti_dac_powerdown_modes
[] = {
75 "2.5kohm_to_gnd", "100kohm_to_gnd", "three_state",
78 static int ti_dac_get_powerdown_mode(struct iio_dev
*indio_dev
,
79 const struct iio_chan_spec
*chan
)
81 struct ti_dac_chip
*ti_dac
= iio_priv(indio_dev
);
83 return ti_dac
->powerdown_mode
;
86 static int ti_dac_set_powerdown_mode(struct iio_dev
*indio_dev
,
87 const struct iio_chan_spec
*chan
,
90 struct ti_dac_chip
*ti_dac
= iio_priv(indio_dev
);
93 if (ti_dac
->powerdown_mode
== mode
)
96 mutex_lock(&ti_dac
->lock
);
97 if (ti_dac
->powerdown
) {
98 ret
= ti_dac_cmd(ti_dac
, POWERDOWN(mode
), 0);
102 ti_dac
->powerdown_mode
= mode
;
105 mutex_unlock(&ti_dac
->lock
);
109 static const struct iio_enum ti_dac_powerdown_mode
= {
110 .items
= ti_dac_powerdown_modes
,
111 .num_items
= ARRAY_SIZE(ti_dac_powerdown_modes
),
112 .get
= ti_dac_get_powerdown_mode
,
113 .set
= ti_dac_set_powerdown_mode
,
116 static ssize_t
ti_dac_read_powerdown(struct iio_dev
*indio_dev
,
118 const struct iio_chan_spec
*chan
,
121 struct ti_dac_chip
*ti_dac
= iio_priv(indio_dev
);
123 return sprintf(buf
, "%d\n", ti_dac
->powerdown
);
126 static ssize_t
ti_dac_write_powerdown(struct iio_dev
*indio_dev
,
128 const struct iio_chan_spec
*chan
,
129 const char *buf
, size_t len
)
131 struct ti_dac_chip
*ti_dac
= iio_priv(indio_dev
);
135 ret
= strtobool(buf
, &powerdown
);
139 if (ti_dac
->powerdown
== powerdown
)
142 mutex_lock(&ti_dac
->lock
);
144 ret
= ti_dac_cmd(ti_dac
, POWERDOWN(ti_dac
->powerdown_mode
), 0);
146 ret
= ti_dac_cmd(ti_dac
, WRITE_AND_UPDATE(0), ti_dac
->val
[0]);
148 ti_dac
->powerdown
= powerdown
;
149 mutex_unlock(&ti_dac
->lock
);
151 return ret
? ret
: len
;
154 static const struct iio_chan_spec_ext_info ti_dac_ext_info
[] = {
157 .read
= ti_dac_read_powerdown
,
158 .write
= ti_dac_write_powerdown
,
159 .shared
= IIO_SHARED_BY_TYPE
,
161 IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE
, &ti_dac_powerdown_mode
),
162 IIO_ENUM_AVAILABLE("powerdown_mode", &ti_dac_powerdown_mode
),
166 #define TI_DAC_CHANNEL(chan) { \
167 .type = IIO_VOLTAGE, \
172 .datasheet_name = (const char[]){ 'A' + (chan), 0 }, \
173 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
174 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
175 .ext_info = ti_dac_ext_info, \
178 static const struct iio_chan_spec ti_dac_channels
[] = {
185 static int ti_dac_read_raw(struct iio_dev
*indio_dev
,
186 struct iio_chan_spec
const *chan
,
187 int *val
, int *val2
, long mask
)
189 struct ti_dac_chip
*ti_dac
= iio_priv(indio_dev
);
193 case IIO_CHAN_INFO_RAW
:
194 *val
= ti_dac
->val
[chan
->channel
];
198 case IIO_CHAN_INFO_SCALE
:
199 ret
= regulator_get_voltage(ti_dac
->vref
);
204 *val2
= ti_dac
->resolution
;
205 ret
= IIO_VAL_FRACTIONAL_LOG2
;
215 static int ti_dac_write_raw(struct iio_dev
*indio_dev
,
216 struct iio_chan_spec
const *chan
,
217 int val
, int val2
, long mask
)
219 struct ti_dac_chip
*ti_dac
= iio_priv(indio_dev
);
223 case IIO_CHAN_INFO_RAW
:
224 if (ti_dac
->val
[chan
->channel
] == val
)
227 if (val
>= (1 << ti_dac
->resolution
) || val
< 0)
230 if (ti_dac
->powerdown
)
233 mutex_lock(&ti_dac
->lock
);
234 ret
= ti_dac_cmd(ti_dac
, WRITE_AND_UPDATE(chan
->channel
), val
);
236 ti_dac
->val
[chan
->channel
] = val
;
237 mutex_unlock(&ti_dac
->lock
);
247 static int ti_dac_write_raw_get_fmt(struct iio_dev
*indio_dev
,
248 struct iio_chan_spec
const *chan
, long mask
)
253 static const struct iio_info ti_dac_info
= {
254 .read_raw
= ti_dac_read_raw
,
255 .write_raw
= ti_dac_write_raw
,
256 .write_raw_get_fmt
= ti_dac_write_raw_get_fmt
,
259 static int ti_dac_probe(struct spi_device
*spi
)
261 struct device
*dev
= &spi
->dev
;
262 const struct ti_dac_spec
*spec
;
263 struct ti_dac_chip
*ti_dac
;
264 struct iio_dev
*indio_dev
;
267 indio_dev
= devm_iio_device_alloc(dev
, sizeof(*ti_dac
));
271 indio_dev
->dev
.parent
= dev
;
272 indio_dev
->info
= &ti_dac_info
;
273 indio_dev
->name
= spi
->modalias
;
274 indio_dev
->modes
= INDIO_DIRECT_MODE
;
275 indio_dev
->channels
= ti_dac_channels
;
276 spi_set_drvdata(spi
, indio_dev
);
278 ti_dac
= iio_priv(indio_dev
);
279 ti_dac
->xfer
.tx_buf
= &ti_dac
->buf
;
280 ti_dac
->xfer
.len
= sizeof(ti_dac
->buf
);
281 spi_message_init_with_transfers(&ti_dac
->mesg
, &ti_dac
->xfer
, 1);
282 ti_dac
->mesg
.spi
= spi
;
284 spec
= &ti_dac_spec
[spi_get_device_id(spi
)->driver_data
];
285 indio_dev
->num_channels
= spec
->num_channels
;
286 ti_dac
->resolution
= spec
->resolution
;
288 ti_dac
->vref
= devm_regulator_get(dev
, "vref");
289 if (IS_ERR(ti_dac
->vref
))
290 return PTR_ERR(ti_dac
->vref
);
292 ret
= regulator_enable(ti_dac
->vref
);
296 mutex_init(&ti_dac
->lock
);
298 ret
= ti_dac_cmd(ti_dac
, WRITE_ALL_UPDATE
, 0);
300 dev_err(dev
, "failed to initialize outputs to 0\n");
304 ret
= iio_device_register(indio_dev
);
311 mutex_destroy(&ti_dac
->lock
);
312 regulator_disable(ti_dac
->vref
);
316 static int ti_dac_remove(struct spi_device
*spi
)
318 struct iio_dev
*indio_dev
= spi_get_drvdata(spi
);
319 struct ti_dac_chip
*ti_dac
= iio_priv(indio_dev
);
321 iio_device_unregister(indio_dev
);
322 mutex_destroy(&ti_dac
->lock
);
323 regulator_disable(ti_dac
->vref
);
329 static const struct of_device_id ti_dac_of_id
[] = {
330 { .compatible
= "ti,dac082s085" },
331 { .compatible
= "ti,dac102s085" },
332 { .compatible
= "ti,dac122s085" },
333 { .compatible
= "ti,dac084s085" },
334 { .compatible
= "ti,dac104s085" },
335 { .compatible
= "ti,dac124s085" },
338 MODULE_DEVICE_TABLE(of
, ti_dac_of_id
);
341 static const struct spi_device_id ti_dac_spi_id
[] = {
342 { "dac082s085", dual_8bit
},
343 { "dac102s085", dual_10bit
},
344 { "dac122s085", dual_12bit
},
345 { "dac084s085", quad_8bit
},
346 { "dac104s085", quad_10bit
},
347 { "dac124s085", quad_12bit
},
350 MODULE_DEVICE_TABLE(spi
, ti_dac_spi_id
);
352 static struct spi_driver ti_dac_driver
= {
354 .name
= "ti-dac082s085",
355 .of_match_table
= of_match_ptr(ti_dac_of_id
),
357 .probe
= ti_dac_probe
,
358 .remove
= ti_dac_remove
,
359 .id_table
= ti_dac_spi_id
,
361 module_spi_driver(ti_dac_driver
);
363 MODULE_AUTHOR("Lukas Wunner <lukas@wunner.de>");
364 MODULE_DESCRIPTION("Texas Instruments 8/10/12-bit 2/4-channel DAC driver");
365 MODULE_LICENSE("GPL v2");