1 // SPDX-License-Identifier: GPL-2.0
3 * Industrial I/O driver for Microchip digital potentiometers
4 * Copyright (c) 2015 Axentia Technologies AB
5 * Author: Peter Rosin <peda@axentia.se>
7 * Datasheet: http://www.microchip.com/downloads/en/DeviceDoc/22096b.pdf
9 * DEVID #Wipers #Positions Resistor Opts (kOhm) i2c address
10 * mcp4531 1 129 5, 10, 50, 100 010111x
11 * mcp4532 1 129 5, 10, 50, 100 01011xx
12 * mcp4541 1 129 5, 10, 50, 100 010111x
13 * mcp4542 1 129 5, 10, 50, 100 01011xx
14 * mcp4551 1 257 5, 10, 50, 100 010111x
15 * mcp4552 1 257 5, 10, 50, 100 01011xx
16 * mcp4561 1 257 5, 10, 50, 100 010111x
17 * mcp4562 1 257 5, 10, 50, 100 01011xx
18 * mcp4631 2 129 5, 10, 50, 100 0101xxx
19 * mcp4632 2 129 5, 10, 50, 100 01011xx
20 * mcp4641 2 129 5, 10, 50, 100 0101xxx
21 * mcp4642 2 129 5, 10, 50, 100 01011xx
22 * mcp4651 2 257 5, 10, 50, 100 0101xxx
23 * mcp4652 2 257 5, 10, 50, 100 01011xx
24 * mcp4661 2 257 5, 10, 50, 100 0101xxx
25 * mcp4662 2 257 5, 10, 50, 100 01011xx
28 #include <linux/module.h>
29 #include <linux/i2c.h>
30 #include <linux/err.h>
31 #include <linux/mod_devicetable.h>
32 #include <linux/property.h>
34 #include <linux/iio/iio.h>
77 static const struct mcp4531_cfg mcp4531_cfg
[] = {
78 [MCP453x_502
] = { .wipers
= 1, .avail
= { 0, 1, 128 }, .kohms
= 5, },
79 [MCP453x_103
] = { .wipers
= 1, .avail
= { 0, 1, 128 }, .kohms
= 10, },
80 [MCP453x_503
] = { .wipers
= 1, .avail
= { 0, 1, 128 }, .kohms
= 50, },
81 [MCP453x_104
] = { .wipers
= 1, .avail
= { 0, 1, 128 }, .kohms
= 100, },
82 [MCP454x_502
] = { .wipers
= 1, .avail
= { 0, 1, 128 }, .kohms
= 5, },
83 [MCP454x_103
] = { .wipers
= 1, .avail
= { 0, 1, 128 }, .kohms
= 10, },
84 [MCP454x_503
] = { .wipers
= 1, .avail
= { 0, 1, 128 }, .kohms
= 50, },
85 [MCP454x_104
] = { .wipers
= 1, .avail
= { 0, 1, 128 }, .kohms
= 100, },
86 [MCP455x_502
] = { .wipers
= 1, .avail
= { 0, 1, 256 }, .kohms
= 5, },
87 [MCP455x_103
] = { .wipers
= 1, .avail
= { 0, 1, 256 }, .kohms
= 10, },
88 [MCP455x_503
] = { .wipers
= 1, .avail
= { 0, 1, 256 }, .kohms
= 50, },
89 [MCP455x_104
] = { .wipers
= 1, .avail
= { 0, 1, 256 }, .kohms
= 100, },
90 [MCP456x_502
] = { .wipers
= 1, .avail
= { 0, 1, 256 }, .kohms
= 5, },
91 [MCP456x_103
] = { .wipers
= 1, .avail
= { 0, 1, 256 }, .kohms
= 10, },
92 [MCP456x_503
] = { .wipers
= 1, .avail
= { 0, 1, 256 }, .kohms
= 50, },
93 [MCP456x_104
] = { .wipers
= 1, .avail
= { 0, 1, 256 }, .kohms
= 100, },
94 [MCP463x_502
] = { .wipers
= 2, .avail
= { 0, 1, 128 }, .kohms
= 5, },
95 [MCP463x_103
] = { .wipers
= 2, .avail
= { 0, 1, 128 }, .kohms
= 10, },
96 [MCP463x_503
] = { .wipers
= 2, .avail
= { 0, 1, 128 }, .kohms
= 50, },
97 [MCP463x_104
] = { .wipers
= 2, .avail
= { 0, 1, 128 }, .kohms
= 100, },
98 [MCP464x_502
] = { .wipers
= 2, .avail
= { 0, 1, 128 }, .kohms
= 5, },
99 [MCP464x_103
] = { .wipers
= 2, .avail
= { 0, 1, 128 }, .kohms
= 10, },
100 [MCP464x_503
] = { .wipers
= 2, .avail
= { 0, 1, 128 }, .kohms
= 50, },
101 [MCP464x_104
] = { .wipers
= 2, .avail
= { 0, 1, 128 }, .kohms
= 100, },
102 [MCP465x_502
] = { .wipers
= 2, .avail
= { 0, 1, 256 }, .kohms
= 5, },
103 [MCP465x_103
] = { .wipers
= 2, .avail
= { 0, 1, 256 }, .kohms
= 10, },
104 [MCP465x_503
] = { .wipers
= 2, .avail
= { 0, 1, 256 }, .kohms
= 50, },
105 [MCP465x_104
] = { .wipers
= 2, .avail
= { 0, 1, 256 }, .kohms
= 100, },
106 [MCP466x_502
] = { .wipers
= 2, .avail
= { 0, 1, 256 }, .kohms
= 5, },
107 [MCP466x_103
] = { .wipers
= 2, .avail
= { 0, 1, 256 }, .kohms
= 10, },
108 [MCP466x_503
] = { .wipers
= 2, .avail
= { 0, 1, 256 }, .kohms
= 50, },
109 [MCP466x_104
] = { .wipers
= 2, .avail
= { 0, 1, 256 }, .kohms
= 100, },
112 #define MCP4531_WRITE (0 << 2)
113 #define MCP4531_INCR (1 << 2)
114 #define MCP4531_DECR (2 << 2)
115 #define MCP4531_READ (3 << 2)
117 #define MCP4531_WIPER_SHIFT (4)
119 struct mcp4531_data
{
120 struct i2c_client
*client
;
121 const struct mcp4531_cfg
*cfg
;
124 #define MCP4531_CHANNEL(ch) { \
125 .type = IIO_RESISTANCE, \
129 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
130 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
131 .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_RAW), \
134 static const struct iio_chan_spec mcp4531_channels
[] = {
139 static int mcp4531_read_raw(struct iio_dev
*indio_dev
,
140 struct iio_chan_spec
const *chan
,
141 int *val
, int *val2
, long mask
)
143 struct mcp4531_data
*data
= iio_priv(indio_dev
);
144 int address
= chan
->channel
<< MCP4531_WIPER_SHIFT
;
148 case IIO_CHAN_INFO_RAW
:
149 ret
= i2c_smbus_read_word_swapped(data
->client
,
150 MCP4531_READ
| address
);
155 case IIO_CHAN_INFO_SCALE
:
156 *val
= 1000 * data
->cfg
->kohms
;
157 *val2
= data
->cfg
->avail
[2];
158 return IIO_VAL_FRACTIONAL
;
164 static int mcp4531_read_avail(struct iio_dev
*indio_dev
,
165 struct iio_chan_spec
const *chan
,
166 const int **vals
, int *type
, int *length
,
169 struct mcp4531_data
*data
= iio_priv(indio_dev
);
172 case IIO_CHAN_INFO_RAW
:
173 *length
= ARRAY_SIZE(data
->cfg
->avail
);
174 *vals
= data
->cfg
->avail
;
176 return IIO_AVAIL_RANGE
;
182 static int mcp4531_write_raw(struct iio_dev
*indio_dev
,
183 struct iio_chan_spec
const *chan
,
184 int val
, int val2
, long mask
)
186 struct mcp4531_data
*data
= iio_priv(indio_dev
);
187 int address
= chan
->channel
<< MCP4531_WIPER_SHIFT
;
190 case IIO_CHAN_INFO_RAW
:
191 if (val
> data
->cfg
->avail
[2] || val
< 0)
198 return i2c_smbus_write_byte_data(data
->client
,
199 MCP4531_WRITE
| address
| (val
>> 8),
203 static const struct iio_info mcp4531_info
= {
204 .read_raw
= mcp4531_read_raw
,
205 .read_avail
= mcp4531_read_avail
,
206 .write_raw
= mcp4531_write_raw
,
209 static const struct i2c_device_id mcp4531_id
[] = {
210 { "mcp4531-502", MCP453x_502
},
211 { "mcp4531-103", MCP453x_103
},
212 { "mcp4531-503", MCP453x_503
},
213 { "mcp4531-104", MCP453x_104
},
214 { "mcp4532-502", MCP453x_502
},
215 { "mcp4532-103", MCP453x_103
},
216 { "mcp4532-503", MCP453x_503
},
217 { "mcp4532-104", MCP453x_104
},
218 { "mcp4541-502", MCP454x_502
},
219 { "mcp4541-103", MCP454x_103
},
220 { "mcp4541-503", MCP454x_503
},
221 { "mcp4541-104", MCP454x_104
},
222 { "mcp4542-502", MCP454x_502
},
223 { "mcp4542-103", MCP454x_103
},
224 { "mcp4542-503", MCP454x_503
},
225 { "mcp4542-104", MCP454x_104
},
226 { "mcp4551-502", MCP455x_502
},
227 { "mcp4551-103", MCP455x_103
},
228 { "mcp4551-503", MCP455x_503
},
229 { "mcp4551-104", MCP455x_104
},
230 { "mcp4552-502", MCP455x_502
},
231 { "mcp4552-103", MCP455x_103
},
232 { "mcp4552-503", MCP455x_503
},
233 { "mcp4552-104", MCP455x_104
},
234 { "mcp4561-502", MCP456x_502
},
235 { "mcp4561-103", MCP456x_103
},
236 { "mcp4561-503", MCP456x_503
},
237 { "mcp4561-104", MCP456x_104
},
238 { "mcp4562-502", MCP456x_502
},
239 { "mcp4562-103", MCP456x_103
},
240 { "mcp4562-503", MCP456x_503
},
241 { "mcp4562-104", MCP456x_104
},
242 { "mcp4631-502", MCP463x_502
},
243 { "mcp4631-103", MCP463x_103
},
244 { "mcp4631-503", MCP463x_503
},
245 { "mcp4631-104", MCP463x_104
},
246 { "mcp4632-502", MCP463x_502
},
247 { "mcp4632-103", MCP463x_103
},
248 { "mcp4632-503", MCP463x_503
},
249 { "mcp4632-104", MCP463x_104
},
250 { "mcp4641-502", MCP464x_502
},
251 { "mcp4641-103", MCP464x_103
},
252 { "mcp4641-503", MCP464x_503
},
253 { "mcp4641-104", MCP464x_104
},
254 { "mcp4642-502", MCP464x_502
},
255 { "mcp4642-103", MCP464x_103
},
256 { "mcp4642-503", MCP464x_503
},
257 { "mcp4642-104", MCP464x_104
},
258 { "mcp4651-502", MCP465x_502
},
259 { "mcp4651-103", MCP465x_103
},
260 { "mcp4651-503", MCP465x_503
},
261 { "mcp4651-104", MCP465x_104
},
262 { "mcp4652-502", MCP465x_502
},
263 { "mcp4652-103", MCP465x_103
},
264 { "mcp4652-503", MCP465x_503
},
265 { "mcp4652-104", MCP465x_104
},
266 { "mcp4661-502", MCP466x_502
},
267 { "mcp4661-103", MCP466x_103
},
268 { "mcp4661-503", MCP466x_503
},
269 { "mcp4661-104", MCP466x_104
},
270 { "mcp4662-502", MCP466x_502
},
271 { "mcp4662-103", MCP466x_103
},
272 { "mcp4662-503", MCP466x_503
},
273 { "mcp4662-104", MCP466x_104
},
276 MODULE_DEVICE_TABLE(i2c
, mcp4531_id
);
278 #define MCP4531_COMPATIBLE(of_compatible, cfg) { \
279 .compatible = of_compatible, \
280 .data = &mcp4531_cfg[cfg], \
283 static const struct of_device_id mcp4531_of_match
[] = {
284 MCP4531_COMPATIBLE("microchip,mcp4531-502", MCP453x_502
),
285 MCP4531_COMPATIBLE("microchip,mcp4531-103", MCP453x_103
),
286 MCP4531_COMPATIBLE("microchip,mcp4531-503", MCP453x_503
),
287 MCP4531_COMPATIBLE("microchip,mcp4531-104", MCP453x_104
),
288 MCP4531_COMPATIBLE("microchip,mcp4532-502", MCP453x_502
),
289 MCP4531_COMPATIBLE("microchip,mcp4532-103", MCP453x_103
),
290 MCP4531_COMPATIBLE("microchip,mcp4532-503", MCP453x_503
),
291 MCP4531_COMPATIBLE("microchip,mcp4532-104", MCP453x_104
),
292 MCP4531_COMPATIBLE("microchip,mcp4541-502", MCP454x_502
),
293 MCP4531_COMPATIBLE("microchip,mcp4541-103", MCP454x_103
),
294 MCP4531_COMPATIBLE("microchip,mcp4541-503", MCP454x_503
),
295 MCP4531_COMPATIBLE("microchip,mcp4541-104", MCP454x_104
),
296 MCP4531_COMPATIBLE("microchip,mcp4542-502", MCP454x_502
),
297 MCP4531_COMPATIBLE("microchip,mcp4542-103", MCP454x_103
),
298 MCP4531_COMPATIBLE("microchip,mcp4542-503", MCP454x_503
),
299 MCP4531_COMPATIBLE("microchip,mcp4542-104", MCP454x_104
),
300 MCP4531_COMPATIBLE("microchip,mcp4551-502", MCP455x_502
),
301 MCP4531_COMPATIBLE("microchip,mcp4551-103", MCP455x_103
),
302 MCP4531_COMPATIBLE("microchip,mcp4551-503", MCP455x_503
),
303 MCP4531_COMPATIBLE("microchip,mcp4551-104", MCP455x_104
),
304 MCP4531_COMPATIBLE("microchip,mcp4552-502", MCP455x_502
),
305 MCP4531_COMPATIBLE("microchip,mcp4552-103", MCP455x_103
),
306 MCP4531_COMPATIBLE("microchip,mcp4552-503", MCP455x_503
),
307 MCP4531_COMPATIBLE("microchip,mcp4552-104", MCP455x_104
),
308 MCP4531_COMPATIBLE("microchip,mcp4561-502", MCP456x_502
),
309 MCP4531_COMPATIBLE("microchip,mcp4561-103", MCP456x_103
),
310 MCP4531_COMPATIBLE("microchip,mcp4561-503", MCP456x_503
),
311 MCP4531_COMPATIBLE("microchip,mcp4561-104", MCP456x_104
),
312 MCP4531_COMPATIBLE("microchip,mcp4562-502", MCP456x_502
),
313 MCP4531_COMPATIBLE("microchip,mcp4562-103", MCP456x_103
),
314 MCP4531_COMPATIBLE("microchip,mcp4562-503", MCP456x_503
),
315 MCP4531_COMPATIBLE("microchip,mcp4562-104", MCP456x_104
),
316 MCP4531_COMPATIBLE("microchip,mcp4631-502", MCP463x_502
),
317 MCP4531_COMPATIBLE("microchip,mcp4631-103", MCP463x_103
),
318 MCP4531_COMPATIBLE("microchip,mcp4631-503", MCP463x_503
),
319 MCP4531_COMPATIBLE("microchip,mcp4631-104", MCP463x_104
),
320 MCP4531_COMPATIBLE("microchip,mcp4632-502", MCP463x_502
),
321 MCP4531_COMPATIBLE("microchip,mcp4632-103", MCP463x_103
),
322 MCP4531_COMPATIBLE("microchip,mcp4632-503", MCP463x_503
),
323 MCP4531_COMPATIBLE("microchip,mcp4632-104", MCP463x_104
),
324 MCP4531_COMPATIBLE("microchip,mcp4641-502", MCP464x_502
),
325 MCP4531_COMPATIBLE("microchip,mcp4641-103", MCP464x_103
),
326 MCP4531_COMPATIBLE("microchip,mcp4641-503", MCP464x_503
),
327 MCP4531_COMPATIBLE("microchip,mcp4641-104", MCP464x_104
),
328 MCP4531_COMPATIBLE("microchip,mcp4642-502", MCP464x_502
),
329 MCP4531_COMPATIBLE("microchip,mcp4642-103", MCP464x_103
),
330 MCP4531_COMPATIBLE("microchip,mcp4642-503", MCP464x_503
),
331 MCP4531_COMPATIBLE("microchip,mcp4642-104", MCP464x_104
),
332 MCP4531_COMPATIBLE("microchip,mcp4651-502", MCP465x_502
),
333 MCP4531_COMPATIBLE("microchip,mcp4651-103", MCP465x_103
),
334 MCP4531_COMPATIBLE("microchip,mcp4651-503", MCP465x_503
),
335 MCP4531_COMPATIBLE("microchip,mcp4651-104", MCP465x_104
),
336 MCP4531_COMPATIBLE("microchip,mcp4652-502", MCP465x_502
),
337 MCP4531_COMPATIBLE("microchip,mcp4652-103", MCP465x_103
),
338 MCP4531_COMPATIBLE("microchip,mcp4652-503", MCP465x_503
),
339 MCP4531_COMPATIBLE("microchip,mcp4652-104", MCP465x_104
),
340 MCP4531_COMPATIBLE("microchip,mcp4661-502", MCP466x_502
),
341 MCP4531_COMPATIBLE("microchip,mcp4661-103", MCP466x_103
),
342 MCP4531_COMPATIBLE("microchip,mcp4661-503", MCP466x_503
),
343 MCP4531_COMPATIBLE("microchip,mcp4661-104", MCP466x_104
),
344 MCP4531_COMPATIBLE("microchip,mcp4662-502", MCP466x_502
),
345 MCP4531_COMPATIBLE("microchip,mcp4662-103", MCP466x_103
),
346 MCP4531_COMPATIBLE("microchip,mcp4662-503", MCP466x_503
),
347 MCP4531_COMPATIBLE("microchip,mcp4662-104", MCP466x_104
),
350 MODULE_DEVICE_TABLE(of
, mcp4531_of_match
);
352 static int mcp4531_probe(struct i2c_client
*client
)
354 struct device
*dev
= &client
->dev
;
355 struct mcp4531_data
*data
;
356 struct iio_dev
*indio_dev
;
358 if (!i2c_check_functionality(client
->adapter
,
359 I2C_FUNC_SMBUS_WORD_DATA
)) {
360 dev_err(dev
, "SMBUS Word Data not supported\n");
364 indio_dev
= devm_iio_device_alloc(dev
, sizeof(*data
));
367 data
= iio_priv(indio_dev
);
368 i2c_set_clientdata(client
, indio_dev
);
369 data
->client
= client
;
371 data
->cfg
= device_get_match_data(dev
);
373 data
->cfg
= &mcp4531_cfg
[i2c_match_id(mcp4531_id
, client
)->driver_data
];
375 indio_dev
->info
= &mcp4531_info
;
376 indio_dev
->channels
= mcp4531_channels
;
377 indio_dev
->num_channels
= data
->cfg
->wipers
;
378 indio_dev
->name
= client
->name
;
380 return devm_iio_device_register(dev
, indio_dev
);
383 static struct i2c_driver mcp4531_driver
= {
386 .of_match_table
= mcp4531_of_match
,
388 .probe_new
= mcp4531_probe
,
389 .id_table
= mcp4531_id
,
392 module_i2c_driver(mcp4531_driver
);
394 MODULE_AUTHOR("Peter Rosin <peda@axentia.se>");
395 MODULE_DESCRIPTION("MCP4531 digital potentiometer");
396 MODULE_LICENSE("GPL v2");