1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Industrial I/O driver for Microchip digital potentiometers |
4 | * |
5 | * Copyright (c) 2016 Slawomir Stepien |
6 | * Based on: Peter Rosin's code from mcp4531.c |
7 | * |
8 | * Datasheet: https://ww1.microchip.com/downloads/en/DeviceDoc/22060b.pdf |
9 | * |
10 | * DEVID #Wipers #Positions Resistor Opts (kOhm) |
11 | * mcp4131 1 129 5, 10, 50, 100 |
12 | * mcp4132 1 129 5, 10, 50, 100 |
13 | * mcp4141 1 129 5, 10, 50, 100 |
14 | * mcp4142 1 129 5, 10, 50, 100 |
15 | * mcp4151 1 257 5, 10, 50, 100 |
16 | * mcp4152 1 257 5, 10, 50, 100 |
17 | * mcp4161 1 257 5, 10, 50, 100 |
18 | * mcp4162 1 257 5, 10, 50, 100 |
19 | * mcp4231 2 129 5, 10, 50, 100 |
20 | * mcp4232 2 129 5, 10, 50, 100 |
21 | * mcp4241 2 129 5, 10, 50, 100 |
22 | * mcp4242 2 129 5, 10, 50, 100 |
23 | * mcp4251 2 257 5, 10, 50, 100 |
24 | * mcp4252 2 257 5, 10, 50, 100 |
25 | * mcp4261 2 257 5, 10, 50, 100 |
26 | * mcp4262 2 257 5, 10, 50, 100 |
27 | */ |
28 | |
29 | /* |
30 | * TODO: |
31 | * 1. Write wiper setting to EEPROM for EEPROM capable models. |
32 | */ |
33 | |
34 | #include <linux/cache.h> |
35 | #include <linux/err.h> |
36 | #include <linux/export.h> |
37 | #include <linux/iio/iio.h> |
38 | #include <linux/iio/types.h> |
39 | #include <linux/module.h> |
40 | #include <linux/mod_devicetable.h> |
41 | #include <linux/mutex.h> |
42 | #include <linux/property.h> |
43 | #include <linux/spi/spi.h> |
44 | |
45 | #define MCP4131_WRITE (0x00 << 2) |
46 | #define MCP4131_READ (0x03 << 2) |
47 | |
48 | #define MCP4131_WIPER_SHIFT 4 |
49 | #define MCP4131_CMDERR(r) ((r[0]) & 0x02) |
50 | #define MCP4131_RAW(r) ((r[0]) == 0xff ? 0x100 : (r[1])) |
51 | |
52 | struct mcp4131_cfg { |
53 | int wipers; |
54 | int max_pos; |
55 | int kohms; |
56 | }; |
57 | |
58 | enum mcp4131_type { |
59 | MCP413x_502 = 0, |
60 | MCP413x_103, |
61 | MCP413x_503, |
62 | MCP413x_104, |
63 | MCP414x_502, |
64 | MCP414x_103, |
65 | MCP414x_503, |
66 | MCP414x_104, |
67 | MCP415x_502, |
68 | MCP415x_103, |
69 | MCP415x_503, |
70 | MCP415x_104, |
71 | MCP416x_502, |
72 | MCP416x_103, |
73 | MCP416x_503, |
74 | MCP416x_104, |
75 | MCP423x_502, |
76 | MCP423x_103, |
77 | MCP423x_503, |
78 | MCP423x_104, |
79 | MCP424x_502, |
80 | MCP424x_103, |
81 | MCP424x_503, |
82 | MCP424x_104, |
83 | MCP425x_502, |
84 | MCP425x_103, |
85 | MCP425x_503, |
86 | MCP425x_104, |
87 | MCP426x_502, |
88 | MCP426x_103, |
89 | MCP426x_503, |
90 | MCP426x_104, |
91 | }; |
92 | |
93 | static const struct mcp4131_cfg mcp4131_cfg[] = { |
94 | [MCP413x_502] = { .wipers = 1, .max_pos = 128, .kohms = 5, }, |
95 | [MCP413x_103] = { .wipers = 1, .max_pos = 128, .kohms = 10, }, |
96 | [MCP413x_503] = { .wipers = 1, .max_pos = 128, .kohms = 50, }, |
97 | [MCP413x_104] = { .wipers = 1, .max_pos = 128, .kohms = 100, }, |
98 | [MCP414x_502] = { .wipers = 1, .max_pos = 128, .kohms = 5, }, |
99 | [MCP414x_103] = { .wipers = 1, .max_pos = 128, .kohms = 10, }, |
100 | [MCP414x_503] = { .wipers = 1, .max_pos = 128, .kohms = 50, }, |
101 | [MCP414x_104] = { .wipers = 1, .max_pos = 128, .kohms = 100, }, |
102 | [MCP415x_502] = { .wipers = 1, .max_pos = 256, .kohms = 5, }, |
103 | [MCP415x_103] = { .wipers = 1, .max_pos = 256, .kohms = 10, }, |
104 | [MCP415x_503] = { .wipers = 1, .max_pos = 256, .kohms = 50, }, |
105 | [MCP415x_104] = { .wipers = 1, .max_pos = 256, .kohms = 100, }, |
106 | [MCP416x_502] = { .wipers = 1, .max_pos = 256, .kohms = 5, }, |
107 | [MCP416x_103] = { .wipers = 1, .max_pos = 256, .kohms = 10, }, |
108 | [MCP416x_503] = { .wipers = 1, .max_pos = 256, .kohms = 50, }, |
109 | [MCP416x_104] = { .wipers = 1, .max_pos = 256, .kohms = 100, }, |
110 | [MCP423x_502] = { .wipers = 2, .max_pos = 128, .kohms = 5, }, |
111 | [MCP423x_103] = { .wipers = 2, .max_pos = 128, .kohms = 10, }, |
112 | [MCP423x_503] = { .wipers = 2, .max_pos = 128, .kohms = 50, }, |
113 | [MCP423x_104] = { .wipers = 2, .max_pos = 128, .kohms = 100, }, |
114 | [MCP424x_502] = { .wipers = 2, .max_pos = 128, .kohms = 5, }, |
115 | [MCP424x_103] = { .wipers = 2, .max_pos = 128, .kohms = 10, }, |
116 | [MCP424x_503] = { .wipers = 2, .max_pos = 128, .kohms = 50, }, |
117 | [MCP424x_104] = { .wipers = 2, .max_pos = 128, .kohms = 100, }, |
118 | [MCP425x_502] = { .wipers = 2, .max_pos = 256, .kohms = 5, }, |
119 | [MCP425x_103] = { .wipers = 2, .max_pos = 256, .kohms = 10, }, |
120 | [MCP425x_503] = { .wipers = 2, .max_pos = 256, .kohms = 50, }, |
121 | [MCP425x_104] = { .wipers = 2, .max_pos = 256, .kohms = 100, }, |
122 | [MCP426x_502] = { .wipers = 2, .max_pos = 256, .kohms = 5, }, |
123 | [MCP426x_103] = { .wipers = 2, .max_pos = 256, .kohms = 10, }, |
124 | [MCP426x_503] = { .wipers = 2, .max_pos = 256, .kohms = 50, }, |
125 | [MCP426x_104] = { .wipers = 2, .max_pos = 256, .kohms = 100, }, |
126 | }; |
127 | |
128 | struct mcp4131_data { |
129 | struct spi_device *spi; |
130 | const struct mcp4131_cfg *cfg; |
131 | struct mutex lock; |
132 | u8 buf[2] __aligned(IIO_DMA_MINALIGN); |
133 | }; |
134 | |
135 | #define MCP4131_CHANNEL(ch) { \ |
136 | .type = IIO_RESISTANCE, \ |
137 | .indexed = 1, \ |
138 | .output = 1, \ |
139 | .channel = (ch), \ |
140 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ |
141 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ |
142 | } |
143 | |
144 | static const struct iio_chan_spec mcp4131_channels[] = { |
145 | MCP4131_CHANNEL(0), |
146 | MCP4131_CHANNEL(1), |
147 | }; |
148 | |
149 | static int mcp4131_read(struct spi_device *spi, void *buf, size_t len) |
150 | { |
151 | struct spi_transfer t = { |
152 | .tx_buf = buf, /* We need to send addr, cmd and 12 bits */ |
153 | .rx_buf = buf, |
154 | .len = len, |
155 | }; |
156 | struct spi_message m; |
157 | |
158 | spi_message_init(m: &m); |
159 | spi_message_add_tail(t: &t, m: &m); |
160 | |
161 | return spi_sync(spi, message: &m); |
162 | } |
163 | |
164 | static int mcp4131_read_raw(struct iio_dev *indio_dev, |
165 | struct iio_chan_spec const *chan, |
166 | int *val, int *val2, long mask) |
167 | { |
168 | int err; |
169 | struct mcp4131_data *data = iio_priv(indio_dev); |
170 | int address = chan->channel; |
171 | |
172 | switch (mask) { |
173 | case IIO_CHAN_INFO_RAW: |
174 | mutex_lock(&data->lock); |
175 | |
176 | data->buf[0] = (address << MCP4131_WIPER_SHIFT) | MCP4131_READ; |
177 | data->buf[1] = 0; |
178 | |
179 | err = mcp4131_read(spi: data->spi, buf: data->buf, len: 2); |
180 | if (err) { |
181 | mutex_unlock(lock: &data->lock); |
182 | return err; |
183 | } |
184 | |
185 | /* Error, bad address/command combination */ |
186 | if (!MCP4131_CMDERR(data->buf)) { |
187 | mutex_unlock(lock: &data->lock); |
188 | return -EIO; |
189 | } |
190 | |
191 | *val = MCP4131_RAW(data->buf); |
192 | mutex_unlock(lock: &data->lock); |
193 | |
194 | return IIO_VAL_INT; |
195 | |
196 | case IIO_CHAN_INFO_SCALE: |
197 | *val = 1000 * data->cfg->kohms; |
198 | *val2 = data->cfg->max_pos; |
199 | return IIO_VAL_FRACTIONAL; |
200 | } |
201 | |
202 | return -EINVAL; |
203 | } |
204 | |
205 | static int mcp4131_write_raw(struct iio_dev *indio_dev, |
206 | struct iio_chan_spec const *chan, |
207 | int val, int val2, long mask) |
208 | { |
209 | int err; |
210 | struct mcp4131_data *data = iio_priv(indio_dev); |
211 | int address = chan->channel << MCP4131_WIPER_SHIFT; |
212 | |
213 | switch (mask) { |
214 | case IIO_CHAN_INFO_RAW: |
215 | if (val > data->cfg->max_pos || val < 0) |
216 | return -EINVAL; |
217 | break; |
218 | |
219 | default: |
220 | return -EINVAL; |
221 | } |
222 | |
223 | mutex_lock(&data->lock); |
224 | |
225 | data->buf[0] = address << MCP4131_WIPER_SHIFT; |
226 | data->buf[0] |= MCP4131_WRITE | (val >> 8); |
227 | data->buf[1] = val & 0xFF; /* 8 bits here */ |
228 | |
229 | err = spi_write(spi: data->spi, buf: data->buf, len: 2); |
230 | mutex_unlock(lock: &data->lock); |
231 | |
232 | return err; |
233 | } |
234 | |
235 | static const struct iio_info mcp4131_info = { |
236 | .read_raw = mcp4131_read_raw, |
237 | .write_raw = mcp4131_write_raw, |
238 | }; |
239 | |
240 | static int mcp4131_probe(struct spi_device *spi) |
241 | { |
242 | int err; |
243 | struct device *dev = &spi->dev; |
244 | unsigned long devid; |
245 | struct mcp4131_data *data; |
246 | struct iio_dev *indio_dev; |
247 | |
248 | indio_dev = devm_iio_device_alloc(parent: dev, sizeof_priv: sizeof(*data)); |
249 | if (!indio_dev) |
250 | return -ENOMEM; |
251 | |
252 | data = iio_priv(indio_dev); |
253 | spi_set_drvdata(spi, data: indio_dev); |
254 | data->spi = spi; |
255 | data->cfg = device_get_match_data(dev: &spi->dev); |
256 | if (!data->cfg) { |
257 | devid = spi_get_device_id(sdev: spi)->driver_data; |
258 | data->cfg = &mcp4131_cfg[devid]; |
259 | } |
260 | |
261 | mutex_init(&data->lock); |
262 | |
263 | indio_dev->info = &mcp4131_info; |
264 | indio_dev->channels = mcp4131_channels; |
265 | indio_dev->num_channels = data->cfg->wipers; |
266 | indio_dev->name = spi_get_device_id(sdev: spi)->name; |
267 | |
268 | err = devm_iio_device_register(dev, indio_dev); |
269 | if (err) { |
270 | dev_info(&spi->dev, "Unable to register %s\n" , indio_dev->name); |
271 | return err; |
272 | } |
273 | |
274 | return 0; |
275 | } |
276 | |
277 | static const struct of_device_id mcp4131_dt_ids[] = { |
278 | { .compatible = "microchip,mcp4131-502" , |
279 | .data = &mcp4131_cfg[MCP413x_502] }, |
280 | { .compatible = "microchip,mcp4131-103" , |
281 | .data = &mcp4131_cfg[MCP413x_103] }, |
282 | { .compatible = "microchip,mcp4131-503" , |
283 | .data = &mcp4131_cfg[MCP413x_503] }, |
284 | { .compatible = "microchip,mcp4131-104" , |
285 | .data = &mcp4131_cfg[MCP413x_104] }, |
286 | { .compatible = "microchip,mcp4132-502" , |
287 | .data = &mcp4131_cfg[MCP413x_502] }, |
288 | { .compatible = "microchip,mcp4132-103" , |
289 | .data = &mcp4131_cfg[MCP413x_103] }, |
290 | { .compatible = "microchip,mcp4132-503" , |
291 | .data = &mcp4131_cfg[MCP413x_503] }, |
292 | { .compatible = "microchip,mcp4132-104" , |
293 | .data = &mcp4131_cfg[MCP413x_104] }, |
294 | { .compatible = "microchip,mcp4141-502" , |
295 | .data = &mcp4131_cfg[MCP414x_502] }, |
296 | { .compatible = "microchip,mcp4141-103" , |
297 | .data = &mcp4131_cfg[MCP414x_103] }, |
298 | { .compatible = "microchip,mcp4141-503" , |
299 | .data = &mcp4131_cfg[MCP414x_503] }, |
300 | { .compatible = "microchip,mcp4141-104" , |
301 | .data = &mcp4131_cfg[MCP414x_104] }, |
302 | { .compatible = "microchip,mcp4142-502" , |
303 | .data = &mcp4131_cfg[MCP414x_502] }, |
304 | { .compatible = "microchip,mcp4142-103" , |
305 | .data = &mcp4131_cfg[MCP414x_103] }, |
306 | { .compatible = "microchip,mcp4142-503" , |
307 | .data = &mcp4131_cfg[MCP414x_503] }, |
308 | { .compatible = "microchip,mcp4142-104" , |
309 | .data = &mcp4131_cfg[MCP414x_104] }, |
310 | { .compatible = "microchip,mcp4151-502" , |
311 | .data = &mcp4131_cfg[MCP415x_502] }, |
312 | { .compatible = "microchip,mcp4151-103" , |
313 | .data = &mcp4131_cfg[MCP415x_103] }, |
314 | { .compatible = "microchip,mcp4151-503" , |
315 | .data = &mcp4131_cfg[MCP415x_503] }, |
316 | { .compatible = "microchip,mcp4151-104" , |
317 | .data = &mcp4131_cfg[MCP415x_104] }, |
318 | { .compatible = "microchip,mcp4152-502" , |
319 | .data = &mcp4131_cfg[MCP415x_502] }, |
320 | { .compatible = "microchip,mcp4152-103" , |
321 | .data = &mcp4131_cfg[MCP415x_103] }, |
322 | { .compatible = "microchip,mcp4152-503" , |
323 | .data = &mcp4131_cfg[MCP415x_503] }, |
324 | { .compatible = "microchip,mcp4152-104" , |
325 | .data = &mcp4131_cfg[MCP415x_104] }, |
326 | { .compatible = "microchip,mcp4161-502" , |
327 | .data = &mcp4131_cfg[MCP416x_502] }, |
328 | { .compatible = "microchip,mcp4161-103" , |
329 | .data = &mcp4131_cfg[MCP416x_103] }, |
330 | { .compatible = "microchip,mcp4161-503" , |
331 | .data = &mcp4131_cfg[MCP416x_503] }, |
332 | { .compatible = "microchip,mcp4161-104" , |
333 | .data = &mcp4131_cfg[MCP416x_104] }, |
334 | { .compatible = "microchip,mcp4162-502" , |
335 | .data = &mcp4131_cfg[MCP416x_502] }, |
336 | { .compatible = "microchip,mcp4162-103" , |
337 | .data = &mcp4131_cfg[MCP416x_103] }, |
338 | { .compatible = "microchip,mcp4162-503" , |
339 | .data = &mcp4131_cfg[MCP416x_503] }, |
340 | { .compatible = "microchip,mcp4162-104" , |
341 | .data = &mcp4131_cfg[MCP416x_104] }, |
342 | { .compatible = "microchip,mcp4231-502" , |
343 | .data = &mcp4131_cfg[MCP423x_502] }, |
344 | { .compatible = "microchip,mcp4231-103" , |
345 | .data = &mcp4131_cfg[MCP423x_103] }, |
346 | { .compatible = "microchip,mcp4231-503" , |
347 | .data = &mcp4131_cfg[MCP423x_503] }, |
348 | { .compatible = "microchip,mcp4231-104" , |
349 | .data = &mcp4131_cfg[MCP423x_104] }, |
350 | { .compatible = "microchip,mcp4232-502" , |
351 | .data = &mcp4131_cfg[MCP423x_502] }, |
352 | { .compatible = "microchip,mcp4232-103" , |
353 | .data = &mcp4131_cfg[MCP423x_103] }, |
354 | { .compatible = "microchip,mcp4232-503" , |
355 | .data = &mcp4131_cfg[MCP423x_503] }, |
356 | { .compatible = "microchip,mcp4232-104" , |
357 | .data = &mcp4131_cfg[MCP423x_104] }, |
358 | { .compatible = "microchip,mcp4241-502" , |
359 | .data = &mcp4131_cfg[MCP424x_502] }, |
360 | { .compatible = "microchip,mcp4241-103" , |
361 | .data = &mcp4131_cfg[MCP424x_103] }, |
362 | { .compatible = "microchip,mcp4241-503" , |
363 | .data = &mcp4131_cfg[MCP424x_503] }, |
364 | { .compatible = "microchip,mcp4241-104" , |
365 | .data = &mcp4131_cfg[MCP424x_104] }, |
366 | { .compatible = "microchip,mcp4242-502" , |
367 | .data = &mcp4131_cfg[MCP424x_502] }, |
368 | { .compatible = "microchip,mcp4242-103" , |
369 | .data = &mcp4131_cfg[MCP424x_103] }, |
370 | { .compatible = "microchip,mcp4242-503" , |
371 | .data = &mcp4131_cfg[MCP424x_503] }, |
372 | { .compatible = "microchip,mcp4242-104" , |
373 | .data = &mcp4131_cfg[MCP424x_104] }, |
374 | { .compatible = "microchip,mcp4251-502" , |
375 | .data = &mcp4131_cfg[MCP425x_502] }, |
376 | { .compatible = "microchip,mcp4251-103" , |
377 | .data = &mcp4131_cfg[MCP425x_103] }, |
378 | { .compatible = "microchip,mcp4251-503" , |
379 | .data = &mcp4131_cfg[MCP425x_503] }, |
380 | { .compatible = "microchip,mcp4251-104" , |
381 | .data = &mcp4131_cfg[MCP425x_104] }, |
382 | { .compatible = "microchip,mcp4252-502" , |
383 | .data = &mcp4131_cfg[MCP425x_502] }, |
384 | { .compatible = "microchip,mcp4252-103" , |
385 | .data = &mcp4131_cfg[MCP425x_103] }, |
386 | { .compatible = "microchip,mcp4252-503" , |
387 | .data = &mcp4131_cfg[MCP425x_503] }, |
388 | { .compatible = "microchip,mcp4252-104" , |
389 | .data = &mcp4131_cfg[MCP425x_104] }, |
390 | { .compatible = "microchip,mcp4261-502" , |
391 | .data = &mcp4131_cfg[MCP426x_502] }, |
392 | { .compatible = "microchip,mcp4261-103" , |
393 | .data = &mcp4131_cfg[MCP426x_103] }, |
394 | { .compatible = "microchip,mcp4261-503" , |
395 | .data = &mcp4131_cfg[MCP426x_503] }, |
396 | { .compatible = "microchip,mcp4261-104" , |
397 | .data = &mcp4131_cfg[MCP426x_104] }, |
398 | { .compatible = "microchip,mcp4262-502" , |
399 | .data = &mcp4131_cfg[MCP426x_502] }, |
400 | { .compatible = "microchip,mcp4262-103" , |
401 | .data = &mcp4131_cfg[MCP426x_103] }, |
402 | { .compatible = "microchip,mcp4262-503" , |
403 | .data = &mcp4131_cfg[MCP426x_503] }, |
404 | { .compatible = "microchip,mcp4262-104" , |
405 | .data = &mcp4131_cfg[MCP426x_104] }, |
406 | {} |
407 | }; |
408 | MODULE_DEVICE_TABLE(of, mcp4131_dt_ids); |
409 | |
410 | static const struct spi_device_id mcp4131_id[] = { |
411 | { "mcp4131-502" , MCP413x_502 }, |
412 | { "mcp4131-103" , MCP413x_103 }, |
413 | { "mcp4131-503" , MCP413x_503 }, |
414 | { "mcp4131-104" , MCP413x_104 }, |
415 | { "mcp4132-502" , MCP413x_502 }, |
416 | { "mcp4132-103" , MCP413x_103 }, |
417 | { "mcp4132-503" , MCP413x_503 }, |
418 | { "mcp4132-104" , MCP413x_104 }, |
419 | { "mcp4141-502" , MCP414x_502 }, |
420 | { "mcp4141-103" , MCP414x_103 }, |
421 | { "mcp4141-503" , MCP414x_503 }, |
422 | { "mcp4141-104" , MCP414x_104 }, |
423 | { "mcp4142-502" , MCP414x_502 }, |
424 | { "mcp4142-103" , MCP414x_103 }, |
425 | { "mcp4142-503" , MCP414x_503 }, |
426 | { "mcp4142-104" , MCP414x_104 }, |
427 | { "mcp4151-502" , MCP415x_502 }, |
428 | { "mcp4151-103" , MCP415x_103 }, |
429 | { "mcp4151-503" , MCP415x_503 }, |
430 | { "mcp4151-104" , MCP415x_104 }, |
431 | { "mcp4152-502" , MCP415x_502 }, |
432 | { "mcp4152-103" , MCP415x_103 }, |
433 | { "mcp4152-503" , MCP415x_503 }, |
434 | { "mcp4152-104" , MCP415x_104 }, |
435 | { "mcp4161-502" , MCP416x_502 }, |
436 | { "mcp4161-103" , MCP416x_103 }, |
437 | { "mcp4161-503" , MCP416x_503 }, |
438 | { "mcp4161-104" , MCP416x_104 }, |
439 | { "mcp4162-502" , MCP416x_502 }, |
440 | { "mcp4162-103" , MCP416x_103 }, |
441 | { "mcp4162-503" , MCP416x_503 }, |
442 | { "mcp4162-104" , MCP416x_104 }, |
443 | { "mcp4231-502" , MCP423x_502 }, |
444 | { "mcp4231-103" , MCP423x_103 }, |
445 | { "mcp4231-503" , MCP423x_503 }, |
446 | { "mcp4231-104" , MCP423x_104 }, |
447 | { "mcp4232-502" , MCP423x_502 }, |
448 | { "mcp4232-103" , MCP423x_103 }, |
449 | { "mcp4232-503" , MCP423x_503 }, |
450 | { "mcp4232-104" , MCP423x_104 }, |
451 | { "mcp4241-502" , MCP424x_502 }, |
452 | { "mcp4241-103" , MCP424x_103 }, |
453 | { "mcp4241-503" , MCP424x_503 }, |
454 | { "mcp4241-104" , MCP424x_104 }, |
455 | { "mcp4242-502" , MCP424x_502 }, |
456 | { "mcp4242-103" , MCP424x_103 }, |
457 | { "mcp4242-503" , MCP424x_503 }, |
458 | { "mcp4242-104" , MCP424x_104 }, |
459 | { "mcp4251-502" , MCP425x_502 }, |
460 | { "mcp4251-103" , MCP425x_103 }, |
461 | { "mcp4251-503" , MCP425x_503 }, |
462 | { "mcp4251-104" , MCP425x_104 }, |
463 | { "mcp4252-502" , MCP425x_502 }, |
464 | { "mcp4252-103" , MCP425x_103 }, |
465 | { "mcp4252-503" , MCP425x_503 }, |
466 | { "mcp4252-104" , MCP425x_104 }, |
467 | { "mcp4261-502" , MCP426x_502 }, |
468 | { "mcp4261-103" , MCP426x_103 }, |
469 | { "mcp4261-503" , MCP426x_503 }, |
470 | { "mcp4261-104" , MCP426x_104 }, |
471 | { "mcp4262-502" , MCP426x_502 }, |
472 | { "mcp4262-103" , MCP426x_103 }, |
473 | { "mcp4262-503" , MCP426x_503 }, |
474 | { "mcp4262-104" , MCP426x_104 }, |
475 | {} |
476 | }; |
477 | MODULE_DEVICE_TABLE(spi, mcp4131_id); |
478 | |
479 | static struct spi_driver mcp4131_driver = { |
480 | .driver = { |
481 | .name = "mcp4131" , |
482 | .of_match_table = mcp4131_dt_ids, |
483 | }, |
484 | .probe = mcp4131_probe, |
485 | .id_table = mcp4131_id, |
486 | }; |
487 | |
488 | module_spi_driver(mcp4131_driver); |
489 | |
490 | MODULE_AUTHOR("Slawomir Stepien <sst@poczta.fm>" ); |
491 | MODULE_DESCRIPTION("MCP4131 digital potentiometer" ); |
492 | MODULE_LICENSE("GPL v2" ); |
493 | |