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> |
11 | #include <linux/gpio/driver.h> |
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 |
58 | #define LTC2992_GPIO_STATUS 0x95 |
59 | #define LTC2992_GPIO_IO_CTRL 0x96 |
60 | #define LTC2992_GPIO_CTRL 0x97 |
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 | |
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 | |
110 | struct ltc2992_state { |
111 | struct i2c_client *client; |
112 | struct gpio_chip gc; |
113 | struct mutex gpio_mutex; /* lock for gpio access */ |
114 | const char *gpio_names[LTC2992_GPIO_NR]; |
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; |
128 | u8 ctrl; |
129 | u8 ctrl_bit; |
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), |
142 | .ctrl = LTC2992_GPIO_IO_CTRL, |
143 | .ctrl_bit = LTC2992_GPIO1_BIT, |
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), |
154 | .ctrl = LTC2992_GPIO_IO_CTRL, |
155 | .ctrl_bit = LTC2992_GPIO2_BIT, |
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), |
166 | .ctrl = LTC2992_GPIO_IO_CTRL, |
167 | .ctrl_bit = LTC2992_GPIO3_BIT, |
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), |
178 | .ctrl = LTC2992_GPIO_CTRL, |
179 | .ctrl_bit = LTC2992_GPIO4_BIT, |
180 | }, |
181 | }; |
182 | |
183 | static const char *ltc2992_gpio_names[LTC2992_GPIO_NR] = { |
184 | "GPIO1" , "GPIO2" , "GPIO3" , "GPIO4" , |
185 | }; |
186 | |
187 | static int ltc2992_read_reg(struct ltc2992_state *st, u8 addr, const u8 reg_len) |
188 | { |
189 | u8 regvals[4]; |
190 | int val; |
191 | int ret; |
192 | int i; |
193 | |
194 | ret = regmap_bulk_read(map: st->regmap, reg: addr, val: regvals, val_count: 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(map: st->regmap, reg: addr, val: regvals, val_count: reg_len); |
214 | } |
215 | |
216 | static int ltc2992_gpio_get(struct gpio_chip *chip, unsigned int offset) |
217 | { |
218 | struct ltc2992_state *st = gpiochip_get_data(gc: 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, reg_len: 1); |
224 | mutex_unlock(lock: &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(gc: 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, reg_len: 1); |
244 | mutex_unlock(lock: &st->gpio_mutex); |
245 | |
246 | if (reg < 0) |
247 | return reg; |
248 | |
249 | gpio_status = reg; |
250 | |
251 | for_each_set_bit(gpio_nr, mask, LTC2992_GPIO_NR) { |
252 | if (test_bit(LTC2992_GPIO_BIT(gpio_nr), &gpio_status)) |
253 | set_bit(nr: gpio_nr, addr: bits); |
254 | } |
255 | |
256 | return 0; |
257 | } |
258 | |
259 | static void ltc2992_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) |
260 | { |
261 | struct ltc2992_state *st = gpiochip_get_data(gc: chip); |
262 | unsigned long gpio_ctrl; |
263 | int reg; |
264 | |
265 | mutex_lock(&st->gpio_mutex); |
266 | reg = ltc2992_read_reg(st, addr: ltc2992_gpio_addr_map[offset].ctrl, reg_len: 1); |
267 | if (reg < 0) { |
268 | mutex_unlock(lock: &st->gpio_mutex); |
269 | return; |
270 | } |
271 | |
272 | gpio_ctrl = reg; |
273 | assign_bit(nr: ltc2992_gpio_addr_map[offset].ctrl_bit, addr: &gpio_ctrl, value); |
274 | |
275 | ltc2992_write_reg(st, addr: ltc2992_gpio_addr_map[offset].ctrl, reg_len: 1, val: gpio_ctrl); |
276 | mutex_unlock(lock: &st->gpio_mutex); |
277 | } |
278 | |
279 | static void ltc2992_gpio_set_multiple(struct gpio_chip *chip, unsigned long *mask, |
280 | unsigned long *bits) |
281 | { |
282 | struct ltc2992_state *st = gpiochip_get_data(gc: chip); |
283 | unsigned long gpio_ctrl_io = 0; |
284 | unsigned long gpio_ctrl = 0; |
285 | unsigned int gpio_nr; |
286 | |
287 | for_each_set_bit(gpio_nr, mask, LTC2992_GPIO_NR) { |
288 | if (gpio_nr < 3) |
289 | assign_bit(nr: ltc2992_gpio_addr_map[gpio_nr].ctrl_bit, addr: &gpio_ctrl_io, value: true); |
290 | |
291 | if (gpio_nr == 3) |
292 | assign_bit(nr: ltc2992_gpio_addr_map[gpio_nr].ctrl_bit, addr: &gpio_ctrl, value: true); |
293 | } |
294 | |
295 | mutex_lock(&st->gpio_mutex); |
296 | ltc2992_write_reg(st, LTC2992_GPIO_IO_CTRL, reg_len: 1, val: gpio_ctrl_io); |
297 | ltc2992_write_reg(st, LTC2992_GPIO_CTRL, reg_len: 1, val: gpio_ctrl); |
298 | mutex_unlock(lock: &st->gpio_mutex); |
299 | } |
300 | |
301 | static int ltc2992_config_gpio(struct ltc2992_state *st) |
302 | { |
303 | const char *name = dev_name(dev: &st->client->dev); |
304 | char *gpio_name; |
305 | int ret; |
306 | int i; |
307 | |
308 | ret = ltc2992_write_reg(st, LTC2992_GPIO_IO_CTRL, reg_len: 1, val: 0); |
309 | if (ret < 0) |
310 | return ret; |
311 | |
312 | mutex_init(&st->gpio_mutex); |
313 | |
314 | for (i = 0; i < ARRAY_SIZE(st->gpio_names); i++) { |
315 | gpio_name = devm_kasprintf(dev: &st->client->dev, GFP_KERNEL, fmt: "ltc2992-%x-%s" , |
316 | st->client->addr, ltc2992_gpio_names[i]); |
317 | if (!gpio_name) |
318 | return -ENOMEM; |
319 | |
320 | st->gpio_names[i] = gpio_name; |
321 | } |
322 | |
323 | st->gc.label = name; |
324 | st->gc.parent = &st->client->dev; |
325 | st->gc.owner = THIS_MODULE; |
326 | st->gc.can_sleep = true; |
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 | |
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, addr: reg, reg_len: 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, addr: reg, reg_len: 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, addr: ltc2992_gpio_addr_map[nr_gpio].alarm, reg_len: 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, addr: ltc2992_gpio_addr_map[nr_gpio].alarm, reg_len: 1, val: 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 | { |
483 | int reg_val; |
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), reg_len: 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), reg_len: 1, val: 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, nr_gpio: 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 | { |
537 | int reg_val; |
538 | |
539 | reg_val = ltc2992_read_reg(st, addr: reg, reg_len: 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, addr: reg, reg_len: 2, val: reg_val); |
557 | } |
558 | |
559 | static int ltc2992_read_curr_alarm(struct ltc2992_state *st, int channel, long *val, u32 attr) |
560 | { |
561 | int reg_val; |
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), reg_len: 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), reg_len: 1, val: 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 | { |
612 | int reg_val; |
613 | |
614 | reg_val = ltc2992_read_reg(st, addr: reg, reg_len: 3); |
615 | if (reg_val < 0) |
616 | return reg_val; |
617 | |
618 | *val = mul_u64_u32_div(a: reg_val, LTC2992_VADC_UV_LSB * LTC2992_IADC_NANOV_LSB, |
619 | div: 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(a: val, mul: st->r_sense_uohm[channel] * 1000, |
629 | LTC2992_VADC_UV_LSB * LTC2992_IADC_NANOV_LSB); |
630 | |
631 | return ltc2992_write_reg(st, addr: reg, reg_len: 3, val: reg_val); |
632 | } |
633 | |
634 | static int ltc2992_read_power_alarm(struct ltc2992_state *st, int channel, long *val, u32 attr) |
635 | { |
636 | int reg_val; |
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), reg_len: 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), reg_len: 1, val: 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, nr_gpio: 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(map: 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 struct hwmon_channel_info * const ltc2992_info[] = { |
816 | HWMON_CHANNEL_INFO(chip, |
817 | HWMON_C_IN_RESET_HISTORY), |
818 | HWMON_CHANNEL_INFO(in, |
819 | HWMON_I_INPUT | HWMON_I_LOWEST | HWMON_I_HIGHEST | HWMON_I_MIN | |
820 | HWMON_I_MAX | HWMON_I_MIN_ALARM | HWMON_I_MAX_ALARM, |
821 | HWMON_I_INPUT | HWMON_I_LOWEST | HWMON_I_HIGHEST | HWMON_I_MIN | |
822 | HWMON_I_MAX | HWMON_I_MIN_ALARM | HWMON_I_MAX_ALARM, |
823 | HWMON_I_INPUT | HWMON_I_LOWEST | HWMON_I_HIGHEST | HWMON_I_MIN | |
824 | HWMON_I_MAX | HWMON_I_MIN_ALARM | HWMON_I_MAX_ALARM, |
825 | HWMON_I_INPUT | HWMON_I_LOWEST | HWMON_I_HIGHEST | HWMON_I_MIN | |
826 | HWMON_I_MAX | HWMON_I_MIN_ALARM | HWMON_I_MAX_ALARM, |
827 | HWMON_I_INPUT | HWMON_I_LOWEST | HWMON_I_HIGHEST | HWMON_I_MIN | |
828 | HWMON_I_MAX | HWMON_I_MIN_ALARM | HWMON_I_MAX_ALARM, |
829 | HWMON_I_INPUT | HWMON_I_LOWEST | HWMON_I_HIGHEST | HWMON_I_MIN | |
830 | HWMON_I_MAX | HWMON_I_MIN_ALARM | HWMON_I_MAX_ALARM), |
831 | HWMON_CHANNEL_INFO(curr, |
832 | HWMON_C_INPUT | HWMON_C_LOWEST | HWMON_C_HIGHEST | HWMON_C_MIN | |
833 | HWMON_C_MAX | HWMON_C_MIN_ALARM | HWMON_C_MAX_ALARM, |
834 | HWMON_C_INPUT | HWMON_C_LOWEST | HWMON_C_HIGHEST | HWMON_C_MIN | |
835 | HWMON_C_MAX | HWMON_C_MIN_ALARM | HWMON_C_MAX_ALARM), |
836 | HWMON_CHANNEL_INFO(power, |
837 | HWMON_P_INPUT | HWMON_P_INPUT_LOWEST | HWMON_P_INPUT_HIGHEST | |
838 | HWMON_P_MIN | HWMON_P_MAX | HWMON_P_MIN_ALARM | HWMON_P_MAX_ALARM, |
839 | HWMON_P_INPUT | HWMON_P_INPUT_LOWEST | HWMON_P_INPUT_HIGHEST | |
840 | HWMON_P_MIN | HWMON_P_MAX | HWMON_P_MIN_ALARM | HWMON_P_MAX_ALARM), |
841 | NULL |
842 | }; |
843 | |
844 | static const struct hwmon_chip_info ltc2992_chip_info = { |
845 | .ops = <c2992_hwmon_ops, |
846 | .info = ltc2992_info, |
847 | }; |
848 | |
849 | static const struct regmap_config ltc2992_regmap_config = { |
850 | .reg_bits = 8, |
851 | .val_bits = 8, |
852 | .max_register = 0xE8, |
853 | }; |
854 | |
855 | static int ltc2992_parse_dt(struct ltc2992_state *st) |
856 | { |
857 | struct fwnode_handle *fwnode; |
858 | struct fwnode_handle *child; |
859 | u32 addr; |
860 | u32 val; |
861 | int ret; |
862 | |
863 | fwnode = dev_fwnode(&st->client->dev); |
864 | |
865 | fwnode_for_each_available_child_node(fwnode, child) { |
866 | ret = fwnode_property_read_u32(fwnode: child, propname: "reg" , val: &addr); |
867 | if (ret < 0) { |
868 | fwnode_handle_put(fwnode: child); |
869 | return ret; |
870 | } |
871 | |
872 | if (addr > 1) { |
873 | fwnode_handle_put(fwnode: child); |
874 | return -EINVAL; |
875 | } |
876 | |
877 | ret = fwnode_property_read_u32(fwnode: child, propname: "shunt-resistor-micro-ohms" , val: &val); |
878 | if (!ret) { |
879 | if (!val) |
880 | return dev_err_probe(dev: &st->client->dev, err: -EINVAL, |
881 | fmt: "shunt resistor value cannot be zero\n" ); |
882 | st->r_sense_uohm[addr] = val; |
883 | } |
884 | } |
885 | |
886 | return 0; |
887 | } |
888 | |
889 | static int ltc2992_i2c_probe(struct i2c_client *client) |
890 | { |
891 | struct device *hwmon_dev; |
892 | struct ltc2992_state *st; |
893 | int ret; |
894 | |
895 | st = devm_kzalloc(dev: &client->dev, size: sizeof(*st), GFP_KERNEL); |
896 | if (!st) |
897 | return -ENOMEM; |
898 | |
899 | st->client = client; |
900 | st->regmap = devm_regmap_init_i2c(client, <c2992_regmap_config); |
901 | if (IS_ERR(ptr: st->regmap)) |
902 | return PTR_ERR(ptr: st->regmap); |
903 | |
904 | ret = ltc2992_parse_dt(st); |
905 | if (ret < 0) |
906 | return ret; |
907 | |
908 | ret = ltc2992_config_gpio(st); |
909 | if (ret < 0) |
910 | return ret; |
911 | |
912 | hwmon_dev = devm_hwmon_device_register_with_info(dev: &client->dev, name: client->name, drvdata: st, |
913 | info: <c2992_chip_info, NULL); |
914 | |
915 | return PTR_ERR_OR_ZERO(ptr: hwmon_dev); |
916 | } |
917 | |
918 | static const struct of_device_id ltc2992_of_match[] = { |
919 | { .compatible = "adi,ltc2992" }, |
920 | { } |
921 | }; |
922 | MODULE_DEVICE_TABLE(of, ltc2992_of_match); |
923 | |
924 | static const struct i2c_device_id ltc2992_i2c_id[] = { |
925 | {"ltc2992" , 0}, |
926 | {} |
927 | }; |
928 | MODULE_DEVICE_TABLE(i2c, ltc2992_i2c_id); |
929 | |
930 | static struct i2c_driver ltc2992_i2c_driver = { |
931 | .driver = { |
932 | .name = "ltc2992" , |
933 | .of_match_table = ltc2992_of_match, |
934 | }, |
935 | .probe = ltc2992_i2c_probe, |
936 | .id_table = ltc2992_i2c_id, |
937 | }; |
938 | |
939 | module_i2c_driver(ltc2992_i2c_driver); |
940 | |
941 | MODULE_AUTHOR("Alexandru Tachici <alexandru.tachici@analog.com>" ); |
942 | MODULE_DESCRIPTION("Hwmon driver for Linear Technology 2992" ); |
943 | MODULE_LICENSE("Dual BSD/GPL" ); |
944 | |