1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Industrial I/O driver for Microchip digital potentiometers 4 * Copyright (c) 2018 Axentia Technologies AB 5 * Author: Peter Rosin <peda@axentia.se> 6 * 7 * Datasheet: http://www.microchip.com/downloads/en/DeviceDoc/22147a.pdf 8 * 9 * DEVID #Wipers #Positions Resistor Opts (kOhm) 10 * mcp4017 1 128 5, 10, 50, 100 11 * mcp4018 1 128 5, 10, 50, 100 12 * mcp4019 1 128 5, 10, 50, 100 13 */ 14 15 #include <linux/err.h> 16 #include <linux/i2c.h> 17 #include <linux/iio/iio.h> 18 #include <linux/module.h> 19 #include <linux/of.h> 20 #include <linux/of_device.h> 21 22 #define MCP4018_WIPER_MAX 127 23 24 struct mcp4018_cfg { 25 int kohms; 26 }; 27 28 enum mcp4018_type { 29 MCP4018_502, 30 MCP4018_103, 31 MCP4018_503, 32 MCP4018_104, 33 }; 34 35 static const struct mcp4018_cfg mcp4018_cfg[] = { 36 [MCP4018_502] = { .kohms = 5, }, 37 [MCP4018_103] = { .kohms = 10, }, 38 [MCP4018_503] = { .kohms = 50, }, 39 [MCP4018_104] = { .kohms = 100, }, 40 }; 41 42 struct mcp4018_data { 43 struct i2c_client *client; 44 const struct mcp4018_cfg *cfg; 45 }; 46 47 static const struct iio_chan_spec mcp4018_channel = { 48 .type = IIO_RESISTANCE, 49 .indexed = 1, 50 .output = 1, 51 .channel = 0, 52 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 53 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), 54 }; 55 56 static int mcp4018_read_raw(struct iio_dev *indio_dev, 57 struct iio_chan_spec const *chan, 58 int *val, int *val2, long mask) 59 { 60 struct mcp4018_data *data = iio_priv(indio_dev); 61 s32 ret; 62 63 switch (mask) { 64 case IIO_CHAN_INFO_RAW: 65 ret = i2c_smbus_read_byte(data->client); 66 if (ret < 0) 67 return ret; 68 *val = ret; 69 return IIO_VAL_INT; 70 case IIO_CHAN_INFO_SCALE: 71 *val = 1000 * data->cfg->kohms; 72 *val2 = MCP4018_WIPER_MAX; 73 return IIO_VAL_FRACTIONAL; 74 } 75 76 return -EINVAL; 77 } 78 79 static int mcp4018_write_raw(struct iio_dev *indio_dev, 80 struct iio_chan_spec const *chan, 81 int val, int val2, long mask) 82 { 83 struct mcp4018_data *data = iio_priv(indio_dev); 84 85 switch (mask) { 86 case IIO_CHAN_INFO_RAW: 87 if (val > MCP4018_WIPER_MAX || val < 0) 88 return -EINVAL; 89 break; 90 default: 91 return -EINVAL; 92 } 93 94 return i2c_smbus_write_byte(data->client, val); 95 } 96 97 static const struct iio_info mcp4018_info = { 98 .read_raw = mcp4018_read_raw, 99 .write_raw = mcp4018_write_raw, 100 }; 101 102 #ifdef CONFIG_OF 103 104 #define MCP4018_COMPATIBLE(of_compatible, cfg) { \ 105 .compatible = of_compatible, \ 106 .data = &mcp4018_cfg[cfg], \ 107 } 108 109 static const struct of_device_id mcp4018_of_match[] = { 110 MCP4018_COMPATIBLE("microchip,mcp4017-502", MCP4018_502), 111 MCP4018_COMPATIBLE("microchip,mcp4017-103", MCP4018_103), 112 MCP4018_COMPATIBLE("microchip,mcp4017-503", MCP4018_503), 113 MCP4018_COMPATIBLE("microchip,mcp4017-104", MCP4018_104), 114 MCP4018_COMPATIBLE("microchip,mcp4018-502", MCP4018_502), 115 MCP4018_COMPATIBLE("microchip,mcp4018-103", MCP4018_103), 116 MCP4018_COMPATIBLE("microchip,mcp4018-503", MCP4018_503), 117 MCP4018_COMPATIBLE("microchip,mcp4018-104", MCP4018_104), 118 MCP4018_COMPATIBLE("microchip,mcp4019-502", MCP4018_502), 119 MCP4018_COMPATIBLE("microchip,mcp4019-103", MCP4018_103), 120 MCP4018_COMPATIBLE("microchip,mcp4019-503", MCP4018_503), 121 MCP4018_COMPATIBLE("microchip,mcp4019-104", MCP4018_104), 122 { /* sentinel */ } 123 }; 124 MODULE_DEVICE_TABLE(of, mcp4018_of_match); 125 126 #endif 127 128 static int mcp4018_probe(struct i2c_client *client, 129 const struct i2c_device_id *id) 130 { 131 struct device *dev = &client->dev; 132 struct mcp4018_data *data; 133 struct iio_dev *indio_dev; 134 const struct of_device_id *match; 135 136 if (!i2c_check_functionality(client->adapter, 137 I2C_FUNC_SMBUS_BYTE)) { 138 dev_err(dev, "SMBUS Byte transfers not supported\n"); 139 return -EOPNOTSUPP; 140 } 141 142 indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); 143 if (!indio_dev) 144 return -ENOMEM; 145 data = iio_priv(indio_dev); 146 i2c_set_clientdata(client, indio_dev); 147 data->client = client; 148 149 match = of_match_device(of_match_ptr(mcp4018_of_match), dev); 150 if (match) 151 data->cfg = of_device_get_match_data(dev); 152 else 153 data->cfg = &mcp4018_cfg[id->driver_data]; 154 155 indio_dev->dev.parent = dev; 156 indio_dev->info = &mcp4018_info; 157 indio_dev->channels = &mcp4018_channel; 158 indio_dev->num_channels = 1; 159 indio_dev->name = client->name; 160 161 return devm_iio_device_register(dev, indio_dev); 162 } 163 164 static const struct i2c_device_id mcp4018_id[] = { 165 { "mcp4017-502", MCP4018_502 }, 166 { "mcp4017-103", MCP4018_103 }, 167 { "mcp4017-503", MCP4018_503 }, 168 { "mcp4017-104", MCP4018_104 }, 169 { "mcp4018-502", MCP4018_502 }, 170 { "mcp4018-103", MCP4018_103 }, 171 { "mcp4018-503", MCP4018_503 }, 172 { "mcp4018-104", MCP4018_104 }, 173 { "mcp4019-502", MCP4018_502 }, 174 { "mcp4019-103", MCP4018_103 }, 175 { "mcp4019-503", MCP4018_503 }, 176 { "mcp4019-104", MCP4018_104 }, 177 {} 178 }; 179 MODULE_DEVICE_TABLE(i2c, mcp4018_id); 180 181 static struct i2c_driver mcp4018_driver = { 182 .driver = { 183 .name = "mcp4018", 184 .of_match_table = of_match_ptr(mcp4018_of_match), 185 }, 186 .probe = mcp4018_probe, 187 .id_table = mcp4018_id, 188 }; 189 190 module_i2c_driver(mcp4018_driver); 191 192 MODULE_AUTHOR("Peter Rosin <peda@axentia.se>"); 193 MODULE_DESCRIPTION("MCP4018 digital potentiometer"); 194 MODULE_LICENSE("GPL"); 195