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