Lines Matching +full:monitor +full:- +full:interval +full:- +full:ms
1 // SPDX-License-Identifier: GPL-2.0-only
3 * Driver for Texas Instruments INA219, INA226 power monitor chips
6 * Zero Drift Bi-Directional Current/Power Monitor with I2C Interface
10 * Bi-Directional Current/Power Monitor with I2C Interface
14 * Bi-Directional Current/Power Monitor with I2C Interface
18 * Bi-directional Current/Power Monitor with I2C Interface
32 #include <linux/hwmon-sysfs.h>
60 /* settings - depend on use case */
64 /* worst case is 68.10 ms (~14.6Hz, ina219) */
66 #define INA2XX_MAX_DELAY 69 /* worst case delay in ms */
169 static u16 ina226_interval_to_reg(int interval) in ina226_interval_to_reg() argument
173 avg = DIV_ROUND_CLOSEST(interval * 1000, in ina226_interval_to_reg()
189 return regmap_write(data->regmap, INA2XX_CALIBRATION, in ina2xx_calibrate()
190 data->config->calibration_value); in ina2xx_calibrate()
198 int ret = regmap_write(data->regmap, INA2XX_CONFIG, in ina2xx_init()
199 data->config->config_default); in ina2xx_init()
213 for (retry = 5; retry; retry--) { in ina2xx_read_reg()
215 ret = regmap_read(data->regmap, reg, regval); in ina2xx_read_reg()
232 ret = regmap_read(data->regmap, INA2XX_CALIBRATION, in ina2xx_read_reg()
261 return -ENODEV; in ina2xx_read_reg()
272 val = DIV_ROUND_CLOSEST((s16)regval, data->config->shunt_div); in ina2xx_get_value()
275 val = (regval >> data->config->bus_voltage_shift) in ina2xx_get_value()
276 * data->config->bus_voltage_lsb; in ina2xx_get_value()
280 val = regval * data->power_lsb_uW; in ina2xx_get_value()
284 val = (s16)regval * data->current_lsb_uA; in ina2xx_get_value()
307 int err = ina2xx_read_reg(dev, attr->index, ®val); in ina2xx_value_show()
312 return sysfs_emit(buf, "%d\n", ina2xx_get_value(data, attr->index, regval)); in ina2xx_value_show()
349 val *= data->config->shunt_div; in ina226_alert_to_reg()
353 val = (val * 1000) << data->config->bus_voltage_shift; in ina226_alert_to_reg()
354 val = DIV_ROUND_CLOSEST(val, data->config->bus_voltage_lsb); in ina226_alert_to_reg()
357 val = DIV_ROUND_CLOSEST(val, data->power_lsb_uW); in ina226_alert_to_reg()
375 mutex_lock(&data->config_lock); in ina226_alert_show()
376 ret = regmap_read(data->regmap, INA226_MASK_ENABLE, ®val); in ina226_alert_show()
380 if (regval & BIT(attr->index)) { in ina226_alert_show()
381 ret = regmap_read(data->regmap, INA226_ALERT_LIMIT, ®val); in ina226_alert_show()
384 val = ina226_reg_to_alert(data, attr->index, regval); in ina226_alert_show()
389 mutex_unlock(&data->config_lock); in ina226_alert_show()
409 * if the value is non-zero. in ina226_alert_store()
411 mutex_lock(&data->config_lock); in ina226_alert_store()
412 ret = regmap_update_bits(data->regmap, INA226_MASK_ENABLE, in ina226_alert_store()
417 ret = regmap_write(data->regmap, INA226_ALERT_LIMIT, in ina226_alert_store()
418 ina226_alert_to_reg(data, attr->index, val)); in ina226_alert_store()
423 ret = regmap_update_bits(data->regmap, INA226_MASK_ENABLE, in ina226_alert_store()
425 BIT(attr->index)); in ina226_alert_store()
432 mutex_unlock(&data->config_lock); in ina226_alert_store()
445 ret = regmap_read(data->regmap, INA226_MASK_ENABLE, ®val); in ina226_alarm_show()
449 alarm = (regval & BIT(attr->index)) && in ina226_alarm_show()
463 data->config->shunt_div); in ina2xx_set_shunt()
465 return -EINVAL; in ina2xx_set_shunt()
467 mutex_lock(&data->config_lock); in ina2xx_set_shunt()
468 data->rshunt = val; in ina2xx_set_shunt()
469 data->current_lsb_uA = DIV_ROUND_CLOSEST(dividend, val); in ina2xx_set_shunt()
470 data->power_lsb_uW = data->config->power_lsb_factor * in ina2xx_set_shunt()
471 data->current_lsb_uA; in ina2xx_set_shunt()
472 mutex_unlock(&data->config_lock); in ina2xx_set_shunt()
482 return sysfs_emit(buf, "%li\n", data->rshunt); in ina2xx_shunt_show()
516 return -EINVAL; in ina226_interval_store()
518 status = regmap_update_bits(data->regmap, INA2XX_CONFIG, in ina226_interval_store()
534 status = regmap_read(data->regmap, INA2XX_CONFIG, ®val); in ina226_interval_show()
570 /* over-limit power alert setting and alarm */
579 /* update interval (ina226 only) */
619 struct device *dev = &client->dev; in ina2xx_probe()
626 if (client->dev.of_node) in ina2xx_probe()
627 chip = (uintptr_t)of_device_get_match_data(&client->dev); in ina2xx_probe()
629 chip = i2c_match_id(ina2xx_id, client)->driver_data; in ina2xx_probe()
633 return -ENOMEM; in ina2xx_probe()
636 data->config = &ina2xx_config[chip]; in ina2xx_probe()
637 mutex_init(&data->config_lock); in ina2xx_probe()
639 if (of_property_read_u32(dev->of_node, "shunt-resistor", &val) < 0) { in ina2xx_probe()
643 val = pdata->shunt_uohms; in ina2xx_probe()
650 ina2xx_regmap_config.max_register = data->config->registers; in ina2xx_probe()
652 data->regmap = devm_regmap_init_i2c(client, &ina2xx_regmap_config); in ina2xx_probe()
653 if (IS_ERR(data->regmap)) { in ina2xx_probe()
655 return PTR_ERR(data->regmap); in ina2xx_probe()
665 return -ENODEV; in ina2xx_probe()
668 data->groups[group++] = &ina2xx_group; in ina2xx_probe()
670 data->groups[group++] = &ina226_group; in ina2xx_probe()
672 hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, in ina2xx_probe()
673 data, data->groups); in ina2xx_probe()
677 dev_info(dev, "power monitor %s (Rshunt = %li uOhm)\n", in ina2xx_probe()
678 client->name, data->rshunt); in ina2xx_probe()
729 MODULE_AUTHOR("Lothar Felten <l-felten@ti.com>");