| The Linux Hardware Monitoring kernel API | |
| ======================================== | |
| Guenter Roeck | |
| Introduction | |
| ------------ | |
| This document describes the API that can be used by hardware monitoring | |
| drivers that want to use the hardware monitoring framework. | |
| This document does not describe what a hardware monitoring (hwmon) Driver or | |
| Device is. It also does not describe the API which can be used by user space | |
| to communicate with a hardware monitoring device. If you want to know this | |
| then please read the following file: Documentation/hwmon/sysfs-interface.rst. | |
| For additional guidelines on how to write and improve hwmon drivers, please | |
| also read Documentation/hwmon/submitting-patches.rst. | |
| The API | |
| ------- | |
| Each hardware monitoring driver must #include <linux/hwmon.h> and, in some | |
| cases, <linux/hwmon-sysfs.h>. linux/hwmon.h declares the following | |
| register/unregister functions:: | |
| struct device * | |
| hwmon_device_register_with_info(struct device *dev, | |
| const char *name, void *drvdata, | |
| const struct hwmon_chip_info *info, | |
| const struct attribute_group **extra_groups); | |
| struct device * | |
| devm_hwmon_device_register_with_info(struct device *dev, | |
| const char *name, | |
| void *drvdata, | |
| const struct hwmon_chip_info *info, | |
| const struct attribute_group **extra_groups); | |
| void hwmon_device_unregister(struct device *dev); | |
| char *hwmon_sanitize_name(const char *name); | |
| char *devm_hwmon_sanitize_name(struct device *dev, const char *name); | |
| int hwmon_notify_event(struct device *dev, enum hwmon_sensor_types type, | |
| u32 attr, int channel); | |
| void hwmon_lock(struct device *dev); | |
| void hwmon_unlock(struct device *dev); | |
| hwmon_device_register_with_info registers a hardware monitoring device. | |
| It creates the standard sysfs attributes in the hardware monitoring core, | |
| letting the driver focus on reading from and writing to the chip instead | |
| of having to bother with sysfs attributes. The parent device parameter | |
| as well as the chip parameter must not be NULL. Its parameters are described | |
| in more detail below. | |
| devm_hwmon_device_register_with_info is similar to | |
| hwmon_device_register_with_info. However, it is device managed, meaning the | |
| hwmon device does not have to be removed explicitly by the removal function. | |
| All other hardware monitoring device registration functions are deprecated | |
| and must not be used in new drivers. | |
| hwmon_device_unregister deregisters a registered hardware monitoring device. | |
| The parameter of this function is the pointer to the registered hardware | |
| monitoring device structure. This function must be called from the driver | |
| remove function if the hardware monitoring device was registered with | |
| hwmon_device_register_with_info. | |
| All supported hwmon device registration functions only accept valid device | |
| names. Device names including invalid characters (whitespace, '*', or '-') | |
| will be rejected. If NULL is passed as name parameter, the hardware monitoring | |
| device name will be derived from the parent device name. | |
| If the driver doesn't use a static device name (for example it uses | |
| dev_name()), and therefore cannot make sure the name only contains valid | |
| characters, hwmon_sanitize_name can be used. This convenience function | |
| will duplicate the string and replace any invalid characters with an | |
| underscore. It will allocate memory for the new string and it is the | |
| responsibility of the caller to release the memory when the device is | |
| removed. | |
| devm_hwmon_sanitize_name is the resource managed version of | |
| hwmon_sanitize_name; the memory will be freed automatically on device | |
| removal. | |
| When using ``[devm_]hwmon_device_register_with_info()`` to register the | |
| hardware monitoring device, accesses using the associated access functions | |
| are serialised by the hardware monitoring core. If a driver needs locking | |
| for other functions such as interrupt handlers, attributes which are fully | |
| implemented in the driver, or debugfs functions, hwmon_lock() and hwmon_unlock() | |
| can be used to ensure that calls to those functions are serialized. Those | |
| functions also support guard() and scoped_guard() variants. | |
| Drivers can call hwmon_notify_event() to notify userspace and the thermal | |
| subsystem when a hardware monitoring event (such as an alarm or a fault | |
| condition) occurs or clears. The parameters are the hwmon device, the sensor | |
| type, the attribute identifier associated with the event (such as | |
| hwmon_temp_max_alarm or hwmon_fan_fault), and the sensor channel number. | |
| hwmon_notify_event() generates a sysfs event (calling sysfs_notify()) and a | |
| udev event with the attribute name passed in the NAME environment property | |
| (e.g., "NAME=temp1_max_alarm"). If the event is for a temperature sensor and | |
| the sensor is attached to a thermal zone, it also notifies the thermal | |
| subsystem to update the thermal zone. hwmon_notify_event() returns 0 on | |
| success or a negative error code on failure. | |
| Using devm_hwmon_device_register_with_info() | |
| -------------------------------------------- | |
| hwmon_device_register_with_info() registers a hardware monitoring device. | |
| The parameters to this function are | |
| =============================================== =============================================== | |
| `struct device *dev` Pointer to parent device | |
| `const char *name` Device name | |
| `void *drvdata` Driver private data | |
| `const struct hwmon_chip_info *info` Pointer to chip description. | |
| `const struct attribute_group **extra_groups` Null-terminated list of additional non-standard | |
| sysfs attribute groups. | |
| =============================================== =============================================== | |
| This function returns a pointer to the created hardware monitoring device | |
| on success and a negative error code for failure. | |
| The hwmon_chip_info structure looks as follows:: | |
| struct hwmon_chip_info { | |
| const struct hwmon_ops *ops; | |
| const struct hwmon_channel_info * const *info; | |
| }; | |
| It contains the following fields: | |
| * ops: | |
| Pointer to device operations. | |
| * info: | |
| NULL-terminated list of device channel descriptors. | |
| The list of hwmon operations is defined as:: | |
| struct hwmon_ops { | |
| umode_t (*is_visible)(const void *, enum hwmon_sensor_types type, | |
| u32 attr, int); | |
| int (*read)(struct device *, enum hwmon_sensor_types type, | |
| u32 attr, int, long *); | |
| int (*write)(struct device *, enum hwmon_sensor_types type, | |
| u32 attr, int, long); | |
| }; | |
| It defines the following operations. | |
| * is_visible: | |
| Pointer to a function to return the file mode for each supported | |
| attribute. This function is mandatory. | |
| * read: | |
| Pointer to a function for reading a value from the chip. This function | |
| is optional, but must be provided if any readable attributes exist. | |
| * write: | |
| Pointer to a function for writing a value to the chip. This function is | |
| optional, but must be provided if any writeable attributes exist. | |
| Each sensor channel is described with struct hwmon_channel_info, which is | |
| defined as follows:: | |
| struct hwmon_channel_info { | |
| enum hwmon_sensor_types type; | |
| u32 *config; | |
| }; | |
| It contains following fields: | |
| * type: | |
| The hardware monitoring sensor type. | |
| Supported sensor types are | |
| ================== ================================================== | |
| hwmon_chip A virtual sensor type, used to describe attributes | |
| which are not bound to a specific input or output | |
| hwmon_temp Temperature sensor | |
| hwmon_in Voltage sensor | |
| 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 | |
| ================== ================================================== | |
| * config: | |
| Pointer to a 0-terminated list of configuration values for each | |
| sensor of the given type. Each value is a combination of bit values | |
| describing the attributes supposed by a single sensor. | |
| As an example, here is the complete description file for a LM75 compatible | |
| sensor chip. The chip has a single temperature sensor. The driver wants to | |
| register with the thermal subsystem (HWMON_C_REGISTER_TZ), and it supports | |
| the update_interval attribute (HWMON_C_UPDATE_INTERVAL). The chip supports | |
| reading the temperature (HWMON_T_INPUT), it has a maximum temperature | |
| register (HWMON_T_MAX) as well as a maximum temperature hysteresis register | |
| (HWMON_T_MAX_HYST):: | |
| static const u32 lm75_chip_config[] = { | |
| HWMON_C_REGISTER_TZ | HWMON_C_UPDATE_INTERVAL, | |
| 0 | |
| }; | |
| static const struct hwmon_channel_info lm75_chip = { | |
| .type = hwmon_chip, | |
| .config = lm75_chip_config, | |
| }; | |
| static const u32 lm75_temp_config[] = { | |
| HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_HYST, | |
| 0 | |
| }; | |
| static const struct hwmon_channel_info lm75_temp = { | |
| .type = hwmon_temp, | |
| .config = lm75_temp_config, | |
| }; | |
| static const struct hwmon_channel_info * const lm75_info[] = { | |
| &lm75_chip, | |
| &lm75_temp, | |
| NULL | |
| }; | |
| The HWMON_CHANNEL_INFO() macro can and should be used when possible. | |
| With this macro, the above example can be simplified to | |
| static const struct hwmon_channel_info * const lm75_info[] = { | |
| HWMON_CHANNEL_INFO(chip, | |
| HWMON_C_REGISTER_TZ | HWMON_C_UPDATE_INTERVAL), | |
| HWMON_CHANNEL_INFO(temp, | |
| HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_HYST), | |
| NULL | |
| }; | |
| The remaining declarations are as follows. | |
| static const struct hwmon_ops lm75_hwmon_ops = { | |
| .is_visible = lm75_is_visible, | |
| .read = lm75_read, | |
| .write = lm75_write, | |
| }; | |
| static const struct hwmon_chip_info lm75_chip_info = { | |
| .ops = &lm75_hwmon_ops, | |
| .info = lm75_info, | |
| }; | |
| A complete list of bit values indicating individual attribute support | |
| is defined in include/linux/hwmon.h. Definition prefixes are as follows. | |
| =============== ================================================= | |
| HWMON_C_xxxx Chip attributes, for use with hwmon_chip. | |
| HWMON_T_xxxx Temperature attributes, for use with hwmon_temp. | |
| HWMON_I_xxxx Voltage attributes, for use with hwmon_in. | |
| HWMON_C_xxxx Current attributes, for use with hwmon_curr. | |
| Notice the prefix overlap with chip attributes. | |
| HWMON_P_xxxx Power attributes, for use with hwmon_power. | |
| HWMON_E_xxxx Energy attributes, for use with hwmon_energy. | |
| HWMON_H_xxxx Humidity attributes, for use with hwmon_humidity. | |
| HWMON_F_xxxx Fan speed attributes, for use with hwmon_fan. | |
| HWMON_PWM_xxxx PWM control attributes, for use with hwmon_pwm. | |
| =============== ================================================= | |
| Driver callback functions | |
| ------------------------- | |
| Each driver provides is_visible, read, and write functions. Parameters | |
| and return values for those functions are as follows:: | |
| umode_t is_visible_func(const void *data, enum hwmon_sensor_types type, | |
| u32 attr, int channel) | |
| Parameters: | |
| data: | |
| Pointer to device private data structure. | |
| type: | |
| The sensor type. | |
| attr: | |
| Attribute identifier associated with a specific attribute. | |
| For example, the attribute value for HWMON_T_INPUT would be | |
| hwmon_temp_input. For complete mappings of bit fields to | |
| attribute values please see include/linux/hwmon.h. | |
| channel: | |
| The sensor channel number. | |
| Return value: | |
| The file mode for this attribute. Typically, this will be 0 (the | |
| attribute will not be created), 0444, or 0644. | |
| :: | |
| int read_func(struct device *dev, enum hwmon_sensor_types type, | |
| u32 attr, int channel, long *val) | |
| Parameters: | |
| dev: | |
| Pointer to the hardware monitoring device. | |
| type: | |
| The sensor type. | |
| attr: | |
| Attribute identifier associated with a specific attribute. | |
| For example, the attribute value for HWMON_T_INPUT would be | |
| hwmon_temp_input. For complete mappings please see | |
| include/linux/hwmon.h. | |
| channel: | |
| 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. | |
| :: | |
| int write_func(struct device *dev, enum hwmon_sensor_types type, | |
| u32 attr, int channel, long val) | |
| Parameters: | |
| dev: | |
| Pointer to the hardware monitoring device. | |
| type: | |
| The sensor type. | |
| attr: | |
| Attribute identifier associated with a specific attribute. | |
| For example, the attribute value for HWMON_T_INPUT would be | |
| hwmon_temp_input. For complete mappings please see | |
| include/linux/hwmon.h. | |
| channel: | |
| The sensor channel number. | |
| val: | |
| The value to write to the chip. | |
| Return value: | |
| 0 on success, a negative error number otherwise. | |
| Driver-provided sysfs attributes | |
| -------------------------------- | |
| In most situations it should not be necessary for a driver to provide sysfs | |
| attributes since the hardware monitoring core creates those internally. | |
| Only additional non-standard sysfs attributes need to be provided. | |
| The header file linux/hwmon-sysfs.h provides a number of useful macros to | |
| declare and use hardware monitoring sysfs attributes. | |
| In many cases, you can use the existing define DEVICE_ATTR or its variants | |
| DEVICE_ATTR_{RW,RO,WO} to declare such attributes. This is feasible if an | |
| attribute has no additional context. However, in many cases there will be | |
| additional information such as a sensor index which will need to be passed | |
| to the sysfs attribute handling function. | |
| SENSOR_DEVICE_ATTR and SENSOR_DEVICE_ATTR_2 can be used to define attributes | |
| which need such additional context information. SENSOR_DEVICE_ATTR requires | |
| one additional argument, SENSOR_DEVICE_ATTR_2 requires two. | |
| Simplified variants of SENSOR_DEVICE_ATTR and SENSOR_DEVICE_ATTR_2 are available | |
| and should be used if standard attribute permissions and function names are | |
| feasible. Standard permissions are 0644 for SENSOR_DEVICE_ATTR[_2]_RW, | |
| 0444 for SENSOR_DEVICE_ATTR[_2]_RO, and 0200 for SENSOR_DEVICE_ATTR[_2]_WO. | |
| Standard functions, similar to DEVICE_ATTR_{RW,RO,WO}, have _show and _store | |
| appended to the provided function name. | |
| SENSOR_DEVICE_ATTR and its variants define a struct sensor_device_attribute | |
| variable. This structure has the following fields:: | |
| struct sensor_device_attribute { | |
| struct device_attribute dev_attr; | |
| int index; | |
| }; | |
| You can use to_sensor_dev_attr to get the pointer to this structure from the | |
| attribute read or write function. Its parameter is the device to which the | |
| attribute is attached. | |
| SENSOR_DEVICE_ATTR_2 and its variants define a struct sensor_device_attribute_2 | |
| variable, which is defined as follows:: | |
| struct sensor_device_attribute_2 { | |
| struct device_attribute dev_attr; | |
| u8 index; | |
| u8 nr; | |
| }; | |
| Use to_sensor_dev_attr_2 to get the pointer to this structure. Its parameter | |
| is the device to which the attribute is attached. |