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 #define MCP4531_ID_TABLE(_name, cfg) { \
211 .driver_data = (kernel_ulong_t)&mcp4531_cfg[cfg], \
214 static const struct i2c_device_id mcp4531_id
[] = {
215 MCP4531_ID_TABLE("mcp4531-502", MCP453x_502
),
216 MCP4531_ID_TABLE("mcp4531-103", MCP453x_103
),
217 MCP4531_ID_TABLE("mcp4531-503", MCP453x_503
),
218 MCP4531_ID_TABLE("mcp4531-104", MCP453x_104
),
219 MCP4531_ID_TABLE("mcp4532-502", MCP453x_502
),
220 MCP4531_ID_TABLE("mcp4532-103", MCP453x_103
),
221 MCP4531_ID_TABLE("mcp4532-503", MCP453x_503
),
222 MCP4531_ID_TABLE("mcp4532-104", MCP453x_104
),
223 MCP4531_ID_TABLE("mcp4541-502", MCP454x_502
),
224 MCP4531_ID_TABLE("mcp4541-103", MCP454x_103
),
225 MCP4531_ID_TABLE("mcp4541-503", MCP454x_503
),
226 MCP4531_ID_TABLE("mcp4541-104", MCP454x_104
),
227 MCP4531_ID_TABLE("mcp4542-502", MCP454x_502
),
228 MCP4531_ID_TABLE("mcp4542-103", MCP454x_103
),
229 MCP4531_ID_TABLE("mcp4542-503", MCP454x_503
),
230 MCP4531_ID_TABLE("mcp4542-104", MCP454x_104
),
231 MCP4531_ID_TABLE("mcp4551-502", MCP455x_502
),
232 MCP4531_ID_TABLE("mcp4551-103", MCP455x_103
),
233 MCP4531_ID_TABLE("mcp4551-503", MCP455x_503
),
234 MCP4531_ID_TABLE("mcp4551-104", MCP455x_104
),
235 MCP4531_ID_TABLE("mcp4552-502", MCP455x_502
),
236 MCP4531_ID_TABLE("mcp4552-103", MCP455x_103
),
237 MCP4531_ID_TABLE("mcp4552-503", MCP455x_503
),
238 MCP4531_ID_TABLE("mcp4552-104", MCP455x_104
),
239 MCP4531_ID_TABLE("mcp4561-502", MCP456x_502
),
240 MCP4531_ID_TABLE("mcp4561-103", MCP456x_103
),
241 MCP4531_ID_TABLE("mcp4561-503", MCP456x_503
),
242 MCP4531_ID_TABLE("mcp4561-104", MCP456x_104
),
243 MCP4531_ID_TABLE("mcp4562-502", MCP456x_502
),
244 MCP4531_ID_TABLE("mcp4562-103", MCP456x_103
),
245 MCP4531_ID_TABLE("mcp4562-503", MCP456x_503
),
246 MCP4531_ID_TABLE("mcp4562-104", MCP456x_104
),
247 MCP4531_ID_TABLE("mcp4631-502", MCP463x_502
),
248 MCP4531_ID_TABLE("mcp4631-103", MCP463x_103
),
249 MCP4531_ID_TABLE("mcp4631-503", MCP463x_503
),
250 MCP4531_ID_TABLE("mcp4631-104", MCP463x_104
),
251 MCP4531_ID_TABLE("mcp4632-502", MCP463x_502
),
252 MCP4531_ID_TABLE("mcp4632-103", MCP463x_103
),
253 MCP4531_ID_TABLE("mcp4632-503", MCP463x_503
),
254 MCP4531_ID_TABLE("mcp4632-104", MCP463x_104
),
255 MCP4531_ID_TABLE("mcp4641-502", MCP464x_502
),
256 MCP4531_ID_TABLE("mcp4641-103", MCP464x_103
),
257 MCP4531_ID_TABLE("mcp4641-503", MCP464x_503
),
258 MCP4531_ID_TABLE("mcp4641-104", MCP464x_104
),
259 MCP4531_ID_TABLE("mcp4642-502", MCP464x_502
),
260 MCP4531_ID_TABLE("mcp4642-103", MCP464x_103
),
261 MCP4531_ID_TABLE("mcp4642-503", MCP464x_503
),
262 MCP4531_ID_TABLE("mcp4642-104", MCP464x_104
),
263 MCP4531_ID_TABLE("mcp4651-502", MCP465x_502
),
264 MCP4531_ID_TABLE("mcp4651-103", MCP465x_103
),
265 MCP4531_ID_TABLE("mcp4651-503", MCP465x_503
),
266 MCP4531_ID_TABLE("mcp4651-104", MCP465x_104
),
267 MCP4531_ID_TABLE("mcp4652-502", MCP465x_502
),
268 MCP4531_ID_TABLE("mcp4652-103", MCP465x_103
),
269 MCP4531_ID_TABLE("mcp4652-503", MCP465x_503
),
270 MCP4531_ID_TABLE("mcp4652-104", MCP465x_104
),
271 MCP4531_ID_TABLE("mcp4661-502", MCP466x_502
),
272 MCP4531_ID_TABLE("mcp4661-103", MCP466x_103
),
273 MCP4531_ID_TABLE("mcp4661-503", MCP466x_503
),
274 MCP4531_ID_TABLE("mcp4661-104", MCP466x_104
),
275 MCP4531_ID_TABLE("mcp4662-502", MCP466x_502
),
276 MCP4531_ID_TABLE("mcp4662-103", MCP466x_103
),
277 MCP4531_ID_TABLE("mcp4662-503", MCP466x_503
),
278 MCP4531_ID_TABLE("mcp4662-104", MCP466x_104
),
281 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
);
357 static int mcp4531_probe(struct i2c_client
*client
)
359 struct device
*dev
= &client
->dev
;
360 struct mcp4531_data
*data
;
361 struct iio_dev
*indio_dev
;
363 if (!i2c_check_functionality(client
->adapter
,
364 I2C_FUNC_SMBUS_WORD_DATA
)) {
365 dev_err(dev
, "SMBUS Word Data not supported\n");
369 indio_dev
= devm_iio_device_alloc(dev
, sizeof(*data
));
372 data
= iio_priv(indio_dev
);
373 i2c_set_clientdata(client
, indio_dev
);
374 data
->client
= client
;
376 data
->cfg
= i2c_get_match_data(client
);
378 indio_dev
->info
= &mcp4531_info
;
379 indio_dev
->channels
= mcp4531_channels
;
380 indio_dev
->num_channels
= data
->cfg
->wipers
;
381 indio_dev
->name
= client
->name
;
383 return devm_iio_device_register(dev
, indio_dev
);
386 static struct i2c_driver mcp4531_driver
= {
389 .of_match_table
= mcp4531_of_match
,
391 .probe
= mcp4531_probe
,
392 .id_table
= mcp4531_id
,
395 module_i2c_driver(mcp4531_driver
);
397 MODULE_AUTHOR("Peter Rosin <peda@axentia.se>");
398 MODULE_DESCRIPTION("MCP4531 digital potentiometer");
399 MODULE_LICENSE("GPL v2");