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 * https://www.ti.com/lit/ds/symlink/dac082s085.pdf
8 * https://www.ti.com/lit/ds/symlink/dac102s085.pdf
9 * https://www.ti.com/lit/ds/symlink/dac122s085.pdf
10 * https://www.ti.com/lit/ds/symlink/dac084s085.pdf
11 * https://www.ti.com/lit/ds/symlink/dac104s085.pdf
12 * https://www.ti.com/lit/ds/symlink/dac124s085.pdf
15 #include <linux/iio/iio.h>
16 #include <linux/module.h>
17 #include <linux/mod_devicetable.h>
18 #include <linux/regulator/consumer.h>
19 #include <linux/spi/spi.h>
21 enum { dual_8bit
, dual_10bit
, dual_12bit
, quad_8bit
, quad_10bit
, quad_12bit
};
28 static const struct ti_dac_spec ti_dac_spec
[] = {
29 [dual_8bit
] = { .num_channels
= 2, .resolution
= 8 },
30 [dual_10bit
] = { .num_channels
= 2, .resolution
= 10 },
31 [dual_12bit
] = { .num_channels
= 2, .resolution
= 12 },
32 [quad_8bit
] = { .num_channels
= 4, .resolution
= 8 },
33 [quad_10bit
] = { .num_channels
= 4, .resolution
= 10 },
34 [quad_12bit
] = { .num_channels
= 4, .resolution
= 12 },
38 * struct ti_dac_chip - TI DAC chip
39 * @lock: protects write sequences
40 * @vref: regulator generating Vref
41 * @mesg: SPI message to perform a write
42 * @xfer: SPI transfer used by @mesg
43 * @val: cached value of each output
44 * @powerdown: whether the chip is powered down
45 * @powerdown_mode: selected by the user
46 * @resolution: resolution of the chip
47 * @buf: buffer for @xfer
51 struct regulator
*vref
;
52 struct spi_message mesg
;
53 struct spi_transfer xfer
;
58 u8 buf
[2] ____cacheline_aligned
;
61 #define WRITE_NOT_UPDATE(chan) (0x00 | (chan) << 6)
62 #define WRITE_AND_UPDATE(chan) (0x10 | (chan) << 6)
63 #define WRITE_ALL_UPDATE 0x20
64 #define POWERDOWN(mode) (0x30 | ((mode) + 1) << 6)
66 static int ti_dac_cmd(struct ti_dac_chip
*ti_dac
, u8 cmd
, u16 val
)
68 u8 shift
= 12 - ti_dac
->resolution
;
70 ti_dac
->buf
[0] = cmd
| (val
>> (8 - shift
));
71 ti_dac
->buf
[1] = (val
<< shift
) & 0xff;
72 return spi_sync(ti_dac
->mesg
.spi
, &ti_dac
->mesg
);
75 static const char * const ti_dac_powerdown_modes
[] = {
76 "2.5kohm_to_gnd", "100kohm_to_gnd", "three_state",
79 static int ti_dac_get_powerdown_mode(struct iio_dev
*indio_dev
,
80 const struct iio_chan_spec
*chan
)
82 struct ti_dac_chip
*ti_dac
= iio_priv(indio_dev
);
84 return ti_dac
->powerdown_mode
;
87 static int ti_dac_set_powerdown_mode(struct iio_dev
*indio_dev
,
88 const struct iio_chan_spec
*chan
,
91 struct ti_dac_chip
*ti_dac
= iio_priv(indio_dev
);
94 if (ti_dac
->powerdown_mode
== mode
)
97 mutex_lock(&ti_dac
->lock
);
98 if (ti_dac
->powerdown
) {
99 ret
= ti_dac_cmd(ti_dac
, POWERDOWN(mode
), 0);
103 ti_dac
->powerdown_mode
= mode
;
106 mutex_unlock(&ti_dac
->lock
);
110 static const struct iio_enum ti_dac_powerdown_mode
= {
111 .items
= ti_dac_powerdown_modes
,
112 .num_items
= ARRAY_SIZE(ti_dac_powerdown_modes
),
113 .get
= ti_dac_get_powerdown_mode
,
114 .set
= ti_dac_set_powerdown_mode
,
117 static ssize_t
ti_dac_read_powerdown(struct iio_dev
*indio_dev
,
119 const struct iio_chan_spec
*chan
,
122 struct ti_dac_chip
*ti_dac
= iio_priv(indio_dev
);
124 return sprintf(buf
, "%d\n", ti_dac
->powerdown
);
127 static ssize_t
ti_dac_write_powerdown(struct iio_dev
*indio_dev
,
129 const struct iio_chan_spec
*chan
,
130 const char *buf
, size_t len
)
132 struct ti_dac_chip
*ti_dac
= iio_priv(indio_dev
);
136 ret
= strtobool(buf
, &powerdown
);
140 if (ti_dac
->powerdown
== powerdown
)
143 mutex_lock(&ti_dac
->lock
);
145 ret
= ti_dac_cmd(ti_dac
, POWERDOWN(ti_dac
->powerdown_mode
), 0);
147 ret
= ti_dac_cmd(ti_dac
, WRITE_AND_UPDATE(0), ti_dac
->val
[0]);
149 ti_dac
->powerdown
= powerdown
;
150 mutex_unlock(&ti_dac
->lock
);
152 return ret
? ret
: len
;
155 static const struct iio_chan_spec_ext_info ti_dac_ext_info
[] = {
158 .read
= ti_dac_read_powerdown
,
159 .write
= ti_dac_write_powerdown
,
160 .shared
= IIO_SHARED_BY_TYPE
,
162 IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE
, &ti_dac_powerdown_mode
),
163 IIO_ENUM_AVAILABLE("powerdown_mode", &ti_dac_powerdown_mode
),
167 #define TI_DAC_CHANNEL(chan) { \
168 .type = IIO_VOLTAGE, \
173 .datasheet_name = (const char[]){ 'A' + (chan), 0 }, \
174 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
175 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
176 .ext_info = ti_dac_ext_info, \
179 static const struct iio_chan_spec ti_dac_channels
[] = {
186 static int ti_dac_read_raw(struct iio_dev
*indio_dev
,
187 struct iio_chan_spec
const *chan
,
188 int *val
, int *val2
, long mask
)
190 struct ti_dac_chip
*ti_dac
= iio_priv(indio_dev
);
194 case IIO_CHAN_INFO_RAW
:
195 *val
= ti_dac
->val
[chan
->channel
];
199 case IIO_CHAN_INFO_SCALE
:
200 ret
= regulator_get_voltage(ti_dac
->vref
);
205 *val2
= ti_dac
->resolution
;
206 ret
= IIO_VAL_FRACTIONAL_LOG2
;
216 static int ti_dac_write_raw(struct iio_dev
*indio_dev
,
217 struct iio_chan_spec
const *chan
,
218 int val
, int val2
, long mask
)
220 struct ti_dac_chip
*ti_dac
= iio_priv(indio_dev
);
224 case IIO_CHAN_INFO_RAW
:
225 if (ti_dac
->val
[chan
->channel
] == val
)
228 if (val
>= (1 << ti_dac
->resolution
) || val
< 0)
231 if (ti_dac
->powerdown
)
234 mutex_lock(&ti_dac
->lock
);
235 ret
= ti_dac_cmd(ti_dac
, WRITE_AND_UPDATE(chan
->channel
), val
);
237 ti_dac
->val
[chan
->channel
] = val
;
238 mutex_unlock(&ti_dac
->lock
);
248 static int ti_dac_write_raw_get_fmt(struct iio_dev
*indio_dev
,
249 struct iio_chan_spec
const *chan
, long mask
)
254 static const struct iio_info ti_dac_info
= {
255 .read_raw
= ti_dac_read_raw
,
256 .write_raw
= ti_dac_write_raw
,
257 .write_raw_get_fmt
= ti_dac_write_raw_get_fmt
,
260 static int ti_dac_probe(struct spi_device
*spi
)
262 struct device
*dev
= &spi
->dev
;
263 const struct ti_dac_spec
*spec
;
264 struct ti_dac_chip
*ti_dac
;
265 struct iio_dev
*indio_dev
;
268 indio_dev
= devm_iio_device_alloc(dev
, sizeof(*ti_dac
));
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
);
328 static const struct of_device_id ti_dac_of_id
[] = {
329 { .compatible
= "ti,dac082s085" },
330 { .compatible
= "ti,dac102s085" },
331 { .compatible
= "ti,dac122s085" },
332 { .compatible
= "ti,dac084s085" },
333 { .compatible
= "ti,dac104s085" },
334 { .compatible
= "ti,dac124s085" },
337 MODULE_DEVICE_TABLE(of
, ti_dac_of_id
);
339 static const struct spi_device_id ti_dac_spi_id
[] = {
340 { "dac082s085", dual_8bit
},
341 { "dac102s085", dual_10bit
},
342 { "dac122s085", dual_12bit
},
343 { "dac084s085", quad_8bit
},
344 { "dac104s085", quad_10bit
},
345 { "dac124s085", quad_12bit
},
348 MODULE_DEVICE_TABLE(spi
, ti_dac_spi_id
);
350 static struct spi_driver ti_dac_driver
= {
352 .name
= "ti-dac082s085",
353 .of_match_table
= ti_dac_of_id
,
355 .probe
= ti_dac_probe
,
356 .remove
= ti_dac_remove
,
357 .id_table
= ti_dac_spi_id
,
359 module_spi_driver(ti_dac_driver
);
361 MODULE_AUTHOR("Lukas Wunner <lukas@wunner.de>");
362 MODULE_DESCRIPTION("Texas Instruments 8/10/12-bit 2/4-channel DAC driver");
363 MODULE_LICENSE("GPL v2");