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