1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * IIO driver for Maxim MAX34409/34408 ADC, 4-Channels/2-Channels, 8bits, I2C |
4 | * |
5 | * Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/MAX34408-MAX34409.pdf |
6 | * |
7 | * TODO: ALERT interrupt, Overcurrent delay, Shutdown delay |
8 | */ |
9 | |
10 | #include <linux/bitfield.h> |
11 | #include <linux/init.h> |
12 | #include <linux/i2c.h> |
13 | #include <linux/module.h> |
14 | #include <linux/mod_devicetable.h> |
15 | #include <linux/property.h> |
16 | #include <linux/regmap.h> |
17 | |
18 | #include <linux/iio/iio.h> |
19 | #include <linux/iio/types.h> |
20 | |
21 | #define MAX34408_STATUS_REG 0x0 |
22 | #define MAX34408_CONTROL_REG 0x1 |
23 | #define MAX34408_OCDELAY_REG 0x2 |
24 | #define MAX34408_SDDELAY_REG 0x3 |
25 | |
26 | #define MAX34408_ADC1_REG 0x4 |
27 | #define MAX34408_ADC2_REG 0x5 |
28 | /* ADC3 & ADC4 always returns 0x0 on 34408 */ |
29 | #define MAX34409_ADC3_REG 0x6 |
30 | #define MAX34409_ADC4_REG 0x7 |
31 | |
32 | #define MAX34408_OCT1_REG 0x8 |
33 | #define MAX34408_OCT2_REG 0x9 |
34 | #define MAX34409_OCT3_REG 0xA |
35 | #define MAX34409_OCT4_REG 0xB |
36 | |
37 | #define MAX34408_DID_REG 0xC |
38 | #define MAX34408_DCYY_REG 0xD |
39 | #define MAX34408_DCWW_REG 0xE |
40 | |
41 | /* Bit masks for status register */ |
42 | #define MAX34408_STATUS_OC_MSK GENMASK(1, 0) |
43 | #define MAX34409_STATUS_OC_MSK GENMASK(3, 0) |
44 | #define MAX34408_STATUS_SHTDN BIT(4) |
45 | #define MAX34408_STATUS_ENA BIT(5) |
46 | |
47 | /* Bit masks for control register */ |
48 | #define MAX34408_CONTROL_AVG0 BIT(0) |
49 | #define MAX34408_CONTROL_AVG1 BIT(1) |
50 | #define MAX34408_CONTROL_AVG2 BIT(2) |
51 | #define MAX34408_CONTROL_ALERT BIT(3) |
52 | |
53 | #define MAX34408_DEFAULT_AVG 0x4 |
54 | |
55 | /* Bit masks for over current delay */ |
56 | #define MAX34408_OCDELAY_OCD_MSK GENMASK(6, 0) |
57 | #define MAX34408_OCDELAY_RESET BIT(7) |
58 | |
59 | /* Bit masks for shutdown delay */ |
60 | #define MAX34408_SDDELAY_SHD_MSK GENMASK(6, 0) |
61 | #define MAX34408_SDDELAY_RESET BIT(7) |
62 | |
63 | #define MAX34408_DEFAULT_RSENSE 1000 |
64 | |
65 | /** |
66 | * struct max34408_data - max34408/max34409 specific data. |
67 | * @regmap: device register map. |
68 | * @dev: max34408 device. |
69 | * @lock: lock for protecting access to device hardware registers, mostly |
70 | * for read modify write cycles for control registers. |
71 | * @input_rsense: Rsense values in uOhm, will be overwritten by |
72 | * values from channel nodes. |
73 | */ |
74 | struct max34408_data { |
75 | struct regmap *regmap; |
76 | struct device *dev; |
77 | struct mutex lock; |
78 | u32 input_rsense[4]; |
79 | }; |
80 | |
81 | static const struct regmap_config max34408_regmap_config = { |
82 | .reg_bits = 8, |
83 | .val_bits = 8, |
84 | .max_register = MAX34408_DCWW_REG, |
85 | }; |
86 | |
87 | struct max34408_adc_model_data { |
88 | const char *model_name; |
89 | const struct iio_chan_spec *channels; |
90 | const int num_channels; |
91 | }; |
92 | |
93 | #define MAX34008_CHANNEL(_index, _address) \ |
94 | { \ |
95 | .type = IIO_CURRENT, \ |
96 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ |
97 | BIT(IIO_CHAN_INFO_SCALE) | \ |
98 | BIT(IIO_CHAN_INFO_OFFSET), \ |
99 | .channel = (_index), \ |
100 | .address = (_address), \ |
101 | .indexed = 1, \ |
102 | } |
103 | |
104 | static const struct iio_chan_spec max34408_channels[] = { |
105 | MAX34008_CHANNEL(0, MAX34408_ADC1_REG), |
106 | MAX34008_CHANNEL(1, MAX34408_ADC2_REG), |
107 | }; |
108 | |
109 | static const struct iio_chan_spec max34409_channels[] = { |
110 | MAX34008_CHANNEL(0, MAX34408_ADC1_REG), |
111 | MAX34008_CHANNEL(1, MAX34408_ADC2_REG), |
112 | MAX34008_CHANNEL(2, MAX34409_ADC3_REG), |
113 | MAX34008_CHANNEL(3, MAX34409_ADC4_REG), |
114 | }; |
115 | |
116 | static int max34408_read_adc_avg(struct max34408_data *max34408, |
117 | const struct iio_chan_spec *chan, int *val) |
118 | { |
119 | unsigned int ctrl; |
120 | int rc; |
121 | |
122 | guard(mutex)(T: &max34408->lock); |
123 | rc = regmap_read(map: max34408->regmap, MAX34408_CONTROL_REG, val: (u32 *)&ctrl); |
124 | if (rc) |
125 | return rc; |
126 | |
127 | /* set averaging (0b100) default values*/ |
128 | rc = regmap_write(map: max34408->regmap, MAX34408_CONTROL_REG, |
129 | MAX34408_DEFAULT_AVG); |
130 | if (rc) { |
131 | dev_err(max34408->dev, |
132 | "Error (%d) writing control register\n" , rc); |
133 | return rc; |
134 | } |
135 | |
136 | rc = regmap_read(map: max34408->regmap, reg: chan->address, val); |
137 | if (rc) |
138 | return rc; |
139 | |
140 | /* back to old values */ |
141 | rc = regmap_write(map: max34408->regmap, MAX34408_CONTROL_REG, val: ctrl); |
142 | if (rc) |
143 | dev_err(max34408->dev, |
144 | "Error (%d) writing control register\n" , rc); |
145 | |
146 | return rc; |
147 | } |
148 | |
149 | static int max34408_read_raw(struct iio_dev *indio_dev, |
150 | struct iio_chan_spec const *chan, |
151 | int *val, int *val2, long mask) |
152 | { |
153 | struct max34408_data *max34408 = iio_priv(indio_dev); |
154 | int rc; |
155 | |
156 | switch (mask) { |
157 | case IIO_CHAN_INFO_RAW: |
158 | rc = max34408_read_adc_avg(max34408, chan, val); |
159 | if (rc) |
160 | return rc; |
161 | return IIO_VAL_INT; |
162 | case IIO_CHAN_INFO_SCALE: |
163 | /* |
164 | * calcluate current for 8bit ADC with Rsense |
165 | * value. |
166 | * 10 mV * 1000 / Rsense uOhm = max current |
167 | * (max current * adc val * 1000) / (2^8 - 1) mA |
168 | */ |
169 | *val = 10000 / max34408->input_rsense[chan->channel]; |
170 | *val2 = 8; |
171 | return IIO_VAL_FRACTIONAL_LOG2; |
172 | default: |
173 | return -EINVAL; |
174 | } |
175 | } |
176 | |
177 | static const struct iio_info max34408_info = { |
178 | .read_raw = max34408_read_raw, |
179 | }; |
180 | |
181 | static const struct max34408_adc_model_data max34408_model_data = { |
182 | .model_name = "max34408" , |
183 | .channels = max34408_channels, |
184 | .num_channels = 2, |
185 | }; |
186 | |
187 | static const struct max34408_adc_model_data max34409_model_data = { |
188 | .model_name = "max34409" , |
189 | .channels = max34409_channels, |
190 | .num_channels = 4, |
191 | }; |
192 | |
193 | static int max34408_probe(struct i2c_client *client) |
194 | { |
195 | const struct max34408_adc_model_data *model_data; |
196 | struct device *dev = &client->dev; |
197 | struct max34408_data *max34408; |
198 | struct fwnode_handle *node; |
199 | struct iio_dev *indio_dev; |
200 | struct regmap *regmap; |
201 | int rc, i = 0; |
202 | |
203 | model_data = i2c_get_match_data(client); |
204 | if (!model_data) |
205 | return -EINVAL; |
206 | |
207 | regmap = devm_regmap_init_i2c(client, &max34408_regmap_config); |
208 | if (IS_ERR(ptr: regmap)) { |
209 | dev_err_probe(dev, err: PTR_ERR(ptr: regmap), |
210 | fmt: "regmap_init failed\n" ); |
211 | return PTR_ERR(ptr: regmap); |
212 | } |
213 | |
214 | indio_dev = devm_iio_device_alloc(parent: dev, sizeof_priv: sizeof(*max34408)); |
215 | if (!indio_dev) |
216 | return -ENOMEM; |
217 | |
218 | max34408 = iio_priv(indio_dev); |
219 | max34408->regmap = regmap; |
220 | max34408->dev = dev; |
221 | mutex_init(&max34408->lock); |
222 | |
223 | device_for_each_child_node(dev, node) { |
224 | fwnode_property_read_u32(fwnode: node, propname: "maxim,rsense-val-micro-ohms" , |
225 | val: &max34408->input_rsense[i]); |
226 | i++; |
227 | } |
228 | |
229 | /* disable ALERT and averaging */ |
230 | rc = regmap_write(map: max34408->regmap, MAX34408_CONTROL_REG, val: 0x0); |
231 | if (rc) |
232 | return rc; |
233 | |
234 | indio_dev->channels = model_data->channels; |
235 | indio_dev->num_channels = model_data->num_channels; |
236 | indio_dev->name = model_data->model_name; |
237 | |
238 | indio_dev->info = &max34408_info; |
239 | indio_dev->modes = INDIO_DIRECT_MODE; |
240 | |
241 | return devm_iio_device_register(dev, indio_dev); |
242 | } |
243 | |
244 | static const struct of_device_id max34408_of_match[] = { |
245 | { |
246 | .compatible = "maxim,max34408" , |
247 | .data = &max34408_model_data, |
248 | }, |
249 | { |
250 | .compatible = "maxim,max34409" , |
251 | .data = &max34409_model_data, |
252 | }, |
253 | {} |
254 | }; |
255 | MODULE_DEVICE_TABLE(of, max34408_of_match); |
256 | |
257 | static const struct i2c_device_id max34408_id[] = { |
258 | { "max34408" , (kernel_ulong_t)&max34408_model_data }, |
259 | { "max34409" , (kernel_ulong_t)&max34409_model_data }, |
260 | {} |
261 | }; |
262 | MODULE_DEVICE_TABLE(i2c, max34408_id); |
263 | |
264 | static struct i2c_driver max34408_driver = { |
265 | .driver = { |
266 | .name = "max34408" , |
267 | .of_match_table = max34408_of_match, |
268 | }, |
269 | .probe = max34408_probe, |
270 | .id_table = max34408_id, |
271 | }; |
272 | module_i2c_driver(max34408_driver); |
273 | |
274 | MODULE_AUTHOR("Ivan Mikhaylov <fr0st61te@gmail.com>" ); |
275 | MODULE_DESCRIPTION("Maxim MAX34408/34409 ADC driver" ); |
276 | MODULE_LICENSE("GPL" ); |
277 | |