1 // SPDX-License-Identifier: GPL-2.0+
3 * tpl0102.c - Support for Texas Instruments digital potentiometers
5 * Copyright (C) 2016, 2018
6 * Author: Matt Ranostay <matt.ranostay@konsulko.com>
8 * TODO: enable/disable hi-z output control
11 #include <linux/module.h>
12 #include <linux/i2c.h>
13 #include <linux/regmap.h>
14 #include <linux/iio/iio.h>
29 static const struct tpl0102_cfg tpl0102_cfg
[] = {
30 /* on-semiconductor parts */
31 [CAT5140_503
] = { .wipers
= 1, .avail
= { 0, 1, 255 }, .kohms
= 50, },
32 [CAT5140_104
] = { .wipers
= 1, .avail
= { 0, 1, 255 }, .kohms
= 100, },
34 [TPL0102_104
] = { .wipers
= 2, .avail
= { 0, 1, 255 }, .kohms
= 100 },
35 [TPL0401_103
] = { .wipers
= 1, .avail
= { 0, 1, 127 }, .kohms
= 10, },
39 struct regmap
*regmap
;
40 const struct tpl0102_cfg
*cfg
;
43 static const struct regmap_config tpl0102_regmap_config
= {
48 #define TPL0102_CHANNEL(ch) { \
49 .type = IIO_RESISTANCE, \
53 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
54 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
55 .info_mask_separate_available = BIT(IIO_CHAN_INFO_RAW), \
58 static const struct iio_chan_spec tpl0102_channels
[] = {
63 static int tpl0102_read_raw(struct iio_dev
*indio_dev
,
64 struct iio_chan_spec
const *chan
,
65 int *val
, int *val2
, long mask
)
67 struct tpl0102_data
*data
= iio_priv(indio_dev
);
70 case IIO_CHAN_INFO_RAW
: {
71 int ret
= regmap_read(data
->regmap
, chan
->channel
, val
);
73 return ret
? ret
: IIO_VAL_INT
;
75 case IIO_CHAN_INFO_SCALE
:
76 *val
= 1000 * data
->cfg
->kohms
;
77 *val2
= data
->cfg
->avail
[2] + 1;
78 return IIO_VAL_FRACTIONAL
;
84 static int tpl0102_read_avail(struct iio_dev
*indio_dev
,
85 struct iio_chan_spec
const *chan
,
86 const int **vals
, int *type
, int *length
,
89 struct tpl0102_data
*data
= iio_priv(indio_dev
);
92 case IIO_CHAN_INFO_RAW
:
93 *length
= ARRAY_SIZE(data
->cfg
->avail
);
94 *vals
= data
->cfg
->avail
;
96 return IIO_AVAIL_RANGE
;
102 static int tpl0102_write_raw(struct iio_dev
*indio_dev
,
103 struct iio_chan_spec
const *chan
,
104 int val
, int val2
, long mask
)
106 struct tpl0102_data
*data
= iio_priv(indio_dev
);
108 if (mask
!= IIO_CHAN_INFO_RAW
)
111 if (val
> data
->cfg
->avail
[2] || val
< 0)
114 return regmap_write(data
->regmap
, chan
->channel
, val
);
117 static const struct iio_info tpl0102_info
= {
118 .read_raw
= tpl0102_read_raw
,
119 .read_avail
= tpl0102_read_avail
,
120 .write_raw
= tpl0102_write_raw
,
123 static int tpl0102_probe(struct i2c_client
*client
,
124 const struct i2c_device_id
*id
)
126 struct device
*dev
= &client
->dev
;
127 struct tpl0102_data
*data
;
128 struct iio_dev
*indio_dev
;
130 indio_dev
= devm_iio_device_alloc(dev
, sizeof(*data
));
133 data
= iio_priv(indio_dev
);
134 i2c_set_clientdata(client
, indio_dev
);
136 data
->cfg
= &tpl0102_cfg
[id
->driver_data
];
137 data
->regmap
= devm_regmap_init_i2c(client
, &tpl0102_regmap_config
);
138 if (IS_ERR(data
->regmap
)) {
139 dev_err(dev
, "regmap initialization failed\n");
140 return PTR_ERR(data
->regmap
);
143 indio_dev
->info
= &tpl0102_info
;
144 indio_dev
->channels
= tpl0102_channels
;
145 indio_dev
->num_channels
= data
->cfg
->wipers
;
146 indio_dev
->name
= client
->name
;
148 return devm_iio_device_register(dev
, indio_dev
);
151 static const struct i2c_device_id tpl0102_id
[] = {
152 { "cat5140-503", CAT5140_503
},
153 { "cat5140-104", CAT5140_104
},
154 { "tpl0102-104", TPL0102_104
},
155 { "tpl0401-103", TPL0401_103
},
158 MODULE_DEVICE_TABLE(i2c
, tpl0102_id
);
160 static struct i2c_driver tpl0102_driver
= {
164 .probe
= tpl0102_probe
,
165 .id_table
= tpl0102_id
,
168 module_i2c_driver(tpl0102_driver
);
170 MODULE_AUTHOR("Matt Ranostay <matt.ranostay@konsulko.com>");
171 MODULE_DESCRIPTION("TPL0102 digital potentiometer");
172 MODULE_LICENSE("GPL");