10ba56985SPeter Rosin // SPDX-License-Identifier: GPL-2.0 2c05dc2ccSPeter Rosin /* 3c05dc2ccSPeter Rosin * Industrial I/O driver for Microchip digital potentiometers 4c05dc2ccSPeter Rosin * Copyright (c) 2015 Axentia Technologies AB 5c05dc2ccSPeter Rosin * Author: Peter Rosin <peda@axentia.se> 6c05dc2ccSPeter Rosin * 7c05dc2ccSPeter Rosin * Datasheet: http://www.microchip.com/downloads/en/DeviceDoc/22096b.pdf 8c05dc2ccSPeter Rosin * 9c05dc2ccSPeter Rosin * DEVID #Wipers #Positions Resistor Opts (kOhm) i2c address 10c05dc2ccSPeter Rosin * mcp4531 1 129 5, 10, 50, 100 010111x 11c05dc2ccSPeter Rosin * mcp4532 1 129 5, 10, 50, 100 01011xx 12294ea6f3SFlorian Vaussard * mcp4541 1 129 5, 10, 50, 100 010111x 13294ea6f3SFlorian Vaussard * mcp4542 1 129 5, 10, 50, 100 01011xx 14c05dc2ccSPeter Rosin * mcp4551 1 257 5, 10, 50, 100 010111x 15c05dc2ccSPeter Rosin * mcp4552 1 257 5, 10, 50, 100 01011xx 16294ea6f3SFlorian Vaussard * mcp4561 1 257 5, 10, 50, 100 010111x 17294ea6f3SFlorian Vaussard * mcp4562 1 257 5, 10, 50, 100 01011xx 18c05dc2ccSPeter Rosin * mcp4631 2 129 5, 10, 50, 100 0101xxx 19c05dc2ccSPeter Rosin * mcp4632 2 129 5, 10, 50, 100 01011xx 20294ea6f3SFlorian Vaussard * mcp4641 2 129 5, 10, 50, 100 0101xxx 21294ea6f3SFlorian Vaussard * mcp4642 2 129 5, 10, 50, 100 01011xx 22c05dc2ccSPeter Rosin * mcp4651 2 257 5, 10, 50, 100 0101xxx 23c05dc2ccSPeter Rosin * mcp4652 2 257 5, 10, 50, 100 01011xx 24294ea6f3SFlorian Vaussard * mcp4661 2 257 5, 10, 50, 100 0101xxx 25294ea6f3SFlorian Vaussard * mcp4662 2 257 5, 10, 50, 100 01011xx 26c05dc2ccSPeter Rosin */ 27c05dc2ccSPeter Rosin 28c05dc2ccSPeter Rosin #include <linux/module.h> 29c05dc2ccSPeter Rosin #include <linux/i2c.h> 30c05dc2ccSPeter Rosin #include <linux/err.h> 3120e39f3aSJonathan Cameron #include <linux/mod_devicetable.h> 3220e39f3aSJonathan Cameron #include <linux/property.h> 33c05dc2ccSPeter Rosin 34c05dc2ccSPeter Rosin #include <linux/iio/iio.h> 35c05dc2ccSPeter Rosin 36c05dc2ccSPeter Rosin struct mcp4531_cfg { 37c05dc2ccSPeter Rosin int wipers; 382704e300SPeter Rosin int avail[3]; 39c05dc2ccSPeter Rosin int kohms; 40c05dc2ccSPeter Rosin }; 41c05dc2ccSPeter Rosin 42c05dc2ccSPeter Rosin enum mcp4531_type { 43c05dc2ccSPeter Rosin MCP453x_502, 44c05dc2ccSPeter Rosin MCP453x_103, 45c05dc2ccSPeter Rosin MCP453x_503, 46c05dc2ccSPeter Rosin MCP453x_104, 47294ea6f3SFlorian Vaussard MCP454x_502, 48294ea6f3SFlorian Vaussard MCP454x_103, 49294ea6f3SFlorian Vaussard MCP454x_503, 50294ea6f3SFlorian Vaussard MCP454x_104, 51c05dc2ccSPeter Rosin MCP455x_502, 52c05dc2ccSPeter Rosin MCP455x_103, 53c05dc2ccSPeter Rosin MCP455x_503, 54c05dc2ccSPeter Rosin MCP455x_104, 55294ea6f3SFlorian Vaussard MCP456x_502, 56294ea6f3SFlorian Vaussard MCP456x_103, 57294ea6f3SFlorian Vaussard MCP456x_503, 58294ea6f3SFlorian Vaussard MCP456x_104, 59c05dc2ccSPeter Rosin MCP463x_502, 60c05dc2ccSPeter Rosin MCP463x_103, 61c05dc2ccSPeter Rosin MCP463x_503, 62c05dc2ccSPeter Rosin MCP463x_104, 63294ea6f3SFlorian Vaussard MCP464x_502, 64294ea6f3SFlorian Vaussard MCP464x_103, 65294ea6f3SFlorian Vaussard MCP464x_503, 66294ea6f3SFlorian Vaussard MCP464x_104, 67c05dc2ccSPeter Rosin MCP465x_502, 68c05dc2ccSPeter Rosin MCP465x_103, 69c05dc2ccSPeter Rosin MCP465x_503, 70c05dc2ccSPeter Rosin MCP465x_104, 71294ea6f3SFlorian Vaussard MCP466x_502, 72294ea6f3SFlorian Vaussard MCP466x_103, 73294ea6f3SFlorian Vaussard MCP466x_503, 74294ea6f3SFlorian Vaussard MCP466x_104, 75c05dc2ccSPeter Rosin }; 76c05dc2ccSPeter Rosin 77c05dc2ccSPeter Rosin static const struct mcp4531_cfg mcp4531_cfg[] = { 782704e300SPeter Rosin [MCP453x_502] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms = 5, }, 792704e300SPeter Rosin [MCP453x_103] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms = 10, }, 802704e300SPeter Rosin [MCP453x_503] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms = 50, }, 812704e300SPeter Rosin [MCP453x_104] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms = 100, }, 822704e300SPeter Rosin [MCP454x_502] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms = 5, }, 832704e300SPeter Rosin [MCP454x_103] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms = 10, }, 842704e300SPeter Rosin [MCP454x_503] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms = 50, }, 852704e300SPeter Rosin [MCP454x_104] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms = 100, }, 862704e300SPeter Rosin [MCP455x_502] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms = 5, }, 872704e300SPeter Rosin [MCP455x_103] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms = 10, }, 882704e300SPeter Rosin [MCP455x_503] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms = 50, }, 892704e300SPeter Rosin [MCP455x_104] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms = 100, }, 902704e300SPeter Rosin [MCP456x_502] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms = 5, }, 912704e300SPeter Rosin [MCP456x_103] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms = 10, }, 922704e300SPeter Rosin [MCP456x_503] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms = 50, }, 932704e300SPeter Rosin [MCP456x_104] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms = 100, }, 942704e300SPeter Rosin [MCP463x_502] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms = 5, }, 952704e300SPeter Rosin [MCP463x_103] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms = 10, }, 962704e300SPeter Rosin [MCP463x_503] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms = 50, }, 972704e300SPeter Rosin [MCP463x_104] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms = 100, }, 982704e300SPeter Rosin [MCP464x_502] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms = 5, }, 992704e300SPeter Rosin [MCP464x_103] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms = 10, }, 1002704e300SPeter Rosin [MCP464x_503] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms = 50, }, 1012704e300SPeter Rosin [MCP464x_104] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms = 100, }, 1022704e300SPeter Rosin [MCP465x_502] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms = 5, }, 1032704e300SPeter Rosin [MCP465x_103] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms = 10, }, 1042704e300SPeter Rosin [MCP465x_503] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms = 50, }, 1052704e300SPeter Rosin [MCP465x_104] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms = 100, }, 1062704e300SPeter Rosin [MCP466x_502] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms = 5, }, 1072704e300SPeter Rosin [MCP466x_103] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms = 10, }, 1082704e300SPeter Rosin [MCP466x_503] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms = 50, }, 1092704e300SPeter Rosin [MCP466x_104] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms = 100, }, 110c05dc2ccSPeter Rosin }; 111c05dc2ccSPeter Rosin 112c05dc2ccSPeter Rosin #define MCP4531_WRITE (0 << 2) 113c05dc2ccSPeter Rosin #define MCP4531_INCR (1 << 2) 114c05dc2ccSPeter Rosin #define MCP4531_DECR (2 << 2) 115c05dc2ccSPeter Rosin #define MCP4531_READ (3 << 2) 116c05dc2ccSPeter Rosin 117c05dc2ccSPeter Rosin #define MCP4531_WIPER_SHIFT (4) 118c05dc2ccSPeter Rosin 119c05dc2ccSPeter Rosin struct mcp4531_data { 120c05dc2ccSPeter Rosin struct i2c_client *client; 12191307cbeSSlawomir Stepien const struct mcp4531_cfg *cfg; 122c05dc2ccSPeter Rosin }; 123c05dc2ccSPeter Rosin 124c05dc2ccSPeter Rosin #define MCP4531_CHANNEL(ch) { \ 125c05dc2ccSPeter Rosin .type = IIO_RESISTANCE, \ 126c05dc2ccSPeter Rosin .indexed = 1, \ 127c05dc2ccSPeter Rosin .output = 1, \ 128c05dc2ccSPeter Rosin .channel = (ch), \ 129c05dc2ccSPeter Rosin .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 130c05dc2ccSPeter Rosin .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 1312704e300SPeter Rosin .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_RAW), \ 132c05dc2ccSPeter Rosin } 133c05dc2ccSPeter Rosin 134c05dc2ccSPeter Rosin static const struct iio_chan_spec mcp4531_channels[] = { 135c05dc2ccSPeter Rosin MCP4531_CHANNEL(0), 136c05dc2ccSPeter Rosin MCP4531_CHANNEL(1), 137c05dc2ccSPeter Rosin }; 138c05dc2ccSPeter Rosin 139c05dc2ccSPeter Rosin static int mcp4531_read_raw(struct iio_dev *indio_dev, 140c05dc2ccSPeter Rosin struct iio_chan_spec const *chan, 141c05dc2ccSPeter Rosin int *val, int *val2, long mask) 142c05dc2ccSPeter Rosin { 143c05dc2ccSPeter Rosin struct mcp4531_data *data = iio_priv(indio_dev); 144c05dc2ccSPeter Rosin int address = chan->channel << MCP4531_WIPER_SHIFT; 145c05dc2ccSPeter Rosin s32 ret; 146c05dc2ccSPeter Rosin 147c05dc2ccSPeter Rosin switch (mask) { 148c05dc2ccSPeter Rosin case IIO_CHAN_INFO_RAW: 149c05dc2ccSPeter Rosin ret = i2c_smbus_read_word_swapped(data->client, 150c05dc2ccSPeter Rosin MCP4531_READ | address); 151c05dc2ccSPeter Rosin if (ret < 0) 152c05dc2ccSPeter Rosin return ret; 153c05dc2ccSPeter Rosin *val = ret; 154c05dc2ccSPeter Rosin return IIO_VAL_INT; 155c05dc2ccSPeter Rosin case IIO_CHAN_INFO_SCALE: 15691307cbeSSlawomir Stepien *val = 1000 * data->cfg->kohms; 1572704e300SPeter Rosin *val2 = data->cfg->avail[2]; 158c05dc2ccSPeter Rosin return IIO_VAL_FRACTIONAL; 159c05dc2ccSPeter Rosin } 160c05dc2ccSPeter Rosin 161c05dc2ccSPeter Rosin return -EINVAL; 162c05dc2ccSPeter Rosin } 163c05dc2ccSPeter Rosin 1642704e300SPeter Rosin static int mcp4531_read_avail(struct iio_dev *indio_dev, 1652704e300SPeter Rosin struct iio_chan_spec const *chan, 1662704e300SPeter Rosin const int **vals, int *type, int *length, 1672704e300SPeter Rosin long mask) 1682704e300SPeter Rosin { 1692704e300SPeter Rosin struct mcp4531_data *data = iio_priv(indio_dev); 1702704e300SPeter Rosin 1712704e300SPeter Rosin switch (mask) { 1722704e300SPeter Rosin case IIO_CHAN_INFO_RAW: 1732704e300SPeter Rosin *length = ARRAY_SIZE(data->cfg->avail); 1742704e300SPeter Rosin *vals = data->cfg->avail; 1752704e300SPeter Rosin *type = IIO_VAL_INT; 1762704e300SPeter Rosin return IIO_AVAIL_RANGE; 1772704e300SPeter Rosin } 1782704e300SPeter Rosin 1792704e300SPeter Rosin return -EINVAL; 1802704e300SPeter Rosin } 1812704e300SPeter Rosin 182c05dc2ccSPeter Rosin static int mcp4531_write_raw(struct iio_dev *indio_dev, 183c05dc2ccSPeter Rosin struct iio_chan_spec const *chan, 184c05dc2ccSPeter Rosin int val, int val2, long mask) 185c05dc2ccSPeter Rosin { 186c05dc2ccSPeter Rosin struct mcp4531_data *data = iio_priv(indio_dev); 187c05dc2ccSPeter Rosin int address = chan->channel << MCP4531_WIPER_SHIFT; 188c05dc2ccSPeter Rosin 189c05dc2ccSPeter Rosin switch (mask) { 190c05dc2ccSPeter Rosin case IIO_CHAN_INFO_RAW: 1912704e300SPeter Rosin if (val > data->cfg->avail[2] || val < 0) 192c05dc2ccSPeter Rosin return -EINVAL; 193c05dc2ccSPeter Rosin break; 194c05dc2ccSPeter Rosin default: 195c05dc2ccSPeter Rosin return -EINVAL; 196c05dc2ccSPeter Rosin } 197c05dc2ccSPeter Rosin 198c05dc2ccSPeter Rosin return i2c_smbus_write_byte_data(data->client, 199c05dc2ccSPeter Rosin MCP4531_WRITE | address | (val >> 8), 200c05dc2ccSPeter Rosin val & 0xff); 201c05dc2ccSPeter Rosin } 202c05dc2ccSPeter Rosin 203c05dc2ccSPeter Rosin static const struct iio_info mcp4531_info = { 204c05dc2ccSPeter Rosin .read_raw = mcp4531_read_raw, 2052704e300SPeter Rosin .read_avail = mcp4531_read_avail, 206c05dc2ccSPeter Rosin .write_raw = mcp4531_write_raw, 207c05dc2ccSPeter Rosin }; 208c05dc2ccSPeter Rosin 209*9afc8c6dSBiju Das #define MCP4531_ID_TABLE(_name, cfg) { \ 210*9afc8c6dSBiju Das .name = _name, \ 211*9afc8c6dSBiju Das .driver_data = (kernel_ulong_t)&mcp4531_cfg[cfg], \ 212*9afc8c6dSBiju Das } 213*9afc8c6dSBiju Das 214c18af98bSPeter Rosin static const struct i2c_device_id mcp4531_id[] = { 215*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4531-502", MCP453x_502), 216*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4531-103", MCP453x_103), 217*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4531-503", MCP453x_503), 218*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4531-104", MCP453x_104), 219*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4532-502", MCP453x_502), 220*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4532-103", MCP453x_103), 221*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4532-503", MCP453x_503), 222*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4532-104", MCP453x_104), 223*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4541-502", MCP454x_502), 224*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4541-103", MCP454x_103), 225*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4541-503", MCP454x_503), 226*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4541-104", MCP454x_104), 227*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4542-502", MCP454x_502), 228*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4542-103", MCP454x_103), 229*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4542-503", MCP454x_503), 230*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4542-104", MCP454x_104), 231*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4551-502", MCP455x_502), 232*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4551-103", MCP455x_103), 233*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4551-503", MCP455x_503), 234*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4551-104", MCP455x_104), 235*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4552-502", MCP455x_502), 236*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4552-103", MCP455x_103), 237*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4552-503", MCP455x_503), 238*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4552-104", MCP455x_104), 239*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4561-502", MCP456x_502), 240*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4561-103", MCP456x_103), 241*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4561-503", MCP456x_503), 242*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4561-104", MCP456x_104), 243*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4562-502", MCP456x_502), 244*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4562-103", MCP456x_103), 245*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4562-503", MCP456x_503), 246*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4562-104", MCP456x_104), 247*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4631-502", MCP463x_502), 248*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4631-103", MCP463x_103), 249*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4631-503", MCP463x_503), 250*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4631-104", MCP463x_104), 251*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4632-502", MCP463x_502), 252*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4632-103", MCP463x_103), 253*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4632-503", MCP463x_503), 254*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4632-104", MCP463x_104), 255*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4641-502", MCP464x_502), 256*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4641-103", MCP464x_103), 257*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4641-503", MCP464x_503), 258*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4641-104", MCP464x_104), 259*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4642-502", MCP464x_502), 260*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4642-103", MCP464x_103), 261*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4642-503", MCP464x_503), 262*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4642-104", MCP464x_104), 263*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4651-502", MCP465x_502), 264*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4651-103", MCP465x_103), 265*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4651-503", MCP465x_503), 266*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4651-104", MCP465x_104), 267*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4652-502", MCP465x_502), 268*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4652-103", MCP465x_103), 269*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4652-503", MCP465x_503), 270*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4652-104", MCP465x_104), 271*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4661-502", MCP466x_502), 272*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4661-103", MCP466x_103), 273*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4661-503", MCP466x_503), 274*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4661-104", MCP466x_104), 275*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4662-502", MCP466x_502), 276*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4662-103", MCP466x_103), 277*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4662-503", MCP466x_503), 278*9afc8c6dSBiju Das MCP4531_ID_TABLE("mcp4662-104", MCP466x_104), 279*9afc8c6dSBiju Das { /* sentinel */ } 280c18af98bSPeter Rosin }; 281c18af98bSPeter Rosin MODULE_DEVICE_TABLE(i2c, mcp4531_id); 282c18af98bSPeter Rosin 2832dc2e189SFlorian Vaussard #define MCP4531_COMPATIBLE(of_compatible, cfg) { \ 2842dc2e189SFlorian Vaussard .compatible = of_compatible, \ 2852dc2e189SFlorian Vaussard .data = &mcp4531_cfg[cfg], \ 2862dc2e189SFlorian Vaussard } 2872dc2e189SFlorian Vaussard 2882dc2e189SFlorian Vaussard static const struct of_device_id mcp4531_of_match[] = { 2892dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4531-502", MCP453x_502), 2902dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4531-103", MCP453x_103), 2912dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4531-503", MCP453x_503), 2922dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4531-104", MCP453x_104), 2932dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4532-502", MCP453x_502), 2942dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4532-103", MCP453x_103), 2952dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4532-503", MCP453x_503), 2962dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4532-104", MCP453x_104), 2972dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4541-502", MCP454x_502), 2982dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4541-103", MCP454x_103), 2992dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4541-503", MCP454x_503), 3002dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4541-104", MCP454x_104), 3012dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4542-502", MCP454x_502), 3022dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4542-103", MCP454x_103), 3032dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4542-503", MCP454x_503), 3042dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4542-104", MCP454x_104), 3052dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4551-502", MCP455x_502), 3062dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4551-103", MCP455x_103), 3072dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4551-503", MCP455x_503), 3082dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4551-104", MCP455x_104), 3092dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4552-502", MCP455x_502), 3102dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4552-103", MCP455x_103), 3112dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4552-503", MCP455x_503), 3122dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4552-104", MCP455x_104), 3132dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4561-502", MCP456x_502), 3142dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4561-103", MCP456x_103), 3152dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4561-503", MCP456x_503), 3162dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4561-104", MCP456x_104), 3172dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4562-502", MCP456x_502), 3182dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4562-103", MCP456x_103), 3192dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4562-503", MCP456x_503), 3202dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4562-104", MCP456x_104), 3212dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4631-502", MCP463x_502), 3222dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4631-103", MCP463x_103), 3232dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4631-503", MCP463x_503), 3242dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4631-104", MCP463x_104), 3252dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4632-502", MCP463x_502), 3262dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4632-103", MCP463x_103), 3272dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4632-503", MCP463x_503), 3282dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4632-104", MCP463x_104), 3292dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4641-502", MCP464x_502), 3302dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4641-103", MCP464x_103), 3312dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4641-503", MCP464x_503), 3322dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4641-104", MCP464x_104), 3332dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4642-502", MCP464x_502), 3342dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4642-103", MCP464x_103), 3352dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4642-503", MCP464x_503), 3362dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4642-104", MCP464x_104), 3372dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4651-502", MCP465x_502), 3382dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4651-103", MCP465x_103), 3392dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4651-503", MCP465x_503), 3402dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4651-104", MCP465x_104), 3412dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4652-502", MCP465x_502), 3422dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4652-103", MCP465x_103), 3432dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4652-503", MCP465x_503), 3442dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4652-104", MCP465x_104), 3452dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4661-502", MCP466x_502), 3462dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4661-103", MCP466x_103), 3472dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4661-503", MCP466x_503), 3482dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4661-104", MCP466x_104), 3492dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4662-502", MCP466x_502), 3502dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4662-103", MCP466x_103), 3512dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4662-503", MCP466x_503), 3522dc2e189SFlorian Vaussard MCP4531_COMPATIBLE("microchip,mcp4662-104", MCP466x_104), 3532dc2e189SFlorian Vaussard { /* sentinel */ } 3542dc2e189SFlorian Vaussard }; 3559c6e4efdSJavier Martinez Canillas MODULE_DEVICE_TABLE(of, mcp4531_of_match); 3562dc2e189SFlorian Vaussard 357c18af98bSPeter Rosin static int mcp4531_probe(struct i2c_client *client) 358c05dc2ccSPeter Rosin { 359c05dc2ccSPeter Rosin struct device *dev = &client->dev; 360c05dc2ccSPeter Rosin struct mcp4531_data *data; 361c05dc2ccSPeter Rosin struct iio_dev *indio_dev; 362c05dc2ccSPeter Rosin 363c05dc2ccSPeter Rosin if (!i2c_check_functionality(client->adapter, 364c05dc2ccSPeter Rosin I2C_FUNC_SMBUS_WORD_DATA)) { 365c05dc2ccSPeter Rosin dev_err(dev, "SMBUS Word Data not supported\n"); 366f8d9d3b4SMatt Ranostay return -EOPNOTSUPP; 367c05dc2ccSPeter Rosin } 368c05dc2ccSPeter Rosin 369c05dc2ccSPeter Rosin indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); 370c05dc2ccSPeter Rosin if (!indio_dev) 371c05dc2ccSPeter Rosin return -ENOMEM; 372c05dc2ccSPeter Rosin data = iio_priv(indio_dev); 373c05dc2ccSPeter Rosin i2c_set_clientdata(client, indio_dev); 374c05dc2ccSPeter Rosin data->client = client; 3752dc2e189SFlorian Vaussard 376*9afc8c6dSBiju Das data->cfg = i2c_get_match_data(client); 377c05dc2ccSPeter Rosin 378c05dc2ccSPeter Rosin indio_dev->info = &mcp4531_info; 379c05dc2ccSPeter Rosin indio_dev->channels = mcp4531_channels; 38091307cbeSSlawomir Stepien indio_dev->num_channels = data->cfg->wipers; 381c05dc2ccSPeter Rosin indio_dev->name = client->name; 382c05dc2ccSPeter Rosin 383c05dc2ccSPeter Rosin return devm_iio_device_register(dev, indio_dev); 384c05dc2ccSPeter Rosin } 385c05dc2ccSPeter Rosin 386c05dc2ccSPeter Rosin static struct i2c_driver mcp4531_driver = { 387c05dc2ccSPeter Rosin .driver = { 388c05dc2ccSPeter Rosin .name = "mcp4531", 38920e39f3aSJonathan Cameron .of_match_table = mcp4531_of_match, 390c05dc2ccSPeter Rosin }, 3917cf15f42SUwe Kleine-König .probe = mcp4531_probe, 392c05dc2ccSPeter Rosin .id_table = mcp4531_id, 393c05dc2ccSPeter Rosin }; 394c05dc2ccSPeter Rosin 395c05dc2ccSPeter Rosin module_i2c_driver(mcp4531_driver); 396c05dc2ccSPeter Rosin 397c05dc2ccSPeter Rosin MODULE_AUTHOR("Peter Rosin <peda@axentia.se>"); 398c05dc2ccSPeter Rosin MODULE_DESCRIPTION("MCP4531 digital potentiometer"); 3990ba56985SPeter Rosin MODULE_LICENSE("GPL v2"); 400