2 * Industrial I/O driver for Microchip digital potentiometers
3 * Copyright (c) 2015 Axentia Technologies AB
4 * Author: Peter Rosin <peda@axentia.se>
6 * Datasheet: http://www.microchip.com/downloads/en/DeviceDoc/22096b.pdf
8 * DEVID #Wipers #Positions Resistor Opts (kOhm) i2c address
9 * mcp4531 1 129 5, 10, 50, 100 010111x
10 * mcp4532 1 129 5, 10, 50, 100 01011xx
11 * mcp4541 1 129 5, 10, 50, 100 010111x
12 * mcp4542 1 129 5, 10, 50, 100 01011xx
13 * mcp4551 1 257 5, 10, 50, 100 010111x
14 * mcp4552 1 257 5, 10, 50, 100 01011xx
15 * mcp4561 1 257 5, 10, 50, 100 010111x
16 * mcp4562 1 257 5, 10, 50, 100 01011xx
17 * mcp4631 2 129 5, 10, 50, 100 0101xxx
18 * mcp4632 2 129 5, 10, 50, 100 01011xx
19 * mcp4641 2 129 5, 10, 50, 100 0101xxx
20 * mcp4642 2 129 5, 10, 50, 100 01011xx
21 * mcp4651 2 257 5, 10, 50, 100 0101xxx
22 * mcp4652 2 257 5, 10, 50, 100 01011xx
23 * mcp4661 2 257 5, 10, 50, 100 0101xxx
24 * mcp4662 2 257 5, 10, 50, 100 01011xx
26 * This program is free software; you can redistribute it and/or modify it
27 * under the terms of the GNU General Public License version 2 as published by
28 * the Free Software Foundation.
31 #include <linux/module.h>
32 #include <linux/i2c.h>
33 #include <linux/err.h>
35 #include <linux/of_device.h>
37 #include <linux/iio/iio.h>
80 static const struct mcp4531_cfg mcp4531_cfg
[] = {
81 [MCP453x_502
] = { .wipers
= 1, .avail
= { 0, 1, 128 }, .kohms
= 5, },
82 [MCP453x_103
] = { .wipers
= 1, .avail
= { 0, 1, 128 }, .kohms
= 10, },
83 [MCP453x_503
] = { .wipers
= 1, .avail
= { 0, 1, 128 }, .kohms
= 50, },
84 [MCP453x_104
] = { .wipers
= 1, .avail
= { 0, 1, 128 }, .kohms
= 100, },
85 [MCP454x_502
] = { .wipers
= 1, .avail
= { 0, 1, 128 }, .kohms
= 5, },
86 [MCP454x_103
] = { .wipers
= 1, .avail
= { 0, 1, 128 }, .kohms
= 10, },
87 [MCP454x_503
] = { .wipers
= 1, .avail
= { 0, 1, 128 }, .kohms
= 50, },
88 [MCP454x_104
] = { .wipers
= 1, .avail
= { 0, 1, 128 }, .kohms
= 100, },
89 [MCP455x_502
] = { .wipers
= 1, .avail
= { 0, 1, 256 }, .kohms
= 5, },
90 [MCP455x_103
] = { .wipers
= 1, .avail
= { 0, 1, 256 }, .kohms
= 10, },
91 [MCP455x_503
] = { .wipers
= 1, .avail
= { 0, 1, 256 }, .kohms
= 50, },
92 [MCP455x_104
] = { .wipers
= 1, .avail
= { 0, 1, 256 }, .kohms
= 100, },
93 [MCP456x_502
] = { .wipers
= 1, .avail
= { 0, 1, 256 }, .kohms
= 5, },
94 [MCP456x_103
] = { .wipers
= 1, .avail
= { 0, 1, 256 }, .kohms
= 10, },
95 [MCP456x_503
] = { .wipers
= 1, .avail
= { 0, 1, 256 }, .kohms
= 50, },
96 [MCP456x_104
] = { .wipers
= 1, .avail
= { 0, 1, 256 }, .kohms
= 100, },
97 [MCP463x_502
] = { .wipers
= 2, .avail
= { 0, 1, 128 }, .kohms
= 5, },
98 [MCP463x_103
] = { .wipers
= 2, .avail
= { 0, 1, 128 }, .kohms
= 10, },
99 [MCP463x_503
] = { .wipers
= 2, .avail
= { 0, 1, 128 }, .kohms
= 50, },
100 [MCP463x_104
] = { .wipers
= 2, .avail
= { 0, 1, 128 }, .kohms
= 100, },
101 [MCP464x_502
] = { .wipers
= 2, .avail
= { 0, 1, 128 }, .kohms
= 5, },
102 [MCP464x_103
] = { .wipers
= 2, .avail
= { 0, 1, 128 }, .kohms
= 10, },
103 [MCP464x_503
] = { .wipers
= 2, .avail
= { 0, 1, 128 }, .kohms
= 50, },
104 [MCP464x_104
] = { .wipers
= 2, .avail
= { 0, 1, 128 }, .kohms
= 100, },
105 [MCP465x_502
] = { .wipers
= 2, .avail
= { 0, 1, 256 }, .kohms
= 5, },
106 [MCP465x_103
] = { .wipers
= 2, .avail
= { 0, 1, 256 }, .kohms
= 10, },
107 [MCP465x_503
] = { .wipers
= 2, .avail
= { 0, 1, 256 }, .kohms
= 50, },
108 [MCP465x_104
] = { .wipers
= 2, .avail
= { 0, 1, 256 }, .kohms
= 100, },
109 [MCP466x_502
] = { .wipers
= 2, .avail
= { 0, 1, 256 }, .kohms
= 5, },
110 [MCP466x_103
] = { .wipers
= 2, .avail
= { 0, 1, 256 }, .kohms
= 10, },
111 [MCP466x_503
] = { .wipers
= 2, .avail
= { 0, 1, 256 }, .kohms
= 50, },
112 [MCP466x_104
] = { .wipers
= 2, .avail
= { 0, 1, 256 }, .kohms
= 100, },
115 #define MCP4531_WRITE (0 << 2)
116 #define MCP4531_INCR (1 << 2)
117 #define MCP4531_DECR (2 << 2)
118 #define MCP4531_READ (3 << 2)
120 #define MCP4531_WIPER_SHIFT (4)
122 struct mcp4531_data
{
123 struct i2c_client
*client
;
124 const struct mcp4531_cfg
*cfg
;
127 #define MCP4531_CHANNEL(ch) { \
128 .type = IIO_RESISTANCE, \
132 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
133 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
134 .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_RAW), \
137 static const struct iio_chan_spec mcp4531_channels
[] = {
142 static int mcp4531_read_raw(struct iio_dev
*indio_dev
,
143 struct iio_chan_spec
const *chan
,
144 int *val
, int *val2
, long mask
)
146 struct mcp4531_data
*data
= iio_priv(indio_dev
);
147 int address
= chan
->channel
<< MCP4531_WIPER_SHIFT
;
151 case IIO_CHAN_INFO_RAW
:
152 ret
= i2c_smbus_read_word_swapped(data
->client
,
153 MCP4531_READ
| address
);
158 case IIO_CHAN_INFO_SCALE
:
159 *val
= 1000 * data
->cfg
->kohms
;
160 *val2
= data
->cfg
->avail
[2];
161 return IIO_VAL_FRACTIONAL
;
167 static int mcp4531_read_avail(struct iio_dev
*indio_dev
,
168 struct iio_chan_spec
const *chan
,
169 const int **vals
, int *type
, int *length
,
172 struct mcp4531_data
*data
= iio_priv(indio_dev
);
175 case IIO_CHAN_INFO_RAW
:
176 *length
= ARRAY_SIZE(data
->cfg
->avail
);
177 *vals
= data
->cfg
->avail
;
179 return IIO_AVAIL_RANGE
;
185 static int mcp4531_write_raw(struct iio_dev
*indio_dev
,
186 struct iio_chan_spec
const *chan
,
187 int val
, int val2
, long mask
)
189 struct mcp4531_data
*data
= iio_priv(indio_dev
);
190 int address
= chan
->channel
<< MCP4531_WIPER_SHIFT
;
193 case IIO_CHAN_INFO_RAW
:
194 if (val
> data
->cfg
->avail
[2] || val
< 0)
201 return i2c_smbus_write_byte_data(data
->client
,
202 MCP4531_WRITE
| address
| (val
>> 8),
206 static const struct iio_info mcp4531_info
= {
207 .read_raw
= mcp4531_read_raw
,
208 .read_avail
= mcp4531_read_avail
,
209 .write_raw
= mcp4531_write_raw
,
212 static const struct i2c_device_id mcp4531_id
[] = {
213 { "mcp4531-502", MCP453x_502
},
214 { "mcp4531-103", MCP453x_103
},
215 { "mcp4531-503", MCP453x_503
},
216 { "mcp4531-104", MCP453x_104
},
217 { "mcp4532-502", MCP453x_502
},
218 { "mcp4532-103", MCP453x_103
},
219 { "mcp4532-503", MCP453x_503
},
220 { "mcp4532-104", MCP453x_104
},
221 { "mcp4541-502", MCP454x_502
},
222 { "mcp4541-103", MCP454x_103
},
223 { "mcp4541-503", MCP454x_503
},
224 { "mcp4541-104", MCP454x_104
},
225 { "mcp4542-502", MCP454x_502
},
226 { "mcp4542-103", MCP454x_103
},
227 { "mcp4542-503", MCP454x_503
},
228 { "mcp4542-104", MCP454x_104
},
229 { "mcp4551-502", MCP455x_502
},
230 { "mcp4551-103", MCP455x_103
},
231 { "mcp4551-503", MCP455x_503
},
232 { "mcp4551-104", MCP455x_104
},
233 { "mcp4552-502", MCP455x_502
},
234 { "mcp4552-103", MCP455x_103
},
235 { "mcp4552-503", MCP455x_503
},
236 { "mcp4552-104", MCP455x_104
},
237 { "mcp4561-502", MCP456x_502
},
238 { "mcp4561-103", MCP456x_103
},
239 { "mcp4561-503", MCP456x_503
},
240 { "mcp4561-104", MCP456x_104
},
241 { "mcp4562-502", MCP456x_502
},
242 { "mcp4562-103", MCP456x_103
},
243 { "mcp4562-503", MCP456x_503
},
244 { "mcp4562-104", MCP456x_104
},
245 { "mcp4631-502", MCP463x_502
},
246 { "mcp4631-103", MCP463x_103
},
247 { "mcp4631-503", MCP463x_503
},
248 { "mcp4631-104", MCP463x_104
},
249 { "mcp4632-502", MCP463x_502
},
250 { "mcp4632-103", MCP463x_103
},
251 { "mcp4632-503", MCP463x_503
},
252 { "mcp4632-104", MCP463x_104
},
253 { "mcp4641-502", MCP464x_502
},
254 { "mcp4641-103", MCP464x_103
},
255 { "mcp4641-503", MCP464x_503
},
256 { "mcp4641-104", MCP464x_104
},
257 { "mcp4642-502", MCP464x_502
},
258 { "mcp4642-103", MCP464x_103
},
259 { "mcp4642-503", MCP464x_503
},
260 { "mcp4642-104", MCP464x_104
},
261 { "mcp4651-502", MCP465x_502
},
262 { "mcp4651-103", MCP465x_103
},
263 { "mcp4651-503", MCP465x_503
},
264 { "mcp4651-104", MCP465x_104
},
265 { "mcp4652-502", MCP465x_502
},
266 { "mcp4652-103", MCP465x_103
},
267 { "mcp4652-503", MCP465x_503
},
268 { "mcp4652-104", MCP465x_104
},
269 { "mcp4661-502", MCP466x_502
},
270 { "mcp4661-103", MCP466x_103
},
271 { "mcp4661-503", MCP466x_503
},
272 { "mcp4661-104", MCP466x_104
},
273 { "mcp4662-502", MCP466x_502
},
274 { "mcp4662-103", MCP466x_103
},
275 { "mcp4662-503", MCP466x_503
},
276 { "mcp4662-104", MCP466x_104
},
279 MODULE_DEVICE_TABLE(i2c
, mcp4531_id
);
283 #define MCP4531_COMPATIBLE(of_compatible, cfg) { \
284 .compatible = of_compatible, \
285 .data = &mcp4531_cfg[cfg], \
288 static const struct of_device_id mcp4531_of_match
[] = {
289 MCP4531_COMPATIBLE("microchip,mcp4531-502", MCP453x_502
),
290 MCP4531_COMPATIBLE("microchip,mcp4531-103", MCP453x_103
),
291 MCP4531_COMPATIBLE("microchip,mcp4531-503", MCP453x_503
),
292 MCP4531_COMPATIBLE("microchip,mcp4531-104", MCP453x_104
),
293 MCP4531_COMPATIBLE("microchip,mcp4532-502", MCP453x_502
),
294 MCP4531_COMPATIBLE("microchip,mcp4532-103", MCP453x_103
),
295 MCP4531_COMPATIBLE("microchip,mcp4532-503", MCP453x_503
),
296 MCP4531_COMPATIBLE("microchip,mcp4532-104", MCP453x_104
),
297 MCP4531_COMPATIBLE("microchip,mcp4541-502", MCP454x_502
),
298 MCP4531_COMPATIBLE("microchip,mcp4541-103", MCP454x_103
),
299 MCP4531_COMPATIBLE("microchip,mcp4541-503", MCP454x_503
),
300 MCP4531_COMPATIBLE("microchip,mcp4541-104", MCP454x_104
),
301 MCP4531_COMPATIBLE("microchip,mcp4542-502", MCP454x_502
),
302 MCP4531_COMPATIBLE("microchip,mcp4542-103", MCP454x_103
),
303 MCP4531_COMPATIBLE("microchip,mcp4542-503", MCP454x_503
),
304 MCP4531_COMPATIBLE("microchip,mcp4542-104", MCP454x_104
),
305 MCP4531_COMPATIBLE("microchip,mcp4551-502", MCP455x_502
),
306 MCP4531_COMPATIBLE("microchip,mcp4551-103", MCP455x_103
),
307 MCP4531_COMPATIBLE("microchip,mcp4551-503", MCP455x_503
),
308 MCP4531_COMPATIBLE("microchip,mcp4551-104", MCP455x_104
),
309 MCP4531_COMPATIBLE("microchip,mcp4552-502", MCP455x_502
),
310 MCP4531_COMPATIBLE("microchip,mcp4552-103", MCP455x_103
),
311 MCP4531_COMPATIBLE("microchip,mcp4552-503", MCP455x_503
),
312 MCP4531_COMPATIBLE("microchip,mcp4552-104", MCP455x_104
),
313 MCP4531_COMPATIBLE("microchip,mcp4561-502", MCP456x_502
),
314 MCP4531_COMPATIBLE("microchip,mcp4561-103", MCP456x_103
),
315 MCP4531_COMPATIBLE("microchip,mcp4561-503", MCP456x_503
),
316 MCP4531_COMPATIBLE("microchip,mcp4561-104", MCP456x_104
),
317 MCP4531_COMPATIBLE("microchip,mcp4562-502", MCP456x_502
),
318 MCP4531_COMPATIBLE("microchip,mcp4562-103", MCP456x_103
),
319 MCP4531_COMPATIBLE("microchip,mcp4562-503", MCP456x_503
),
320 MCP4531_COMPATIBLE("microchip,mcp4562-104", MCP456x_104
),
321 MCP4531_COMPATIBLE("microchip,mcp4631-502", MCP463x_502
),
322 MCP4531_COMPATIBLE("microchip,mcp4631-103", MCP463x_103
),
323 MCP4531_COMPATIBLE("microchip,mcp4631-503", MCP463x_503
),
324 MCP4531_COMPATIBLE("microchip,mcp4631-104", MCP463x_104
),
325 MCP4531_COMPATIBLE("microchip,mcp4632-502", MCP463x_502
),
326 MCP4531_COMPATIBLE("microchip,mcp4632-103", MCP463x_103
),
327 MCP4531_COMPATIBLE("microchip,mcp4632-503", MCP463x_503
),
328 MCP4531_COMPATIBLE("microchip,mcp4632-104", MCP463x_104
),
329 MCP4531_COMPATIBLE("microchip,mcp4641-502", MCP464x_502
),
330 MCP4531_COMPATIBLE("microchip,mcp4641-103", MCP464x_103
),
331 MCP4531_COMPATIBLE("microchip,mcp4641-503", MCP464x_503
),
332 MCP4531_COMPATIBLE("microchip,mcp4641-104", MCP464x_104
),
333 MCP4531_COMPATIBLE("microchip,mcp4642-502", MCP464x_502
),
334 MCP4531_COMPATIBLE("microchip,mcp4642-103", MCP464x_103
),
335 MCP4531_COMPATIBLE("microchip,mcp4642-503", MCP464x_503
),
336 MCP4531_COMPATIBLE("microchip,mcp4642-104", MCP464x_104
),
337 MCP4531_COMPATIBLE("microchip,mcp4651-502", MCP465x_502
),
338 MCP4531_COMPATIBLE("microchip,mcp4651-103", MCP465x_103
),
339 MCP4531_COMPATIBLE("microchip,mcp4651-503", MCP465x_503
),
340 MCP4531_COMPATIBLE("microchip,mcp4651-104", MCP465x_104
),
341 MCP4531_COMPATIBLE("microchip,mcp4652-502", MCP465x_502
),
342 MCP4531_COMPATIBLE("microchip,mcp4652-103", MCP465x_103
),
343 MCP4531_COMPATIBLE("microchip,mcp4652-503", MCP465x_503
),
344 MCP4531_COMPATIBLE("microchip,mcp4652-104", MCP465x_104
),
345 MCP4531_COMPATIBLE("microchip,mcp4661-502", MCP466x_502
),
346 MCP4531_COMPATIBLE("microchip,mcp4661-103", MCP466x_103
),
347 MCP4531_COMPATIBLE("microchip,mcp4661-503", MCP466x_503
),
348 MCP4531_COMPATIBLE("microchip,mcp4661-104", MCP466x_104
),
349 MCP4531_COMPATIBLE("microchip,mcp4662-502", MCP466x_502
),
350 MCP4531_COMPATIBLE("microchip,mcp4662-103", MCP466x_103
),
351 MCP4531_COMPATIBLE("microchip,mcp4662-503", MCP466x_503
),
352 MCP4531_COMPATIBLE("microchip,mcp4662-104", MCP466x_104
),
355 MODULE_DEVICE_TABLE(of
, mcp4531_of_match
);
358 static int mcp4531_probe(struct i2c_client
*client
)
360 struct device
*dev
= &client
->dev
;
361 struct mcp4531_data
*data
;
362 struct iio_dev
*indio_dev
;
363 const struct of_device_id
*match
;
365 if (!i2c_check_functionality(client
->adapter
,
366 I2C_FUNC_SMBUS_WORD_DATA
)) {
367 dev_err(dev
, "SMBUS Word Data not supported\n");
371 indio_dev
= devm_iio_device_alloc(dev
, sizeof(*data
));
374 data
= iio_priv(indio_dev
);
375 i2c_set_clientdata(client
, indio_dev
);
376 data
->client
= client
;
378 match
= of_match_device(of_match_ptr(mcp4531_of_match
), dev
);
380 data
->cfg
= of_device_get_match_data(dev
);
382 data
->cfg
= &mcp4531_cfg
[i2c_match_id(mcp4531_id
, client
)->driver_data
];
384 indio_dev
->dev
.parent
= dev
;
385 indio_dev
->info
= &mcp4531_info
;
386 indio_dev
->channels
= mcp4531_channels
;
387 indio_dev
->num_channels
= data
->cfg
->wipers
;
388 indio_dev
->name
= client
->name
;
390 return devm_iio_device_register(dev
, indio_dev
);
393 static struct i2c_driver mcp4531_driver
= {
396 .of_match_table
= of_match_ptr(mcp4531_of_match
),
398 .probe_new
= mcp4531_probe
,
399 .id_table
= mcp4531_id
,
402 module_i2c_driver(mcp4531_driver
);
404 MODULE_AUTHOR("Peter Rosin <peda@axentia.se>");
405 MODULE_DESCRIPTION("MCP4531 digital potentiometer");
406 MODULE_LICENSE("GPL");