From b7ecf663c75eed1e764f57281f9508c49c18516e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 21 Apr 2017 12:47:40 +0200 Subject: [PATCH 1/7] ACPI / bus: Introduce a list of ids for "always present" devices Several Bay / Cherry Trail devices (all of which ship with Windows 10) hide the LPSS PWM controller in ACPI, typically the _STA method looks like this: Method (_STA, 0, NotSerialized) // _STA: Status { If (OSID == One) { Return (Zero) } Return (0x0F) } Where OSID is some dark magic seen in all Cherry Trail ACPI tables making the machine behave differently depending on which OS it *thinks* it is booting, this gets set in a number of ways which we cannot control, on some newer machines it simple hardcoded to "One" aka win10. This causes the PWM controller to get hidden, which means Linux cannot control the backlight level on cht based tablets / laptops. Since loading the driver for this does no harm (the only in kernel user of it is the i915 driver, which will only uses it when it needs it), this commit makes acpi_bus_get_status() always set status to ACPI_STA_DEFAULT for the LPSS PWM device, fixing the lack of backlight control. Signed-off-by: Hans de Goede [ rjw: Rename the new file to utils.c ] Signed-off-by: Rafael J. Wysocki --- drivers/acpi/Makefile | 1 + drivers/acpi/bus.c | 5 +++ drivers/acpi/x86/utils.c | 85 ++++++++++++++++++++++++++++++++++++++++ include/acpi/acpi_bus.h | 9 +++++ 4 files changed, 100 insertions(+) create mode 100644 drivers/acpi/x86/utils.c diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index d94f92f88ca1..2a81d278bcf3 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -50,6 +50,7 @@ acpi-$(CONFIG_ACPI_REDUCED_HARDWARE_ONLY) += evged.o acpi-y += sysfs.o acpi-y += property.o acpi-$(CONFIG_X86) += acpi_cmos_rtc.o +acpi-$(CONFIG_X86) += x86/utils.o acpi-$(CONFIG_DEBUG_FS) += debugfs.o acpi-$(CONFIG_ACPI_NUMA) += numa.o acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 34fbe027e73a..784bda663d16 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -114,6 +114,11 @@ int acpi_bus_get_status(struct acpi_device *device) acpi_status status; unsigned long long sta; + if (acpi_device_always_present(device)) { + acpi_set_device_status(device, ACPI_STA_DEFAULT); + return 0; + } + status = acpi_bus_get_status_handle(device->handle, &sta); if (ACPI_FAILURE(status)) return -ENODEV; diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c new file mode 100644 index 000000000000..c8e90ef4485f --- /dev/null +++ b/drivers/acpi/x86/utils.c @@ -0,0 +1,85 @@ +/* + * X86 ACPI Utility Functions + * + * Copyright (C) 2017 Hans de Goede + * + * Based on various non upstream patches to support the CHT Whiskey Cove PMIC: + * Copyright (C) 2013-2015 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include "../internal.h" + +/* + * Some ACPI devices are hidden (status == 0x0) in recent BIOS-es because + * some recent Windows drivers bind to one device but poke at multiple + * devices at the same time, so the others get hidden. + * We work around this by always reporting ACPI_STA_DEFAULT for these + * devices. Note this MUST only be done for devices where this is safe. + * + * This forcing of devices to be present is limited to specific CPU (SoC) + * models both to avoid potentially causing trouble on other models and + * because some HIDs are re-used on different SoCs for completely + * different devices. + */ +struct always_present_id { + struct acpi_device_id hid[2]; + struct x86_cpu_id cpu_ids[2]; + const char *uid; +}; + +#define ICPU(model) { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, } + +#define ENTRY(hid, uid, cpu_models) { \ + { { hid, }, {} }, \ + { cpu_models, {} }, \ + uid, \ +} + +static const struct always_present_id always_present_ids[] = { + /* + * Bay / Cherry Trail PWM directly poked by GPU driver in win10, + * but Linux uses a separate PWM driver, harmless if not used. + */ + ENTRY("80860F09", "1", ICPU(INTEL_FAM6_ATOM_SILVERMONT1)), + ENTRY("80862288", "1", ICPU(INTEL_FAM6_ATOM_AIRMONT)), +}; + +bool acpi_device_always_present(struct acpi_device *adev) +{ + u32 *status = (u32 *)&adev->status; + u32 old_status = *status; + bool ret = false; + unsigned int i; + + /* acpi_match_device_ids checks status, so set it to default */ + *status = ACPI_STA_DEFAULT; + for (i = 0; i < ARRAY_SIZE(always_present_ids); i++) { + if (acpi_match_device_ids(adev, always_present_ids[i].hid)) + continue; + + if (!adev->pnp.unique_id || + strcmp(adev->pnp.unique_id, always_present_ids[i].uid)) + continue; + + if (!x86_match_cpu(always_present_ids[i].cpu_ids)) + continue; + + if (old_status != ACPI_STA_DEFAULT) /* Log only once */ + dev_info(&adev->dev, + "Device [%s] is in always present list\n", + adev->pnp.bus_id); + + ret = true; + break; + } + *status = old_status; + + return ret; +} diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index ef0ae8aaa567..b86b90489140 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -586,6 +586,15 @@ struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle); int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state); int acpi_disable_wakeup_device_power(struct acpi_device *dev); +#ifdef CONFIG_X86 +bool acpi_device_always_present(struct acpi_device *adev); +#else +static inline bool acpi_device_always_present(struct acpi_device *adev) +{ + return false; +} +#endif + #ifdef CONFIG_PM acpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev, void (*work_func)(struct work_struct *work)); From 753a448c27a0238dc1db58cd6954e8ef511a97e1 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 21 Apr 2017 12:47:41 +0200 Subject: [PATCH 2/7] ACPI / bus: Add INT0002 to list of always-present devices The INT0002 device is necessary to clear wakeup interrupt sources on Cherry Trail devices, without it we get nobody cared IRQ msgs and some systems don't properly resume at all without it. Signed-off-by: Hans de Goede Signed-off-by: Rafael J. Wysocki --- drivers/acpi/x86/utils.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c index c8e90ef4485f..bd86b809c848 100644 --- a/drivers/acpi/x86/utils.c +++ b/drivers/acpi/x86/utils.c @@ -49,6 +49,11 @@ static const struct always_present_id always_present_ids[] = { */ ENTRY("80860F09", "1", ICPU(INTEL_FAM6_ATOM_SILVERMONT1)), ENTRY("80862288", "1", ICPU(INTEL_FAM6_ATOM_AIRMONT)), + /* + * The INT0002 device is necessary to clear wakeup interrupt sources + * on Cherry Trail devices, without it we get nobody cared IRQ msgs. + */ + ENTRY("INT0002", "1", ICPU(INTEL_FAM6_ATOM_AIRMONT)), }; bool acpi_device_always_present(struct acpi_device *adev) From 6e14cf361a0cf3bbe0026557427a7eb2f64d3157 Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Sat, 22 Apr 2017 11:23:43 +0800 Subject: [PATCH 3/7] ACPI / APD: Add clock frequency for Hisilicon Hip07/08 I2C controller I2C clock frequency of Designware ip for Hisilicon Hip07 is 200M, but 250M for Hip08, use two ACPI IDs to differentiate them. Signed-off-by: Hanjun Guo Reviewed-by: Kefeng Wang Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_apd.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c index 26696b693e63..8f57648f318b 100644 --- a/drivers/acpi/acpi_apd.c +++ b/drivers/acpi/acpi_apd.c @@ -106,6 +106,16 @@ static const struct apd_device_desc vulcan_spi_desc = { .setup = acpi_apd_setup, .fixed_clk_rate = 133000000, }; + +static const struct apd_device_desc hip07_i2c_desc = { + .setup = acpi_apd_setup, + .fixed_clk_rate = 200000000, +}; + +static const struct apd_device_desc hip08_i2c_desc = { + .setup = acpi_apd_setup, + .fixed_clk_rate = 250000000, +}; #endif #else @@ -169,6 +179,8 @@ static const struct acpi_device_id acpi_apd_device_ids[] = { #ifdef CONFIG_ARM64 { "APMC0D0F", APD_ADDR(xgene_i2c_desc) }, { "BRCM900D", APD_ADDR(vulcan_spi_desc) }, + { "HISI0A21", APD_ADDR(hip07_i2c_desc) }, + { "HISI0A22", APD_ADDR(hip08_i2c_desc) }, #endif { } }; From 58dd8abfad028633d36e2ba81109bd62f6e6e215 Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Sat, 22 Apr 2017 11:23:44 +0800 Subject: [PATCH 4/7] i2c: designware: Add ACPI HID for Hisilicon Hip07/08 I2C controller Add ACPI HID HISI02A1 and HISI02A2 for Hisilicon Hip07/08, which have different clock frequency. Signed-off-by: Hanjun Guo Acked-by: Jarkko Nikula Signed-off-by: Rafael J. Wysocki --- drivers/i2c/busses/i2c-designware-platdrv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index 79c4b4ea0539..90c7c101b7fd 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -129,6 +129,8 @@ static const struct acpi_device_id dw_i2c_acpi_match[] = { { "AMDI0010", ACCESS_INTR_MASK }, { "AMDI0510", 0 }, { "APMC0D0F", 0 }, + { "HISI02A1", 0 }, + { "HISI02A2", 0 }, { } }; MODULE_DEVICE_TABLE(acpi, dw_i2c_acpi_match); From 04434ab5120a362c11ae6e6cf196fc6a98c3365d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 21 Apr 2017 09:35:07 +0200 Subject: [PATCH 5/7] ACPI / LPSS: Call pwm_add_table() for Bay Trail PWM device On Bay Trail systems with a Crystal Cove PMIC the Crystal Cove's PWM is used to control the backlight brightness. On systems without one, the Crystal Cove SoC's PWM is used and we need to call pwm_add_table() so that the i915 driver can find the pwm for controlling the backlight. Signed-off-by: Hans de Goede Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_lpss.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 5edfd9c49044..10347e3d73ad 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -143,6 +143,22 @@ static void lpss_deassert_reset(struct lpss_private_data *pdata) writel(val, pdata->mmio_base + offset); } +/* + * BYT PWM used for backlight control by the i915 driver on systems without + * the Crystal Cove PMIC. + */ +static struct pwm_lookup byt_pwm_lookup[] = { + PWM_LOOKUP_WITH_MODULE("80860F09:00", 0, "0000:00:02.0", + "pwm_backlight", 0, PWM_POLARITY_NORMAL, + "pwm-lpss-platform"), +}; + +static void byt_pwm_setup(struct lpss_private_data *pdata) +{ + if (!acpi_dev_present("INT33FD", NULL, -1)) + pwm_add_table(byt_pwm_lookup, ARRAY_SIZE(byt_pwm_lookup)); +} + #define LPSS_I2C_ENABLE 0x6c static void byt_i2c_setup(struct lpss_private_data *pdata) @@ -200,6 +216,7 @@ static const struct lpss_device_desc lpt_sdio_dev_desc = { static const struct lpss_device_desc byt_pwm_dev_desc = { .flags = LPSS_SAVE_CTX, + .setup = byt_pwm_setup, }; static const struct lpss_device_desc bsw_pwm_dev_desc = { From 2bde7c32b1db162692f05c6be066b5bcd3d9fdbe Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 21 Apr 2017 13:48:08 +0200 Subject: [PATCH 6/7] ACPI / PMIC: xpower: Fix power_table addresses The power table addresses should be contiguous, but there was a hole where 0x34 was missing. On most devices this is not a problem as addresses above 0x34 are used for the BUC# convertors which are not used in the DSDTs I've access to but after the BUC# convertors there is a field named GPI1 in the DSTDs, which does get used in some cases and ended up turning BUC6 on and off due to the wrong addresses, resulting in turning the entire device off (or causing it to reboot). Removing the hole in the addresses fixes this, fixing one of my Bay Trail tablets turning off while booting the mainline kernel. While at it add comments with the field names used in the DSDTs to make it easier to compare the register and bits used at each address with the datasheet. Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Rafael J. Wysocki --- drivers/acpi/pmic/intel_pmic_xpower.c | 54 +++++++++++++-------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/drivers/acpi/pmic/intel_pmic_xpower.c b/drivers/acpi/pmic/intel_pmic_xpower.c index 55f51115f016..1a76c784cd4c 100644 --- a/drivers/acpi/pmic/intel_pmic_xpower.c +++ b/drivers/acpi/pmic/intel_pmic_xpower.c @@ -27,97 +27,97 @@ static struct pmic_table power_table[] = { .address = 0x00, .reg = 0x13, .bit = 0x05, - }, + }, /* ALD1 */ { .address = 0x04, .reg = 0x13, .bit = 0x06, - }, + }, /* ALD2 */ { .address = 0x08, .reg = 0x13, .bit = 0x07, - }, + }, /* ALD3 */ { .address = 0x0c, .reg = 0x12, .bit = 0x03, - }, + }, /* DLD1 */ { .address = 0x10, .reg = 0x12, .bit = 0x04, - }, + }, /* DLD2 */ { .address = 0x14, .reg = 0x12, .bit = 0x05, - }, + }, /* DLD3 */ { .address = 0x18, .reg = 0x12, .bit = 0x06, - }, + }, /* DLD4 */ { .address = 0x1c, .reg = 0x12, .bit = 0x00, - }, + }, /* ELD1 */ { .address = 0x20, .reg = 0x12, .bit = 0x01, - }, + }, /* ELD2 */ { .address = 0x24, .reg = 0x12, .bit = 0x02, - }, + }, /* ELD3 */ { .address = 0x28, .reg = 0x13, .bit = 0x02, - }, + }, /* FLD1 */ { .address = 0x2c, .reg = 0x13, .bit = 0x03, - }, + }, /* FLD2 */ { .address = 0x30, .reg = 0x13, .bit = 0x04, - }, + }, /* FLD3 */ + { + .address = 0x34, + .reg = 0x10, + .bit = 0x03, + }, /* BUC1 */ { .address = 0x38, .reg = 0x10, - .bit = 0x03, - }, + .bit = 0x06, + }, /* BUC2 */ { .address = 0x3c, .reg = 0x10, - .bit = 0x06, - }, + .bit = 0x05, + }, /* BUC3 */ { .address = 0x40, .reg = 0x10, - .bit = 0x05, - }, + .bit = 0x04, + }, /* BUC4 */ { .address = 0x44, .reg = 0x10, - .bit = 0x04, - }, + .bit = 0x01, + }, /* BUC5 */ { .address = 0x48, .reg = 0x10, - .bit = 0x01, - }, - { - .address = 0x4c, - .reg = 0x10, .bit = 0x00 - }, + }, /* BUC6 */ }; /* TMP0 - TMP5 are the same, all from GPADC */ From 8ece1d83346bcc431090d59a2184276192189cdd Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 30 Apr 2017 22:54:16 +0200 Subject: [PATCH 7/7] ACPI / power: Delay turning off unused power resources after suspend Commit 660b1113e0f3 (ACPI / PM: Fix consistency check for power resources during resume) introduced a check for ACPI power resources which have been turned on by the BIOS during suspend and turns these back off again. This is causing problems on a Dell Venue Pro 11 7130 (i5-4300Y) it causes the following messages to show up in dmesg: [ 131.014605] ACPI: Waking up from system sleep state S3 [ 131.150271] acpi LNXPOWER:07: Turning OFF [ 131.150323] acpi LNXPOWER:06: Turning OFF [ 131.150911] acpi LNXPOWER:00: Turning OFF [ 131.169014] ACPI : EC: interrupt unblocked [ 131.181811] xhci_hcd 0000:00:14.0: System wakeup disabled by ACPI [ 133.535728] pci_raw_set_power_state: 76 callbacks suppressed [ 133.535735] iwlwifi 0000:01:00.0: Refused to change power state, currently in D3 [ 133.597672] PM: noirq resume of devices complete after 2428.891 msecs Followed by a bunch of iwlwifi errors later on and the pcie device dropping from the bus (acpiphp thinks it has been unplugged). Disabling the turning off of unused power resources fixes this. Instead of adding a quirk for this system, this commit fixes this by moving the disabling of unused power resources to later in the resume sequence when the iwlwifi card has been moved out of D3 so the ref_count for its power resource no longer is 0. This new behavior seems to match the intend of the original commit which commit-msg says: "(... which means that no devices are going to need them any time soon) and we should turn them off". This also avoids power resources which we need when bringing devices out of D3 from getting bounced off and then back on again. Signed-off-by: Hans de Goede Signed-off-by: Rafael J. Wysocki --- drivers/acpi/power.c | 10 ++++++++++ drivers/acpi/sleep.c | 1 + drivers/acpi/sleep.h | 1 + 3 files changed, 12 insertions(+) diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 1c2b846c5776..3a6c9b741b23 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -864,6 +864,16 @@ void acpi_resume_power_resources(void) mutex_unlock(&resource->resource_lock); } + + mutex_unlock(&power_resource_list_lock); +} + +void acpi_turn_off_unused_power_resources(void) +{ + struct acpi_power_resource *resource; + + mutex_lock(&power_resource_list_lock); + list_for_each_entry_reverse(resource, &acpi_power_resource_list, list_node) { int result, state; diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index a4327af676fe..097d630ab886 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -474,6 +474,7 @@ static void acpi_pm_start(u32 acpi_state) */ static void acpi_pm_end(void) { + acpi_turn_off_unused_power_resources(); acpi_scan_lock_release(); /* * This is necessary in case acpi_pm_finish() is not called during a diff --git a/drivers/acpi/sleep.h b/drivers/acpi/sleep.h index a9cc34e663f9..a82ff74faf7a 100644 --- a/drivers/acpi/sleep.h +++ b/drivers/acpi/sleep.h @@ -6,6 +6,7 @@ extern struct list_head acpi_wakeup_device_list; extern struct mutex acpi_device_lock; extern void acpi_resume_power_resources(void); +extern void acpi_turn_off_unused_power_resources(void); static inline acpi_status acpi_set_waking_vector(u32 wakeup_address) {