hwmon: Introduce 64-bit energy attribute support
authorGuenter Roeck <linux@roeck-us.net>
Thu, 29 Aug 2024 04:56:57 +0000 (21:56 -0700)
committerGuenter Roeck <linux@roeck-us.net>
Sun, 7 Sep 2025 23:33:48 +0000 (16:33 -0700)
Many chips require 64-bit variables to display the accumulated energy,
even more so since the energy units are micro-Joule. Add new sensor type
"energy64" to support reporting the chip energy as 64-bit values.

Changing the entire hardware monitoring API is not feasible, and it is only
really necessary to support reading 64-bit values for the "energyX_input"
attribute. For this reason, keep the API as-is and use type casts on both
ends to pass 64-bit pointers when reading the accumulated energy. On the
write side (which is only useful for the energyX_enable attribute), keep
passing the written value as long.

Reviewed-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
Tested-by: Chris Packham <chris.packham@alliedtelesis.co.nz> # INA780
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Documentation/hwmon/hwmon-kernel-api.rst
drivers/hwmon/hwmon.c
include/linux/hwmon.h
include/trace/events/hwmon.h

index e47fc75..037b69c 100644 (file)
@@ -159,6 +159,7 @@ It contains following fields:
      hwmon_curr                Current sensor
      hwmon_power               Power sensor
      hwmon_energy      Energy sensor
+     hwmon_energy64    Energy sensor, reported as 64-bit signed value
      hwmon_humidity    Humidity sensor
      hwmon_fan         Fan speed sensor
      hwmon_pwm         PWM control
@@ -288,6 +289,8 @@ Parameters:
                The sensor channel number.
        val:
                Pointer to attribute value.
+               For hwmon_energy64, `'val`' is passed as `long *` but needs
+               a typecast to `s64 *`.
 
 Return value:
        0 on success, a negative error number otherwise.
index 1688c21..2e17f3a 100644 (file)
@@ -426,18 +426,22 @@ static ssize_t hwmon_attr_show(struct device *dev,
                               struct device_attribute *devattr, char *buf)
 {
        struct hwmon_device_attribute *hattr = to_hwmon_attr(devattr);
+       s64 val64;
        long val;
        int ret;
 
        ret = hattr->ops->read(dev, hattr->type, hattr->attr, hattr->index,
-                              &val);
+                              (hattr->type == hwmon_energy64) ? (long *)&val64 : &val);
        if (ret < 0)
                return ret;
 
+       if (hattr->type != hwmon_energy64)
+               val64 = val;
+
        trace_hwmon_attr_show(hattr->index + hwmon_attr_base(hattr->type),
-                             hattr->name, val);
+                             hattr->name, val64);
 
-       return sprintf(buf, "%ld\n", val);
+       return sprintf(buf, "%lld\n", val64);
 }
 
 static ssize_t hwmon_attr_show_string(struct device *dev,
@@ -478,7 +482,7 @@ static ssize_t hwmon_attr_store(struct device *dev,
                return ret;
 
        trace_hwmon_attr_store(hattr->index + hwmon_attr_base(hattr->type),
-                              hattr->name, val);
+                              hattr->name, (s64)val);
 
        return count;
 }
@@ -734,6 +738,7 @@ static const char * const *__templates[] = {
        [hwmon_curr] = hwmon_curr_attr_templates,
        [hwmon_power] = hwmon_power_attr_templates,
        [hwmon_energy] = hwmon_energy_attr_templates,
+       [hwmon_energy64] = hwmon_energy_attr_templates,
        [hwmon_humidity] = hwmon_humidity_attr_templates,
        [hwmon_fan] = hwmon_fan_attr_templates,
        [hwmon_pwm] = hwmon_pwm_attr_templates,
@@ -747,6 +752,7 @@ static const int __templates_size[] = {
        [hwmon_curr] = ARRAY_SIZE(hwmon_curr_attr_templates),
        [hwmon_power] = ARRAY_SIZE(hwmon_power_attr_templates),
        [hwmon_energy] = ARRAY_SIZE(hwmon_energy_attr_templates),
+       [hwmon_energy64] = ARRAY_SIZE(hwmon_energy_attr_templates),
        [hwmon_humidity] = ARRAY_SIZE(hwmon_humidity_attr_templates),
        [hwmon_fan] = ARRAY_SIZE(hwmon_fan_attr_templates),
        [hwmon_pwm] = ARRAY_SIZE(hwmon_pwm_attr_templates),
index 3a63dff..886fc90 100644 (file)
@@ -24,6 +24,7 @@ enum hwmon_sensor_types {
        hwmon_curr,
        hwmon_power,
        hwmon_energy,
+       hwmon_energy64,
        hwmon_humidity,
        hwmon_fan,
        hwmon_pwm,
index d1ff560..3865098 100644 (file)
@@ -9,14 +9,14 @@
 
 DECLARE_EVENT_CLASS(hwmon_attr_class,
 
-       TP_PROTO(int index, const char *attr_name, long val),
+       TP_PROTO(int index, const char *attr_name, long long val),
 
        TP_ARGS(index, attr_name, val),
 
        TP_STRUCT__entry(
                __field(int, index)
                __string(attr_name, attr_name)
-               __field(long, val)
+               __field(long long, val)
        ),
 
        TP_fast_assign(
@@ -25,20 +25,20 @@ DECLARE_EVENT_CLASS(hwmon_attr_class,
                __entry->val = val;
        ),
 
-       TP_printk("index=%d, attr_name=%s, val=%ld",
+       TP_printk("index=%d, attr_name=%s, val=%lld",
                  __entry->index,  __get_str(attr_name), __entry->val)
 );
 
 DEFINE_EVENT(hwmon_attr_class, hwmon_attr_show,
 
-       TP_PROTO(int index, const char *attr_name, long val),
+       TP_PROTO(int index, const char *attr_name, long long val),
 
        TP_ARGS(index, attr_name, val)
 );
 
 DEFINE_EVENT(hwmon_attr_class, hwmon_attr_store,
 
-       TP_PROTO(int index, const char *attr_name, long val),
+       TP_PROTO(int index, const char *attr_name, long long val),
 
        TP_ARGS(index, attr_name, val)
 );