1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * isl28022.c - driver for Renesas ISL28022 power monitor chip monitoring 4 * 5 * Copyright (c) 2023 Carsten Spieß <mail@carsten-spiess.de> 6 */ 7 8 #include <linux/debugfs.h> 9 #include <linux/err.h> 10 #include <linux/hwmon.h> 11 #include <linux/i2c.h> 12 #include <linux/math64.h> 13 #include <linux/module.h> 14 #include <linux/regmap.h> 15 16 /* ISL28022 registers */ 17 #define ISL28022_REG_CONFIG 0x00 18 #define ISL28022_REG_SHUNT 0x01 19 #define ISL28022_REG_BUS 0x02 20 #define ISL28022_REG_POWER 0x03 21 #define ISL28022_REG_CURRENT 0x04 22 #define ISL28022_REG_CALIB 0x05 23 #define ISL28022_REG_SHUNT_THR 0x06 24 #define ISL28022_REG_BUS_THR 0x07 25 #define ISL28022_REG_INT 0x08 26 #define ISL28022_REG_AUX 0x09 27 #define ISL28022_REG_MAX ISL28022_REG_AUX 28 29 /* ISL28022 config flags */ 30 /* mode flags */ 31 #define ISL28022_MODE_SHIFT 0 32 #define ISL28022_MODE_MASK 0x0007 33 34 #define ISL28022_MODE_PWR_DOWN 0x0 35 #define ISL28022_MODE_TRG_S 0x1 36 #define ISL28022_MODE_TRG_B 0x2 37 #define ISL28022_MODE_TRG_SB 0x3 38 #define ISL28022_MODE_ADC_OFF 0x4 39 #define ISL28022_MODE_CONT_S 0x5 40 #define ISL28022_MODE_CONT_B 0x6 41 #define ISL28022_MODE_CONT_SB 0x7 42 43 /* shunt ADC settings */ 44 #define ISL28022_SADC_SHIFT 3 45 #define ISL28022_SADC_MASK 0x0078 46 47 #define ISL28022_BADC_SHIFT 7 48 #define ISL28022_BADC_MASK 0x0780 49 50 #define ISL28022_ADC_12 0x0 /* 12 bit ADC */ 51 #define ISL28022_ADC_13 0x1 /* 13 bit ADC */ 52 #define ISL28022_ADC_14 0x2 /* 14 bit ADC */ 53 #define ISL28022_ADC_15 0x3 /* 15 bit ADC */ 54 #define ISL28022_ADC_15_1 0x8 /* 15 bit ADC, 1 sample */ 55 #define ISL28022_ADC_15_2 0x9 /* 15 bit ADC, 2 samples */ 56 #define ISL28022_ADC_15_4 0xA /* 15 bit ADC, 4 samples */ 57 #define ISL28022_ADC_15_8 0xB /* 15 bit ADC, 8 samples */ 58 #define ISL28022_ADC_15_16 0xC /* 15 bit ADC, 16 samples */ 59 #define ISL28022_ADC_15_32 0xD /* 15 bit ADC, 32 samples */ 60 #define ISL28022_ADC_15_64 0xE /* 15 bit ADC, 64 samples */ 61 #define ISL28022_ADC_15_128 0xF /* 15 bit ADC, 128 samples */ 62 63 /* shunt voltage range */ 64 #define ISL28022_PG_SHIFT 11 65 #define ISL28022_PG_MASK 0x1800 66 67 #define ISL28022_PG_40 0x0 /* +/-40 mV */ 68 #define ISL28022_PG_80 0x1 /* +/-80 mV */ 69 #define ISL28022_PG_160 0x2 /* +/-160 mV */ 70 #define ISL28022_PG_320 0x3 /* +/-3200 mV */ 71 72 /* bus voltage range */ 73 #define ISL28022_BRNG_SHIFT 13 74 #define ISL28022_BRNG_MASK 0x6000 75 76 #define ISL28022_BRNG_16 0x0 /* 16 V */ 77 #define ISL28022_BRNG_32 0x1 /* 32 V */ 78 #define ISL28022_BRNG_60 0x3 /* 60 V */ 79 80 /* reset */ 81 #define ISL28022_RESET 0x8000 82 83 struct isl28022_data { 84 struct regmap *regmap; 85 u32 shunt; 86 u32 gain; 87 u32 average; 88 }; 89 90 static int isl28022_read_in(struct device *dev, u32 attr, int channel, long *val) 91 { 92 struct isl28022_data *data = dev_get_drvdata(dev); 93 unsigned int regval; 94 int err; 95 u16 sign_bit; 96 97 switch (channel) { 98 case 0: 99 switch (attr) { 100 case hwmon_in_input: 101 err = regmap_read(data->regmap, 102 ISL28022_REG_BUS, ®val); 103 if (err < 0) 104 return err; 105 /* driver supports only 60V mode (BRNG 11) */ 106 *val = (long)(((u16)regval) & 0xFFFC); 107 break; 108 default: 109 return -EOPNOTSUPP; 110 } 111 break; 112 case 1: 113 switch (attr) { 114 case hwmon_in_input: 115 err = regmap_read(data->regmap, 116 ISL28022_REG_SHUNT, ®val); 117 if (err < 0) 118 return err; 119 switch (data->gain) { 120 case 8: 121 sign_bit = (regval >> 15) & 0x01; 122 *val = (long)((((u16)regval) & 0x7FFF) - 123 (sign_bit * 32768)) / 100; 124 break; 125 case 4: 126 sign_bit = (regval >> 14) & 0x01; 127 *val = (long)((((u16)regval) & 0x3FFF) - 128 (sign_bit * 16384)) / 100; 129 break; 130 case 2: 131 sign_bit = (regval >> 13) & 0x01; 132 *val = (long)((((u16)regval) & 0x1FFF) - 133 (sign_bit * 8192)) / 100; 134 break; 135 case 1: 136 sign_bit = (regval >> 12) & 0x01; 137 *val = (long)((((u16)regval) & 0x0FFF) - 138 (sign_bit * 4096)) / 100; 139 break; 140 } 141 break; 142 default: 143 return -EOPNOTSUPP; 144 } 145 break; 146 default: 147 return -EOPNOTSUPP; 148 } 149 150 return 0; 151 } 152 153 static int isl28022_read_current(struct device *dev, u32 attr, long *val) 154 { 155 struct isl28022_data *data = dev_get_drvdata(dev); 156 unsigned int regval; 157 int err; 158 u16 sign_bit; 159 160 switch (attr) { 161 case hwmon_curr_input: 162 err = regmap_read(data->regmap, 163 ISL28022_REG_CURRENT, ®val); 164 if (err < 0) 165 return err; 166 sign_bit = (regval >> 15) & 0x01; 167 *val = (((long)(((u16)regval) & 0x7FFF) - (sign_bit * 32768)) * 168 1250L * (long)data->gain) / (long)data->shunt; 169 break; 170 default: 171 return -EOPNOTSUPP; 172 } 173 174 return 0; 175 } 176 177 static int isl28022_read_power(struct device *dev, u32 attr, long *val) 178 { 179 struct isl28022_data *data = dev_get_drvdata(dev); 180 unsigned int regval; 181 int err; 182 183 switch (attr) { 184 case hwmon_power_input: 185 err = regmap_read(data->regmap, 186 ISL28022_REG_POWER, ®val); 187 if (err < 0) 188 return err; 189 *val = min(div_u64(51200000ULL * data->gain * regval, 190 data->shunt), LONG_MAX); 191 break; 192 default: 193 return -EOPNOTSUPP; 194 } 195 196 return 0; 197 } 198 199 static int isl28022_read(struct device *dev, enum hwmon_sensor_types type, 200 u32 attr, int channel, long *val) 201 { 202 switch (type) { 203 case hwmon_in: 204 return isl28022_read_in(dev, attr, channel, val); 205 case hwmon_curr: 206 return isl28022_read_current(dev, attr, val); 207 case hwmon_power: 208 return isl28022_read_power(dev, attr, val); 209 default: 210 return -EOPNOTSUPP; 211 } 212 return 0; 213 } 214 215 static umode_t isl28022_is_visible(const void *data, enum hwmon_sensor_types type, 216 u32 attr, int channel) 217 { 218 switch (type) { 219 case hwmon_in: 220 switch (attr) { 221 case hwmon_in_input: 222 return 0444; 223 default: 224 break; 225 } 226 break; 227 case hwmon_curr: 228 switch (attr) { 229 case hwmon_curr_input: 230 return 0444; 231 default: 232 break; 233 } 234 break; 235 case hwmon_power: 236 switch (attr) { 237 case hwmon_power_input: 238 return 0444; 239 default: 240 break; 241 } 242 break; 243 default: 244 break; 245 } 246 return 0; 247 } 248 249 static const struct hwmon_channel_info *isl28022_info[] = { 250 HWMON_CHANNEL_INFO(in, 251 HWMON_I_INPUT, /* channel 0: bus voltage (mV) */ 252 HWMON_I_INPUT), /* channel 1: shunt voltage (mV) */ 253 HWMON_CHANNEL_INFO(curr, 254 HWMON_C_INPUT), /* channel 1: current (mA) */ 255 HWMON_CHANNEL_INFO(power, 256 HWMON_P_INPUT), /* channel 1: power (µW) */ 257 NULL 258 }; 259 260 static const struct hwmon_ops isl28022_hwmon_ops = { 261 .is_visible = isl28022_is_visible, 262 .read = isl28022_read, 263 }; 264 265 static const struct hwmon_chip_info isl28022_chip_info = { 266 .ops = &isl28022_hwmon_ops, 267 .info = isl28022_info, 268 }; 269 270 static bool isl28022_is_writeable_reg(struct device *dev, unsigned int reg) 271 { 272 switch (reg) { 273 case ISL28022_REG_CONFIG: 274 case ISL28022_REG_CALIB: 275 case ISL28022_REG_SHUNT_THR: 276 case ISL28022_REG_BUS_THR: 277 case ISL28022_REG_INT: 278 case ISL28022_REG_AUX: 279 return true; 280 } 281 282 return false; 283 } 284 285 static bool isl28022_is_volatile_reg(struct device *dev, unsigned int reg) 286 { 287 switch (reg) { 288 case ISL28022_REG_CONFIG: 289 case ISL28022_REG_SHUNT: 290 case ISL28022_REG_BUS: 291 case ISL28022_REG_POWER: 292 case ISL28022_REG_CURRENT: 293 case ISL28022_REG_INT: 294 case ISL28022_REG_AUX: 295 return true; 296 } 297 return true; 298 } 299 300 static const struct regmap_config isl28022_regmap_config = { 301 .reg_bits = 8, 302 .val_bits = 16, 303 .max_register = ISL28022_REG_MAX, 304 .writeable_reg = isl28022_is_writeable_reg, 305 .volatile_reg = isl28022_is_volatile_reg, 306 .val_format_endian = REGMAP_ENDIAN_BIG, 307 .cache_type = REGCACHE_MAPLE, 308 .use_single_read = true, 309 .use_single_write = true, 310 }; 311 312 static int shunt_voltage_show(struct seq_file *seqf, void *unused) 313 { 314 struct isl28022_data *data = seqf->private; 315 unsigned int regval; 316 int err; 317 318 err = regmap_read(data->regmap, 319 ISL28022_REG_SHUNT, ®val); 320 if (err) 321 return err; 322 323 /* print shunt voltage in micro volt */ 324 seq_printf(seqf, "%d\n", regval * 10); 325 326 return 0; 327 } 328 DEFINE_SHOW_ATTRIBUTE(shunt_voltage); 329 330 /* 331 * read property values and make consistency checks. 332 * 333 * following values for shunt range and resistor are allowed: 334 * 40 mV -> gain 1, shunt min. 800 micro ohms 335 * 80 mV -> gain 2, shunt min. 1600 micro ohms 336 * 160 mV -> gain 4, shunt min. 3200 micro ohms 337 * 320 mV -> gain 8, shunt min. 6400 micro ohms 338 */ 339 static int isl28022_read_properties(struct device *dev, struct isl28022_data *data) 340 { 341 const char *propname; 342 u32 val; 343 int err; 344 345 propname = "shunt-resistor-micro-ohms"; 346 if (device_property_present(dev, propname)) { 347 err = device_property_read_u32(dev, propname, &val); 348 if (err) 349 return err; 350 } else { 351 val = 10000; 352 } 353 data->shunt = val; 354 355 propname = "renesas,shunt-range-microvolt"; 356 if (device_property_present(dev, propname)) { 357 err = device_property_read_u32(dev, propname, &val); 358 if (err) 359 return err; 360 } else { 361 val = 320000; 362 } 363 364 switch (val) { 365 case 40000: 366 data->gain = 1; 367 if (data->shunt < 800) 368 goto shunt_invalid; 369 break; 370 case 80000: 371 data->gain = 2; 372 if (data->shunt < 1600) 373 goto shunt_invalid; 374 break; 375 case 160000: 376 data->gain = 4; 377 if (data->shunt < 3200) 378 goto shunt_invalid; 379 break; 380 case 320000: 381 data->gain = 8; 382 if (data->shunt < 6400) 383 goto shunt_invalid; 384 break; 385 default: 386 return dev_err_probe(dev, -EINVAL, "%s invalid value %u\n", propname, val); 387 } 388 389 propname = "renesas,average-samples"; 390 if (device_property_present(dev, propname)) { 391 err = device_property_read_u32(dev, propname, &val); 392 if (err) 393 return err; 394 } else { 395 val = 1; 396 } 397 if (val > 128 || hweight32(val) != 1) 398 return dev_err_probe(dev, -EINVAL, "%s invalid value %u\n", propname, val); 399 400 data->average = val; 401 402 return 0; 403 404 shunt_invalid: 405 return dev_err_probe(dev, -EINVAL, 406 "renesas,shunt-resistor-microvolt invalid value %d\n", 407 data->shunt); 408 } 409 410 /* 411 * write configuration and calibration registers 412 * 413 * The driver supports only shunt and bus continuous ADC mode at 15bit resolution 414 * with averaging from 1 to 128 samples (pow of 2) on both channels. 415 * Shunt voltage gain 1,2,4 or 8 is allowed. 416 * The bus voltage range is 60V fixed. 417 */ 418 static int isl28022_config(struct isl28022_data *data) 419 { 420 int err; 421 u16 config; 422 u16 calib; 423 424 config = (ISL28022_MODE_CONT_SB << ISL28022_MODE_SHIFT) | 425 (ISL28022_BRNG_60 << ISL28022_BRNG_SHIFT) | 426 (__ffs(data->gain) << ISL28022_PG_SHIFT) | 427 ((ISL28022_ADC_15_1 + __ffs(data->average)) << ISL28022_SADC_SHIFT) | 428 ((ISL28022_ADC_15_1 + __ffs(data->average)) << ISL28022_BADC_SHIFT); 429 430 calib = data->shunt ? 0x8000 / data->gain : 0; 431 432 err = regmap_write(data->regmap, ISL28022_REG_CONFIG, config); 433 if (err < 0) 434 return err; 435 436 return regmap_write(data->regmap, ISL28022_REG_CALIB, calib); 437 } 438 439 static int isl28022_probe(struct i2c_client *client) 440 { 441 struct device *dev = &client->dev; 442 struct device *hwmon_dev; 443 struct isl28022_data *data; 444 int err; 445 446 if (!i2c_check_functionality(client->adapter, 447 I2C_FUNC_SMBUS_BYTE_DATA | 448 I2C_FUNC_SMBUS_WORD_DATA)) 449 return -ENODEV; 450 451 data = devm_kzalloc(dev, sizeof(struct isl28022_data), GFP_KERNEL); 452 if (!data) 453 return -ENOMEM; 454 455 err = isl28022_read_properties(dev, data); 456 if (err) 457 return err; 458 459 data->regmap = devm_regmap_init_i2c(client, &isl28022_regmap_config); 460 if (IS_ERR(data->regmap)) 461 return PTR_ERR(data->regmap); 462 463 err = isl28022_config(data); 464 if (err) 465 return err; 466 467 debugfs_create_file("shunt_voltage", 0444, client->debugfs, data, &shunt_voltage_fops); 468 469 hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, 470 data, &isl28022_chip_info, NULL); 471 if (IS_ERR(hwmon_dev)) 472 return PTR_ERR(hwmon_dev); 473 474 return 0; 475 } 476 477 static const struct i2c_device_id isl28022_ids[] = { 478 { "isl28022" }, 479 { /* LIST END */ } 480 }; 481 MODULE_DEVICE_TABLE(i2c, isl28022_ids); 482 483 static const struct of_device_id __maybe_unused isl28022_of_match[] = { 484 { .compatible = "renesas,isl28022"}, 485 { /* LIST END */ } 486 }; 487 MODULE_DEVICE_TABLE(of, isl28022_of_match); 488 489 static struct i2c_driver isl28022_driver = { 490 .class = I2C_CLASS_HWMON, 491 .driver = { 492 .name = "isl28022", 493 }, 494 .probe = isl28022_probe, 495 .id_table = isl28022_ids, 496 }; 497 module_i2c_driver(isl28022_driver); 498 499 MODULE_AUTHOR("Carsten Spieß <mail@carsten-spiess.de>"); 500 MODULE_DESCRIPTION("ISL28022 driver"); 501 MODULE_LICENSE("GPL"); 502