| 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); |
| |
| void devm_hwmon_device_unregister(struct device *dev); |
| |
| char *hwmon_sanitize_name(const char *name); |
| |
| char *devm_hwmon_sanitize_name(struct device *dev, const char *name); |
| |
| 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. |
| |
| devm_hwmon_device_unregister does not normally have to be called. It is only |
| needed for error handling, and only needed if the driver probe fails after |
| the call to hwmon_device_register_with_info and if the automatic (device |
| managed) removal would be too late. |
| |
| All supported hwmon device registration functions only accept valid device |
| names. Device names including invalid characters (whitespace, '*', or '-') |
| will be rejected. The 'name' parameter is mandatory. |
| |
| 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. |
| |
| 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_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. |
| |
| 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. |