0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/module.h>
0012 #include <linux/i2c.h>
0013 #include <linux/regmap.h>
0014 #include <linux/iio/iio.h>
0015
0016 struct tpl0102_cfg {
0017 int wipers;
0018 int avail[3];
0019 int kohms;
0020 };
0021
0022 enum tpl0102_type {
0023 CAT5140_503,
0024 CAT5140_104,
0025 TPL0102_104,
0026 TPL0401_103,
0027 };
0028
0029 static const struct tpl0102_cfg tpl0102_cfg[] = {
0030
0031 [CAT5140_503] = { .wipers = 1, .avail = { 0, 1, 255 }, .kohms = 50, },
0032 [CAT5140_104] = { .wipers = 1, .avail = { 0, 1, 255 }, .kohms = 100, },
0033
0034 [TPL0102_104] = { .wipers = 2, .avail = { 0, 1, 255 }, .kohms = 100 },
0035 [TPL0401_103] = { .wipers = 1, .avail = { 0, 1, 127 }, .kohms = 10, },
0036 };
0037
0038 struct tpl0102_data {
0039 struct regmap *regmap;
0040 const struct tpl0102_cfg *cfg;
0041 };
0042
0043 static const struct regmap_config tpl0102_regmap_config = {
0044 .reg_bits = 8,
0045 .val_bits = 8,
0046 };
0047
0048 #define TPL0102_CHANNEL(ch) { \
0049 .type = IIO_RESISTANCE, \
0050 .indexed = 1, \
0051 .output = 1, \
0052 .channel = (ch), \
0053 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
0054 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
0055 .info_mask_separate_available = BIT(IIO_CHAN_INFO_RAW), \
0056 }
0057
0058 static const struct iio_chan_spec tpl0102_channels[] = {
0059 TPL0102_CHANNEL(0),
0060 TPL0102_CHANNEL(1),
0061 };
0062
0063 static int tpl0102_read_raw(struct iio_dev *indio_dev,
0064 struct iio_chan_spec const *chan,
0065 int *val, int *val2, long mask)
0066 {
0067 struct tpl0102_data *data = iio_priv(indio_dev);
0068
0069 switch (mask) {
0070 case IIO_CHAN_INFO_RAW: {
0071 int ret = regmap_read(data->regmap, chan->channel, val);
0072
0073 return ret ? ret : IIO_VAL_INT;
0074 }
0075 case IIO_CHAN_INFO_SCALE:
0076 *val = 1000 * data->cfg->kohms;
0077 *val2 = data->cfg->avail[2] + 1;
0078 return IIO_VAL_FRACTIONAL;
0079 }
0080
0081 return -EINVAL;
0082 }
0083
0084 static int tpl0102_read_avail(struct iio_dev *indio_dev,
0085 struct iio_chan_spec const *chan,
0086 const int **vals, int *type, int *length,
0087 long mask)
0088 {
0089 struct tpl0102_data *data = iio_priv(indio_dev);
0090
0091 switch (mask) {
0092 case IIO_CHAN_INFO_RAW:
0093 *length = ARRAY_SIZE(data->cfg->avail);
0094 *vals = data->cfg->avail;
0095 *type = IIO_VAL_INT;
0096 return IIO_AVAIL_RANGE;
0097 }
0098
0099 return -EINVAL;
0100 }
0101
0102 static int tpl0102_write_raw(struct iio_dev *indio_dev,
0103 struct iio_chan_spec const *chan,
0104 int val, int val2, long mask)
0105 {
0106 struct tpl0102_data *data = iio_priv(indio_dev);
0107
0108 if (mask != IIO_CHAN_INFO_RAW)
0109 return -EINVAL;
0110
0111 if (val > data->cfg->avail[2] || val < 0)
0112 return -EINVAL;
0113
0114 return regmap_write(data->regmap, chan->channel, val);
0115 }
0116
0117 static const struct iio_info tpl0102_info = {
0118 .read_raw = tpl0102_read_raw,
0119 .read_avail = tpl0102_read_avail,
0120 .write_raw = tpl0102_write_raw,
0121 };
0122
0123 static int tpl0102_probe(struct i2c_client *client,
0124 const struct i2c_device_id *id)
0125 {
0126 struct device *dev = &client->dev;
0127 struct tpl0102_data *data;
0128 struct iio_dev *indio_dev;
0129
0130 indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
0131 if (!indio_dev)
0132 return -ENOMEM;
0133 data = iio_priv(indio_dev);
0134 i2c_set_clientdata(client, indio_dev);
0135
0136 data->cfg = &tpl0102_cfg[id->driver_data];
0137 data->regmap = devm_regmap_init_i2c(client, &tpl0102_regmap_config);
0138 if (IS_ERR(data->regmap)) {
0139 dev_err(dev, "regmap initialization failed\n");
0140 return PTR_ERR(data->regmap);
0141 }
0142
0143 indio_dev->info = &tpl0102_info;
0144 indio_dev->channels = tpl0102_channels;
0145 indio_dev->num_channels = data->cfg->wipers;
0146 indio_dev->name = client->name;
0147
0148 return devm_iio_device_register(dev, indio_dev);
0149 }
0150
0151 static const struct i2c_device_id tpl0102_id[] = {
0152 { "cat5140-503", CAT5140_503 },
0153 { "cat5140-104", CAT5140_104 },
0154 { "tpl0102-104", TPL0102_104 },
0155 { "tpl0401-103", TPL0401_103 },
0156 {}
0157 };
0158 MODULE_DEVICE_TABLE(i2c, tpl0102_id);
0159
0160 static struct i2c_driver tpl0102_driver = {
0161 .driver = {
0162 .name = "tpl0102",
0163 },
0164 .probe = tpl0102_probe,
0165 .id_table = tpl0102_id,
0166 };
0167
0168 module_i2c_driver(tpl0102_driver);
0169
0170 MODULE_AUTHOR("Matt Ranostay <matt.ranostay@konsulko.com>");
0171 MODULE_DESCRIPTION("TPL0102 digital potentiometer");
0172 MODULE_LICENSE("GPL");