1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * ltc2497-core.c - Common code for Analog Devices/Linear Technology |
4 | * LTC2496 and LTC2497 ADCs |
5 | * |
6 | * Copyright (C) 2017 Analog Devices Inc. |
7 | */ |
8 | |
9 | #include <linux/delay.h> |
10 | #include <linux/iio/iio.h> |
11 | #include <linux/iio/driver.h> |
12 | #include <linux/module.h> |
13 | #include <linux/mutex.h> |
14 | #include <linux/regulator/consumer.h> |
15 | |
16 | #include "ltc2497.h" |
17 | |
18 | #define LTC2497_SGL BIT(4) |
19 | #define LTC2497_DIFF 0 |
20 | #define LTC2497_SIGN BIT(3) |
21 | |
22 | static int ltc2497core_wait_conv(struct ltc2497core_driverdata *ddata) |
23 | { |
24 | s64 time_elapsed; |
25 | |
26 | time_elapsed = ktime_ms_delta(later: ktime_get(), earlier: ddata->time_prev); |
27 | |
28 | if (time_elapsed < LTC2497_CONVERSION_TIME_MS) { |
29 | /* delay if conversion time not passed |
30 | * since last read or write |
31 | */ |
32 | if (msleep_interruptible( |
33 | LTC2497_CONVERSION_TIME_MS - time_elapsed)) |
34 | return -ERESTARTSYS; |
35 | |
36 | return 0; |
37 | } |
38 | |
39 | if (time_elapsed - LTC2497_CONVERSION_TIME_MS <= 0) { |
40 | /* We're in automatic mode - |
41 | * so the last reading is still not outdated |
42 | */ |
43 | return 0; |
44 | } |
45 | |
46 | return 1; |
47 | } |
48 | |
49 | static int ltc2497core_read(struct ltc2497core_driverdata *ddata, u8 address, int *val) |
50 | { |
51 | int ret; |
52 | |
53 | ret = ltc2497core_wait_conv(ddata); |
54 | if (ret < 0) |
55 | return ret; |
56 | |
57 | if (ret || ddata->addr_prev != address) { |
58 | ret = ddata->result_and_measure(ddata, address, NULL); |
59 | if (ret < 0) |
60 | return ret; |
61 | ddata->addr_prev = address; |
62 | |
63 | if (msleep_interruptible(LTC2497_CONVERSION_TIME_MS)) |
64 | return -ERESTARTSYS; |
65 | } |
66 | |
67 | ret = ddata->result_and_measure(ddata, address, val); |
68 | if (ret < 0) |
69 | return ret; |
70 | |
71 | ddata->time_prev = ktime_get(); |
72 | |
73 | return ret; |
74 | } |
75 | |
76 | static int ltc2497core_read_raw(struct iio_dev *indio_dev, |
77 | struct iio_chan_spec const *chan, |
78 | int *val, int *val2, long mask) |
79 | { |
80 | struct ltc2497core_driverdata *ddata = iio_priv(indio_dev); |
81 | int ret; |
82 | |
83 | switch (mask) { |
84 | case IIO_CHAN_INFO_RAW: |
85 | mutex_lock(&ddata->lock); |
86 | ret = ltc2497core_read(ddata, address: chan->address, val); |
87 | mutex_unlock(lock: &ddata->lock); |
88 | if (ret < 0) |
89 | return ret; |
90 | |
91 | return IIO_VAL_INT; |
92 | |
93 | case IIO_CHAN_INFO_SCALE: |
94 | ret = regulator_get_voltage(regulator: ddata->ref); |
95 | if (ret < 0) |
96 | return ret; |
97 | |
98 | *val = ret / 1000; |
99 | *val2 = ddata->chip_info->resolution + 1; |
100 | |
101 | return IIO_VAL_FRACTIONAL_LOG2; |
102 | |
103 | default: |
104 | return -EINVAL; |
105 | } |
106 | } |
107 | |
108 | #define LTC2497_CHAN(_chan, _addr, _ds_name) { \ |
109 | .type = IIO_VOLTAGE, \ |
110 | .indexed = 1, \ |
111 | .channel = (_chan), \ |
112 | .address = (_addr | (_chan / 2) | ((_chan & 1) ? LTC2497_SIGN : 0)), \ |
113 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ |
114 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ |
115 | .datasheet_name = (_ds_name), \ |
116 | } |
117 | |
118 | #define LTC2497_CHAN_DIFF(_chan, _addr) { \ |
119 | .type = IIO_VOLTAGE, \ |
120 | .indexed = 1, \ |
121 | .channel = (_chan) * 2 + ((_addr) & LTC2497_SIGN ? 1 : 0), \ |
122 | .channel2 = (_chan) * 2 + ((_addr) & LTC2497_SIGN ? 0 : 1),\ |
123 | .address = (_addr | _chan), \ |
124 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ |
125 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ |
126 | .differential = 1, \ |
127 | } |
128 | |
129 | static const struct iio_chan_spec ltc2497core_channel[] = { |
130 | LTC2497_CHAN(0, LTC2497_SGL, "CH0" ), |
131 | LTC2497_CHAN(1, LTC2497_SGL, "CH1" ), |
132 | LTC2497_CHAN(2, LTC2497_SGL, "CH2" ), |
133 | LTC2497_CHAN(3, LTC2497_SGL, "CH3" ), |
134 | LTC2497_CHAN(4, LTC2497_SGL, "CH4" ), |
135 | LTC2497_CHAN(5, LTC2497_SGL, "CH5" ), |
136 | LTC2497_CHAN(6, LTC2497_SGL, "CH6" ), |
137 | LTC2497_CHAN(7, LTC2497_SGL, "CH7" ), |
138 | LTC2497_CHAN(8, LTC2497_SGL, "CH8" ), |
139 | LTC2497_CHAN(9, LTC2497_SGL, "CH9" ), |
140 | LTC2497_CHAN(10, LTC2497_SGL, "CH10" ), |
141 | LTC2497_CHAN(11, LTC2497_SGL, "CH11" ), |
142 | LTC2497_CHAN(12, LTC2497_SGL, "CH12" ), |
143 | LTC2497_CHAN(13, LTC2497_SGL, "CH13" ), |
144 | LTC2497_CHAN(14, LTC2497_SGL, "CH14" ), |
145 | LTC2497_CHAN(15, LTC2497_SGL, "CH15" ), |
146 | LTC2497_CHAN_DIFF(0, LTC2497_DIFF), |
147 | LTC2497_CHAN_DIFF(1, LTC2497_DIFF), |
148 | LTC2497_CHAN_DIFF(2, LTC2497_DIFF), |
149 | LTC2497_CHAN_DIFF(3, LTC2497_DIFF), |
150 | LTC2497_CHAN_DIFF(4, LTC2497_DIFF), |
151 | LTC2497_CHAN_DIFF(5, LTC2497_DIFF), |
152 | LTC2497_CHAN_DIFF(6, LTC2497_DIFF), |
153 | LTC2497_CHAN_DIFF(7, LTC2497_DIFF), |
154 | LTC2497_CHAN_DIFF(0, LTC2497_DIFF | LTC2497_SIGN), |
155 | LTC2497_CHAN_DIFF(1, LTC2497_DIFF | LTC2497_SIGN), |
156 | LTC2497_CHAN_DIFF(2, LTC2497_DIFF | LTC2497_SIGN), |
157 | LTC2497_CHAN_DIFF(3, LTC2497_DIFF | LTC2497_SIGN), |
158 | LTC2497_CHAN_DIFF(4, LTC2497_DIFF | LTC2497_SIGN), |
159 | LTC2497_CHAN_DIFF(5, LTC2497_DIFF | LTC2497_SIGN), |
160 | LTC2497_CHAN_DIFF(6, LTC2497_DIFF | LTC2497_SIGN), |
161 | LTC2497_CHAN_DIFF(7, LTC2497_DIFF | LTC2497_SIGN), |
162 | }; |
163 | |
164 | static const struct iio_info ltc2497core_info = { |
165 | .read_raw = ltc2497core_read_raw, |
166 | }; |
167 | |
168 | int ltc2497core_probe(struct device *dev, struct iio_dev *indio_dev) |
169 | { |
170 | struct ltc2497core_driverdata *ddata = iio_priv(indio_dev); |
171 | int ret; |
172 | |
173 | /* |
174 | * Keep using dev_name() for the iio_dev's name on some of the parts, |
175 | * since updating it would result in a ABI breakage. |
176 | */ |
177 | if (ddata->chip_info->name) |
178 | indio_dev->name = ddata->chip_info->name; |
179 | else |
180 | indio_dev->name = dev_name(dev); |
181 | |
182 | indio_dev->info = <c2497core_info; |
183 | indio_dev->modes = INDIO_DIRECT_MODE; |
184 | indio_dev->channels = ltc2497core_channel; |
185 | indio_dev->num_channels = ARRAY_SIZE(ltc2497core_channel); |
186 | |
187 | ret = ddata->result_and_measure(ddata, LTC2497_CONFIG_DEFAULT, NULL); |
188 | if (ret < 0) |
189 | return ret; |
190 | |
191 | ddata->ref = devm_regulator_get(dev, id: "vref" ); |
192 | if (IS_ERR(ptr: ddata->ref)) |
193 | return dev_err_probe(dev, err: PTR_ERR(ptr: ddata->ref), |
194 | fmt: "Failed to get vref regulator\n" ); |
195 | |
196 | ret = regulator_enable(regulator: ddata->ref); |
197 | if (ret < 0) { |
198 | dev_err(dev, "Failed to enable vref regulator: %pe\n" , |
199 | ERR_PTR(ret)); |
200 | return ret; |
201 | } |
202 | |
203 | if (dev->platform_data) { |
204 | struct iio_map *plat_data; |
205 | |
206 | plat_data = (struct iio_map *)dev->platform_data; |
207 | |
208 | ret = iio_map_array_register(indio_dev, map: plat_data); |
209 | if (ret) { |
210 | dev_err(&indio_dev->dev, "iio map err: %d\n" , ret); |
211 | goto err_regulator_disable; |
212 | } |
213 | } |
214 | |
215 | ddata->addr_prev = LTC2497_CONFIG_DEFAULT; |
216 | ddata->time_prev = ktime_get(); |
217 | |
218 | mutex_init(&ddata->lock); |
219 | |
220 | ret = iio_device_register(indio_dev); |
221 | if (ret < 0) |
222 | goto err_array_unregister; |
223 | |
224 | return 0; |
225 | |
226 | err_array_unregister: |
227 | iio_map_array_unregister(indio_dev); |
228 | |
229 | err_regulator_disable: |
230 | regulator_disable(regulator: ddata->ref); |
231 | |
232 | return ret; |
233 | } |
234 | EXPORT_SYMBOL_NS(ltc2497core_probe, LTC2497); |
235 | |
236 | void ltc2497core_remove(struct iio_dev *indio_dev) |
237 | { |
238 | struct ltc2497core_driverdata *ddata = iio_priv(indio_dev); |
239 | |
240 | iio_device_unregister(indio_dev); |
241 | |
242 | iio_map_array_unregister(indio_dev); |
243 | |
244 | regulator_disable(regulator: ddata->ref); |
245 | } |
246 | EXPORT_SYMBOL_NS(ltc2497core_remove, LTC2497); |
247 | |
248 | MODULE_DESCRIPTION("common code for LTC2496/LTC2497 drivers" ); |
249 | MODULE_LICENSE("GPL v2" ); |
250 | |