.. | .. |
---|
| 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) { |
---|