This commit is contained in:
ed 2021-10-10 18:43:12 +01:00
parent 7722079d0f
commit 7121e03c4f

View File

@ -3,10 +3,9 @@
* HWMON driver for ASUS motherboards that provides sensor readouts via WMI * HWMON driver for ASUS motherboards that provides sensor readouts via WMI
* interface present in the UEFI of the X370/X470/B450/X399 Ryzen motherboards. * interface present in the UEFI of the X370/X470/B450/X399 Ryzen motherboards.
* *
* Copyright (C) 2021 Eugene Shalygin <eugene.shalygin@gmail.com>
* Copyright (C) 2018-2019 Ed Brindley <kernel@maidavale.org> * Copyright (C) 2018-2019 Ed Brindley <kernel@maidavale.org>
* *
* WMI interface provided: * WMI interface provides:
* CPU Core Voltage, * CPU Core Voltage,
* CPU SOC Voltage, * CPU SOC Voltage,
* DRAM Voltage, * DRAM Voltage,
@ -21,15 +20,15 @@
* CPU Core Voltage, * CPU Core Voltage,
* CPU SOC Voltage, * CPU SOC Voltage,
* DRAM Voltage, * DRAM Voltage,
* CPU Fan, * CPU Fan RPM,
* Chassis Fan 1, * Chassis Fan 1 RPM,
* Chassis Fan 2, * Chassis Fan 2 RPM,
* Chassis Fan 3, * Chassis Fan 3 RPM,
* HAMP Fan, * HAMP Fan RPM,
* Water Pump, * Water Pump RPM,
* CPU OPT, * CPU OPT RPM,
* Water Flow, * Water Flow RPM,
* AIO Pump, * AIO Pump RPM,
* CPU Temperature, * CPU Temperature,
* CPU Socket Temperature, * CPU Socket Temperature,
* Motherboard Temperature, * Motherboard Temperature,
@ -39,6 +38,7 @@
* Water In, * Water In,
* Water Out, * Water Out,
* CPU VRM Output Current. * CPU VRM Output Current.
*
*/ */
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/dmi.h> #include <linux/dmi.h>
@ -62,24 +62,34 @@
#define ASUS_WMI_MAX_STR_SIZE 32 #define ASUS_WMI_MAX_STR_SIZE 32
/* boards with wmi sensors support */ #define DMI_EXACT_MATCH_ASUS_BOARD_NAME(name) \
static const char *const asus_wmi_boards_names[] = { { \
"ROG CROSSHAIR VI HERO", .matches = { \
"PRIME X399-A", DMI_EXACT_MATCH(DMI_BOARD_VENDOR, \
"PRIME X470-PRO", "ASUSTeK COMPUTER INC."), \
"ROG CROSSHAIR VI EXTREME", DMI_EXACT_MATCH(DMI_BOARD_NAME, name), \
"ROG CROSSHAIR VI HERO (WI-FI AC)", }, \
"ROG CROSSHAIR VII HERO", }
"ROG CROSSHAIR VII HERO (WI-FI)",
"ROG STRIX B450-E GAMING", static const struct dmi_system_id asus_wmi_dmi_table[] __initconst = {
"ROG STRIX B450-F GAMING", DMI_EXACT_MATCH_ASUS_BOARD_NAME("PRIME X399-A"),
"ROG STRIX B450-I GAMING", DMI_EXACT_MATCH_ASUS_BOARD_NAME("PRIME X470-PRO"),
"ROG STRIX X399-E GAMING", DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VI EXTREME"),
"ROG STRIX X470-F GAMING", DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VI HERO"),
"ROG STRIX X470-I GAMING", DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VI HERO (WI-FI AC)"),
"ROG ZENITH EXTREME", DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VII HERO"),
"ROG ZENITH EXTREME ALPHA", DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VII HERO (WI-FI)"),
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX B450-E GAMING"),
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX B450-F GAMING"),
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX B450-I GAMING"),
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX X399-E GAMING"),
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX X470-F GAMING"),
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX X470-I GAMING"),
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG ZENITH EXTREME"),
DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG ZENITH EXTREME ALPHA"),
{}
}; };
MODULE_DEVICE_TABLE(dmi, asus_wmi_dmi_table);
enum asus_wmi_sensor_class { enum asus_wmi_sensor_class {
VOLTAGE = 0x0, VOLTAGE = 0x0,
@ -150,7 +160,7 @@ struct asus_wmi_sensor_info {
struct asus_wmi_wmi_info { struct asus_wmi_wmi_info {
u8 buffer; u8 buffer;
unsigned long source_last_updated[3]; /* in jiffies */ unsigned long source_last_updated[3]; /* in jiffies */
u8 sensor_count; int sensor_count;
const struct asus_wmi_sensor_info **info[hwmon_max]; const struct asus_wmi_sensor_info **info[hwmon_max];
struct asus_wmi_sensor_info **info_by_id; struct asus_wmi_sensor_info **info_by_id;
@ -160,13 +170,6 @@ struct asus_wmi_sensors {
/* lock access to instrnal cache */ /* lock access to instrnal cache */
struct mutex lock; struct mutex lock;
struct asus_wmi_wmi_info wmi; struct asus_wmi_wmi_info wmi;
int wmi_board;
};
struct asus_wmi_data {
int wmi_board;
int wmi_count;
}; };
/* /*
@ -405,10 +408,8 @@ static int asus_wmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
sensor = *(sensor_data->wmi.info[type] + channel); sensor = *(sensor_data->wmi.info[type] + channel);
mutex_lock(&sensor_data->lock); mutex_lock(&sensor_data->lock);
ret = asus_wmi_get_cached_value_or_update(sensor, sensor_data, &value); ret = asus_wmi_get_cached_value_or_update(sensor, sensor_data, &value);
mutex_unlock(&sensor_data->lock); mutex_unlock(&sensor_data->lock);
if (!ret) if (!ret)
*val = asus_wmi_scale_sensor_value(value, sensor->data_type); *val = asus_wmi_scale_sensor_value(value, sensor->data_type);
@ -555,8 +556,7 @@ static int asus_wmi_configure_sensor_setup(struct platform_device *pdev,
} }
} }
dev_dbg(&pdev->dev, "%s board has %d sensors", dev_dbg(&pdev->dev, "board has %d sensors",
asus_wmi_boards_names[sensor_data->wmi_board],
sensor_data->wmi.sensor_count); sensor_data->wmi.sensor_count);
hwdev = devm_hwmon_device_register_with_info(dev, KBUILD_MODNAME, hwdev = devm_hwmon_device_register_with_info(dev, KBUILD_MODNAME,
@ -569,24 +569,35 @@ static int asus_wmi_probe(struct platform_device *pdev)
{ {
struct asus_wmi_sensors *sensor_data; struct asus_wmi_sensors *sensor_data;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct asus_wmi_data *data; u32 version = 0;
data = dev_get_platdata(dev);
sensor_data = devm_kzalloc(dev, sizeof(struct asus_wmi_sensors), sensor_data = devm_kzalloc(dev, sizeof(struct asus_wmi_sensors),
GFP_KERNEL); GFP_KERNEL);
if (!sensor_data) if (!sensor_data)
return -ENOMEM; return -ENOMEM;
if (!wmi_has_guid(ASUSWMI_MONITORING_GUID))
return -ENODEV;
if (asus_wmi_get_version(&version))
return -ENODEV;
if (asus_wmi_get_item_count(&sensor_data->wmi.sensor_count))
return -ENODEV;
if (sensor_data->wmi.sensor_count <= 0 || version < 2) {
dev_info(dev, "version: %u with %d sensors is unsupported\n",
version, sensor_data->wmi.sensor_count);
return -ENODEV;
}
mutex_init(&sensor_data->lock); mutex_init(&sensor_data->lock);
sensor_data->wmi_board = data->wmi_board;
sensor_data->wmi.sensor_count = data->wmi_count;
platform_set_drvdata(pdev, sensor_data); platform_set_drvdata(pdev, sensor_data);
return asus_wmi_configure_sensor_setup(pdev, return asus_wmi_configure_sensor_setup(pdev,
sensor_data); sensor_data);
return 0;
} }
static struct platform_driver asus_wmi_sensors_platform_driver = { static struct platform_driver asus_wmi_sensors_platform_driver = {
@ -600,49 +611,13 @@ static struct platform_device *sensors_pdev;
static int __init asus_wmi_init(void) static int __init asus_wmi_init(void)
{ {
const char *board_vendor, *board_name; if (!dmi_check_system(asus_wmi_dmi_table))
u32 version = 0;
struct asus_wmi_data data;
data.wmi_board = -1;
data.wmi_count = 0;
board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
board_name = dmi_get_system_info(DMI_BOARD_NAME);
if (board_vendor && board_name &&
!strcmp(board_vendor, "ASUSTeK COMPUTER INC.")) {
if (!wmi_has_guid(ASUSWMI_MONITORING_GUID))
return -ENODEV;
data.wmi_board = match_string(asus_wmi_boards_names,
ARRAY_SIZE(asus_wmi_boards_names),
board_name);
if (data.wmi_board >= 0) {
if (asus_wmi_get_item_count(&data.wmi_count))
return -ENODEV;
if (asus_wmi_get_version(&version))
return -ENODEV;
if (data.wmi_count <= 0 || version < 2) {
pr_err("Board: %s WMI wmi version: %u with %d sensors is unsupported\n",
board_name, version, data.wmi_count);
data.wmi_board = -ENODEV;
}
}
}
/* Nothing to support */
if (data.wmi_board < 0)
return -ENODEV; return -ENODEV;
sensors_pdev = platform_create_bundle(&asus_wmi_sensors_platform_driver, sensors_pdev = platform_create_bundle(&asus_wmi_sensors_platform_driver,
asus_wmi_probe, asus_wmi_probe,
NULL, 0, NULL, 0,
&data, sizeof(struct asus_wmi_data)); NULL, 0);
return PTR_ERR_OR_ZERO(sensors_pdev); return PTR_ERR_OR_ZERO(sensors_pdev);
} }
@ -656,6 +631,5 @@ static void __exit asus_wmi_exit(void)
module_exit(asus_wmi_exit); module_exit(asus_wmi_exit);
MODULE_AUTHOR("Ed Brindley <kernel@maidavale.org>"); MODULE_AUTHOR("Ed Brindley <kernel@maidavale.org>");
MODULE_AUTHOR("Eugene Shalygin <eugene.shalygin@gmail.com>");
MODULE_DESCRIPTION("Asus WMI Sensors Driver"); MODULE_DESCRIPTION("Asus WMI Sensors Driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");