1 // SPDX-License-Identifier: GPL-2.0+ 2 3 /* Platform driver for GPD devices that expose fan control via hwmon sysfs. 4 * 5 * Fan control is provided via pwm interface in the range [0-255]. 6 * Each model has a different range in the EC, the written value is scaled to 7 * accommodate for that. 8 * 9 * Based on this repo: 10 * https://github.com/Cryolitia/gpd-fan-driver 11 * 12 * Copyright (c) 2024 Cryolitia PukNgae 13 */ 14 15 #include <linux/acpi.h> 16 #include <linux/dmi.h> 17 #include <linux/hwmon.h> 18 #include <linux/ioport.h> 19 #include <linux/kernel.h> 20 #include <linux/module.h> 21 #include <linux/platform_device.h> 22 23 #define DRIVER_NAME "gpdfan" 24 #define GPD_PWM_CTR_OFFSET 0x1841 25 26 static char *gpd_fan_board = ""; 27 module_param(gpd_fan_board, charp, 0444); 28 29 // EC read/write locker, protecting a sequence of EC operations 30 static DEFINE_MUTEX(gpd_fan_sequence_lock); 31 32 enum gpd_board { 33 win_mini, 34 win4_6800u, 35 win_max_2, 36 duo, 37 }; 38 39 enum FAN_PWM_ENABLE { 40 DISABLE = 0, 41 MANUAL = 1, 42 AUTOMATIC = 2, 43 }; 44 45 static struct { 46 enum FAN_PWM_ENABLE pwm_enable; 47 u8 pwm_value; 48 49 const struct gpd_fan_drvdata *drvdata; 50 } gpd_driver_priv; 51 52 struct gpd_fan_drvdata { 53 const char *board_name; // Board name for module param comparison 54 const enum gpd_board board; 55 56 const u8 addr_port; 57 const u8 data_port; 58 const u16 manual_control_enable; 59 const u16 rpm_read; 60 const u16 pwm_write; 61 const u16 pwm_max; 62 }; 63 64 static struct gpd_fan_drvdata gpd_win_mini_drvdata = { 65 .board_name = "win_mini", 66 .board = win_mini, 67 68 .addr_port = 0x4E, 69 .data_port = 0x4F, 70 .manual_control_enable = 0x047A, 71 .rpm_read = 0x0478, 72 .pwm_write = 0x047A, 73 .pwm_max = 244, 74 }; 75 76 static struct gpd_fan_drvdata gpd_duo_drvdata = { 77 .board_name = "duo", 78 .board = duo, 79 80 .addr_port = 0x4E, 81 .data_port = 0x4F, 82 .manual_control_enable = 0x047A, 83 .rpm_read = 0x0478, 84 .pwm_write = 0x047A, 85 .pwm_max = 244, 86 }; 87 88 static struct gpd_fan_drvdata gpd_win4_drvdata = { 89 .board_name = "win4", 90 .board = win4_6800u, 91 92 .addr_port = 0x2E, 93 .data_port = 0x2F, 94 .manual_control_enable = 0xC311, 95 .rpm_read = 0xC880, 96 .pwm_write = 0xC311, 97 .pwm_max = 127, 98 }; 99 100 static struct gpd_fan_drvdata gpd_wm2_drvdata = { 101 .board_name = "wm2", 102 .board = win_max_2, 103 104 .addr_port = 0x4E, 105 .data_port = 0x4F, 106 .manual_control_enable = 0x0275, 107 .rpm_read = 0x0218, 108 .pwm_write = 0x1809, 109 .pwm_max = 184, 110 }; 111 112 static const struct dmi_system_id dmi_table[] = { 113 { 114 // GPD Win Mini 115 // GPD Win Mini with AMD Ryzen 8840U 116 .matches = { 117 DMI_MATCH(DMI_SYS_VENDOR, "GPD"), 118 DMI_MATCH(DMI_PRODUCT_NAME, "G1617-01") 119 }, 120 .driver_data = &gpd_win_mini_drvdata, 121 }, 122 { 123 // GPD Win Mini 124 // GPD Win Mini with AMD Ryzen HX370 125 .matches = { 126 DMI_MATCH(DMI_SYS_VENDOR, "GPD"), 127 DMI_MATCH(DMI_PRODUCT_NAME, "G1617-02") 128 }, 129 .driver_data = &gpd_win_mini_drvdata, 130 }, 131 { 132 // GPD Win Mini 133 // GPD Win Mini with AMD Ryzen HX370 134 .matches = { 135 DMI_MATCH(DMI_SYS_VENDOR, "GPD"), 136 DMI_MATCH(DMI_PRODUCT_NAME, "G1617-02-L") 137 }, 138 .driver_data = &gpd_win_mini_drvdata, 139 }, 140 { 141 // GPD Win 4 with AMD Ryzen 6800U 142 .matches = { 143 DMI_MATCH(DMI_SYS_VENDOR, "GPD"), 144 DMI_MATCH(DMI_PRODUCT_NAME, "G1618-04"), 145 DMI_MATCH(DMI_BOARD_VERSION, "Default string"), 146 }, 147 .driver_data = &gpd_win4_drvdata, 148 }, 149 { 150 // GPD Win 4 with Ryzen 7840U 151 .matches = { 152 DMI_MATCH(DMI_SYS_VENDOR, "GPD"), 153 DMI_MATCH(DMI_PRODUCT_NAME, "G1618-04"), 154 DMI_MATCH(DMI_BOARD_VERSION, "Ver. 1.0"), 155 }, 156 // Since 7840U, win4 uses the same drvdata as wm2 157 .driver_data = &gpd_wm2_drvdata, 158 }, 159 { 160 // GPD Win 4 with Ryzen 7840U (another) 161 .matches = { 162 DMI_MATCH(DMI_SYS_VENDOR, "GPD"), 163 DMI_MATCH(DMI_PRODUCT_NAME, "G1618-04"), 164 DMI_MATCH(DMI_BOARD_VERSION, "Ver.1.0"), 165 }, 166 .driver_data = &gpd_wm2_drvdata, 167 }, 168 { 169 // GPD Win Max 2 with Ryzen 6800U 170 // GPD Win Max 2 2023 with Ryzen 7840U 171 // GPD Win Max 2 2024 with Ryzen 8840U 172 .matches = { 173 DMI_MATCH(DMI_SYS_VENDOR, "GPD"), 174 DMI_MATCH(DMI_PRODUCT_NAME, "G1619-04"), 175 }, 176 .driver_data = &gpd_wm2_drvdata, 177 }, 178 { 179 // GPD Win Max 2 with AMD Ryzen HX370 180 .matches = { 181 DMI_MATCH(DMI_SYS_VENDOR, "GPD"), 182 DMI_MATCH(DMI_PRODUCT_NAME, "G1619-05"), 183 }, 184 .driver_data = &gpd_wm2_drvdata, 185 }, 186 { 187 // GPD Duo 188 .matches = { 189 DMI_MATCH(DMI_SYS_VENDOR, "GPD"), 190 DMI_MATCH(DMI_PRODUCT_NAME, "G1622-01"), 191 }, 192 .driver_data = &gpd_duo_drvdata, 193 }, 194 { 195 // GPD Duo (another) 196 .matches = { 197 DMI_MATCH(DMI_SYS_VENDOR, "GPD"), 198 DMI_MATCH(DMI_PRODUCT_NAME, "G1622-01-L"), 199 }, 200 .driver_data = &gpd_duo_drvdata, 201 }, 202 { 203 // GPD Pocket 4 204 .matches = { 205 DMI_MATCH(DMI_SYS_VENDOR, "GPD"), 206 DMI_MATCH(DMI_PRODUCT_NAME, "G1628-04"), 207 }, 208 .driver_data = &gpd_win_mini_drvdata, 209 }, 210 { 211 // GPD Pocket 4 (another) 212 .matches = { 213 DMI_MATCH(DMI_SYS_VENDOR, "GPD"), 214 DMI_MATCH(DMI_PRODUCT_NAME, "G1628-04-L"), 215 }, 216 .driver_data = &gpd_win_mini_drvdata, 217 }, 218 {} 219 }; 220 221 static const struct gpd_fan_drvdata *gpd_module_drvdata[] = { 222 &gpd_win_mini_drvdata, &gpd_win4_drvdata, &gpd_wm2_drvdata, NULL 223 }; 224 225 // Helper functions to handle EC read/write 226 static void gpd_ecram_read(u16 offset, u8 *val) 227 { 228 u16 addr_port = gpd_driver_priv.drvdata->addr_port; 229 u16 data_port = gpd_driver_priv.drvdata->data_port; 230 231 outb(0x2E, addr_port); 232 outb(0x11, data_port); 233 outb(0x2F, addr_port); 234 outb((u8)((offset >> 8) & 0xFF), data_port); 235 236 outb(0x2E, addr_port); 237 outb(0x10, data_port); 238 outb(0x2F, addr_port); 239 outb((u8)(offset & 0xFF), data_port); 240 241 outb(0x2E, addr_port); 242 outb(0x12, data_port); 243 outb(0x2F, addr_port); 244 *val = inb(data_port); 245 } 246 247 static void gpd_ecram_write(u16 offset, u8 value) 248 { 249 u16 addr_port = gpd_driver_priv.drvdata->addr_port; 250 u16 data_port = gpd_driver_priv.drvdata->data_port; 251 252 outb(0x2E, addr_port); 253 outb(0x11, data_port); 254 outb(0x2F, addr_port); 255 outb((u8)((offset >> 8) & 0xFF), data_port); 256 257 outb(0x2E, addr_port); 258 outb(0x10, data_port); 259 outb(0x2F, addr_port); 260 outb((u8)(offset & 0xFF), data_port); 261 262 outb(0x2E, addr_port); 263 outb(0x12, data_port); 264 outb(0x2F, addr_port); 265 outb(value, data_port); 266 } 267 268 static int gpd_generic_read_rpm(void) 269 { 270 const struct gpd_fan_drvdata *const drvdata = gpd_driver_priv.drvdata; 271 u8 high, low; 272 273 gpd_ecram_read(drvdata->rpm_read, &high); 274 gpd_ecram_read(drvdata->rpm_read + 1, &low); 275 276 return (u16)high << 8 | low; 277 } 278 279 static void gpd_win4_init_ec(void) 280 { 281 u8 chip_id, chip_ver; 282 283 gpd_ecram_read(0x2000, &chip_id); 284 285 if (chip_id == 0x55) { 286 gpd_ecram_read(0x1060, &chip_ver); 287 gpd_ecram_write(0x1060, chip_ver | 0x80); 288 } 289 } 290 291 static int gpd_win4_read_rpm(void) 292 { 293 int ret; 294 295 ret = gpd_generic_read_rpm(); 296 297 if (ret == 0) 298 // Re-init EC when speed is 0 299 gpd_win4_init_ec(); 300 301 return ret; 302 } 303 304 static int gpd_wm2_read_rpm(void) 305 { 306 for (u16 pwm_ctr_offset = GPD_PWM_CTR_OFFSET; 307 pwm_ctr_offset <= GPD_PWM_CTR_OFFSET + 2; pwm_ctr_offset++) { 308 u8 PWMCTR; 309 310 gpd_ecram_read(pwm_ctr_offset, &PWMCTR); 311 312 if (PWMCTR != 0xB8) 313 gpd_ecram_write(pwm_ctr_offset, 0xB8); 314 } 315 316 return gpd_generic_read_rpm(); 317 } 318 319 // Read value for fan1_input 320 static int gpd_read_rpm(void) 321 { 322 switch (gpd_driver_priv.drvdata->board) { 323 case win_mini: 324 case duo: 325 return gpd_generic_read_rpm(); 326 case win4_6800u: 327 return gpd_win4_read_rpm(); 328 case win_max_2: 329 return gpd_wm2_read_rpm(); 330 } 331 332 return 0; 333 } 334 335 static int gpd_wm2_read_pwm(void) 336 { 337 const struct gpd_fan_drvdata *const drvdata = gpd_driver_priv.drvdata; 338 u8 var; 339 340 gpd_ecram_read(drvdata->pwm_write, &var); 341 342 // Match gpd_generic_write_pwm(u8) below 343 return DIV_ROUND_CLOSEST((var - 1) * 255, (drvdata->pwm_max - 1)); 344 } 345 346 // Read value for pwm1 347 static int gpd_read_pwm(void) 348 { 349 switch (gpd_driver_priv.drvdata->board) { 350 case win_mini: 351 case duo: 352 case win4_6800u: 353 switch (gpd_driver_priv.pwm_enable) { 354 case DISABLE: 355 return 255; 356 case MANUAL: 357 return gpd_driver_priv.pwm_value; 358 case AUTOMATIC: 359 return -EOPNOTSUPP; 360 } 361 break; 362 case win_max_2: 363 return gpd_wm2_read_pwm(); 364 } 365 return 0; 366 } 367 368 // PWM value's range in EC is 1 - pwm_max, cast 0 - 255 to it. 369 static inline u8 gpd_cast_pwm_range(u8 val) 370 { 371 const struct gpd_fan_drvdata *const drvdata = gpd_driver_priv.drvdata; 372 373 return DIV_ROUND_CLOSEST(val * (drvdata->pwm_max - 1), 255) + 1; 374 } 375 376 static void gpd_generic_write_pwm(u8 val) 377 { 378 const struct gpd_fan_drvdata *const drvdata = gpd_driver_priv.drvdata; 379 u8 pwm_reg; 380 381 pwm_reg = gpd_cast_pwm_range(val); 382 gpd_ecram_write(drvdata->pwm_write, pwm_reg); 383 } 384 385 static void gpd_duo_write_pwm(u8 val) 386 { 387 const struct gpd_fan_drvdata *const drvdata = gpd_driver_priv.drvdata; 388 u8 pwm_reg; 389 390 pwm_reg = gpd_cast_pwm_range(val); 391 gpd_ecram_write(drvdata->pwm_write, pwm_reg); 392 gpd_ecram_write(drvdata->pwm_write + 1, pwm_reg); 393 } 394 395 // Write value for pwm1 396 static int gpd_write_pwm(u8 val) 397 { 398 if (gpd_driver_priv.pwm_enable != MANUAL) 399 return -EPERM; 400 401 switch (gpd_driver_priv.drvdata->board) { 402 case duo: 403 gpd_duo_write_pwm(val); 404 break; 405 case win_mini: 406 case win4_6800u: 407 case win_max_2: 408 gpd_generic_write_pwm(val); 409 break; 410 } 411 412 return 0; 413 } 414 415 static void gpd_win_mini_set_pwm_enable(enum FAN_PWM_ENABLE pwm_enable) 416 { 417 switch (pwm_enable) { 418 case DISABLE: 419 gpd_generic_write_pwm(255); 420 break; 421 case MANUAL: 422 gpd_generic_write_pwm(gpd_driver_priv.pwm_value); 423 break; 424 case AUTOMATIC: 425 gpd_ecram_write(gpd_driver_priv.drvdata->pwm_write, 0); 426 break; 427 } 428 } 429 430 static void gpd_duo_set_pwm_enable(enum FAN_PWM_ENABLE pwm_enable) 431 { 432 switch (pwm_enable) { 433 case DISABLE: 434 gpd_duo_write_pwm(255); 435 break; 436 case MANUAL: 437 gpd_duo_write_pwm(gpd_driver_priv.pwm_value); 438 break; 439 case AUTOMATIC: 440 gpd_ecram_write(gpd_driver_priv.drvdata->pwm_write, 0); 441 break; 442 } 443 } 444 445 static void gpd_wm2_set_pwm_enable(enum FAN_PWM_ENABLE enable) 446 { 447 const struct gpd_fan_drvdata *const drvdata = gpd_driver_priv.drvdata; 448 449 switch (enable) { 450 case DISABLE: 451 gpd_generic_write_pwm(255); 452 gpd_ecram_write(drvdata->manual_control_enable, 1); 453 break; 454 case MANUAL: 455 gpd_generic_write_pwm(gpd_driver_priv.pwm_value); 456 gpd_ecram_write(drvdata->manual_control_enable, 1); 457 break; 458 case AUTOMATIC: 459 gpd_ecram_write(drvdata->manual_control_enable, 0); 460 break; 461 } 462 } 463 464 // Write value for pwm1_enable 465 static void gpd_set_pwm_enable(enum FAN_PWM_ENABLE enable) 466 { 467 if (enable == MANUAL) 468 // Set pwm_value to max firstly when switching to manual mode, in 469 // consideration of device safety. 470 gpd_driver_priv.pwm_value = 255; 471 472 switch (gpd_driver_priv.drvdata->board) { 473 case win_mini: 474 case win4_6800u: 475 gpd_win_mini_set_pwm_enable(enable); 476 break; 477 case duo: 478 gpd_duo_set_pwm_enable(enable); 479 break; 480 case win_max_2: 481 gpd_wm2_set_pwm_enable(enable); 482 break; 483 } 484 } 485 486 static umode_t gpd_fan_hwmon_is_visible(__always_unused const void *drvdata, 487 enum hwmon_sensor_types type, u32 attr, 488 __always_unused int channel) 489 { 490 if (type == hwmon_fan && attr == hwmon_fan_input) { 491 return 0444; 492 } else if (type == hwmon_pwm) { 493 switch (attr) { 494 case hwmon_pwm_enable: 495 case hwmon_pwm_input: 496 return 0644; 497 default: 498 return 0; 499 } 500 } 501 return 0; 502 } 503 504 static int gpd_fan_hwmon_read(__always_unused struct device *dev, 505 enum hwmon_sensor_types type, u32 attr, 506 __always_unused int channel, long *val) 507 { 508 int ret; 509 510 ret = mutex_lock_interruptible(&gpd_fan_sequence_lock); 511 if (ret) 512 return ret; 513 514 if (type == hwmon_fan) { 515 if (attr == hwmon_fan_input) { 516 ret = gpd_read_rpm(); 517 518 if (ret < 0) 519 goto OUT; 520 521 *val = ret; 522 ret = 0; 523 goto OUT; 524 } 525 } else if (type == hwmon_pwm) { 526 switch (attr) { 527 case hwmon_pwm_enable: 528 *val = gpd_driver_priv.pwm_enable; 529 ret = 0; 530 goto OUT; 531 case hwmon_pwm_input: 532 ret = gpd_read_pwm(); 533 534 if (ret < 0) 535 goto OUT; 536 537 *val = ret; 538 ret = 0; 539 goto OUT; 540 } 541 } 542 543 ret = -EOPNOTSUPP; 544 545 OUT: 546 mutex_unlock(&gpd_fan_sequence_lock); 547 return ret; 548 } 549 550 static int gpd_fan_hwmon_write(__always_unused struct device *dev, 551 enum hwmon_sensor_types type, u32 attr, 552 __always_unused int channel, long val) 553 { 554 int ret; 555 556 ret = mutex_lock_interruptible(&gpd_fan_sequence_lock); 557 if (ret) 558 return ret; 559 560 if (type == hwmon_pwm) { 561 switch (attr) { 562 case hwmon_pwm_enable: 563 if (!in_range(val, 0, 3)) { 564 ret = -EINVAL; 565 goto OUT; 566 } 567 568 gpd_driver_priv.pwm_enable = val; 569 570 gpd_set_pwm_enable(gpd_driver_priv.pwm_enable); 571 ret = 0; 572 goto OUT; 573 case hwmon_pwm_input: 574 if (!in_range(val, 0, 256)) { 575 ret = -ERANGE; 576 goto OUT; 577 } 578 579 gpd_driver_priv.pwm_value = val; 580 581 ret = gpd_write_pwm(val); 582 goto OUT; 583 } 584 } 585 586 ret = -EOPNOTSUPP; 587 588 OUT: 589 mutex_unlock(&gpd_fan_sequence_lock); 590 return ret; 591 } 592 593 static const struct hwmon_ops gpd_fan_ops = { 594 .is_visible = gpd_fan_hwmon_is_visible, 595 .read = gpd_fan_hwmon_read, 596 .write = gpd_fan_hwmon_write, 597 }; 598 599 static const struct hwmon_channel_info *gpd_fan_hwmon_channel_info[] = { 600 HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT), 601 HWMON_CHANNEL_INFO(pwm, HWMON_PWM_INPUT | HWMON_PWM_ENABLE), 602 NULL 603 }; 604 605 static struct hwmon_chip_info gpd_fan_chip_info = { 606 .ops = &gpd_fan_ops, 607 .info = gpd_fan_hwmon_channel_info 608 }; 609 610 static int gpd_fan_probe(struct platform_device *pdev) 611 { 612 struct device *dev = &pdev->dev; 613 const struct resource *region; 614 const struct resource *res; 615 const struct device *hwdev; 616 617 res = platform_get_resource(pdev, IORESOURCE_IO, 0); 618 if (IS_ERR(res)) 619 return dev_err_probe(dev, PTR_ERR(res), 620 "Failed to get platform resource\n"); 621 622 region = devm_request_region(dev, res->start, 623 resource_size(res), DRIVER_NAME); 624 if (IS_ERR(region)) 625 return dev_err_probe(dev, PTR_ERR(region), 626 "Failed to request region\n"); 627 628 hwdev = devm_hwmon_device_register_with_info(dev, 629 DRIVER_NAME, 630 NULL, 631 &gpd_fan_chip_info, 632 NULL); 633 if (IS_ERR(hwdev)) 634 return dev_err_probe(dev, PTR_ERR(region), 635 "Failed to register hwmon device\n"); 636 637 return 0; 638 } 639 640 static void gpd_fan_remove(__always_unused struct platform_device *pdev) 641 { 642 gpd_driver_priv.pwm_enable = AUTOMATIC; 643 gpd_set_pwm_enable(AUTOMATIC); 644 } 645 646 static struct platform_driver gpd_fan_driver = { 647 .probe = gpd_fan_probe, 648 .remove = gpd_fan_remove, 649 .driver = { 650 .name = KBUILD_MODNAME, 651 }, 652 }; 653 654 static struct platform_device *gpd_fan_platform_device; 655 656 static int __init gpd_fan_init(void) 657 { 658 const struct gpd_fan_drvdata *match = NULL; 659 660 for (const struct gpd_fan_drvdata **p = gpd_module_drvdata; *p; p++) { 661 if (strcmp(gpd_fan_board, (*p)->board_name) == 0) { 662 match = *p; 663 break; 664 } 665 } 666 667 if (!match) { 668 const struct dmi_system_id *dmi_match = 669 dmi_first_match(dmi_table); 670 if (dmi_match) 671 match = dmi_match->driver_data; 672 } 673 674 if (!match) 675 return -ENODEV; 676 677 gpd_driver_priv.pwm_enable = AUTOMATIC; 678 gpd_driver_priv.pwm_value = 255; 679 gpd_driver_priv.drvdata = match; 680 681 struct resource gpd_fan_resources[] = { 682 { 683 .start = match->addr_port, 684 .end = match->data_port, 685 .flags = IORESOURCE_IO, 686 }, 687 }; 688 689 gpd_fan_platform_device = platform_create_bundle(&gpd_fan_driver, 690 gpd_fan_probe, 691 gpd_fan_resources, 692 1, NULL, 0); 693 694 if (IS_ERR(gpd_fan_platform_device)) { 695 pr_warn("Failed to create platform device\n"); 696 return PTR_ERR(gpd_fan_platform_device); 697 } 698 699 return 0; 700 } 701 702 static void __exit gpd_fan_exit(void) 703 { 704 platform_device_unregister(gpd_fan_platform_device); 705 platform_driver_unregister(&gpd_fan_driver); 706 } 707 708 MODULE_DEVICE_TABLE(dmi, dmi_table); 709 710 module_init(gpd_fan_init); 711 module_exit(gpd_fan_exit); 712 713 MODULE_LICENSE("GPL"); 714 MODULE_AUTHOR("Cryolitia PukNgae <cryolitia@uniontech.com>"); 715 MODULE_DESCRIPTION("GPD Devices fan control driver"); 716