Commit | Line | Data |
---|---|---|
8341dc04 LPC |
1 | /* |
2 | * AD5415, AD5426, AD5429, AD5432, AD5439, AD5443, AD5449 Digital to Analog | |
3 | * Converter driver. | |
4 | * | |
5 | * Copyright 2012 Analog Devices Inc. | |
6 | * Author: Lars-Peter Clausen <lars@metafoo.de> | |
7 | * | |
8 | * Licensed under the GPL-2. | |
9 | */ | |
10 | ||
11 | #include <linux/device.h> | |
12 | #include <linux/err.h> | |
13 | #include <linux/module.h> | |
14 | #include <linux/kernel.h> | |
15 | #include <linux/spi/spi.h> | |
16 | #include <linux/slab.h> | |
17 | #include <linux/sysfs.h> | |
18 | #include <linux/regulator/consumer.h> | |
19 | #include <asm/unaligned.h> | |
20 | ||
21 | #include <linux/iio/iio.h> | |
22 | #include <linux/iio/sysfs.h> | |
23 | ||
24 | #include <linux/platform_data/ad5449.h> | |
25 | ||
26 | #define AD5449_MAX_CHANNELS 2 | |
27 | #define AD5449_MAX_VREFS 2 | |
28 | ||
29 | #define AD5449_CMD_NOOP 0x0 | |
30 | #define AD5449_CMD_LOAD_AND_UPDATE(x) (0x1 + (x) * 3) | |
31 | #define AD5449_CMD_READ(x) (0x2 + (x) * 3) | |
32 | #define AD5449_CMD_LOAD(x) (0x3 + (x) * 3) | |
33 | #define AD5449_CMD_CTRL 13 | |
34 | ||
35 | #define AD5449_CTRL_SDO_OFFSET 10 | |
36 | #define AD5449_CTRL_DAISY_CHAIN BIT(9) | |
37 | #define AD5449_CTRL_HCLR_TO_MIDSCALE BIT(8) | |
38 | #define AD5449_CTRL_SAMPLE_RISING BIT(7) | |
39 | ||
40 | /** | |
41 | * struct ad5449_chip_info - chip specific information | |
42 | * @channels: Channel specification | |
43 | * @num_channels: Number of channels | |
44 | * @has_ctrl: Chip has a control register | |
45 | */ | |
46 | struct ad5449_chip_info { | |
47 | const struct iio_chan_spec *channels; | |
48 | unsigned int num_channels; | |
49 | bool has_ctrl; | |
50 | }; | |
51 | ||
52 | /** | |
53 | * struct ad5449 - driver instance specific data | |
54 | * @spi: the SPI device for this driver instance | |
55 | * @chip_info: chip model specific constants, available modes etc | |
56 | * @vref_reg: vref supply regulators | |
57 | * @has_sdo: whether the SDO line is connected | |
58 | * @dac_cache: Cache for the DAC values | |
59 | * @data: spi transfer buffers | |
60 | */ | |
61 | struct ad5449 { | |
62 | struct spi_device *spi; | |
63 | const struct ad5449_chip_info *chip_info; | |
64 | struct regulator_bulk_data vref_reg[AD5449_MAX_VREFS]; | |
65 | ||
66 | bool has_sdo; | |
67 | uint16_t dac_cache[AD5449_MAX_CHANNELS]; | |
68 | ||
69 | /* | |
70 | * DMA (thus cache coherency maintenance) requires the | |
71 | * transfer buffers to live in their own cache lines. | |
72 | */ | |
73 | __be16 data[2] ____cacheline_aligned; | |
74 | }; | |
75 | ||
76 | enum ad5449_type { | |
77 | ID_AD5426, | |
78 | ID_AD5429, | |
79 | ID_AD5432, | |
80 | ID_AD5439, | |
81 | ID_AD5443, | |
82 | ID_AD5449, | |
83 | }; | |
84 | ||
85 | static int ad5449_write(struct iio_dev *indio_dev, unsigned int addr, | |
86 | unsigned int val) | |
87 | { | |
88 | struct ad5449 *st = iio_priv(indio_dev); | |
89 | int ret; | |
90 | ||
91 | mutex_lock(&indio_dev->mlock); | |
92 | st->data[0] = cpu_to_be16((addr << 12) | val); | |
93 | ret = spi_write(st->spi, st->data, 2); | |
94 | mutex_unlock(&indio_dev->mlock); | |
95 | ||
96 | return ret; | |
97 | } | |
98 | ||
99 | static int ad5449_read(struct iio_dev *indio_dev, unsigned int addr, | |
100 | unsigned int *val) | |
101 | { | |
102 | struct ad5449 *st = iio_priv(indio_dev); | |
103 | int ret; | |
8341dc04 LPC |
104 | struct spi_transfer t[] = { |
105 | { | |
106 | .tx_buf = &st->data[0], | |
107 | .len = 2, | |
108 | .cs_change = 1, | |
109 | }, { | |
110 | .tx_buf = &st->data[1], | |
111 | .rx_buf = &st->data[1], | |
112 | .len = 2, | |
113 | }, | |
114 | }; | |
115 | ||
8341dc04 LPC |
116 | mutex_lock(&indio_dev->mlock); |
117 | st->data[0] = cpu_to_be16(addr << 12); | |
118 | st->data[1] = cpu_to_be16(AD5449_CMD_NOOP); | |
119 | ||
66a18916 | 120 | ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t)); |
8341dc04 | 121 | if (ret < 0) |
0c88d23c | 122 | goto out_unlock; |
8341dc04 LPC |
123 | |
124 | *val = be16_to_cpu(st->data[1]); | |
8341dc04 | 125 | |
0c88d23c DC |
126 | out_unlock: |
127 | mutex_unlock(&indio_dev->mlock); | |
128 | return ret; | |
8341dc04 LPC |
129 | } |
130 | ||
131 | static int ad5449_read_raw(struct iio_dev *indio_dev, | |
132 | struct iio_chan_spec const *chan, int *val, int *val2, long info) | |
133 | { | |
134 | struct ad5449 *st = iio_priv(indio_dev); | |
135 | struct regulator_bulk_data *reg; | |
136 | int scale_uv; | |
137 | int ret; | |
138 | ||
139 | switch (info) { | |
140 | case IIO_CHAN_INFO_RAW: | |
141 | if (st->has_sdo) { | |
142 | ret = ad5449_read(indio_dev, | |
143 | AD5449_CMD_READ(chan->address), val); | |
144 | if (ret) | |
145 | return ret; | |
146 | *val &= 0xfff; | |
147 | } else { | |
148 | *val = st->dac_cache[chan->address]; | |
149 | } | |
150 | ||
151 | return IIO_VAL_INT; | |
152 | case IIO_CHAN_INFO_SCALE: | |
153 | reg = &st->vref_reg[chan->channel]; | |
154 | scale_uv = regulator_get_voltage(reg->consumer); | |
155 | if (scale_uv < 0) | |
156 | return scale_uv; | |
157 | ||
158 | *val = scale_uv / 1000; | |
159 | *val2 = chan->scan_type.realbits; | |
160 | ||
161 | return IIO_VAL_FRACTIONAL_LOG2; | |
162 | default: | |
163 | break; | |
164 | } | |
165 | ||
166 | return -EINVAL; | |
167 | } | |
168 | ||
169 | static int ad5449_write_raw(struct iio_dev *indio_dev, | |
170 | struct iio_chan_spec const *chan, int val, int val2, long info) | |
171 | { | |
172 | struct ad5449 *st = iio_priv(indio_dev); | |
173 | int ret; | |
174 | ||
175 | switch (info) { | |
176 | case IIO_CHAN_INFO_RAW: | |
177 | if (val < 0 || val >= (1 << chan->scan_type.realbits)) | |
178 | return -EINVAL; | |
179 | ||
180 | ret = ad5449_write(indio_dev, | |
181 | AD5449_CMD_LOAD_AND_UPDATE(chan->address), | |
182 | val << chan->scan_type.shift); | |
183 | if (ret == 0) | |
184 | st->dac_cache[chan->address] = val; | |
185 | break; | |
186 | default: | |
187 | ret = -EINVAL; | |
188 | } | |
189 | ||
190 | return ret; | |
191 | } | |
192 | ||
193 | static const struct iio_info ad5449_info = { | |
194 | .read_raw = ad5449_read_raw, | |
195 | .write_raw = ad5449_write_raw, | |
196 | .driver_module = THIS_MODULE, | |
197 | }; | |
198 | ||
199 | #define AD5449_CHANNEL(chan, bits) { \ | |
200 | .type = IIO_VOLTAGE, \ | |
201 | .indexed = 1, \ | |
202 | .output = 1, \ | |
203 | .channel = (chan), \ | |
f8c62713 JC |
204 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ |
205 | BIT(IIO_CHAN_INFO_SCALE), \ | |
8341dc04 | 206 | .address = (chan), \ |
3d42e148 JC |
207 | .scan_type = { \ |
208 | .sign = 'u', \ | |
209 | .realbits = (bits), \ | |
210 | .storagebits = 16, \ | |
211 | .shift = 12 - (bits), \ | |
212 | }, \ | |
8341dc04 LPC |
213 | } |
214 | ||
215 | #define DECLARE_AD5449_CHANNELS(name, bits) \ | |
216 | const struct iio_chan_spec name[] = { \ | |
217 | AD5449_CHANNEL(0, bits), \ | |
218 | AD5449_CHANNEL(1, bits), \ | |
219 | } | |
220 | ||
221 | static DECLARE_AD5449_CHANNELS(ad5429_channels, 8); | |
222 | static DECLARE_AD5449_CHANNELS(ad5439_channels, 10); | |
223 | static DECLARE_AD5449_CHANNELS(ad5449_channels, 12); | |
224 | ||
225 | static const struct ad5449_chip_info ad5449_chip_info[] = { | |
226 | [ID_AD5426] = { | |
227 | .channels = ad5429_channels, | |
228 | .num_channels = 1, | |
229 | .has_ctrl = false, | |
230 | }, | |
231 | [ID_AD5429] = { | |
232 | .channels = ad5429_channels, | |
233 | .num_channels = 2, | |
234 | .has_ctrl = true, | |
235 | }, | |
236 | [ID_AD5432] = { | |
237 | .channels = ad5439_channels, | |
238 | .num_channels = 1, | |
239 | .has_ctrl = false, | |
240 | }, | |
241 | [ID_AD5439] = { | |
242 | .channels = ad5439_channels, | |
243 | .num_channels = 2, | |
244 | .has_ctrl = true, | |
245 | }, | |
246 | [ID_AD5443] = { | |
247 | .channels = ad5449_channels, | |
248 | .num_channels = 1, | |
249 | .has_ctrl = false, | |
250 | }, | |
251 | [ID_AD5449] = { | |
252 | .channels = ad5449_channels, | |
253 | .num_channels = 2, | |
254 | .has_ctrl = true, | |
255 | }, | |
256 | }; | |
257 | ||
258 | static const char *ad5449_vref_name(struct ad5449 *st, int n) | |
259 | { | |
260 | if (st->chip_info->num_channels == 1) | |
261 | return "VREF"; | |
262 | ||
263 | if (n == 0) | |
264 | return "VREFA"; | |
265 | else | |
266 | return "VREFB"; | |
267 | } | |
268 | ||
fc52692c | 269 | static int ad5449_spi_probe(struct spi_device *spi) |
8341dc04 LPC |
270 | { |
271 | struct ad5449_platform_data *pdata = spi->dev.platform_data; | |
272 | const struct spi_device_id *id = spi_get_device_id(spi); | |
273 | struct iio_dev *indio_dev; | |
274 | struct ad5449 *st; | |
275 | unsigned int i; | |
276 | int ret; | |
277 | ||
cd5e5785 | 278 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); |
8341dc04 LPC |
279 | if (indio_dev == NULL) |
280 | return -ENOMEM; | |
281 | ||
282 | st = iio_priv(indio_dev); | |
283 | spi_set_drvdata(spi, indio_dev); | |
284 | ||
285 | st->chip_info = &ad5449_chip_info[id->driver_data]; | |
286 | st->spi = spi; | |
287 | ||
288 | for (i = 0; i < st->chip_info->num_channels; ++i) | |
289 | st->vref_reg[i].supply = ad5449_vref_name(st, i); | |
290 | ||
cd5e5785 | 291 | ret = devm_regulator_bulk_get(&spi->dev, st->chip_info->num_channels, |
8341dc04 LPC |
292 | st->vref_reg); |
293 | if (ret) | |
cd5e5785 | 294 | return ret; |
8341dc04 LPC |
295 | |
296 | ret = regulator_bulk_enable(st->chip_info->num_channels, st->vref_reg); | |
297 | if (ret) | |
cd5e5785 | 298 | return ret; |
8341dc04 LPC |
299 | |
300 | indio_dev->dev.parent = &spi->dev; | |
301 | indio_dev->name = id->name; | |
302 | indio_dev->info = &ad5449_info; | |
303 | indio_dev->modes = INDIO_DIRECT_MODE; | |
304 | indio_dev->channels = st->chip_info->channels; | |
305 | indio_dev->num_channels = st->chip_info->num_channels; | |
306 | ||
307 | if (st->chip_info->has_ctrl) { | |
308 | unsigned int ctrl = 0x00; | |
309 | if (pdata) { | |
310 | if (pdata->hardware_clear_to_midscale) | |
311 | ctrl |= AD5449_CTRL_HCLR_TO_MIDSCALE; | |
312 | ctrl |= pdata->sdo_mode << AD5449_CTRL_SDO_OFFSET; | |
313 | st->has_sdo = pdata->sdo_mode != AD5449_SDO_DISABLED; | |
314 | } else { | |
315 | st->has_sdo = true; | |
316 | } | |
317 | ad5449_write(indio_dev, AD5449_CMD_CTRL, ctrl); | |
318 | } | |
319 | ||
320 | ret = iio_device_register(indio_dev); | |
321 | if (ret) | |
322 | goto error_disable_reg; | |
323 | ||
324 | return 0; | |
325 | ||
326 | error_disable_reg: | |
327 | regulator_bulk_disable(st->chip_info->num_channels, st->vref_reg); | |
8341dc04 LPC |
328 | |
329 | return ret; | |
330 | } | |
331 | ||
fc52692c | 332 | static int ad5449_spi_remove(struct spi_device *spi) |
8341dc04 LPC |
333 | { |
334 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | |
335 | struct ad5449 *st = iio_priv(indio_dev); | |
336 | ||
337 | iio_device_unregister(indio_dev); | |
338 | ||
339 | regulator_bulk_disable(st->chip_info->num_channels, st->vref_reg); | |
8341dc04 LPC |
340 | |
341 | return 0; | |
342 | } | |
343 | ||
344 | static const struct spi_device_id ad5449_spi_ids[] = { | |
345 | { "ad5415", ID_AD5449 }, | |
346 | { "ad5426", ID_AD5426 }, | |
347 | { "ad5429", ID_AD5429 }, | |
348 | { "ad5432", ID_AD5432 }, | |
349 | { "ad5439", ID_AD5439 }, | |
350 | { "ad5443", ID_AD5443 }, | |
351 | { "ad5449", ID_AD5449 }, | |
352 | {} | |
353 | }; | |
354 | MODULE_DEVICE_TABLE(spi, ad5449_spi_ids); | |
355 | ||
356 | static struct spi_driver ad5449_spi_driver = { | |
357 | .driver = { | |
358 | .name = "ad5449", | |
8341dc04 LPC |
359 | }, |
360 | .probe = ad5449_spi_probe, | |
fc52692c | 361 | .remove = ad5449_spi_remove, |
8341dc04 LPC |
362 | .id_table = ad5449_spi_ids, |
363 | }; | |
364 | module_spi_driver(ad5449_spi_driver); | |
365 | ||
366 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | |
367 | MODULE_DESCRIPTION("Analog Devices AD5449 and similar DACs"); | |
368 | MODULE_LICENSE("GPL v2"); |