1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Industrial I/O driver for Microchip digital potentiometers 4 * Copyright (c) 2015 Axentia Technologies AB 5 * Author: Peter Rosin <peda@axentia.se> 6 * 7 * Datasheet: http://www.microchip.com/downloads/en/DeviceDoc/22096b.pdf 8 * 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 26 */ 27 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> 33 34 #include <linux/iio/iio.h> 35 36 struct mcp4531_cfg { 37 int wipers; 38 int avail[3]; 39 int kohms; 40 }; 41 42 enum mcp4531_type { 43 MCP453x_502, 44 MCP453x_103, 45 MCP453x_503, 46 MCP453x_104, 47 MCP454x_502, 48 MCP454x_103, 49 MCP454x_503, 50 MCP454x_104, 51 MCP455x_502, 52 MCP455x_103, 53 MCP455x_503, 54 MCP455x_104, 55 MCP456x_502, 56 MCP456x_103, 57 MCP456x_503, 58 MCP456x_104, 59 MCP463x_502, 60 MCP463x_103, 61 MCP463x_503, 62 MCP463x_104, 63 MCP464x_502, 64 MCP464x_103, 65 MCP464x_503, 66 MCP464x_104, 67 MCP465x_502, 68 MCP465x_103, 69 MCP465x_503, 70 MCP465x_104, 71 MCP466x_502, 72 MCP466x_103, 73 MCP466x_503, 74 MCP466x_104, 75 }; 76 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, }, 110 }; 111 112 #define MCP4531_WRITE (0 << 2) 113 #define MCP4531_INCR (1 << 2) 114 #define MCP4531_DECR (2 << 2) 115 #define MCP4531_READ (3 << 2) 116 117 #define MCP4531_WIPER_SHIFT (4) 118 119 struct mcp4531_data { 120 struct i2c_client *client; 121 const struct mcp4531_cfg *cfg; 122 }; 123 124 #define MCP4531_CHANNEL(ch) { \ 125 .type = IIO_RESISTANCE, \ 126 .indexed = 1, \ 127 .output = 1, \ 128 .channel = (ch), \ 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), \ 132 } 133 134 static const struct iio_chan_spec mcp4531_channels[] = { 135 MCP4531_CHANNEL(0), 136 MCP4531_CHANNEL(1), 137 }; 138 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) 142 { 143 struct mcp4531_data *data = iio_priv(indio_dev); 144 int address = chan->channel << MCP4531_WIPER_SHIFT; 145 s32 ret; 146 147 switch (mask) { 148 case IIO_CHAN_INFO_RAW: 149 ret = i2c_smbus_read_word_swapped(data->client, 150 MCP4531_READ | address); 151 if (ret < 0) 152 return ret; 153 *val = ret; 154 return IIO_VAL_INT; 155 case IIO_CHAN_INFO_SCALE: 156 *val = 1000 * data->cfg->kohms; 157 *val2 = data->cfg->avail[2]; 158 return IIO_VAL_FRACTIONAL; 159 } 160 161 return -EINVAL; 162 } 163 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, 167 long mask) 168 { 169 struct mcp4531_data *data = iio_priv(indio_dev); 170 171 switch (mask) { 172 case IIO_CHAN_INFO_RAW: 173 *length = ARRAY_SIZE(data->cfg->avail); 174 *vals = data->cfg->avail; 175 *type = IIO_VAL_INT; 176 return IIO_AVAIL_RANGE; 177 } 178 179 return -EINVAL; 180 } 181 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) 185 { 186 struct mcp4531_data *data = iio_priv(indio_dev); 187 int address = chan->channel << MCP4531_WIPER_SHIFT; 188 189 switch (mask) { 190 case IIO_CHAN_INFO_RAW: 191 if (val > data->cfg->avail[2] || val < 0) 192 return -EINVAL; 193 break; 194 default: 195 return -EINVAL; 196 } 197 198 return i2c_smbus_write_byte_data(data->client, 199 MCP4531_WRITE | address | (val >> 8), 200 val & 0xff); 201 } 202 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, 207 }; 208 209 #define MCP4531_ID_TABLE(_name, cfg) { \ 210 .name = _name, \ 211 .driver_data = (kernel_ulong_t)&mcp4531_cfg[cfg], \ 212 } 213 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), 279 { /* sentinel */ } 280 }; 281 MODULE_DEVICE_TABLE(i2c, mcp4531_id); 282 283 #define MCP4531_COMPATIBLE(of_compatible, cfg) { \ 284 .compatible = of_compatible, \ 285 .data = &mcp4531_cfg[cfg], \ 286 } 287 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), 353 { /* sentinel */ } 354 }; 355 MODULE_DEVICE_TABLE(of, mcp4531_of_match); 356 357 static int mcp4531_probe(struct i2c_client *client) 358 { 359 struct device *dev = &client->dev; 360 struct mcp4531_data *data; 361 struct iio_dev *indio_dev; 362 363 if (!i2c_check_functionality(client->adapter, 364 I2C_FUNC_SMBUS_WORD_DATA)) { 365 dev_err(dev, "SMBUS Word Data not supported\n"); 366 return -EOPNOTSUPP; 367 } 368 369 indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); 370 if (!indio_dev) 371 return -ENOMEM; 372 data = iio_priv(indio_dev); 373 i2c_set_clientdata(client, indio_dev); 374 data->client = client; 375 376 data->cfg = i2c_get_match_data(client); 377 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; 382 383 return devm_iio_device_register(dev, indio_dev); 384 } 385 386 static struct i2c_driver mcp4531_driver = { 387 .driver = { 388 .name = "mcp4531", 389 .of_match_table = mcp4531_of_match, 390 }, 391 .probe = mcp4531_probe, 392 .id_table = mcp4531_id, 393 }; 394 395 module_i2c_driver(mcp4531_driver); 396 397 MODULE_AUTHOR("Peter Rosin <peda@axentia.se>"); 398 MODULE_DESCRIPTION("MCP4531 digital potentiometer"); 399 MODULE_LICENSE("GPL v2"); 400