FILE
asus-ec-sensors.c
File preview with syntax highlighting.
linux-6.19.14/drivers/hwmon/asus-ec-sensors.c
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * HWMON driver for ASUS motherboards that publish some sensor values 4 * via the embedded controller registers. 5 * 6 * Copyright (C) 2021 Eugene Shalygin <eugene.shalygin@gmail.com> 7 8 * EC provides: 9 * - Chipset temperature 10 * - CPU temperature 11 * - Motherboard temperature 12 * - T_Sensor temperature 13 * - VRM temperature 14 * - Water In temperature 15 * - Water Out temperature 16 * - CPU Optional fan RPM 17 * - Chipset fan RPM 18 * - VRM Heat Sink fan RPM 19 * - Water Flow fan RPM 20 * - CPU current 21 * - CPU core voltage 22 */ 23 24#include <linux/acpi.h> 25#include <linux/bitops.h> 26#include <linux/dev_printk.h> 27#include <linux/dmi.h> 28#include <linux/hwmon.h> 29#include <linux/init.h> 30#include <linux/jiffies.h> 31#include <linux/kernel.h> 32#include <linux/module.h> 33#include <linux/platform_device.h> 34#include <linux/sort.h> 35#include <linux/units.h> 36 37#include <linux/unaligned.h> 38 39static char *mutex_path_override; 40 41/* Writing to this EC register switches EC bank */ 42#define ASUS_EC_BANK_REGISTER 0xff 43#define SENSOR_LABEL_LEN 16 44 45/* 46 * Arbitrary set max. allowed bank number. Required for sorting banks and 47 * currently is overkill with just 2 banks used at max, but for the sake 48 * of alignment let's set it to a higher value. 49 */ 50#define ASUS_EC_MAX_BANK 3 51 52#define ACPI_LOCK_DELAY_MS 800 53 54/* ACPI mutex for locking access to the EC for the firmware */ 55#define ASUS_HW_ACCESS_MUTEX_ASMX "\\AMW0.ASMX" 56 57#define ASUS_HW_ACCESS_MUTEX_RMTW_ASMX "\\RMTW.ASMX" 58 59#define ASUS_HW_ACCESS_MUTEX_SB_PC00_LPCB_SIO1_MUT0 "\\_SB.PC00.LPCB.SIO1.MUT0" 60 61#define ASUS_HW_ACCESS_MUTEX_SB_PCI0_SBRG_SIO1_MUT0 "\\_SB_.PCI0.SBRG.SIO1.MUT0" 62 63#define ASUS_HW_ACCESS_MUTEX_SB_PCI0_LPCB_SIO1_MUT0 "\\_SB_.PCI0.LPCB.SIO1.MUT0" 64 65#define MAX_IDENTICAL_BOARD_VARIATIONS 3 66 67/* Moniker for the ACPI global lock (':' is not allowed in ASL identifiers) */ 68#define ACPI_GLOBAL_LOCK_PSEUDO_PATH ":GLOBAL_LOCK" 69 70typedef union { 71 u32 value; 72 struct { 73 u8 index; 74 u8 bank; 75 u8 size; 76 u8 dummy; 77 } components; 78} sensor_address; 79 80#define MAKE_SENSOR_ADDRESS(size, bank, index) { \ 81 .value = (size << 16) + (bank << 8) + index \ 82 } 83 84static u32 hwmon_attributes[hwmon_max] = { 85 [hwmon_chip] = HWMON_C_REGISTER_TZ, 86 [hwmon_temp] = HWMON_T_INPUT | HWMON_T_LABEL, 87 [hwmon_in] = HWMON_I_INPUT | HWMON_I_LABEL, 88 [hwmon_curr] = HWMON_C_INPUT | HWMON_C_LABEL, 89 [hwmon_fan] = HWMON_F_INPUT | HWMON_F_LABEL, 90}; 91 92struct ec_sensor_info { 93 char label[SENSOR_LABEL_LEN]; 94 enum hwmon_sensor_types type; 95 sensor_address addr; 96}; 97 98#define EC_SENSOR(sensor_label, sensor_type, size, bank, index) { \ 99 .label = sensor_label, .type = sensor_type, \ 100 .addr = MAKE_SENSOR_ADDRESS(size, bank, index), \ 101 } 102 103enum ec_sensors { 104 /* chipset temperature [℃] */ 105 ec_sensor_temp_chipset, 106 /* CPU temperature [℃] */ 107 ec_sensor_temp_cpu, 108 /* CPU package temperature [℃] */ 109 ec_sensor_temp_cpu_package, 110 /* motherboard temperature [℃] */ 111 ec_sensor_temp_mb, 112 /* "T_Sensor" temperature sensor reading [℃] */ 113 ec_sensor_temp_t_sensor, 114 /* like ec_sensor_temp_t_sensor, but at an alternate address [℃] */ 115 ec_sensor_temp_t_sensor_alt1, 116 /* VRM temperature [℃] */ 117 ec_sensor_temp_vrm, 118 /* VRM east (right) temperature [℃] */ 119 ec_sensor_temp_vrme, 120 /* VRM west (left) temperature [℃] */ 121 ec_sensor_temp_vrmw, 122 /* CPU Core voltage [mV] */ 123 ec_sensor_in_cpu_core, 124 /* CPU_Opt fan [RPM] */ 125 ec_sensor_fan_cpu_opt, 126 /* VRM heat sink fan [RPM] */ 127 ec_sensor_fan_vrm_hs, 128 /* VRM east (right) heat sink fan [RPM] */ 129 ec_sensor_fan_vrme_hs, 130 /* VRM west (left) heat sink fan [RPM] */ 131 ec_sensor_fan_vrmw_hs, 132 /* Chipset fan [RPM] */ 133 ec_sensor_fan_chipset, 134 /* Water flow sensor reading [RPM] */ 135 ec_sensor_fan_water_flow, 136 /* USB4 fan [RPM] */ 137 ec_sensor_fan_usb4, 138 /* M.2 fan [RPM] */ 139 ec_sensor_fan_m2, 140 /* CPU current [A] */ 141 ec_sensor_curr_cpu, 142 /* "Water_In" temperature sensor reading [℃] */ 143 ec_sensor_temp_water_in, 144 /* "Water_Out" temperature sensor reading [℃] */ 145 ec_sensor_temp_water_out, 146 /* "Water_Block_In" temperature sensor reading [℃] */ 147 ec_sensor_temp_water_block_in, 148 /* "Water_Block_Out" temperature sensor reading [℃] */ 149 ec_sensor_temp_water_block_out, 150 /* "T_sensor_2" temperature sensor reading [℃] */ 151 ec_sensor_temp_t_sensor_2, 152 /* "Extra_1" temperature sensor reading [℃] */ 153 ec_sensor_temp_sensor_extra_1, 154 /* "Extra_2" temperature sensor reading [℃] */ 155 ec_sensor_temp_sensor_extra_2, 156 /* "Extra_3" temperature sensor reading [℃] */ 157 ec_sensor_temp_sensor_extra_3, 158}; 159 160#define SENSOR_TEMP_CHIPSET BIT(ec_sensor_temp_chipset) 161#define SENSOR_TEMP_CPU BIT(ec_sensor_temp_cpu) 162#define SENSOR_TEMP_CPU_PACKAGE BIT(ec_sensor_temp_cpu_package) 163#define SENSOR_TEMP_MB BIT(ec_sensor_temp_mb) 164#define SENSOR_TEMP_T_SENSOR BIT(ec_sensor_temp_t_sensor) 165#define SENSOR_TEMP_T_SENSOR_ALT1 BIT(ec_sensor_temp_t_sensor_alt1) 166#define SENSOR_TEMP_VRM BIT(ec_sensor_temp_vrm) 167#define SENSOR_TEMP_VRME BIT(ec_sensor_temp_vrme) 168#define SENSOR_TEMP_VRMW BIT(ec_sensor_temp_vrmw) 169#define SENSOR_IN_CPU_CORE BIT(ec_sensor_in_cpu_core) 170#define SENSOR_FAN_CPU_OPT BIT(ec_sensor_fan_cpu_opt) 171#define SENSOR_FAN_VRM_HS BIT(ec_sensor_fan_vrm_hs) 172#define SENSOR_FAN_VRME_HS BIT(ec_sensor_fan_vrme_hs) 173#define SENSOR_FAN_VRMW_HS BIT(ec_sensor_fan_vrmw_hs) 174#define SENSOR_FAN_CHIPSET BIT(ec_sensor_fan_chipset) 175#define SENSOR_FAN_WATER_FLOW BIT(ec_sensor_fan_water_flow) 176#define SENSOR_FAN_USB4 BIT(ec_sensor_fan_usb4) 177#define SENSOR_FAN_M2 BIT(ec_sensor_fan_m2) 178#define SENSOR_CURR_CPU BIT(ec_sensor_curr_cpu) 179#define SENSOR_TEMP_WATER_IN BIT(ec_sensor_temp_water_in) 180#define SENSOR_TEMP_WATER_OUT BIT(ec_sensor_temp_water_out) 181#define SENSOR_TEMP_WATER_BLOCK_IN BIT(ec_sensor_temp_water_block_in) 182#define SENSOR_TEMP_WATER_BLOCK_OUT BIT(ec_sensor_temp_water_block_out) 183#define SENSOR_TEMP_T_SENSOR_2 BIT(ec_sensor_temp_t_sensor_2) 184#define SENSOR_TEMP_SENSOR_EXTRA_1 BIT(ec_sensor_temp_sensor_extra_1) 185#define SENSOR_TEMP_SENSOR_EXTRA_2 BIT(ec_sensor_temp_sensor_extra_2) 186#define SENSOR_TEMP_SENSOR_EXTRA_3 BIT(ec_sensor_temp_sensor_extra_3) 187 188enum board_family { 189 family_unknown, 190 family_amd_400_series, 191 family_amd_500_series, 192 family_amd_600_series, 193 family_amd_800_series, 194 family_amd_trx_50, 195 family_amd_wrx_90, 196 family_intel_200_series, 197 family_intel_300_series, 198 family_intel_400_series, 199 family_intel_600_series, 200 family_intel_700_series 201}; 202 203/* 204 * All the known sensors for ASUS EC controllers. These arrays have to be sorted 205 * by the full ((bank << 8) + index) register index (see asus_ec_block_read() as 206 * to why). 207 */ 208static const struct ec_sensor_info sensors_family_amd_400[] = { 209 [ec_sensor_temp_chipset] = 210 EC_SENSOR("Chipset", hwmon_temp, 1, 0x00, 0x3a), 211 [ec_sensor_temp_cpu] = 212 EC_SENSOR("CPU", hwmon_temp, 1, 0x00, 0x3b), 213 [ec_sensor_temp_mb] = 214 EC_SENSOR("Motherboard", hwmon_temp, 1, 0x00, 0x3c), 215 [ec_sensor_temp_t_sensor] = 216 EC_SENSOR("T_Sensor", hwmon_temp, 1, 0x00, 0x3d), 217 [ec_sensor_temp_vrm] = 218 EC_SENSOR("VRM", hwmon_temp, 1, 0x00, 0x3e), 219 [ec_sensor_in_cpu_core] = 220 EC_SENSOR("CPU Core", hwmon_in, 2, 0x00, 0xa2), 221 [ec_sensor_fan_vrm_hs] = 222 EC_SENSOR("VRM HS", hwmon_fan, 2, 0x00, 0xb2), 223 [ec_sensor_fan_cpu_opt] = 224 EC_SENSOR("CPU_Opt", hwmon_fan, 2, 0x00, 0xbc), 225 [ec_sensor_fan_chipset] = 226 /* no chipset fans in this generation */ 227 EC_SENSOR("Chipset", hwmon_fan, 0, 0x00, 0x00), 228 [ec_sensor_fan_water_flow] = 229 EC_SENSOR("Water_Flow", hwmon_fan, 2, 0x00, 0xb4), 230 [ec_sensor_curr_cpu] = 231 EC_SENSOR("CPU", hwmon_curr, 1, 0x00, 0xf4), 232 [ec_sensor_temp_water_out] = 233 EC_SENSOR("Water_Out", hwmon_temp, 1, 0x01, 0x0b), 234 [ec_sensor_temp_water_in] = 235 EC_SENSOR("Water_In", hwmon_temp, 1, 0x01, 0x0d), 236}; 237 238static const struct ec_sensor_info sensors_family_amd_500[] = { 239 [ec_sensor_temp_chipset] = 240 EC_SENSOR("Chipset", hwmon_temp, 1, 0x00, 0x3a), 241 [ec_sensor_temp_cpu] = EC_SENSOR("CPU", hwmon_temp, 1, 0x00, 0x3b), 242 [ec_sensor_temp_mb] = 243 EC_SENSOR("Motherboard", hwmon_temp, 1, 0x00, 0x3c), 244 [ec_sensor_temp_t_sensor] = 245 EC_SENSOR("T_Sensor", hwmon_temp, 1, 0x00, 0x3d), 246 [ec_sensor_temp_vrm] = EC_SENSOR("VRM", hwmon_temp, 1, 0x00, 0x3e), 247 [ec_sensor_in_cpu_core] = 248 EC_SENSOR("CPU Core", hwmon_in, 2, 0x00, 0xa2), 249 [ec_sensor_fan_cpu_opt] = 250 EC_SENSOR("CPU_Opt", hwmon_fan, 2, 0x00, 0xb0), 251 [ec_sensor_fan_vrm_hs] = EC_SENSOR("VRM HS", hwmon_fan, 2, 0x00, 0xb2), 252 [ec_sensor_fan_chipset] = 253 EC_SENSOR("Chipset", hwmon_fan, 2, 0x00, 0xb4), 254 [ec_sensor_fan_water_flow] = 255 EC_SENSOR("Water_Flow", hwmon_fan, 2, 0x00, 0xbc), 256 [ec_sensor_curr_cpu] = EC_SENSOR("CPU", hwmon_curr, 1, 0x00, 0xf4), 257 [ec_sensor_temp_water_in] = 258 EC_SENSOR("Water_In", hwmon_temp, 1, 0x01, 0x00), 259 [ec_sensor_temp_water_out] = 260 EC_SENSOR("Water_Out", hwmon_temp, 1, 0x01, 0x01), 261 [ec_sensor_temp_water_block_in] = 262 EC_SENSOR("Water_Block_In", hwmon_temp, 1, 0x01, 0x02), 263 [ec_sensor_temp_water_block_out] = 264 EC_SENSOR("Water_Block_Out", hwmon_temp, 1, 0x01, 0x03), 265 [ec_sensor_temp_sensor_extra_1] = 266 EC_SENSOR("Extra_1", hwmon_temp, 1, 0x01, 0x09), 267 [ec_sensor_temp_t_sensor_2] = 268 EC_SENSOR("T_sensor_2", hwmon_temp, 1, 0x01, 0x0a), 269 [ec_sensor_temp_sensor_extra_2] = 270 EC_SENSOR("Extra_2", hwmon_temp, 1, 0x01, 0x0b), 271 [ec_sensor_temp_sensor_extra_3] = 272 EC_SENSOR("Extra_3", hwmon_temp, 1, 0x01, 0x0c), 273}; 274 275static const struct ec_sensor_info sensors_family_amd_600[] = { 276 [ec_sensor_temp_cpu] = EC_SENSOR("CPU", hwmon_temp, 1, 0x00, 0x30), 277 [ec_sensor_temp_cpu_package] = 278 EC_SENSOR("CPU Package", hwmon_temp, 1, 0x00, 0x31), 279 [ec_sensor_temp_mb] = 280 EC_SENSOR("Motherboard", hwmon_temp, 1, 0x00, 0x32), 281 [ec_sensor_temp_vrm] = 282 EC_SENSOR("VRM", hwmon_temp, 1, 0x00, 0x33), 283 [ec_sensor_temp_t_sensor] = 284 EC_SENSOR("T_Sensor", hwmon_temp, 1, 0x00, 0x36), 285 [ec_sensor_temp_t_sensor_alt1] = 286 EC_SENSOR("T_Sensor", hwmon_temp, 1, 0x00, 0x37), 287 [ec_sensor_fan_cpu_opt] = 288 EC_SENSOR("CPU_Opt", hwmon_fan, 2, 0x00, 0xb0), 289 [ec_sensor_temp_water_in] = 290 EC_SENSOR("Water_In", hwmon_temp, 1, 0x01, 0x00), 291 [ec_sensor_temp_water_out] = 292 EC_SENSOR("Water_Out", hwmon_temp, 1, 0x01, 0x01), 293}; 294 295static const struct ec_sensor_info sensors_family_amd_800[] = { 296 [ec_sensor_temp_cpu] = EC_SENSOR("CPU", hwmon_temp, 1, 0x00, 0x30), 297 [ec_sensor_temp_cpu_package] = 298 EC_SENSOR("CPU Package", hwmon_temp, 1, 0x00, 0x31), 299 [ec_sensor_temp_mb] = 300 EC_SENSOR("Motherboard", hwmon_temp, 1, 0x00, 0x32), 301 [ec_sensor_temp_vrm] = 302 EC_SENSOR("VRM", hwmon_temp, 1, 0x00, 0x33), 303 [ec_sensor_temp_t_sensor] = 304 EC_SENSOR("T_Sensor", hwmon_temp, 1, 0x00, 0x36), 305 [ec_sensor_fan_cpu_opt] = 306 EC_SENSOR("CPU_Opt", hwmon_fan, 2, 0x00, 0xb0), 307}; 308 309static const struct ec_sensor_info sensors_family_amd_trx_50[] = { 310 [ec_sensor_temp_cpu] = EC_SENSOR("CPU", hwmon_temp, 1, 0x00, 0x30), 311 [ec_sensor_temp_cpu_package] = 312 EC_SENSOR("CPU Package", hwmon_temp, 1, 0x00, 0x31), 313 [ec_sensor_temp_vrme] = EC_SENSOR("VRM_E", hwmon_temp, 1, 0x00, 0x33), 314 [ec_sensor_temp_vrmw] = EC_SENSOR("VRM_W", hwmon_temp, 1, 0x00, 0x34), 315 [ec_sensor_fan_cpu_opt] = EC_SENSOR("CPU_Opt", hwmon_fan, 2, 0x00, 0xb0), 316 [ec_sensor_fan_vrmw_hs] = EC_SENSOR("VRM_E HS", hwmon_fan, 2, 0x00, 0xb4), 317 [ec_sensor_fan_vrme_hs] = EC_SENSOR("VRM_W HS", hwmon_fan, 2, 0x00, 0xbc), 318 [ec_sensor_temp_t_sensor] = 319 EC_SENSOR("T_Sensor", hwmon_temp, 1, 0x01, 0x04), 320}; 321 322static const struct ec_sensor_info sensors_family_amd_wrx_90[] = { 323 [ec_sensor_temp_cpu_package] = 324 EC_SENSOR("CPU Package", hwmon_temp, 1, 0x00, 0x31), 325 [ec_sensor_fan_cpu_opt] = 326 EC_SENSOR("CPU_Opt", hwmon_fan, 2, 0x00, 0xb0), 327 [ec_sensor_fan_vrmw_hs] = 328 EC_SENSOR("VRMW HS", hwmon_fan, 2, 0x00, 0xb4), 329 [ec_sensor_fan_usb4] = EC_SENSOR("USB4", hwmon_fan, 2, 0x00, 0xb6), 330 [ec_sensor_fan_vrme_hs] = 331 EC_SENSOR("VRME HS", hwmon_fan, 2, 0x00, 0xbc), 332 [ec_sensor_fan_m2] = EC_SENSOR("M.2", hwmon_fan, 2, 0x00, 0xbe), 333 [ec_sensor_temp_t_sensor] = 334 EC_SENSOR("T_Sensor", hwmon_temp, 1, 0x01, 0x04), 335}; 336 337static const struct ec_sensor_info sensors_family_intel_200[] = { 338 [ec_sensor_temp_chipset] = 339 EC_SENSOR("Chipset", hwmon_temp, 1, 0x00, 0x3a), 340 [ec_sensor_temp_cpu] = EC_SENSOR("CPU", hwmon_temp, 1, 0x00, 0x3b), 341 [ec_sensor_temp_mb] = 342 EC_SENSOR("Motherboard", hwmon_temp, 1, 0x00, 0x3c), 343 [ec_sensor_temp_t_sensor] = 344 EC_SENSOR("T_Sensor", hwmon_temp, 1, 0x00, 0x3d), 345 [ec_sensor_fan_cpu_opt] = 346 EC_SENSOR("CPU_Opt", hwmon_fan, 2, 0x00, 0xbc), 347}; 348 349static const struct ec_sensor_info sensors_family_intel_300[] = { 350 [ec_sensor_temp_chipset] = 351 EC_SENSOR("Chipset", hwmon_temp, 1, 0x00, 0x3a), 352 [ec_sensor_temp_cpu] = EC_SENSOR("CPU", hwmon_temp, 1, 0x00, 0x3b), 353 [ec_sensor_temp_mb] = 354 EC_SENSOR("Motherboard", hwmon_temp, 1, 0x00, 0x3c), 355 [ec_sensor_temp_t_sensor] = 356 EC_SENSOR("T_Sensor", hwmon_temp, 1, 0x00, 0x3d), 357 [ec_sensor_temp_vrm] = EC_SENSOR("VRM", hwmon_temp, 1, 0x00, 0x3e), 358 [ec_sensor_fan_cpu_opt] = 359 EC_SENSOR("CPU_Opt", hwmon_fan, 2, 0x00, 0xb0), 360 [ec_sensor_fan_vrm_hs] = EC_SENSOR("VRM HS", hwmon_fan, 2, 0x00, 0xb2), 361 [ec_sensor_fan_water_flow] = 362 EC_SENSOR("Water_Flow", hwmon_fan, 2, 0x00, 0xbc), 363 [ec_sensor_temp_water_in] = 364 EC_SENSOR("Water_In", hwmon_temp, 1, 0x01, 0x00), 365 [ec_sensor_temp_water_out] = 366 EC_SENSOR("Water_Out", hwmon_temp, 1, 0x01, 0x01), 367}; 368 369static const struct ec_sensor_info sensors_family_intel_400[] = { 370 [ec_sensor_temp_chipset] = 371 EC_SENSOR("Chipset", hwmon_temp, 1, 0x00, 0x3a), 372 [ec_sensor_temp_cpu] = EC_SENSOR("CPU", hwmon_temp, 1, 0x00, 0x3b), 373 [ec_sensor_temp_mb] = 374 EC_SENSOR("Motherboard", hwmon_temp, 1, 0x00, 0x3c), 375 [ec_sensor_temp_t_sensor] = 376 EC_SENSOR("T_Sensor", hwmon_temp, 1, 0x00, 0x3d), 377 [ec_sensor_temp_vrm] = EC_SENSOR("VRM", hwmon_temp, 1, 0x00, 0x3e), 378 [ec_sensor_fan_cpu_opt] = 379 EC_SENSOR("CPU_Opt", hwmon_fan, 2, 0x00, 0xb0), 380 [ec_sensor_fan_vrm_hs] = EC_SENSOR("VRM HS", hwmon_fan, 2, 0x00, 0xb2), 381}; 382 383static const struct ec_sensor_info sensors_family_intel_600[] = { 384 [ec_sensor_temp_t_sensor] = 385 EC_SENSOR("T_Sensor", hwmon_temp, 1, 0x00, 0x3d), 386 [ec_sensor_temp_vrm] = EC_SENSOR("VRM", hwmon_temp, 1, 0x00, 0x3e), 387 [ec_sensor_fan_water_flow] = 388 EC_SENSOR("Water_Flow", hwmon_fan, 2, 0x00, 0xbe), 389 [ec_sensor_temp_water_in] = 390 EC_SENSOR("Water_In", hwmon_temp, 1, 0x01, 0x00), 391 [ec_sensor_temp_water_out] = 392 EC_SENSOR("Water_Out", hwmon_temp, 1, 0x01, 0x01), 393 [ec_sensor_temp_water_block_in] = 394 EC_SENSOR("Water_Block_In", hwmon_temp, 1, 0x01, 0x02), 395}; 396 397static const struct ec_sensor_info sensors_family_intel_700[] = { 398 [ec_sensor_temp_t_sensor] = 399 EC_SENSOR("T_Sensor", hwmon_temp, 1, 0x01, 0x09), 400 [ec_sensor_temp_t_sensor_2] = 401 EC_SENSOR("T_Sensor 2", hwmon_temp, 1, 0x01, 0x05), 402 [ec_sensor_temp_vrm] = EC_SENSOR("VRM", hwmon_temp, 1, 0x00, 0x33), 403 [ec_sensor_fan_cpu_opt] = 404 EC_SENSOR("CPU_Opt", hwmon_fan, 2, 0x00, 0xb0), 405}; 406 407/* Shortcuts for common combinations */ 408#define SENSOR_SET_TEMP_CHIPSET_CPU_MB \ 409 (SENSOR_TEMP_CHIPSET | SENSOR_TEMP_CPU | SENSOR_TEMP_MB) 410#define SENSOR_SET_TEMP_WATER (SENSOR_TEMP_WATER_IN | SENSOR_TEMP_WATER_OUT) 411#define SENSOR_SET_WATER_BLOCK \ 412 (SENSOR_TEMP_WATER_BLOCK_IN | SENSOR_TEMP_WATER_BLOCK_OUT) 413 414struct ec_board_info { 415 unsigned long sensors; 416 /* 417 * Defines which mutex to use for guarding access to the state and the 418 * hardware. Can be either a full path to an AML mutex or the 419 * pseudo-path ACPI_GLOBAL_LOCK_PSEUDO_PATH to use the global ACPI lock, 420 * or left empty to use a regular mutex object, in which case access to 421 * the hardware is not guarded. 422 */ 423 const char *mutex_path; 424 enum board_family family; 425}; 426 427static const struct ec_board_info board_info_crosshair_viii_dark_hero = { 428 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | 429 SENSOR_TEMP_T_SENSOR | 430 SENSOR_TEMP_VRM | SENSOR_SET_TEMP_WATER | 431 SENSOR_FAN_CPU_OPT | SENSOR_FAN_WATER_FLOW | 432 SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE, 433 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX, 434 .family = family_amd_500_series, 435}; 436 437static const struct ec_board_info board_info_crosshair_viii_hero = { 438 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | 439 SENSOR_TEMP_T_SENSOR | 440 SENSOR_TEMP_VRM | SENSOR_SET_TEMP_WATER | 441 SENSOR_FAN_CPU_OPT | SENSOR_FAN_CHIPSET | 442 SENSOR_FAN_WATER_FLOW | SENSOR_CURR_CPU | 443 SENSOR_IN_CPU_CORE, 444 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX, 445 .family = family_amd_500_series, 446}; 447 448static const struct ec_board_info board_info_crosshair_viii_impact = { 449 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | 450 SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM | 451 SENSOR_FAN_CHIPSET | SENSOR_CURR_CPU | 452 SENSOR_IN_CPU_CORE, 453 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX, 454 .family = family_amd_500_series, 455}; 456 457static const struct ec_board_info board_info_crosshair_x670e_gene = { 458 .sensors = SENSOR_TEMP_CPU | SENSOR_TEMP_CPU_PACKAGE | 459 SENSOR_TEMP_T_SENSOR | 460 SENSOR_TEMP_MB | SENSOR_TEMP_VRM, 461 .mutex_path = ACPI_GLOBAL_LOCK_PSEUDO_PATH, 462 .family = family_amd_600_series, 463}; 464 465static const struct ec_board_info board_info_crosshair_x670e_hero = { 466 .sensors = SENSOR_TEMP_CPU | SENSOR_TEMP_CPU_PACKAGE | 467 SENSOR_TEMP_MB | SENSOR_TEMP_VRM | 468 SENSOR_SET_TEMP_WATER, 469 .mutex_path = ACPI_GLOBAL_LOCK_PSEUDO_PATH, 470 .family = family_amd_600_series, 471}; 472 473static const struct ec_board_info board_info_maximus_vi_hero = { 474 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | 475 SENSOR_TEMP_T_SENSOR | 476 SENSOR_TEMP_VRM | SENSOR_SET_TEMP_WATER | 477 SENSOR_FAN_CPU_OPT | SENSOR_FAN_WATER_FLOW, 478 .mutex_path = ACPI_GLOBAL_LOCK_PSEUDO_PATH, 479 .family = family_intel_300_series, 480}; 481 482static const struct ec_board_info board_info_maximus_xi_hero = { 483 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | 484 SENSOR_TEMP_T_SENSOR | 485 SENSOR_TEMP_VRM | SENSOR_SET_TEMP_WATER | 486 SENSOR_FAN_CPU_OPT | SENSOR_FAN_WATER_FLOW, 487 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX, 488 .family = family_intel_300_series, 489}; 490 491static const struct ec_board_info board_info_maximus_z690_formula = { 492 .sensors = SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM | 493 SENSOR_SET_TEMP_WATER | SENSOR_FAN_WATER_FLOW, 494 .mutex_path = ASUS_HW_ACCESS_MUTEX_RMTW_ASMX, 495 .family = family_intel_600_series, 496}; 497 498static const struct ec_board_info board_info_prime_x470_pro = { 499 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | 500 SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM | 501 SENSOR_FAN_CPU_OPT | 502 SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE, 503 .mutex_path = ACPI_GLOBAL_LOCK_PSEUDO_PATH, 504 .family = family_amd_400_series, 505}; 506 507static const struct ec_board_info board_info_prime_x570_pro = { 508 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | SENSOR_TEMP_VRM | 509 SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CHIPSET, 510 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX, 511 .family = family_amd_500_series, 512}; 513 514static const struct ec_board_info board_info_prime_x670e_pro_wifi = { 515 .sensors = SENSOR_TEMP_CPU | SENSOR_TEMP_CPU_PACKAGE | 516 SENSOR_TEMP_MB | SENSOR_TEMP_VRM | 517 SENSOR_TEMP_T_SENSOR_ALT1 | SENSOR_FAN_CPU_OPT, 518 .mutex_path = ACPI_GLOBAL_LOCK_PSEUDO_PATH, 519 .family = family_amd_600_series, 520}; 521 522static const struct ec_board_info board_info_prime_z270_a = { 523 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | 524 SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CPU_OPT, 525 .mutex_path = ASUS_HW_ACCESS_MUTEX_SB_PCI0_LPCB_SIO1_MUT0, 526 .family = family_intel_200_series, 527}; 528 529static const struct ec_board_info board_info_pro_art_b550_creator = { 530 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | 531 SENSOR_TEMP_T_SENSOR | 532 SENSOR_FAN_CPU_OPT, 533 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX, 534 .family = family_amd_500_series, 535}; 536 537static const struct ec_board_info board_info_pro_art_x570_creator_wifi = { 538 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | SENSOR_TEMP_VRM | 539 SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CPU_OPT | 540 SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE, 541 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX, 542 .family = family_amd_500_series, 543}; 544 545static const struct ec_board_info board_info_pro_art_x670E_creator_wifi = { 546 .sensors = SENSOR_TEMP_CPU | SENSOR_TEMP_CPU_PACKAGE | 547 SENSOR_TEMP_MB | SENSOR_TEMP_VRM | 548 SENSOR_TEMP_T_SENSOR, 549 .mutex_path = ACPI_GLOBAL_LOCK_PSEUDO_PATH, 550 .family = family_amd_600_series, 551}; 552 553static const struct ec_board_info board_info_pro_art_x870E_creator_wifi = { 554 .sensors = SENSOR_TEMP_CPU | SENSOR_TEMP_CPU_PACKAGE | 555 SENSOR_TEMP_MB | SENSOR_TEMP_VRM | 556 SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CPU_OPT, 557 .mutex_path = ASUS_HW_ACCESS_MUTEX_SB_PCI0_SBRG_SIO1_MUT0, 558 .family = family_amd_800_series, 559}; 560 561static const struct ec_board_info board_info_pro_ws_trx50_sage_wifi = { 562 /* Board also has a nct6798 */ 563 .sensors = SENSOR_TEMP_CPU | SENSOR_TEMP_CPU_PACKAGE | SENSOR_TEMP_VRME | 564 SENSOR_TEMP_VRMW | SENSOR_FAN_CPU_OPT | SENSOR_FAN_VRME_HS | 565 SENSOR_FAN_VRMW_HS | SENSOR_TEMP_T_SENSOR, 566 .mutex_path = ASUS_HW_ACCESS_MUTEX_RMTW_ASMX, 567 .family = family_amd_trx_50, 568}; 569 570static const struct ec_board_info board_info_pro_ws_wrx90e_sage_se = { 571 /* Board also has a nct6798 with 7 more fans and temperatures */ 572 .sensors = SENSOR_TEMP_CPU_PACKAGE | SENSOR_TEMP_T_SENSOR | 573 SENSOR_FAN_CPU_OPT | SENSOR_FAN_USB4 | SENSOR_FAN_M2 | 574 SENSOR_FAN_VRME_HS | SENSOR_FAN_VRMW_HS, 575 .mutex_path = ASUS_HW_ACCESS_MUTEX_RMTW_ASMX, 576 .family = family_amd_wrx_90, 577}; 578 579static const struct ec_board_info board_info_pro_ws_x570_ace = { 580 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | SENSOR_TEMP_VRM | 581 SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CHIPSET | 582 SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE, 583 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX, 584 .family = family_amd_500_series, 585}; 586 587static const struct ec_board_info board_info_strix_b550_e_gaming = { 588 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | 589 SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM | 590 SENSOR_FAN_CPU_OPT, 591 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX, 592 .family = family_amd_500_series, 593}; 594 595static const struct ec_board_info board_info_strix_b550_i_gaming = { 596 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | 597 SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM | 598 SENSOR_FAN_VRM_HS | SENSOR_CURR_CPU | 599 SENSOR_IN_CPU_CORE, 600 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX, 601 .family = family_amd_500_series, 602}; 603 604static const struct ec_board_info board_info_strix_b650e_i_gaming = { 605 .sensors = SENSOR_TEMP_VRM | SENSOR_TEMP_T_SENSOR | 606 SENSOR_SET_TEMP_CHIPSET_CPU_MB | SENSOR_IN_CPU_CORE, 607 .mutex_path = ACPI_GLOBAL_LOCK_PSEUDO_PATH, 608 .family = family_amd_600_series, 609}; 610 611static const struct ec_board_info board_info_strix_b850_i_gaming_wifi = { 612 .sensors = SENSOR_TEMP_CPU | SENSOR_TEMP_CPU_PACKAGE | 613 SENSOR_TEMP_MB | SENSOR_TEMP_VRM, 614 .mutex_path = ACPI_GLOBAL_LOCK_PSEUDO_PATH, 615 .family = family_amd_800_series, 616}; 617 618static const struct ec_board_info board_info_strix_x470_i_gaming = { 619 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | 620 SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM | 621 SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE, 622 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX, 623 .family = family_amd_400_series, 624}; 625 626static const struct ec_board_info board_info_strix_x570_e_gaming = { 627 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | 628 SENSOR_TEMP_T_SENSOR | 629 SENSOR_FAN_CHIPSET | SENSOR_CURR_CPU | 630 SENSOR_IN_CPU_CORE, 631 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX, 632 .family = family_amd_500_series, 633}; 634 635static const struct ec_board_info board_info_strix_x570_e_gaming_wifi_ii = { 636 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | 637 SENSOR_TEMP_T_SENSOR | SENSOR_CURR_CPU | 638 SENSOR_IN_CPU_CORE, 639 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX, 640 .family = family_amd_500_series, 641}; 642 643static const struct ec_board_info board_info_strix_x570_f_gaming = { 644 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | 645 SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CHIPSET, 646 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX, 647 .family = family_amd_500_series, 648}; 649 650static const struct ec_board_info board_info_strix_x570_i_gaming = { 651 .sensors = SENSOR_TEMP_CHIPSET | SENSOR_TEMP_VRM | 652 SENSOR_TEMP_T_SENSOR | 653 SENSOR_FAN_VRM_HS | SENSOR_FAN_CHIPSET | 654 SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE, 655 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX, 656 .family = family_amd_500_series, 657}; 658 659static const struct ec_board_info board_info_strix_x670e_e_gaming_wifi = { 660 .sensors = SENSOR_TEMP_CPU | SENSOR_TEMP_CPU_PACKAGE | 661 SENSOR_TEMP_MB | SENSOR_TEMP_VRM, 662 .mutex_path = ASUS_HW_ACCESS_MUTEX_SB_PCI0_SBRG_SIO1_MUT0, 663 .family = family_amd_600_series, 664}; 665 666static const struct ec_board_info board_info_strix_x670e_i_gaming_wifi = { 667 .sensors = SENSOR_TEMP_CPU | SENSOR_TEMP_CPU_PACKAGE | 668 SENSOR_TEMP_MB | SENSOR_TEMP_VRM, 669 .mutex_path = ACPI_GLOBAL_LOCK_PSEUDO_PATH, 670 .family = family_amd_600_series, 671}; 672 673static const struct ec_board_info board_info_strix_x870_f_gaming_wifi = { 674 .sensors = SENSOR_TEMP_CPU | SENSOR_TEMP_CPU_PACKAGE | 675 SENSOR_TEMP_MB | SENSOR_TEMP_VRM | SENSOR_TEMP_T_SENSOR, 676 .mutex_path = ASUS_HW_ACCESS_MUTEX_SB_PCI0_SBRG_SIO1_MUT0, 677 .family = family_amd_800_series, 678}; 679 680static const struct ec_board_info board_info_strix_x870_i_gaming_wifi = { 681 .sensors = SENSOR_TEMP_CPU | SENSOR_TEMP_CPU_PACKAGE | 682 SENSOR_TEMP_MB | SENSOR_TEMP_VRM, 683 .mutex_path = ASUS_HW_ACCESS_MUTEX_SB_PCI0_SBRG_SIO1_MUT0, 684 .family = family_amd_800_series, 685}; 686 687static const struct ec_board_info board_info_strix_x870e_e_gaming_wifi = { 688 .sensors = SENSOR_TEMP_CPU | SENSOR_TEMP_CPU_PACKAGE | 689 SENSOR_TEMP_MB | SENSOR_TEMP_VRM | 690 SENSOR_FAN_CPU_OPT, 691 .mutex_path = ASUS_HW_ACCESS_MUTEX_SB_PCI0_SBRG_SIO1_MUT0, 692 .family = family_amd_800_series, 693}; 694 695static const struct ec_board_info board_info_strix_x870e_h_gaming_wifi7 = { 696 .sensors = SENSOR_TEMP_CPU | SENSOR_TEMP_CPU_PACKAGE | 697 SENSOR_TEMP_MB | SENSOR_TEMP_VRM | SENSOR_TEMP_T_SENSOR | 698 SENSOR_FAN_CPU_OPT, 699 .mutex_path = ASUS_HW_ACCESS_MUTEX_SB_PCI0_SBRG_SIO1_MUT0, 700 .family = family_amd_800_series, 701}; 702 703static const struct ec_board_info board_info_strix_z390_f_gaming = { 704 .sensors = SENSOR_TEMP_CHIPSET | SENSOR_TEMP_VRM | 705 SENSOR_TEMP_T_SENSOR | 706 SENSOR_FAN_CPU_OPT, 707 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX, 708 .family = family_intel_300_series, 709}; 710 711static const struct ec_board_info board_info_strix_z490_f_gaming = { 712 .sensors = SENSOR_TEMP_CHIPSET | 713 SENSOR_TEMP_CPU | 714 SENSOR_TEMP_MB | 715 SENSOR_TEMP_T_SENSOR | 716 SENSOR_TEMP_VRM | 717 SENSOR_FAN_CPU_OPT | 718 SENSOR_FAN_VRM_HS, 719 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX, 720 .family = family_intel_400_series, 721}; 722 723static const struct ec_board_info board_info_strix_z690_a_gaming_wifi_d4 = { 724 .sensors = SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM, 725 .mutex_path = ASUS_HW_ACCESS_MUTEX_RMTW_ASMX, 726 .family = family_intel_600_series, 727}; 728 729static const struct ec_board_info board_info_strix_z690_e_gaming_wifi = { 730 .sensors = SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM, 731 .mutex_path = ASUS_HW_ACCESS_MUTEX_RMTW_ASMX, 732 .family = family_intel_600_series, 733}; 734 735static const struct ec_board_info board_info_strix_z790_e_gaming_wifi_ii = { 736 .sensors = SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM | 737 SENSOR_FAN_CPU_OPT, 738 .mutex_path = ASUS_HW_ACCESS_MUTEX_SB_PC00_LPCB_SIO1_MUT0, 739 .family = family_intel_700_series, 740}; 741 742static const struct ec_board_info board_info_strix_z790_i_gaming_wifi = { 743 .sensors = SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_T_SENSOR_2 | 744 SENSOR_TEMP_VRM, 745 .mutex_path = ASUS_HW_ACCESS_MUTEX_SB_PC00_LPCB_SIO1_MUT0, 746 .family = family_intel_700_series, 747}; 748 749static const struct ec_board_info board_info_tuf_gaming_x670e_plus = { 750 .sensors = SENSOR_TEMP_CPU | SENSOR_TEMP_CPU_PACKAGE | 751 SENSOR_TEMP_MB | SENSOR_TEMP_VRM | 752 SENSOR_TEMP_WATER_IN | SENSOR_TEMP_WATER_OUT | 753 SENSOR_FAN_CPU_OPT, 754 .mutex_path = ACPI_GLOBAL_LOCK_PSEUDO_PATH, 755 .family = family_amd_600_series, 756}; 757 758static const struct ec_board_info board_info_zenith_ii_extreme = { 759 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | SENSOR_TEMP_T_SENSOR | 760 SENSOR_TEMP_VRM | SENSOR_SET_TEMP_WATER | 761 SENSOR_FAN_CPU_OPT | SENSOR_FAN_CHIPSET | SENSOR_FAN_VRM_HS | 762 SENSOR_FAN_WATER_FLOW | SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE | 763 SENSOR_SET_WATER_BLOCK | 764 SENSOR_TEMP_T_SENSOR_2 | SENSOR_TEMP_SENSOR_EXTRA_1 | 765 SENSOR_TEMP_SENSOR_EXTRA_2 | SENSOR_TEMP_SENSOR_EXTRA_3, 766 .mutex_path = ASUS_HW_ACCESS_MUTEX_SB_PCI0_SBRG_SIO1_MUT0, 767 .family = family_amd_500_series, 768}; 769 770#define DMI_EXACT_MATCH_ASUS_BOARD_NAME(name, board_info) \ 771 { \ 772 .matches = { \ 773 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, \ 774 "ASUSTeK COMPUTER INC."), \ 775 DMI_EXACT_MATCH(DMI_BOARD_NAME, name), \ 776 }, \ 777 .driver_data = (void *)board_info, \ 778 } 779 780static const struct dmi_system_id dmi_table[] = { 781 DMI_EXACT_MATCH_ASUS_BOARD_NAME("MAXIMUS VI HERO", 782 &board_info_maximus_vi_hero), 783 DMI_EXACT_MATCH_ASUS_BOARD_NAME("PRIME X470-PRO", 784 &board_info_prime_x470_pro), 785 DMI_EXACT_MATCH_ASUS_BOARD_NAME("PRIME X570-PRO", 786 &board_info_prime_x570_pro), 787 DMI_EXACT_MATCH_ASUS_BOARD_NAME("PRIME X670E-PRO WIFI", 788 &board_info_prime_x670e_pro_wifi), 789 DMI_EXACT_MATCH_ASUS_BOARD_NAME("PRIME Z270-A", 790 &board_info_prime_z270_a), 791 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ProArt B550-CREATOR", 792 &board_info_pro_art_b550_creator), 793 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ProArt X570-CREATOR WIFI", 794 &board_info_pro_art_x570_creator_wifi), 795 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ProArt X670E-CREATOR WIFI", 796 &board_info_pro_art_x670E_creator_wifi), 797 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ProArt X870E-CREATOR WIFI", 798 &board_info_pro_art_x870E_creator_wifi), 799 DMI_EXACT_MATCH_ASUS_BOARD_NAME("Pro WS TRX50-SAGE WIFI", 800 &board_info_pro_ws_trx50_sage_wifi), 801 DMI_EXACT_MATCH_ASUS_BOARD_NAME("Pro WS TRX50-SAGE WIFI A", 802 &board_info_pro_ws_trx50_sage_wifi), 803 DMI_EXACT_MATCH_ASUS_BOARD_NAME("Pro WS WRX90E-SAGE SE", 804 &board_info_pro_ws_wrx90e_sage_se), 805 DMI_EXACT_MATCH_ASUS_BOARD_NAME("Pro WS X570-ACE", 806 &board_info_pro_ws_x570_ace), 807 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VIII DARK HERO", 808 &board_info_crosshair_viii_dark_hero), 809 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VIII FORMULA", 810 &board_info_crosshair_viii_hero), 811 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VIII HERO", 812 &board_info_crosshair_viii_hero), 813 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VIII HERO (WI-FI)", 814 &board_info_crosshair_viii_hero), 815 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VIII IMPACT", 816 &board_info_crosshair_viii_impact), 817 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR X670E GENE", 818 &board_info_crosshair_x670e_gene), 819 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR X670E HERO", 820 &board_info_crosshair_x670e_hero), 821 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG MAXIMUS XI HERO", 822 &board_info_maximus_xi_hero), 823 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG MAXIMUS XI HERO (WI-FI)", 824 &board_info_maximus_xi_hero), 825 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG MAXIMUS Z690 FORMULA", 826 &board_info_maximus_z690_formula), 827 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX B550-E GAMING", 828 &board_info_strix_b550_e_gaming), 829 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX B550-I GAMING", 830 &board_info_strix_b550_i_gaming), 831 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX B650E-I GAMING WIFI", 832 &board_info_strix_b650e_i_gaming), 833 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX B850-I GAMING WIFI", 834 &board_info_strix_b850_i_gaming_wifi), 835 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX X470-I GAMING", 836 &board_info_strix_x470_i_gaming), 837 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX X570-E GAMING", 838 &board_info_strix_x570_e_gaming), 839 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX X570-E GAMING WIFI II", 840 &board_info_strix_x570_e_gaming_wifi_ii), 841 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX X570-F GAMING", 842 &board_info_strix_x570_f_gaming), 843 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX X570-I GAMING", 844 &board_info_strix_x570_i_gaming), 845 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX X670E-E GAMING WIFI", 846 &board_info_strix_x670e_e_gaming_wifi), 847 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX X670E-I GAMING WIFI", 848 &board_info_strix_x670e_i_gaming_wifi), 849 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX X870-F GAMING WIFI", 850 &board_info_strix_x870_f_gaming_wifi), 851 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX X870-I GAMING WIFI", 852 &board_info_strix_x870_i_gaming_wifi), 853 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX X870E-E GAMING WIFI", 854 &board_info_strix_x870e_e_gaming_wifi), 855 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX X870E-H GAMING WIFI7", 856 &board_info_strix_x870e_h_gaming_wifi7), 857 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX Z390-F GAMING", 858 &board_info_strix_z390_f_gaming), 859 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX Z490-F GAMING", 860 &board_info_strix_z490_f_gaming), 861 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX Z690-A GAMING WIFI D4", 862 &board_info_strix_z690_a_gaming_wifi_d4), 863 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX Z690-E GAMING WIFI", 864 &board_info_strix_z690_e_gaming_wifi), 865 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX Z790-E GAMING WIFI II", 866 &board_info_strix_z790_e_gaming_wifi_ii), 867 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX Z790-I GAMING WIFI", 868 &board_info_strix_z790_i_gaming_wifi), 869 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG ZENITH II EXTREME", 870 &board_info_zenith_ii_extreme), 871 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG ZENITH II EXTREME ALPHA", 872 &board_info_zenith_ii_extreme), 873 DMI_EXACT_MATCH_ASUS_BOARD_NAME("TUF GAMING X670E-PLUS", 874 &board_info_tuf_gaming_x670e_plus), 875 DMI_EXACT_MATCH_ASUS_BOARD_NAME("TUF GAMING X670E-PLUS WIFI", 876 &board_info_tuf_gaming_x670e_plus), 877 {}, 878}; 879 880struct ec_sensor { 881 unsigned int info_index; 882 s32 cached_value; 883}; 884 885struct lock_data { 886 union { 887 acpi_handle aml; 888 /* global lock handle */ 889 u32 glk; 890 } mutex; 891 bool (*lock)(struct lock_data *data); 892 bool (*unlock)(struct lock_data *data); 893}; 894 895/* 896 * The next function pairs implement options for locking access to the 897 * state and the EC 898 */ 899static bool lock_via_acpi_mutex(struct lock_data *data) 900{ 901 /* 902 * ASUS DSDT does not specify that access to the EC has to be guarded, 903 * but firmware does access it via ACPI 904 */ 905 return ACPI_SUCCESS(acpi_acquire_mutex(data->mutex.aml, 906 NULL, ACPI_LOCK_DELAY_MS)); 907} 908 909static bool unlock_acpi_mutex(struct lock_data *data) 910{ 911 return ACPI_SUCCESS(acpi_release_mutex(data->mutex.aml, NULL)); 912} 913 914static bool lock_via_global_acpi_lock(struct lock_data *data) 915{ 916 return ACPI_SUCCESS(acpi_acquire_global_lock(ACPI_LOCK_DELAY_MS, 917 &data->mutex.glk)); 918} 919 920static bool unlock_global_acpi_lock(struct lock_data *data) 921{ 922 return ACPI_SUCCESS(acpi_release_global_lock(data->mutex.glk)); 923} 924 925struct ec_sensors_data { 926 const struct ec_board_info *board_info; 927 const struct ec_sensor_info *sensors_info; 928 struct ec_sensor *sensors; 929 /* EC registers to read from */ 930 u16 *registers; 931 u8 *read_buffer; 932 /* sorted list of unique register banks */ 933 u8 banks[ASUS_EC_MAX_BANK + 1]; 934 /* in jiffies */ 935 unsigned long last_updated; 936 struct lock_data lock_data; 937 /* number of board EC sensors */ 938 u8 nr_sensors; 939 /* 940 * number of EC registers to read 941 * (sensor might span more than 1 register) 942 */ 943 u8 nr_registers; 944 /* number of unique register banks */ 945 u8 nr_banks; 946}; 947 948static u8 register_bank(u16 reg) 949{ 950 return reg >> 8; 951} 952 953static u8 register_index(u16 reg) 954{ 955 return reg & 0x00ff; 956} 957 958static bool is_sensor_data_signed(const struct ec_sensor_info *si) 959{ 960 /* 961 * guessed from WMI functions in DSDT code for boards 962 * of the X470 generation 963 */ 964 return si->type == hwmon_temp; 965} 966 967static const struct ec_sensor_info * 968get_sensor_info(const struct ec_sensors_data *state, int index) 969{ 970 return state->sensors_info + state->sensors[index].info_index; 971} 972 973static int find_ec_sensor_index(const struct ec_sensors_data *ec, 974 enum hwmon_sensor_types type, int channel) 975{ 976 unsigned int i; 977 978 for (i = 0; i < ec->nr_sensors; i++) { 979 if (get_sensor_info(ec, i)->type == type) { 980 if (channel == 0) 981 return i; 982 channel--; 983 } 984 } 985 return -ENOENT; 986} 987 988static int bank_compare(const void *a, const void *b) 989{ 990 return *((const s8 *)a) - *((const s8 *)b); 991} 992 993static void setup_sensor_data(struct ec_sensors_data *ec) 994{ 995 struct ec_sensor *s = ec->sensors; 996 bool bank_found; 997 int i, j; 998 u8 bank; 999 1000 ec->nr_banks = 0; 1001 ec->nr_registers = 0; 1002 1003 for_each_set_bit(i, &ec->board_info->sensors, 1004 BITS_PER_TYPE(ec->board_info->sensors)) { 1005 s->info_index = i; 1006 s->cached_value = 0; 1007 ec->nr_registers += 1008 ec->sensors_info[s->info_index].addr.components.size; 1009 bank_found = false; 1010 bank = ec->sensors_info[s->info_index].addr.components.bank; 1011 for (j = 0; j < ec->nr_banks; j++) { 1012 if (ec->banks[j] == bank) { 1013 bank_found = true; 1014 break; 1015 } 1016 } 1017 if (!bank_found) { 1018 ec->banks[ec->nr_banks++] = bank; 1019 } 1020 s++; 1021 } 1022 sort(ec->banks, ec->nr_banks, 1, bank_compare, NULL); 1023} 1024 1025static void fill_ec_registers(struct ec_sensors_data *ec) 1026{ 1027 const struct ec_sensor_info *si; 1028 unsigned int i, j, register_idx = 0; 1029 1030 for (i = 0; i < ec->nr_sensors; ++i) { 1031 si = get_sensor_info(ec, i); 1032 for (j = 0; j < si->addr.components.size; ++j, ++register_idx) { 1033 ec->registers[register_idx] = 1034 (si->addr.components.bank << 8) + 1035 si->addr.components.index + j; 1036 } 1037 } 1038} 1039 1040static int setup_lock_data(struct device *dev) 1041{ 1042 const char *mutex_path; 1043 int status; 1044 struct ec_sensors_data *state = dev_get_drvdata(dev); 1045 1046 mutex_path = mutex_path_override ? 1047 mutex_path_override : state->board_info->mutex_path; 1048 1049 if (!mutex_path || !strlen(mutex_path)) { 1050 dev_err(dev, "Hardware access guard mutex name is empty"); 1051 return -EINVAL; 1052 } 1053 if (!strcmp(mutex_path, ACPI_GLOBAL_LOCK_PSEUDO_PATH)) { 1054 state->lock_data.mutex.glk = 0; 1055 state->lock_data.lock = lock_via_global_acpi_lock; 1056 state->lock_data.unlock = unlock_global_acpi_lock; 1057 } else { 1058 status = acpi_get_handle(NULL, (acpi_string)mutex_path, 1059 &state->lock_data.mutex.aml); 1060 if (ACPI_FAILURE(status)) { 1061 dev_err(dev, 1062 "Failed to get hardware access guard AML mutex '%s': error %d", 1063 mutex_path, status); 1064 return -ENOENT; 1065 } 1066 state->lock_data.lock = lock_via_acpi_mutex; 1067 state->lock_data.unlock = unlock_acpi_mutex; 1068 } 1069 return 0; 1070} 1071 1072static int asus_ec_bank_switch(u8 bank, u8 *old) 1073{ 1074 int status = 0; 1075 1076 if (old) { 1077 status = ec_read(ASUS_EC_BANK_REGISTER, old); 1078 } 1079 if (status || (old && (*old == bank))) 1080 return status; 1081 return ec_write(ASUS_EC_BANK_REGISTER, bank); 1082} 1083 1084static int asus_ec_block_read(const struct device *dev, 1085 struct ec_sensors_data *ec) 1086{ 1087 int ireg, ibank, status; 1088 u8 bank, reg_bank, prev_bank; 1089 1090 bank = 0; 1091 status = asus_ec_bank_switch(bank, &prev_bank); 1092 if (status) { 1093 dev_warn(dev, "EC bank switch failed"); 1094 return status; 1095 } 1096 1097 if (prev_bank) { 1098 /* oops... somebody else is working with the EC too */ 1099 dev_warn(dev, 1100 "Concurrent access to the ACPI EC detected.\nRace condition possible."); 1101 } 1102 1103 /* read registers minimizing bank switches. */ 1104 for (ibank = 0; ibank < ec->nr_banks; ibank++) { 1105 if (bank != ec->banks[ibank]) { 1106 bank = ec->banks[ibank]; 1107 if (asus_ec_bank_switch(bank, NULL)) { 1108 dev_warn(dev, "EC bank switch to %d failed", 1109 bank); 1110 break; 1111 } 1112 } 1113 for (ireg = 0; ireg < ec->nr_registers; ireg++) { 1114 reg_bank = register_bank(ec->registers[ireg]); 1115 if (reg_bank < bank) { 1116 continue; 1117 } 1118 ec_read(register_index(ec->registers[ireg]), 1119 ec->read_buffer + ireg); 1120 } 1121 } 1122 1123 status = asus_ec_bank_switch(prev_bank, NULL); 1124 return status; 1125} 1126 1127static inline s32 get_sensor_value(const struct ec_sensor_info *si, u8 *data) 1128{ 1129 if (is_sensor_data_signed(si)) { 1130 switch (si->addr.components.size) { 1131 case 1: 1132 return (s8)*data; 1133 case 2: 1134 return (s16)get_unaligned_be16(data); 1135 case 4: 1136 return (s32)get_unaligned_be32(data); 1137 default: 1138 return 0; 1139 } 1140 } else { 1141 switch (si->addr.components.size) { 1142 case 1: 1143 return *data; 1144 case 2: 1145 return get_unaligned_be16(data); 1146 case 4: 1147 return get_unaligned_be32(data); 1148 default: 1149 return 0; 1150 } 1151 } 1152} 1153 1154static void update_sensor_values(struct ec_sensors_data *ec, u8 *data) 1155{ 1156 const struct ec_sensor_info *si; 1157 struct ec_sensor *s, *sensor_end; 1158 1159 sensor_end = ec->sensors + ec->nr_sensors; 1160 for (s = ec->sensors; s != sensor_end; s++) { 1161 si = ec->sensors_info + s->info_index; 1162 s->cached_value = get_sensor_value(si, data); 1163 data += si->addr.components.size; 1164 } 1165} 1166 1167static int update_ec_sensors(const struct device *dev, 1168 struct ec_sensors_data *ec) 1169{ 1170 int status; 1171 1172 if (!ec->lock_data.lock(&ec->lock_data)) { 1173 dev_warn(dev, "Failed to acquire mutex"); 1174 return -EBUSY; 1175 } 1176 1177 status = asus_ec_block_read(dev, ec); 1178 1179 if (!status) { 1180 update_sensor_values(ec, ec->read_buffer); 1181 } 1182 1183 if (!ec->lock_data.unlock(&ec->lock_data)) 1184 dev_err(dev, "Failed to release mutex"); 1185 1186 return status; 1187} 1188 1189static long scale_sensor_value(s32 value, int data_type) 1190{ 1191 switch (data_type) { 1192 case hwmon_curr: 1193 case hwmon_temp: 1194 return value * MILLI; 1195 default: 1196 return value; 1197 } 1198} 1199 1200static int get_cached_value_or_update(const struct device *dev, 1201 int sensor_index, 1202 struct ec_sensors_data *state, s32 *value) 1203{ 1204 if (time_after(jiffies, state->last_updated + HZ)) { 1205 if (update_ec_sensors(dev, state)) { 1206 dev_err(dev, "update_ec_sensors() failure\n"); 1207 return -EIO; 1208 } 1209 1210 state->last_updated = jiffies; 1211 } 1212 1213 *value = state->sensors[sensor_index].cached_value; 1214 return 0; 1215} 1216 1217/* 1218 * Now follow the functions that implement the hwmon interface 1219 */ 1220 1221static int asus_ec_hwmon_read(struct device *dev, enum hwmon_sensor_types type, 1222 u32 attr, int channel, long *val) 1223{ 1224 int ret; 1225 s32 value = 0; 1226 1227 struct ec_sensors_data *state = dev_get_drvdata(dev); 1228 int sidx = find_ec_sensor_index(state, type, channel); 1229 1230 if (sidx < 0) { 1231 return sidx; 1232 } 1233 1234 ret = get_cached_value_or_update(dev, sidx, state, &value); 1235 if (!ret) { 1236 *val = scale_sensor_value(value, 1237 get_sensor_info(state, sidx)->type); 1238 } 1239 1240 return ret; 1241} 1242 1243static int asus_ec_hwmon_read_string(struct device *dev, 1244 enum hwmon_sensor_types type, u32 attr, 1245 int channel, const char **str) 1246{ 1247 struct ec_sensors_data *state = dev_get_drvdata(dev); 1248 int sensor_index = find_ec_sensor_index(state, type, channel); 1249 1250 if (sensor_index < 0) 1251 return sensor_index; 1252 1253 *str = get_sensor_info(state, sensor_index)->label; 1254 1255 return 0; 1256} 1257 1258static umode_t asus_ec_hwmon_is_visible(const void *drvdata, 1259 enum hwmon_sensor_types type, u32 attr, 1260 int channel) 1261{ 1262 const struct ec_sensors_data *state = drvdata; 1263 1264 return find_ec_sensor_index(state, type, channel) >= 0 ? S_IRUGO : 0; 1265} 1266 1267static int 1268asus_ec_hwmon_add_chan_info(struct hwmon_channel_info *asus_ec_hwmon_chan, 1269 struct device *dev, int num, 1270 enum hwmon_sensor_types type, u32 config) 1271{ 1272 int i; 1273 u32 *cfg = devm_kcalloc(dev, num + 1, sizeof(*cfg), GFP_KERNEL); 1274 1275 if (!cfg) 1276 return -ENOMEM; 1277 1278 asus_ec_hwmon_chan->type = type; 1279 asus_ec_hwmon_chan->config = cfg; 1280 for (i = 0; i < num; i++, cfg++) 1281 *cfg = config; 1282 1283 return 0; 1284} 1285 1286static const struct hwmon_ops asus_ec_hwmon_ops = { 1287 .is_visible = asus_ec_hwmon_is_visible, 1288 .read = asus_ec_hwmon_read, 1289 .read_string = asus_ec_hwmon_read_string, 1290}; 1291 1292static struct hwmon_chip_info asus_ec_chip_info = { 1293 .ops = &asus_ec_hwmon_ops, 1294}; 1295 1296static const struct ec_board_info *get_board_info(void) 1297{ 1298 const struct dmi_system_id *dmi_entry; 1299 1300 dmi_entry = dmi_first_match(dmi_table); 1301 return dmi_entry ? dmi_entry->driver_data : NULL; 1302} 1303 1304static int asus_ec_probe(struct platform_device *pdev) 1305{ 1306 const struct hwmon_channel_info **ptr_asus_ec_ci; 1307 int nr_count[hwmon_max] = { 0 }, nr_types = 0; 1308 struct hwmon_channel_info *asus_ec_hwmon_chan; 1309 const struct ec_board_info *pboard_info; 1310 const struct hwmon_chip_info *chip_info; 1311 struct device *dev = &pdev->dev; 1312 struct ec_sensors_data *ec_data; 1313 const struct ec_sensor_info *si; 1314 enum hwmon_sensor_types type; 1315 struct device *hwdev; 1316 unsigned int i; 1317 int status; 1318 1319 pboard_info = get_board_info(); 1320 if (!pboard_info) 1321 return -ENODEV; 1322 1323 ec_data = devm_kzalloc(dev, sizeof(struct ec_sensors_data), 1324 GFP_KERNEL); 1325 if (!ec_data) 1326 return -ENOMEM; 1327 1328 dev_set_drvdata(dev, ec_data); 1329 ec_data->board_info = pboard_info; 1330 1331 switch (ec_data->board_info->family) { 1332 case family_amd_400_series: 1333 ec_data->sensors_info = sensors_family_amd_400; 1334 break; 1335 case family_amd_500_series: 1336 ec_data->sensors_info = sensors_family_amd_500; 1337 break; 1338 case family_amd_600_series: 1339 ec_data->sensors_info = sensors_family_amd_600; 1340 break; 1341 case family_amd_800_series: 1342 ec_data->sensors_info = sensors_family_amd_800; 1343 break; 1344 case family_amd_trx_50: 1345 ec_data->sensors_info = sensors_family_amd_trx_50; 1346 break; 1347 case family_amd_wrx_90: 1348 ec_data->sensors_info = sensors_family_amd_wrx_90; 1349 break; 1350 case family_intel_200_series: 1351 ec_data->sensors_info = sensors_family_intel_200; 1352 break; 1353 case family_intel_300_series: 1354 ec_data->sensors_info = sensors_family_intel_300; 1355 break; 1356 case family_intel_400_series: 1357 ec_data->sensors_info = sensors_family_intel_400; 1358 break; 1359 case family_intel_600_series: 1360 ec_data->sensors_info = sensors_family_intel_600; 1361 break; 1362 case family_intel_700_series: 1363 ec_data->sensors_info = sensors_family_intel_700; 1364 break; 1365 default: 1366 dev_err(dev, "Unknown board family: %d", 1367 ec_data->board_info->family); 1368 return -EINVAL; 1369 } 1370 1371 ec_data->nr_sensors = hweight_long(ec_data->board_info->sensors); 1372 ec_data->sensors = devm_kcalloc(dev, ec_data->nr_sensors, 1373 sizeof(struct ec_sensor), GFP_KERNEL); 1374 if (!ec_data->sensors) 1375 return -ENOMEM; 1376 1377 status = setup_lock_data(dev); 1378 if (status) { 1379 dev_err(dev, "Failed to setup state/EC locking: %d", status); 1380 return status; 1381 } 1382 1383 setup_sensor_data(ec_data); 1384 ec_data->registers = devm_kcalloc(dev, ec_data->nr_registers, 1385 sizeof(u16), GFP_KERNEL); 1386 ec_data->read_buffer = devm_kcalloc(dev, ec_data->nr_registers, 1387 sizeof(u8), GFP_KERNEL); 1388 1389 if (!ec_data->registers || !ec_data->read_buffer) 1390 return -ENOMEM; 1391 1392 fill_ec_registers(ec_data); 1393 1394 for (i = 0; i < ec_data->nr_sensors; ++i) { 1395 si = get_sensor_info(ec_data, i); 1396 if (!nr_count[si->type]) 1397 ++nr_types; 1398 ++nr_count[si->type]; 1399 } 1400 1401 if (nr_count[hwmon_temp]) 1402 nr_count[hwmon_chip]++, nr_types++; 1403 1404 asus_ec_hwmon_chan = devm_kcalloc( 1405 dev, nr_types, sizeof(*asus_ec_hwmon_chan), GFP_KERNEL); 1406 if (!asus_ec_hwmon_chan) 1407 return -ENOMEM; 1408 1409 ptr_asus_ec_ci = devm_kcalloc(dev, nr_types + 1, 1410 sizeof(*ptr_asus_ec_ci), GFP_KERNEL); 1411 if (!ptr_asus_ec_ci) 1412 return -ENOMEM; 1413 1414 asus_ec_chip_info.info = ptr_asus_ec_ci; 1415 chip_info = &asus_ec_chip_info; 1416 1417 for (type = 0; type < hwmon_max; ++type) { 1418 if (!nr_count[type]) 1419 continue; 1420 1421 asus_ec_hwmon_add_chan_info(asus_ec_hwmon_chan, dev, 1422 nr_count[type], type, 1423 hwmon_attributes[type]); 1424 *ptr_asus_ec_ci++ = asus_ec_hwmon_chan++; 1425 } 1426 1427 dev_info(dev, "board has %d EC sensors that span %d registers", 1428 ec_data->nr_sensors, ec_data->nr_registers); 1429 1430 hwdev = devm_hwmon_device_register_with_info(dev, "asusec", 1431 ec_data, chip_info, NULL); 1432 1433 return PTR_ERR_OR_ZERO(hwdev); 1434} 1435 1436MODULE_DEVICE_TABLE(dmi, dmi_table); 1437 1438static struct platform_driver asus_ec_sensors_platform_driver = { 1439 .driver = { 1440 .name = "asus-ec-sensors", 1441 }, 1442 .probe = asus_ec_probe, 1443}; 1444 1445static struct platform_device *asus_ec_sensors_platform_device; 1446 1447static int __init asus_ec_init(void) 1448{ 1449 asus_ec_sensors_platform_device = 1450 platform_create_bundle(&asus_ec_sensors_platform_driver, 1451 asus_ec_probe, NULL, 0, NULL, 0); 1452 1453 if (IS_ERR(asus_ec_sensors_platform_device)) 1454 return PTR_ERR(asus_ec_sensors_platform_device); 1455 1456 return 0; 1457} 1458 1459static void __exit asus_ec_exit(void) 1460{ 1461 platform_device_unregister(asus_ec_sensors_platform_device); 1462 platform_driver_unregister(&asus_ec_sensors_platform_driver); 1463} 1464 1465module_init(asus_ec_init); 1466module_exit(asus_ec_exit); 1467 1468module_param_named(mutex_path, mutex_path_override, charp, 0); 1469MODULE_PARM_DESC(mutex_path, 1470 "Override ACPI mutex path used to guard access to hardware"); 1471 1472MODULE_AUTHOR("Eugene Shalygin <eugene.shalygin@gmail.com>"); 1473MODULE_DESCRIPTION( 1474 "HWMON driver for sensors accessible via ACPI EC in ASUS motherboards"); 1475MODULE_LICENSE("GPL");
~/
Read-only file preview.