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, .max_pos
= 256, .kohms
= 50, },
32 [CAT5140_104
] = { .wipers
= 1, .max_pos
= 256, .kohms
= 100, },
34 [TPL0102_104
] = { .wipers
= 2, .max_pos
= 256, .kohms
= 100 },
35 [TPL0401_103
] = { .wipers
= 1, .max_pos
= 128, .kohms
= 10, },
39 struct regmap
*regmap
;
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), \
57 static const struct iio_chan_spec tpl0102_channels
[] = {
62 static int tpl0102_read_raw(struct iio_dev
*indio_dev
,
63 struct iio_chan_spec
const *chan
,
64 int *val
, int *val2
, long mask
)
66 struct tpl0102_data
*data
= iio_priv(indio_dev
);
69 case IIO_CHAN_INFO_RAW
: {
70 int ret
= regmap_read(data
->regmap
, chan
->channel
, val
);
72 return ret
? ret
: IIO_VAL_INT
;
74 case IIO_CHAN_INFO_SCALE
:
75 *val
= 1000 * tpl0102_cfg
[data
->devid
].kohms
;
76 *val2
= tpl0102_cfg
[data
->devid
].max_pos
;
77 return IIO_VAL_FRACTIONAL
;
83 static int tpl0102_write_raw(struct iio_dev
*indio_dev
,
84 struct iio_chan_spec
const *chan
,
85 int val
, int val2
, long mask
)
87 struct tpl0102_data
*data
= iio_priv(indio_dev
);
89 if (mask
!= IIO_CHAN_INFO_RAW
)
92 if (val
>= tpl0102_cfg
[data
->devid
].max_pos
|| val
< 0)
95 return regmap_write(data
->regmap
, chan
->channel
, val
);
98 static const struct iio_info tpl0102_info
= {
99 .read_raw
= tpl0102_read_raw
,
100 .write_raw
= tpl0102_write_raw
,
103 static int tpl0102_probe(struct i2c_client
*client
,
104 const struct i2c_device_id
*id
)
106 struct device
*dev
= &client
->dev
;
107 struct tpl0102_data
*data
;
108 struct iio_dev
*indio_dev
;
110 indio_dev
= devm_iio_device_alloc(dev
, sizeof(*data
));
113 data
= iio_priv(indio_dev
);
114 i2c_set_clientdata(client
, indio_dev
);
116 data
->devid
= id
->driver_data
;
117 data
->regmap
= devm_regmap_init_i2c(client
, &tpl0102_regmap_config
);
118 if (IS_ERR(data
->regmap
)) {
119 dev_err(dev
, "regmap initialization failed\n");
120 return PTR_ERR(data
->regmap
);
123 indio_dev
->dev
.parent
= dev
;
124 indio_dev
->info
= &tpl0102_info
;
125 indio_dev
->channels
= tpl0102_channels
;
126 indio_dev
->num_channels
= tpl0102_cfg
[data
->devid
].wipers
;
127 indio_dev
->name
= client
->name
;
129 return devm_iio_device_register(dev
, indio_dev
);
132 static const struct i2c_device_id tpl0102_id
[] = {
133 { "cat5140-503", CAT5140_503
},
134 { "cat5140-104", CAT5140_104
},
135 { "tpl0102-104", TPL0102_104
},
136 { "tpl0401-103", TPL0401_103
},
139 MODULE_DEVICE_TABLE(i2c
, tpl0102_id
);
141 static struct i2c_driver tpl0102_driver
= {
145 .probe
= tpl0102_probe
,
146 .id_table
= tpl0102_id
,
149 module_i2c_driver(tpl0102_driver
);
151 MODULE_AUTHOR("Matt Ranostay <matt.ranostay@konsulko.com>");
152 MODULE_DESCRIPTION("TPL0102 digital potentiometer");
153 MODULE_LICENSE("GPL");