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 | ||
749443de | 251 | for_each_set_bit(gpio_nr, mask, LTC2992_GPIO_NR) { |
9ca26df1 AT |
252 | if (test_bit(LTC2992_GPIO_BIT(gpio_nr), &gpio_status)) |
253 | set_bit(gpio_nr, 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(chip); | |
262 | unsigned long gpio_ctrl; | |
263 | int reg; | |
264 | ||
265 | mutex_lock(&st->gpio_mutex); | |
266 | reg = ltc2992_read_reg(st, ltc2992_gpio_addr_map[offset].ctrl, 1); | |
267 | if (reg < 0) { | |
268 | mutex_unlock(&st->gpio_mutex); | |
269 | return; | |
270 | } | |
271 | ||
272 | gpio_ctrl = reg; | |
273 | assign_bit(ltc2992_gpio_addr_map[offset].ctrl_bit, &gpio_ctrl, value); | |
274 | ||
275 | ltc2992_write_reg(st, ltc2992_gpio_addr_map[offset].ctrl, 1, gpio_ctrl); | |
276 | mutex_unlock(&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(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(ltc2992_gpio_addr_map[gpio_nr].ctrl_bit, &gpio_ctrl_io, true); | |
290 | ||
291 | if (gpio_nr == 3) | |
292 | assign_bit(ltc2992_gpio_addr_map[gpio_nr].ctrl_bit, &gpio_ctrl, true); | |
293 | } | |
294 | ||
295 | mutex_lock(&st->gpio_mutex); | |
296 | ltc2992_write_reg(st, LTC2992_GPIO_IO_CTRL, 1, gpio_ctrl_io); | |
297 | ltc2992_write_reg(st, LTC2992_GPIO_CTRL, 1, gpio_ctrl); | |
298 | mutex_unlock(&st->gpio_mutex); | |
299 | } | |
300 | ||
301 | static int ltc2992_config_gpio(struct ltc2992_state *st) | |
302 | { | |
303 | const char *name = dev_name(&st->client->dev); | |
304 | char *gpio_name; | |
305 | int ret; | |
306 | int i; | |
307 | ||
308 | ret = ltc2992_write_reg(st, LTC2992_GPIO_IO_CTRL, 1, 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(&st->client->dev, GFP_KERNEL, "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.base = -1; | |
327 | st->gc.names = st->gpio_names; | |
328 | st->gc.ngpio = ARRAY_SIZE(st->gpio_names); | |
329 | st->gc.get = ltc2992_gpio_get; | |
330 | st->gc.get_multiple = ltc2992_gpio_get_multiple; | |
331 | st->gc.set = ltc2992_gpio_set; | |
332 | st->gc.set_multiple = ltc2992_gpio_set_multiple; | |
333 | ||
334 | ret = devm_gpiochip_add_data(&st->client->dev, &st->gc, st); | |
335 | if (ret) | |
336 | dev_err(&st->client->dev, "GPIO registering failed (%d)\n", ret); | |
337 | ||
338 | return ret; | |
339 | } | |
340 | ||
b0bd407e AT |
341 | static umode_t ltc2992_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr, |
342 | int channel) | |
343 | { | |
344 | const struct ltc2992_state *st = data; | |
345 | ||
346 | switch (type) { | |
347 | case hwmon_chip: | |
348 | switch (attr) { | |
349 | case hwmon_chip_in_reset_history: | |
350 | return 0200; | |
351 | } | |
352 | break; | |
353 | case hwmon_in: | |
354 | switch (attr) { | |
355 | case hwmon_in_input: | |
356 | case hwmon_in_lowest: | |
357 | case hwmon_in_highest: | |
358 | case hwmon_in_min_alarm: | |
359 | case hwmon_in_max_alarm: | |
360 | return 0444; | |
361 | case hwmon_in_min: | |
362 | case hwmon_in_max: | |
363 | return 0644; | |
364 | } | |
365 | break; | |
366 | case hwmon_curr: | |
367 | switch (attr) { | |
368 | case hwmon_curr_input: | |
369 | case hwmon_curr_lowest: | |
370 | case hwmon_curr_highest: | |
371 | case hwmon_curr_min_alarm: | |
372 | case hwmon_curr_max_alarm: | |
373 | if (st->r_sense_uohm[channel]) | |
374 | return 0444; | |
375 | break; | |
376 | case hwmon_curr_min: | |
377 | case hwmon_curr_max: | |
378 | if (st->r_sense_uohm[channel]) | |
379 | return 0644; | |
380 | break; | |
381 | } | |
382 | break; | |
383 | case hwmon_power: | |
384 | switch (attr) { | |
385 | case hwmon_power_input: | |
386 | case hwmon_power_input_lowest: | |
387 | case hwmon_power_input_highest: | |
388 | case hwmon_power_min_alarm: | |
389 | case hwmon_power_max_alarm: | |
390 | if (st->r_sense_uohm[channel]) | |
391 | return 0444; | |
392 | break; | |
393 | case hwmon_power_min: | |
394 | case hwmon_power_max: | |
395 | if (st->r_sense_uohm[channel]) | |
396 | return 0644; | |
397 | break; | |
398 | } | |
399 | break; | |
400 | default: | |
401 | break; | |
402 | } | |
403 | ||
404 | return 0; | |
405 | } | |
406 | ||
407 | static int ltc2992_get_voltage(struct ltc2992_state *st, u32 reg, u32 scale, long *val) | |
408 | { | |
409 | int reg_val; | |
410 | ||
411 | reg_val = ltc2992_read_reg(st, reg, 2); | |
412 | if (reg_val < 0) | |
413 | return reg_val; | |
414 | ||
415 | reg_val = reg_val >> 4; | |
416 | *val = DIV_ROUND_CLOSEST(reg_val * scale, 1000); | |
417 | ||
418 | return 0; | |
419 | } | |
420 | ||
421 | static int ltc2992_set_voltage(struct ltc2992_state *st, u32 reg, u32 scale, long val) | |
422 | { | |
423 | val = DIV_ROUND_CLOSEST(val * 1000, scale); | |
424 | val = val << 4; | |
425 | ||
426 | return ltc2992_write_reg(st, reg, 2, val); | |
427 | } | |
428 | ||
429 | static int ltc2992_read_gpio_alarm(struct ltc2992_state *st, int nr_gpio, u32 attr, long *val) | |
430 | { | |
431 | int reg_val; | |
432 | u32 mask; | |
433 | ||
434 | if (attr == hwmon_in_max_alarm) | |
435 | mask = ltc2992_gpio_addr_map[nr_gpio].max_alarm_msk; | |
436 | else | |
437 | mask = ltc2992_gpio_addr_map[nr_gpio].min_alarm_msk; | |
438 | ||
439 | reg_val = ltc2992_read_reg(st, ltc2992_gpio_addr_map[nr_gpio].alarm, 1); | |
440 | if (reg_val < 0) | |
441 | return reg_val; | |
442 | ||
443 | *val = !!(reg_val & mask); | |
444 | reg_val &= ~mask; | |
445 | ||
446 | return ltc2992_write_reg(st, ltc2992_gpio_addr_map[nr_gpio].alarm, 1, reg_val); | |
447 | } | |
448 | ||
449 | static int ltc2992_read_gpios_in(struct device *dev, u32 attr, int nr_gpio, long *val) | |
450 | { | |
451 | struct ltc2992_state *st = dev_get_drvdata(dev); | |
452 | u32 reg; | |
453 | ||
454 | switch (attr) { | |
455 | case hwmon_in_input: | |
456 | reg = ltc2992_gpio_addr_map[nr_gpio].data; | |
457 | break; | |
458 | case hwmon_in_lowest: | |
459 | reg = ltc2992_gpio_addr_map[nr_gpio].min; | |
460 | break; | |
461 | case hwmon_in_highest: | |
462 | reg = ltc2992_gpio_addr_map[nr_gpio].max; | |
463 | break; | |
464 | case hwmon_in_min: | |
465 | reg = ltc2992_gpio_addr_map[nr_gpio].min_thresh; | |
466 | break; | |
467 | case hwmon_in_max: | |
468 | reg = ltc2992_gpio_addr_map[nr_gpio].max_thresh; | |
469 | break; | |
470 | case hwmon_in_min_alarm: | |
471 | case hwmon_in_max_alarm: | |
472 | return ltc2992_read_gpio_alarm(st, nr_gpio, attr, val); | |
473 | default: | |
474 | return -EOPNOTSUPP; | |
475 | } | |
476 | ||
477 | return ltc2992_get_voltage(st, reg, LTC2992_VADC_GPIO_UV_LSB, val); | |
478 | } | |
479 | ||
480 | static int ltc2992_read_in_alarm(struct ltc2992_state *st, int channel, long *val, u32 attr) | |
481 | { | |
e1d15969 | 482 | int reg_val; |
b0bd407e AT |
483 | u32 mask; |
484 | ||
485 | if (attr == hwmon_in_max_alarm) | |
486 | mask = LTC2992_SENSE_FAULT_MSK(1); | |
487 | else | |
488 | mask = LTC2992_SENSE_FAULT_MSK(0); | |
489 | ||
490 | reg_val = ltc2992_read_reg(st, LTC2992_SENSE_FAULT(channel), 1); | |
491 | if (reg_val < 0) | |
492 | return reg_val; | |
493 | ||
494 | *val = !!(reg_val & mask); | |
495 | reg_val &= ~mask; | |
496 | ||
497 | return ltc2992_write_reg(st, LTC2992_SENSE_FAULT(channel), 1, reg_val); | |
498 | } | |
499 | ||
500 | static int ltc2992_read_in(struct device *dev, u32 attr, int channel, long *val) | |
501 | { | |
502 | struct ltc2992_state *st = dev_get_drvdata(dev); | |
503 | u32 reg; | |
504 | ||
505 | if (channel > 1) | |
506 | return ltc2992_read_gpios_in(dev, attr, channel - 2, val); | |
507 | ||
508 | switch (attr) { | |
509 | case hwmon_in_input: | |
510 | reg = LTC2992_SENSE(channel); | |
511 | break; | |
512 | case hwmon_in_lowest: | |
513 | reg = LTC2992_SENSE_MIN(channel); | |
514 | break; | |
515 | case hwmon_in_highest: | |
516 | reg = LTC2992_SENSE_MAX(channel); | |
517 | break; | |
518 | case hwmon_in_min: | |
519 | reg = LTC2992_SENSE_MIN_THRESH(channel); | |
520 | break; | |
521 | case hwmon_in_max: | |
522 | reg = LTC2992_SENSE_MAX_THRESH(channel); | |
523 | break; | |
524 | case hwmon_in_min_alarm: | |
525 | case hwmon_in_max_alarm: | |
526 | return ltc2992_read_in_alarm(st, channel, val, attr); | |
527 | default: | |
528 | return -EOPNOTSUPP; | |
529 | } | |
530 | ||
531 | return ltc2992_get_voltage(st, reg, LTC2992_VADC_UV_LSB, val); | |
532 | } | |
533 | ||
534 | static int ltc2992_get_current(struct ltc2992_state *st, u32 reg, u32 channel, long *val) | |
535 | { | |
e1d15969 | 536 | int reg_val; |
b0bd407e AT |
537 | |
538 | reg_val = ltc2992_read_reg(st, reg, 2); | |
539 | if (reg_val < 0) | |
540 | return reg_val; | |
541 | ||
542 | reg_val = reg_val >> 4; | |
543 | *val = DIV_ROUND_CLOSEST(reg_val * LTC2992_IADC_NANOV_LSB, st->r_sense_uohm[channel]); | |
544 | ||
545 | return 0; | |
546 | } | |
547 | ||
548 | static int ltc2992_set_current(struct ltc2992_state *st, u32 reg, u32 channel, long val) | |
549 | { | |
550 | u32 reg_val; | |
551 | ||
552 | reg_val = DIV_ROUND_CLOSEST(val * st->r_sense_uohm[channel], LTC2992_IADC_NANOV_LSB); | |
553 | reg_val = reg_val << 4; | |
554 | ||
555 | return ltc2992_write_reg(st, reg, 2, reg_val); | |
556 | } | |
557 | ||
558 | static int ltc2992_read_curr_alarm(struct ltc2992_state *st, int channel, long *val, u32 attr) | |
559 | { | |
e1d15969 | 560 | int reg_val; |
b0bd407e AT |
561 | u32 mask; |
562 | ||
563 | if (attr == hwmon_curr_max_alarm) | |
564 | mask = LTC2992_DSENSE_FAULT_MSK(1); | |
565 | else | |
566 | mask = LTC2992_DSENSE_FAULT_MSK(0); | |
567 | ||
568 | reg_val = ltc2992_read_reg(st, LTC2992_DSENSE_FAULT(channel), 1); | |
569 | if (reg_val < 0) | |
570 | return reg_val; | |
571 | ||
572 | *val = !!(reg_val & mask); | |
573 | ||
574 | reg_val &= ~mask; | |
575 | return ltc2992_write_reg(st, LTC2992_DSENSE_FAULT(channel), 1, reg_val); | |
576 | } | |
577 | ||
578 | static int ltc2992_read_curr(struct device *dev, u32 attr, int channel, long *val) | |
579 | { | |
580 | struct ltc2992_state *st = dev_get_drvdata(dev); | |
581 | u32 reg; | |
582 | ||
583 | switch (attr) { | |
584 | case hwmon_curr_input: | |
585 | reg = LTC2992_DSENSE(channel); | |
586 | break; | |
587 | case hwmon_curr_lowest: | |
588 | reg = LTC2992_DSENSE_MIN(channel); | |
589 | break; | |
590 | case hwmon_curr_highest: | |
591 | reg = LTC2992_DSENSE_MAX(channel); | |
592 | break; | |
593 | case hwmon_curr_min: | |
594 | reg = LTC2992_DSENSE_MIN_THRESH(channel); | |
595 | break; | |
596 | case hwmon_curr_max: | |
597 | reg = LTC2992_DSENSE_MAX_THRESH(channel); | |
598 | break; | |
599 | case hwmon_curr_min_alarm: | |
600 | case hwmon_curr_max_alarm: | |
601 | return ltc2992_read_curr_alarm(st, channel, val, attr); | |
602 | default: | |
603 | return -EOPNOTSUPP; | |
604 | } | |
605 | ||
606 | return ltc2992_get_current(st, reg, channel, val); | |
607 | } | |
608 | ||
609 | static int ltc2992_get_power(struct ltc2992_state *st, u32 reg, u32 channel, long *val) | |
610 | { | |
e1d15969 | 611 | int reg_val; |
b0bd407e AT |
612 | |
613 | reg_val = ltc2992_read_reg(st, reg, 3); | |
614 | if (reg_val < 0) | |
615 | return reg_val; | |
616 | ||
617 | *val = mul_u64_u32_div(reg_val, LTC2992_VADC_UV_LSB * LTC2992_IADC_NANOV_LSB, | |
618 | st->r_sense_uohm[channel] * 1000); | |
619 | ||
620 | return 0; | |
621 | } | |
622 | ||
623 | static int ltc2992_set_power(struct ltc2992_state *st, u32 reg, u32 channel, long val) | |
624 | { | |
625 | u32 reg_val; | |
626 | ||
627 | reg_val = mul_u64_u32_div(val, st->r_sense_uohm[channel] * 1000, | |
628 | LTC2992_VADC_UV_LSB * LTC2992_IADC_NANOV_LSB); | |
629 | ||
630 | return ltc2992_write_reg(st, reg, 3, reg_val); | |
631 | } | |
632 | ||
633 | static int ltc2992_read_power_alarm(struct ltc2992_state *st, int channel, long *val, u32 attr) | |
634 | { | |
e1d15969 | 635 | int reg_val; |
b0bd407e AT |
636 | u32 mask; |
637 | ||
638 | if (attr == hwmon_power_max_alarm) | |
639 | mask = LTC2992_POWER_FAULT_MSK(1); | |
640 | else | |
641 | mask = LTC2992_POWER_FAULT_MSK(0); | |
642 | ||
643 | reg_val = ltc2992_read_reg(st, LTC2992_POWER_FAULT(channel), 1); | |
644 | if (reg_val < 0) | |
645 | return reg_val; | |
646 | ||
647 | *val = !!(reg_val & mask); | |
648 | reg_val &= ~mask; | |
649 | ||
650 | return ltc2992_write_reg(st, LTC2992_POWER_FAULT(channel), 1, reg_val); | |
651 | } | |
652 | ||
653 | static int ltc2992_read_power(struct device *dev, u32 attr, int channel, long *val) | |
654 | { | |
655 | struct ltc2992_state *st = dev_get_drvdata(dev); | |
656 | u32 reg; | |
657 | ||
658 | switch (attr) { | |
659 | case hwmon_power_input: | |
660 | reg = LTC2992_POWER(channel); | |
661 | break; | |
662 | case hwmon_power_input_lowest: | |
663 | reg = LTC2992_POWER_MIN(channel); | |
664 | break; | |
665 | case hwmon_power_input_highest: | |
666 | reg = LTC2992_POWER_MAX(channel); | |
667 | break; | |
668 | case hwmon_power_min: | |
669 | reg = LTC2992_POWER_MIN_THRESH(channel); | |
670 | break; | |
671 | case hwmon_power_max: | |
672 | reg = LTC2992_POWER_MAX_THRESH(channel); | |
673 | break; | |
674 | case hwmon_power_min_alarm: | |
675 | case hwmon_power_max_alarm: | |
676 | return ltc2992_read_power_alarm(st, channel, val, attr); | |
677 | default: | |
678 | return -EOPNOTSUPP; | |
679 | } | |
680 | ||
681 | return ltc2992_get_power(st, reg, channel, val); | |
682 | } | |
683 | ||
684 | static int ltc2992_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, | |
685 | long *val) | |
686 | { | |
687 | switch (type) { | |
688 | case hwmon_in: | |
689 | return ltc2992_read_in(dev, attr, channel, val); | |
690 | case hwmon_curr: | |
691 | return ltc2992_read_curr(dev, attr, channel, val); | |
692 | case hwmon_power: | |
693 | return ltc2992_read_power(dev, attr, channel, val); | |
694 | default: | |
695 | return -EOPNOTSUPP; | |
696 | } | |
697 | } | |
698 | ||
699 | static int ltc2992_write_curr(struct device *dev, u32 attr, int channel, long val) | |
700 | { | |
701 | struct ltc2992_state *st = dev_get_drvdata(dev); | |
702 | u32 reg; | |
703 | ||
704 | switch (attr) { | |
705 | case hwmon_curr_min: | |
706 | reg = LTC2992_DSENSE_MIN_THRESH(channel); | |
707 | break; | |
708 | case hwmon_curr_max: | |
709 | reg = LTC2992_DSENSE_MAX_THRESH(channel); | |
710 | break; | |
711 | default: | |
712 | return -EOPNOTSUPP; | |
713 | } | |
714 | ||
715 | return ltc2992_set_current(st, reg, channel, val); | |
716 | } | |
717 | ||
718 | static int ltc2992_write_gpios_in(struct device *dev, u32 attr, int nr_gpio, long val) | |
719 | { | |
720 | struct ltc2992_state *st = dev_get_drvdata(dev); | |
721 | u32 reg; | |
722 | ||
723 | switch (attr) { | |
724 | case hwmon_in_min: | |
725 | reg = ltc2992_gpio_addr_map[nr_gpio].min_thresh; | |
726 | break; | |
727 | case hwmon_in_max: | |
728 | reg = ltc2992_gpio_addr_map[nr_gpio].max_thresh; | |
729 | break; | |
730 | default: | |
731 | return -EOPNOTSUPP; | |
732 | } | |
733 | ||
734 | return ltc2992_set_voltage(st, reg, LTC2992_VADC_GPIO_UV_LSB, val); | |
735 | } | |
736 | ||
737 | static int ltc2992_write_in(struct device *dev, u32 attr, int channel, long val) | |
738 | { | |
739 | struct ltc2992_state *st = dev_get_drvdata(dev); | |
740 | u32 reg; | |
741 | ||
742 | if (channel > 1) | |
743 | return ltc2992_write_gpios_in(dev, attr, channel - 2, val); | |
744 | ||
745 | switch (attr) { | |
746 | case hwmon_in_min: | |
747 | reg = LTC2992_SENSE_MIN_THRESH(channel); | |
748 | break; | |
749 | case hwmon_in_max: | |
750 | reg = LTC2992_SENSE_MAX_THRESH(channel); | |
751 | break; | |
752 | default: | |
753 | return -EOPNOTSUPP; | |
754 | } | |
755 | ||
756 | return ltc2992_set_voltage(st, reg, LTC2992_VADC_UV_LSB, val); | |
757 | } | |
758 | ||
759 | static int ltc2992_write_power(struct device *dev, u32 attr, int channel, long val) | |
760 | { | |
761 | struct ltc2992_state *st = dev_get_drvdata(dev); | |
762 | u32 reg; | |
763 | ||
764 | switch (attr) { | |
765 | case hwmon_power_min: | |
766 | reg = LTC2992_POWER_MIN_THRESH(channel); | |
767 | break; | |
768 | case hwmon_power_max: | |
769 | reg = LTC2992_POWER_MAX_THRESH(channel); | |
770 | break; | |
771 | default: | |
772 | return -EOPNOTSUPP; | |
773 | } | |
774 | ||
775 | return ltc2992_set_power(st, reg, channel, val); | |
776 | } | |
777 | ||
778 | static int ltc2992_write_chip(struct device *dev, u32 attr, int channel, long val) | |
779 | { | |
780 | struct ltc2992_state *st = dev_get_drvdata(dev); | |
781 | ||
782 | switch (attr) { | |
783 | case hwmon_chip_in_reset_history: | |
784 | return regmap_update_bits(st->regmap, LTC2992_CTRLB, LTC2992_RESET_HISTORY, | |
785 | LTC2992_RESET_HISTORY); | |
786 | default: | |
787 | return -EOPNOTSUPP; | |
788 | } | |
789 | } | |
790 | ||
791 | static int ltc2992_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, | |
792 | long val) | |
793 | { | |
794 | switch (type) { | |
795 | case hwmon_chip: | |
796 | return ltc2992_write_chip(dev, attr, channel, val); | |
797 | case hwmon_in: | |
798 | return ltc2992_write_in(dev, attr, channel, val); | |
799 | case hwmon_curr: | |
800 | return ltc2992_write_curr(dev, attr, channel, val); | |
801 | case hwmon_power: | |
802 | return ltc2992_write_power(dev, attr, channel, val); | |
803 | default: | |
804 | return -EOPNOTSUPP; | |
805 | } | |
806 | } | |
807 | ||
808 | static const struct hwmon_ops ltc2992_hwmon_ops = { | |
809 | .is_visible = ltc2992_is_visible, | |
810 | .read = ltc2992_read, | |
811 | .write = ltc2992_write, | |
812 | }; | |
813 | ||
814 | static const u32 ltc2992_chip_config[] = { | |
815 | HWMON_C_IN_RESET_HISTORY, | |
816 | 0 | |
817 | }; | |
818 | ||
819 | static const struct hwmon_channel_info ltc2992_chip = { | |
820 | .type = hwmon_chip, | |
821 | .config = ltc2992_chip_config, | |
822 | }; | |
823 | ||
824 | static const u32 ltc2992_in_config[] = { | |
825 | HWMON_I_INPUT | HWMON_I_LOWEST | HWMON_I_HIGHEST | HWMON_I_MIN | HWMON_I_MAX | | |
826 | HWMON_I_MIN_ALARM | HWMON_I_MAX_ALARM, | |
827 | HWMON_I_INPUT | HWMON_I_LOWEST | HWMON_I_HIGHEST | HWMON_I_MIN | HWMON_I_MAX | | |
828 | HWMON_I_MIN_ALARM | HWMON_I_MAX_ALARM, | |
829 | HWMON_I_INPUT | HWMON_I_LOWEST | HWMON_I_HIGHEST | HWMON_I_MIN | HWMON_I_MAX | | |
830 | HWMON_I_MIN_ALARM | HWMON_I_MAX_ALARM, | |
831 | HWMON_I_INPUT | HWMON_I_LOWEST | HWMON_I_HIGHEST | HWMON_I_MIN | HWMON_I_MAX | | |
832 | HWMON_I_MIN_ALARM | HWMON_I_MAX_ALARM, | |
833 | HWMON_I_INPUT | HWMON_I_LOWEST | HWMON_I_HIGHEST | HWMON_I_MIN | HWMON_I_MAX | | |
834 | HWMON_I_MIN_ALARM | HWMON_I_MAX_ALARM, | |
835 | HWMON_I_INPUT | HWMON_I_LOWEST | HWMON_I_HIGHEST | HWMON_I_MIN | HWMON_I_MAX | | |
836 | HWMON_I_MIN_ALARM | HWMON_I_MAX_ALARM, | |
837 | 0 | |
838 | }; | |
839 | ||
840 | static const struct hwmon_channel_info ltc2992_in = { | |
841 | .type = hwmon_in, | |
842 | .config = ltc2992_in_config, | |
843 | }; | |
844 | ||
845 | static const u32 ltc2992_curr_config[] = { | |
846 | HWMON_C_INPUT | HWMON_C_LOWEST | HWMON_C_HIGHEST | HWMON_C_MIN | HWMON_C_MAX | | |
847 | HWMON_C_MIN_ALARM | HWMON_C_MAX_ALARM, | |
848 | HWMON_C_INPUT | HWMON_C_LOWEST | HWMON_C_HIGHEST | HWMON_C_MIN | HWMON_C_MAX | | |
849 | HWMON_C_MIN_ALARM | HWMON_C_MAX_ALARM, | |
850 | 0 | |
851 | }; | |
852 | ||
853 | static const struct hwmon_channel_info ltc2992_curr = { | |
854 | .type = hwmon_curr, | |
855 | .config = ltc2992_curr_config, | |
856 | }; | |
857 | ||
858 | static const u32 ltc2992_power_config[] = { | |
859 | HWMON_P_INPUT | HWMON_P_INPUT_LOWEST | HWMON_P_INPUT_HIGHEST | HWMON_P_MIN | HWMON_P_MAX | | |
860 | HWMON_P_MIN_ALARM | HWMON_P_MAX_ALARM, | |
861 | HWMON_P_INPUT | HWMON_P_INPUT_LOWEST | HWMON_P_INPUT_HIGHEST | HWMON_P_MIN | HWMON_P_MAX | | |
862 | HWMON_P_MIN_ALARM | HWMON_P_MAX_ALARM, | |
863 | 0 | |
864 | }; | |
865 | ||
866 | static const struct hwmon_channel_info ltc2992_power = { | |
867 | .type = hwmon_power, | |
868 | .config = ltc2992_power_config, | |
869 | }; | |
870 | ||
871 | static const struct hwmon_channel_info *ltc2992_info[] = { | |
872 | <c2992_chip, | |
873 | <c2992_in, | |
874 | <c2992_curr, | |
875 | <c2992_power, | |
876 | NULL | |
877 | }; | |
878 | ||
879 | static const struct hwmon_chip_info ltc2992_chip_info = { | |
880 | .ops = <c2992_hwmon_ops, | |
881 | .info = ltc2992_info, | |
882 | }; | |
883 | ||
884 | static const struct regmap_config ltc2992_regmap_config = { | |
885 | .reg_bits = 8, | |
886 | .val_bits = 8, | |
887 | .max_register = 0xE8, | |
888 | }; | |
889 | ||
890 | static int ltc2992_parse_dt(struct ltc2992_state *st) | |
891 | { | |
892 | struct fwnode_handle *fwnode; | |
893 | struct fwnode_handle *child; | |
894 | u32 addr; | |
895 | u32 val; | |
896 | int ret; | |
897 | ||
898 | fwnode = dev_fwnode(&st->client->dev); | |
899 | ||
900 | fwnode_for_each_available_child_node(fwnode, child) { | |
901 | ret = fwnode_property_read_u32(child, "reg", &addr); | |
8370e5b0 AS |
902 | if (ret < 0) { |
903 | fwnode_handle_put(child); | |
b0bd407e | 904 | return ret; |
8370e5b0 | 905 | } |
b0bd407e | 906 | |
8370e5b0 AS |
907 | if (addr > 1) { |
908 | fwnode_handle_put(child); | |
b0bd407e | 909 | return -EINVAL; |
8370e5b0 | 910 | } |
b0bd407e AT |
911 | |
912 | ret = fwnode_property_read_u32(child, "shunt-resistor-micro-ohms", &val); | |
913 | if (!ret) | |
914 | st->r_sense_uohm[addr] = val; | |
915 | } | |
916 | ||
917 | return 0; | |
918 | } | |
919 | ||
920 | static int ltc2992_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) | |
921 | { | |
922 | struct device *hwmon_dev; | |
923 | struct ltc2992_state *st; | |
924 | int ret; | |
925 | ||
926 | st = devm_kzalloc(&client->dev, sizeof(*st), GFP_KERNEL); | |
927 | if (!st) | |
928 | return -ENOMEM; | |
929 | ||
930 | st->client = client; | |
931 | st->regmap = devm_regmap_init_i2c(client, <c2992_regmap_config); | |
932 | if (IS_ERR(st->regmap)) | |
933 | return PTR_ERR(st->regmap); | |
934 | ||
935 | ret = ltc2992_parse_dt(st); | |
936 | if (ret < 0) | |
937 | return ret; | |
938 | ||
9ca26df1 AT |
939 | ret = ltc2992_config_gpio(st); |
940 | if (ret < 0) | |
941 | return ret; | |
942 | ||
b0bd407e AT |
943 | hwmon_dev = devm_hwmon_device_register_with_info(&client->dev, client->name, st, |
944 | <c2992_chip_info, NULL); | |
945 | ||
946 | return PTR_ERR_OR_ZERO(hwmon_dev); | |
947 | } | |
948 | ||
949 | static const struct of_device_id ltc2992_of_match[] = { | |
950 | { .compatible = "adi,ltc2992" }, | |
951 | { } | |
952 | }; | |
953 | MODULE_DEVICE_TABLE(of, ltc2992_of_match); | |
954 | ||
955 | static const struct i2c_device_id ltc2992_i2c_id[] = { | |
956 | {"ltc2992", 0}, | |
957 | {} | |
958 | }; | |
959 | MODULE_DEVICE_TABLE(i2c, ltc2992_i2c_id); | |
960 | ||
961 | static struct i2c_driver ltc2992_i2c_driver = { | |
962 | .driver = { | |
963 | .name = "ltc2992", | |
964 | .of_match_table = ltc2992_of_match, | |
965 | }, | |
966 | .probe = ltc2992_i2c_probe, | |
967 | .id_table = ltc2992_i2c_id, | |
968 | }; | |
969 | ||
970 | module_i2c_driver(ltc2992_i2c_driver); | |
971 | ||
972 | MODULE_AUTHOR("Alexandru Tachici <alexandru.tachici@analog.com>"); | |
973 | MODULE_DESCRIPTION("Hwmon driver for Linear Technology 2992"); | |
974 | MODULE_LICENSE("Dual BSD/GPL"); |