| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * ACPI support for Intel Lynxpoint LPSS. |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (C) 2013, Intel Corporation |
|---|
| 5 | 6 | * Authors: Mika Westerberg <mika.westerberg@linux.intel.com> |
|---|
| 6 | 7 | * Rafael J. Wysocki <rafael.j.wysocki@intel.com> |
|---|
| 7 | | - * |
|---|
| 8 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 9 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 10 | | - * published by the Free Software Foundation. |
|---|
| 11 | 8 | */ |
|---|
| 12 | 9 | |
|---|
| 13 | 10 | #include <linux/acpi.h> |
|---|
| 14 | 11 | #include <linux/clkdev.h> |
|---|
| 15 | 12 | #include <linux/clk-provider.h> |
|---|
| 13 | +#include <linux/dmi.h> |
|---|
| 16 | 14 | #include <linux/err.h> |
|---|
| 17 | 15 | #include <linux/io.h> |
|---|
| 18 | 16 | #include <linux/mutex.h> |
|---|
| 19 | 17 | #include <linux/pci.h> |
|---|
| 20 | 18 | #include <linux/platform_device.h> |
|---|
| 21 | | -#include <linux/platform_data/clk-lpss.h> |
|---|
| 19 | +#include <linux/platform_data/x86/clk-lpss.h> |
|---|
| 22 | 20 | #include <linux/platform_data/x86/pmc_atom.h> |
|---|
| 23 | 21 | #include <linux/pm_domain.h> |
|---|
| 24 | 22 | #include <linux/pm_runtime.h> |
|---|
| .. | .. |
|---|
| 27 | 25 | #include <linux/delay.h> |
|---|
| 28 | 26 | |
|---|
| 29 | 27 | #include "internal.h" |
|---|
| 30 | | - |
|---|
| 31 | | -ACPI_MODULE_NAME("acpi_lpss"); |
|---|
| 32 | 28 | |
|---|
| 33 | 29 | #ifdef CONFIG_X86_INTEL_LPSS |
|---|
| 34 | 30 | |
|---|
| .. | .. |
|---|
| 69 | 65 | #define LPSS_CLK_DIVIDER BIT(2) |
|---|
| 70 | 66 | #define LPSS_LTR BIT(3) |
|---|
| 71 | 67 | #define LPSS_SAVE_CTX BIT(4) |
|---|
| 72 | | -#define LPSS_NO_D3_DELAY BIT(5) |
|---|
| 73 | | - |
|---|
| 74 | | -/* Crystal Cove PMIC shares same ACPI ID between different platforms */ |
|---|
| 75 | | -#define BYT_CRC_HRV 2 |
|---|
| 76 | | -#define CHT_CRC_HRV 3 |
|---|
| 68 | +/* |
|---|
| 69 | + * For some devices the DSDT AML code for another device turns off the device |
|---|
| 70 | + * before our suspend handler runs, causing us to read/save all 1-s (0xffffffff) |
|---|
| 71 | + * as ctx register values. |
|---|
| 72 | + * Luckily these devices always use the same ctx register values, so we can |
|---|
| 73 | + * work around this by saving the ctx registers once on activation. |
|---|
| 74 | + */ |
|---|
| 75 | +#define LPSS_SAVE_CTX_ONCE BIT(5) |
|---|
| 76 | +#define LPSS_NO_D3_DELAY BIT(6) |
|---|
| 77 | 77 | |
|---|
| 78 | 78 | struct lpss_private_data; |
|---|
| 79 | 79 | |
|---|
| .. | .. |
|---|
| 160 | 160 | */ |
|---|
| 161 | 161 | static struct pwm_lookup byt_pwm_lookup[] = { |
|---|
| 162 | 162 | PWM_LOOKUP_WITH_MODULE("80860F09:00", 0, "0000:00:02.0", |
|---|
| 163 | | - "pwm_backlight", 0, PWM_POLARITY_NORMAL, |
|---|
| 163 | + "pwm_soc_backlight", 0, PWM_POLARITY_NORMAL, |
|---|
| 164 | 164 | "pwm-lpss-platform"), |
|---|
| 165 | 165 | }; |
|---|
| 166 | 166 | |
|---|
| .. | .. |
|---|
| 172 | 172 | if (!adev->pnp.unique_id || strcmp(adev->pnp.unique_id, "1")) |
|---|
| 173 | 173 | return; |
|---|
| 174 | 174 | |
|---|
| 175 | | - if (!acpi_dev_present("INT33FD", NULL, BYT_CRC_HRV)) |
|---|
| 176 | | - pwm_add_table(byt_pwm_lookup, ARRAY_SIZE(byt_pwm_lookup)); |
|---|
| 175 | + pwm_add_table(byt_pwm_lookup, ARRAY_SIZE(byt_pwm_lookup)); |
|---|
| 177 | 176 | } |
|---|
| 178 | 177 | |
|---|
| 179 | 178 | #define LPSS_I2C_ENABLE 0x6c |
|---|
| .. | .. |
|---|
| 206 | 205 | /* BSW PWM used for backlight control by the i915 driver */ |
|---|
| 207 | 206 | static struct pwm_lookup bsw_pwm_lookup[] = { |
|---|
| 208 | 207 | PWM_LOOKUP_WITH_MODULE("80862288:00", 0, "0000:00:02.0", |
|---|
| 209 | | - "pwm_backlight", 0, PWM_POLARITY_NORMAL, |
|---|
| 208 | + "pwm_soc_backlight", 0, PWM_POLARITY_NORMAL, |
|---|
| 210 | 209 | "pwm-lpss-platform"), |
|---|
| 211 | 210 | }; |
|---|
| 212 | 211 | |
|---|
| .. | .. |
|---|
| 222 | 221 | } |
|---|
| 223 | 222 | |
|---|
| 224 | 223 | static const struct lpss_device_desc lpt_dev_desc = { |
|---|
| 225 | | - .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_LTR, |
|---|
| 224 | + .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_LTR |
|---|
| 225 | + | LPSS_SAVE_CTX, |
|---|
| 226 | 226 | .prv_offset = 0x800, |
|---|
| 227 | 227 | }; |
|---|
| 228 | 228 | |
|---|
| 229 | 229 | static const struct lpss_device_desc lpt_i2c_dev_desc = { |
|---|
| 230 | | - .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_LTR, |
|---|
| 230 | + .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_LTR | LPSS_SAVE_CTX, |
|---|
| 231 | 231 | .prv_offset = 0x800, |
|---|
| 232 | 232 | }; |
|---|
| 233 | 233 | |
|---|
| .. | .. |
|---|
| 239 | 239 | }; |
|---|
| 240 | 240 | |
|---|
| 241 | 241 | static const struct lpss_device_desc lpt_uart_dev_desc = { |
|---|
| 242 | | - .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_LTR, |
|---|
| 242 | + .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_LTR |
|---|
| 243 | + | LPSS_SAVE_CTX, |
|---|
| 243 | 244 | .clk_con_id = "baudclk", |
|---|
| 244 | 245 | .prv_offset = 0x800, |
|---|
| 245 | 246 | .setup = lpss_uart_setup, |
|---|
| .. | .. |
|---|
| 259 | 260 | }; |
|---|
| 260 | 261 | |
|---|
| 261 | 262 | static const struct lpss_device_desc bsw_pwm_dev_desc = { |
|---|
| 262 | | - .flags = LPSS_SAVE_CTX | LPSS_NO_D3_DELAY, |
|---|
| 263 | + .flags = LPSS_SAVE_CTX_ONCE | LPSS_NO_D3_DELAY, |
|---|
| 263 | 264 | .prv_offset = 0x800, |
|---|
| 264 | 265 | .setup = bsw_pwm_setup, |
|---|
| 266 | + .resume_from_noirq = true, |
|---|
| 265 | 267 | }; |
|---|
| 266 | 268 | |
|---|
| 267 | 269 | static const struct lpss_device_desc byt_uart_dev_desc = { |
|---|
| .. | .. |
|---|
| 311 | 313 | .setup = lpss_deassert_reset, |
|---|
| 312 | 314 | }; |
|---|
| 313 | 315 | |
|---|
| 314 | | -#define ICPU(model) { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, } |
|---|
| 315 | | - |
|---|
| 316 | 316 | static const struct x86_cpu_id lpss_cpu_ids[] = { |
|---|
| 317 | | - ICPU(INTEL_FAM6_ATOM_SILVERMONT), /* Valleyview, Bay Trail */ |
|---|
| 318 | | - ICPU(INTEL_FAM6_ATOM_AIRMONT), /* Braswell, Cherry Trail */ |
|---|
| 317 | + X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT, NULL), |
|---|
| 318 | + X86_MATCH_INTEL_FAM6_MODEL(ATOM_AIRMONT, NULL), |
|---|
| 319 | 319 | {} |
|---|
| 320 | 320 | }; |
|---|
| 321 | 321 | |
|---|
| .. | .. |
|---|
| 401 | 401 | if (!lpss_clk_dev) |
|---|
| 402 | 402 | lpt_register_clock_device(); |
|---|
| 403 | 403 | |
|---|
| 404 | + if (IS_ERR(lpss_clk_dev)) |
|---|
| 405 | + return PTR_ERR(lpss_clk_dev); |
|---|
| 406 | + |
|---|
| 404 | 407 | clk_data = platform_get_drvdata(lpss_clk_dev); |
|---|
| 405 | 408 | if (!clk_data) |
|---|
| 406 | 409 | return -ENODEV; |
|---|
| .. | .. |
|---|
| 464 | 467 | const char *consumer_hid; |
|---|
| 465 | 468 | const char *consumer_uid; |
|---|
| 466 | 469 | u32 flags; |
|---|
| 470 | + const struct dmi_system_id *dep_missing_ids; |
|---|
| 471 | +}; |
|---|
| 472 | + |
|---|
| 473 | +/* Please keep this list sorted alphabetically by vendor and model */ |
|---|
| 474 | +static const struct dmi_system_id i2c1_dep_missing_dmi_ids[] = { |
|---|
| 475 | + { |
|---|
| 476 | + .matches = { |
|---|
| 477 | + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), |
|---|
| 478 | + DMI_MATCH(DMI_PRODUCT_NAME, "T200TA"), |
|---|
| 479 | + }, |
|---|
| 480 | + }, |
|---|
| 481 | + {} |
|---|
| 467 | 482 | }; |
|---|
| 468 | 483 | |
|---|
| 469 | 484 | /* |
|---|
| .. | .. |
|---|
| 474 | 489 | * the supplier is not enumerated until after the consumer is probed. |
|---|
| 475 | 490 | */ |
|---|
| 476 | 491 | static const struct lpss_device_links lpss_device_links[] = { |
|---|
| 492 | + /* CHT External sdcard slot controller depends on PMIC I2C ctrl */ |
|---|
| 477 | 493 | {"808622C1", "7", "80860F14", "3", DL_FLAG_PM_RUNTIME}, |
|---|
| 494 | + /* CHT iGPU depends on PMIC I2C controller */ |
|---|
| 495 | + {"808622C1", "7", "LNXVIDEO", NULL, DL_FLAG_PM_RUNTIME}, |
|---|
| 496 | + /* BYT iGPU depends on the Embedded Controller I2C controller (UID 1) */ |
|---|
| 497 | + {"80860F41", "1", "LNXVIDEO", NULL, DL_FLAG_PM_RUNTIME, |
|---|
| 498 | + i2c1_dep_missing_dmi_ids}, |
|---|
| 499 | + /* BYT CR iGPU depends on PMIC I2C controller (UID 5 on CR) */ |
|---|
| 500 | + {"80860F41", "5", "LNXVIDEO", NULL, DL_FLAG_PM_RUNTIME}, |
|---|
| 501 | + /* BYT iGPU depends on PMIC I2C controller (UID 7 on non CR) */ |
|---|
| 502 | + {"80860F41", "7", "LNXVIDEO", NULL, DL_FLAG_PM_RUNTIME}, |
|---|
| 478 | 503 | }; |
|---|
| 479 | | - |
|---|
| 480 | | -static bool hid_uid_match(const char *hid1, const char *uid1, |
|---|
| 481 | | - const char *hid2, const char *uid2) |
|---|
| 482 | | -{ |
|---|
| 483 | | - return !strcmp(hid1, hid2) && uid1 && uid2 && !strcmp(uid1, uid2); |
|---|
| 484 | | -} |
|---|
| 485 | 504 | |
|---|
| 486 | 505 | static bool acpi_lpss_is_supplier(struct acpi_device *adev, |
|---|
| 487 | 506 | const struct lpss_device_links *link) |
|---|
| 488 | 507 | { |
|---|
| 489 | | - return hid_uid_match(acpi_device_hid(adev), acpi_device_uid(adev), |
|---|
| 490 | | - link->supplier_hid, link->supplier_uid); |
|---|
| 508 | + return acpi_dev_hid_uid_match(adev, link->supplier_hid, link->supplier_uid); |
|---|
| 491 | 509 | } |
|---|
| 492 | 510 | |
|---|
| 493 | 511 | static bool acpi_lpss_is_consumer(struct acpi_device *adev, |
|---|
| 494 | 512 | const struct lpss_device_links *link) |
|---|
| 495 | 513 | { |
|---|
| 496 | | - return hid_uid_match(acpi_device_hid(adev), acpi_device_uid(adev), |
|---|
| 497 | | - link->consumer_hid, link->consumer_uid); |
|---|
| 514 | + return acpi_dev_hid_uid_match(adev, link->consumer_hid, link->consumer_uid); |
|---|
| 498 | 515 | } |
|---|
| 499 | 516 | |
|---|
| 500 | 517 | struct hid_uid { |
|---|
| .. | .. |
|---|
| 502 | 519 | const char *uid; |
|---|
| 503 | 520 | }; |
|---|
| 504 | 521 | |
|---|
| 505 | | -static int match_hid_uid(struct device *dev, void *data) |
|---|
| 522 | +static int match_hid_uid(struct device *dev, const void *data) |
|---|
| 506 | 523 | { |
|---|
| 507 | 524 | struct acpi_device *adev = ACPI_COMPANION(dev); |
|---|
| 508 | | - struct hid_uid *id = data; |
|---|
| 525 | + const struct hid_uid *id = data; |
|---|
| 509 | 526 | |
|---|
| 510 | 527 | if (!adev) |
|---|
| 511 | 528 | return 0; |
|---|
| 512 | 529 | |
|---|
| 513 | | - return hid_uid_match(acpi_device_hid(adev), acpi_device_uid(adev), |
|---|
| 514 | | - id->hid, id->uid); |
|---|
| 530 | + return acpi_dev_hid_uid_match(adev, id->hid, id->uid); |
|---|
| 515 | 531 | } |
|---|
| 516 | 532 | |
|---|
| 517 | 533 | static struct device *acpi_lpss_find_device(const char *hid, const char *uid) |
|---|
| .. | .. |
|---|
| 563 | 579 | if (!dev2) |
|---|
| 564 | 580 | return; |
|---|
| 565 | 581 | |
|---|
| 566 | | - if (acpi_lpss_dep(ACPI_COMPANION(dev2), ACPI_HANDLE(dev1))) |
|---|
| 582 | + if ((link->dep_missing_ids && dmi_check_system(link->dep_missing_ids)) |
|---|
| 583 | + || acpi_lpss_dep(ACPI_COMPANION(dev2), ACPI_HANDLE(dev1))) |
|---|
| 567 | 584 | device_link_add(dev2, dev1, link->flags); |
|---|
| 568 | 585 | |
|---|
| 569 | 586 | put_device(dev2); |
|---|
| .. | .. |
|---|
| 578 | 595 | if (!dev2) |
|---|
| 579 | 596 | return; |
|---|
| 580 | 597 | |
|---|
| 581 | | - if (acpi_lpss_dep(ACPI_COMPANION(dev1), ACPI_HANDLE(dev2))) |
|---|
| 598 | + if ((link->dep_missing_ids && dmi_check_system(link->dep_missing_ids)) |
|---|
| 599 | + || acpi_lpss_dep(ACPI_COMPANION(dev1), ACPI_HANDLE(dev2))) |
|---|
| 582 | 600 | device_link_add(dev1, dev2, link->flags); |
|---|
| 583 | 601 | |
|---|
| 584 | 602 | put_device(dev2); |
|---|
| .. | .. |
|---|
| 876 | 894 | * we have to deassert reset line to be sure that ->probe() will |
|---|
| 877 | 895 | * recognize the device. |
|---|
| 878 | 896 | */ |
|---|
| 879 | | - if (pdata->dev_desc->flags & LPSS_SAVE_CTX) |
|---|
| 897 | + if (pdata->dev_desc->flags & (LPSS_SAVE_CTX | LPSS_SAVE_CTX_ONCE)) |
|---|
| 880 | 898 | lpss_deassert_reset(pdata); |
|---|
| 899 | + |
|---|
| 900 | +#ifdef CONFIG_PM |
|---|
| 901 | + if (pdata->dev_desc->flags & LPSS_SAVE_CTX_ONCE) |
|---|
| 902 | + acpi_lpss_save_ctx(dev, pdata); |
|---|
| 903 | +#endif |
|---|
| 881 | 904 | |
|---|
| 882 | 905 | return 0; |
|---|
| 883 | 906 | } |
|---|
| .. | .. |
|---|
| 1022 | 1045 | |
|---|
| 1023 | 1046 | acpi_lpss_d3_to_d0_delay(pdata); |
|---|
| 1024 | 1047 | |
|---|
| 1025 | | - if (pdata->dev_desc->flags & LPSS_SAVE_CTX) |
|---|
| 1048 | + if (pdata->dev_desc->flags & (LPSS_SAVE_CTX | LPSS_SAVE_CTX_ONCE)) |
|---|
| 1026 | 1049 | acpi_lpss_restore_ctx(dev, pdata); |
|---|
| 1027 | 1050 | |
|---|
| 1028 | 1051 | return 0; |
|---|
| .. | .. |
|---|
| 1033 | 1056 | { |
|---|
| 1034 | 1057 | int ret; |
|---|
| 1035 | 1058 | |
|---|
| 1036 | | - if (dev_pm_smart_suspend_and_suspended(dev)) |
|---|
| 1059 | + if (dev_pm_skip_suspend(dev)) |
|---|
| 1037 | 1060 | return 0; |
|---|
| 1038 | 1061 | |
|---|
| 1039 | 1062 | ret = pm_generic_suspend_late(dev); |
|---|
| .. | .. |
|---|
| 1085 | 1108 | if (pdata->dev_desc->resume_from_noirq) |
|---|
| 1086 | 1109 | return 0; |
|---|
| 1087 | 1110 | |
|---|
| 1111 | + if (dev_pm_skip_resume(dev)) |
|---|
| 1112 | + return 0; |
|---|
| 1113 | + |
|---|
| 1088 | 1114 | return acpi_lpss_do_resume_early(dev); |
|---|
| 1089 | 1115 | } |
|---|
| 1090 | 1116 | |
|---|
| .. | .. |
|---|
| 1094 | 1120 | int ret; |
|---|
| 1095 | 1121 | |
|---|
| 1096 | 1122 | /* Follow acpi_subsys_resume_noirq(). */ |
|---|
| 1097 | | - if (dev_pm_may_skip_resume(dev)) |
|---|
| 1123 | + if (dev_pm_skip_resume(dev)) |
|---|
| 1098 | 1124 | return 0; |
|---|
| 1099 | | - |
|---|
| 1100 | | - if (dev_pm_smart_suspend_and_suspended(dev)) |
|---|
| 1101 | | - pm_runtime_set_active(dev); |
|---|
| 1102 | 1125 | |
|---|
| 1103 | 1126 | ret = pm_generic_resume_noirq(dev); |
|---|
| 1104 | 1127 | if (ret) |
|---|
| .. | .. |
|---|
| 1161 | 1184 | { |
|---|
| 1162 | 1185 | struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); |
|---|
| 1163 | 1186 | |
|---|
| 1164 | | - if (dev_pm_smart_suspend_and_suspended(dev)) |
|---|
| 1187 | + if (dev_pm_skip_suspend(dev)) |
|---|
| 1165 | 1188 | return 0; |
|---|
| 1166 | 1189 | |
|---|
| 1167 | 1190 | if (pdata->dev_desc->resume_from_noirq) |
|---|
| .. | .. |
|---|
| 1174 | 1197 | { |
|---|
| 1175 | 1198 | struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); |
|---|
| 1176 | 1199 | |
|---|
| 1177 | | - if (dev_pm_smart_suspend_and_suspended(dev)) |
|---|
| 1200 | + if (dev_pm_skip_suspend(dev)) |
|---|
| 1178 | 1201 | return 0; |
|---|
| 1179 | 1202 | |
|---|
| 1180 | 1203 | if (pdata->dev_desc->resume_from_noirq) { |
|---|