0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #include <linux/acpi.h>
0025 #include <linux/bitops.h>
0026 #include <linux/dev_printk.h>
0027 #include <linux/dmi.h>
0028 #include <linux/hwmon.h>
0029 #include <linux/init.h>
0030 #include <linux/jiffies.h>
0031 #include <linux/kernel.h>
0032 #include <linux/module.h>
0033 #include <linux/platform_device.h>
0034 #include <linux/sort.h>
0035 #include <linux/units.h>
0036
0037 #include <asm/unaligned.h>
0038
0039 static char *mutex_path_override;
0040
0041
0042 #define ASUS_EC_BANK_REGISTER 0xff
0043 #define SENSOR_LABEL_LEN 16
0044
0045
0046
0047
0048
0049
0050 #define ASUS_EC_MAX_BANK 3
0051
0052 #define ACPI_LOCK_DELAY_MS 500
0053
0054
0055 #define ASUS_HW_ACCESS_MUTEX_ASMX "\\AMW0.ASMX"
0056
0057 #define ASUS_HW_ACCESS_MUTEX_RMTW_ASMX "\\RMTW.ASMX"
0058
0059 #define ASUS_HW_ACCESS_MUTEX_SB_PCI0_SBRG_SIO1_MUT0 "\\_SB_.PCI0.SBRG.SIO1.MUT0"
0060
0061 #define MAX_IDENTICAL_BOARD_VARIATIONS 3
0062
0063
0064 #define ACPI_GLOBAL_LOCK_PSEUDO_PATH ":GLOBAL_LOCK"
0065
0066 typedef union {
0067 u32 value;
0068 struct {
0069 u8 index;
0070 u8 bank;
0071 u8 size;
0072 u8 dummy;
0073 } components;
0074 } sensor_address;
0075
0076 #define MAKE_SENSOR_ADDRESS(size, bank, index) { \
0077 .value = (size << 16) + (bank << 8) + index \
0078 }
0079
0080 static u32 hwmon_attributes[hwmon_max] = {
0081 [hwmon_chip] = HWMON_C_REGISTER_TZ,
0082 [hwmon_temp] = HWMON_T_INPUT | HWMON_T_LABEL,
0083 [hwmon_in] = HWMON_I_INPUT | HWMON_I_LABEL,
0084 [hwmon_curr] = HWMON_C_INPUT | HWMON_C_LABEL,
0085 [hwmon_fan] = HWMON_F_INPUT | HWMON_F_LABEL,
0086 };
0087
0088 struct ec_sensor_info {
0089 char label[SENSOR_LABEL_LEN];
0090 enum hwmon_sensor_types type;
0091 sensor_address addr;
0092 };
0093
0094 #define EC_SENSOR(sensor_label, sensor_type, size, bank, index) { \
0095 .label = sensor_label, .type = sensor_type, \
0096 .addr = MAKE_SENSOR_ADDRESS(size, bank, index), \
0097 }
0098
0099 enum ec_sensors {
0100
0101 ec_sensor_temp_chipset,
0102
0103 ec_sensor_temp_cpu,
0104
0105 ec_sensor_temp_mb,
0106
0107 ec_sensor_temp_t_sensor,
0108
0109 ec_sensor_temp_vrm,
0110
0111 ec_sensor_in_cpu_core,
0112
0113 ec_sensor_fan_cpu_opt,
0114
0115 ec_sensor_fan_vrm_hs,
0116
0117 ec_sensor_fan_chipset,
0118
0119 ec_sensor_fan_water_flow,
0120
0121 ec_sensor_curr_cpu,
0122
0123 ec_sensor_temp_water_in,
0124
0125 ec_sensor_temp_water_out,
0126
0127 ec_sensor_temp_water_block_in,
0128
0129 ec_sensor_temp_water_block_out,
0130
0131 ec_sensor_temp_t_sensor_2,
0132
0133 ec_sensor_temp_sensor_extra_1,
0134
0135 ec_sensor_temp_sensor_extra_2,
0136
0137 ec_sensor_temp_sensor_extra_3,
0138 };
0139
0140 #define SENSOR_TEMP_CHIPSET BIT(ec_sensor_temp_chipset)
0141 #define SENSOR_TEMP_CPU BIT(ec_sensor_temp_cpu)
0142 #define SENSOR_TEMP_MB BIT(ec_sensor_temp_mb)
0143 #define SENSOR_TEMP_T_SENSOR BIT(ec_sensor_temp_t_sensor)
0144 #define SENSOR_TEMP_VRM BIT(ec_sensor_temp_vrm)
0145 #define SENSOR_IN_CPU_CORE BIT(ec_sensor_in_cpu_core)
0146 #define SENSOR_FAN_CPU_OPT BIT(ec_sensor_fan_cpu_opt)
0147 #define SENSOR_FAN_VRM_HS BIT(ec_sensor_fan_vrm_hs)
0148 #define SENSOR_FAN_CHIPSET BIT(ec_sensor_fan_chipset)
0149 #define SENSOR_FAN_WATER_FLOW BIT(ec_sensor_fan_water_flow)
0150 #define SENSOR_CURR_CPU BIT(ec_sensor_curr_cpu)
0151 #define SENSOR_TEMP_WATER_IN BIT(ec_sensor_temp_water_in)
0152 #define SENSOR_TEMP_WATER_OUT BIT(ec_sensor_temp_water_out)
0153 #define SENSOR_TEMP_WATER_BLOCK_IN BIT(ec_sensor_temp_water_block_in)
0154 #define SENSOR_TEMP_WATER_BLOCK_OUT BIT(ec_sensor_temp_water_block_out)
0155 #define SENSOR_TEMP_T_SENSOR_2 BIT(ec_sensor_temp_t_sensor_2)
0156 #define SENSOR_TEMP_SENSOR_EXTRA_1 BIT(ec_sensor_temp_sensor_extra_1)
0157 #define SENSOR_TEMP_SENSOR_EXTRA_2 BIT(ec_sensor_temp_sensor_extra_2)
0158 #define SENSOR_TEMP_SENSOR_EXTRA_3 BIT(ec_sensor_temp_sensor_extra_3)
0159
0160 enum board_family {
0161 family_unknown,
0162 family_amd_400_series,
0163 family_amd_500_series,
0164 family_intel_300_series,
0165 family_intel_600_series
0166 };
0167
0168
0169 static const struct ec_sensor_info sensors_family_amd_400[] = {
0170 [ec_sensor_temp_chipset] =
0171 EC_SENSOR("Chipset", hwmon_temp, 1, 0x00, 0x3a),
0172 [ec_sensor_temp_cpu] =
0173 EC_SENSOR("CPU", hwmon_temp, 1, 0x00, 0x3b),
0174 [ec_sensor_temp_mb] =
0175 EC_SENSOR("Motherboard", hwmon_temp, 1, 0x00, 0x3c),
0176 [ec_sensor_temp_t_sensor] =
0177 EC_SENSOR("T_Sensor", hwmon_temp, 1, 0x00, 0x3d),
0178 [ec_sensor_temp_vrm] =
0179 EC_SENSOR("VRM", hwmon_temp, 1, 0x00, 0x3e),
0180 [ec_sensor_in_cpu_core] =
0181 EC_SENSOR("CPU Core", hwmon_in, 2, 0x00, 0xa2),
0182 [ec_sensor_fan_cpu_opt] =
0183 EC_SENSOR("CPU_Opt", hwmon_fan, 2, 0x00, 0xbc),
0184 [ec_sensor_fan_vrm_hs] =
0185 EC_SENSOR("VRM HS", hwmon_fan, 2, 0x00, 0xb2),
0186 [ec_sensor_fan_chipset] =
0187
0188 EC_SENSOR("Chipset", hwmon_fan, 0, 0x00, 0x00),
0189 [ec_sensor_fan_water_flow] =
0190 EC_SENSOR("Water_Flow", hwmon_fan, 2, 0x00, 0xb4),
0191 [ec_sensor_curr_cpu] =
0192 EC_SENSOR("CPU", hwmon_curr, 1, 0x00, 0xf4),
0193 [ec_sensor_temp_water_in] =
0194 EC_SENSOR("Water_In", hwmon_temp, 1, 0x01, 0x0d),
0195 [ec_sensor_temp_water_out] =
0196 EC_SENSOR("Water_Out", hwmon_temp, 1, 0x01, 0x0b),
0197 };
0198
0199 static const struct ec_sensor_info sensors_family_amd_500[] = {
0200 [ec_sensor_temp_chipset] =
0201 EC_SENSOR("Chipset", hwmon_temp, 1, 0x00, 0x3a),
0202 [ec_sensor_temp_cpu] = EC_SENSOR("CPU", hwmon_temp, 1, 0x00, 0x3b),
0203 [ec_sensor_temp_mb] =
0204 EC_SENSOR("Motherboard", hwmon_temp, 1, 0x00, 0x3c),
0205 [ec_sensor_temp_t_sensor] =
0206 EC_SENSOR("T_Sensor", hwmon_temp, 1, 0x00, 0x3d),
0207 [ec_sensor_temp_vrm] = EC_SENSOR("VRM", hwmon_temp, 1, 0x00, 0x3e),
0208 [ec_sensor_in_cpu_core] =
0209 EC_SENSOR("CPU Core", hwmon_in, 2, 0x00, 0xa2),
0210 [ec_sensor_fan_cpu_opt] =
0211 EC_SENSOR("CPU_Opt", hwmon_fan, 2, 0x00, 0xb0),
0212 [ec_sensor_fan_vrm_hs] = EC_SENSOR("VRM HS", hwmon_fan, 2, 0x00, 0xb2),
0213 [ec_sensor_fan_chipset] =
0214 EC_SENSOR("Chipset", hwmon_fan, 2, 0x00, 0xb4),
0215 [ec_sensor_fan_water_flow] =
0216 EC_SENSOR("Water_Flow", hwmon_fan, 2, 0x00, 0xbc),
0217 [ec_sensor_curr_cpu] = EC_SENSOR("CPU", hwmon_curr, 1, 0x00, 0xf4),
0218 [ec_sensor_temp_water_in] =
0219 EC_SENSOR("Water_In", hwmon_temp, 1, 0x01, 0x00),
0220 [ec_sensor_temp_water_out] =
0221 EC_SENSOR("Water_Out", hwmon_temp, 1, 0x01, 0x01),
0222 [ec_sensor_temp_water_block_in] =
0223 EC_SENSOR("Water_Block_In", hwmon_temp, 1, 0x01, 0x02),
0224 [ec_sensor_temp_water_block_out] =
0225 EC_SENSOR("Water_Block_Out", hwmon_temp, 1, 0x01, 0x03),
0226 [ec_sensor_temp_sensor_extra_1] =
0227 EC_SENSOR("Extra_1", hwmon_temp, 1, 0x01, 0x09),
0228 [ec_sensor_temp_t_sensor_2] =
0229 EC_SENSOR("T_sensor_2", hwmon_temp, 1, 0x01, 0x0a),
0230 [ec_sensor_temp_sensor_extra_2] =
0231 EC_SENSOR("Extra_2", hwmon_temp, 1, 0x01, 0x0b),
0232 [ec_sensor_temp_sensor_extra_3] =
0233 EC_SENSOR("Extra_3", hwmon_temp, 1, 0x01, 0x0c),
0234 };
0235
0236 static const struct ec_sensor_info sensors_family_intel_300[] = {
0237 [ec_sensor_temp_chipset] =
0238 EC_SENSOR("Chipset", hwmon_temp, 1, 0x00, 0x3a),
0239 [ec_sensor_temp_cpu] = EC_SENSOR("CPU", hwmon_temp, 1, 0x00, 0x3b),
0240 [ec_sensor_temp_mb] =
0241 EC_SENSOR("Motherboard", hwmon_temp, 1, 0x00, 0x3c),
0242 [ec_sensor_temp_t_sensor] =
0243 EC_SENSOR("T_Sensor", hwmon_temp, 1, 0x00, 0x3d),
0244 [ec_sensor_temp_vrm] = EC_SENSOR("VRM", hwmon_temp, 1, 0x00, 0x3e),
0245 [ec_sensor_fan_cpu_opt] =
0246 EC_SENSOR("CPU_Opt", hwmon_fan, 2, 0x00, 0xb0),
0247 [ec_sensor_fan_vrm_hs] = EC_SENSOR("VRM HS", hwmon_fan, 2, 0x00, 0xb2),
0248 [ec_sensor_fan_water_flow] =
0249 EC_SENSOR("Water_Flow", hwmon_fan, 2, 0x00, 0xbc),
0250 [ec_sensor_temp_water_in] =
0251 EC_SENSOR("Water_In", hwmon_temp, 1, 0x01, 0x00),
0252 [ec_sensor_temp_water_out] =
0253 EC_SENSOR("Water_Out", hwmon_temp, 1, 0x01, 0x01),
0254 };
0255
0256 static const struct ec_sensor_info sensors_family_intel_600[] = {
0257 [ec_sensor_temp_t_sensor] =
0258 EC_SENSOR("T_Sensor", hwmon_temp, 1, 0x00, 0x3d),
0259 [ec_sensor_temp_vrm] = EC_SENSOR("VRM", hwmon_temp, 1, 0x00, 0x3e),
0260 };
0261
0262
0263 #define SENSOR_SET_TEMP_CHIPSET_CPU_MB \
0264 (SENSOR_TEMP_CHIPSET | SENSOR_TEMP_CPU | SENSOR_TEMP_MB)
0265 #define SENSOR_SET_TEMP_WATER (SENSOR_TEMP_WATER_IN | SENSOR_TEMP_WATER_OUT)
0266 #define SENSOR_SET_WATER_BLOCK \
0267 (SENSOR_TEMP_WATER_BLOCK_IN | SENSOR_TEMP_WATER_BLOCK_OUT)
0268
0269 struct ec_board_info {
0270 unsigned long sensors;
0271
0272
0273
0274
0275
0276
0277
0278 const char *mutex_path;
0279 enum board_family family;
0280 };
0281
0282 static const struct ec_board_info board_info_prime_x470_pro = {
0283 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
0284 SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM |
0285 SENSOR_FAN_CPU_OPT |
0286 SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE,
0287 .mutex_path = ACPI_GLOBAL_LOCK_PSEUDO_PATH,
0288 .family = family_amd_400_series,
0289 };
0290
0291 static const struct ec_board_info board_info_prime_x570_pro = {
0292 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | SENSOR_TEMP_VRM |
0293 SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CHIPSET,
0294 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
0295 .family = family_amd_500_series,
0296 };
0297
0298 static const struct ec_board_info board_info_pro_art_x570_creator_wifi = {
0299 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | SENSOR_TEMP_VRM |
0300 SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CPU_OPT |
0301 SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE,
0302 .family = family_amd_500_series,
0303 };
0304
0305 static const struct ec_board_info board_info_pro_ws_x570_ace = {
0306 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | SENSOR_TEMP_VRM |
0307 SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CHIPSET |
0308 SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE,
0309 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
0310 .family = family_amd_500_series,
0311 };
0312
0313 static const struct ec_board_info board_info_crosshair_viii_dark_hero = {
0314 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
0315 SENSOR_TEMP_T_SENSOR |
0316 SENSOR_TEMP_VRM | SENSOR_SET_TEMP_WATER |
0317 SENSOR_FAN_CPU_OPT | SENSOR_FAN_WATER_FLOW |
0318 SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE,
0319 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
0320 .family = family_amd_500_series,
0321 };
0322
0323 static const struct ec_board_info board_info_crosshair_viii_hero = {
0324 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
0325 SENSOR_TEMP_T_SENSOR |
0326 SENSOR_TEMP_VRM | SENSOR_SET_TEMP_WATER |
0327 SENSOR_FAN_CPU_OPT | SENSOR_FAN_CHIPSET |
0328 SENSOR_FAN_WATER_FLOW | SENSOR_CURR_CPU |
0329 SENSOR_IN_CPU_CORE,
0330 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
0331 .family = family_amd_500_series,
0332 };
0333
0334 static const struct ec_board_info board_info_maximus_xi_hero = {
0335 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
0336 SENSOR_TEMP_T_SENSOR |
0337 SENSOR_TEMP_VRM | SENSOR_SET_TEMP_WATER |
0338 SENSOR_FAN_CPU_OPT | SENSOR_FAN_WATER_FLOW,
0339 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
0340 .family = family_intel_300_series,
0341 };
0342
0343 static const struct ec_board_info board_info_crosshair_viii_impact = {
0344 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
0345 SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM |
0346 SENSOR_FAN_CHIPSET | SENSOR_CURR_CPU |
0347 SENSOR_IN_CPU_CORE,
0348 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
0349 .family = family_amd_500_series,
0350 };
0351
0352 static const struct ec_board_info board_info_strix_b550_e_gaming = {
0353 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
0354 SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM |
0355 SENSOR_FAN_CPU_OPT,
0356 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
0357 .family = family_amd_500_series,
0358 };
0359
0360 static const struct ec_board_info board_info_strix_b550_i_gaming = {
0361 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
0362 SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM |
0363 SENSOR_FAN_VRM_HS | SENSOR_CURR_CPU |
0364 SENSOR_IN_CPU_CORE,
0365 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
0366 .family = family_amd_500_series,
0367 };
0368
0369 static const struct ec_board_info board_info_strix_x570_e_gaming = {
0370 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
0371 SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM |
0372 SENSOR_FAN_CHIPSET | SENSOR_CURR_CPU |
0373 SENSOR_IN_CPU_CORE,
0374 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
0375 .family = family_amd_500_series,
0376 };
0377
0378 static const struct ec_board_info board_info_strix_x570_e_gaming_wifi_ii = {
0379 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
0380 SENSOR_TEMP_T_SENSOR | SENSOR_CURR_CPU |
0381 SENSOR_IN_CPU_CORE,
0382 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
0383 .family = family_amd_500_series,
0384 };
0385
0386 static const struct ec_board_info board_info_strix_x570_f_gaming = {
0387 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB |
0388 SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CHIPSET,
0389 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
0390 .family = family_amd_500_series,
0391 };
0392
0393 static const struct ec_board_info board_info_strix_x570_i_gaming = {
0394 .sensors = SENSOR_TEMP_CHIPSET | SENSOR_TEMP_VRM |
0395 SENSOR_TEMP_T_SENSOR |
0396 SENSOR_FAN_VRM_HS | SENSOR_FAN_CHIPSET |
0397 SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE,
0398 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX,
0399 .family = family_amd_500_series,
0400 };
0401
0402 static const struct ec_board_info board_info_strix_z690_a_gaming_wifi_d4 = {
0403 .sensors = SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM,
0404 .mutex_path = ASUS_HW_ACCESS_MUTEX_RMTW_ASMX,
0405 .family = family_intel_600_series,
0406 };
0407
0408 static const struct ec_board_info board_info_zenith_ii_extreme = {
0409 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | SENSOR_TEMP_T_SENSOR |
0410 SENSOR_TEMP_VRM | SENSOR_SET_TEMP_WATER |
0411 SENSOR_FAN_CPU_OPT | SENSOR_FAN_CHIPSET | SENSOR_FAN_VRM_HS |
0412 SENSOR_FAN_WATER_FLOW | SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE |
0413 SENSOR_SET_WATER_BLOCK |
0414 SENSOR_TEMP_T_SENSOR_2 | SENSOR_TEMP_SENSOR_EXTRA_1 |
0415 SENSOR_TEMP_SENSOR_EXTRA_2 | SENSOR_TEMP_SENSOR_EXTRA_3,
0416 .mutex_path = ASUS_HW_ACCESS_MUTEX_SB_PCI0_SBRG_SIO1_MUT0,
0417 .family = family_amd_500_series,
0418 };
0419
0420 #define DMI_EXACT_MATCH_ASUS_BOARD_NAME(name, board_info) \
0421 { \
0422 .matches = { \
0423 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, \
0424 "ASUSTeK COMPUTER INC."), \
0425 DMI_EXACT_MATCH(DMI_BOARD_NAME, name), \
0426 }, \
0427 .driver_data = (void *)board_info, \
0428 }
0429
0430 static const struct dmi_system_id dmi_table[] = {
0431 DMI_EXACT_MATCH_ASUS_BOARD_NAME("PRIME X470-PRO",
0432 &board_info_prime_x470_pro),
0433 DMI_EXACT_MATCH_ASUS_BOARD_NAME("PRIME X570-PRO",
0434 &board_info_prime_x570_pro),
0435 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ProArt X570-CREATOR WIFI",
0436 &board_info_pro_art_x570_creator_wifi),
0437 DMI_EXACT_MATCH_ASUS_BOARD_NAME("Pro WS X570-ACE",
0438 &board_info_pro_ws_x570_ace),
0439 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VIII DARK HERO",
0440 &board_info_crosshair_viii_dark_hero),
0441 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VIII FORMULA",
0442 &board_info_crosshair_viii_hero),
0443 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VIII HERO",
0444 &board_info_crosshair_viii_hero),
0445 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VIII HERO (WI-FI)",
0446 &board_info_crosshair_viii_hero),
0447 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG MAXIMUS XI HERO",
0448 &board_info_maximus_xi_hero),
0449 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG MAXIMUS XI HERO (WI-FI)",
0450 &board_info_maximus_xi_hero),
0451 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VIII IMPACT",
0452 &board_info_crosshair_viii_impact),
0453 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX B550-E GAMING",
0454 &board_info_strix_b550_e_gaming),
0455 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX B550-I GAMING",
0456 &board_info_strix_b550_i_gaming),
0457 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX X570-E GAMING",
0458 &board_info_strix_x570_e_gaming),
0459 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX X570-E GAMING WIFI II",
0460 &board_info_strix_x570_e_gaming_wifi_ii),
0461 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX X570-F GAMING",
0462 &board_info_strix_x570_f_gaming),
0463 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX X570-I GAMING",
0464 &board_info_strix_x570_i_gaming),
0465 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX Z690-A GAMING WIFI D4",
0466 &board_info_strix_z690_a_gaming_wifi_d4),
0467 DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG ZENITH II EXTREME",
0468 &board_info_zenith_ii_extreme),
0469 {},
0470 };
0471
0472 struct ec_sensor {
0473 unsigned int info_index;
0474 s32 cached_value;
0475 };
0476
0477 struct lock_data {
0478 union {
0479 acpi_handle aml;
0480
0481 u32 glk;
0482 } mutex;
0483 bool (*lock)(struct lock_data *data);
0484 bool (*unlock)(struct lock_data *data);
0485 };
0486
0487
0488
0489
0490
0491 static bool lock_via_acpi_mutex(struct lock_data *data)
0492 {
0493
0494
0495
0496
0497 return ACPI_SUCCESS(acpi_acquire_mutex(data->mutex.aml,
0498 NULL, ACPI_LOCK_DELAY_MS));
0499 }
0500
0501 static bool unlock_acpi_mutex(struct lock_data *data)
0502 {
0503 return ACPI_SUCCESS(acpi_release_mutex(data->mutex.aml, NULL));
0504 }
0505
0506 static bool lock_via_global_acpi_lock(struct lock_data *data)
0507 {
0508 return ACPI_SUCCESS(acpi_acquire_global_lock(ACPI_LOCK_DELAY_MS,
0509 &data->mutex.glk));
0510 }
0511
0512 static bool unlock_global_acpi_lock(struct lock_data *data)
0513 {
0514 return ACPI_SUCCESS(acpi_release_global_lock(data->mutex.glk));
0515 }
0516
0517 struct ec_sensors_data {
0518 const struct ec_board_info *board_info;
0519 const struct ec_sensor_info *sensors_info;
0520 struct ec_sensor *sensors;
0521
0522 u16 *registers;
0523 u8 *read_buffer;
0524
0525 u8 banks[ASUS_EC_MAX_BANK + 1];
0526
0527 unsigned long last_updated;
0528 struct lock_data lock_data;
0529
0530 u8 nr_sensors;
0531
0532
0533
0534
0535 u8 nr_registers;
0536
0537 u8 nr_banks;
0538 };
0539
0540 static u8 register_bank(u16 reg)
0541 {
0542 return reg >> 8;
0543 }
0544
0545 static u8 register_index(u16 reg)
0546 {
0547 return reg & 0x00ff;
0548 }
0549
0550 static bool is_sensor_data_signed(const struct ec_sensor_info *si)
0551 {
0552
0553
0554
0555
0556 return si->type == hwmon_temp;
0557 }
0558
0559 static const struct ec_sensor_info *
0560 get_sensor_info(const struct ec_sensors_data *state, int index)
0561 {
0562 return state->sensors_info + state->sensors[index].info_index;
0563 }
0564
0565 static int find_ec_sensor_index(const struct ec_sensors_data *ec,
0566 enum hwmon_sensor_types type, int channel)
0567 {
0568 unsigned int i;
0569
0570 for (i = 0; i < ec->nr_sensors; i++) {
0571 if (get_sensor_info(ec, i)->type == type) {
0572 if (channel == 0)
0573 return i;
0574 channel--;
0575 }
0576 }
0577 return -ENOENT;
0578 }
0579
0580 static int bank_compare(const void *a, const void *b)
0581 {
0582 return *((const s8 *)a) - *((const s8 *)b);
0583 }
0584
0585 static void setup_sensor_data(struct ec_sensors_data *ec)
0586 {
0587 struct ec_sensor *s = ec->sensors;
0588 bool bank_found;
0589 int i, j;
0590 u8 bank;
0591
0592 ec->nr_banks = 0;
0593 ec->nr_registers = 0;
0594
0595 for_each_set_bit(i, &ec->board_info->sensors,
0596 BITS_PER_TYPE(ec->board_info->sensors)) {
0597 s->info_index = i;
0598 s->cached_value = 0;
0599 ec->nr_registers +=
0600 ec->sensors_info[s->info_index].addr.components.size;
0601 bank_found = false;
0602 bank = ec->sensors_info[s->info_index].addr.components.bank;
0603 for (j = 0; j < ec->nr_banks; j++) {
0604 if (ec->banks[j] == bank) {
0605 bank_found = true;
0606 break;
0607 }
0608 }
0609 if (!bank_found) {
0610 ec->banks[ec->nr_banks++] = bank;
0611 }
0612 s++;
0613 }
0614 sort(ec->banks, ec->nr_banks, 1, bank_compare, NULL);
0615 }
0616
0617 static void fill_ec_registers(struct ec_sensors_data *ec)
0618 {
0619 const struct ec_sensor_info *si;
0620 unsigned int i, j, register_idx = 0;
0621
0622 for (i = 0; i < ec->nr_sensors; ++i) {
0623 si = get_sensor_info(ec, i);
0624 for (j = 0; j < si->addr.components.size; ++j, ++register_idx) {
0625 ec->registers[register_idx] =
0626 (si->addr.components.bank << 8) +
0627 si->addr.components.index + j;
0628 }
0629 }
0630 }
0631
0632 static int setup_lock_data(struct device *dev)
0633 {
0634 const char *mutex_path;
0635 int status;
0636 struct ec_sensors_data *state = dev_get_drvdata(dev);
0637
0638 mutex_path = mutex_path_override ?
0639 mutex_path_override : state->board_info->mutex_path;
0640
0641 if (!mutex_path || !strlen(mutex_path)) {
0642 dev_err(dev, "Hardware access guard mutex name is empty");
0643 return -EINVAL;
0644 }
0645 if (!strcmp(mutex_path, ACPI_GLOBAL_LOCK_PSEUDO_PATH)) {
0646 state->lock_data.mutex.glk = 0;
0647 state->lock_data.lock = lock_via_global_acpi_lock;
0648 state->lock_data.unlock = unlock_global_acpi_lock;
0649 } else {
0650 status = acpi_get_handle(NULL, (acpi_string)mutex_path,
0651 &state->lock_data.mutex.aml);
0652 if (ACPI_FAILURE(status)) {
0653 dev_err(dev,
0654 "Failed to get hardware access guard AML mutex '%s': error %d",
0655 mutex_path, status);
0656 return -ENOENT;
0657 }
0658 state->lock_data.lock = lock_via_acpi_mutex;
0659 state->lock_data.unlock = unlock_acpi_mutex;
0660 }
0661 return 0;
0662 }
0663
0664 static int asus_ec_bank_switch(u8 bank, u8 *old)
0665 {
0666 int status = 0;
0667
0668 if (old) {
0669 status = ec_read(ASUS_EC_BANK_REGISTER, old);
0670 }
0671 if (status || (old && (*old == bank)))
0672 return status;
0673 return ec_write(ASUS_EC_BANK_REGISTER, bank);
0674 }
0675
0676 static int asus_ec_block_read(const struct device *dev,
0677 struct ec_sensors_data *ec)
0678 {
0679 int ireg, ibank, status;
0680 u8 bank, reg_bank, prev_bank;
0681
0682 bank = 0;
0683 status = asus_ec_bank_switch(bank, &prev_bank);
0684 if (status) {
0685 dev_warn(dev, "EC bank switch failed");
0686 return status;
0687 }
0688
0689 if (prev_bank) {
0690
0691 dev_warn(dev,
0692 "Concurrent access to the ACPI EC detected.\nRace condition possible.");
0693 }
0694
0695
0696 for (ibank = 0; ibank < ec->nr_banks; ibank++) {
0697 if (bank != ec->banks[ibank]) {
0698 bank = ec->banks[ibank];
0699 if (asus_ec_bank_switch(bank, NULL)) {
0700 dev_warn(dev, "EC bank switch to %d failed",
0701 bank);
0702 break;
0703 }
0704 }
0705 for (ireg = 0; ireg < ec->nr_registers; ireg++) {
0706 reg_bank = register_bank(ec->registers[ireg]);
0707 if (reg_bank < bank) {
0708 continue;
0709 }
0710 ec_read(register_index(ec->registers[ireg]),
0711 ec->read_buffer + ireg);
0712 }
0713 }
0714
0715 status = asus_ec_bank_switch(prev_bank, NULL);
0716 return status;
0717 }
0718
0719 static inline s32 get_sensor_value(const struct ec_sensor_info *si, u8 *data)
0720 {
0721 if (is_sensor_data_signed(si)) {
0722 switch (si->addr.components.size) {
0723 case 1:
0724 return (s8)*data;
0725 case 2:
0726 return (s16)get_unaligned_be16(data);
0727 case 4:
0728 return (s32)get_unaligned_be32(data);
0729 default:
0730 return 0;
0731 }
0732 } else {
0733 switch (si->addr.components.size) {
0734 case 1:
0735 return *data;
0736 case 2:
0737 return get_unaligned_be16(data);
0738 case 4:
0739 return get_unaligned_be32(data);
0740 default:
0741 return 0;
0742 }
0743 }
0744 }
0745
0746 static void update_sensor_values(struct ec_sensors_data *ec, u8 *data)
0747 {
0748 const struct ec_sensor_info *si;
0749 struct ec_sensor *s, *sensor_end;
0750
0751 sensor_end = ec->sensors + ec->nr_sensors;
0752 for (s = ec->sensors; s != sensor_end; s++) {
0753 si = ec->sensors_info + s->info_index;
0754 s->cached_value = get_sensor_value(si, data);
0755 data += si->addr.components.size;
0756 }
0757 }
0758
0759 static int update_ec_sensors(const struct device *dev,
0760 struct ec_sensors_data *ec)
0761 {
0762 int status;
0763
0764 if (!ec->lock_data.lock(&ec->lock_data)) {
0765 dev_warn(dev, "Failed to acquire mutex");
0766 return -EBUSY;
0767 }
0768
0769 status = asus_ec_block_read(dev, ec);
0770
0771 if (!status) {
0772 update_sensor_values(ec, ec->read_buffer);
0773 }
0774
0775 if (!ec->lock_data.unlock(&ec->lock_data))
0776 dev_err(dev, "Failed to release mutex");
0777
0778 return status;
0779 }
0780
0781 static long scale_sensor_value(s32 value, int data_type)
0782 {
0783 switch (data_type) {
0784 case hwmon_curr:
0785 case hwmon_temp:
0786 return value * MILLI;
0787 default:
0788 return value;
0789 }
0790 }
0791
0792 static int get_cached_value_or_update(const struct device *dev,
0793 int sensor_index,
0794 struct ec_sensors_data *state, s32 *value)
0795 {
0796 if (time_after(jiffies, state->last_updated + HZ)) {
0797 if (update_ec_sensors(dev, state)) {
0798 dev_err(dev, "update_ec_sensors() failure\n");
0799 return -EIO;
0800 }
0801
0802 state->last_updated = jiffies;
0803 }
0804
0805 *value = state->sensors[sensor_index].cached_value;
0806 return 0;
0807 }
0808
0809
0810
0811
0812
0813 static int asus_ec_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
0814 u32 attr, int channel, long *val)
0815 {
0816 int ret;
0817 s32 value = 0;
0818
0819 struct ec_sensors_data *state = dev_get_drvdata(dev);
0820 int sidx = find_ec_sensor_index(state, type, channel);
0821
0822 if (sidx < 0) {
0823 return sidx;
0824 }
0825
0826 ret = get_cached_value_or_update(dev, sidx, state, &value);
0827 if (!ret) {
0828 *val = scale_sensor_value(value,
0829 get_sensor_info(state, sidx)->type);
0830 }
0831
0832 return ret;
0833 }
0834
0835 static int asus_ec_hwmon_read_string(struct device *dev,
0836 enum hwmon_sensor_types type, u32 attr,
0837 int channel, const char **str)
0838 {
0839 struct ec_sensors_data *state = dev_get_drvdata(dev);
0840 int sensor_index = find_ec_sensor_index(state, type, channel);
0841 *str = get_sensor_info(state, sensor_index)->label;
0842
0843 return 0;
0844 }
0845
0846 static umode_t asus_ec_hwmon_is_visible(const void *drvdata,
0847 enum hwmon_sensor_types type, u32 attr,
0848 int channel)
0849 {
0850 const struct ec_sensors_data *state = drvdata;
0851
0852 return find_ec_sensor_index(state, type, channel) >= 0 ? S_IRUGO : 0;
0853 }
0854
0855 static int
0856 asus_ec_hwmon_add_chan_info(struct hwmon_channel_info *asus_ec_hwmon_chan,
0857 struct device *dev, int num,
0858 enum hwmon_sensor_types type, u32 config)
0859 {
0860 int i;
0861 u32 *cfg = devm_kcalloc(dev, num + 1, sizeof(*cfg), GFP_KERNEL);
0862
0863 if (!cfg)
0864 return -ENOMEM;
0865
0866 asus_ec_hwmon_chan->type = type;
0867 asus_ec_hwmon_chan->config = cfg;
0868 for (i = 0; i < num; i++, cfg++)
0869 *cfg = config;
0870
0871 return 0;
0872 }
0873
0874 static const struct hwmon_ops asus_ec_hwmon_ops = {
0875 .is_visible = asus_ec_hwmon_is_visible,
0876 .read = asus_ec_hwmon_read,
0877 .read_string = asus_ec_hwmon_read_string,
0878 };
0879
0880 static struct hwmon_chip_info asus_ec_chip_info = {
0881 .ops = &asus_ec_hwmon_ops,
0882 };
0883
0884 static const struct ec_board_info *get_board_info(void)
0885 {
0886 const struct dmi_system_id *dmi_entry;
0887
0888 dmi_entry = dmi_first_match(dmi_table);
0889 return dmi_entry ? dmi_entry->driver_data : NULL;
0890 }
0891
0892 static int asus_ec_probe(struct platform_device *pdev)
0893 {
0894 const struct hwmon_channel_info **ptr_asus_ec_ci;
0895 int nr_count[hwmon_max] = { 0 }, nr_types = 0;
0896 struct hwmon_channel_info *asus_ec_hwmon_chan;
0897 const struct ec_board_info *pboard_info;
0898 const struct hwmon_chip_info *chip_info;
0899 struct device *dev = &pdev->dev;
0900 struct ec_sensors_data *ec_data;
0901 const struct ec_sensor_info *si;
0902 enum hwmon_sensor_types type;
0903 struct device *hwdev;
0904 unsigned int i;
0905 int status;
0906
0907 pboard_info = get_board_info();
0908 if (!pboard_info)
0909 return -ENODEV;
0910
0911 ec_data = devm_kzalloc(dev, sizeof(struct ec_sensors_data),
0912 GFP_KERNEL);
0913 if (!ec_data)
0914 return -ENOMEM;
0915
0916 dev_set_drvdata(dev, ec_data);
0917 ec_data->board_info = pboard_info;
0918
0919 switch (ec_data->board_info->family) {
0920 case family_amd_400_series:
0921 ec_data->sensors_info = sensors_family_amd_400;
0922 break;
0923 case family_amd_500_series:
0924 ec_data->sensors_info = sensors_family_amd_500;
0925 break;
0926 case family_intel_300_series:
0927 ec_data->sensors_info = sensors_family_intel_300;
0928 break;
0929 case family_intel_600_series:
0930 ec_data->sensors_info = sensors_family_intel_600;
0931 break;
0932 default:
0933 dev_err(dev, "Unknown board family: %d",
0934 ec_data->board_info->family);
0935 return -EINVAL;
0936 }
0937
0938 ec_data->nr_sensors = hweight_long(ec_data->board_info->sensors);
0939 ec_data->sensors = devm_kcalloc(dev, ec_data->nr_sensors,
0940 sizeof(struct ec_sensor), GFP_KERNEL);
0941
0942 status = setup_lock_data(dev);
0943 if (status) {
0944 dev_err(dev, "Failed to setup state/EC locking: %d", status);
0945 return status;
0946 }
0947
0948 setup_sensor_data(ec_data);
0949 ec_data->registers = devm_kcalloc(dev, ec_data->nr_registers,
0950 sizeof(u16), GFP_KERNEL);
0951 ec_data->read_buffer = devm_kcalloc(dev, ec_data->nr_registers,
0952 sizeof(u8), GFP_KERNEL);
0953
0954 if (!ec_data->registers || !ec_data->read_buffer)
0955 return -ENOMEM;
0956
0957 fill_ec_registers(ec_data);
0958
0959 for (i = 0; i < ec_data->nr_sensors; ++i) {
0960 si = get_sensor_info(ec_data, i);
0961 if (!nr_count[si->type])
0962 ++nr_types;
0963 ++nr_count[si->type];
0964 }
0965
0966 if (nr_count[hwmon_temp])
0967 nr_count[hwmon_chip]++, nr_types++;
0968
0969 asus_ec_hwmon_chan = devm_kcalloc(
0970 dev, nr_types, sizeof(*asus_ec_hwmon_chan), GFP_KERNEL);
0971 if (!asus_ec_hwmon_chan)
0972 return -ENOMEM;
0973
0974 ptr_asus_ec_ci = devm_kcalloc(dev, nr_types + 1,
0975 sizeof(*ptr_asus_ec_ci), GFP_KERNEL);
0976 if (!ptr_asus_ec_ci)
0977 return -ENOMEM;
0978
0979 asus_ec_chip_info.info = ptr_asus_ec_ci;
0980 chip_info = &asus_ec_chip_info;
0981
0982 for (type = 0; type < hwmon_max; ++type) {
0983 if (!nr_count[type])
0984 continue;
0985
0986 asus_ec_hwmon_add_chan_info(asus_ec_hwmon_chan, dev,
0987 nr_count[type], type,
0988 hwmon_attributes[type]);
0989 *ptr_asus_ec_ci++ = asus_ec_hwmon_chan++;
0990 }
0991
0992 dev_info(dev, "board has %d EC sensors that span %d registers",
0993 ec_data->nr_sensors, ec_data->nr_registers);
0994
0995 hwdev = devm_hwmon_device_register_with_info(dev, "asusec",
0996 ec_data, chip_info, NULL);
0997
0998 return PTR_ERR_OR_ZERO(hwdev);
0999 }
1000
1001 MODULE_DEVICE_TABLE(dmi, dmi_table);
1002
1003 static struct platform_driver asus_ec_sensors_platform_driver = {
1004 .driver = {
1005 .name = "asus-ec-sensors",
1006 },
1007 .probe = asus_ec_probe,
1008 };
1009
1010 static struct platform_device *asus_ec_sensors_platform_device;
1011
1012 static int __init asus_ec_init(void)
1013 {
1014 asus_ec_sensors_platform_device =
1015 platform_create_bundle(&asus_ec_sensors_platform_driver,
1016 asus_ec_probe, NULL, 0, NULL, 0);
1017
1018 if (IS_ERR(asus_ec_sensors_platform_device))
1019 return PTR_ERR(asus_ec_sensors_platform_device);
1020
1021 return 0;
1022 }
1023
1024 static void __exit asus_ec_exit(void)
1025 {
1026 platform_device_unregister(asus_ec_sensors_platform_device);
1027 platform_driver_unregister(&asus_ec_sensors_platform_driver);
1028 }
1029
1030 module_init(asus_ec_init);
1031 module_exit(asus_ec_exit);
1032
1033 module_param_named(mutex_path, mutex_path_override, charp, 0);
1034 MODULE_PARM_DESC(mutex_path,
1035 "Override ACPI mutex path used to guard access to hardware");
1036
1037 MODULE_AUTHOR("Eugene Shalygin <eugene.shalygin@gmail.com>");
1038 MODULE_DESCRIPTION(
1039 "HWMON driver for sensors accessible via ACPI EC in ASUS motherboards");
1040 MODULE_LICENSE("GPL");