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