Commit | Line | Data |
---|---|---|
d2912cb1 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
f5ce4a7a OA |
2 | /* |
3 | * Copyright (C) 2013 Oskar Andero <oskar.andero@gmail.com> | |
b12206e9 SA |
4 | * Copyright (C) 2014 Rose Technology |
5 | * Allan Bendorff Jensen <abj@rosetechnology.dk> | |
6 | * Soren Andersen <san@rosetechnology.dk> | |
7 | * | |
8 | * Driver for following ADC chips from Microchip Technology's: | |
9 | * 10 Bit converter | |
10 | * MCP3001 | |
11 | * MCP3002 | |
12 | * MCP3004 | |
13 | * MCP3008 | |
14 | * ------------ | |
15 | * 12 bit converter | |
16 | * MCP3201 | |
17 | * MCP3202 | |
18 | * MCP3204 | |
19 | * MCP3208 | |
20 | * ------------ | |
e6f47943 LW |
21 | * 13 bit converter |
22 | * MCP3301 | |
c1375d67 LW |
23 | * ------------ |
24 | * 22 bit converter | |
25 | * MCP3550 | |
26 | * MCP3551 | |
27 | * MCP3553 | |
f5ce4a7a | 28 | * |
f5ce4a7a | 29 | * Datasheet can be found here: |
3593cd53 AK |
30 | * https://ww1.microchip.com/downloads/en/DeviceDoc/21293C.pdf mcp3001 |
31 | * https://ww1.microchip.com/downloads/en/DeviceDoc/21294E.pdf mcp3002 | |
32 | * https://ww1.microchip.com/downloads/en/DeviceDoc/21295d.pdf mcp3004/08 | |
b12206e9 SA |
33 | * http://ww1.microchip.com/downloads/en/DeviceDoc/21290D.pdf mcp3201 |
34 | * http://ww1.microchip.com/downloads/en/DeviceDoc/21034D.pdf mcp3202 | |
35 | * http://ww1.microchip.com/downloads/en/DeviceDoc/21298c.pdf mcp3204/08 | |
3593cd53 | 36 | * https://ww1.microchip.com/downloads/en/DeviceDoc/21700E.pdf mcp3301 |
c1375d67 | 37 | * http://ww1.microchip.com/downloads/en/DeviceDoc/21950D.pdf mcp3550/1/3 |
f5ce4a7a OA |
38 | */ |
39 | ||
40 | #include <linux/err.h> | |
b12206e9 | 41 | #include <linux/delay.h> |
f5ce4a7a OA |
42 | #include <linux/spi/spi.h> |
43 | #include <linux/module.h> | |
016d271e | 44 | #include <linux/mod_devicetable.h> |
f5ce4a7a OA |
45 | #include <linux/iio/iio.h> |
46 | #include <linux/regulator/consumer.h> | |
47 | ||
f5ce4a7a | 48 | enum { |
b12206e9 SA |
49 | mcp3001, |
50 | mcp3002, | |
51 | mcp3004, | |
52 | mcp3008, | |
53 | mcp3201, | |
54 | mcp3202, | |
f5ce4a7a OA |
55 | mcp3204, |
56 | mcp3208, | |
f686a36b | 57 | mcp3301, |
c1375d67 LW |
58 | mcp3550_50, |
59 | mcp3550_60, | |
60 | mcp3551, | |
61 | mcp3553, | |
f5ce4a7a OA |
62 | }; |
63 | ||
b12206e9 SA |
64 | struct mcp320x_chip_info { |
65 | const struct iio_chan_spec *channels; | |
66 | unsigned int num_channels; | |
67 | unsigned int resolution; | |
c1375d67 | 68 | unsigned int conv_time; /* usec */ |
b12206e9 SA |
69 | }; |
70 | ||
9c84c910 LW |
71 | /** |
72 | * struct mcp320x - Microchip SPI ADC instance | |
73 | * @spi: SPI slave (parent of the IIO device) | |
74 | * @msg: SPI message to select a channel and receive a value from the ADC | |
75 | * @transfer: SPI transfers used by @msg | |
c1375d67 LW |
76 | * @start_conv_msg: SPI message to start a conversion by briefly asserting CS |
77 | * @start_conv_transfer: SPI transfer used by @start_conv_msg | |
9c84c910 LW |
78 | * @reg: regulator generating Vref |
79 | * @lock: protects read sequences | |
80 | * @chip_info: ADC properties | |
81 | * @tx_buf: buffer for @transfer[0] (not used on single-channel converters) | |
82 | * @rx_buf: buffer for @transfer[1] | |
83 | */ | |
f5ce4a7a OA |
84 | struct mcp320x { |
85 | struct spi_device *spi; | |
86 | struct spi_message msg; | |
87 | struct spi_transfer transfer[2]; | |
c1375d67 LW |
88 | struct spi_message start_conv_msg; |
89 | struct spi_transfer start_conv_transfer; | |
f5ce4a7a | 90 | |
f5ce4a7a OA |
91 | struct regulator *reg; |
92 | struct mutex lock; | |
b12206e9 | 93 | const struct mcp320x_chip_info *chip_info; |
0e81bc99 | 94 | |
e770f780 | 95 | u8 tx_buf __aligned(IIO_DMA_MINALIGN); |
c1375d67 | 96 | u8 rx_buf[4]; |
f5ce4a7a OA |
97 | }; |
98 | ||
b12206e9 SA |
99 | static int mcp320x_channel_to_tx_data(int device_index, |
100 | const unsigned int channel, bool differential) | |
101 | { | |
102 | int start_bit = 1; | |
103 | ||
104 | switch (device_index) { | |
b12206e9 SA |
105 | case mcp3002: |
106 | case mcp3202: | |
107 | return ((start_bit << 4) | (!differential << 3) | | |
108 | (channel << 2)); | |
109 | case mcp3004: | |
110 | case mcp3204: | |
111 | case mcp3008: | |
112 | case mcp3208: | |
113 | return ((start_bit << 6) | (!differential << 5) | | |
114 | (channel << 2)); | |
115 | default: | |
116 | return -EINVAL; | |
117 | } | |
118 | } | |
119 | ||
120 | static int mcp320x_adc_conversion(struct mcp320x *adc, u8 channel, | |
e6f47943 | 121 | bool differential, int device_index, int *val) |
f5ce4a7a OA |
122 | { |
123 | int ret; | |
124 | ||
c1375d67 LW |
125 | if (adc->chip_info->conv_time) { |
126 | ret = spi_sync(adc->spi, &adc->start_conv_msg); | |
127 | if (ret < 0) | |
128 | return ret; | |
129 | ||
130 | usleep_range(adc->chip_info->conv_time, | |
131 | adc->chip_info->conv_time + 100); | |
132 | } | |
133 | ||
ea910318 LW |
134 | memset(&adc->rx_buf, 0, sizeof(adc->rx_buf)); |
135 | if (adc->chip_info->num_channels > 1) | |
136 | adc->tx_buf = mcp320x_channel_to_tx_data(device_index, channel, | |
137 | differential); | |
b12206e9 | 138 | |
ea910318 LW |
139 | ret = spi_sync(adc->spi, &adc->msg); |
140 | if (ret < 0) | |
141 | return ret; | |
f5ce4a7a | 142 | |
b12206e9 SA |
143 | switch (device_index) { |
144 | case mcp3001: | |
e6f47943 LW |
145 | *val = (adc->rx_buf[0] << 5 | adc->rx_buf[1] >> 3); |
146 | return 0; | |
b12206e9 SA |
147 | case mcp3002: |
148 | case mcp3004: | |
149 | case mcp3008: | |
e6f47943 LW |
150 | *val = (adc->rx_buf[0] << 2 | adc->rx_buf[1] >> 6); |
151 | return 0; | |
b12206e9 | 152 | case mcp3201: |
e6f47943 LW |
153 | *val = (adc->rx_buf[0] << 7 | adc->rx_buf[1] >> 1); |
154 | return 0; | |
b12206e9 SA |
155 | case mcp3202: |
156 | case mcp3204: | |
157 | case mcp3208: | |
e6f47943 LW |
158 | *val = (adc->rx_buf[0] << 4 | adc->rx_buf[1] >> 4); |
159 | return 0; | |
f686a36b | 160 | case mcp3301: |
e6f47943 LW |
161 | *val = sign_extend32((adc->rx_buf[0] & 0x1f) << 8 |
162 | | adc->rx_buf[1], 12); | |
163 | return 0; | |
c1375d67 LW |
164 | case mcp3550_50: |
165 | case mcp3550_60: | |
166 | case mcp3551: | |
167 | case mcp3553: { | |
9299b503 | 168 | u32 raw = be32_to_cpup((__be32 *)adc->rx_buf); |
c1375d67 LW |
169 | |
170 | if (!(adc->spi->mode & SPI_CPOL)) | |
171 | raw <<= 1; /* strip Data Ready bit in SPI mode 0,0 */ | |
172 | ||
173 | /* | |
174 | * If the input is within -vref and vref, bit 21 is the sign. | |
175 | * Up to 12% overrange or underrange are allowed, in which case | |
176 | * bit 23 is the sign and bit 0 to 21 is the value. | |
177 | */ | |
178 | raw >>= 8; | |
179 | if (raw & BIT(22) && raw & BIT(23)) | |
180 | return -EIO; /* cannot have overrange AND underrange */ | |
181 | else if (raw & BIT(22)) | |
182 | raw &= ~BIT(22); /* overrange */ | |
183 | else if (raw & BIT(23) || raw & BIT(21)) | |
184 | raw |= GENMASK(31, 22); /* underrange or negative */ | |
185 | ||
186 | *val = (s32)raw; | |
187 | return 0; | |
188 | } | |
b12206e9 SA |
189 | default: |
190 | return -EINVAL; | |
191 | } | |
f5ce4a7a OA |
192 | } |
193 | ||
194 | static int mcp320x_read_raw(struct iio_dev *indio_dev, | |
195 | struct iio_chan_spec const *channel, int *val, | |
196 | int *val2, long mask) | |
197 | { | |
198 | struct mcp320x *adc = iio_priv(indio_dev); | |
199 | int ret = -EINVAL; | |
b12206e9 | 200 | int device_index = 0; |
f5ce4a7a OA |
201 | |
202 | mutex_lock(&adc->lock); | |
203 | ||
b12206e9 SA |
204 | device_index = spi_get_device_id(adc->spi)->driver_data; |
205 | ||
f5ce4a7a OA |
206 | switch (mask) { |
207 | case IIO_CHAN_INFO_RAW: | |
b12206e9 | 208 | ret = mcp320x_adc_conversion(adc, channel->address, |
e6f47943 | 209 | channel->differential, device_index, val); |
f5ce4a7a OA |
210 | if (ret < 0) |
211 | goto out; | |
212 | ||
f5ce4a7a OA |
213 | ret = IIO_VAL_INT; |
214 | break; | |
215 | ||
216 | case IIO_CHAN_INFO_SCALE: | |
f5ce4a7a OA |
217 | ret = regulator_get_voltage(adc->reg); |
218 | if (ret < 0) | |
219 | goto out; | |
220 | ||
b12206e9 | 221 | /* convert regulator output voltage to mV */ |
f5ce4a7a | 222 | *val = ret / 1000; |
b12206e9 | 223 | *val2 = adc->chip_info->resolution; |
f5ce4a7a OA |
224 | ret = IIO_VAL_FRACTIONAL_LOG2; |
225 | break; | |
f5ce4a7a OA |
226 | } |
227 | ||
228 | out: | |
229 | mutex_unlock(&adc->lock); | |
230 | ||
231 | return ret; | |
232 | } | |
233 | ||
234 | #define MCP320X_VOLTAGE_CHANNEL(num) \ | |
235 | { \ | |
236 | .type = IIO_VOLTAGE, \ | |
237 | .indexed = 1, \ | |
238 | .channel = (num), \ | |
239 | .address = (num), \ | |
240 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | |
241 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \ | |
242 | } | |
243 | ||
4ea71e5c | 244 | #define MCP320X_VOLTAGE_CHANNEL_DIFF(chan1, chan2) \ |
f5ce4a7a OA |
245 | { \ |
246 | .type = IIO_VOLTAGE, \ | |
247 | .indexed = 1, \ | |
4ea71e5c AM |
248 | .channel = (chan1), \ |
249 | .channel2 = (chan2), \ | |
250 | .address = (chan1), \ | |
f5ce4a7a OA |
251 | .differential = 1, \ |
252 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | |
253 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \ | |
254 | } | |
255 | ||
b12206e9 | 256 | static const struct iio_chan_spec mcp3201_channels[] = { |
4ea71e5c | 257 | MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1), |
b12206e9 SA |
258 | }; |
259 | ||
260 | static const struct iio_chan_spec mcp3202_channels[] = { | |
261 | MCP320X_VOLTAGE_CHANNEL(0), | |
262 | MCP320X_VOLTAGE_CHANNEL(1), | |
4ea71e5c AM |
263 | MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1), |
264 | MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0), | |
b12206e9 SA |
265 | }; |
266 | ||
f5ce4a7a OA |
267 | static const struct iio_chan_spec mcp3204_channels[] = { |
268 | MCP320X_VOLTAGE_CHANNEL(0), | |
269 | MCP320X_VOLTAGE_CHANNEL(1), | |
270 | MCP320X_VOLTAGE_CHANNEL(2), | |
271 | MCP320X_VOLTAGE_CHANNEL(3), | |
4ea71e5c AM |
272 | MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1), |
273 | MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0), | |
274 | MCP320X_VOLTAGE_CHANNEL_DIFF(2, 3), | |
275 | MCP320X_VOLTAGE_CHANNEL_DIFF(3, 2), | |
f5ce4a7a OA |
276 | }; |
277 | ||
278 | static const struct iio_chan_spec mcp3208_channels[] = { | |
279 | MCP320X_VOLTAGE_CHANNEL(0), | |
280 | MCP320X_VOLTAGE_CHANNEL(1), | |
281 | MCP320X_VOLTAGE_CHANNEL(2), | |
282 | MCP320X_VOLTAGE_CHANNEL(3), | |
283 | MCP320X_VOLTAGE_CHANNEL(4), | |
284 | MCP320X_VOLTAGE_CHANNEL(5), | |
285 | MCP320X_VOLTAGE_CHANNEL(6), | |
286 | MCP320X_VOLTAGE_CHANNEL(7), | |
4ea71e5c AM |
287 | MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1), |
288 | MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0), | |
289 | MCP320X_VOLTAGE_CHANNEL_DIFF(2, 3), | |
290 | MCP320X_VOLTAGE_CHANNEL_DIFF(3, 2), | |
291 | MCP320X_VOLTAGE_CHANNEL_DIFF(4, 5), | |
292 | MCP320X_VOLTAGE_CHANNEL_DIFF(5, 4), | |
293 | MCP320X_VOLTAGE_CHANNEL_DIFF(6, 7), | |
294 | MCP320X_VOLTAGE_CHANNEL_DIFF(7, 6), | |
f5ce4a7a OA |
295 | }; |
296 | ||
297 | static const struct iio_info mcp320x_info = { | |
298 | .read_raw = mcp320x_read_raw, | |
f5ce4a7a OA |
299 | }; |
300 | ||
b12206e9 SA |
301 | static const struct mcp320x_chip_info mcp320x_chip_infos[] = { |
302 | [mcp3001] = { | |
303 | .channels = mcp3201_channels, | |
304 | .num_channels = ARRAY_SIZE(mcp3201_channels), | |
305 | .resolution = 10 | |
306 | }, | |
307 | [mcp3002] = { | |
308 | .channels = mcp3202_channels, | |
309 | .num_channels = ARRAY_SIZE(mcp3202_channels), | |
310 | .resolution = 10 | |
311 | }, | |
312 | [mcp3004] = { | |
313 | .channels = mcp3204_channels, | |
314 | .num_channels = ARRAY_SIZE(mcp3204_channels), | |
315 | .resolution = 10 | |
316 | }, | |
317 | [mcp3008] = { | |
318 | .channels = mcp3208_channels, | |
319 | .num_channels = ARRAY_SIZE(mcp3208_channels), | |
320 | .resolution = 10 | |
321 | }, | |
322 | [mcp3201] = { | |
323 | .channels = mcp3201_channels, | |
324 | .num_channels = ARRAY_SIZE(mcp3201_channels), | |
325 | .resolution = 12 | |
326 | }, | |
327 | [mcp3202] = { | |
328 | .channels = mcp3202_channels, | |
329 | .num_channels = ARRAY_SIZE(mcp3202_channels), | |
330 | .resolution = 12 | |
331 | }, | |
f5ce4a7a OA |
332 | [mcp3204] = { |
333 | .channels = mcp3204_channels, | |
b12206e9 SA |
334 | .num_channels = ARRAY_SIZE(mcp3204_channels), |
335 | .resolution = 12 | |
f5ce4a7a OA |
336 | }, |
337 | [mcp3208] = { | |
338 | .channels = mcp3208_channels, | |
b12206e9 SA |
339 | .num_channels = ARRAY_SIZE(mcp3208_channels), |
340 | .resolution = 12 | |
f5ce4a7a | 341 | }, |
f686a36b AG |
342 | [mcp3301] = { |
343 | .channels = mcp3201_channels, | |
344 | .num_channels = ARRAY_SIZE(mcp3201_channels), | |
345 | .resolution = 13 | |
346 | }, | |
c1375d67 LW |
347 | [mcp3550_50] = { |
348 | .channels = mcp3201_channels, | |
349 | .num_channels = ARRAY_SIZE(mcp3201_channels), | |
350 | .resolution = 21, | |
351 | /* 2% max deviation + 144 clock periods to exit shutdown */ | |
352 | .conv_time = 80000 * 1.02 + 144000 / 102.4, | |
353 | }, | |
354 | [mcp3550_60] = { | |
355 | .channels = mcp3201_channels, | |
356 | .num_channels = ARRAY_SIZE(mcp3201_channels), | |
357 | .resolution = 21, | |
358 | .conv_time = 66670 * 1.02 + 144000 / 122.88, | |
359 | }, | |
360 | [mcp3551] = { | |
361 | .channels = mcp3201_channels, | |
362 | .num_channels = ARRAY_SIZE(mcp3201_channels), | |
363 | .resolution = 21, | |
364 | .conv_time = 73100 * 1.02 + 144000 / 112.64, | |
365 | }, | |
366 | [mcp3553] = { | |
367 | .channels = mcp3201_channels, | |
368 | .num_channels = ARRAY_SIZE(mcp3201_channels), | |
369 | .resolution = 21, | |
370 | .conv_time = 16670 * 1.02 + 144000 / 122.88, | |
371 | }, | |
f5ce4a7a OA |
372 | }; |
373 | ||
58efe761 AM |
374 | static void mcp320x_regulator_disable(void *reg) |
375 | { | |
376 | regulator_disable(reg); | |
377 | } | |
378 | ||
f5ce4a7a OA |
379 | static int mcp320x_probe(struct spi_device *spi) |
380 | { | |
381 | struct iio_dev *indio_dev; | |
382 | struct mcp320x *adc; | |
b12206e9 | 383 | const struct mcp320x_chip_info *chip_info; |
c1375d67 | 384 | int ret, device_index; |
f5ce4a7a | 385 | |
a726dea5 | 386 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc)); |
f5ce4a7a OA |
387 | if (!indio_dev) |
388 | return -ENOMEM; | |
389 | ||
390 | adc = iio_priv(indio_dev); | |
391 | adc->spi = spi; | |
392 | ||
f5ce4a7a OA |
393 | indio_dev->name = spi_get_device_id(spi)->name; |
394 | indio_dev->modes = INDIO_DIRECT_MODE; | |
395 | indio_dev->info = &mcp320x_info; | |
396 | ||
c1375d67 LW |
397 | device_index = spi_get_device_id(spi)->driver_data; |
398 | chip_info = &mcp320x_chip_infos[device_index]; | |
f5ce4a7a OA |
399 | indio_dev->channels = chip_info->channels; |
400 | indio_dev->num_channels = chip_info->num_channels; | |
401 | ||
41be6a0d MS |
402 | adc->chip_info = chip_info; |
403 | ||
f5ce4a7a OA |
404 | adc->transfer[0].tx_buf = &adc->tx_buf; |
405 | adc->transfer[0].len = sizeof(adc->tx_buf); | |
406 | adc->transfer[1].rx_buf = adc->rx_buf; | |
c1375d67 LW |
407 | adc->transfer[1].len = DIV_ROUND_UP(chip_info->resolution, 8); |
408 | ||
ea910318 LW |
409 | if (chip_info->num_channels == 1) |
410 | /* single-channel converters are rx only (no MOSI pin) */ | |
411 | spi_message_init_with_transfers(&adc->msg, | |
412 | &adc->transfer[1], 1); | |
413 | else | |
414 | spi_message_init_with_transfers(&adc->msg, adc->transfer, | |
415 | ARRAY_SIZE(adc->transfer)); | |
f5ce4a7a | 416 | |
c1375d67 LW |
417 | switch (device_index) { |
418 | case mcp3550_50: | |
419 | case mcp3550_60: | |
420 | case mcp3551: | |
421 | case mcp3553: | |
422 | /* rx len increases from 24 to 25 bit in SPI mode 0,0 */ | |
423 | if (!(spi->mode & SPI_CPOL)) | |
424 | adc->transfer[1].len++; | |
425 | ||
426 | /* conversions are started by asserting CS pin for 8 usec */ | |
eccd0718 SC |
427 | adc->start_conv_transfer.delay.value = 8; |
428 | adc->start_conv_transfer.delay.unit = SPI_DELAY_UNIT_USECS; | |
c1375d67 LW |
429 | spi_message_init_with_transfers(&adc->start_conv_msg, |
430 | &adc->start_conv_transfer, 1); | |
431 | ||
432 | /* | |
433 | * If CS was previously kept low (continuous conversion mode) | |
434 | * and then changed to high, the chip is in shutdown. | |
435 | * Sometimes it fails to wake from shutdown and clocks out | |
436 | * only 0xffffff. The magic sequence of performing two | |
437 | * conversions without delay between them resets the chip | |
438 | * and ensures all subsequent conversions succeed. | |
439 | */ | |
440 | mcp320x_adc_conversion(adc, 0, 1, device_index, &ret); | |
441 | mcp320x_adc_conversion(adc, 0, 1, device_index, &ret); | |
442 | } | |
443 | ||
a726dea5 SK |
444 | adc->reg = devm_regulator_get(&spi->dev, "vref"); |
445 | if (IS_ERR(adc->reg)) | |
446 | return PTR_ERR(adc->reg); | |
f5ce4a7a OA |
447 | |
448 | ret = regulator_enable(adc->reg); | |
449 | if (ret < 0) | |
a726dea5 | 450 | return ret; |
f5ce4a7a | 451 | |
58efe761 | 452 | ret = devm_add_action_or_reset(&spi->dev, mcp320x_regulator_disable, adc->reg); |
f5ce4a7a | 453 | if (ret < 0) |
58efe761 | 454 | return ret; |
f5ce4a7a | 455 | |
58efe761 | 456 | mutex_init(&adc->lock); |
f5ce4a7a | 457 | |
58efe761 | 458 | return devm_iio_device_register(&spi->dev, indio_dev); |
f5ce4a7a OA |
459 | } |
460 | ||
b12206e9 | 461 | static const struct of_device_id mcp320x_dt_ids[] = { |
35ed9fbf LW |
462 | { .compatible = "microchip,mcp3001" }, |
463 | { .compatible = "microchip,mcp3002" }, | |
464 | { .compatible = "microchip,mcp3004" }, | |
465 | { .compatible = "microchip,mcp3008" }, | |
466 | { .compatible = "microchip,mcp3201" }, | |
467 | { .compatible = "microchip,mcp3202" }, | |
468 | { .compatible = "microchip,mcp3204" }, | |
469 | { .compatible = "microchip,mcp3208" }, | |
470 | { .compatible = "microchip,mcp3301" }, | |
c1375d67 LW |
471 | { .compatible = "microchip,mcp3550-50" }, |
472 | { .compatible = "microchip,mcp3550-60" }, | |
473 | { .compatible = "microchip,mcp3551" }, | |
474 | { .compatible = "microchip,mcp3553" }, | |
35ed9fbf | 475 | { } |
b12206e9 SA |
476 | }; |
477 | MODULE_DEVICE_TABLE(of, mcp320x_dt_ids); | |
b12206e9 | 478 | |
f5ce4a7a | 479 | static const struct spi_device_id mcp320x_id[] = { |
b12206e9 SA |
480 | { "mcp3001", mcp3001 }, |
481 | { "mcp3002", mcp3002 }, | |
482 | { "mcp3004", mcp3004 }, | |
483 | { "mcp3008", mcp3008 }, | |
484 | { "mcp3201", mcp3201 }, | |
485 | { "mcp3202", mcp3202 }, | |
f5ce4a7a OA |
486 | { "mcp3204", mcp3204 }, |
487 | { "mcp3208", mcp3208 }, | |
f686a36b | 488 | { "mcp3301", mcp3301 }, |
c1375d67 LW |
489 | { "mcp3550-50", mcp3550_50 }, |
490 | { "mcp3550-60", mcp3550_60 }, | |
491 | { "mcp3551", mcp3551 }, | |
492 | { "mcp3553", mcp3553 }, | |
f5ce4a7a OA |
493 | { } |
494 | }; | |
495 | MODULE_DEVICE_TABLE(spi, mcp320x_id); | |
496 | ||
497 | static struct spi_driver mcp320x_driver = { | |
498 | .driver = { | |
499 | .name = "mcp320x", | |
016d271e | 500 | .of_match_table = mcp320x_dt_ids, |
f5ce4a7a OA |
501 | }, |
502 | .probe = mcp320x_probe, | |
f5ce4a7a OA |
503 | .id_table = mcp320x_id, |
504 | }; | |
505 | module_spi_driver(mcp320x_driver); | |
506 | ||
507 | MODULE_AUTHOR("Oskar Andero <oskar.andero@gmail.com>"); | |
c1375d67 | 508 | MODULE_DESCRIPTION("Microchip Technology MCP3x01/02/04/08 and MCP3550/1/3"); |
f5ce4a7a | 509 | MODULE_LICENSE("GPL v2"); |