1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * IIO DAC driver for Analog Devices AD8801 DAC |
4 | * |
5 | * Copyright (C) 2016 Gwenhael Goavec-Merou |
6 | */ |
7 | |
8 | #include <linux/iio/iio.h> |
9 | #include <linux/module.h> |
10 | #include <linux/regulator/consumer.h> |
11 | #include <linux/spi/spi.h> |
12 | #include <linux/sysfs.h> |
13 | |
14 | #define AD8801_CFG_ADDR_OFFSET 8 |
15 | |
16 | enum ad8801_device_ids { |
17 | ID_AD8801, |
18 | ID_AD8803, |
19 | }; |
20 | |
21 | struct ad8801_state { |
22 | struct spi_device *spi; |
23 | unsigned char dac_cache[8]; /* Value write on each channel */ |
24 | unsigned int vrefh_mv; |
25 | unsigned int vrefl_mv; |
26 | struct regulator *vrefh_reg; |
27 | struct regulator *vrefl_reg; |
28 | |
29 | __be16 data __aligned(IIO_DMA_MINALIGN); |
30 | }; |
31 | |
32 | static int ad8801_spi_write(struct ad8801_state *state, |
33 | u8 channel, unsigned char value) |
34 | { |
35 | state->data = cpu_to_be16((channel << AD8801_CFG_ADDR_OFFSET) | value); |
36 | return spi_write(spi: state->spi, buf: &state->data, len: sizeof(state->data)); |
37 | } |
38 | |
39 | static int ad8801_write_raw(struct iio_dev *indio_dev, |
40 | struct iio_chan_spec const *chan, int val, int val2, long mask) |
41 | { |
42 | struct ad8801_state *state = iio_priv(indio_dev); |
43 | int ret; |
44 | |
45 | switch (mask) { |
46 | case IIO_CHAN_INFO_RAW: |
47 | if (val >= 256 || val < 0) |
48 | return -EINVAL; |
49 | |
50 | ret = ad8801_spi_write(state, channel: chan->channel, value: val); |
51 | if (ret == 0) |
52 | state->dac_cache[chan->channel] = val; |
53 | break; |
54 | default: |
55 | ret = -EINVAL; |
56 | } |
57 | |
58 | return ret; |
59 | } |
60 | |
61 | static int ad8801_read_raw(struct iio_dev *indio_dev, |
62 | struct iio_chan_spec const *chan, int *val, int *val2, long info) |
63 | { |
64 | struct ad8801_state *state = iio_priv(indio_dev); |
65 | |
66 | switch (info) { |
67 | case IIO_CHAN_INFO_RAW: |
68 | *val = state->dac_cache[chan->channel]; |
69 | return IIO_VAL_INT; |
70 | case IIO_CHAN_INFO_SCALE: |
71 | *val = state->vrefh_mv - state->vrefl_mv; |
72 | *val2 = 8; |
73 | return IIO_VAL_FRACTIONAL_LOG2; |
74 | case IIO_CHAN_INFO_OFFSET: |
75 | *val = state->vrefl_mv; |
76 | return IIO_VAL_INT; |
77 | default: |
78 | return -EINVAL; |
79 | } |
80 | |
81 | return -EINVAL; |
82 | } |
83 | |
84 | static const struct iio_info ad8801_info = { |
85 | .read_raw = ad8801_read_raw, |
86 | .write_raw = ad8801_write_raw, |
87 | }; |
88 | |
89 | #define AD8801_CHANNEL(chan) { \ |
90 | .type = IIO_VOLTAGE, \ |
91 | .indexed = 1, \ |
92 | .output = 1, \ |
93 | .channel = chan, \ |
94 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ |
95 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ |
96 | BIT(IIO_CHAN_INFO_OFFSET), \ |
97 | } |
98 | |
99 | static const struct iio_chan_spec ad8801_channels[] = { |
100 | AD8801_CHANNEL(0), |
101 | AD8801_CHANNEL(1), |
102 | AD8801_CHANNEL(2), |
103 | AD8801_CHANNEL(3), |
104 | AD8801_CHANNEL(4), |
105 | AD8801_CHANNEL(5), |
106 | AD8801_CHANNEL(6), |
107 | AD8801_CHANNEL(7), |
108 | }; |
109 | |
110 | static int ad8801_probe(struct spi_device *spi) |
111 | { |
112 | struct iio_dev *indio_dev; |
113 | struct ad8801_state *state; |
114 | const struct spi_device_id *id; |
115 | int ret; |
116 | |
117 | indio_dev = devm_iio_device_alloc(parent: &spi->dev, sizeof_priv: sizeof(*state)); |
118 | if (indio_dev == NULL) |
119 | return -ENOMEM; |
120 | |
121 | state = iio_priv(indio_dev); |
122 | state->spi = spi; |
123 | id = spi_get_device_id(sdev: spi); |
124 | |
125 | state->vrefh_reg = devm_regulator_get(dev: &spi->dev, id: "vrefh" ); |
126 | if (IS_ERR(ptr: state->vrefh_reg)) |
127 | return dev_err_probe(dev: &spi->dev, err: PTR_ERR(ptr: state->vrefh_reg), |
128 | fmt: "Vrefh regulator not specified\n" ); |
129 | |
130 | ret = regulator_enable(regulator: state->vrefh_reg); |
131 | if (ret) { |
132 | dev_err(&spi->dev, "Failed to enable vrefh regulator: %d\n" , |
133 | ret); |
134 | return ret; |
135 | } |
136 | |
137 | ret = regulator_get_voltage(regulator: state->vrefh_reg); |
138 | if (ret < 0) { |
139 | dev_err(&spi->dev, "Failed to read vrefh regulator: %d\n" , |
140 | ret); |
141 | goto error_disable_vrefh_reg; |
142 | } |
143 | state->vrefh_mv = ret / 1000; |
144 | |
145 | if (id->driver_data == ID_AD8803) { |
146 | state->vrefl_reg = devm_regulator_get(dev: &spi->dev, id: "vrefl" ); |
147 | if (IS_ERR(ptr: state->vrefl_reg)) { |
148 | ret = dev_err_probe(dev: &spi->dev, err: PTR_ERR(ptr: state->vrefl_reg), |
149 | fmt: "Vrefl regulator not specified\n" ); |
150 | goto error_disable_vrefh_reg; |
151 | } |
152 | |
153 | ret = regulator_enable(regulator: state->vrefl_reg); |
154 | if (ret) { |
155 | dev_err(&spi->dev, "Failed to enable vrefl regulator: %d\n" , |
156 | ret); |
157 | goto error_disable_vrefh_reg; |
158 | } |
159 | |
160 | ret = regulator_get_voltage(regulator: state->vrefl_reg); |
161 | if (ret < 0) { |
162 | dev_err(&spi->dev, "Failed to read vrefl regulator: %d\n" , |
163 | ret); |
164 | goto error_disable_vrefl_reg; |
165 | } |
166 | state->vrefl_mv = ret / 1000; |
167 | } else { |
168 | state->vrefl_mv = 0; |
169 | state->vrefl_reg = NULL; |
170 | } |
171 | |
172 | spi_set_drvdata(spi, data: indio_dev); |
173 | indio_dev->info = &ad8801_info; |
174 | indio_dev->modes = INDIO_DIRECT_MODE; |
175 | indio_dev->channels = ad8801_channels; |
176 | indio_dev->num_channels = ARRAY_SIZE(ad8801_channels); |
177 | indio_dev->name = id->name; |
178 | |
179 | ret = iio_device_register(indio_dev); |
180 | if (ret) { |
181 | dev_err(&spi->dev, "Failed to register iio device: %d\n" , |
182 | ret); |
183 | goto error_disable_vrefl_reg; |
184 | } |
185 | |
186 | return 0; |
187 | |
188 | error_disable_vrefl_reg: |
189 | if (state->vrefl_reg) |
190 | regulator_disable(regulator: state->vrefl_reg); |
191 | error_disable_vrefh_reg: |
192 | regulator_disable(regulator: state->vrefh_reg); |
193 | return ret; |
194 | } |
195 | |
196 | static void ad8801_remove(struct spi_device *spi) |
197 | { |
198 | struct iio_dev *indio_dev = spi_get_drvdata(spi); |
199 | struct ad8801_state *state = iio_priv(indio_dev); |
200 | |
201 | iio_device_unregister(indio_dev); |
202 | if (state->vrefl_reg) |
203 | regulator_disable(regulator: state->vrefl_reg); |
204 | regulator_disable(regulator: state->vrefh_reg); |
205 | } |
206 | |
207 | static const struct spi_device_id ad8801_ids[] = { |
208 | {"ad8801" , ID_AD8801}, |
209 | {"ad8803" , ID_AD8803}, |
210 | {} |
211 | }; |
212 | MODULE_DEVICE_TABLE(spi, ad8801_ids); |
213 | |
214 | static struct spi_driver ad8801_driver = { |
215 | .driver = { |
216 | .name = "ad8801" , |
217 | }, |
218 | .probe = ad8801_probe, |
219 | .remove = ad8801_remove, |
220 | .id_table = ad8801_ids, |
221 | }; |
222 | module_spi_driver(ad8801_driver); |
223 | |
224 | MODULE_AUTHOR("Gwenhael Goavec-Merou <gwenhael.goavec-merou@trabucayre.com>" ); |
225 | MODULE_DESCRIPTION("Analog Devices AD8801/AD8803 DAC" ); |
226 | MODULE_LICENSE("GPL v2" ); |
227 | |