// SPDX-License-Identifier: GPL-2.0-only /* * X86 ACPI Utility Functions * * Copyright (C) 2017 Hans de Goede <[email protected]> * * Based on various non upstream patches to support the CHT Whiskey Cove PMIC: * Copyright (C) 2013-2015 Intel Corporation. All rights reserved. */ #define pr_fmt(fmt) … #include <linux/acpi.h> #include <linux/dmi.h> #include <linux/platform_device.h> #include <asm/cpu_device_id.h> #include <asm/intel-family.h> #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. * * Some BIOS-es (temporarily) hide specific APCI devices to work around Windows * driver bugs. We use DMI matching to match known cases of this. * * Likewise sometimes some not-actually present devices are sometimes * reported as present, which may cause issues. * * We work around this by using the below quirk list to override the status * reported by the _STA method with a fixed value (ACPI_STA_DEFAULT or 0). * Note this MUST only be done for devices where this is safe. * * This status overriding 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 override_status_id { … }; #define ENTRY(status, hid, uid, path, cpu_vfm, dmi...) … #define PRESENT_ENTRY_HID(hid, uid, cpu_vfm, dmi...) … #define NOT_PRESENT_ENTRY_HID(hid, uid, cpu_vfm, dmi...) … #define PRESENT_ENTRY_PATH(path, cpu_vfm, dmi...) … #define NOT_PRESENT_ENTRY_PATH(path, cpu_vfm, dmi...) … static const struct override_status_id override_status_ids[] = …; bool acpi_device_override_status(struct acpi_device *adev, unsigned long long *status) { … } /* * AMD systems from Renoir onwards *require* that the NVME controller * is put into D3 over a Modern Standby / suspend-to-idle cycle. * * This is "typically" accomplished using the `StorageD3Enable` * property in the _DSD that is checked via the `acpi_storage_d3` function * but some OEM systems still don't have it in their BIOS. * * The Microsoft documentation for StorageD3Enable mentioned that Windows has * a hardcoded allowlist for D3 support as well as a registry key to override * the BIOS, which has been used for these cases. * * This allows quirking on Linux in a similar fashion. * * Cezanne systems shouldn't *normally* need this as the BIOS includes * StorageD3Enable. But for two reasons we have added it. * 1) The BIOS on a number of Dell systems have ambiguity * between the same value used for _ADR on ACPI nodes GPP1.DEV0 and GPP1.NVME. * GPP1.NVME is needed to get StorageD3Enable node set properly. * https://bugzilla.kernel.org/show_bug.cgi?id=216440 * https://bugzilla.kernel.org/show_bug.cgi?id=216773 * https://bugzilla.kernel.org/show_bug.cgi?id=217003 * 2) On at least one HP system StorageD3Enable is missing on the second NVME * disk in the system. * 3) On at least one HP Rembrandt system StorageD3Enable is missing on the only * NVME device. */ bool force_storage_d3(void) { … } /* * x86 ACPI boards which ship with only Android as their factory image usually * declare a whole bunch of bogus I2C devices in their ACPI tables and sometimes * there are issues with serdev devices on these boards too, e.g. the resource * points to the wrong serdev_controller. * * Instantiating I2C / serdev devs for these bogus devs causes various issues, * e.g. GPIO/IRQ resource conflicts because sometimes drivers do bind to them. * The Android x86 kernel fork shipped on these devices has some special code * to remove the bogus I2C clients (and AFAICT serdevs are ignored completely). * * The acpi_quirk_skip_*_enumeration() functions below are used by the I2C or * serdev code to skip instantiating any I2C or serdev devs on broken boards. * * In case of I2C an exception is made for HIDs on the i2c_acpi_known_good_ids * list. These are known to always be correct (and in case of the audio-codecs * the drivers heavily rely on the codec being enumerated through ACPI). * * Note these boards typically do actually have I2C and serdev devices, * just different ones then the ones described in their DSDT. The devices * which are actually present are manually instantiated by the * drivers/platform/x86/x86-android-tablets.c kernel module. */ #define ACPI_QUIRK_SKIP_I2C_CLIENTS … #define ACPI_QUIRK_UART1_SKIP … #define ACPI_QUIRK_UART1_TTY_UART2_SKIP … #define ACPI_QUIRK_PNP_UART1_SKIP … #define ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY … #define ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY … #define ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS … static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = …; #if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS) static const struct acpi_device_id i2c_acpi_known_good_ids[] = …; bool acpi_quirk_skip_i2c_client_enumeration(struct acpi_device *adev) { … } EXPORT_SYMBOL_GPL(…); static int acpi_dmi_skip_serdev_enumeration(struct device *controller_parent, bool *skip) { … } bool acpi_quirk_skip_gpio_event_handlers(void) { … } EXPORT_SYMBOL_GPL(…); #else static int acpi_dmi_skip_serdev_enumeration(struct device *controller_parent, bool *skip) { return 0; } #endif int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip) { … } EXPORT_SYMBOL_GPL(…); /* Lists of PMIC ACPI HIDs with an (often better) native charger driver */ static const struct { … } acpi_skip_ac_and_battery_pmic_ids[] = …; bool acpi_quirk_skip_acpi_ac_and_battery(void) { … } EXPORT_SYMBOL_GPL(…); /* This section provides a workaround for a specific x86 system * which requires disabling of mwait to work correctly. */ static int __init acpi_proc_quirk_set_no_mwait(const struct dmi_system_id *id) { … } static const struct dmi_system_id acpi_proc_quirk_mwait_dmi_table[] __initconst = …; void __init acpi_proc_quirk_mwait_check(void) { … }