xref: /linux/drivers/iio/adc/ltc2309.c (revision f68afce8e8a74f52a879f56f607dfedf552b5ab5)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * The LTC2305 is a  2-Channel, 12-Bit SAR ADC with an I2C Interface.
4  * The LTC2309 is an 8-Channel, 12-Bit SAR ADC with an I2C Interface.
5  *
6  * Datasheet:
7  * https://www.analog.com/media/en/technical-documentation/data-sheets/23015fb.pdf
8  * https://www.analog.com/media/en/technical-documentation/data-sheets/2309fd.pdf
9  *
10  * Copyright (c) 2023, Liam Beguin <liambeguin@gmail.com>
11  */
12 #include <linux/array_size.h>
13 #include <linux/bitfield.h>
14 #include <linux/delay.h>
15 #include <linux/i2c.h>
16 #include <linux/iio/iio.h>
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/mutex.h>
20 #include <linux/regulator/consumer.h>
21 
22 #define LTC2309_ADC_RESOLUTION	12
23 #define LTC2309_INTERNAL_REF_MV 4096
24 
25 #define LTC2309_DIN_CH_MASK	GENMASK(7, 4)
26 #define LTC2309_DIN_SDN		BIT(7)
27 #define LTC2309_DIN_OSN		BIT(6)
28 #define LTC2309_DIN_S1		BIT(5)
29 #define LTC2309_DIN_S0		BIT(4)
30 #define LTC2309_DIN_UNI		BIT(3)
31 #define LTC2309_DIN_SLEEP	BIT(2)
32 
33 /**
34  * struct ltc2309 - internal device data structure
35  * @dev:	Device reference
36  * @client:	I2C reference
37  * @lock:	Lock to serialize data access
38  * @vref_mv:	Internal voltage reference
39  * @read_delay_us:	Chip-specific read delay in microseconds
40  */
41 struct ltc2309 {
42 	struct device		*dev;
43 	struct i2c_client	*client;
44 	struct mutex		lock; /* serialize data access */
45 	int			vref_mv;
46 	unsigned int		read_delay_us;
47 };
48 
49 /* Order matches expected channel address, See datasheet Table 1. */
50 enum ltc2305_channels {
51 	LTC2305_CH0_CH1 = 0x0,
52 	LTC2305_CH1_CH0 = 0x4,
53 	LTC2305_CH0     = 0x8,
54 	LTC2305_CH1     = 0xc,
55 };
56 
57 enum ltc2309_channels {
58 	LTC2309_CH0_CH1 = 0x0,
59 	LTC2309_CH2_CH3 = 0x1,
60 	LTC2309_CH4_CH5 = 0x2,
61 	LTC2309_CH6_CH7 = 0x3,
62 	LTC2309_CH1_CH0 = 0x4,
63 	LTC2309_CH3_CH2 = 0x5,
64 	LTC2309_CH5_CH4 = 0x6,
65 	LTC2309_CH7_CH6 = 0x7,
66 	LTC2309_CH0     = 0x8,
67 	LTC2309_CH2     = 0x9,
68 	LTC2309_CH4     = 0xa,
69 	LTC2309_CH6     = 0xb,
70 	LTC2309_CH1     = 0xc,
71 	LTC2309_CH3     = 0xd,
72 	LTC2309_CH5     = 0xe,
73 	LTC2309_CH7     = 0xf,
74 };
75 
76 #define LTC2309_CHAN(_chan, _addr) {				\
77 	.type = IIO_VOLTAGE,					\
78 	.indexed = 1,						\
79 	.address = _addr,					\
80 	.channel = _chan,					\
81 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
82 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
83 }
84 
85 #define LTC2309_DIFF_CHAN(_chan, _chan2, _addr) {		\
86 	.type = IIO_VOLTAGE,					\
87 	.differential = 1,					\
88 	.indexed = 1,						\
89 	.address = _addr,					\
90 	.channel = _chan,					\
91 	.channel2 = _chan2,					\
92 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
93 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
94 }
95 
96 static const struct iio_chan_spec ltc2305_channels[] = {
97 	LTC2309_CHAN(0, LTC2305_CH0),
98 	LTC2309_CHAN(1, LTC2305_CH1),
99 	LTC2309_DIFF_CHAN(0, 1, LTC2305_CH0_CH1),
100 	LTC2309_DIFF_CHAN(1, 0, LTC2305_CH1_CH0),
101 };
102 
103 static const struct iio_chan_spec ltc2309_channels[] = {
104 	LTC2309_CHAN(0, LTC2309_CH0),
105 	LTC2309_CHAN(1, LTC2309_CH1),
106 	LTC2309_CHAN(2, LTC2309_CH2),
107 	LTC2309_CHAN(3, LTC2309_CH3),
108 	LTC2309_CHAN(4, LTC2309_CH4),
109 	LTC2309_CHAN(5, LTC2309_CH5),
110 	LTC2309_CHAN(6, LTC2309_CH6),
111 	LTC2309_CHAN(7, LTC2309_CH7),
112 	LTC2309_DIFF_CHAN(0, 1, LTC2309_CH0_CH1),
113 	LTC2309_DIFF_CHAN(2, 3, LTC2309_CH2_CH3),
114 	LTC2309_DIFF_CHAN(4, 5, LTC2309_CH4_CH5),
115 	LTC2309_DIFF_CHAN(6, 7, LTC2309_CH6_CH7),
116 	LTC2309_DIFF_CHAN(1, 0, LTC2309_CH1_CH0),
117 	LTC2309_DIFF_CHAN(3, 2, LTC2309_CH3_CH2),
118 	LTC2309_DIFF_CHAN(5, 4, LTC2309_CH5_CH4),
119 	LTC2309_DIFF_CHAN(7, 6, LTC2309_CH7_CH6),
120 };
121 
122 struct ltc2309_chip_info {
123 	const char *name;
124 	unsigned int read_delay_us;
125 	int num_channels;
126 	const struct iio_chan_spec *channels __counted_by_ptr(num_channels);
127 };
128 
129 static const struct ltc2309_chip_info ltc2305_chip_info = {
130 	.name = "ltc2305",
131 	.read_delay_us = 2,
132 	.num_channels = ARRAY_SIZE(ltc2305_channels),
133 	.channels = ltc2305_channels,
134 };
135 
136 static const struct ltc2309_chip_info ltc2309_chip_info = {
137 	.name = "ltc2309",
138 	.num_channels = ARRAY_SIZE(ltc2309_channels),
139 	.channels = ltc2309_channels,
140 };
141 
142 static int ltc2309_read_raw_channel(struct ltc2309 *ltc2309,
143 				    unsigned long address, int *val)
144 {
145 	int ret;
146 	__be16 buf;
147 	u8 din;
148 
149 	din = FIELD_PREP(LTC2309_DIN_CH_MASK, address & 0x0f) |
150 		FIELD_PREP(LTC2309_DIN_UNI, 1) |
151 		FIELD_PREP(LTC2309_DIN_SLEEP, 0);
152 
153 	ret = i2c_smbus_write_byte(ltc2309->client, din);
154 	if (ret < 0) {
155 		dev_err(ltc2309->dev, "i2c command failed: %pe\n",
156 			ERR_PTR(ret));
157 		return ret;
158 	}
159 
160 	if (ltc2309->read_delay_us)
161 		fsleep(ltc2309->read_delay_us);
162 
163 	ret = i2c_master_recv(ltc2309->client, (char *)&buf, 2);
164 	if (ret < 0) {
165 		dev_err(ltc2309->dev, "i2c read failed: %pe\n", ERR_PTR(ret));
166 		return ret;
167 	}
168 
169 	*val = be16_to_cpu(buf) >> 4;
170 
171 	return ret;
172 }
173 
174 static int ltc2309_read_raw(struct iio_dev *indio_dev,
175 			    struct iio_chan_spec const *chan, int *val,
176 			    int *val2, long mask)
177 {
178 	struct ltc2309 *ltc2309 = iio_priv(indio_dev);
179 	int ret;
180 
181 	switch (mask) {
182 	case IIO_CHAN_INFO_RAW:
183 		mutex_lock(&ltc2309->lock);
184 		ret = ltc2309_read_raw_channel(ltc2309, chan->address, val);
185 		mutex_unlock(&ltc2309->lock);
186 		if (ret < 0)
187 			return -EINVAL;
188 		return IIO_VAL_INT;
189 	case IIO_CHAN_INFO_SCALE:
190 		*val = ltc2309->vref_mv;
191 		*val2 = LTC2309_ADC_RESOLUTION;
192 		return IIO_VAL_FRACTIONAL_LOG2;
193 	default:
194 		return -EINVAL;
195 	}
196 }
197 
198 static const struct iio_info ltc2309_info = {
199 	.read_raw = ltc2309_read_raw,
200 };
201 
202 static int ltc2309_probe(struct i2c_client *client)
203 {
204 	const struct ltc2309_chip_info *chip_info;
205 	struct iio_dev *indio_dev;
206 	struct ltc2309 *ltc2309;
207 	int ret;
208 
209 	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*ltc2309));
210 	if (!indio_dev)
211 		return -ENOMEM;
212 
213 	ltc2309 = iio_priv(indio_dev);
214 	chip_info = i2c_get_match_data(client);
215 
216 	ltc2309->dev = &indio_dev->dev;
217 	ltc2309->client = client;
218 	ltc2309->read_delay_us = chip_info->read_delay_us;
219 
220 	indio_dev->name = chip_info->name;
221 	indio_dev->modes = INDIO_DIRECT_MODE;
222 	indio_dev->channels = chip_info->channels;
223 	indio_dev->num_channels = chip_info->num_channels;
224 	indio_dev->info = &ltc2309_info;
225 
226 	ret = devm_regulator_get_enable_read_voltage(&client->dev, "vref");
227 	if (ret < 0 && ret != -ENODEV)
228 		return dev_err_probe(ltc2309->dev, ret,
229 				     "failed to get vref voltage\n");
230 
231 	ltc2309->vref_mv = ret == -ENODEV ? LTC2309_INTERNAL_REF_MV : ret / 1000;
232 
233 	mutex_init(&ltc2309->lock);
234 
235 	return devm_iio_device_register(&client->dev, indio_dev);
236 }
237 
238 static const struct of_device_id ltc2309_of_match[] = {
239 	{ .compatible = "lltc,ltc2305", .data = &ltc2305_chip_info },
240 	{ .compatible = "lltc,ltc2309", .data = &ltc2309_chip_info },
241 	{ }
242 };
243 MODULE_DEVICE_TABLE(of, ltc2309_of_match);
244 
245 static const struct i2c_device_id ltc2309_id[] = {
246 	{ .name = "ltc2305", .driver_data = (kernel_ulong_t)&ltc2305_chip_info },
247 	{ .name = "ltc2309", .driver_data = (kernel_ulong_t)&ltc2309_chip_info },
248 	{ }
249 };
250 MODULE_DEVICE_TABLE(i2c, ltc2309_id);
251 
252 static struct i2c_driver ltc2309_driver = {
253 	.driver = {
254 		.name = "ltc2309",
255 		.of_match_table = ltc2309_of_match,
256 	},
257 	.probe		= ltc2309_probe,
258 	.id_table	= ltc2309_id,
259 };
260 module_i2c_driver(ltc2309_driver);
261 
262 MODULE_AUTHOR("Liam Beguin <liambeguin@gmail.com>");
263 MODULE_DESCRIPTION("Linear Technology LTC2309 ADC");
264 MODULE_LICENSE("GPL v2");
265