UBUNTU: ODM: hwmon: add driver for AAEON devices
BugLink: https://bugs.launchpad.net/bugs/1929504 This refator patch adds support for the hwmon information which are transported to userspace through ASUS WMI interface. Signed-off-by: Kunyang_Fan <kunyang_fan@asus.com> Review-by: Kai-Heng Feng <kai.heng.feng@canonical.com> Review-by: Chia-Lin Kao (AceLan) <acelan.kao@canonical.com> Signed-off-by: Chia-Lin Kao (AceLan) <acelan.kao@canonical.com> Acked-by: Stefan Bader <stefan.bader@canonical.com> Acked-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com> Signed-off-by: Andrea Righi <andrea.righi@canonical.com>
This commit is contained in:
committed by
Paolo Pisati
parent
8f49f5e43b
commit
1e6e88c0d9
@@ -38,6 +38,18 @@ config HWMON_DEBUG_CHIP
|
||||
|
||||
comment "Native drivers"
|
||||
|
||||
config SENSORS_AAEON
|
||||
tristate "AAEON hwmon driver"
|
||||
depends on X86
|
||||
depends on UBUNTU_ODM_DRIVERS
|
||||
select MFD_AAEON
|
||||
help
|
||||
This hwmon driver adds support for reporting temperature or fan
|
||||
speed and voltage on Single Board Computers produced by AAEON.
|
||||
|
||||
This driver leverages the ASUS WMI interface to access device
|
||||
resources.
|
||||
|
||||
config SENSORS_ABITUGURU
|
||||
tristate "Abit uGuru (rev 1 & 2)"
|
||||
depends on (X86 && DMI) || COMPILE_TEST
|
||||
|
||||
@@ -15,6 +15,7 @@ obj-$(CONFIG_SENSORS_HP_WMI) += hp-wmi-sensors.o
|
||||
|
||||
# Native drivers
|
||||
# asb100, then w83781d go first, as they can override other drivers' addresses.
|
||||
obj-$(CONFIG_SENSORS_AAEON) += hwmon-aaeon.o
|
||||
obj-$(CONFIG_SENSORS_ASB100) += asb100.o
|
||||
obj-$(CONFIG_SENSORS_W83627HF) += w83627hf.o
|
||||
obj-$(CONFIG_SENSORS_W83773G) += w83773g.o
|
||||
|
||||
@@ -0,0 +1,568 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* AAEON HWMON driver
|
||||
* Copyright (c) 2021, AAEON Ltd.
|
||||
*
|
||||
* Author: Edward Lin <edward1_lin@aaeon.com.tw>
|
||||
* Author: Kunyang Fan <kunyang_fan@aaeon.com.tw>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/platform_data/x86/asus-wmi.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#define DRVNAME "hwmon-aaeon"
|
||||
|
||||
#define AAEON_WMI_MGMT_GUID "97845ED0-4E6D-11DE-8A39-0800200C9A66"
|
||||
|
||||
#define AAEON_VERSION_METHOD_ID 0x00000000
|
||||
#define HWM_INFORMATION_METHOD_ID 0x00030000
|
||||
#define HWM_METHOD_ID 0x00030001
|
||||
|
||||
#define BITMAP_TEMP_ARG 0x12
|
||||
#define BITMAP_FAN_ARG 0x13
|
||||
#define BITMAP_VOLTAGE_ARG 0x14
|
||||
|
||||
#define SENSOR_TEMP_NUMBER 0
|
||||
#define SENSOR_FAN_NUMBER 1
|
||||
#define SENSOR_VOLTAGE_NUMBER 2
|
||||
#define SENSOR_MAX_NUMBER 2
|
||||
|
||||
static ssize_t aaeon_show_sensor(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf);
|
||||
static ssize_t aaeon_show_sensor_name(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
char *buf);
|
||||
static ssize_t aaeon_show_version(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf);
|
||||
static ssize_t name_show(struct device *dev, struct device_attribute *devattr,
|
||||
char *buf);
|
||||
static int aaeon_get_version(void);
|
||||
static int aaeon_hwmon_probe(struct platform_device *pdev);
|
||||
static int aaeon_hwmon_remove(struct platform_device *pdev);
|
||||
|
||||
static const char * const temp_sensors_name_table[] = {
|
||||
"CPU_Temp",
|
||||
"SYS1_Temp",
|
||||
"SYS2_Temp",
|
||||
};
|
||||
|
||||
static const char * const temp_sensors_name_table_V3[] = {
|
||||
"SYS_Temp",
|
||||
"CPU_Temp",
|
||||
};
|
||||
|
||||
static const char * const fan_sensors_name_table[] = {
|
||||
"CPU_FAN",
|
||||
"SYS1_FAN",
|
||||
"SYS2_FAN",
|
||||
"Chasis1_FAN",
|
||||
"Chasis2_FAN",
|
||||
};
|
||||
|
||||
static const char * const fan_sensors_name_table_V3[] = {
|
||||
"Chasis_FAN",
|
||||
"CPU_FAN",
|
||||
};
|
||||
|
||||
static const char * const voltage_sensors_name_table[] = {
|
||||
"VCORE_Voltage",
|
||||
"VMEM_Voltage",
|
||||
"+12_Voltage",
|
||||
"+5_Voltage",
|
||||
"+3.3_Voltage",
|
||||
"+1.8_Voltage",
|
||||
"5VSB_Voltage",
|
||||
"3VSB_Voltage",
|
||||
"VBAT_Voltage",
|
||||
};
|
||||
|
||||
static const char * const voltage_sensors_name_table_V3[] = {
|
||||
"VCORE_Voltage",
|
||||
"+5_Voltage",
|
||||
"AVCC_Voltage",
|
||||
"+3.3_Voltage",
|
||||
"+12_Voltage",
|
||||
"VCOREREFIN_Voltage",
|
||||
"VIN4_Voltage",
|
||||
"3VSB_Voltage",
|
||||
"VBAT_Voltage",
|
||||
};
|
||||
|
||||
struct aaeon_hwmon_data {
|
||||
struct device *hwmon_dev;
|
||||
int bfpi_version;
|
||||
u32 temp_bitmap;
|
||||
u32 fan_bitmap;
|
||||
u32 voltage_bitmap;
|
||||
unsigned int sensors_number[SENSOR_MAX_NUMBER + 1];
|
||||
const char * const *temp_names;
|
||||
const char * const *fan_names;
|
||||
const char * const *voltage_names;
|
||||
};
|
||||
|
||||
/* Temperature attributes */
|
||||
static struct sensor_device_attribute_2 temp_sys_nodes_atts[] = {
|
||||
SENSOR_ATTR_2(temp1_input, 0444, aaeon_show_sensor, NULL,
|
||||
SENSOR_TEMP_NUMBER, 0),
|
||||
SENSOR_ATTR_2(temp1_label, 0444, aaeon_show_sensor_name, NULL,
|
||||
SENSOR_TEMP_NUMBER, 0),
|
||||
SENSOR_ATTR_2(temp2_input, 0444, aaeon_show_sensor, NULL,
|
||||
SENSOR_TEMP_NUMBER, 1),
|
||||
SENSOR_ATTR_2(temp2_label, 0444, aaeon_show_sensor_name, NULL,
|
||||
SENSOR_TEMP_NUMBER, 1),
|
||||
SENSOR_ATTR_2(temp3_input, 0444, aaeon_show_sensor, NULL,
|
||||
SENSOR_TEMP_NUMBER, 2),
|
||||
SENSOR_ATTR_2(temp3_label, 0444, aaeon_show_sensor_name, NULL,
|
||||
SENSOR_TEMP_NUMBER, 2),
|
||||
};
|
||||
|
||||
/* Cooler Fan attributes */
|
||||
static struct sensor_device_attribute_2 fan_sys_nodes_atts[] = {
|
||||
SENSOR_ATTR_2(fan1_input, 0444, aaeon_show_sensor, NULL,
|
||||
SENSOR_FAN_NUMBER, 0),
|
||||
SENSOR_ATTR_2(fan1_label, 0444, aaeon_show_sensor_name, NULL,
|
||||
SENSOR_FAN_NUMBER, 0),
|
||||
SENSOR_ATTR_2(fan2_input, 0444, aaeon_show_sensor, NULL,
|
||||
SENSOR_FAN_NUMBER, 1),
|
||||
SENSOR_ATTR_2(fan2_label, 0444, aaeon_show_sensor_name, NULL,
|
||||
SENSOR_FAN_NUMBER, 1),
|
||||
SENSOR_ATTR_2(fan3_input, 0444, aaeon_show_sensor, NULL,
|
||||
SENSOR_FAN_NUMBER, 2),
|
||||
SENSOR_ATTR_2(fan3_label, 0444, aaeon_show_sensor_name, NULL,
|
||||
SENSOR_FAN_NUMBER, 2),
|
||||
SENSOR_ATTR_2(fan4_input, 0444, aaeon_show_sensor, NULL,
|
||||
SENSOR_FAN_NUMBER, 3),
|
||||
SENSOR_ATTR_2(fan4_label, 0444, aaeon_show_sensor_name, NULL,
|
||||
SENSOR_FAN_NUMBER, 3),
|
||||
SENSOR_ATTR_2(fan5_input, 0444, aaeon_show_sensor, NULL,
|
||||
SENSOR_FAN_NUMBER, 4),
|
||||
SENSOR_ATTR_2(fan5_label, 0444, aaeon_show_sensor_name, NULL,
|
||||
SENSOR_FAN_NUMBER, 4),
|
||||
};
|
||||
|
||||
/* Voltage attributes */
|
||||
static struct sensor_device_attribute_2 voltage_sys_nodes_atts[] = {
|
||||
SENSOR_ATTR_2(in1_input, 0444, aaeon_show_sensor, NULL,
|
||||
SENSOR_VOLTAGE_NUMBER, 0),
|
||||
SENSOR_ATTR_2(in1_label, 0444, aaeon_show_sensor_name, NULL,
|
||||
SENSOR_VOLTAGE_NUMBER, 0),
|
||||
SENSOR_ATTR_2(in2_input, 0444, aaeon_show_sensor, NULL,
|
||||
SENSOR_VOLTAGE_NUMBER, 1),
|
||||
SENSOR_ATTR_2(in2_label, 0444, aaeon_show_sensor_name, NULL,
|
||||
SENSOR_VOLTAGE_NUMBER, 1),
|
||||
SENSOR_ATTR_2(in3_input, 0444, aaeon_show_sensor, NULL,
|
||||
SENSOR_VOLTAGE_NUMBER, 2),
|
||||
SENSOR_ATTR_2(in3_label, 0444, aaeon_show_sensor_name, NULL,
|
||||
SENSOR_VOLTAGE_NUMBER, 2),
|
||||
SENSOR_ATTR_2(in4_input, 0444, aaeon_show_sensor, NULL,
|
||||
SENSOR_VOLTAGE_NUMBER, 3),
|
||||
SENSOR_ATTR_2(in4_label, 0444, aaeon_show_sensor_name, NULL,
|
||||
SENSOR_VOLTAGE_NUMBER, 3),
|
||||
SENSOR_ATTR_2(in5_input, 0444, aaeon_show_sensor, NULL,
|
||||
SENSOR_VOLTAGE_NUMBER, 4),
|
||||
SENSOR_ATTR_2(in5_label, 0444, aaeon_show_sensor_name, NULL,
|
||||
SENSOR_VOLTAGE_NUMBER, 4),
|
||||
SENSOR_ATTR_2(in6_input, 0444, aaeon_show_sensor, NULL,
|
||||
SENSOR_VOLTAGE_NUMBER, 5),
|
||||
SENSOR_ATTR_2(in6_label, 0444, aaeon_show_sensor_name, NULL,
|
||||
SENSOR_VOLTAGE_NUMBER, 5),
|
||||
SENSOR_ATTR_2(in7_input, 0444, aaeon_show_sensor, NULL,
|
||||
SENSOR_VOLTAGE_NUMBER, 6),
|
||||
SENSOR_ATTR_2(in7_label, 0444, aaeon_show_sensor_name, NULL,
|
||||
SENSOR_VOLTAGE_NUMBER, 6),
|
||||
SENSOR_ATTR_2(in8_input, 0444, aaeon_show_sensor, NULL,
|
||||
SENSOR_VOLTAGE_NUMBER, 7),
|
||||
SENSOR_ATTR_2(in8_label, 0444, aaeon_show_sensor_name, NULL,
|
||||
SENSOR_VOLTAGE_NUMBER, 7),
|
||||
SENSOR_ATTR_2(in9_input, 0444, aaeon_show_sensor, NULL,
|
||||
SENSOR_VOLTAGE_NUMBER, 8),
|
||||
SENSOR_ATTR_2(in9_label, 0444, aaeon_show_sensor_name, NULL,
|
||||
SENSOR_VOLTAGE_NUMBER, 8),
|
||||
|
||||
};
|
||||
|
||||
static struct sensor_device_attribute_2 info_sys_nodes_atts[] = {
|
||||
/* WMI version Information */
|
||||
SENSOR_ATTR_2(AAEON_VERSION, 0444, aaeon_show_version, NULL, 0, 0),
|
||||
};
|
||||
|
||||
DEVICE_ATTR_RO(name);
|
||||
static ssize_t name_show(struct device *dev, struct device_attribute *devattr,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf(buf, "%s\n", DRVNAME);
|
||||
}
|
||||
|
||||
static ssize_t aaeon_show_version(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
struct aaeon_hwmon_data *data =
|
||||
(struct aaeon_hwmon_data *)dev_get_drvdata(dev);
|
||||
|
||||
return sprintf(buf, "%d\n", data->bfpi_version);
|
||||
}
|
||||
|
||||
static ssize_t aaeon_show_sensor_name(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
u8 nr = to_sensor_dev_attr_2(devattr)->nr;
|
||||
u8 index = to_sensor_dev_attr_2(devattr)->index;
|
||||
struct aaeon_hwmon_data *data =
|
||||
(struct aaeon_hwmon_data *)dev_get_drvdata(dev);
|
||||
|
||||
if (nr > SENSOR_MAX_NUMBER || index >= data->sensors_number[nr]) {
|
||||
pr_debug("Can not check the device");
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (nr) {
|
||||
case SENSOR_TEMP_NUMBER:
|
||||
return sprintf(buf, "%s\n", data->temp_names[index]);
|
||||
case SENSOR_FAN_NUMBER:
|
||||
return sprintf(buf, "%s\n", data->fan_names[index]);
|
||||
case SENSOR_VOLTAGE_NUMBER:
|
||||
return sprintf(buf, "%s\n", data->voltage_names[index]);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t aaeon_show_sensor(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
u8 nr = to_sensor_dev_attr_2(devattr)->nr;
|
||||
u8 index = to_sensor_dev_attr_2(devattr)->index;
|
||||
u32 dev_id;
|
||||
int retval, err;
|
||||
struct aaeon_hwmon_data *data =
|
||||
(struct aaeon_hwmon_data *)dev_get_drvdata(dev);
|
||||
|
||||
if (nr > SENSOR_MAX_NUMBER || index >= data->sensors_number[nr]) {
|
||||
pr_debug("Can not check the device");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* For the V3 version, index need offset */
|
||||
if (data->bfpi_version == 0x03 && nr != SENSOR_VOLTAGE_NUMBER)
|
||||
index++;
|
||||
|
||||
dev_id = (index << 12) | (nr << 8);
|
||||
err = asus_wmi_evaluate_method(HWM_METHOD_ID, dev_id, 0, &retval);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* For the V3 version, need to convert the raw value*/
|
||||
if (nr == SENSOR_VOLTAGE_NUMBER && data->bfpi_version == 0x03) {
|
||||
switch (index) {
|
||||
case 0: /* VCORE */
|
||||
retval = retval * 16;
|
||||
break;
|
||||
case 1: /* +5V */
|
||||
retval = (retval * 2008) / 50;
|
||||
break;
|
||||
case 2: /* AVCC */
|
||||
retval = retval * 16;
|
||||
break;
|
||||
case 3: /* +3.3V */
|
||||
retval = retval * 16;
|
||||
break;
|
||||
case 4: /* +12V */
|
||||
retval = retval * 96;
|
||||
break;
|
||||
case 5: /* VCOREREFIN */
|
||||
retval = (retval * 552) / 41;
|
||||
break;
|
||||
case 6: /* VIN4 */
|
||||
retval = retval * 8;
|
||||
break;
|
||||
case 7: /* 3VSB */
|
||||
retval = retval * 16;
|
||||
break;
|
||||
case 8: /* VBAT */
|
||||
retval = retval * 16;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (nr == SENSOR_TEMP_NUMBER && data->bfpi_version == 0x03)
|
||||
retval = retval * 1000;
|
||||
|
||||
return sprintf(buf, "%d\n", retval);
|
||||
}
|
||||
|
||||
static int aaeon_hwmon_create_sub_sysfs_fs(struct platform_device *pdev,
|
||||
struct sensor_device_attribute_2 *attr,
|
||||
int sensor_number,
|
||||
u32 sensor_mask,
|
||||
int bfpi_version)
|
||||
{
|
||||
int i, err = 0;
|
||||
|
||||
for (i = 0; i < sensor_number; i++) {
|
||||
if (bfpi_version == 0x03 || sensor_mask & BIT(i)) {
|
||||
err = device_create_file(&pdev->dev, &attr[2 * i].dev_attr);
|
||||
if (err)
|
||||
break;
|
||||
err = device_create_file(&pdev->dev, &attr[2 * i + 1].dev_attr);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
aaeon_hwmon_create_sysfs_files(struct platform_device *pdev, struct aaeon_hwmon_data *data)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* register sysfs interface files */
|
||||
err = device_create_file(&pdev->dev, &dev_attr_name);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* registe sysfs to dump sensors BFPI version */
|
||||
err = device_create_file(&pdev->dev, &info_sys_nodes_atts[0].dev_attr);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* create temperature name and value node */
|
||||
err = aaeon_hwmon_create_sub_sysfs_fs(pdev, temp_sys_nodes_atts,
|
||||
data->sensors_number[SENSOR_TEMP_NUMBER],
|
||||
data->temp_bitmap, data->bfpi_version);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* create fan name and value node */
|
||||
err = aaeon_hwmon_create_sub_sysfs_fs(pdev, fan_sys_nodes_atts,
|
||||
data->sensors_number[SENSOR_FAN_NUMBER],
|
||||
data->fan_bitmap, data->bfpi_version);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* create voltage name and value node */
|
||||
err = aaeon_hwmon_create_sub_sysfs_fs(pdev, voltage_sys_nodes_atts,
|
||||
data->sensors_number[SENSOR_VOLTAGE_NUMBER],
|
||||
data->voltage_bitmap, data->bfpi_version);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void aaeon_hwmon_remove_sub_sysfs_fs(struct platform_device *pdev,
|
||||
struct sensor_device_attribute_2 *attr,
|
||||
int sensor_number,
|
||||
u32 sensor_mask,
|
||||
int bfpi_version)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sensor_number; i++) {
|
||||
if (bfpi_version == 0x03 || sensor_mask & BIT(i)) {
|
||||
device_remove_file(&pdev->dev, &attr[2 * i].dev_attr);
|
||||
device_remove_file(&pdev->dev, &attr[2 * i + 1].dev_attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
aaeon_hwmon_remove_sysfs_files(struct platform_device *pdev,
|
||||
struct aaeon_hwmon_data *data)
|
||||
{
|
||||
/* degister sysfs interface files */
|
||||
device_remove_file(&pdev->dev, &dev_attr_name);
|
||||
|
||||
/* degiste sysfs to dump sensors BFPI version */
|
||||
device_remove_file(&pdev->dev, &info_sys_nodes_atts[0].dev_attr);
|
||||
|
||||
/* remove temperature name and value node */
|
||||
aaeon_hwmon_remove_sub_sysfs_fs(pdev, temp_sys_nodes_atts,
|
||||
data->sensors_number[SENSOR_TEMP_NUMBER],
|
||||
data->temp_bitmap,
|
||||
data->bfpi_version);
|
||||
|
||||
/* remove fan name and value node */
|
||||
aaeon_hwmon_remove_sub_sysfs_fs(pdev, fan_sys_nodes_atts,
|
||||
data->sensors_number[SENSOR_FAN_NUMBER],
|
||||
data->fan_bitmap,
|
||||
data->bfpi_version);
|
||||
|
||||
/* remove voltage name and value node */
|
||||
aaeon_hwmon_remove_sub_sysfs_fs(pdev, voltage_sys_nodes_atts,
|
||||
data->sensors_number[SENSOR_VOLTAGE_NUMBER],
|
||||
data->voltage_bitmap,
|
||||
data->bfpi_version);
|
||||
}
|
||||
|
||||
static int aaeon_hwmon_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct aaeon_hwmon_data *data = platform_get_drvdata(pdev);
|
||||
|
||||
if (data->hwmon_dev)
|
||||
hwmon_device_unregister(data->hwmon_dev);
|
||||
|
||||
aaeon_hwmon_remove_sysfs_files(pdev, data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aaeon_get_version(void)
|
||||
{
|
||||
int err, retval;
|
||||
u32 dev_id = 0x00;
|
||||
|
||||
err = asus_wmi_evaluate_method(AAEON_VERSION_METHOD_ID, dev_id, 0,
|
||||
&retval);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int aaeon_hwmon_init_drv_data(struct aaeon_hwmon_data *data)
|
||||
{
|
||||
int err;
|
||||
|
||||
data->bfpi_version = aaeon_get_version();
|
||||
if (data->bfpi_version < 0) {
|
||||
pr_debug("Error BFPI verion\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (data->bfpi_version == 0x03) {
|
||||
/* set the number of bits in temp bitmap */
|
||||
data->sensors_number[SENSOR_TEMP_NUMBER] =
|
||||
ARRAY_SIZE(temp_sensors_name_table_V3);
|
||||
data->temp_names = temp_sensors_name_table_V3;
|
||||
|
||||
/* set the number of bits in fan bitmap */
|
||||
data->sensors_number[SENSOR_FAN_NUMBER] =
|
||||
ARRAY_SIZE(fan_sensors_name_table_V3);
|
||||
data->fan_names = fan_sensors_name_table_V3;
|
||||
|
||||
/* set the number of bits in voltage bitmap */
|
||||
data->sensors_number[SENSOR_VOLTAGE_NUMBER] =
|
||||
ARRAY_SIZE(voltage_sensors_name_table_V3);
|
||||
data->voltage_names = voltage_sensors_name_table_V3;
|
||||
} else {
|
||||
/* set the number of bits in temp bitmap */
|
||||
data->sensors_number[SENSOR_TEMP_NUMBER] =
|
||||
ARRAY_SIZE(temp_sensors_name_table);
|
||||
data->temp_names = temp_sensors_name_table;
|
||||
|
||||
/* set the number of bits in fan bitmap */
|
||||
data->sensors_number[SENSOR_FAN_NUMBER] =
|
||||
ARRAY_SIZE(fan_sensors_name_table);
|
||||
data->fan_names = fan_sensors_name_table;
|
||||
|
||||
/* set the number of bits in voltage bitmap */
|
||||
data->sensors_number[SENSOR_VOLTAGE_NUMBER] =
|
||||
ARRAY_SIZE(voltage_sensors_name_table);
|
||||
data->voltage_names = voltage_sensors_name_table;
|
||||
}
|
||||
|
||||
/* get temp supported bitmap */
|
||||
err = asus_wmi_evaluate_method(HWM_INFORMATION_METHOD_ID,
|
||||
BITMAP_TEMP_ARG, 0, &data->temp_bitmap);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* get fan supported bitmap */
|
||||
err = asus_wmi_evaluate_method(HWM_INFORMATION_METHOD_ID,
|
||||
BITMAP_FAN_ARG, 0, &data->fan_bitmap);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* get voltage supported bitmap */
|
||||
err = asus_wmi_evaluate_method(HWM_INFORMATION_METHOD_ID,
|
||||
BITMAP_VOLTAGE_ARG, 0, &data->voltage_bitmap);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aaeon_hwmon_probe(struct platform_device *pdev)
|
||||
{
|
||||
int err;
|
||||
struct aaeon_hwmon_data *data;
|
||||
|
||||
pr_debug("aaeon hwomon device probe (support V3)!\n");
|
||||
if (!wmi_has_guid(AAEON_WMI_MGMT_GUID)) {
|
||||
pr_info("AAEON Management GUID not found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
data = devm_kzalloc(&pdev->dev, sizeof(struct aaeon_hwmon_data),
|
||||
GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
err = aaeon_hwmon_init_drv_data(data);
|
||||
if (err) {
|
||||
pr_info("Error to get sensor support bitmap\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (data->bfpi_version != 0x03 && data->temp_bitmap == 0 &&
|
||||
data->fan_bitmap == 0 && data->voltage_bitmap == 0) {
|
||||
pr_debug("No sensors found\n");
|
||||
err = -ENODEV;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, data);
|
||||
err = aaeon_hwmon_create_sysfs_files(pdev, data);
|
||||
if (err)
|
||||
goto exit;
|
||||
|
||||
data->hwmon_dev = devm_hwmon_device_register_with_info(&pdev->dev,
|
||||
"AAEON_HWM",
|
||||
data,
|
||||
NULL,
|
||||
NULL);
|
||||
if (IS_ERR(data->hwmon_dev)) {
|
||||
err = PTR_ERR(data->hwmon_dev);
|
||||
data->hwmon_dev = NULL;
|
||||
goto exit_unregister_sysfs;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
exit_unregister_sysfs:
|
||||
aaeon_hwmon_remove(pdev);
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct platform_driver aaeon_hwmon_driver = {
|
||||
.driver = {
|
||||
.name = DRVNAME,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = aaeon_hwmon_probe,
|
||||
.remove = aaeon_hwmon_remove,
|
||||
};
|
||||
|
||||
module_platform_driver_probe(aaeon_hwmon_driver, aaeon_hwmon_probe);
|
||||
|
||||
MODULE_ALIAS("platform:hwmon-aaeon");
|
||||
MODULE_DESCRIPTION("AAEON Hardware Monitoring Driver");
|
||||
MODULE_AUTHOR("Edward Lin <edward1_lin@aaeon.com.tw>");
|
||||
MODULE_AUTHOR("Kunyang Fan <kunyang_fan@aaeon.com.tw>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
Reference in New Issue
Block a user