asus-ec-sensors.c (24658B)
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 <asm/unaligned.h> 38 39static char *mutex_path_override; 40 41/* Writing to this EC register switches EC bank */ 42#define ASUS_EC_BANK_REGISTER 0xff 43#define SENSOR_LABEL_LEN 16 44 45/* 46 * Arbitrary set max. allowed bank number. Required for sorting banks and 47 * currently is overkill with just 2 banks used at max, but for the sake 48 * of alignment let's set it to a higher value. 49 */ 50#define ASUS_EC_MAX_BANK 3 51 52#define ACPI_LOCK_DELAY_MS 500 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 MAX_IDENTICAL_BOARD_VARIATIONS 3 58 59/* Moniker for the ACPI global lock (':' is not allowed in ASL identifiers) */ 60#define ACPI_GLOBAL_LOCK_PSEUDO_PATH ":GLOBAL_LOCK" 61 62typedef union { 63 u32 value; 64 struct { 65 u8 index; 66 u8 bank; 67 u8 size; 68 u8 dummy; 69 } components; 70} sensor_address; 71 72#define MAKE_SENSOR_ADDRESS(size, bank, index) { \ 73 .value = (size << 16) + (bank << 8) + index \ 74 } 75 76static u32 hwmon_attributes[hwmon_max] = { 77 [hwmon_chip] = HWMON_C_REGISTER_TZ, 78 [hwmon_temp] = HWMON_T_INPUT | HWMON_T_LABEL, 79 [hwmon_in] = HWMON_I_INPUT | HWMON_I_LABEL, 80 [hwmon_curr] = HWMON_C_INPUT | HWMON_C_LABEL, 81 [hwmon_fan] = HWMON_F_INPUT | HWMON_F_LABEL, 82}; 83 84struct ec_sensor_info { 85 char label[SENSOR_LABEL_LEN]; 86 enum hwmon_sensor_types type; 87 sensor_address addr; 88}; 89 90#define EC_SENSOR(sensor_label, sensor_type, size, bank, index) { \ 91 .label = sensor_label, .type = sensor_type, \ 92 .addr = MAKE_SENSOR_ADDRESS(size, bank, index), \ 93 } 94 95enum ec_sensors { 96 /* chipset temperature [℃] */ 97 ec_sensor_temp_chipset, 98 /* CPU temperature [℃] */ 99 ec_sensor_temp_cpu, 100 /* motherboard temperature [℃] */ 101 ec_sensor_temp_mb, 102 /* "T_Sensor" temperature sensor reading [℃] */ 103 ec_sensor_temp_t_sensor, 104 /* VRM temperature [℃] */ 105 ec_sensor_temp_vrm, 106 /* CPU Core voltage [mV] */ 107 ec_sensor_in_cpu_core, 108 /* CPU_Opt fan [RPM] */ 109 ec_sensor_fan_cpu_opt, 110 /* VRM heat sink fan [RPM] */ 111 ec_sensor_fan_vrm_hs, 112 /* Chipset fan [RPM] */ 113 ec_sensor_fan_chipset, 114 /* Water flow sensor reading [RPM] */ 115 ec_sensor_fan_water_flow, 116 /* CPU current [A] */ 117 ec_sensor_curr_cpu, 118 /* "Water_In" temperature sensor reading [℃] */ 119 ec_sensor_temp_water_in, 120 /* "Water_Out" temperature sensor reading [℃] */ 121 ec_sensor_temp_water_out, 122}; 123 124#define SENSOR_TEMP_CHIPSET BIT(ec_sensor_temp_chipset) 125#define SENSOR_TEMP_CPU BIT(ec_sensor_temp_cpu) 126#define SENSOR_TEMP_MB BIT(ec_sensor_temp_mb) 127#define SENSOR_TEMP_T_SENSOR BIT(ec_sensor_temp_t_sensor) 128#define SENSOR_TEMP_VRM BIT(ec_sensor_temp_vrm) 129#define SENSOR_IN_CPU_CORE BIT(ec_sensor_in_cpu_core) 130#define SENSOR_FAN_CPU_OPT BIT(ec_sensor_fan_cpu_opt) 131#define SENSOR_FAN_VRM_HS BIT(ec_sensor_fan_vrm_hs) 132#define SENSOR_FAN_CHIPSET BIT(ec_sensor_fan_chipset) 133#define SENSOR_FAN_WATER_FLOW BIT(ec_sensor_fan_water_flow) 134#define SENSOR_CURR_CPU BIT(ec_sensor_curr_cpu) 135#define SENSOR_TEMP_WATER_IN BIT(ec_sensor_temp_water_in) 136#define SENSOR_TEMP_WATER_OUT BIT(ec_sensor_temp_water_out) 137 138enum board_family { 139 family_unknown, 140 family_amd_400_series, 141 family_amd_500_series, 142}; 143 144/* All the known sensors for ASUS EC controllers */ 145static const struct ec_sensor_info sensors_family_amd_400[] = { 146 [ec_sensor_temp_chipset] = 147 EC_SENSOR("Chipset", hwmon_temp, 1, 0x00, 0x3a), 148 [ec_sensor_temp_cpu] = 149 EC_SENSOR("CPU", hwmon_temp, 1, 0x00, 0x3b), 150 [ec_sensor_temp_mb] = 151 EC_SENSOR("Motherboard", hwmon_temp, 1, 0x00, 0x3c), 152 [ec_sensor_temp_t_sensor] = 153 EC_SENSOR("T_Sensor", hwmon_temp, 1, 0x00, 0x3d), 154 [ec_sensor_temp_vrm] = 155 EC_SENSOR("VRM", hwmon_temp, 1, 0x00, 0x3e), 156 [ec_sensor_in_cpu_core] = 157 EC_SENSOR("CPU Core", hwmon_in, 2, 0x00, 0xa2), 158 [ec_sensor_fan_cpu_opt] = 159 EC_SENSOR("CPU_Opt", hwmon_fan, 2, 0x00, 0xbc), 160 [ec_sensor_fan_vrm_hs] = 161 EC_SENSOR("VRM HS", hwmon_fan, 2, 0x00, 0xb2), 162 [ec_sensor_fan_chipset] = 163 /* no chipset fans in this generation */ 164 EC_SENSOR("Chipset", hwmon_fan, 0, 0x00, 0x00), 165 [ec_sensor_fan_water_flow] = 166 EC_SENSOR("Water_Flow", hwmon_fan, 2, 0x00, 0xb4), 167 [ec_sensor_curr_cpu] = 168 EC_SENSOR("CPU", hwmon_curr, 1, 0x00, 0xf4), 169 [ec_sensor_temp_water_in] = 170 EC_SENSOR("Water_In", hwmon_temp, 1, 0x01, 0x0d), 171 [ec_sensor_temp_water_out] = 172 EC_SENSOR("Water_Out", hwmon_temp, 1, 0x01, 0x0b), 173}; 174 175static const struct ec_sensor_info sensors_family_amd_500[] = { 176 [ec_sensor_temp_chipset] = 177 EC_SENSOR("Chipset", hwmon_temp, 1, 0x00, 0x3a), 178 [ec_sensor_temp_cpu] = EC_SENSOR("CPU", hwmon_temp, 1, 0x00, 0x3b), 179 [ec_sensor_temp_mb] = 180 EC_SENSOR("Motherboard", hwmon_temp, 1, 0x00, 0x3c), 181 [ec_sensor_temp_t_sensor] = 182 EC_SENSOR("T_Sensor", hwmon_temp, 1, 0x00, 0x3d), 183 [ec_sensor_temp_vrm] = EC_SENSOR("VRM", hwmon_temp, 1, 0x00, 0x3e), 184 [ec_sensor_in_cpu_core] = 185 EC_SENSOR("CPU Core", hwmon_in, 2, 0x00, 0xa2), 186 [ec_sensor_fan_cpu_opt] = 187 EC_SENSOR("CPU_Opt", hwmon_fan, 2, 0x00, 0xb0), 188 [ec_sensor_fan_vrm_hs] = EC_SENSOR("VRM HS", hwmon_fan, 2, 0x00, 0xb2), 189 [ec_sensor_fan_chipset] = 190 EC_SENSOR("Chipset", hwmon_fan, 2, 0x00, 0xb4), 191 [ec_sensor_fan_water_flow] = 192 EC_SENSOR("Water_Flow", hwmon_fan, 2, 0x00, 0xbc), 193 [ec_sensor_curr_cpu] = EC_SENSOR("CPU", hwmon_curr, 1, 0x00, 0xf4), 194 [ec_sensor_temp_water_in] = 195 EC_SENSOR("Water_In", hwmon_temp, 1, 0x01, 0x00), 196 [ec_sensor_temp_water_out] = 197 EC_SENSOR("Water_Out", hwmon_temp, 1, 0x01, 0x01), 198}; 199 200/* Shortcuts for common combinations */ 201#define SENSOR_SET_TEMP_CHIPSET_CPU_MB \ 202 (SENSOR_TEMP_CHIPSET | SENSOR_TEMP_CPU | SENSOR_TEMP_MB) 203#define SENSOR_SET_TEMP_WATER (SENSOR_TEMP_WATER_IN | SENSOR_TEMP_WATER_OUT) 204 205struct ec_board_info { 206 const char *board_names[MAX_IDENTICAL_BOARD_VARIATIONS]; 207 unsigned long sensors; 208 /* 209 * Defines which mutex to use for guarding access to the state and the 210 * hardware. Can be either a full path to an AML mutex or the 211 * pseudo-path ACPI_GLOBAL_LOCK_PSEUDO_PATH to use the global ACPI lock, 212 * or left empty to use a regular mutex object, in which case access to 213 * the hardware is not guarded. 214 */ 215 const char *mutex_path; 216 enum board_family family; 217}; 218 219static const struct ec_board_info board_info[] = { 220 { 221 .board_names = {"PRIME X470-PRO"}, 222 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | 223 SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM | 224 SENSOR_FAN_CPU_OPT | 225 SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE, 226 .mutex_path = ACPI_GLOBAL_LOCK_PSEUDO_PATH, 227 .family = family_amd_400_series, 228 }, 229 { 230 .board_names = {"PRIME X570-PRO"}, 231 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | SENSOR_TEMP_VRM | 232 SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CHIPSET, 233 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX, 234 .family = family_amd_500_series, 235 }, 236 { 237 .board_names = {"ProArt X570-CREATOR WIFI"}, 238 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | SENSOR_TEMP_VRM | 239 SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CPU_OPT | 240 SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE, 241 }, 242 { 243 .board_names = {"Pro WS X570-ACE"}, 244 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | SENSOR_TEMP_VRM | 245 SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CHIPSET | 246 SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE, 247 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX, 248 .family = family_amd_500_series, 249 }, 250 { 251 .board_names = {"ROG CROSSHAIR VIII DARK HERO"}, 252 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | 253 SENSOR_TEMP_T_SENSOR | 254 SENSOR_TEMP_VRM | SENSOR_SET_TEMP_WATER | 255 SENSOR_FAN_CPU_OPT | SENSOR_FAN_WATER_FLOW | 256 SENSOR_CURR_CPU | SENSOR_IN_CPU_CORE, 257 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX, 258 .family = family_amd_500_series, 259 }, 260 { 261 .board_names = { 262 "ROG CROSSHAIR VIII FORMULA", 263 "ROG CROSSHAIR VIII HERO", 264 "ROG CROSSHAIR VIII HERO (WI-FI)", 265 }, 266 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | 267 SENSOR_TEMP_T_SENSOR | 268 SENSOR_TEMP_VRM | SENSOR_SET_TEMP_WATER | 269 SENSOR_FAN_CPU_OPT | SENSOR_FAN_CHIPSET | 270 SENSOR_FAN_WATER_FLOW | SENSOR_CURR_CPU | 271 SENSOR_IN_CPU_CORE, 272 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX, 273 .family = family_amd_500_series, 274 }, 275 { 276 .board_names = {"ROG CROSSHAIR VIII IMPACT"}, 277 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | 278 SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM | 279 SENSOR_FAN_CHIPSET | SENSOR_CURR_CPU | 280 SENSOR_IN_CPU_CORE, 281 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX, 282 .family = family_amd_500_series, 283 }, 284 { 285 .board_names = {"ROG STRIX B550-E GAMING"}, 286 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | 287 SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM | 288 SENSOR_FAN_CPU_OPT, 289 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX, 290 .family = family_amd_500_series, 291 }, 292 { 293 .board_names = {"ROG STRIX B550-I GAMING"}, 294 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | 295 SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM | 296 SENSOR_FAN_VRM_HS | SENSOR_CURR_CPU | 297 SENSOR_IN_CPU_CORE, 298 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX, 299 .family = family_amd_500_series, 300 }, 301 { 302 .board_names = {"ROG STRIX X570-E GAMING"}, 303 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | 304 SENSOR_TEMP_T_SENSOR | SENSOR_TEMP_VRM | 305 SENSOR_FAN_CHIPSET | SENSOR_CURR_CPU | 306 SENSOR_IN_CPU_CORE, 307 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX, 308 .family = family_amd_500_series, 309 }, 310 { 311 .board_names = {"ROG STRIX X570-E GAMING WIFI II"}, 312 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | 313 SENSOR_TEMP_T_SENSOR | SENSOR_CURR_CPU | 314 SENSOR_IN_CPU_CORE, 315 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX, 316 .family = family_amd_500_series, 317 }, 318 { 319 .board_names = {"ROG STRIX X570-F GAMING"}, 320 .sensors = SENSOR_SET_TEMP_CHIPSET_CPU_MB | 321 SENSOR_TEMP_T_SENSOR | SENSOR_FAN_CHIPSET, 322 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX, 323 .family = family_amd_500_series, 324 }, 325 { 326 .board_names = {"ROG STRIX X570-I GAMING"}, 327 .sensors = SENSOR_TEMP_T_SENSOR | SENSOR_FAN_VRM_HS | 328 SENSOR_FAN_CHIPSET | SENSOR_CURR_CPU | 329 SENSOR_IN_CPU_CORE, 330 .mutex_path = ASUS_HW_ACCESS_MUTEX_ASMX, 331 .family = family_amd_500_series, 332 }, 333 {} 334}; 335 336struct ec_sensor { 337 unsigned int info_index; 338 s32 cached_value; 339}; 340 341struct lock_data { 342 union { 343 acpi_handle aml; 344 /* global lock handle */ 345 u32 glk; 346 } mutex; 347 bool (*lock)(struct lock_data *data); 348 bool (*unlock)(struct lock_data *data); 349}; 350 351/* 352 * The next function pairs implement options for locking access to the 353 * state and the EC 354 */ 355static bool lock_via_acpi_mutex(struct lock_data *data) 356{ 357 /* 358 * ASUS DSDT does not specify that access to the EC has to be guarded, 359 * but firmware does access it via ACPI 360 */ 361 return ACPI_SUCCESS(acpi_acquire_mutex(data->mutex.aml, 362 NULL, ACPI_LOCK_DELAY_MS)); 363} 364 365static bool unlock_acpi_mutex(struct lock_data *data) 366{ 367 return ACPI_SUCCESS(acpi_release_mutex(data->mutex.aml, NULL)); 368} 369 370static bool lock_via_global_acpi_lock(struct lock_data *data) 371{ 372 return ACPI_SUCCESS(acpi_acquire_global_lock(ACPI_LOCK_DELAY_MS, 373 &data->mutex.glk)); 374} 375 376static bool unlock_global_acpi_lock(struct lock_data *data) 377{ 378 return ACPI_SUCCESS(acpi_release_global_lock(data->mutex.glk)); 379} 380 381struct ec_sensors_data { 382 const struct ec_board_info *board_info; 383 const struct ec_sensor_info *sensors_info; 384 struct ec_sensor *sensors; 385 /* EC registers to read from */ 386 u16 *registers; 387 u8 *read_buffer; 388 /* sorted list of unique register banks */ 389 u8 banks[ASUS_EC_MAX_BANK + 1]; 390 /* in jiffies */ 391 unsigned long last_updated; 392 struct lock_data lock_data; 393 /* number of board EC sensors */ 394 u8 nr_sensors; 395 /* 396 * number of EC registers to read 397 * (sensor might span more than 1 register) 398 */ 399 u8 nr_registers; 400 /* number of unique register banks */ 401 u8 nr_banks; 402}; 403 404static u8 register_bank(u16 reg) 405{ 406 return reg >> 8; 407} 408 409static u8 register_index(u16 reg) 410{ 411 return reg & 0x00ff; 412} 413 414static bool is_sensor_data_signed(const struct ec_sensor_info *si) 415{ 416 /* 417 * guessed from WMI functions in DSDT code for boards 418 * of the X470 generation 419 */ 420 return si->type == hwmon_temp; 421} 422 423static const struct ec_sensor_info * 424get_sensor_info(const struct ec_sensors_data *state, int index) 425{ 426 return state->sensors_info + state->sensors[index].info_index; 427} 428 429static int find_ec_sensor_index(const struct ec_sensors_data *ec, 430 enum hwmon_sensor_types type, int channel) 431{ 432 unsigned int i; 433 434 for (i = 0; i < ec->nr_sensors; i++) { 435 if (get_sensor_info(ec, i)->type == type) { 436 if (channel == 0) 437 return i; 438 channel--; 439 } 440 } 441 return -ENOENT; 442} 443 444static int __init bank_compare(const void *a, const void *b) 445{ 446 return *((const s8 *)a) - *((const s8 *)b); 447} 448 449static void __init setup_sensor_data(struct ec_sensors_data *ec) 450{ 451 struct ec_sensor *s = ec->sensors; 452 bool bank_found; 453 int i, j; 454 u8 bank; 455 456 ec->nr_banks = 0; 457 ec->nr_registers = 0; 458 459 for_each_set_bit(i, &ec->board_info->sensors, 460 BITS_PER_TYPE(ec->board_info->sensors)) { 461 s->info_index = i; 462 s->cached_value = 0; 463 ec->nr_registers += 464 ec->sensors_info[s->info_index].addr.components.size; 465 bank_found = false; 466 bank = ec->sensors_info[s->info_index].addr.components.bank; 467 for (j = 0; j < ec->nr_banks; j++) { 468 if (ec->banks[j] == bank) { 469 bank_found = true; 470 break; 471 } 472 } 473 if (!bank_found) { 474 ec->banks[ec->nr_banks++] = bank; 475 } 476 s++; 477 } 478 sort(ec->banks, ec->nr_banks, 1, bank_compare, NULL); 479} 480 481static void __init fill_ec_registers(struct ec_sensors_data *ec) 482{ 483 const struct ec_sensor_info *si; 484 unsigned int i, j, register_idx = 0; 485 486 for (i = 0; i < ec->nr_sensors; ++i) { 487 si = get_sensor_info(ec, i); 488 for (j = 0; j < si->addr.components.size; ++j, ++register_idx) { 489 ec->registers[register_idx] = 490 (si->addr.components.bank << 8) + 491 si->addr.components.index + j; 492 } 493 } 494} 495 496static int __init setup_lock_data(struct device *dev) 497{ 498 const char *mutex_path; 499 int status; 500 struct ec_sensors_data *state = dev_get_drvdata(dev); 501 502 mutex_path = mutex_path_override ? 503 mutex_path_override : state->board_info->mutex_path; 504 505 if (!mutex_path || !strlen(mutex_path)) { 506 dev_err(dev, "Hardware access guard mutex name is empty"); 507 return -EINVAL; 508 } 509 if (!strcmp(mutex_path, ACPI_GLOBAL_LOCK_PSEUDO_PATH)) { 510 state->lock_data.mutex.glk = 0; 511 state->lock_data.lock = lock_via_global_acpi_lock; 512 state->lock_data.unlock = unlock_global_acpi_lock; 513 } else { 514 status = acpi_get_handle(NULL, (acpi_string)mutex_path, 515 &state->lock_data.mutex.aml); 516 if (ACPI_FAILURE(status)) { 517 dev_err(dev, 518 "Failed to get hardware access guard AML mutex '%s': error %d", 519 mutex_path, status); 520 return -ENOENT; 521 } 522 state->lock_data.lock = lock_via_acpi_mutex; 523 state->lock_data.unlock = unlock_acpi_mutex; 524 } 525 return 0; 526} 527 528static int asus_ec_bank_switch(u8 bank, u8 *old) 529{ 530 int status = 0; 531 532 if (old) { 533 status = ec_read(ASUS_EC_BANK_REGISTER, old); 534 } 535 if (status || (old && (*old == bank))) 536 return status; 537 return ec_write(ASUS_EC_BANK_REGISTER, bank); 538} 539 540static int asus_ec_block_read(const struct device *dev, 541 struct ec_sensors_data *ec) 542{ 543 int ireg, ibank, status; 544 u8 bank, reg_bank, prev_bank; 545 546 bank = 0; 547 status = asus_ec_bank_switch(bank, &prev_bank); 548 if (status) { 549 dev_warn(dev, "EC bank switch failed"); 550 return status; 551 } 552 553 if (prev_bank) { 554 /* oops... somebody else is working with the EC too */ 555 dev_warn(dev, 556 "Concurrent access to the ACPI EC detected.\nRace condition possible."); 557 } 558 559 /* read registers minimizing bank switches. */ 560 for (ibank = 0; ibank < ec->nr_banks; ibank++) { 561 if (bank != ec->banks[ibank]) { 562 bank = ec->banks[ibank]; 563 if (asus_ec_bank_switch(bank, NULL)) { 564 dev_warn(dev, "EC bank switch to %d failed", 565 bank); 566 break; 567 } 568 } 569 for (ireg = 0; ireg < ec->nr_registers; ireg++) { 570 reg_bank = register_bank(ec->registers[ireg]); 571 if (reg_bank < bank) { 572 continue; 573 } 574 ec_read(register_index(ec->registers[ireg]), 575 ec->read_buffer + ireg); 576 } 577 } 578 579 status = asus_ec_bank_switch(prev_bank, NULL); 580 return status; 581} 582 583static inline s32 get_sensor_value(const struct ec_sensor_info *si, u8 *data) 584{ 585 if (is_sensor_data_signed(si)) { 586 switch (si->addr.components.size) { 587 case 1: 588 return (s8)*data; 589 case 2: 590 return (s16)get_unaligned_be16(data); 591 case 4: 592 return (s32)get_unaligned_be32(data); 593 default: 594 return 0; 595 } 596 } else { 597 switch (si->addr.components.size) { 598 case 1: 599 return *data; 600 case 2: 601 return get_unaligned_be16(data); 602 case 4: 603 return get_unaligned_be32(data); 604 default: 605 return 0; 606 } 607 } 608} 609 610static void update_sensor_values(struct ec_sensors_data *ec, u8 *data) 611{ 612 const struct ec_sensor_info *si; 613 struct ec_sensor *s, *sensor_end; 614 615 sensor_end = ec->sensors + ec->nr_sensors; 616 for (s = ec->sensors; s != sensor_end; s++) { 617 si = ec->sensors_info + s->info_index; 618 s->cached_value = get_sensor_value(si, data); 619 data += si->addr.components.size; 620 } 621} 622 623static int update_ec_sensors(const struct device *dev, 624 struct ec_sensors_data *ec) 625{ 626 int status; 627 628 if (!ec->lock_data.lock(&ec->lock_data)) { 629 dev_warn(dev, "Failed to acquire mutex"); 630 return -EBUSY; 631 } 632 633 status = asus_ec_block_read(dev, ec); 634 635 if (!status) { 636 update_sensor_values(ec, ec->read_buffer); 637 } 638 639 if (!ec->lock_data.unlock(&ec->lock_data)) 640 dev_err(dev, "Failed to release mutex"); 641 642 return status; 643} 644 645static long scale_sensor_value(s32 value, int data_type) 646{ 647 switch (data_type) { 648 case hwmon_curr: 649 case hwmon_temp: 650 return value * MILLI; 651 default: 652 return value; 653 } 654} 655 656static int get_cached_value_or_update(const struct device *dev, 657 int sensor_index, 658 struct ec_sensors_data *state, s32 *value) 659{ 660 if (time_after(jiffies, state->last_updated + HZ)) { 661 if (update_ec_sensors(dev, state)) { 662 dev_err(dev, "update_ec_sensors() failure\n"); 663 return -EIO; 664 } 665 666 state->last_updated = jiffies; 667 } 668 669 *value = state->sensors[sensor_index].cached_value; 670 return 0; 671} 672 673/* 674 * Now follow the functions that implement the hwmon interface 675 */ 676 677static int asus_ec_hwmon_read(struct device *dev, enum hwmon_sensor_types type, 678 u32 attr, int channel, long *val) 679{ 680 int ret; 681 s32 value = 0; 682 683 struct ec_sensors_data *state = dev_get_drvdata(dev); 684 int sidx = find_ec_sensor_index(state, type, channel); 685 686 if (sidx < 0) { 687 return sidx; 688 } 689 690 ret = get_cached_value_or_update(dev, sidx, state, &value); 691 if (!ret) { 692 *val = scale_sensor_value(value, 693 get_sensor_info(state, sidx)->type); 694 } 695 696 return ret; 697} 698 699static int asus_ec_hwmon_read_string(struct device *dev, 700 enum hwmon_sensor_types type, u32 attr, 701 int channel, const char **str) 702{ 703 struct ec_sensors_data *state = dev_get_drvdata(dev); 704 int sensor_index = find_ec_sensor_index(state, type, channel); 705 *str = get_sensor_info(state, sensor_index)->label; 706 707 return 0; 708} 709 710static umode_t asus_ec_hwmon_is_visible(const void *drvdata, 711 enum hwmon_sensor_types type, u32 attr, 712 int channel) 713{ 714 const struct ec_sensors_data *state = drvdata; 715 716 return find_ec_sensor_index(state, type, channel) >= 0 ? S_IRUGO : 0; 717} 718 719static int __init 720asus_ec_hwmon_add_chan_info(struct hwmon_channel_info *asus_ec_hwmon_chan, 721 struct device *dev, int num, 722 enum hwmon_sensor_types type, u32 config) 723{ 724 int i; 725 u32 *cfg = devm_kcalloc(dev, num + 1, sizeof(*cfg), GFP_KERNEL); 726 727 if (!cfg) 728 return -ENOMEM; 729 730 asus_ec_hwmon_chan->type = type; 731 asus_ec_hwmon_chan->config = cfg; 732 for (i = 0; i < num; i++, cfg++) 733 *cfg = config; 734 735 return 0; 736} 737 738static const struct hwmon_ops asus_ec_hwmon_ops = { 739 .is_visible = asus_ec_hwmon_is_visible, 740 .read = asus_ec_hwmon_read, 741 .read_string = asus_ec_hwmon_read_string, 742}; 743 744static struct hwmon_chip_info asus_ec_chip_info = { 745 .ops = &asus_ec_hwmon_ops, 746}; 747 748static const struct ec_board_info * __init get_board_info(void) 749{ 750 const char *dmi_board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR); 751 const char *dmi_board_name = dmi_get_system_info(DMI_BOARD_NAME); 752 const struct ec_board_info *board; 753 754 if (!dmi_board_vendor || !dmi_board_name || 755 strcasecmp(dmi_board_vendor, "ASUSTeK COMPUTER INC.")) 756 return NULL; 757 758 for (board = board_info; board->sensors; board++) { 759 if (match_string(board->board_names, 760 MAX_IDENTICAL_BOARD_VARIATIONS, 761 dmi_board_name) >= 0) 762 return board; 763 } 764 765 return NULL; 766} 767 768static int __init asus_ec_probe(struct platform_device *pdev) 769{ 770 const struct hwmon_channel_info **ptr_asus_ec_ci; 771 int nr_count[hwmon_max] = { 0 }, nr_types = 0; 772 struct hwmon_channel_info *asus_ec_hwmon_chan; 773 const struct ec_board_info *pboard_info; 774 const struct hwmon_chip_info *chip_info; 775 struct device *dev = &pdev->dev; 776 struct ec_sensors_data *ec_data; 777 const struct ec_sensor_info *si; 778 enum hwmon_sensor_types type; 779 struct device *hwdev; 780 unsigned int i; 781 int status; 782 783 pboard_info = get_board_info(); 784 if (!pboard_info) 785 return -ENODEV; 786 787 ec_data = devm_kzalloc(dev, sizeof(struct ec_sensors_data), 788 GFP_KERNEL); 789 if (!ec_data) 790 return -ENOMEM; 791 792 dev_set_drvdata(dev, ec_data); 793 ec_data->board_info = pboard_info; 794 795 switch (ec_data->board_info->family) { 796 case family_amd_400_series: 797 ec_data->sensors_info = sensors_family_amd_400; 798 break; 799 case family_amd_500_series: 800 ec_data->sensors_info = sensors_family_amd_500; 801 break; 802 default: 803 dev_err(dev, "Unknown board family: %d", 804 ec_data->board_info->family); 805 return -EINVAL; 806 } 807 808 ec_data->nr_sensors = hweight_long(ec_data->board_info->sensors); 809 ec_data->sensors = devm_kcalloc(dev, ec_data->nr_sensors, 810 sizeof(struct ec_sensor), GFP_KERNEL); 811 812 status = setup_lock_data(dev); 813 if (status) { 814 dev_err(dev, "Failed to setup state/EC locking: %d", status); 815 return status; 816 } 817 818 setup_sensor_data(ec_data); 819 ec_data->registers = devm_kcalloc(dev, ec_data->nr_registers, 820 sizeof(u16), GFP_KERNEL); 821 ec_data->read_buffer = devm_kcalloc(dev, ec_data->nr_registers, 822 sizeof(u8), GFP_KERNEL); 823 824 if (!ec_data->registers || !ec_data->read_buffer) 825 return -ENOMEM; 826 827 fill_ec_registers(ec_data); 828 829 for (i = 0; i < ec_data->nr_sensors; ++i) { 830 si = get_sensor_info(ec_data, i); 831 if (!nr_count[si->type]) 832 ++nr_types; 833 ++nr_count[si->type]; 834 } 835 836 if (nr_count[hwmon_temp]) 837 nr_count[hwmon_chip]++, nr_types++; 838 839 asus_ec_hwmon_chan = devm_kcalloc( 840 dev, nr_types, sizeof(*asus_ec_hwmon_chan), GFP_KERNEL); 841 if (!asus_ec_hwmon_chan) 842 return -ENOMEM; 843 844 ptr_asus_ec_ci = devm_kcalloc(dev, nr_types + 1, 845 sizeof(*ptr_asus_ec_ci), GFP_KERNEL); 846 if (!ptr_asus_ec_ci) 847 return -ENOMEM; 848 849 asus_ec_chip_info.info = ptr_asus_ec_ci; 850 chip_info = &asus_ec_chip_info; 851 852 for (type = 0; type < hwmon_max; ++type) { 853 if (!nr_count[type]) 854 continue; 855 856 asus_ec_hwmon_add_chan_info(asus_ec_hwmon_chan, dev, 857 nr_count[type], type, 858 hwmon_attributes[type]); 859 *ptr_asus_ec_ci++ = asus_ec_hwmon_chan++; 860 } 861 862 dev_info(dev, "board has %d EC sensors that span %d registers", 863 ec_data->nr_sensors, ec_data->nr_registers); 864 865 hwdev = devm_hwmon_device_register_with_info(dev, "asusec", 866 ec_data, chip_info, NULL); 867 868 return PTR_ERR_OR_ZERO(hwdev); 869} 870 871 872static const struct acpi_device_id acpi_ec_ids[] = { 873 /* Embedded Controller Device */ 874 { "PNP0C09", 0 }, 875 {} 876}; 877 878static struct platform_driver asus_ec_sensors_platform_driver = { 879 .driver = { 880 .name = "asus-ec-sensors", 881 .acpi_match_table = acpi_ec_ids, 882 }, 883}; 884 885MODULE_DEVICE_TABLE(acpi, acpi_ec_ids); 886/* 887 * we use module_platform_driver_probe() rather than module_platform_driver() 888 * because the probe function (and its dependants) are marked with __init, which 889 * means we can't put it into the .probe member of the platform_driver struct 890 * above, and we can't mark the asus_ec_sensors_platform_driver object as __init 891 * because the object is referenced from the module exit code. 892 */ 893module_platform_driver_probe(asus_ec_sensors_platform_driver, asus_ec_probe); 894 895module_param_named(mutex_path, mutex_path_override, charp, 0); 896MODULE_PARM_DESC(mutex_path, 897 "Override ACPI mutex path used to guard access to hardware"); 898 899MODULE_AUTHOR("Eugene Shalygin <eugene.shalygin@gmail.com>"); 900MODULE_DESCRIPTION( 901 "HWMON driver for sensors accessible via ACPI EC in ASUS motherboards"); 902MODULE_LICENSE("GPL");