1 /* 2 * Industrial I/O driver for Microchip digital potentiometers 3 * Copyright (c) 2015 Axentia Technologies AB 4 * Author: Peter Rosin <peda@axentia.se> 5 * 6 * Datasheet: http://www.microchip.com/downloads/en/DeviceDoc/22096b.pdf 7 * 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 25 * 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. 29 */ 30 31 #include <linux/module.h> 32 #include <linux/i2c.h> 33 #include <linux/err.h> 34 #include <linux/of.h> 35 #include <linux/of_device.h> 36 37 #include <linux/iio/iio.h> 38 39 struct mcp4531_cfg { 40 int wipers; 41 int max_pos; 42 int kohms; 43 }; 44 45 enum mcp4531_type { 46 MCP453x_502, 47 MCP453x_103, 48 MCP453x_503, 49 MCP453x_104, 50 MCP454x_502, 51 MCP454x_103, 52 MCP454x_503, 53 MCP454x_104, 54 MCP455x_502, 55 MCP455x_103, 56 MCP455x_503, 57 MCP455x_104, 58 MCP456x_502, 59 MCP456x_103, 60 MCP456x_503, 61 MCP456x_104, 62 MCP463x_502, 63 MCP463x_103, 64 MCP463x_503, 65 MCP463x_104, 66 MCP464x_502, 67 MCP464x_103, 68 MCP464x_503, 69 MCP464x_104, 70 MCP465x_502, 71 MCP465x_103, 72 MCP465x_503, 73 MCP465x_104, 74 MCP466x_502, 75 MCP466x_103, 76 MCP466x_503, 77 MCP466x_104, 78 }; 79 80 static const struct mcp4531_cfg mcp4531_cfg[] = { 81 [MCP453x_502] = { .wipers = 1, .max_pos = 128, .kohms = 5, }, 82 [MCP453x_103] = { .wipers = 1, .max_pos = 128, .kohms = 10, }, 83 [MCP453x_503] = { .wipers = 1, .max_pos = 128, .kohms = 50, }, 84 [MCP453x_104] = { .wipers = 1, .max_pos = 128, .kohms = 100, }, 85 [MCP454x_502] = { .wipers = 1, .max_pos = 128, .kohms = 5, }, 86 [MCP454x_103] = { .wipers = 1, .max_pos = 128, .kohms = 10, }, 87 [MCP454x_503] = { .wipers = 1, .max_pos = 128, .kohms = 50, }, 88 [MCP454x_104] = { .wipers = 1, .max_pos = 128, .kohms = 100, }, 89 [MCP455x_502] = { .wipers = 1, .max_pos = 256, .kohms = 5, }, 90 [MCP455x_103] = { .wipers = 1, .max_pos = 256, .kohms = 10, }, 91 [MCP455x_503] = { .wipers = 1, .max_pos = 256, .kohms = 50, }, 92 [MCP455x_104] = { .wipers = 1, .max_pos = 256, .kohms = 100, }, 93 [MCP456x_502] = { .wipers = 1, .max_pos = 256, .kohms = 5, }, 94 [MCP456x_103] = { .wipers = 1, .max_pos = 256, .kohms = 10, }, 95 [MCP456x_503] = { .wipers = 1, .max_pos = 256, .kohms = 50, }, 96 [MCP456x_104] = { .wipers = 1, .max_pos = 256, .kohms = 100, }, 97 [MCP463x_502] = { .wipers = 2, .max_pos = 128, .kohms = 5, }, 98 [MCP463x_103] = { .wipers = 2, .max_pos = 128, .kohms = 10, }, 99 [MCP463x_503] = { .wipers = 2, .max_pos = 128, .kohms = 50, }, 100 [MCP463x_104] = { .wipers = 2, .max_pos = 128, .kohms = 100, }, 101 [MCP464x_502] = { .wipers = 2, .max_pos = 128, .kohms = 5, }, 102 [MCP464x_103] = { .wipers = 2, .max_pos = 128, .kohms = 10, }, 103 [MCP464x_503] = { .wipers = 2, .max_pos = 128, .kohms = 50, }, 104 [MCP464x_104] = { .wipers = 2, .max_pos = 128, .kohms = 100, }, 105 [MCP465x_502] = { .wipers = 2, .max_pos = 256, .kohms = 5, }, 106 [MCP465x_103] = { .wipers = 2, .max_pos = 256, .kohms = 10, }, 107 [MCP465x_503] = { .wipers = 2, .max_pos = 256, .kohms = 50, }, 108 [MCP465x_104] = { .wipers = 2, .max_pos = 256, .kohms = 100, }, 109 [MCP466x_502] = { .wipers = 2, .max_pos = 256, .kohms = 5, }, 110 [MCP466x_103] = { .wipers = 2, .max_pos = 256, .kohms = 10, }, 111 [MCP466x_503] = { .wipers = 2, .max_pos = 256, .kohms = 50, }, 112 [MCP466x_104] = { .wipers = 2, .max_pos = 256, .kohms = 100, }, 113 }; 114 115 #define MCP4531_WRITE (0 << 2) 116 #define MCP4531_INCR (1 << 2) 117 #define MCP4531_DECR (2 << 2) 118 #define MCP4531_READ (3 << 2) 119 120 #define MCP4531_WIPER_SHIFT (4) 121 122 struct mcp4531_data { 123 struct i2c_client *client; 124 const struct mcp4531_cfg *cfg; 125 }; 126 127 #define MCP4531_CHANNEL(ch) { \ 128 .type = IIO_RESISTANCE, \ 129 .indexed = 1, \ 130 .output = 1, \ 131 .channel = (ch), \ 132 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 133 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 134 } 135 136 static const struct iio_chan_spec mcp4531_channels[] = { 137 MCP4531_CHANNEL(0), 138 MCP4531_CHANNEL(1), 139 }; 140 141 static int mcp4531_read_raw(struct iio_dev *indio_dev, 142 struct iio_chan_spec const *chan, 143 int *val, int *val2, long mask) 144 { 145 struct mcp4531_data *data = iio_priv(indio_dev); 146 int address = chan->channel << MCP4531_WIPER_SHIFT; 147 s32 ret; 148 149 switch (mask) { 150 case IIO_CHAN_INFO_RAW: 151 ret = i2c_smbus_read_word_swapped(data->client, 152 MCP4531_READ | address); 153 if (ret < 0) 154 return ret; 155 *val = ret; 156 return IIO_VAL_INT; 157 case IIO_CHAN_INFO_SCALE: 158 *val = 1000 * data->cfg->kohms; 159 *val2 = data->cfg->max_pos; 160 return IIO_VAL_FRACTIONAL; 161 } 162 163 return -EINVAL; 164 } 165 166 static int mcp4531_write_raw(struct iio_dev *indio_dev, 167 struct iio_chan_spec const *chan, 168 int val, int val2, long mask) 169 { 170 struct mcp4531_data *data = iio_priv(indio_dev); 171 int address = chan->channel << MCP4531_WIPER_SHIFT; 172 173 switch (mask) { 174 case IIO_CHAN_INFO_RAW: 175 if (val > data->cfg->max_pos || val < 0) 176 return -EINVAL; 177 break; 178 default: 179 return -EINVAL; 180 } 181 182 return i2c_smbus_write_byte_data(data->client, 183 MCP4531_WRITE | address | (val >> 8), 184 val & 0xff); 185 } 186 187 static const struct iio_info mcp4531_info = { 188 .read_raw = mcp4531_read_raw, 189 .write_raw = mcp4531_write_raw, 190 .driver_module = THIS_MODULE, 191 }; 192 193 #ifdef CONFIG_OF 194 195 #define MCP4531_COMPATIBLE(of_compatible, cfg) { \ 196 .compatible = of_compatible, \ 197 .data = &mcp4531_cfg[cfg], \ 198 } 199 200 static const struct of_device_id mcp4531_of_match[] = { 201 MCP4531_COMPATIBLE("microchip,mcp4531-502", MCP453x_502), 202 MCP4531_COMPATIBLE("microchip,mcp4531-103", MCP453x_103), 203 MCP4531_COMPATIBLE("microchip,mcp4531-503", MCP453x_503), 204 MCP4531_COMPATIBLE("microchip,mcp4531-104", MCP453x_104), 205 MCP4531_COMPATIBLE("microchip,mcp4532-502", MCP453x_502), 206 MCP4531_COMPATIBLE("microchip,mcp4532-103", MCP453x_103), 207 MCP4531_COMPATIBLE("microchip,mcp4532-503", MCP453x_503), 208 MCP4531_COMPATIBLE("microchip,mcp4532-104", MCP453x_104), 209 MCP4531_COMPATIBLE("microchip,mcp4541-502", MCP454x_502), 210 MCP4531_COMPATIBLE("microchip,mcp4541-103", MCP454x_103), 211 MCP4531_COMPATIBLE("microchip,mcp4541-503", MCP454x_503), 212 MCP4531_COMPATIBLE("microchip,mcp4541-104", MCP454x_104), 213 MCP4531_COMPATIBLE("microchip,mcp4542-502", MCP454x_502), 214 MCP4531_COMPATIBLE("microchip,mcp4542-103", MCP454x_103), 215 MCP4531_COMPATIBLE("microchip,mcp4542-503", MCP454x_503), 216 MCP4531_COMPATIBLE("microchip,mcp4542-104", MCP454x_104), 217 MCP4531_COMPATIBLE("microchip,mcp4551-502", MCP455x_502), 218 MCP4531_COMPATIBLE("microchip,mcp4551-103", MCP455x_103), 219 MCP4531_COMPATIBLE("microchip,mcp4551-503", MCP455x_503), 220 MCP4531_COMPATIBLE("microchip,mcp4551-104", MCP455x_104), 221 MCP4531_COMPATIBLE("microchip,mcp4552-502", MCP455x_502), 222 MCP4531_COMPATIBLE("microchip,mcp4552-103", MCP455x_103), 223 MCP4531_COMPATIBLE("microchip,mcp4552-503", MCP455x_503), 224 MCP4531_COMPATIBLE("microchip,mcp4552-104", MCP455x_104), 225 MCP4531_COMPATIBLE("microchip,mcp4561-502", MCP456x_502), 226 MCP4531_COMPATIBLE("microchip,mcp4561-103", MCP456x_103), 227 MCP4531_COMPATIBLE("microchip,mcp4561-503", MCP456x_503), 228 MCP4531_COMPATIBLE("microchip,mcp4561-104", MCP456x_104), 229 MCP4531_COMPATIBLE("microchip,mcp4562-502", MCP456x_502), 230 MCP4531_COMPATIBLE("microchip,mcp4562-103", MCP456x_103), 231 MCP4531_COMPATIBLE("microchip,mcp4562-503", MCP456x_503), 232 MCP4531_COMPATIBLE("microchip,mcp4562-104", MCP456x_104), 233 MCP4531_COMPATIBLE("microchip,mcp4631-502", MCP463x_502), 234 MCP4531_COMPATIBLE("microchip,mcp4631-103", MCP463x_103), 235 MCP4531_COMPATIBLE("microchip,mcp4631-503", MCP463x_503), 236 MCP4531_COMPATIBLE("microchip,mcp4631-104", MCP463x_104), 237 MCP4531_COMPATIBLE("microchip,mcp4632-502", MCP463x_502), 238 MCP4531_COMPATIBLE("microchip,mcp4632-103", MCP463x_103), 239 MCP4531_COMPATIBLE("microchip,mcp4632-503", MCP463x_503), 240 MCP4531_COMPATIBLE("microchip,mcp4632-104", MCP463x_104), 241 MCP4531_COMPATIBLE("microchip,mcp4641-502", MCP464x_502), 242 MCP4531_COMPATIBLE("microchip,mcp4641-103", MCP464x_103), 243 MCP4531_COMPATIBLE("microchip,mcp4641-503", MCP464x_503), 244 MCP4531_COMPATIBLE("microchip,mcp4641-104", MCP464x_104), 245 MCP4531_COMPATIBLE("microchip,mcp4642-502", MCP464x_502), 246 MCP4531_COMPATIBLE("microchip,mcp4642-103", MCP464x_103), 247 MCP4531_COMPATIBLE("microchip,mcp4642-503", MCP464x_503), 248 MCP4531_COMPATIBLE("microchip,mcp4642-104", MCP464x_104), 249 MCP4531_COMPATIBLE("microchip,mcp4651-502", MCP465x_502), 250 MCP4531_COMPATIBLE("microchip,mcp4651-103", MCP465x_103), 251 MCP4531_COMPATIBLE("microchip,mcp4651-503", MCP465x_503), 252 MCP4531_COMPATIBLE("microchip,mcp4651-104", MCP465x_104), 253 MCP4531_COMPATIBLE("microchip,mcp4652-502", MCP465x_502), 254 MCP4531_COMPATIBLE("microchip,mcp4652-103", MCP465x_103), 255 MCP4531_COMPATIBLE("microchip,mcp4652-503", MCP465x_503), 256 MCP4531_COMPATIBLE("microchip,mcp4652-104", MCP465x_104), 257 MCP4531_COMPATIBLE("microchip,mcp4661-502", MCP466x_502), 258 MCP4531_COMPATIBLE("microchip,mcp4661-103", MCP466x_103), 259 MCP4531_COMPATIBLE("microchip,mcp4661-503", MCP466x_503), 260 MCP4531_COMPATIBLE("microchip,mcp4661-104", MCP466x_104), 261 MCP4531_COMPATIBLE("microchip,mcp4662-502", MCP466x_502), 262 MCP4531_COMPATIBLE("microchip,mcp4662-103", MCP466x_103), 263 MCP4531_COMPATIBLE("microchip,mcp4662-503", MCP466x_503), 264 MCP4531_COMPATIBLE("microchip,mcp4662-104", MCP466x_104), 265 { /* sentinel */ } 266 }; 267 #endif 268 269 static int mcp4531_probe(struct i2c_client *client, 270 const struct i2c_device_id *id) 271 { 272 struct device *dev = &client->dev; 273 struct mcp4531_data *data; 274 struct iio_dev *indio_dev; 275 const struct of_device_id *match; 276 277 if (!i2c_check_functionality(client->adapter, 278 I2C_FUNC_SMBUS_WORD_DATA)) { 279 dev_err(dev, "SMBUS Word Data not supported\n"); 280 return -EOPNOTSUPP; 281 } 282 283 indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); 284 if (!indio_dev) 285 return -ENOMEM; 286 data = iio_priv(indio_dev); 287 i2c_set_clientdata(client, indio_dev); 288 data->client = client; 289 290 match = of_match_device(of_match_ptr(mcp4531_of_match), dev); 291 if (match) 292 data->cfg = of_device_get_match_data(dev); 293 else 294 data->cfg = &mcp4531_cfg[id->driver_data]; 295 296 indio_dev->dev.parent = dev; 297 indio_dev->info = &mcp4531_info; 298 indio_dev->channels = mcp4531_channels; 299 indio_dev->num_channels = data->cfg->wipers; 300 indio_dev->name = client->name; 301 302 return devm_iio_device_register(dev, indio_dev); 303 } 304 305 static const struct i2c_device_id mcp4531_id[] = { 306 { "mcp4531-502", MCP453x_502 }, 307 { "mcp4531-103", MCP453x_103 }, 308 { "mcp4531-503", MCP453x_503 }, 309 { "mcp4531-104", MCP453x_104 }, 310 { "mcp4532-502", MCP453x_502 }, 311 { "mcp4532-103", MCP453x_103 }, 312 { "mcp4532-503", MCP453x_503 }, 313 { "mcp4532-104", MCP453x_104 }, 314 { "mcp4541-502", MCP454x_502 }, 315 { "mcp4541-103", MCP454x_103 }, 316 { "mcp4541-503", MCP454x_503 }, 317 { "mcp4541-104", MCP454x_104 }, 318 { "mcp4542-502", MCP454x_502 }, 319 { "mcp4542-103", MCP454x_103 }, 320 { "mcp4542-503", MCP454x_503 }, 321 { "mcp4542-104", MCP454x_104 }, 322 { "mcp4551-502", MCP455x_502 }, 323 { "mcp4551-103", MCP455x_103 }, 324 { "mcp4551-503", MCP455x_503 }, 325 { "mcp4551-104", MCP455x_104 }, 326 { "mcp4552-502", MCP455x_502 }, 327 { "mcp4552-103", MCP455x_103 }, 328 { "mcp4552-503", MCP455x_503 }, 329 { "mcp4552-104", MCP455x_104 }, 330 { "mcp4561-502", MCP456x_502 }, 331 { "mcp4561-103", MCP456x_103 }, 332 { "mcp4561-503", MCP456x_503 }, 333 { "mcp4561-104", MCP456x_104 }, 334 { "mcp4562-502", MCP456x_502 }, 335 { "mcp4562-103", MCP456x_103 }, 336 { "mcp4562-503", MCP456x_503 }, 337 { "mcp4562-104", MCP456x_104 }, 338 { "mcp4631-502", MCP463x_502 }, 339 { "mcp4631-103", MCP463x_103 }, 340 { "mcp4631-503", MCP463x_503 }, 341 { "mcp4631-104", MCP463x_104 }, 342 { "mcp4632-502", MCP463x_502 }, 343 { "mcp4632-103", MCP463x_103 }, 344 { "mcp4632-503", MCP463x_503 }, 345 { "mcp4632-104", MCP463x_104 }, 346 { "mcp4641-502", MCP464x_502 }, 347 { "mcp4641-103", MCP464x_103 }, 348 { "mcp4641-503", MCP464x_503 }, 349 { "mcp4641-104", MCP464x_104 }, 350 { "mcp4642-502", MCP464x_502 }, 351 { "mcp4642-103", MCP464x_103 }, 352 { "mcp4642-503", MCP464x_503 }, 353 { "mcp4642-104", MCP464x_104 }, 354 { "mcp4651-502", MCP465x_502 }, 355 { "mcp4651-103", MCP465x_103 }, 356 { "mcp4651-503", MCP465x_503 }, 357 { "mcp4651-104", MCP465x_104 }, 358 { "mcp4652-502", MCP465x_502 }, 359 { "mcp4652-103", MCP465x_103 }, 360 { "mcp4652-503", MCP465x_503 }, 361 { "mcp4652-104", MCP465x_104 }, 362 { "mcp4661-502", MCP466x_502 }, 363 { "mcp4661-103", MCP466x_103 }, 364 { "mcp4661-503", MCP466x_503 }, 365 { "mcp4661-104", MCP466x_104 }, 366 { "mcp4662-502", MCP466x_502 }, 367 { "mcp4662-103", MCP466x_103 }, 368 { "mcp4662-503", MCP466x_503 }, 369 { "mcp4662-104", MCP466x_104 }, 370 {} 371 }; 372 MODULE_DEVICE_TABLE(i2c, mcp4531_id); 373 374 static struct i2c_driver mcp4531_driver = { 375 .driver = { 376 .name = "mcp4531", 377 .of_match_table = of_match_ptr(mcp4531_of_match), 378 }, 379 .probe = mcp4531_probe, 380 .id_table = mcp4531_id, 381 }; 382 383 module_i2c_driver(mcp4531_driver); 384 385 MODULE_AUTHOR("Peter Rosin <peda@axentia.se>"); 386 MODULE_DESCRIPTION("MCP4531 digital potentiometer"); 387 MODULE_LICENSE("GPL"); 388