Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

hwmon: (ltc2992) Add support

LTC2992 is a rail-to-rail system monitor that
measures current, voltage, and power of two supplies.

Two ADCs simultaneously measure each supply’s current.
A third ADC monitors the input voltages and four
auxiliary external voltages.

Signed-off-by: Alexandru Tachici <alexandru.tachici@analog.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>

authored by

Alexandru Tachici and committed by
Guenter Roeck
b0bd407e d014538a

+882
+1
Documentation/hwmon/index.rst
··· 101 101 lm95234 102 102 lm95245 103 103 lochnagar 104 + ltc2992 104 105 ltc2945 105 106 ltc2947 106 107 ltc2978
+56
Documentation/hwmon/ltc2992.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + 3 + Kernel driver ltc2992 4 + ===================== 5 + 6 + Supported chips: 7 + * Linear Technology LTC2992 8 + Prefix: 'ltc2992' 9 + Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ltc2992.pdf 10 + 11 + Author: Alexandru Tachici <alexandru.tachici@analog.com> 12 + 13 + 14 + Description 15 + ----------- 16 + 17 + This driver supports hardware monitoring for Linear Technology LTC2992 power monitor. 18 + 19 + LTC2992 is a rail-to-rail system monitor that measures current, 20 + voltage, and power of two supplies. 21 + 22 + Two ADCs simultaneously measure each supply’s current. A third ADC monitors 23 + the input voltages and four auxiliary external voltages. 24 + 25 + 26 + Sysfs entries 27 + ------------- 28 + 29 + The following attributes are supported. Limits are read-write, 30 + all other attributes are read-only. 31 + 32 + in_reset_history Reset all highest/lowest values. 33 + 34 + inX_input Measured voltage. 35 + inX_lowest Minimum measured voltage. 36 + inX_highest Maximum measured voltage. 37 + inX_min Minimum voltage allowed. 38 + inX_max Maximum voltage allowed. 39 + inX_min_alarm An undervoltage occurred. Cleared on read. 40 + inX_max_alarm An overvoltage occurred. Cleared on read. 41 + 42 + currX_input Measured current. 43 + currX_lowest Minimum measured current. 44 + currX_highest Maximum measured current. 45 + currX_min Minimum current allowed. 46 + currX_max Maximum current allowed. 47 + currX_min_alarm An undercurrent occurred. Cleared on read. 48 + currX_max_alarm An overcurrent occurred. Cleared on read. 49 + 50 + powerX_input Measured power. 51 + powerX_input_lowest Minimum measured voltage. 52 + powerX_input_highest Maximum measured voltage. 53 + powerX_min Minimum power. 54 + powerX_max Maximum power. 55 + powerX_min_alarm An underpower occurred. Cleared on read. 56 + powerX_max_alarm An overpower occurred. Cleared on read.
+11
drivers/hwmon/Kconfig
··· 871 871 This driver can also be built as a module. If so, the module will 872 872 be called ltc2990. 873 873 874 + config SENSORS_LTC2992 875 + tristate "Linear Technology LTC2992" 876 + depends on I2C 877 + help 878 + If you say yes here you get support for Linear Technology LTC2992 879 + I2C System Monitor. The LTC2992 measures current, voltage, and 880 + power of two supplies. 881 + 882 + This driver can also be built as a module. If so, the module will 883 + be called ltc2992. 884 + 874 885 config SENSORS_LTC4151 875 886 tristate "Linear Technology LTC4151" 876 887 depends on I2C
+1
drivers/hwmon/Makefile
··· 119 119 obj-$(CONFIG_SENSORS_LTC2947_I2C) += ltc2947-i2c.o 120 120 obj-$(CONFIG_SENSORS_LTC2947_SPI) += ltc2947-spi.o 121 121 obj-$(CONFIG_SENSORS_LTC2990) += ltc2990.o 122 + obj-$(CONFIG_SENSORS_LTC2992) += ltc2992.o 122 123 obj-$(CONFIG_SENSORS_LTC4151) += ltc4151.o 123 124 obj-$(CONFIG_SENSORS_LTC4215) += ltc4215.o 124 125 obj-$(CONFIG_SENSORS_LTC4222) += ltc4222.o
+813
drivers/hwmon/ltc2992.c
··· 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/hwmon.h> 12 + #include <linux/i2c.h> 13 + #include <linux/kernel.h> 14 + #include <linux/module.h> 15 + #include <linux/property.h> 16 + #include <linux/regmap.h> 17 + 18 + #define LTC2992_CTRLB 0x01 19 + #define LTC2992_FAULT1 0x03 20 + #define LTC2992_POWER1 0x05 21 + #define LTC2992_POWER1_MAX 0x08 22 + #define LTC2992_POWER1_MIN 0x0B 23 + #define LTC2992_POWER1_MAX_THRESH 0x0E 24 + #define LTC2992_POWER1_MIN_THRESH 0x11 25 + #define LTC2992_DSENSE1 0x14 26 + #define LTC2992_DSENSE1_MAX 0x16 27 + #define LTC2992_DSENSE1_MIN 0x18 28 + #define LTC2992_DSENSE1_MAX_THRESH 0x1A 29 + #define LTC2992_DSENSE1_MIN_THRESH 0x1C 30 + #define LTC2992_SENSE1 0x1E 31 + #define LTC2992_SENSE1_MAX 0x20 32 + #define LTC2992_SENSE1_MIN 0x22 33 + #define LTC2992_SENSE1_MAX_THRESH 0x24 34 + #define LTC2992_SENSE1_MIN_THRESH 0x26 35 + #define LTC2992_G1 0x28 36 + #define LTC2992_G1_MAX 0x2A 37 + #define LTC2992_G1_MIN 0x2C 38 + #define LTC2992_G1_MAX_THRESH 0x2E 39 + #define LTC2992_G1_MIN_THRESH 0x30 40 + #define LTC2992_FAULT2 0x35 41 + #define LTC2992_G2 0x5A 42 + #define LTC2992_G2_MAX 0x5C 43 + #define LTC2992_G2_MIN 0x5E 44 + #define LTC2992_G2_MAX_THRESH 0x60 45 + #define LTC2992_G2_MIN_THRESH 0x62 46 + #define LTC2992_G3 0x64 47 + #define LTC2992_G3_MAX 0x66 48 + #define LTC2992_G3_MIN 0x68 49 + #define LTC2992_G3_MAX_THRESH 0x6A 50 + #define LTC2992_G3_MIN_THRESH 0x6C 51 + #define LTC2992_G4 0x6E 52 + #define LTC2992_G4_MAX 0x70 53 + #define LTC2992_G4_MIN 0x72 54 + #define LTC2992_G4_MAX_THRESH 0x74 55 + #define LTC2992_G4_MIN_THRESH 0x76 56 + #define LTC2992_FAULT3 0x92 57 + 58 + #define LTC2992_POWER(x) (LTC2992_POWER1 + ((x) * 0x32)) 59 + #define LTC2992_POWER_MAX(x) (LTC2992_POWER1_MAX + ((x) * 0x32)) 60 + #define LTC2992_POWER_MIN(x) (LTC2992_POWER1_MIN + ((x) * 0x32)) 61 + #define LTC2992_POWER_MAX_THRESH(x) (LTC2992_POWER1_MAX_THRESH + ((x) * 0x32)) 62 + #define LTC2992_POWER_MIN_THRESH(x) (LTC2992_POWER1_MIN_THRESH + ((x) * 0x32)) 63 + #define LTC2992_DSENSE(x) (LTC2992_DSENSE1 + ((x) * 0x32)) 64 + #define LTC2992_DSENSE_MAX(x) (LTC2992_DSENSE1_MAX + ((x) * 0x32)) 65 + #define LTC2992_DSENSE_MIN(x) (LTC2992_DSENSE1_MIN + ((x) * 0x32)) 66 + #define LTC2992_DSENSE_MAX_THRESH(x) (LTC2992_DSENSE1_MAX_THRESH + ((x) * 0x32)) 67 + #define LTC2992_DSENSE_MIN_THRESH(x) (LTC2992_DSENSE1_MIN_THRESH + ((x) * 0x32)) 68 + #define LTC2992_SENSE(x) (LTC2992_SENSE1 + ((x) * 0x32)) 69 + #define LTC2992_SENSE_MAX(x) (LTC2992_SENSE1_MAX + ((x) * 0x32)) 70 + #define LTC2992_SENSE_MIN(x) (LTC2992_SENSE1_MIN + ((x) * 0x32)) 71 + #define LTC2992_SENSE_MAX_THRESH(x) (LTC2992_SENSE1_MAX_THRESH + ((x) * 0x32)) 72 + #define LTC2992_SENSE_MIN_THRESH(x) (LTC2992_SENSE1_MIN_THRESH + ((x) * 0x32)) 73 + #define LTC2992_POWER_FAULT(x) (LTC2992_FAULT1 + ((x) * 0x32)) 74 + #define LTC2992_SENSE_FAULT(x) (LTC2992_FAULT1 + ((x) * 0x32)) 75 + #define LTC2992_DSENSE_FAULT(x) (LTC2992_FAULT1 + ((x) * 0x32)) 76 + 77 + /* CTRLB register bitfields */ 78 + #define LTC2992_RESET_HISTORY BIT(3) 79 + 80 + /* FAULT1 FAULT2 registers common bitfields */ 81 + #define LTC2992_POWER_FAULT_MSK(x) (BIT(6) << (x)) 82 + #define LTC2992_DSENSE_FAULT_MSK(x) (BIT(4) << (x)) 83 + #define LTC2992_SENSE_FAULT_MSK(x) (BIT(2) << (x)) 84 + 85 + /* FAULT1 bitfields */ 86 + #define LTC2992_GPIO1_FAULT_MSK(x) (BIT(0) << (x)) 87 + 88 + /* FAULT2 bitfields */ 89 + #define LTC2992_GPIO2_FAULT_MSK(x) (BIT(0) << (x)) 90 + 91 + /* FAULT3 bitfields */ 92 + #define LTC2992_GPIO3_FAULT_MSK(x) (BIT(6) << (x)) 93 + #define LTC2992_GPIO4_FAULT_MSK(x) (BIT(4) << (x)) 94 + 95 + #define LTC2992_IADC_NANOV_LSB 12500 96 + #define LTC2992_VADC_UV_LSB 25000 97 + #define LTC2992_VADC_GPIO_UV_LSB 500 98 + 99 + struct ltc2992_state { 100 + struct i2c_client *client; 101 + struct regmap *regmap; 102 + u32 r_sense_uohm[2]; 103 + }; 104 + 105 + struct ltc2992_gpio_regs { 106 + u8 data; 107 + u8 max; 108 + u8 min; 109 + u8 max_thresh; 110 + u8 min_thresh; 111 + u8 alarm; 112 + u8 min_alarm_msk; 113 + u8 max_alarm_msk; 114 + }; 115 + 116 + static const struct ltc2992_gpio_regs ltc2992_gpio_addr_map[] = { 117 + { 118 + .data = LTC2992_G1, 119 + .max = LTC2992_G1_MAX, 120 + .min = LTC2992_G1_MIN, 121 + .max_thresh = LTC2992_G1_MAX_THRESH, 122 + .min_thresh = LTC2992_G1_MIN_THRESH, 123 + .alarm = LTC2992_FAULT1, 124 + .min_alarm_msk = LTC2992_GPIO1_FAULT_MSK(0), 125 + .max_alarm_msk = LTC2992_GPIO1_FAULT_MSK(1), 126 + }, 127 + { 128 + .data = LTC2992_G2, 129 + .max = LTC2992_G2_MAX, 130 + .min = LTC2992_G2_MIN, 131 + .max_thresh = LTC2992_G2_MAX_THRESH, 132 + .min_thresh = LTC2992_G2_MIN_THRESH, 133 + .alarm = LTC2992_FAULT2, 134 + .min_alarm_msk = LTC2992_GPIO2_FAULT_MSK(0), 135 + .max_alarm_msk = LTC2992_GPIO2_FAULT_MSK(1), 136 + }, 137 + { 138 + .data = LTC2992_G3, 139 + .max = LTC2992_G3_MAX, 140 + .min = LTC2992_G3_MIN, 141 + .max_thresh = LTC2992_G3_MAX_THRESH, 142 + .min_thresh = LTC2992_G3_MIN_THRESH, 143 + .alarm = LTC2992_FAULT3, 144 + .min_alarm_msk = LTC2992_GPIO3_FAULT_MSK(0), 145 + .max_alarm_msk = LTC2992_GPIO3_FAULT_MSK(1), 146 + }, 147 + { 148 + .data = LTC2992_G4, 149 + .max = LTC2992_G4_MAX, 150 + .min = LTC2992_G4_MIN, 151 + .max_thresh = LTC2992_G4_MAX_THRESH, 152 + .min_thresh = LTC2992_G4_MIN_THRESH, 153 + .alarm = LTC2992_FAULT3, 154 + .min_alarm_msk = LTC2992_GPIO4_FAULT_MSK(0), 155 + .max_alarm_msk = LTC2992_GPIO4_FAULT_MSK(1), 156 + }, 157 + }; 158 + 159 + static int ltc2992_read_reg(struct ltc2992_state *st, u8 addr, const u8 reg_len) 160 + { 161 + u8 regvals[4]; 162 + int ret; 163 + int val; 164 + int i; 165 + 166 + ret = regmap_bulk_read(st->regmap, addr, regvals, reg_len); 167 + if (ret < 0) 168 + return ret; 169 + 170 + val = 0; 171 + for (i = 0; i < reg_len; i++) 172 + val |= regvals[reg_len - i - 1] << (i * 8); 173 + 174 + return val; 175 + } 176 + 177 + static int ltc2992_write_reg(struct ltc2992_state *st, u8 addr, const u8 reg_len, u32 val) 178 + { 179 + u8 regvals[4]; 180 + int i; 181 + 182 + for (i = 0; i < reg_len; i++) 183 + regvals[reg_len - i - 1] = (val >> (i * 8)) & 0xFF; 184 + 185 + return regmap_bulk_write(st->regmap, addr, regvals, reg_len); 186 + } 187 + 188 + static umode_t ltc2992_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr, 189 + int channel) 190 + { 191 + const struct ltc2992_state *st = data; 192 + 193 + switch (type) { 194 + case hwmon_chip: 195 + switch (attr) { 196 + case hwmon_chip_in_reset_history: 197 + return 0200; 198 + } 199 + break; 200 + case hwmon_in: 201 + switch (attr) { 202 + case hwmon_in_input: 203 + case hwmon_in_lowest: 204 + case hwmon_in_highest: 205 + case hwmon_in_min_alarm: 206 + case hwmon_in_max_alarm: 207 + return 0444; 208 + case hwmon_in_min: 209 + case hwmon_in_max: 210 + return 0644; 211 + } 212 + break; 213 + case hwmon_curr: 214 + switch (attr) { 215 + case hwmon_curr_input: 216 + case hwmon_curr_lowest: 217 + case hwmon_curr_highest: 218 + case hwmon_curr_min_alarm: 219 + case hwmon_curr_max_alarm: 220 + if (st->r_sense_uohm[channel]) 221 + return 0444; 222 + break; 223 + case hwmon_curr_min: 224 + case hwmon_curr_max: 225 + if (st->r_sense_uohm[channel]) 226 + return 0644; 227 + break; 228 + } 229 + break; 230 + case hwmon_power: 231 + switch (attr) { 232 + case hwmon_power_input: 233 + case hwmon_power_input_lowest: 234 + case hwmon_power_input_highest: 235 + case hwmon_power_min_alarm: 236 + case hwmon_power_max_alarm: 237 + if (st->r_sense_uohm[channel]) 238 + return 0444; 239 + break; 240 + case hwmon_power_min: 241 + case hwmon_power_max: 242 + if (st->r_sense_uohm[channel]) 243 + return 0644; 244 + break; 245 + } 246 + break; 247 + default: 248 + break; 249 + } 250 + 251 + return 0; 252 + } 253 + 254 + static int ltc2992_get_voltage(struct ltc2992_state *st, u32 reg, u32 scale, long *val) 255 + { 256 + int reg_val; 257 + 258 + reg_val = ltc2992_read_reg(st, reg, 2); 259 + if (reg_val < 0) 260 + return reg_val; 261 + 262 + reg_val = reg_val >> 4; 263 + *val = DIV_ROUND_CLOSEST(reg_val * scale, 1000); 264 + 265 + return 0; 266 + } 267 + 268 + static int ltc2992_set_voltage(struct ltc2992_state *st, u32 reg, u32 scale, long val) 269 + { 270 + val = DIV_ROUND_CLOSEST(val * 1000, scale); 271 + val = val << 4; 272 + 273 + return ltc2992_write_reg(st, reg, 2, val); 274 + } 275 + 276 + static int ltc2992_read_gpio_alarm(struct ltc2992_state *st, int nr_gpio, u32 attr, long *val) 277 + { 278 + int reg_val; 279 + u32 mask; 280 + 281 + if (attr == hwmon_in_max_alarm) 282 + mask = ltc2992_gpio_addr_map[nr_gpio].max_alarm_msk; 283 + else 284 + mask = ltc2992_gpio_addr_map[nr_gpio].min_alarm_msk; 285 + 286 + reg_val = ltc2992_read_reg(st, ltc2992_gpio_addr_map[nr_gpio].alarm, 1); 287 + if (reg_val < 0) 288 + return reg_val; 289 + 290 + *val = !!(reg_val & mask); 291 + reg_val &= ~mask; 292 + 293 + return ltc2992_write_reg(st, ltc2992_gpio_addr_map[nr_gpio].alarm, 1, reg_val); 294 + } 295 + 296 + static int ltc2992_read_gpios_in(struct device *dev, u32 attr, int nr_gpio, long *val) 297 + { 298 + struct ltc2992_state *st = dev_get_drvdata(dev); 299 + u32 reg; 300 + 301 + switch (attr) { 302 + case hwmon_in_input: 303 + reg = ltc2992_gpio_addr_map[nr_gpio].data; 304 + break; 305 + case hwmon_in_lowest: 306 + reg = ltc2992_gpio_addr_map[nr_gpio].min; 307 + break; 308 + case hwmon_in_highest: 309 + reg = ltc2992_gpio_addr_map[nr_gpio].max; 310 + break; 311 + case hwmon_in_min: 312 + reg = ltc2992_gpio_addr_map[nr_gpio].min_thresh; 313 + break; 314 + case hwmon_in_max: 315 + reg = ltc2992_gpio_addr_map[nr_gpio].max_thresh; 316 + break; 317 + case hwmon_in_min_alarm: 318 + case hwmon_in_max_alarm: 319 + return ltc2992_read_gpio_alarm(st, nr_gpio, attr, val); 320 + default: 321 + return -EOPNOTSUPP; 322 + } 323 + 324 + return ltc2992_get_voltage(st, reg, LTC2992_VADC_GPIO_UV_LSB, val); 325 + } 326 + 327 + static int ltc2992_read_in_alarm(struct ltc2992_state *st, int channel, long *val, u32 attr) 328 + { 329 + u32 reg_val; 330 + u32 mask; 331 + 332 + if (attr == hwmon_in_max_alarm) 333 + mask = LTC2992_SENSE_FAULT_MSK(1); 334 + else 335 + mask = LTC2992_SENSE_FAULT_MSK(0); 336 + 337 + reg_val = ltc2992_read_reg(st, LTC2992_SENSE_FAULT(channel), 1); 338 + if (reg_val < 0) 339 + return reg_val; 340 + 341 + *val = !!(reg_val & mask); 342 + reg_val &= ~mask; 343 + 344 + return ltc2992_write_reg(st, LTC2992_SENSE_FAULT(channel), 1, reg_val); 345 + } 346 + 347 + static int ltc2992_read_in(struct device *dev, u32 attr, int channel, long *val) 348 + { 349 + struct ltc2992_state *st = dev_get_drvdata(dev); 350 + u32 reg; 351 + 352 + if (channel > 1) 353 + return ltc2992_read_gpios_in(dev, attr, channel - 2, val); 354 + 355 + switch (attr) { 356 + case hwmon_in_input: 357 + reg = LTC2992_SENSE(channel); 358 + break; 359 + case hwmon_in_lowest: 360 + reg = LTC2992_SENSE_MIN(channel); 361 + break; 362 + case hwmon_in_highest: 363 + reg = LTC2992_SENSE_MAX(channel); 364 + break; 365 + case hwmon_in_min: 366 + reg = LTC2992_SENSE_MIN_THRESH(channel); 367 + break; 368 + case hwmon_in_max: 369 + reg = LTC2992_SENSE_MAX_THRESH(channel); 370 + break; 371 + case hwmon_in_min_alarm: 372 + case hwmon_in_max_alarm: 373 + return ltc2992_read_in_alarm(st, channel, val, attr); 374 + default: 375 + return -EOPNOTSUPP; 376 + } 377 + 378 + return ltc2992_get_voltage(st, reg, LTC2992_VADC_UV_LSB, val); 379 + } 380 + 381 + static int ltc2992_get_current(struct ltc2992_state *st, u32 reg, u32 channel, long *val) 382 + { 383 + u32 reg_val; 384 + 385 + reg_val = ltc2992_read_reg(st, reg, 2); 386 + if (reg_val < 0) 387 + return reg_val; 388 + 389 + reg_val = reg_val >> 4; 390 + *val = DIV_ROUND_CLOSEST(reg_val * LTC2992_IADC_NANOV_LSB, st->r_sense_uohm[channel]); 391 + 392 + return 0; 393 + } 394 + 395 + static int ltc2992_set_current(struct ltc2992_state *st, u32 reg, u32 channel, long val) 396 + { 397 + u32 reg_val; 398 + 399 + reg_val = DIV_ROUND_CLOSEST(val * st->r_sense_uohm[channel], LTC2992_IADC_NANOV_LSB); 400 + reg_val = reg_val << 4; 401 + 402 + return ltc2992_write_reg(st, reg, 2, reg_val); 403 + } 404 + 405 + static int ltc2992_read_curr_alarm(struct ltc2992_state *st, int channel, long *val, u32 attr) 406 + { 407 + u32 reg_val; 408 + u32 mask; 409 + 410 + if (attr == hwmon_curr_max_alarm) 411 + mask = LTC2992_DSENSE_FAULT_MSK(1); 412 + else 413 + mask = LTC2992_DSENSE_FAULT_MSK(0); 414 + 415 + reg_val = ltc2992_read_reg(st, LTC2992_DSENSE_FAULT(channel), 1); 416 + if (reg_val < 0) 417 + return reg_val; 418 + 419 + *val = !!(reg_val & mask); 420 + 421 + reg_val &= ~mask; 422 + return ltc2992_write_reg(st, LTC2992_DSENSE_FAULT(channel), 1, reg_val); 423 + } 424 + 425 + static int ltc2992_read_curr(struct device *dev, u32 attr, int channel, long *val) 426 + { 427 + struct ltc2992_state *st = dev_get_drvdata(dev); 428 + u32 reg; 429 + 430 + switch (attr) { 431 + case hwmon_curr_input: 432 + reg = LTC2992_DSENSE(channel); 433 + break; 434 + case hwmon_curr_lowest: 435 + reg = LTC2992_DSENSE_MIN(channel); 436 + break; 437 + case hwmon_curr_highest: 438 + reg = LTC2992_DSENSE_MAX(channel); 439 + break; 440 + case hwmon_curr_min: 441 + reg = LTC2992_DSENSE_MIN_THRESH(channel); 442 + break; 443 + case hwmon_curr_max: 444 + reg = LTC2992_DSENSE_MAX_THRESH(channel); 445 + break; 446 + case hwmon_curr_min_alarm: 447 + case hwmon_curr_max_alarm: 448 + return ltc2992_read_curr_alarm(st, channel, val, attr); 449 + default: 450 + return -EOPNOTSUPP; 451 + } 452 + 453 + return ltc2992_get_current(st, reg, channel, val); 454 + } 455 + 456 + static int ltc2992_get_power(struct ltc2992_state *st, u32 reg, u32 channel, long *val) 457 + { 458 + u32 reg_val; 459 + 460 + reg_val = ltc2992_read_reg(st, reg, 3); 461 + if (reg_val < 0) 462 + return reg_val; 463 + 464 + *val = mul_u64_u32_div(reg_val, LTC2992_VADC_UV_LSB * LTC2992_IADC_NANOV_LSB, 465 + st->r_sense_uohm[channel] * 1000); 466 + 467 + return 0; 468 + } 469 + 470 + static int ltc2992_set_power(struct ltc2992_state *st, u32 reg, u32 channel, long val) 471 + { 472 + u32 reg_val; 473 + 474 + reg_val = mul_u64_u32_div(val, st->r_sense_uohm[channel] * 1000, 475 + LTC2992_VADC_UV_LSB * LTC2992_IADC_NANOV_LSB); 476 + 477 + return ltc2992_write_reg(st, reg, 3, reg_val); 478 + } 479 + 480 + static int ltc2992_read_power_alarm(struct ltc2992_state *st, int channel, long *val, u32 attr) 481 + { 482 + u32 reg_val; 483 + u32 mask; 484 + 485 + if (attr == hwmon_power_max_alarm) 486 + mask = LTC2992_POWER_FAULT_MSK(1); 487 + else 488 + mask = LTC2992_POWER_FAULT_MSK(0); 489 + 490 + reg_val = ltc2992_read_reg(st, LTC2992_POWER_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_POWER_FAULT(channel), 1, reg_val); 498 + } 499 + 500 + static int ltc2992_read_power(struct device *dev, u32 attr, int channel, long *val) 501 + { 502 + struct ltc2992_state *st = dev_get_drvdata(dev); 503 + u32 reg; 504 + 505 + switch (attr) { 506 + case hwmon_power_input: 507 + reg = LTC2992_POWER(channel); 508 + break; 509 + case hwmon_power_input_lowest: 510 + reg = LTC2992_POWER_MIN(channel); 511 + break; 512 + case hwmon_power_input_highest: 513 + reg = LTC2992_POWER_MAX(channel); 514 + break; 515 + case hwmon_power_min: 516 + reg = LTC2992_POWER_MIN_THRESH(channel); 517 + break; 518 + case hwmon_power_max: 519 + reg = LTC2992_POWER_MAX_THRESH(channel); 520 + break; 521 + case hwmon_power_min_alarm: 522 + case hwmon_power_max_alarm: 523 + return ltc2992_read_power_alarm(st, channel, val, attr); 524 + default: 525 + return -EOPNOTSUPP; 526 + } 527 + 528 + return ltc2992_get_power(st, reg, channel, val); 529 + } 530 + 531 + static int ltc2992_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, 532 + long *val) 533 + { 534 + switch (type) { 535 + case hwmon_in: 536 + return ltc2992_read_in(dev, attr, channel, val); 537 + case hwmon_curr: 538 + return ltc2992_read_curr(dev, attr, channel, val); 539 + case hwmon_power: 540 + return ltc2992_read_power(dev, attr, channel, val); 541 + default: 542 + return -EOPNOTSUPP; 543 + } 544 + } 545 + 546 + static int ltc2992_write_curr(struct device *dev, u32 attr, int channel, long val) 547 + { 548 + struct ltc2992_state *st = dev_get_drvdata(dev); 549 + u32 reg; 550 + 551 + switch (attr) { 552 + case hwmon_curr_min: 553 + reg = LTC2992_DSENSE_MIN_THRESH(channel); 554 + break; 555 + case hwmon_curr_max: 556 + reg = LTC2992_DSENSE_MAX_THRESH(channel); 557 + break; 558 + default: 559 + return -EOPNOTSUPP; 560 + } 561 + 562 + return ltc2992_set_current(st, reg, channel, val); 563 + } 564 + 565 + static int ltc2992_write_gpios_in(struct device *dev, u32 attr, int nr_gpio, long val) 566 + { 567 + struct ltc2992_state *st = dev_get_drvdata(dev); 568 + u32 reg; 569 + 570 + switch (attr) { 571 + case hwmon_in_min: 572 + reg = ltc2992_gpio_addr_map[nr_gpio].min_thresh; 573 + break; 574 + case hwmon_in_max: 575 + reg = ltc2992_gpio_addr_map[nr_gpio].max_thresh; 576 + break; 577 + default: 578 + return -EOPNOTSUPP; 579 + } 580 + 581 + return ltc2992_set_voltage(st, reg, LTC2992_VADC_GPIO_UV_LSB, val); 582 + } 583 + 584 + static int ltc2992_write_in(struct device *dev, u32 attr, int channel, long val) 585 + { 586 + struct ltc2992_state *st = dev_get_drvdata(dev); 587 + u32 reg; 588 + 589 + if (channel > 1) 590 + return ltc2992_write_gpios_in(dev, attr, channel - 2, val); 591 + 592 + switch (attr) { 593 + case hwmon_in_min: 594 + reg = LTC2992_SENSE_MIN_THRESH(channel); 595 + break; 596 + case hwmon_in_max: 597 + reg = LTC2992_SENSE_MAX_THRESH(channel); 598 + break; 599 + default: 600 + return -EOPNOTSUPP; 601 + } 602 + 603 + return ltc2992_set_voltage(st, reg, LTC2992_VADC_UV_LSB, val); 604 + } 605 + 606 + static int ltc2992_write_power(struct device *dev, u32 attr, int channel, long val) 607 + { 608 + struct ltc2992_state *st = dev_get_drvdata(dev); 609 + u32 reg; 610 + 611 + switch (attr) { 612 + case hwmon_power_min: 613 + reg = LTC2992_POWER_MIN_THRESH(channel); 614 + break; 615 + case hwmon_power_max: 616 + reg = LTC2992_POWER_MAX_THRESH(channel); 617 + break; 618 + default: 619 + return -EOPNOTSUPP; 620 + } 621 + 622 + return ltc2992_set_power(st, reg, channel, val); 623 + } 624 + 625 + static int ltc2992_write_chip(struct device *dev, u32 attr, int channel, long val) 626 + { 627 + struct ltc2992_state *st = dev_get_drvdata(dev); 628 + 629 + switch (attr) { 630 + case hwmon_chip_in_reset_history: 631 + return regmap_update_bits(st->regmap, LTC2992_CTRLB, LTC2992_RESET_HISTORY, 632 + LTC2992_RESET_HISTORY); 633 + default: 634 + return -EOPNOTSUPP; 635 + } 636 + } 637 + 638 + static int ltc2992_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, 639 + long val) 640 + { 641 + switch (type) { 642 + case hwmon_chip: 643 + return ltc2992_write_chip(dev, attr, channel, val); 644 + case hwmon_in: 645 + return ltc2992_write_in(dev, attr, channel, val); 646 + case hwmon_curr: 647 + return ltc2992_write_curr(dev, attr, channel, val); 648 + case hwmon_power: 649 + return ltc2992_write_power(dev, attr, channel, val); 650 + default: 651 + return -EOPNOTSUPP; 652 + } 653 + } 654 + 655 + static const struct hwmon_ops ltc2992_hwmon_ops = { 656 + .is_visible = ltc2992_is_visible, 657 + .read = ltc2992_read, 658 + .write = ltc2992_write, 659 + }; 660 + 661 + static const u32 ltc2992_chip_config[] = { 662 + HWMON_C_IN_RESET_HISTORY, 663 + 0 664 + }; 665 + 666 + static const struct hwmon_channel_info ltc2992_chip = { 667 + .type = hwmon_chip, 668 + .config = ltc2992_chip_config, 669 + }; 670 + 671 + static const u32 ltc2992_in_config[] = { 672 + HWMON_I_INPUT | HWMON_I_LOWEST | HWMON_I_HIGHEST | HWMON_I_MIN | HWMON_I_MAX | 673 + HWMON_I_MIN_ALARM | HWMON_I_MAX_ALARM, 674 + HWMON_I_INPUT | HWMON_I_LOWEST | HWMON_I_HIGHEST | HWMON_I_MIN | HWMON_I_MAX | 675 + HWMON_I_MIN_ALARM | HWMON_I_MAX_ALARM, 676 + HWMON_I_INPUT | HWMON_I_LOWEST | HWMON_I_HIGHEST | HWMON_I_MIN | HWMON_I_MAX | 677 + HWMON_I_MIN_ALARM | HWMON_I_MAX_ALARM, 678 + HWMON_I_INPUT | HWMON_I_LOWEST | HWMON_I_HIGHEST | HWMON_I_MIN | HWMON_I_MAX | 679 + HWMON_I_MIN_ALARM | HWMON_I_MAX_ALARM, 680 + HWMON_I_INPUT | HWMON_I_LOWEST | HWMON_I_HIGHEST | HWMON_I_MIN | HWMON_I_MAX | 681 + HWMON_I_MIN_ALARM | HWMON_I_MAX_ALARM, 682 + HWMON_I_INPUT | HWMON_I_LOWEST | HWMON_I_HIGHEST | HWMON_I_MIN | HWMON_I_MAX | 683 + HWMON_I_MIN_ALARM | HWMON_I_MAX_ALARM, 684 + 0 685 + }; 686 + 687 + static const struct hwmon_channel_info ltc2992_in = { 688 + .type = hwmon_in, 689 + .config = ltc2992_in_config, 690 + }; 691 + 692 + static const u32 ltc2992_curr_config[] = { 693 + HWMON_C_INPUT | HWMON_C_LOWEST | HWMON_C_HIGHEST | HWMON_C_MIN | HWMON_C_MAX | 694 + HWMON_C_MIN_ALARM | HWMON_C_MAX_ALARM, 695 + HWMON_C_INPUT | HWMON_C_LOWEST | HWMON_C_HIGHEST | HWMON_C_MIN | HWMON_C_MAX | 696 + HWMON_C_MIN_ALARM | HWMON_C_MAX_ALARM, 697 + 0 698 + }; 699 + 700 + static const struct hwmon_channel_info ltc2992_curr = { 701 + .type = hwmon_curr, 702 + .config = ltc2992_curr_config, 703 + }; 704 + 705 + static const u32 ltc2992_power_config[] = { 706 + HWMON_P_INPUT | HWMON_P_INPUT_LOWEST | HWMON_P_INPUT_HIGHEST | HWMON_P_MIN | HWMON_P_MAX | 707 + HWMON_P_MIN_ALARM | HWMON_P_MAX_ALARM, 708 + HWMON_P_INPUT | HWMON_P_INPUT_LOWEST | HWMON_P_INPUT_HIGHEST | HWMON_P_MIN | HWMON_P_MAX | 709 + HWMON_P_MIN_ALARM | HWMON_P_MAX_ALARM, 710 + 0 711 + }; 712 + 713 + static const struct hwmon_channel_info ltc2992_power = { 714 + .type = hwmon_power, 715 + .config = ltc2992_power_config, 716 + }; 717 + 718 + static const struct hwmon_channel_info *ltc2992_info[] = { 719 + &ltc2992_chip, 720 + &ltc2992_in, 721 + &ltc2992_curr, 722 + &ltc2992_power, 723 + NULL 724 + }; 725 + 726 + static const struct hwmon_chip_info ltc2992_chip_info = { 727 + .ops = &ltc2992_hwmon_ops, 728 + .info = ltc2992_info, 729 + }; 730 + 731 + static const struct regmap_config ltc2992_regmap_config = { 732 + .reg_bits = 8, 733 + .val_bits = 8, 734 + .max_register = 0xE8, 735 + }; 736 + 737 + static int ltc2992_parse_dt(struct ltc2992_state *st) 738 + { 739 + struct fwnode_handle *fwnode; 740 + struct fwnode_handle *child; 741 + u32 addr; 742 + u32 val; 743 + int ret; 744 + 745 + fwnode = dev_fwnode(&st->client->dev); 746 + 747 + fwnode_for_each_available_child_node(fwnode, child) { 748 + ret = fwnode_property_read_u32(child, "reg", &addr); 749 + if (ret < 0) 750 + return ret; 751 + 752 + if (addr > 1) 753 + return -EINVAL; 754 + 755 + ret = fwnode_property_read_u32(child, "shunt-resistor-micro-ohms", &val); 756 + if (!ret) 757 + st->r_sense_uohm[addr] = val; 758 + } 759 + 760 + return 0; 761 + } 762 + 763 + static int ltc2992_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) 764 + { 765 + struct device *hwmon_dev; 766 + struct ltc2992_state *st; 767 + int ret; 768 + 769 + st = devm_kzalloc(&client->dev, sizeof(*st), GFP_KERNEL); 770 + if (!st) 771 + return -ENOMEM; 772 + 773 + st->client = client; 774 + st->regmap = devm_regmap_init_i2c(client, &ltc2992_regmap_config); 775 + if (IS_ERR(st->regmap)) 776 + return PTR_ERR(st->regmap); 777 + 778 + ret = ltc2992_parse_dt(st); 779 + if (ret < 0) 780 + return ret; 781 + 782 + hwmon_dev = devm_hwmon_device_register_with_info(&client->dev, client->name, st, 783 + &ltc2992_chip_info, NULL); 784 + 785 + return PTR_ERR_OR_ZERO(hwmon_dev); 786 + } 787 + 788 + static const struct of_device_id ltc2992_of_match[] = { 789 + { .compatible = "adi,ltc2992" }, 790 + { } 791 + }; 792 + MODULE_DEVICE_TABLE(of, ltc2992_of_match); 793 + 794 + static const struct i2c_device_id ltc2992_i2c_id[] = { 795 + {"ltc2992", 0}, 796 + {} 797 + }; 798 + MODULE_DEVICE_TABLE(i2c, ltc2992_i2c_id); 799 + 800 + static struct i2c_driver ltc2992_i2c_driver = { 801 + .driver = { 802 + .name = "ltc2992", 803 + .of_match_table = ltc2992_of_match, 804 + }, 805 + .probe = ltc2992_i2c_probe, 806 + .id_table = ltc2992_i2c_id, 807 + }; 808 + 809 + module_i2c_driver(ltc2992_i2c_driver); 810 + 811 + MODULE_AUTHOR("Alexandru Tachici <alexandru.tachici@analog.com>"); 812 + MODULE_DESCRIPTION("Hwmon driver for Linear Technology 2992"); 813 + MODULE_LICENSE("Dual BSD/GPL");