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