Commit | Line | Data |
---|---|---|
b0bd407e AT |
1 | // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) |
2 | /* | |
3 | * LTC2992 - Dual Wide Range Power Monitor | |
4 | * | |
5 | * Copyright 2020 Analog Devices Inc. | |
6 | */ | |
7 | ||
8 | #include <linux/bitfield.h> | |
9 | #include <linux/bitops.h> | |
10 | #include <linux/err.h> | |
9ca26df1 | 11 | #include <linux/gpio/driver.h> |
b0bd407e AT |
12 | #include <linux/hwmon.h> |
13 | #include <linux/i2c.h> | |
14 | #include <linux/kernel.h> | |
15 | #include <linux/module.h> | |
16 | #include <linux/property.h> | |
17 | #include <linux/regmap.h> | |
18 | ||
19 | #define LTC2992_CTRLB 0x01 | |
20 | #define LTC2992_FAULT1 0x03 | |
21 | #define LTC2992_POWER1 0x05 | |
22 | #define LTC2992_POWER1_MAX 0x08 | |
23 | #define LTC2992_POWER1_MIN 0x0B | |
24 | #define LTC2992_POWER1_MAX_THRESH 0x0E | |
25 | #define LTC2992_POWER1_MIN_THRESH 0x11 | |
26 | #define LTC2992_DSENSE1 0x14 | |
27 | #define LTC2992_DSENSE1_MAX 0x16 | |
28 | #define LTC2992_DSENSE1_MIN 0x18 | |
29 | #define LTC2992_DSENSE1_MAX_THRESH 0x1A | |
30 | #define LTC2992_DSENSE1_MIN_THRESH 0x1C | |
31 | #define LTC2992_SENSE1 0x1E | |
32 | #define LTC2992_SENSE1_MAX 0x20 | |
33 | #define LTC2992_SENSE1_MIN 0x22 | |
34 | #define LTC2992_SENSE1_MAX_THRESH 0x24 | |
35 | #define LTC2992_SENSE1_MIN_THRESH 0x26 | |
36 | #define LTC2992_G1 0x28 | |
37 | #define LTC2992_G1_MAX 0x2A | |
38 | #define LTC2992_G1_MIN 0x2C | |
39 | #define LTC2992_G1_MAX_THRESH 0x2E | |
40 | #define LTC2992_G1_MIN_THRESH 0x30 | |
41 | #define LTC2992_FAULT2 0x35 | |
42 | #define LTC2992_G2 0x5A | |
43 | #define LTC2992_G2_MAX 0x5C | |
44 | #define LTC2992_G2_MIN 0x5E | |
45 | #define LTC2992_G2_MAX_THRESH 0x60 | |
46 | #define LTC2992_G2_MIN_THRESH 0x62 | |
47 | #define LTC2992_G3 0x64 | |
48 | #define LTC2992_G3_MAX 0x66 | |
49 | #define LTC2992_G3_MIN 0x68 | |
50 | #define LTC2992_G3_MAX_THRESH 0x6A | |
51 | #define LTC2992_G3_MIN_THRESH 0x6C | |
52 | #define LTC2992_G4 0x6E | |
53 | #define LTC2992_G4_MAX 0x70 | |
54 | #define LTC2992_G4_MIN 0x72 | |
55 | #define LTC2992_G4_MAX_THRESH 0x74 | |
56 | #define LTC2992_G4_MIN_THRESH 0x76 | |
57 | #define LTC2992_FAULT3 0x92 | |
9ca26df1 AT |
58 | #define LTC2992_GPIO_STATUS 0x95 |
59 | #define LTC2992_GPIO_IO_CTRL 0x96 | |
60 | #define LTC2992_GPIO_CTRL 0x97 | |
b0bd407e AT |
61 | |
62 | #define LTC2992_POWER(x) (LTC2992_POWER1 + ((x) * 0x32)) | |
63 | #define LTC2992_POWER_MAX(x) (LTC2992_POWER1_MAX + ((x) * 0x32)) | |
64 | #define LTC2992_POWER_MIN(x) (LTC2992_POWER1_MIN + ((x) * 0x32)) | |
65 | #define LTC2992_POWER_MAX_THRESH(x) (LTC2992_POWER1_MAX_THRESH + ((x) * 0x32)) | |
66 | #define LTC2992_POWER_MIN_THRESH(x) (LTC2992_POWER1_MIN_THRESH + ((x) * 0x32)) | |
67 | #define LTC2992_DSENSE(x) (LTC2992_DSENSE1 + ((x) * 0x32)) | |
68 | #define LTC2992_DSENSE_MAX(x) (LTC2992_DSENSE1_MAX + ((x) * 0x32)) | |
69 | #define LTC2992_DSENSE_MIN(x) (LTC2992_DSENSE1_MIN + ((x) * 0x32)) | |
70 | #define LTC2992_DSENSE_MAX_THRESH(x) (LTC2992_DSENSE1_MAX_THRESH + ((x) * 0x32)) | |
71 | #define LTC2992_DSENSE_MIN_THRESH(x) (LTC2992_DSENSE1_MIN_THRESH + ((x) * 0x32)) | |
72 | #define LTC2992_SENSE(x) (LTC2992_SENSE1 + ((x) * 0x32)) | |
73 | #define LTC2992_SENSE_MAX(x) (LTC2992_SENSE1_MAX + ((x) * 0x32)) | |
74 | #define LTC2992_SENSE_MIN(x) (LTC2992_SENSE1_MIN + ((x) * 0x32)) | |
75 | #define LTC2992_SENSE_MAX_THRESH(x) (LTC2992_SENSE1_MAX_THRESH + ((x) * 0x32)) | |
76 | #define LTC2992_SENSE_MIN_THRESH(x) (LTC2992_SENSE1_MIN_THRESH + ((x) * 0x32)) | |
77 | #define LTC2992_POWER_FAULT(x) (LTC2992_FAULT1 + ((x) * 0x32)) | |
78 | #define LTC2992_SENSE_FAULT(x) (LTC2992_FAULT1 + ((x) * 0x32)) | |
79 | #define LTC2992_DSENSE_FAULT(x) (LTC2992_FAULT1 + ((x) * 0x32)) | |
80 | ||
81 | /* CTRLB register bitfields */ | |
82 | #define LTC2992_RESET_HISTORY BIT(3) | |
83 | ||
84 | /* FAULT1 FAULT2 registers common bitfields */ | |
85 | #define LTC2992_POWER_FAULT_MSK(x) (BIT(6) << (x)) | |
86 | #define LTC2992_DSENSE_FAULT_MSK(x) (BIT(4) << (x)) | |
87 | #define LTC2992_SENSE_FAULT_MSK(x) (BIT(2) << (x)) | |
88 | ||
89 | /* FAULT1 bitfields */ | |
90 | #define LTC2992_GPIO1_FAULT_MSK(x) (BIT(0) << (x)) | |
91 | ||
92 | /* FAULT2 bitfields */ | |
93 | #define LTC2992_GPIO2_FAULT_MSK(x) (BIT(0) << (x)) | |
94 | ||
95 | /* FAULT3 bitfields */ | |
96 | #define LTC2992_GPIO3_FAULT_MSK(x) (BIT(6) << (x)) | |
97 | #define LTC2992_GPIO4_FAULT_MSK(x) (BIT(4) << (x)) | |
98 | ||
99 | #define LTC2992_IADC_NANOV_LSB 12500 | |
100 | #define LTC2992_VADC_UV_LSB 25000 | |
101 | #define LTC2992_VADC_GPIO_UV_LSB 500 | |
102 | ||
9ca26df1 AT |
103 | #define LTC2992_GPIO_NR 4 |
104 | #define LTC2992_GPIO1_BIT 7 | |
105 | #define LTC2992_GPIO2_BIT 6 | |
106 | #define LTC2992_GPIO3_BIT 0 | |
107 | #define LTC2992_GPIO4_BIT 6 | |
108 | #define LTC2992_GPIO_BIT(x) (LTC2992_GPIO_NR - (x) - 1) | |
109 | ||
b0bd407e AT |
110 | struct ltc2992_state { |
111 | struct i2c_client *client; | |
9ca26df1 AT |
112 | struct gpio_chip gc; |
113 | struct mutex gpio_mutex; /* lock for gpio access */ | |
114 | const char *gpio_names[LTC2992_GPIO_NR]; | |
b0bd407e AT |
115 | struct regmap *regmap; |
116 | u32 r_sense_uohm[2]; | |
117 | }; | |
118 | ||
119 | struct ltc2992_gpio_regs { | |
120 | u8 data; | |
121 | u8 max; | |
122 | u8 min; | |
123 | u8 max_thresh; | |
124 | u8 min_thresh; | |
125 | u8 alarm; | |
126 | u8 min_alarm_msk; | |
127 | u8 max_alarm_msk; | |
9ca26df1 AT |
128 | u8 ctrl; |
129 | u8 ctrl_bit; | |
b0bd407e AT |
130 | }; |
131 | ||
132 | static const struct ltc2992_gpio_regs ltc2992_gpio_addr_map[] = { | |
133 | { | |
134 | .data = LTC2992_G1, | |
135 | .max = LTC2992_G1_MAX, | |
136 | .min = LTC2992_G1_MIN, | |
137 | .max_thresh = LTC2992_G1_MAX_THRESH, | |
138 | .min_thresh = LTC2992_G1_MIN_THRESH, | |
139 | .alarm = LTC2992_FAULT1, | |
140 | .min_alarm_msk = LTC2992_GPIO1_FAULT_MSK(0), | |
141 | .max_alarm_msk = LTC2992_GPIO1_FAULT_MSK(1), | |
9ca26df1 AT |
142 | .ctrl = LTC2992_GPIO_IO_CTRL, |
143 | .ctrl_bit = LTC2992_GPIO1_BIT, | |
b0bd407e AT |
144 | }, |
145 | { | |
146 | .data = LTC2992_G2, | |
147 | .max = LTC2992_G2_MAX, | |
148 | .min = LTC2992_G2_MIN, | |
149 | .max_thresh = LTC2992_G2_MAX_THRESH, | |
150 | .min_thresh = LTC2992_G2_MIN_THRESH, | |
151 | .alarm = LTC2992_FAULT2, | |
152 | .min_alarm_msk = LTC2992_GPIO2_FAULT_MSK(0), | |
153 | .max_alarm_msk = LTC2992_GPIO2_FAULT_MSK(1), | |
9ca26df1 AT |
154 | .ctrl = LTC2992_GPIO_IO_CTRL, |
155 | .ctrl_bit = LTC2992_GPIO2_BIT, | |
b0bd407e AT |
156 | }, |
157 | { | |
158 | .data = LTC2992_G3, | |
159 | .max = LTC2992_G3_MAX, | |
160 | .min = LTC2992_G3_MIN, | |
161 | .max_thresh = LTC2992_G3_MAX_THRESH, | |
162 | .min_thresh = LTC2992_G3_MIN_THRESH, | |
163 | .alarm = LTC2992_FAULT3, | |
164 | .min_alarm_msk = LTC2992_GPIO3_FAULT_MSK(0), | |
165 | .max_alarm_msk = LTC2992_GPIO3_FAULT_MSK(1), | |
9ca26df1 AT |
166 | .ctrl = LTC2992_GPIO_IO_CTRL, |
167 | .ctrl_bit = LTC2992_GPIO3_BIT, | |
b0bd407e AT |
168 | }, |
169 | { | |
170 | .data = LTC2992_G4, | |
171 | .max = LTC2992_G4_MAX, | |
172 | .min = LTC2992_G4_MIN, | |
173 | .max_thresh = LTC2992_G4_MAX_THRESH, | |
174 | .min_thresh = LTC2992_G4_MIN_THRESH, | |
175 | .alarm = LTC2992_FAULT3, | |
176 | .min_alarm_msk = LTC2992_GPIO4_FAULT_MSK(0), | |
177 | .max_alarm_msk = LTC2992_GPIO4_FAULT_MSK(1), | |
9ca26df1 AT |
178 | .ctrl = LTC2992_GPIO_CTRL, |
179 | .ctrl_bit = LTC2992_GPIO4_BIT, | |
b0bd407e AT |
180 | }, |
181 | }; | |
182 | ||
9ca26df1 AT |
183 | static const char *ltc2992_gpio_names[LTC2992_GPIO_NR] = { |
184 | "GPIO1", "GPIO2", "GPIO3", "GPIO4", | |
185 | }; | |
186 | ||
b0bd407e AT |
187 | static int ltc2992_read_reg(struct ltc2992_state *st, u8 addr, const u8 reg_len) |
188 | { | |
189 | u8 regvals[4]; | |
b0bd407e | 190 | int val; |
9ca26df1 | 191 | int ret; |
b0bd407e AT |
192 | int i; |
193 | ||
194 | ret = regmap_bulk_read(st->regmap, addr, regvals, reg_len); | |
195 | if (ret < 0) | |
196 | return ret; | |
197 | ||
198 | val = 0; | |
199 | for (i = 0; i < reg_len; i++) | |
200 | val |= regvals[reg_len - i - 1] << (i * 8); | |
201 | ||
202 | return val; | |
203 | } | |
204 | ||
205 | static int ltc2992_write_reg(struct ltc2992_state *st, u8 addr, const u8 reg_len, u32 val) | |
206 | { | |
207 | u8 regvals[4]; | |
208 | int i; | |
209 | ||
210 | for (i = 0; i < reg_len; i++) | |
211 | regvals[reg_len - i - 1] = (val >> (i * 8)) & 0xFF; | |
212 | ||
213 | return regmap_bulk_write(st->regmap, addr, regvals, reg_len); | |
214 | } | |
215 | ||
9ca26df1 AT |
216 | static int ltc2992_gpio_get(struct gpio_chip *chip, unsigned int offset) |
217 | { | |
218 | struct ltc2992_state *st = gpiochip_get_data(chip); | |
219 | unsigned long gpio_status; | |
220 | int reg; | |
221 | ||
222 | mutex_lock(&st->gpio_mutex); | |
223 | reg = ltc2992_read_reg(st, LTC2992_GPIO_STATUS, 1); | |
224 | mutex_unlock(&st->gpio_mutex); | |
225 | ||
226 | if (reg < 0) | |
227 | return reg; | |
228 | ||
229 | gpio_status = reg; | |
230 | ||
231 | return !test_bit(LTC2992_GPIO_BIT(offset), &gpio_status); | |
232 | } | |
233 | ||
234 | static int ltc2992_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask, | |
235 | unsigned long *bits) | |
236 | { | |
237 | struct ltc2992_state *st = gpiochip_get_data(chip); | |
238 | unsigned long gpio_status; | |
239 | unsigned int gpio_nr; | |
240 | int reg; | |
241 | ||
242 | mutex_lock(&st->gpio_mutex); | |
243 | reg = ltc2992_read_reg(st, LTC2992_GPIO_STATUS, 1); | |
244 | mutex_unlock(&st->gpio_mutex); | |
245 | ||
246 | if (reg < 0) | |
247 | return reg; | |
248 | ||
249 | gpio_status = reg; | |
250 | ||
251 | gpio_nr = 0; | |
252 | for_each_set_bit_from(gpio_nr, mask, LTC2992_GPIO_NR) { | |
253 | if (test_bit(LTC2992_GPIO_BIT(gpio_nr), &gpio_status)) | |
254 | set_bit(gpio_nr, bits); | |
255 | } | |
256 | ||
257 | return 0; | |
258 | } | |
259 | ||
260 | static void ltc2992_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) | |
261 | { | |
262 | struct ltc2992_state *st = gpiochip_get_data(chip); | |
263 | unsigned long gpio_ctrl; | |
264 | int reg; | |
265 | ||
266 | mutex_lock(&st->gpio_mutex); | |
267 | reg = ltc2992_read_reg(st, ltc2992_gpio_addr_map[offset].ctrl, 1); | |
268 | if (reg < 0) { | |
269 | mutex_unlock(&st->gpio_mutex); | |
270 | return; | |
271 | } | |
272 | ||
273 | gpio_ctrl = reg; | |
274 | assign_bit(ltc2992_gpio_addr_map[offset].ctrl_bit, &gpio_ctrl, value); | |
275 | ||
276 | ltc2992_write_reg(st, ltc2992_gpio_addr_map[offset].ctrl, 1, gpio_ctrl); | |
277 | mutex_unlock(&st->gpio_mutex); | |
278 | } | |
279 | ||
280 | static void ltc2992_gpio_set_multiple(struct gpio_chip *chip, unsigned long *mask, | |
281 | unsigned long *bits) | |
282 | { | |
283 | struct ltc2992_state *st = gpiochip_get_data(chip); | |
284 | unsigned long gpio_ctrl_io = 0; | |
285 | unsigned long gpio_ctrl = 0; | |
286 | unsigned int gpio_nr; | |
287 | ||
288 | for_each_set_bit(gpio_nr, mask, LTC2992_GPIO_NR) { | |
289 | if (gpio_nr < 3) | |
290 | assign_bit(ltc2992_gpio_addr_map[gpio_nr].ctrl_bit, &gpio_ctrl_io, true); | |
291 | ||
292 | if (gpio_nr == 3) | |
293 | assign_bit(ltc2992_gpio_addr_map[gpio_nr].ctrl_bit, &gpio_ctrl, true); | |
294 | } | |
295 | ||
296 | mutex_lock(&st->gpio_mutex); | |
297 | ltc2992_write_reg(st, LTC2992_GPIO_IO_CTRL, 1, gpio_ctrl_io); | |
298 | ltc2992_write_reg(st, LTC2992_GPIO_CTRL, 1, gpio_ctrl); | |
299 | mutex_unlock(&st->gpio_mutex); | |
300 | } | |
301 | ||
302 | static int ltc2992_config_gpio(struct ltc2992_state *st) | |
303 | { | |
304 | const char *name = dev_name(&st->client->dev); | |
305 | char *gpio_name; | |
306 | int ret; | |
307 | int i; | |
308 | ||
309 | ret = ltc2992_write_reg(st, LTC2992_GPIO_IO_CTRL, 1, 0); | |
310 | if (ret < 0) | |
311 | return ret; | |
312 | ||
313 | mutex_init(&st->gpio_mutex); | |
314 | ||
315 | for (i = 0; i < ARRAY_SIZE(st->gpio_names); i++) { | |
316 | gpio_name = devm_kasprintf(&st->client->dev, GFP_KERNEL, "ltc2992-%x-%s", | |
317 | st->client->addr, ltc2992_gpio_names[i]); | |
318 | if (!gpio_name) | |
319 | return -ENOMEM; | |
320 | ||
321 | st->gpio_names[i] = gpio_name; | |
322 | } | |
323 | ||
324 | st->gc.label = name; | |
325 | st->gc.parent = &st->client->dev; | |
326 | st->gc.owner = THIS_MODULE; | |
327 | st->gc.base = -1; | |
328 | st->gc.names = st->gpio_names; | |
329 | st->gc.ngpio = ARRAY_SIZE(st->gpio_names); | |
330 | st->gc.get = ltc2992_gpio_get; | |
331 | st->gc.get_multiple = ltc2992_gpio_get_multiple; | |
332 | st->gc.set = ltc2992_gpio_set; | |
333 | st->gc.set_multiple = ltc2992_gpio_set_multiple; | |
334 | ||
335 | ret = devm_gpiochip_add_data(&st->client->dev, &st->gc, st); | |
336 | if (ret) | |
337 | dev_err(&st->client->dev, "GPIO registering failed (%d)\n", ret); | |
338 | ||
339 | return ret; | |
340 | } | |
341 | ||
b0bd407e AT |
342 | static umode_t ltc2992_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr, |
343 | int channel) | |
344 | { | |
345 | const struct ltc2992_state *st = data; | |
346 | ||
347 | switch (type) { | |
348 | case hwmon_chip: | |
349 | switch (attr) { | |
350 | case hwmon_chip_in_reset_history: | |
351 | return 0200; | |
352 | } | |
353 | break; | |
354 | case hwmon_in: | |
355 | switch (attr) { | |
356 | case hwmon_in_input: | |
357 | case hwmon_in_lowest: | |
358 | case hwmon_in_highest: | |
359 | case hwmon_in_min_alarm: | |
360 | case hwmon_in_max_alarm: | |
361 | return 0444; | |
362 | case hwmon_in_min: | |
363 | case hwmon_in_max: | |
364 | return 0644; | |
365 | } | |
366 | break; | |
367 | case hwmon_curr: | |
368 | switch (attr) { | |
369 | case hwmon_curr_input: | |
370 | case hwmon_curr_lowest: | |
371 | case hwmon_curr_highest: | |
372 | case hwmon_curr_min_alarm: | |
373 | case hwmon_curr_max_alarm: | |
374 | if (st->r_sense_uohm[channel]) | |
375 | return 0444; | |
376 | break; | |
377 | case hwmon_curr_min: | |
378 | case hwmon_curr_max: | |
379 | if (st->r_sense_uohm[channel]) | |
380 | return 0644; | |
381 | break; | |
382 | } | |
383 | break; | |
384 | case hwmon_power: | |
385 | switch (attr) { | |
386 | case hwmon_power_input: | |
387 | case hwmon_power_input_lowest: | |
388 | case hwmon_power_input_highest: | |
389 | case hwmon_power_min_alarm: | |
390 | case hwmon_power_max_alarm: | |
391 | if (st->r_sense_uohm[channel]) | |
392 | return 0444; | |
393 | break; | |
394 | case hwmon_power_min: | |
395 | case hwmon_power_max: | |
396 | if (st->r_sense_uohm[channel]) | |
397 | return 0644; | |
398 | break; | |
399 | } | |
400 | break; | |
401 | default: | |
402 | break; | |
403 | } | |
404 | ||
405 | return 0; | |
406 | } | |
407 | ||
408 | static int ltc2992_get_voltage(struct ltc2992_state *st, u32 reg, u32 scale, long *val) | |
409 | { | |
410 | int reg_val; | |
411 | ||
412 | reg_val = ltc2992_read_reg(st, reg, 2); | |
413 | if (reg_val < 0) | |
414 | return reg_val; | |
415 | ||
416 | reg_val = reg_val >> 4; | |
417 | *val = DIV_ROUND_CLOSEST(reg_val * scale, 1000); | |
418 | ||
419 | return 0; | |
420 | } | |
421 | ||
422 | static int ltc2992_set_voltage(struct ltc2992_state *st, u32 reg, u32 scale, long val) | |
423 | { | |
424 | val = DIV_ROUND_CLOSEST(val * 1000, scale); | |
425 | val = val << 4; | |
426 | ||
427 | return ltc2992_write_reg(st, reg, 2, val); | |
428 | } | |
429 | ||
430 | static int ltc2992_read_gpio_alarm(struct ltc2992_state *st, int nr_gpio, u32 attr, long *val) | |
431 | { | |
432 | int reg_val; | |
433 | u32 mask; | |
434 | ||
435 | if (attr == hwmon_in_max_alarm) | |
436 | mask = ltc2992_gpio_addr_map[nr_gpio].max_alarm_msk; | |
437 | else | |
438 | mask = ltc2992_gpio_addr_map[nr_gpio].min_alarm_msk; | |
439 | ||
440 | reg_val = ltc2992_read_reg(st, ltc2992_gpio_addr_map[nr_gpio].alarm, 1); | |
441 | if (reg_val < 0) | |
442 | return reg_val; | |
443 | ||
444 | *val = !!(reg_val & mask); | |
445 | reg_val &= ~mask; | |
446 | ||
447 | return ltc2992_write_reg(st, ltc2992_gpio_addr_map[nr_gpio].alarm, 1, reg_val); | |
448 | } | |
449 | ||
450 | static int ltc2992_read_gpios_in(struct device *dev, u32 attr, int nr_gpio, long *val) | |
451 | { | |
452 | struct ltc2992_state *st = dev_get_drvdata(dev); | |
453 | u32 reg; | |
454 | ||
455 | switch (attr) { | |
456 | case hwmon_in_input: | |
457 | reg = ltc2992_gpio_addr_map[nr_gpio].data; | |
458 | break; | |
459 | case hwmon_in_lowest: | |
460 | reg = ltc2992_gpio_addr_map[nr_gpio].min; | |
461 | break; | |
462 | case hwmon_in_highest: | |
463 | reg = ltc2992_gpio_addr_map[nr_gpio].max; | |
464 | break; | |
465 | case hwmon_in_min: | |
466 | reg = ltc2992_gpio_addr_map[nr_gpio].min_thresh; | |
467 | break; | |
468 | case hwmon_in_max: | |
469 | reg = ltc2992_gpio_addr_map[nr_gpio].max_thresh; | |
470 | break; | |
471 | case hwmon_in_min_alarm: | |
472 | case hwmon_in_max_alarm: | |
473 | return ltc2992_read_gpio_alarm(st, nr_gpio, attr, val); | |
474 | default: | |
475 | return -EOPNOTSUPP; | |
476 | } | |
477 | ||
478 | return ltc2992_get_voltage(st, reg, LTC2992_VADC_GPIO_UV_LSB, val); | |
479 | } | |
480 | ||
481 | static int ltc2992_read_in_alarm(struct ltc2992_state *st, int channel, long *val, u32 attr) | |
482 | { | |
e1d15969 | 483 | int reg_val; |
b0bd407e AT |
484 | u32 mask; |
485 | ||
486 | if (attr == hwmon_in_max_alarm) | |
487 | mask = LTC2992_SENSE_FAULT_MSK(1); | |
488 | else | |
489 | mask = LTC2992_SENSE_FAULT_MSK(0); | |
490 | ||
491 | reg_val = ltc2992_read_reg(st, LTC2992_SENSE_FAULT(channel), 1); | |
492 | if (reg_val < 0) | |
493 | return reg_val; | |
494 | ||
495 | *val = !!(reg_val & mask); | |
496 | reg_val &= ~mask; | |
497 | ||
498 | return ltc2992_write_reg(st, LTC2992_SENSE_FAULT(channel), 1, reg_val); | |
499 | } | |
500 | ||
501 | static int ltc2992_read_in(struct device *dev, u32 attr, int channel, long *val) | |
502 | { | |
503 | struct ltc2992_state *st = dev_get_drvdata(dev); | |
504 | u32 reg; | |
505 | ||
506 | if (channel > 1) | |
507 | return ltc2992_read_gpios_in(dev, attr, channel - 2, val); | |
508 | ||
509 | switch (attr) { | |
510 | case hwmon_in_input: | |
511 | reg = LTC2992_SENSE(channel); | |
512 | break; | |
513 | case hwmon_in_lowest: | |
514 | reg = LTC2992_SENSE_MIN(channel); | |
515 | break; | |
516 | case hwmon_in_highest: | |
517 | reg = LTC2992_SENSE_MAX(channel); | |
518 | break; | |
519 | case hwmon_in_min: | |
520 | reg = LTC2992_SENSE_MIN_THRESH(channel); | |
521 | break; | |
522 | case hwmon_in_max: | |
523 | reg = LTC2992_SENSE_MAX_THRESH(channel); | |
524 | break; | |
525 | case hwmon_in_min_alarm: | |
526 | case hwmon_in_max_alarm: | |
527 | return ltc2992_read_in_alarm(st, channel, val, attr); | |
528 | default: | |
529 | return -EOPNOTSUPP; | |
530 | } | |
531 | ||
532 | return ltc2992_get_voltage(st, reg, LTC2992_VADC_UV_LSB, val); | |
533 | } | |
534 | ||
535 | static int ltc2992_get_current(struct ltc2992_state *st, u32 reg, u32 channel, long *val) | |
536 | { | |
e1d15969 | 537 | int reg_val; |
b0bd407e AT |
538 | |
539 | reg_val = ltc2992_read_reg(st, reg, 2); | |
540 | if (reg_val < 0) | |
541 | return reg_val; | |
542 | ||
543 | reg_val = reg_val >> 4; | |
544 | *val = DIV_ROUND_CLOSEST(reg_val * LTC2992_IADC_NANOV_LSB, st->r_sense_uohm[channel]); | |
545 | ||
546 | return 0; | |
547 | } | |
548 | ||
549 | static int ltc2992_set_current(struct ltc2992_state *st, u32 reg, u32 channel, long val) | |
550 | { | |
551 | u32 reg_val; | |
552 | ||
553 | reg_val = DIV_ROUND_CLOSEST(val * st->r_sense_uohm[channel], LTC2992_IADC_NANOV_LSB); | |
554 | reg_val = reg_val << 4; | |
555 | ||
556 | return ltc2992_write_reg(st, reg, 2, reg_val); | |
557 | } | |
558 | ||
559 | static int ltc2992_read_curr_alarm(struct ltc2992_state *st, int channel, long *val, u32 attr) | |
560 | { | |
e1d15969 | 561 | int reg_val; |
b0bd407e AT |
562 | u32 mask; |
563 | ||
564 | if (attr == hwmon_curr_max_alarm) | |
565 | mask = LTC2992_DSENSE_FAULT_MSK(1); | |
566 | else | |
567 | mask = LTC2992_DSENSE_FAULT_MSK(0); | |
568 | ||
569 | reg_val = ltc2992_read_reg(st, LTC2992_DSENSE_FAULT(channel), 1); | |
570 | if (reg_val < 0) | |
571 | return reg_val; | |
572 | ||
573 | *val = !!(reg_val & mask); | |
574 | ||
575 | reg_val &= ~mask; | |
576 | return ltc2992_write_reg(st, LTC2992_DSENSE_FAULT(channel), 1, reg_val); | |
577 | } | |
578 | ||
579 | static int ltc2992_read_curr(struct device *dev, u32 attr, int channel, long *val) | |
580 | { | |
581 | struct ltc2992_state *st = dev_get_drvdata(dev); | |
582 | u32 reg; | |
583 | ||
584 | switch (attr) { | |
585 | case hwmon_curr_input: | |
586 | reg = LTC2992_DSENSE(channel); | |
587 | break; | |
588 | case hwmon_curr_lowest: | |
589 | reg = LTC2992_DSENSE_MIN(channel); | |
590 | break; | |
591 | case hwmon_curr_highest: | |
592 | reg = LTC2992_DSENSE_MAX(channel); | |
593 | break; | |
594 | case hwmon_curr_min: | |
595 | reg = LTC2992_DSENSE_MIN_THRESH(channel); | |
596 | break; | |
597 | case hwmon_curr_max: | |
598 | reg = LTC2992_DSENSE_MAX_THRESH(channel); | |
599 | break; | |
600 | case hwmon_curr_min_alarm: | |
601 | case hwmon_curr_max_alarm: | |
602 | return ltc2992_read_curr_alarm(st, channel, val, attr); | |
603 | default: | |
604 | return -EOPNOTSUPP; | |
605 | } | |
606 | ||
607 | return ltc2992_get_current(st, reg, channel, val); | |
608 | } | |
609 | ||
610 | static int ltc2992_get_power(struct ltc2992_state *st, u32 reg, u32 channel, long *val) | |
611 | { | |
e1d15969 | 612 | int reg_val; |
b0bd407e AT |
613 | |
614 | reg_val = ltc2992_read_reg(st, reg, 3); | |
615 | if (reg_val < 0) | |
616 | return reg_val; | |
617 | ||
618 | *val = mul_u64_u32_div(reg_val, LTC2992_VADC_UV_LSB * LTC2992_IADC_NANOV_LSB, | |
619 | st->r_sense_uohm[channel] * 1000); | |
620 | ||
621 | return 0; | |
622 | } | |
623 | ||
624 | static int ltc2992_set_power(struct ltc2992_state *st, u32 reg, u32 channel, long val) | |
625 | { | |
626 | u32 reg_val; | |
627 | ||
628 | reg_val = mul_u64_u32_div(val, st->r_sense_uohm[channel] * 1000, | |
629 | LTC2992_VADC_UV_LSB * LTC2992_IADC_NANOV_LSB); | |
630 | ||
631 | return ltc2992_write_reg(st, reg, 3, reg_val); | |
632 | } | |
633 | ||
634 | static int ltc2992_read_power_alarm(struct ltc2992_state *st, int channel, long *val, u32 attr) | |
635 | { | |
e1d15969 | 636 | int reg_val; |
b0bd407e AT |
637 | u32 mask; |
638 | ||
639 | if (attr == hwmon_power_max_alarm) | |
640 | mask = LTC2992_POWER_FAULT_MSK(1); | |
641 | else | |
642 | mask = LTC2992_POWER_FAULT_MSK(0); | |
643 | ||
644 | reg_val = ltc2992_read_reg(st, LTC2992_POWER_FAULT(channel), 1); | |
645 | if (reg_val < 0) | |
646 | return reg_val; | |
647 | ||
648 | *val = !!(reg_val & mask); | |
649 | reg_val &= ~mask; | |
650 | ||
651 | return ltc2992_write_reg(st, LTC2992_POWER_FAULT(channel), 1, reg_val); | |
652 | } | |
653 | ||
654 | static int ltc2992_read_power(struct device *dev, u32 attr, int channel, long *val) | |
655 | { | |
656 | struct ltc2992_state *st = dev_get_drvdata(dev); | |
657 | u32 reg; | |
658 | ||
659 | switch (attr) { | |
660 | case hwmon_power_input: | |
661 | reg = LTC2992_POWER(channel); | |
662 | break; | |
663 | case hwmon_power_input_lowest: | |
664 | reg = LTC2992_POWER_MIN(channel); | |
665 | break; | |
666 | case hwmon_power_input_highest: | |
667 | reg = LTC2992_POWER_MAX(channel); | |
668 | break; | |
669 | case hwmon_power_min: | |
670 | reg = LTC2992_POWER_MIN_THRESH(channel); | |
671 | break; | |
672 | case hwmon_power_max: | |
673 | reg = LTC2992_POWER_MAX_THRESH(channel); | |
674 | break; | |
675 | case hwmon_power_min_alarm: | |
676 | case hwmon_power_max_alarm: | |
677 | return ltc2992_read_power_alarm(st, channel, val, attr); | |
678 | default: | |
679 | return -EOPNOTSUPP; | |
680 | } | |
681 | ||
682 | return ltc2992_get_power(st, reg, channel, val); | |
683 | } | |
684 | ||
685 | static int ltc2992_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, | |
686 | long *val) | |
687 | { | |
688 | switch (type) { | |
689 | case hwmon_in: | |
690 | return ltc2992_read_in(dev, attr, channel, val); | |
691 | case hwmon_curr: | |
692 | return ltc2992_read_curr(dev, attr, channel, val); | |
693 | case hwmon_power: | |
694 | return ltc2992_read_power(dev, attr, channel, val); | |
695 | default: | |
696 | return -EOPNOTSUPP; | |
697 | } | |
698 | } | |
699 | ||
700 | static int ltc2992_write_curr(struct device *dev, u32 attr, int channel, long val) | |
701 | { | |
702 | struct ltc2992_state *st = dev_get_drvdata(dev); | |
703 | u32 reg; | |
704 | ||
705 | switch (attr) { | |
706 | case hwmon_curr_min: | |
707 | reg = LTC2992_DSENSE_MIN_THRESH(channel); | |
708 | break; | |
709 | case hwmon_curr_max: | |
710 | reg = LTC2992_DSENSE_MAX_THRESH(channel); | |
711 | break; | |
712 | default: | |
713 | return -EOPNOTSUPP; | |
714 | } | |
715 | ||
716 | return ltc2992_set_current(st, reg, channel, val); | |
717 | } | |
718 | ||
719 | static int ltc2992_write_gpios_in(struct device *dev, u32 attr, int nr_gpio, long val) | |
720 | { | |
721 | struct ltc2992_state *st = dev_get_drvdata(dev); | |
722 | u32 reg; | |
723 | ||
724 | switch (attr) { | |
725 | case hwmon_in_min: | |
726 | reg = ltc2992_gpio_addr_map[nr_gpio].min_thresh; | |
727 | break; | |
728 | case hwmon_in_max: | |
729 | reg = ltc2992_gpio_addr_map[nr_gpio].max_thresh; | |
730 | break; | |
731 | default: | |
732 | return -EOPNOTSUPP; | |
733 | } | |
734 | ||
735 | return ltc2992_set_voltage(st, reg, LTC2992_VADC_GPIO_UV_LSB, val); | |
736 | } | |
737 | ||
738 | static int ltc2992_write_in(struct device *dev, u32 attr, int channel, long val) | |
739 | { | |
740 | struct ltc2992_state *st = dev_get_drvdata(dev); | |
741 | u32 reg; | |
742 | ||
743 | if (channel > 1) | |
744 | return ltc2992_write_gpios_in(dev, attr, channel - 2, val); | |
745 | ||
746 | switch (attr) { | |
747 | case hwmon_in_min: | |
748 | reg = LTC2992_SENSE_MIN_THRESH(channel); | |
749 | break; | |
750 | case hwmon_in_max: | |
751 | reg = LTC2992_SENSE_MAX_THRESH(channel); | |
752 | break; | |
753 | default: | |
754 | return -EOPNOTSUPP; | |
755 | } | |
756 | ||
757 | return ltc2992_set_voltage(st, reg, LTC2992_VADC_UV_LSB, val); | |
758 | } | |
759 | ||
760 | static int ltc2992_write_power(struct device *dev, u32 attr, int channel, long val) | |
761 | { | |
762 | struct ltc2992_state *st = dev_get_drvdata(dev); | |
763 | u32 reg; | |
764 | ||
765 | switch (attr) { | |
766 | case hwmon_power_min: | |
767 | reg = LTC2992_POWER_MIN_THRESH(channel); | |
768 | break; | |
769 | case hwmon_power_max: | |
770 | reg = LTC2992_POWER_MAX_THRESH(channel); | |
771 | break; | |
772 | default: | |
773 | return -EOPNOTSUPP; | |
774 | } | |
775 | ||
776 | return ltc2992_set_power(st, reg, channel, val); | |
777 | } | |
778 | ||
779 | static int ltc2992_write_chip(struct device *dev, u32 attr, int channel, long val) | |
780 | { | |
781 | struct ltc2992_state *st = dev_get_drvdata(dev); | |
782 | ||
783 | switch (attr) { | |
784 | case hwmon_chip_in_reset_history: | |
785 | return regmap_update_bits(st->regmap, LTC2992_CTRLB, LTC2992_RESET_HISTORY, | |
786 | LTC2992_RESET_HISTORY); | |
787 | default: | |
788 | return -EOPNOTSUPP; | |
789 | } | |
790 | } | |
791 | ||
792 | static int ltc2992_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, | |
793 | long val) | |
794 | { | |
795 | switch (type) { | |
796 | case hwmon_chip: | |
797 | return ltc2992_write_chip(dev, attr, channel, val); | |
798 | case hwmon_in: | |
799 | return ltc2992_write_in(dev, attr, channel, val); | |
800 | case hwmon_curr: | |
801 | return ltc2992_write_curr(dev, attr, channel, val); | |
802 | case hwmon_power: | |
803 | return ltc2992_write_power(dev, attr, channel, val); | |
804 | default: | |
805 | return -EOPNOTSUPP; | |
806 | } | |
807 | } | |
808 | ||
809 | static const struct hwmon_ops ltc2992_hwmon_ops = { | |
810 | .is_visible = ltc2992_is_visible, | |
811 | .read = ltc2992_read, | |
812 | .write = ltc2992_write, | |
813 | }; | |
814 | ||
815 | static const u32 ltc2992_chip_config[] = { | |
816 | HWMON_C_IN_RESET_HISTORY, | |
817 | 0 | |
818 | }; | |
819 | ||
820 | static const struct hwmon_channel_info ltc2992_chip = { | |
821 | .type = hwmon_chip, | |
822 | .config = ltc2992_chip_config, | |
823 | }; | |
824 | ||
825 | static const u32 ltc2992_in_config[] = { | |
826 | HWMON_I_INPUT | HWMON_I_LOWEST | HWMON_I_HIGHEST | HWMON_I_MIN | HWMON_I_MAX | | |
827 | HWMON_I_MIN_ALARM | HWMON_I_MAX_ALARM, | |
828 | HWMON_I_INPUT | HWMON_I_LOWEST | HWMON_I_HIGHEST | HWMON_I_MIN | HWMON_I_MAX | | |
829 | HWMON_I_MIN_ALARM | HWMON_I_MAX_ALARM, | |
830 | HWMON_I_INPUT | HWMON_I_LOWEST | HWMON_I_HIGHEST | HWMON_I_MIN | HWMON_I_MAX | | |
831 | HWMON_I_MIN_ALARM | HWMON_I_MAX_ALARM, | |
832 | HWMON_I_INPUT | HWMON_I_LOWEST | HWMON_I_HIGHEST | HWMON_I_MIN | HWMON_I_MAX | | |
833 | HWMON_I_MIN_ALARM | HWMON_I_MAX_ALARM, | |
834 | HWMON_I_INPUT | HWMON_I_LOWEST | HWMON_I_HIGHEST | HWMON_I_MIN | HWMON_I_MAX | | |
835 | HWMON_I_MIN_ALARM | HWMON_I_MAX_ALARM, | |
836 | HWMON_I_INPUT | HWMON_I_LOWEST | HWMON_I_HIGHEST | HWMON_I_MIN | HWMON_I_MAX | | |
837 | HWMON_I_MIN_ALARM | HWMON_I_MAX_ALARM, | |
838 | 0 | |
839 | }; | |
840 | ||
841 | static const struct hwmon_channel_info ltc2992_in = { | |
842 | .type = hwmon_in, | |
843 | .config = ltc2992_in_config, | |
844 | }; | |
845 | ||
846 | static const u32 ltc2992_curr_config[] = { | |
847 | HWMON_C_INPUT | HWMON_C_LOWEST | HWMON_C_HIGHEST | HWMON_C_MIN | HWMON_C_MAX | | |
848 | HWMON_C_MIN_ALARM | HWMON_C_MAX_ALARM, | |
849 | HWMON_C_INPUT | HWMON_C_LOWEST | HWMON_C_HIGHEST | HWMON_C_MIN | HWMON_C_MAX | | |
850 | HWMON_C_MIN_ALARM | HWMON_C_MAX_ALARM, | |
851 | 0 | |
852 | }; | |
853 | ||
854 | static const struct hwmon_channel_info ltc2992_curr = { | |
855 | .type = hwmon_curr, | |
856 | .config = ltc2992_curr_config, | |
857 | }; | |
858 | ||
859 | static const u32 ltc2992_power_config[] = { | |
860 | HWMON_P_INPUT | HWMON_P_INPUT_LOWEST | HWMON_P_INPUT_HIGHEST | HWMON_P_MIN | HWMON_P_MAX | | |
861 | HWMON_P_MIN_ALARM | HWMON_P_MAX_ALARM, | |
862 | HWMON_P_INPUT | HWMON_P_INPUT_LOWEST | HWMON_P_INPUT_HIGHEST | HWMON_P_MIN | HWMON_P_MAX | | |
863 | HWMON_P_MIN_ALARM | HWMON_P_MAX_ALARM, | |
864 | 0 | |
865 | }; | |
866 | ||
867 | static const struct hwmon_channel_info ltc2992_power = { | |
868 | .type = hwmon_power, | |
869 | .config = ltc2992_power_config, | |
870 | }; | |
871 | ||
872 | static const struct hwmon_channel_info *ltc2992_info[] = { | |
873 | <c2992_chip, | |
874 | <c2992_in, | |
875 | <c2992_curr, | |
876 | <c2992_power, | |
877 | NULL | |
878 | }; | |
879 | ||
880 | static const struct hwmon_chip_info ltc2992_chip_info = { | |
881 | .ops = <c2992_hwmon_ops, | |
882 | .info = ltc2992_info, | |
883 | }; | |
884 | ||
885 | static const struct regmap_config ltc2992_regmap_config = { | |
886 | .reg_bits = 8, | |
887 | .val_bits = 8, | |
888 | .max_register = 0xE8, | |
889 | }; | |
890 | ||
891 | static int ltc2992_parse_dt(struct ltc2992_state *st) | |
892 | { | |
893 | struct fwnode_handle *fwnode; | |
894 | struct fwnode_handle *child; | |
895 | u32 addr; | |
896 | u32 val; | |
897 | int ret; | |
898 | ||
899 | fwnode = dev_fwnode(&st->client->dev); | |
900 | ||
901 | fwnode_for_each_available_child_node(fwnode, child) { | |
902 | ret = fwnode_property_read_u32(child, "reg", &addr); | |
8370e5b0 AS |
903 | if (ret < 0) { |
904 | fwnode_handle_put(child); | |
b0bd407e | 905 | return ret; |
8370e5b0 | 906 | } |
b0bd407e | 907 | |
8370e5b0 AS |
908 | if (addr > 1) { |
909 | fwnode_handle_put(child); | |
b0bd407e | 910 | return -EINVAL; |
8370e5b0 | 911 | } |
b0bd407e AT |
912 | |
913 | ret = fwnode_property_read_u32(child, "shunt-resistor-micro-ohms", &val); | |
914 | if (!ret) | |
915 | st->r_sense_uohm[addr] = val; | |
916 | } | |
917 | ||
918 | return 0; | |
919 | } | |
920 | ||
921 | static int ltc2992_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) | |
922 | { | |
923 | struct device *hwmon_dev; | |
924 | struct ltc2992_state *st; | |
925 | int ret; | |
926 | ||
927 | st = devm_kzalloc(&client->dev, sizeof(*st), GFP_KERNEL); | |
928 | if (!st) | |
929 | return -ENOMEM; | |
930 | ||
931 | st->client = client; | |
932 | st->regmap = devm_regmap_init_i2c(client, <c2992_regmap_config); | |
933 | if (IS_ERR(st->regmap)) | |
934 | return PTR_ERR(st->regmap); | |
935 | ||
936 | ret = ltc2992_parse_dt(st); | |
937 | if (ret < 0) | |
938 | return ret; | |
939 | ||
9ca26df1 AT |
940 | ret = ltc2992_config_gpio(st); |
941 | if (ret < 0) | |
942 | return ret; | |
943 | ||
b0bd407e AT |
944 | hwmon_dev = devm_hwmon_device_register_with_info(&client->dev, client->name, st, |
945 | <c2992_chip_info, NULL); | |
946 | ||
947 | return PTR_ERR_OR_ZERO(hwmon_dev); | |
948 | } | |
949 | ||
950 | static const struct of_device_id ltc2992_of_match[] = { | |
951 | { .compatible = "adi,ltc2992" }, | |
952 | { } | |
953 | }; | |
954 | MODULE_DEVICE_TABLE(of, ltc2992_of_match); | |
955 | ||
956 | static const struct i2c_device_id ltc2992_i2c_id[] = { | |
957 | {"ltc2992", 0}, | |
958 | {} | |
959 | }; | |
960 | MODULE_DEVICE_TABLE(i2c, ltc2992_i2c_id); | |
961 | ||
962 | static struct i2c_driver ltc2992_i2c_driver = { | |
963 | .driver = { | |
964 | .name = "ltc2992", | |
965 | .of_match_table = ltc2992_of_match, | |
966 | }, | |
967 | .probe = ltc2992_i2c_probe, | |
968 | .id_table = ltc2992_i2c_id, | |
969 | }; | |
970 | ||
971 | module_i2c_driver(ltc2992_i2c_driver); | |
972 | ||
973 | MODULE_AUTHOR("Alexandru Tachici <alexandru.tachici@analog.com>"); | |
974 | MODULE_DESCRIPTION("Hwmon driver for Linear Technology 2992"); | |
975 | MODULE_LICENSE("Dual BSD/GPL"); |