Merge tag 'sound-5.13-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai...
[linux-2.6-microblaze.git] / drivers / iio / adc / mcp3911.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Driver for Microchip MCP3911, Two-channel Analog Front End
4  *
5  * Copyright (C) 2018 Marcus Folkesson <marcus.folkesson@gmail.com>
6  * Copyright (C) 2018 Kent Gustavsson <kent@minoris.se>
7  */
8 #include <linux/clk.h>
9 #include <linux/delay.h>
10 #include <linux/err.h>
11 #include <linux/iio/iio.h>
12 #include <linux/module.h>
13 #include <linux/regulator/consumer.h>
14 #include <linux/spi/spi.h>
15
16 #define MCP3911_REG_CHANNEL0            0x00
17 #define MCP3911_REG_CHANNEL1            0x03
18 #define MCP3911_REG_MOD                 0x06
19 #define MCP3911_REG_PHASE               0x07
20 #define MCP3911_REG_GAIN                0x09
21
22 #define MCP3911_REG_STATUSCOM           0x0a
23 #define MCP3911_STATUSCOM_CH1_24WIDTH   BIT(4)
24 #define MCP3911_STATUSCOM_CH0_24WIDTH   BIT(3)
25 #define MCP3911_STATUSCOM_EN_OFFCAL     BIT(2)
26 #define MCP3911_STATUSCOM_EN_GAINCAL    BIT(1)
27
28 #define MCP3911_REG_CONFIG              0x0c
29 #define MCP3911_CONFIG_CLKEXT           BIT(1)
30 #define MCP3911_CONFIG_VREFEXT          BIT(2)
31
32 #define MCP3911_REG_OFFCAL_CH0          0x0e
33 #define MCP3911_REG_GAINCAL_CH0         0x11
34 #define MCP3911_REG_OFFCAL_CH1          0x14
35 #define MCP3911_REG_GAINCAL_CH1         0x17
36 #define MCP3911_REG_VREFCAL             0x1a
37
38 #define MCP3911_CHANNEL(x)              (MCP3911_REG_CHANNEL0 + x * 3)
39 #define MCP3911_OFFCAL(x)               (MCP3911_REG_OFFCAL_CH0 + x * 6)
40
41 /* Internal voltage reference in uV */
42 #define MCP3911_INT_VREF_UV             1200000
43
44 #define MCP3911_REG_READ(reg, id)       ((((reg) << 1) | ((id) << 5) | (1 << 0)) & 0xff)
45 #define MCP3911_REG_WRITE(reg, id)      ((((reg) << 1) | ((id) << 5) | (0 << 0)) & 0xff)
46
47 #define MCP3911_NUM_CHANNELS            2
48
49 struct mcp3911 {
50         struct spi_device *spi;
51         struct mutex lock;
52         struct regulator *vref;
53         struct clk *clki;
54         u32 dev_addr;
55 };
56
57 static int mcp3911_read(struct mcp3911 *adc, u8 reg, u32 *val, u8 len)
58 {
59         int ret;
60
61         reg = MCP3911_REG_READ(reg, adc->dev_addr);
62         ret = spi_write_then_read(adc->spi, &reg, 1, val, len);
63         if (ret < 0)
64                 return ret;
65
66         be32_to_cpus(val);
67         *val >>= ((4 - len) * 8);
68         dev_dbg(&adc->spi->dev, "reading 0x%x from register 0x%x\n", *val,
69                 reg >> 1);
70         return ret;
71 }
72
73 static int mcp3911_write(struct mcp3911 *adc, u8 reg, u32 val, u8 len)
74 {
75         dev_dbg(&adc->spi->dev, "writing 0x%x to register 0x%x\n", val, reg);
76
77         val <<= (3 - len) * 8;
78         cpu_to_be32s(&val);
79         val |= MCP3911_REG_WRITE(reg, adc->dev_addr);
80
81         return spi_write(adc->spi, &val, len + 1);
82 }
83
84 static int mcp3911_update(struct mcp3911 *adc, u8 reg, u32 mask,
85                 u32 val, u8 len)
86 {
87         u32 tmp;
88         int ret;
89
90         ret = mcp3911_read(adc, reg, &tmp, len);
91         if (ret)
92                 return ret;
93
94         val &= mask;
95         val |= tmp & ~mask;
96         return mcp3911_write(adc, reg, val, len);
97 }
98
99 static int mcp3911_read_raw(struct iio_dev *indio_dev,
100                             struct iio_chan_spec const *channel, int *val,
101                             int *val2, long mask)
102 {
103         struct mcp3911 *adc = iio_priv(indio_dev);
104         int ret = -EINVAL;
105
106         mutex_lock(&adc->lock);
107         switch (mask) {
108         case IIO_CHAN_INFO_RAW:
109                 ret = mcp3911_read(adc,
110                                    MCP3911_CHANNEL(channel->channel), val, 3);
111                 if (ret)
112                         goto out;
113
114                 ret = IIO_VAL_INT;
115                 break;
116
117         case IIO_CHAN_INFO_OFFSET:
118                 ret = mcp3911_read(adc,
119                                    MCP3911_OFFCAL(channel->channel), val, 3);
120                 if (ret)
121                         goto out;
122
123                 ret = IIO_VAL_INT;
124                 break;
125
126         case IIO_CHAN_INFO_SCALE:
127                 if (adc->vref) {
128                         ret = regulator_get_voltage(adc->vref);
129                         if (ret < 0) {
130                                 dev_err(indio_dev->dev.parent,
131                                         "failed to get vref voltage: %d\n",
132                                        ret);
133                                 goto out;
134                         }
135
136                         *val = ret / 1000;
137                 } else {
138                         *val = MCP3911_INT_VREF_UV;
139                 }
140
141                 *val2 = 24;
142                 ret = IIO_VAL_FRACTIONAL_LOG2;
143                 break;
144         }
145
146 out:
147         mutex_unlock(&adc->lock);
148         return ret;
149 }
150
151 static int mcp3911_write_raw(struct iio_dev *indio_dev,
152                             struct iio_chan_spec const *channel, int val,
153                             int val2, long mask)
154 {
155         struct mcp3911 *adc = iio_priv(indio_dev);
156         int ret = -EINVAL;
157
158         mutex_lock(&adc->lock);
159         switch (mask) {
160         case IIO_CHAN_INFO_OFFSET:
161                 if (val2 != 0) {
162                         ret = -EINVAL;
163                         goto out;
164                 }
165
166                 /* Write offset */
167                 ret = mcp3911_write(adc, MCP3911_OFFCAL(channel->channel), val,
168                                     3);
169                 if (ret)
170                         goto out;
171
172                 /* Enable offset*/
173                 ret = mcp3911_update(adc, MCP3911_REG_STATUSCOM,
174                                 MCP3911_STATUSCOM_EN_OFFCAL,
175                                 MCP3911_STATUSCOM_EN_OFFCAL, 2);
176                 break;
177         }
178
179 out:
180         mutex_unlock(&adc->lock);
181         return ret;
182 }
183
184 #define MCP3911_CHAN(idx) {                                     \
185                 .type = IIO_VOLTAGE,                            \
186                 .indexed = 1,                                   \
187                 .channel = idx,                                 \
188                 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |  \
189                         BIT(IIO_CHAN_INFO_OFFSET) |             \
190                         BIT(IIO_CHAN_INFO_SCALE),               \
191 }
192
193 static const struct iio_chan_spec mcp3911_channels[] = {
194         MCP3911_CHAN(0),
195         MCP3911_CHAN(1),
196 };
197
198 static const struct iio_info mcp3911_info = {
199         .read_raw = mcp3911_read_raw,
200         .write_raw = mcp3911_write_raw,
201 };
202
203 static int mcp3911_config(struct mcp3911 *adc, struct device_node *of_node)
204 {
205         u32 configreg;
206         int ret;
207
208         of_property_read_u32(of_node, "device-addr", &adc->dev_addr);
209         if (adc->dev_addr > 3) {
210                 dev_err(&adc->spi->dev,
211                         "invalid device address (%i). Must be in range 0-3.\n",
212                         adc->dev_addr);
213                 return -EINVAL;
214         }
215         dev_dbg(&adc->spi->dev, "use device address %i\n", adc->dev_addr);
216
217         ret = mcp3911_read(adc, MCP3911_REG_CONFIG, &configreg, 2);
218         if (ret)
219                 return ret;
220
221         if (adc->vref) {
222                 dev_dbg(&adc->spi->dev, "use external voltage reference\n");
223                 configreg |= MCP3911_CONFIG_VREFEXT;
224         } else {
225                 dev_dbg(&adc->spi->dev,
226                         "use internal voltage reference (1.2V)\n");
227                 configreg &= ~MCP3911_CONFIG_VREFEXT;
228         }
229
230         if (adc->clki) {
231                 dev_dbg(&adc->spi->dev, "use external clock as clocksource\n");
232                 configreg |= MCP3911_CONFIG_CLKEXT;
233         } else {
234                 dev_dbg(&adc->spi->dev,
235                         "use crystal oscillator as clocksource\n");
236                 configreg &= ~MCP3911_CONFIG_CLKEXT;
237         }
238
239         return  mcp3911_write(adc, MCP3911_REG_CONFIG, configreg, 2);
240 }
241
242 static int mcp3911_probe(struct spi_device *spi)
243 {
244         struct iio_dev *indio_dev;
245         struct mcp3911 *adc;
246         int ret;
247
248         indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc));
249         if (!indio_dev)
250                 return -ENOMEM;
251
252         adc = iio_priv(indio_dev);
253         adc->spi = spi;
254
255         adc->vref = devm_regulator_get_optional(&adc->spi->dev, "vref");
256         if (IS_ERR(adc->vref)) {
257                 if (PTR_ERR(adc->vref) == -ENODEV) {
258                         adc->vref = NULL;
259                 } else {
260                         dev_err(&adc->spi->dev,
261                                 "failed to get regulator (%ld)\n",
262                                 PTR_ERR(adc->vref));
263                         return PTR_ERR(adc->vref);
264                 }
265
266         } else {
267                 ret = regulator_enable(adc->vref);
268                 if (ret)
269                         return ret;
270         }
271
272         adc->clki = devm_clk_get(&adc->spi->dev, NULL);
273         if (IS_ERR(adc->clki)) {
274                 if (PTR_ERR(adc->clki) == -ENOENT) {
275                         adc->clki = NULL;
276                 } else {
277                         dev_err(&adc->spi->dev,
278                                 "failed to get adc clk (%ld)\n",
279                                 PTR_ERR(adc->clki));
280                         ret = PTR_ERR(adc->clki);
281                         goto reg_disable;
282                 }
283         } else {
284                 ret = clk_prepare_enable(adc->clki);
285                 if (ret < 0) {
286                         dev_err(&adc->spi->dev,
287                                 "Failed to enable clki: %d\n", ret);
288                         goto reg_disable;
289                 }
290         }
291
292         ret = mcp3911_config(adc, spi->dev.of_node);
293         if (ret)
294                 goto clk_disable;
295
296         indio_dev->name = spi_get_device_id(spi)->name;
297         indio_dev->modes = INDIO_DIRECT_MODE;
298         indio_dev->info = &mcp3911_info;
299         spi_set_drvdata(spi, indio_dev);
300
301         indio_dev->channels = mcp3911_channels;
302         indio_dev->num_channels = ARRAY_SIZE(mcp3911_channels);
303
304         mutex_init(&adc->lock);
305
306         ret = iio_device_register(indio_dev);
307         if (ret)
308                 goto clk_disable;
309
310         return ret;
311
312 clk_disable:
313         clk_disable_unprepare(adc->clki);
314 reg_disable:
315         if (adc->vref)
316                 regulator_disable(adc->vref);
317
318         return ret;
319 }
320
321 static int mcp3911_remove(struct spi_device *spi)
322 {
323         struct iio_dev *indio_dev = spi_get_drvdata(spi);
324         struct mcp3911 *adc = iio_priv(indio_dev);
325
326         iio_device_unregister(indio_dev);
327
328         clk_disable_unprepare(adc->clki);
329         if (adc->vref)
330                 regulator_disable(adc->vref);
331
332         return 0;
333 }
334
335 static const struct of_device_id mcp3911_dt_ids[] = {
336         { .compatible = "microchip,mcp3911" },
337         { }
338 };
339 MODULE_DEVICE_TABLE(of, mcp3911_dt_ids);
340
341 static const struct spi_device_id mcp3911_id[] = {
342         { "mcp3911", 0 },
343         { }
344 };
345 MODULE_DEVICE_TABLE(spi, mcp3911_id);
346
347 static struct spi_driver mcp3911_driver = {
348         .driver = {
349                 .name = "mcp3911",
350                 .of_match_table = mcp3911_dt_ids,
351         },
352         .probe = mcp3911_probe,
353         .remove = mcp3911_remove,
354         .id_table = mcp3911_id,
355 };
356 module_spi_driver(mcp3911_driver);
357
358 MODULE_AUTHOR("Marcus Folkesson <marcus.folkesson@gmail.com>");
359 MODULE_AUTHOR("Kent Gustavsson <kent@minoris.se>");
360 MODULE_DESCRIPTION("Microchip Technology MCP3911");
361 MODULE_LICENSE("GPL v2");