1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * INA3221 Triple Current/Voltage Monitor
4 *
5 * Copyright (C) 2016 Texas Instruments Incorporated - https://www.ti.com/
6 * Andrew F. Davis <afd@ti.com>
7 */
8
9#include <linux/debugfs.h>
10#include <linux/hwmon.h>
11#include <linux/hwmon-sysfs.h>
12#include <linux/i2c.h>
13#include <linux/module.h>
14#include <linux/mutex.h>
15#include <linux/of.h>
16#include <linux/pm_runtime.h>
17#include <linux/regmap.h>
18#include <linux/util_macros.h>
19
20#define INA3221_DRIVER_NAME "ina3221"
21
22#define INA3221_CONFIG 0x00
23#define INA3221_SHUNT1 0x01
24#define INA3221_BUS1 0x02
25#define INA3221_SHUNT2 0x03
26#define INA3221_BUS2 0x04
27#define INA3221_SHUNT3 0x05
28#define INA3221_BUS3 0x06
29#define INA3221_CRIT1 0x07
30#define INA3221_WARN1 0x08
31#define INA3221_CRIT2 0x09
32#define INA3221_WARN2 0x0a
33#define INA3221_CRIT3 0x0b
34#define INA3221_WARN3 0x0c
35#define INA3221_SHUNT_SUM 0x0d
36#define INA3221_CRIT_SUM 0x0e
37#define INA3221_MASK_ENABLE 0x0f
38
39#define INA3221_CONFIG_MODE_MASK GENMASK(2, 0)
40#define INA3221_CONFIG_MODE_POWERDOWN 0
41#define INA3221_CONFIG_MODE_SHUNT BIT(0)
42#define INA3221_CONFIG_MODE_BUS BIT(1)
43#define INA3221_CONFIG_MODE_CONTINUOUS BIT(2)
44#define INA3221_CONFIG_VSH_CT_SHIFT 3
45#define INA3221_CONFIG_VSH_CT_MASK GENMASK(5, 3)
46#define INA3221_CONFIG_VSH_CT(x) (((x) & GENMASK(5, 3)) >> 3)
47#define INA3221_CONFIG_VBUS_CT_SHIFT 6
48#define INA3221_CONFIG_VBUS_CT_MASK GENMASK(8, 6)
49#define INA3221_CONFIG_VBUS_CT(x) (((x) & GENMASK(8, 6)) >> 6)
50#define INA3221_CONFIG_AVG_SHIFT 9
51#define INA3221_CONFIG_AVG_MASK GENMASK(11, 9)
52#define INA3221_CONFIG_AVG(x) (((x) & GENMASK(11, 9)) >> 9)
53#define INA3221_CONFIG_CHs_EN_MASK GENMASK(14, 12)
54#define INA3221_CONFIG_CHx_EN(x) BIT(14 - (x))
55
56#define INA3221_MASK_ENABLE_SCC_MASK GENMASK(14, 12)
57
58#define INA3221_CONFIG_DEFAULT 0x7127
59#define INA3221_RSHUNT_DEFAULT 10000
60
61enum ina3221_fields {
62 /* Configuration */
63 F_RST,
64
65 /* Status Flags */
66 F_CVRF,
67
68 /* Warning Flags */
69 F_WF3, F_WF2, F_WF1,
70
71 /* Alert Flags: SF is the summation-alert flag */
72 F_SF, F_CF3, F_CF2, F_CF1,
73
74 /* sentinel */
75 F_MAX_FIELDS
76};
77
78static const struct reg_field ina3221_reg_fields[] = {
79 [F_RST] = REG_FIELD(INA3221_CONFIG, 15, 15),
80
81 [F_CVRF] = REG_FIELD(INA3221_MASK_ENABLE, 0, 0),
82 [F_WF3] = REG_FIELD(INA3221_MASK_ENABLE, 3, 3),
83 [F_WF2] = REG_FIELD(INA3221_MASK_ENABLE, 4, 4),
84 [F_WF1] = REG_FIELD(INA3221_MASK_ENABLE, 5, 5),
85 [F_SF] = REG_FIELD(INA3221_MASK_ENABLE, 6, 6),
86 [F_CF3] = REG_FIELD(INA3221_MASK_ENABLE, 7, 7),
87 [F_CF2] = REG_FIELD(INA3221_MASK_ENABLE, 8, 8),
88 [F_CF1] = REG_FIELD(INA3221_MASK_ENABLE, 9, 9),
89};
90
91enum ina3221_channels {
92 INA3221_CHANNEL1,
93 INA3221_CHANNEL2,
94 INA3221_CHANNEL3,
95 INA3221_NUM_CHANNELS
96};
97
98/**
99 * struct ina3221_input - channel input source specific information
100 * @label: label of channel input source
101 * @shunt_resistor: shunt resistor value of channel input source
102 * @disconnected: connection status of channel input source
103 * @summation_disable: channel summation status of input source
104 */
105struct ina3221_input {
106 const char *label;
107 int shunt_resistor;
108 bool disconnected;
109 bool summation_disable;
110};
111
112/**
113 * struct ina3221_data - device specific information
114 * @pm_dev: Device pointer for pm runtime
115 * @regmap: Register map of the device
116 * @fields: Register fields of the device
117 * @inputs: Array of channel input source specific structures
118 * @lock: mutex lock to serialize sysfs attribute accesses
119 * @reg_config: Register value of INA3221_CONFIG
120 * @summation_shunt_resistor: equivalent shunt resistor value for summation
121 * @summation_channel_control: Value written to SCC field in INA3221_MASK_ENABLE
122 * @single_shot: running in single-shot operating mode
123 */
124struct ina3221_data {
125 struct device *pm_dev;
126 struct regmap *regmap;
127 struct regmap_field *fields[F_MAX_FIELDS];
128 struct ina3221_input inputs[INA3221_NUM_CHANNELS];
129 struct mutex lock;
130 u32 reg_config;
131 int summation_shunt_resistor;
132 u32 summation_channel_control;
133
134 bool single_shot;
135};
136
137static inline bool ina3221_is_enabled(struct ina3221_data *ina, int channel)
138{
139 /* Summation channel checks shunt resistor values */
140 if (channel > INA3221_CHANNEL3)
141 return ina->summation_shunt_resistor != 0;
142
143 return pm_runtime_active(dev: ina->pm_dev) &&
144 (ina->reg_config & INA3221_CONFIG_CHx_EN(channel));
145}
146
147/*
148 * Helper function to return the resistor value for current summation.
149 *
150 * There is a condition to calculate current summation -- all the shunt
151 * resistor values should be the same, so as to simply fit the formula:
152 * current summation = shunt voltage summation / shunt resistor
153 *
154 * Returns the equivalent shunt resistor value on success or 0 on failure
155 */
156static inline int ina3221_summation_shunt_resistor(struct ina3221_data *ina)
157{
158 struct ina3221_input *input = ina->inputs;
159 int i, shunt_resistor = 0;
160
161 for (i = 0; i < INA3221_NUM_CHANNELS; i++) {
162 if (input[i].disconnected || !input[i].shunt_resistor ||
163 input[i].summation_disable)
164 continue;
165 if (!shunt_resistor) {
166 /* Found the reference shunt resistor value */
167 shunt_resistor = input[i].shunt_resistor;
168 } else {
169 /* No summation if resistor values are different */
170 if (shunt_resistor != input[i].shunt_resistor)
171 return 0;
172 }
173 }
174
175 return shunt_resistor;
176}
177
178/* Lookup table for Bus and Shunt conversion times in usec */
179static const u16 ina3221_conv_time[] = {
180 140, 204, 332, 588, 1100, 2116, 4156, 8244,
181};
182
183/* Lookup table for number of samples using in averaging mode */
184static const int ina3221_avg_samples[] = {
185 1, 4, 16, 64, 128, 256, 512, 1024,
186};
187
188/* Converting update_interval in msec to conversion time in usec */
189static inline u32 ina3221_interval_ms_to_conv_time(u16 config, int interval)
190{
191 u32 channels = hweight16(config & INA3221_CONFIG_CHs_EN_MASK);
192 u32 samples_idx = INA3221_CONFIG_AVG(config);
193 u32 samples = ina3221_avg_samples[samples_idx];
194
195 /* Bisect the result to Bus and Shunt conversion times */
196 return DIV_ROUND_CLOSEST(interval * 1000 / 2, channels * samples);
197}
198
199/* Converting CONFIG register value to update_interval in usec */
200static inline u32 ina3221_reg_to_interval_us(u16 config)
201{
202 u32 channels = hweight16(config & INA3221_CONFIG_CHs_EN_MASK);
203 u32 vbus_ct_idx = INA3221_CONFIG_VBUS_CT(config);
204 u32 vsh_ct_idx = INA3221_CONFIG_VSH_CT(config);
205 u32 vbus_ct = ina3221_conv_time[vbus_ct_idx];
206 u32 vsh_ct = ina3221_conv_time[vsh_ct_idx];
207
208 /* Calculate total conversion time */
209 return channels * (vbus_ct + vsh_ct);
210}
211
212static inline int ina3221_wait_for_data(struct ina3221_data *ina)
213{
214 u32 wait, cvrf;
215
216 wait = ina3221_reg_to_interval_us(config: ina->reg_config);
217
218 /* Polling the CVRF bit to make sure read data is ready */
219 return regmap_field_read_poll_timeout(ina->fields[F_CVRF],
220 cvrf, cvrf, wait, wait * 2);
221}
222
223static int ina3221_read_value(struct ina3221_data *ina, unsigned int reg,
224 int *val)
225{
226 unsigned int regval;
227 int ret;
228
229 ret = regmap_read(map: ina->regmap, reg, val: &regval);
230 if (ret)
231 return ret;
232
233 /*
234 * Shunt Voltage Sum register has 14-bit value with 1-bit shift
235 * Other Shunt Voltage registers have 12 bits with 3-bit shift
236 */
237 if (reg == INA3221_SHUNT_SUM || reg == INA3221_CRIT_SUM)
238 *val = sign_extend32(value: regval >> 1, index: 14);
239 else
240 *val = sign_extend32(value: regval >> 3, index: 12);
241
242 return 0;
243}
244
245static const u8 ina3221_in_reg[] = {
246 INA3221_BUS1,
247 INA3221_BUS2,
248 INA3221_BUS3,
249 INA3221_SHUNT1,
250 INA3221_SHUNT2,
251 INA3221_SHUNT3,
252 INA3221_SHUNT_SUM,
253};
254
255static int ina3221_read_chip(struct device *dev, u32 attr, long *val)
256{
257 struct ina3221_data *ina = dev_get_drvdata(dev);
258 int regval;
259
260 switch (attr) {
261 case hwmon_chip_samples:
262 regval = INA3221_CONFIG_AVG(ina->reg_config);
263 *val = ina3221_avg_samples[regval];
264 return 0;
265 case hwmon_chip_update_interval:
266 /* Return in msec */
267 *val = ina3221_reg_to_interval_us(config: ina->reg_config);
268 *val = DIV_ROUND_CLOSEST(*val, 1000);
269 return 0;
270 default:
271 return -EOPNOTSUPP;
272 }
273}
274
275static int ina3221_read_in(struct device *dev, u32 attr, int channel, long *val)
276{
277 const bool is_shunt = channel > INA3221_CHANNEL3;
278 struct ina3221_data *ina = dev_get_drvdata(dev);
279 u8 reg = ina3221_in_reg[channel];
280 int regval, ret;
281
282 /*
283 * Translate shunt channel index to sensor channel index except
284 * the 7th channel (6 since being 0-aligned) is for summation.
285 */
286 if (channel != 6)
287 channel %= INA3221_NUM_CHANNELS;
288
289 switch (attr) {
290 case hwmon_in_input:
291 if (!ina3221_is_enabled(ina, channel))
292 return -ENODATA;
293
294 /* Write CONFIG register to trigger a single-shot measurement */
295 if (ina->single_shot) {
296 regmap_write(map: ina->regmap, INA3221_CONFIG,
297 val: ina->reg_config);
298
299 ret = ina3221_wait_for_data(ina);
300 if (ret)
301 return ret;
302 }
303
304 ret = ina3221_read_value(ina, reg, val: &regval);
305 if (ret)
306 return ret;
307
308 /*
309 * Scale of shunt voltage (uV): LSB is 40uV
310 * Scale of bus voltage (mV): LSB is 8mV
311 */
312 *val = regval * (is_shunt ? 40 : 8);
313 return 0;
314 case hwmon_in_enable:
315 *val = ina3221_is_enabled(ina, channel);
316 return 0;
317 default:
318 return -EOPNOTSUPP;
319 }
320}
321
322static const u8 ina3221_curr_reg[][INA3221_NUM_CHANNELS + 1] = {
323 [hwmon_curr_input] = { INA3221_SHUNT1, INA3221_SHUNT2,
324 INA3221_SHUNT3, INA3221_SHUNT_SUM },
325 [hwmon_curr_max] = { INA3221_WARN1, INA3221_WARN2, INA3221_WARN3, 0 },
326 [hwmon_curr_crit] = { INA3221_CRIT1, INA3221_CRIT2,
327 INA3221_CRIT3, INA3221_CRIT_SUM },
328 [hwmon_curr_max_alarm] = { F_WF1, F_WF2, F_WF3, 0 },
329 [hwmon_curr_crit_alarm] = { F_CF1, F_CF2, F_CF3, F_SF },
330};
331
332static int ina3221_read_curr(struct device *dev, u32 attr,
333 int channel, long *val)
334{
335 struct ina3221_data *ina = dev_get_drvdata(dev);
336 struct ina3221_input *input = ina->inputs;
337 u8 reg = ina3221_curr_reg[attr][channel];
338 int resistance_uo, voltage_nv;
339 int regval, ret;
340
341 if (channel > INA3221_CHANNEL3)
342 resistance_uo = ina->summation_shunt_resistor;
343 else
344 resistance_uo = input[channel].shunt_resistor;
345
346 switch (attr) {
347 case hwmon_curr_input:
348 if (!ina3221_is_enabled(ina, channel))
349 return -ENODATA;
350
351 /* Write CONFIG register to trigger a single-shot measurement */
352 if (ina->single_shot) {
353 regmap_write(map: ina->regmap, INA3221_CONFIG,
354 val: ina->reg_config);
355
356 ret = ina3221_wait_for_data(ina);
357 if (ret)
358 return ret;
359 }
360
361 fallthrough;
362 case hwmon_curr_crit:
363 case hwmon_curr_max:
364 if (!resistance_uo)
365 return -ENODATA;
366
367 ret = ina3221_read_value(ina, reg, val: &regval);
368 if (ret)
369 return ret;
370
371 /* Scale of shunt voltage: LSB is 40uV (40000nV) */
372 voltage_nv = regval * 40000;
373 /* Return current in mA */
374 *val = DIV_ROUND_CLOSEST(voltage_nv, resistance_uo);
375 return 0;
376 case hwmon_curr_crit_alarm:
377 case hwmon_curr_max_alarm:
378 /* No actual register read if channel is disabled */
379 if (!ina3221_is_enabled(ina, channel)) {
380 /* Return 0 for alert flags */
381 *val = 0;
382 return 0;
383 }
384 ret = regmap_field_read(field: ina->fields[reg], val: &regval);
385 if (ret)
386 return ret;
387 *val = regval;
388 return 0;
389 default:
390 return -EOPNOTSUPP;
391 }
392}
393
394static int ina3221_write_chip(struct device *dev, u32 attr, long val)
395{
396 struct ina3221_data *ina = dev_get_drvdata(dev);
397 int ret, idx;
398 u32 tmp;
399
400 switch (attr) {
401 case hwmon_chip_samples:
402 idx = find_closest(val, ina3221_avg_samples,
403 ARRAY_SIZE(ina3221_avg_samples));
404
405 tmp = (ina->reg_config & ~INA3221_CONFIG_AVG_MASK) |
406 (idx << INA3221_CONFIG_AVG_SHIFT);
407 ret = regmap_write(map: ina->regmap, INA3221_CONFIG, val: tmp);
408 if (ret)
409 return ret;
410
411 /* Update reg_config accordingly */
412 ina->reg_config = tmp;
413 return 0;
414 case hwmon_chip_update_interval:
415 tmp = ina3221_interval_ms_to_conv_time(config: ina->reg_config, interval: val);
416 idx = find_closest(tmp, ina3221_conv_time,
417 ARRAY_SIZE(ina3221_conv_time));
418
419 /* Update Bus and Shunt voltage conversion times */
420 tmp = INA3221_CONFIG_VBUS_CT_MASK | INA3221_CONFIG_VSH_CT_MASK;
421 tmp = (ina->reg_config & ~tmp) |
422 (idx << INA3221_CONFIG_VBUS_CT_SHIFT) |
423 (idx << INA3221_CONFIG_VSH_CT_SHIFT);
424 ret = regmap_write(map: ina->regmap, INA3221_CONFIG, val: tmp);
425 if (ret)
426 return ret;
427
428 /* Update reg_config accordingly */
429 ina->reg_config = tmp;
430 return 0;
431 default:
432 return -EOPNOTSUPP;
433 }
434}
435
436static int ina3221_write_curr(struct device *dev, u32 attr,
437 int channel, long val)
438{
439 struct ina3221_data *ina = dev_get_drvdata(dev);
440 struct ina3221_input *input = ina->inputs;
441 u8 reg = ina3221_curr_reg[attr][channel];
442 int resistance_uo, current_ma, voltage_uv;
443 int regval;
444
445 if (channel > INA3221_CHANNEL3)
446 resistance_uo = ina->summation_shunt_resistor;
447 else
448 resistance_uo = input[channel].shunt_resistor;
449
450 if (!resistance_uo)
451 return -EOPNOTSUPP;
452
453 /* clamp current */
454 current_ma = clamp_val(val,
455 INT_MIN / resistance_uo,
456 INT_MAX / resistance_uo);
457
458 voltage_uv = DIV_ROUND_CLOSEST(current_ma * resistance_uo, 1000);
459
460 /* clamp voltage */
461 voltage_uv = clamp_val(voltage_uv, -163800, 163800);
462
463 /*
464 * Formula to convert voltage_uv to register value:
465 * regval = (voltage_uv / scale) << shift
466 * Note:
467 * The scale is 40uV for all shunt voltage registers
468 * Shunt Voltage Sum register left-shifts 1 bit
469 * All other Shunt Voltage registers shift 3 bits
470 * Results:
471 * SHUNT_SUM: (1 / 40uV) << 1 = 1 / 20uV
472 * SHUNT[1-3]: (1 / 40uV) << 3 = 1 / 5uV
473 */
474 if (reg == INA3221_SHUNT_SUM || reg == INA3221_CRIT_SUM)
475 regval = DIV_ROUND_CLOSEST(voltage_uv, 20) & 0xfffe;
476 else
477 regval = DIV_ROUND_CLOSEST(voltage_uv, 5) & 0xfff8;
478
479 return regmap_write(map: ina->regmap, reg, val: regval);
480}
481
482static int ina3221_write_enable(struct device *dev, int channel, bool enable)
483{
484 struct ina3221_data *ina = dev_get_drvdata(dev);
485 u16 config, mask = INA3221_CONFIG_CHx_EN(channel);
486 u16 config_old = ina->reg_config & mask;
487 u32 tmp;
488 int ret;
489
490 config = enable ? mask : 0;
491
492 /* Bypass if enable status is not being changed */
493 if (config_old == config)
494 return 0;
495
496 /* For enabling routine, increase refcount and resume() at first */
497 if (enable) {
498 ret = pm_runtime_resume_and_get(dev: ina->pm_dev);
499 if (ret < 0) {
500 dev_err(dev, "Failed to get PM runtime\n");
501 return ret;
502 }
503 }
504
505 /* Enable or disable the channel */
506 tmp = (ina->reg_config & ~mask) | (config & mask);
507 ret = regmap_write(map: ina->regmap, INA3221_CONFIG, val: tmp);
508 if (ret)
509 goto fail;
510
511 /* Cache the latest config register value */
512 ina->reg_config = tmp;
513
514 /* For disabling routine, decrease refcount or suspend() at last */
515 if (!enable)
516 pm_runtime_put_sync(dev: ina->pm_dev);
517
518 return 0;
519
520fail:
521 if (enable) {
522 dev_err(dev, "Failed to enable channel %d: error %d\n",
523 channel, ret);
524 pm_runtime_put_sync(dev: ina->pm_dev);
525 }
526
527 return ret;
528}
529
530static int ina3221_read(struct device *dev, enum hwmon_sensor_types type,
531 u32 attr, int channel, long *val)
532{
533 struct ina3221_data *ina = dev_get_drvdata(dev);
534 int ret;
535
536 mutex_lock(&ina->lock);
537
538 switch (type) {
539 case hwmon_chip:
540 ret = ina3221_read_chip(dev, attr, val);
541 break;
542 case hwmon_in:
543 /* 0-align channel ID */
544 ret = ina3221_read_in(dev, attr, channel: channel - 1, val);
545 break;
546 case hwmon_curr:
547 ret = ina3221_read_curr(dev, attr, channel, val);
548 break;
549 default:
550 ret = -EOPNOTSUPP;
551 break;
552 }
553
554 mutex_unlock(lock: &ina->lock);
555
556 return ret;
557}
558
559static int ina3221_write(struct device *dev, enum hwmon_sensor_types type,
560 u32 attr, int channel, long val)
561{
562 struct ina3221_data *ina = dev_get_drvdata(dev);
563 int ret;
564
565 mutex_lock(&ina->lock);
566
567 switch (type) {
568 case hwmon_chip:
569 ret = ina3221_write_chip(dev, attr, val);
570 break;
571 case hwmon_in:
572 /* 0-align channel ID */
573 ret = ina3221_write_enable(dev, channel: channel - 1, enable: val);
574 break;
575 case hwmon_curr:
576 ret = ina3221_write_curr(dev, attr, channel, val);
577 break;
578 default:
579 ret = -EOPNOTSUPP;
580 break;
581 }
582
583 mutex_unlock(lock: &ina->lock);
584
585 return ret;
586}
587
588static int ina3221_read_string(struct device *dev, enum hwmon_sensor_types type,
589 u32 attr, int channel, const char **str)
590{
591 struct ina3221_data *ina = dev_get_drvdata(dev);
592 int index = channel - 1;
593
594 if (channel == 7)
595 *str = "sum of shunt voltages";
596 else
597 *str = ina->inputs[index].label;
598
599 return 0;
600}
601
602static umode_t ina3221_is_visible(const void *drvdata,
603 enum hwmon_sensor_types type,
604 u32 attr, int channel)
605{
606 const struct ina3221_data *ina = drvdata;
607 const struct ina3221_input *input = NULL;
608
609 switch (type) {
610 case hwmon_chip:
611 switch (attr) {
612 case hwmon_chip_samples:
613 case hwmon_chip_update_interval:
614 return 0644;
615 default:
616 return 0;
617 }
618 case hwmon_in:
619 /* Ignore in0_ */
620 if (channel == 0)
621 return 0;
622
623 switch (attr) {
624 case hwmon_in_label:
625 if (channel - 1 <= INA3221_CHANNEL3)
626 input = &ina->inputs[channel - 1];
627 else if (channel == 7)
628 return 0444;
629 /* Hide label node if label is not provided */
630 return (input && input->label) ? 0444 : 0;
631 case hwmon_in_input:
632 return 0444;
633 case hwmon_in_enable:
634 return 0644;
635 default:
636 return 0;
637 }
638 case hwmon_curr:
639 switch (attr) {
640 case hwmon_curr_input:
641 case hwmon_curr_crit_alarm:
642 case hwmon_curr_max_alarm:
643 return 0444;
644 case hwmon_curr_crit:
645 case hwmon_curr_max:
646 return 0644;
647 default:
648 return 0;
649 }
650 default:
651 return 0;
652 }
653}
654
655#define INA3221_HWMON_CURR_CONFIG (HWMON_C_INPUT | \
656 HWMON_C_CRIT | HWMON_C_CRIT_ALARM | \
657 HWMON_C_MAX | HWMON_C_MAX_ALARM)
658
659static const struct hwmon_channel_info * const ina3221_info[] = {
660 HWMON_CHANNEL_INFO(chip,
661 HWMON_C_SAMPLES,
662 HWMON_C_UPDATE_INTERVAL),
663 HWMON_CHANNEL_INFO(in,
664 /* 0: dummy, skipped in is_visible */
665 HWMON_I_INPUT,
666 /* 1-3: input voltage Channels */
667 HWMON_I_INPUT | HWMON_I_ENABLE | HWMON_I_LABEL,
668 HWMON_I_INPUT | HWMON_I_ENABLE | HWMON_I_LABEL,
669 HWMON_I_INPUT | HWMON_I_ENABLE | HWMON_I_LABEL,
670 /* 4-6: shunt voltage Channels */
671 HWMON_I_INPUT,
672 HWMON_I_INPUT,
673 HWMON_I_INPUT,
674 /* 7: summation of shunt voltage channels */
675 HWMON_I_INPUT | HWMON_I_LABEL),
676 HWMON_CHANNEL_INFO(curr,
677 /* 1-3: current channels*/
678 INA3221_HWMON_CURR_CONFIG,
679 INA3221_HWMON_CURR_CONFIG,
680 INA3221_HWMON_CURR_CONFIG,
681 /* 4: summation of current channels */
682 HWMON_C_INPUT | HWMON_C_CRIT | HWMON_C_CRIT_ALARM),
683 NULL
684};
685
686static const struct hwmon_ops ina3221_hwmon_ops = {
687 .is_visible = ina3221_is_visible,
688 .read_string = ina3221_read_string,
689 .read = ina3221_read,
690 .write = ina3221_write,
691};
692
693static const struct hwmon_chip_info ina3221_chip_info = {
694 .ops = &ina3221_hwmon_ops,
695 .info = ina3221_info,
696};
697
698/* Extra attribute groups */
699static ssize_t ina3221_shunt_show(struct device *dev,
700 struct device_attribute *attr, char *buf)
701{
702 struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr);
703 struct ina3221_data *ina = dev_get_drvdata(dev);
704 unsigned int channel = sd_attr->index;
705 struct ina3221_input *input = &ina->inputs[channel];
706
707 return sysfs_emit(buf, fmt: "%d\n", input->shunt_resistor);
708}
709
710static ssize_t ina3221_shunt_store(struct device *dev,
711 struct device_attribute *attr,
712 const char *buf, size_t count)
713{
714 struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr);
715 struct ina3221_data *ina = dev_get_drvdata(dev);
716 unsigned int channel = sd_attr->index;
717 struct ina3221_input *input = &ina->inputs[channel];
718 int val;
719 int ret;
720
721 ret = kstrtoint(s: buf, base: 0, res: &val);
722 if (ret)
723 return ret;
724
725 val = clamp_val(val, 1, INT_MAX);
726
727 input->shunt_resistor = val;
728
729 /* Update summation_shunt_resistor for summation channel */
730 ina->summation_shunt_resistor = ina3221_summation_shunt_resistor(ina);
731
732 return count;
733}
734
735/* shunt resistance */
736static SENSOR_DEVICE_ATTR_RW(shunt1_resistor, ina3221_shunt, INA3221_CHANNEL1);
737static SENSOR_DEVICE_ATTR_RW(shunt2_resistor, ina3221_shunt, INA3221_CHANNEL2);
738static SENSOR_DEVICE_ATTR_RW(shunt3_resistor, ina3221_shunt, INA3221_CHANNEL3);
739
740static struct attribute *ina3221_attrs[] = {
741 &sensor_dev_attr_shunt1_resistor.dev_attr.attr,
742 &sensor_dev_attr_shunt2_resistor.dev_attr.attr,
743 &sensor_dev_attr_shunt3_resistor.dev_attr.attr,
744 NULL,
745};
746ATTRIBUTE_GROUPS(ina3221);
747
748static const struct regmap_range ina3221_yes_ranges[] = {
749 regmap_reg_range(INA3221_CONFIG, INA3221_BUS3),
750 regmap_reg_range(INA3221_SHUNT_SUM, INA3221_SHUNT_SUM),
751 regmap_reg_range(INA3221_MASK_ENABLE, INA3221_MASK_ENABLE),
752};
753
754static const struct regmap_access_table ina3221_volatile_table = {
755 .yes_ranges = ina3221_yes_ranges,
756 .n_yes_ranges = ARRAY_SIZE(ina3221_yes_ranges),
757};
758
759static const struct regmap_config ina3221_regmap_config = {
760 .reg_bits = 8,
761 .val_bits = 16,
762
763 .cache_type = REGCACHE_MAPLE,
764 .volatile_table = &ina3221_volatile_table,
765};
766
767static int ina3221_probe_child_from_dt(struct device *dev,
768 struct device_node *child,
769 struct ina3221_data *ina)
770{
771 struct ina3221_input *input;
772 u32 val;
773 int ret;
774
775 ret = of_property_read_u32(np: child, propname: "reg", out_value: &val);
776 if (ret) {
777 dev_err(dev, "missing reg property of %pOFn\n", child);
778 return ret;
779 } else if (val > INA3221_CHANNEL3) {
780 dev_err(dev, "invalid reg %d of %pOFn\n", val, child);
781 return -EINVAL;
782 }
783
784 input = &ina->inputs[val];
785
786 /* Log the disconnected channel input */
787 if (!of_device_is_available(device: child)) {
788 input->disconnected = true;
789 return 0;
790 }
791
792 /* Save the connected input label if available */
793 of_property_read_string(np: child, propname: "label", out_string: &input->label);
794
795 /* summation channel control */
796 input->summation_disable = of_property_read_bool(np: child, propname: "ti,summation-disable");
797
798 /* Overwrite default shunt resistor value optionally */
799 if (!of_property_read_u32(np: child, propname: "shunt-resistor-micro-ohms", out_value: &val)) {
800 if (val < 1 || val > INT_MAX) {
801 dev_err(dev, "invalid shunt resistor value %u of %pOFn\n",
802 val, child);
803 return -EINVAL;
804 }
805 input->shunt_resistor = val;
806 }
807
808 return 0;
809}
810
811static int ina3221_probe_from_dt(struct device *dev, struct ina3221_data *ina)
812{
813 const struct device_node *np = dev->of_node;
814 int ret;
815
816 /* Compatible with non-DT platforms */
817 if (!np)
818 return 0;
819
820 ina->single_shot = of_property_read_bool(np, propname: "ti,single-shot");
821
822 for_each_child_of_node_scoped(np, child) {
823 ret = ina3221_probe_child_from_dt(dev, child, ina);
824 if (ret)
825 return ret;
826 }
827
828 return 0;
829}
830
831static int ina3221_probe(struct i2c_client *client)
832{
833 struct device *dev = &client->dev;
834 struct ina3221_data *ina;
835 struct device *hwmon_dev;
836 char name[32];
837 int i, ret;
838
839 ina = devm_kzalloc(dev, size: sizeof(*ina), GFP_KERNEL);
840 if (!ina)
841 return -ENOMEM;
842
843 ina->regmap = devm_regmap_init_i2c(client, &ina3221_regmap_config);
844 if (IS_ERR(ptr: ina->regmap)) {
845 dev_err(dev, "Unable to allocate register map\n");
846 return PTR_ERR(ptr: ina->regmap);
847 }
848
849 for (i = 0; i < F_MAX_FIELDS; i++) {
850 ina->fields[i] = devm_regmap_field_alloc(dev,
851 regmap: ina->regmap,
852 reg_field: ina3221_reg_fields[i]);
853 if (IS_ERR(ptr: ina->fields[i])) {
854 dev_err(dev, "Unable to allocate regmap fields\n");
855 return PTR_ERR(ptr: ina->fields[i]);
856 }
857 }
858
859 for (i = 0; i < INA3221_NUM_CHANNELS; i++)
860 ina->inputs[i].shunt_resistor = INA3221_RSHUNT_DEFAULT;
861
862 ret = ina3221_probe_from_dt(dev, ina);
863 if (ret) {
864 dev_err(dev, "Unable to probe from device tree\n");
865 return ret;
866 }
867
868 /* The driver will be reset, so use reset value */
869 ina->reg_config = INA3221_CONFIG_DEFAULT;
870
871 /* Clear continuous bit to use single-shot mode */
872 if (ina->single_shot)
873 ina->reg_config &= ~INA3221_CONFIG_MODE_CONTINUOUS;
874
875 /* Disable channels if their inputs are disconnected */
876 for (i = 0; i < INA3221_NUM_CHANNELS; i++) {
877 if (ina->inputs[i].disconnected)
878 ina->reg_config &= ~INA3221_CONFIG_CHx_EN(i);
879 }
880
881 /* Initialize summation_shunt_resistor for summation channel control */
882 ina->summation_shunt_resistor = ina3221_summation_shunt_resistor(ina);
883 for (i = 0; i < INA3221_NUM_CHANNELS; i++) {
884 if (!ina->inputs[i].summation_disable)
885 ina->summation_channel_control |= BIT(14 - i);
886 }
887
888 ina->pm_dev = dev;
889 mutex_init(&ina->lock);
890 dev_set_drvdata(dev, data: ina);
891
892 /* Enable PM runtime -- status is suspended by default */
893 pm_runtime_enable(dev: ina->pm_dev);
894
895 /* Initialize (resume) the device */
896 for (i = 0; i < INA3221_NUM_CHANNELS; i++) {
897 if (ina->inputs[i].disconnected)
898 continue;
899 /* Match the refcount with number of enabled channels */
900 ret = pm_runtime_get_sync(dev: ina->pm_dev);
901 if (ret < 0)
902 goto fail;
903 }
904
905 hwmon_dev = devm_hwmon_device_register_with_info(dev, name: client->name, drvdata: ina,
906 info: &ina3221_chip_info,
907 extra_groups: ina3221_groups);
908 if (IS_ERR(ptr: hwmon_dev)) {
909 dev_err(dev, "Unable to register hwmon device\n");
910 ret = PTR_ERR(ptr: hwmon_dev);
911 goto fail;
912 }
913
914 for (i = 0; i < INA3221_NUM_CHANNELS; i++) {
915 scnprintf(buf: name, size: sizeof(name), fmt: "in%d_summation_disable", i);
916 debugfs_create_bool(name, mode: 0400, parent: client->debugfs,
917 value: &ina->inputs[i].summation_disable);
918 }
919
920 return 0;
921
922fail:
923 pm_runtime_disable(dev: ina->pm_dev);
924 pm_runtime_set_suspended(dev: ina->pm_dev);
925 /* pm_runtime_put_noidle() will decrease the PM refcount until 0 */
926 for (i = 0; i < INA3221_NUM_CHANNELS; i++)
927 pm_runtime_put_noidle(dev: ina->pm_dev);
928 mutex_destroy(lock: &ina->lock);
929
930 return ret;
931}
932
933static void ina3221_remove(struct i2c_client *client)
934{
935 struct ina3221_data *ina = dev_get_drvdata(dev: &client->dev);
936 int i;
937
938 pm_runtime_disable(dev: ina->pm_dev);
939 pm_runtime_set_suspended(dev: ina->pm_dev);
940
941 /* pm_runtime_put_noidle() will decrease the PM refcount until 0 */
942 for (i = 0; i < INA3221_NUM_CHANNELS; i++)
943 pm_runtime_put_noidle(dev: ina->pm_dev);
944
945 mutex_destroy(lock: &ina->lock);
946}
947
948static int ina3221_suspend(struct device *dev)
949{
950 struct ina3221_data *ina = dev_get_drvdata(dev);
951 int ret;
952
953 /* Save config register value and enable cache-only */
954 ret = regmap_read(map: ina->regmap, INA3221_CONFIG, val: &ina->reg_config);
955 if (ret)
956 return ret;
957
958 /* Set to power-down mode for power saving */
959 ret = regmap_update_bits(map: ina->regmap, INA3221_CONFIG,
960 INA3221_CONFIG_MODE_MASK,
961 INA3221_CONFIG_MODE_POWERDOWN);
962 if (ret)
963 return ret;
964
965 regcache_cache_only(map: ina->regmap, enable: true);
966 regcache_mark_dirty(map: ina->regmap);
967
968 return 0;
969}
970
971static int ina3221_resume(struct device *dev)
972{
973 struct ina3221_data *ina = dev_get_drvdata(dev);
974 int ret;
975
976 regcache_cache_only(map: ina->regmap, enable: false);
977
978 /* Software reset the chip */
979 ret = regmap_field_write(field: ina->fields[F_RST], val: true);
980 if (ret) {
981 dev_err(dev, "Unable to reset device\n");
982 return ret;
983 }
984
985 /* Restore cached register values to hardware */
986 ret = regcache_sync(map: ina->regmap);
987 if (ret)
988 return ret;
989
990 /* Restore config register value to hardware */
991 ret = regmap_write(map: ina->regmap, INA3221_CONFIG, val: ina->reg_config);
992 if (ret)
993 return ret;
994
995 /* Initialize summation channel control */
996 if (ina->summation_shunt_resistor) {
997 /*
998 * Sum only channels that are not disabled for summation.
999 * Shunt measurements of disconnected channels should
1000 * be 0, so it does not matter for summation.
1001 */
1002 ret = regmap_update_bits(map: ina->regmap, INA3221_MASK_ENABLE,
1003 INA3221_MASK_ENABLE_SCC_MASK,
1004 val: ina->summation_channel_control);
1005 if (ret) {
1006 dev_err(dev, "Unable to control summation channel\n");
1007 return ret;
1008 }
1009 }
1010
1011 return 0;
1012}
1013
1014static DEFINE_RUNTIME_DEV_PM_OPS(ina3221_pm, ina3221_suspend, ina3221_resume,
1015 NULL);
1016
1017static const struct of_device_id ina3221_of_match_table[] = {
1018 { .compatible = "ti,ina3221", },
1019 { /* sentinel */ }
1020};
1021MODULE_DEVICE_TABLE(of, ina3221_of_match_table);
1022
1023static const struct i2c_device_id ina3221_ids[] = {
1024 { "ina3221" },
1025 { /* sentinel */ }
1026};
1027MODULE_DEVICE_TABLE(i2c, ina3221_ids);
1028
1029static struct i2c_driver ina3221_i2c_driver = {
1030 .probe = ina3221_probe,
1031 .remove = ina3221_remove,
1032 .driver = {
1033 .name = INA3221_DRIVER_NAME,
1034 .of_match_table = ina3221_of_match_table,
1035 .pm = pm_ptr(&ina3221_pm),
1036 },
1037 .id_table = ina3221_ids,
1038};
1039module_i2c_driver(ina3221_i2c_driver);
1040
1041MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>");
1042MODULE_DESCRIPTION("Texas Instruments INA3221 HWMon Driver");
1043MODULE_LICENSE("GPL v2");
1044

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of linux/drivers/hwmon/ina3221.c