xref: /kernel/linux/linux-6.6/drivers/acpi/x86/utils.c (revision 62306a36)
162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * X86 ACPI Utility Functions
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Based on various non upstream patches to support the CHT Whiskey Cove PMIC:
862306a36Sopenharmony_ci * Copyright (C) 2013-2015 Intel Corporation. All rights reserved.
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#define pr_fmt(fmt) "ACPI: " fmt
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/acpi.h>
1462306a36Sopenharmony_ci#include <linux/dmi.h>
1562306a36Sopenharmony_ci#include <linux/platform_device.h>
1662306a36Sopenharmony_ci#include <asm/cpu_device_id.h>
1762306a36Sopenharmony_ci#include <asm/intel-family.h>
1862306a36Sopenharmony_ci#include "../internal.h"
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci/*
2162306a36Sopenharmony_ci * Some ACPI devices are hidden (status == 0x0) in recent BIOS-es because
2262306a36Sopenharmony_ci * some recent Windows drivers bind to one device but poke at multiple
2362306a36Sopenharmony_ci * devices at the same time, so the others get hidden.
2462306a36Sopenharmony_ci *
2562306a36Sopenharmony_ci * Some BIOS-es (temporarily) hide specific APCI devices to work around Windows
2662306a36Sopenharmony_ci * driver bugs. We use DMI matching to match known cases of this.
2762306a36Sopenharmony_ci *
2862306a36Sopenharmony_ci * Likewise sometimes some not-actually present devices are sometimes
2962306a36Sopenharmony_ci * reported as present, which may cause issues.
3062306a36Sopenharmony_ci *
3162306a36Sopenharmony_ci * We work around this by using the below quirk list to override the status
3262306a36Sopenharmony_ci * reported by the _STA method with a fixed value (ACPI_STA_DEFAULT or 0).
3362306a36Sopenharmony_ci * Note this MUST only be done for devices where this is safe.
3462306a36Sopenharmony_ci *
3562306a36Sopenharmony_ci * This status overriding is limited to specific CPU (SoC) models both to
3662306a36Sopenharmony_ci * avoid potentially causing trouble on other models and because some HIDs
3762306a36Sopenharmony_ci * are re-used on different SoCs for completely different devices.
3862306a36Sopenharmony_ci */
3962306a36Sopenharmony_cistruct override_status_id {
4062306a36Sopenharmony_ci	struct acpi_device_id hid[2];
4162306a36Sopenharmony_ci	struct x86_cpu_id cpu_ids[2];
4262306a36Sopenharmony_ci	struct dmi_system_id dmi_ids[2]; /* Optional */
4362306a36Sopenharmony_ci	const char *uid;
4462306a36Sopenharmony_ci	const char *path;
4562306a36Sopenharmony_ci	unsigned long long status;
4662306a36Sopenharmony_ci};
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci#define ENTRY(status, hid, uid, path, cpu_model, dmi...) {		\
4962306a36Sopenharmony_ci	{ { hid, }, {} },						\
5062306a36Sopenharmony_ci	{ X86_MATCH_INTEL_FAM6_MODEL(cpu_model, NULL), {} },		\
5162306a36Sopenharmony_ci	{ { .matches = dmi }, {} },					\
5262306a36Sopenharmony_ci	uid,								\
5362306a36Sopenharmony_ci	path,								\
5462306a36Sopenharmony_ci	status,								\
5562306a36Sopenharmony_ci}
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci#define PRESENT_ENTRY_HID(hid, uid, cpu_model, dmi...) \
5862306a36Sopenharmony_ci	ENTRY(ACPI_STA_DEFAULT, hid, uid, NULL, cpu_model, dmi)
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci#define NOT_PRESENT_ENTRY_HID(hid, uid, cpu_model, dmi...) \
6162306a36Sopenharmony_ci	ENTRY(0, hid, uid, NULL, cpu_model, dmi)
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci#define PRESENT_ENTRY_PATH(path, cpu_model, dmi...) \
6462306a36Sopenharmony_ci	ENTRY(ACPI_STA_DEFAULT, "", NULL, path, cpu_model, dmi)
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci#define NOT_PRESENT_ENTRY_PATH(path, cpu_model, dmi...) \
6762306a36Sopenharmony_ci	ENTRY(0, "", NULL, path, cpu_model, dmi)
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_cistatic const struct override_status_id override_status_ids[] = {
7062306a36Sopenharmony_ci	/*
7162306a36Sopenharmony_ci	 * Bay / Cherry Trail PWM directly poked by GPU driver in win10,
7262306a36Sopenharmony_ci	 * but Linux uses a separate PWM driver, harmless if not used.
7362306a36Sopenharmony_ci	 */
7462306a36Sopenharmony_ci	PRESENT_ENTRY_HID("80860F09", "1", ATOM_SILVERMONT, {}),
7562306a36Sopenharmony_ci	PRESENT_ENTRY_HID("80862288", "1", ATOM_AIRMONT, {}),
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	/* The Xiaomi Mi Pad 2 uses PWM2 for touchkeys backlight control */
7862306a36Sopenharmony_ci	PRESENT_ENTRY_HID("80862289", "2", ATOM_AIRMONT, {
7962306a36Sopenharmony_ci		DMI_MATCH(DMI_SYS_VENDOR, "Xiaomi Inc"),
8062306a36Sopenharmony_ci		DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"),
8162306a36Sopenharmony_ci	      }),
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	/*
8462306a36Sopenharmony_ci	 * The INT0002 device is necessary to clear wakeup interrupt sources
8562306a36Sopenharmony_ci	 * on Cherry Trail devices, without it we get nobody cared IRQ msgs.
8662306a36Sopenharmony_ci	 */
8762306a36Sopenharmony_ci	PRESENT_ENTRY_HID("INT0002", "1", ATOM_AIRMONT, {}),
8862306a36Sopenharmony_ci	/*
8962306a36Sopenharmony_ci	 * On the Dell Venue 11 Pro 7130 and 7139, the DSDT hides
9062306a36Sopenharmony_ci	 * the touchscreen ACPI device until a certain time
9162306a36Sopenharmony_ci	 * after _SB.PCI0.GFX0.LCD.LCD1._ON gets called has passed
9262306a36Sopenharmony_ci	 * *and* _STA has been called at least 3 times since.
9362306a36Sopenharmony_ci	 */
9462306a36Sopenharmony_ci	PRESENT_ENTRY_HID("SYNA7500", "1", HASWELL_L, {
9562306a36Sopenharmony_ci		DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
9662306a36Sopenharmony_ci		DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7130"),
9762306a36Sopenharmony_ci	      }),
9862306a36Sopenharmony_ci	PRESENT_ENTRY_HID("SYNA7500", "1", HASWELL_L, {
9962306a36Sopenharmony_ci		DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
10062306a36Sopenharmony_ci		DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7139"),
10162306a36Sopenharmony_ci	      }),
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	/*
10462306a36Sopenharmony_ci	 * The GPD win BIOS dated 20170221 has disabled the accelerometer, the
10562306a36Sopenharmony_ci	 * drivers sometimes cause crashes under Windows and this is how the
10662306a36Sopenharmony_ci	 * manufacturer has solved this :|  The DMI match may not seem unique,
10762306a36Sopenharmony_ci	 * but it is. In the 67000+ DMI decode dumps from linux-hardware.org
10862306a36Sopenharmony_ci	 * only 116 have board_vendor set to "AMI Corporation" and of those 116
10962306a36Sopenharmony_ci	 * only the GPD win and pocket entries' board_name is "Default string".
11062306a36Sopenharmony_ci	 *
11162306a36Sopenharmony_ci	 * Unfortunately the GPD pocket also uses these strings and its BIOS
11262306a36Sopenharmony_ci	 * was copy-pasted from the GPD win, so it has a disabled KIOX000A
11362306a36Sopenharmony_ci	 * node which we should not enable, thus we also check the BIOS date.
11462306a36Sopenharmony_ci	 */
11562306a36Sopenharmony_ci	PRESENT_ENTRY_HID("KIOX000A", "1", ATOM_AIRMONT, {
11662306a36Sopenharmony_ci		DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
11762306a36Sopenharmony_ci		DMI_MATCH(DMI_BOARD_NAME, "Default string"),
11862306a36Sopenharmony_ci		DMI_MATCH(DMI_PRODUCT_NAME, "Default string"),
11962306a36Sopenharmony_ci		DMI_MATCH(DMI_BIOS_DATE, "02/21/2017")
12062306a36Sopenharmony_ci	      }),
12162306a36Sopenharmony_ci	PRESENT_ENTRY_HID("KIOX000A", "1", ATOM_AIRMONT, {
12262306a36Sopenharmony_ci		DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
12362306a36Sopenharmony_ci		DMI_MATCH(DMI_BOARD_NAME, "Default string"),
12462306a36Sopenharmony_ci		DMI_MATCH(DMI_PRODUCT_NAME, "Default string"),
12562306a36Sopenharmony_ci		DMI_MATCH(DMI_BIOS_DATE, "03/20/2017")
12662306a36Sopenharmony_ci	      }),
12762306a36Sopenharmony_ci	PRESENT_ENTRY_HID("KIOX000A", "1", ATOM_AIRMONT, {
12862306a36Sopenharmony_ci		DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
12962306a36Sopenharmony_ci		DMI_MATCH(DMI_BOARD_NAME, "Default string"),
13062306a36Sopenharmony_ci		DMI_MATCH(DMI_PRODUCT_NAME, "Default string"),
13162306a36Sopenharmony_ci		DMI_MATCH(DMI_BIOS_DATE, "05/25/2017")
13262306a36Sopenharmony_ci	      }),
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	/*
13562306a36Sopenharmony_ci	 * The GPD win/pocket have a PCI wifi card, but its DSDT has the SDIO
13662306a36Sopenharmony_ci	 * mmc controller enabled and that has a child-device which _PS3
13762306a36Sopenharmony_ci	 * method sets a GPIO causing the PCI wifi card to turn off.
13862306a36Sopenharmony_ci	 * See above remark about uniqueness of the DMI match.
13962306a36Sopenharmony_ci	 */
14062306a36Sopenharmony_ci	NOT_PRESENT_ENTRY_PATH("\\_SB_.PCI0.SDHB.BRC1", ATOM_AIRMONT, {
14162306a36Sopenharmony_ci		DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
14262306a36Sopenharmony_ci		DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"),
14362306a36Sopenharmony_ci		DMI_EXACT_MATCH(DMI_BOARD_SERIAL, "Default string"),
14462306a36Sopenharmony_ci		DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"),
14562306a36Sopenharmony_ci	      }),
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	/*
14862306a36Sopenharmony_ci	 * The LSM303D on the Lenovo Yoga Tablet 2 series is present
14962306a36Sopenharmony_ci	 * as both ACCL0001 and MAGN0001. As we can only ever register an
15062306a36Sopenharmony_ci	 * i2c client for one of them, ignore MAGN0001.
15162306a36Sopenharmony_ci	 */
15262306a36Sopenharmony_ci	NOT_PRESENT_ENTRY_HID("MAGN0001", "1", ATOM_SILVERMONT, {
15362306a36Sopenharmony_ci		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
15462306a36Sopenharmony_ci		DMI_MATCH(DMI_PRODUCT_FAMILY, "YOGATablet2"),
15562306a36Sopenharmony_ci	      }),
15662306a36Sopenharmony_ci};
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_cibool acpi_device_override_status(struct acpi_device *adev, unsigned long long *status)
15962306a36Sopenharmony_ci{
16062306a36Sopenharmony_ci	bool ret = false;
16162306a36Sopenharmony_ci	unsigned int i;
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(override_status_ids); i++) {
16462306a36Sopenharmony_ci		if (!x86_match_cpu(override_status_ids[i].cpu_ids))
16562306a36Sopenharmony_ci			continue;
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci		if (override_status_ids[i].dmi_ids[0].matches[0].slot &&
16862306a36Sopenharmony_ci		    !dmi_check_system(override_status_ids[i].dmi_ids))
16962306a36Sopenharmony_ci			continue;
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci		if (override_status_ids[i].path) {
17262306a36Sopenharmony_ci			struct acpi_buffer path = { ACPI_ALLOCATE_BUFFER, NULL };
17362306a36Sopenharmony_ci			bool match;
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci			if (acpi_get_name(adev->handle, ACPI_FULL_PATHNAME, &path))
17662306a36Sopenharmony_ci				continue;
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci			match = strcmp((char *)path.pointer, override_status_ids[i].path) == 0;
17962306a36Sopenharmony_ci			kfree(path.pointer);
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci			if (!match)
18262306a36Sopenharmony_ci				continue;
18362306a36Sopenharmony_ci		} else {
18462306a36Sopenharmony_ci			if (acpi_match_device_ids(adev, override_status_ids[i].hid))
18562306a36Sopenharmony_ci				continue;
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci			if (!adev->pnp.unique_id ||
18862306a36Sopenharmony_ci			    strcmp(adev->pnp.unique_id, override_status_ids[i].uid))
18962306a36Sopenharmony_ci				continue;
19062306a36Sopenharmony_ci		}
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci		*status = override_status_ids[i].status;
19362306a36Sopenharmony_ci		ret = true;
19462306a36Sopenharmony_ci		break;
19562306a36Sopenharmony_ci	}
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	return ret;
19862306a36Sopenharmony_ci}
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci/*
20162306a36Sopenharmony_ci * AMD systems from Renoir and Lucienne *require* that the NVME controller
20262306a36Sopenharmony_ci * is put into D3 over a Modern Standby / suspend-to-idle cycle.
20362306a36Sopenharmony_ci *
20462306a36Sopenharmony_ci * This is "typically" accomplished using the `StorageD3Enable`
20562306a36Sopenharmony_ci * property in the _DSD that is checked via the `acpi_storage_d3` function
20662306a36Sopenharmony_ci * but this property was introduced after many of these systems launched
20762306a36Sopenharmony_ci * and most OEM systems don't have it in their BIOS.
20862306a36Sopenharmony_ci *
20962306a36Sopenharmony_ci * The Microsoft documentation for StorageD3Enable mentioned that Windows has
21062306a36Sopenharmony_ci * a hardcoded allowlist for D3 support, which was used for these platforms.
21162306a36Sopenharmony_ci *
21262306a36Sopenharmony_ci * This allows quirking on Linux in a similar fashion.
21362306a36Sopenharmony_ci *
21462306a36Sopenharmony_ci * Cezanne systems shouldn't *normally* need this as the BIOS includes
21562306a36Sopenharmony_ci * StorageD3Enable.  But for two reasons we have added it.
21662306a36Sopenharmony_ci * 1) The BIOS on a number of Dell systems have ambiguity
21762306a36Sopenharmony_ci *    between the same value used for _ADR on ACPI nodes GPP1.DEV0 and GPP1.NVME.
21862306a36Sopenharmony_ci *    GPP1.NVME is needed to get StorageD3Enable node set properly.
21962306a36Sopenharmony_ci *    https://bugzilla.kernel.org/show_bug.cgi?id=216440
22062306a36Sopenharmony_ci *    https://bugzilla.kernel.org/show_bug.cgi?id=216773
22162306a36Sopenharmony_ci *    https://bugzilla.kernel.org/show_bug.cgi?id=217003
22262306a36Sopenharmony_ci * 2) On at least one HP system StorageD3Enable is missing on the second NVME
22362306a36Sopenharmony_ci      disk in the system.
22462306a36Sopenharmony_ci */
22562306a36Sopenharmony_cistatic const struct x86_cpu_id storage_d3_cpu_ids[] = {
22662306a36Sopenharmony_ci	X86_MATCH_VENDOR_FAM_MODEL(AMD, 23, 24, NULL),  /* Picasso */
22762306a36Sopenharmony_ci	X86_MATCH_VENDOR_FAM_MODEL(AMD, 23, 96, NULL),	/* Renoir */
22862306a36Sopenharmony_ci	X86_MATCH_VENDOR_FAM_MODEL(AMD, 23, 104, NULL),	/* Lucienne */
22962306a36Sopenharmony_ci	X86_MATCH_VENDOR_FAM_MODEL(AMD, 25, 80, NULL),	/* Cezanne */
23062306a36Sopenharmony_ci	{}
23162306a36Sopenharmony_ci};
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_cibool force_storage_d3(void)
23462306a36Sopenharmony_ci{
23562306a36Sopenharmony_ci	return x86_match_cpu(storage_d3_cpu_ids);
23662306a36Sopenharmony_ci}
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci/*
23962306a36Sopenharmony_ci * x86 ACPI boards which ship with only Android as their factory image usually
24062306a36Sopenharmony_ci * declare a whole bunch of bogus I2C devices in their ACPI tables and sometimes
24162306a36Sopenharmony_ci * there are issues with serdev devices on these boards too, e.g. the resource
24262306a36Sopenharmony_ci * points to the wrong serdev_controller.
24362306a36Sopenharmony_ci *
24462306a36Sopenharmony_ci * Instantiating I2C / serdev devs for these bogus devs causes various issues,
24562306a36Sopenharmony_ci * e.g. GPIO/IRQ resource conflicts because sometimes drivers do bind to them.
24662306a36Sopenharmony_ci * The Android x86 kernel fork shipped on these devices has some special code
24762306a36Sopenharmony_ci * to remove the bogus I2C clients (and AFAICT serdevs are ignored completely).
24862306a36Sopenharmony_ci *
24962306a36Sopenharmony_ci * The acpi_quirk_skip_*_enumeration() functions below are used by the I2C or
25062306a36Sopenharmony_ci * serdev code to skip instantiating any I2C or serdev devs on broken boards.
25162306a36Sopenharmony_ci *
25262306a36Sopenharmony_ci * In case of I2C an exception is made for HIDs on the i2c_acpi_known_good_ids
25362306a36Sopenharmony_ci * list. These are known to always be correct (and in case of the audio-codecs
25462306a36Sopenharmony_ci * the drivers heavily rely on the codec being enumerated through ACPI).
25562306a36Sopenharmony_ci *
25662306a36Sopenharmony_ci * Note these boards typically do actually have I2C and serdev devices,
25762306a36Sopenharmony_ci * just different ones then the ones described in their DSDT. The devices
25862306a36Sopenharmony_ci * which are actually present are manually instantiated by the
25962306a36Sopenharmony_ci * drivers/platform/x86/x86-android-tablets.c kernel module.
26062306a36Sopenharmony_ci */
26162306a36Sopenharmony_ci#define ACPI_QUIRK_SKIP_I2C_CLIENTS				BIT(0)
26262306a36Sopenharmony_ci#define ACPI_QUIRK_UART1_SKIP					BIT(1)
26362306a36Sopenharmony_ci#define ACPI_QUIRK_UART1_TTY_UART2_SKIP				BIT(2)
26462306a36Sopenharmony_ci#define ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY			BIT(3)
26562306a36Sopenharmony_ci#define ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY			BIT(4)
26662306a36Sopenharmony_ci#define ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS			BIT(5)
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_cistatic const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
26962306a36Sopenharmony_ci	/*
27062306a36Sopenharmony_ci	 * 1. Devices with only the skip / don't-skip AC and battery quirks,
27162306a36Sopenharmony_ci	 *    sorted alphabetically.
27262306a36Sopenharmony_ci	 */
27362306a36Sopenharmony_ci	{
27462306a36Sopenharmony_ci		/* ECS EF20EA, AXP288 PMIC but uses separate fuel-gauge */
27562306a36Sopenharmony_ci		.matches = {
27662306a36Sopenharmony_ci			DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"),
27762306a36Sopenharmony_ci		},
27862306a36Sopenharmony_ci		.driver_data = (void *)ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY
27962306a36Sopenharmony_ci	},
28062306a36Sopenharmony_ci	{
28162306a36Sopenharmony_ci		/* Lenovo Ideapad Miix 320, AXP288 PMIC, separate fuel-gauge */
28262306a36Sopenharmony_ci		.matches = {
28362306a36Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
28462306a36Sopenharmony_ci			DMI_MATCH(DMI_PRODUCT_NAME, "80XF"),
28562306a36Sopenharmony_ci			DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"),
28662306a36Sopenharmony_ci		},
28762306a36Sopenharmony_ci		.driver_data = (void *)ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY
28862306a36Sopenharmony_ci	},
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	/*
29162306a36Sopenharmony_ci	 * 2. Devices which also have the skip i2c/serdev quirks and which
29262306a36Sopenharmony_ci	 *    need the x86-android-tablets module to properly work.
29362306a36Sopenharmony_ci	 */
29462306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS)
29562306a36Sopenharmony_ci	{
29662306a36Sopenharmony_ci		/* Acer Iconia One 7 B1-750 */
29762306a36Sopenharmony_ci		.matches = {
29862306a36Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
29962306a36Sopenharmony_ci			DMI_MATCH(DMI_PRODUCT_NAME, "VESPA2"),
30062306a36Sopenharmony_ci		},
30162306a36Sopenharmony_ci		.driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
30262306a36Sopenharmony_ci					ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY |
30362306a36Sopenharmony_ci					ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS),
30462306a36Sopenharmony_ci	},
30562306a36Sopenharmony_ci	{
30662306a36Sopenharmony_ci		.matches = {
30762306a36Sopenharmony_ci			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
30862306a36Sopenharmony_ci			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ME176C"),
30962306a36Sopenharmony_ci		},
31062306a36Sopenharmony_ci		.driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
31162306a36Sopenharmony_ci					ACPI_QUIRK_UART1_TTY_UART2_SKIP |
31262306a36Sopenharmony_ci					ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY |
31362306a36Sopenharmony_ci					ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS),
31462306a36Sopenharmony_ci	},
31562306a36Sopenharmony_ci	{
31662306a36Sopenharmony_ci		/* Lenovo Yoga Book X90F/L */
31762306a36Sopenharmony_ci		.matches = {
31862306a36Sopenharmony_ci			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
31962306a36Sopenharmony_ci			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
32062306a36Sopenharmony_ci			DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "YETI-11"),
32162306a36Sopenharmony_ci		},
32262306a36Sopenharmony_ci		.driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
32362306a36Sopenharmony_ci					ACPI_QUIRK_UART1_SKIP |
32462306a36Sopenharmony_ci					ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY |
32562306a36Sopenharmony_ci					ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS),
32662306a36Sopenharmony_ci	},
32762306a36Sopenharmony_ci	{
32862306a36Sopenharmony_ci		.matches = {
32962306a36Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
33062306a36Sopenharmony_ci			DMI_MATCH(DMI_PRODUCT_NAME, "TF103C"),
33162306a36Sopenharmony_ci		},
33262306a36Sopenharmony_ci		.driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
33362306a36Sopenharmony_ci					ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY |
33462306a36Sopenharmony_ci					ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS),
33562306a36Sopenharmony_ci	},
33662306a36Sopenharmony_ci	{
33762306a36Sopenharmony_ci		/* Lenovo Yoga Tablet 2 1050F/L */
33862306a36Sopenharmony_ci		.matches = {
33962306a36Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corp."),
34062306a36Sopenharmony_ci			DMI_MATCH(DMI_PRODUCT_NAME, "VALLEYVIEW C0 PLATFORM"),
34162306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "BYT-T FFD8"),
34262306a36Sopenharmony_ci			/* Partial match on beginning of BIOS version */
34362306a36Sopenharmony_ci			DMI_MATCH(DMI_BIOS_VERSION, "BLADE_21"),
34462306a36Sopenharmony_ci		},
34562306a36Sopenharmony_ci		.driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
34662306a36Sopenharmony_ci					ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
34762306a36Sopenharmony_ci	},
34862306a36Sopenharmony_ci	{
34962306a36Sopenharmony_ci		/* Lenovo Yoga Tab 3 Pro X90F */
35062306a36Sopenharmony_ci		.matches = {
35162306a36Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
35262306a36Sopenharmony_ci			DMI_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
35362306a36Sopenharmony_ci			DMI_MATCH(DMI_PRODUCT_VERSION, "Blade3-10A-001"),
35462306a36Sopenharmony_ci		},
35562306a36Sopenharmony_ci		.driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
35662306a36Sopenharmony_ci					ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
35762306a36Sopenharmony_ci	},
35862306a36Sopenharmony_ci	{
35962306a36Sopenharmony_ci		/* Medion Lifetab S10346 */
36062306a36Sopenharmony_ci		.matches = {
36162306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
36262306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
36362306a36Sopenharmony_ci			/* Way too generic, also match on BIOS data */
36462306a36Sopenharmony_ci			DMI_MATCH(DMI_BIOS_DATE, "10/22/2015"),
36562306a36Sopenharmony_ci		},
36662306a36Sopenharmony_ci		.driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
36762306a36Sopenharmony_ci					ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
36862306a36Sopenharmony_ci	},
36962306a36Sopenharmony_ci	{
37062306a36Sopenharmony_ci		/* Nextbook Ares 8 (BYT version)*/
37162306a36Sopenharmony_ci		.matches = {
37262306a36Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
37362306a36Sopenharmony_ci			DMI_MATCH(DMI_PRODUCT_NAME, "M890BAP"),
37462306a36Sopenharmony_ci		},
37562306a36Sopenharmony_ci		.driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
37662306a36Sopenharmony_ci					ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY |
37762306a36Sopenharmony_ci					ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS),
37862306a36Sopenharmony_ci	},
37962306a36Sopenharmony_ci	{
38062306a36Sopenharmony_ci		/* Nextbook Ares 8A (CHT version)*/
38162306a36Sopenharmony_ci		.matches = {
38262306a36Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
38362306a36Sopenharmony_ci			DMI_MATCH(DMI_PRODUCT_NAME, "CherryTrail"),
38462306a36Sopenharmony_ci			DMI_MATCH(DMI_BIOS_VERSION, "M882"),
38562306a36Sopenharmony_ci		},
38662306a36Sopenharmony_ci		.driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
38762306a36Sopenharmony_ci					ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
38862306a36Sopenharmony_ci	},
38962306a36Sopenharmony_ci	{
39062306a36Sopenharmony_ci		/* Whitelabel (sold as various brands) TM800A550L */
39162306a36Sopenharmony_ci		.matches = {
39262306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
39362306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
39462306a36Sopenharmony_ci			/* Above strings are too generic, also match on BIOS version */
39562306a36Sopenharmony_ci			DMI_MATCH(DMI_BIOS_VERSION, "ZY-8-BI-PX4S70VTR400-X423B-005-D"),
39662306a36Sopenharmony_ci		},
39762306a36Sopenharmony_ci		.driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
39862306a36Sopenharmony_ci					ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
39962306a36Sopenharmony_ci	},
40062306a36Sopenharmony_ci#endif
40162306a36Sopenharmony_ci	{}
40262306a36Sopenharmony_ci};
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS)
40562306a36Sopenharmony_cistatic const struct acpi_device_id i2c_acpi_known_good_ids[] = {
40662306a36Sopenharmony_ci	{ "10EC5640", 0 }, /* RealTek ALC5640 audio codec */
40762306a36Sopenharmony_ci	{ "10EC5651", 0 }, /* RealTek ALC5651 audio codec */
40862306a36Sopenharmony_ci	{ "INT33F4", 0 },  /* X-Powers AXP288 PMIC */
40962306a36Sopenharmony_ci	{ "INT33FD", 0 },  /* Intel Crystal Cove PMIC */
41062306a36Sopenharmony_ci	{ "INT34D3", 0 },  /* Intel Whiskey Cove PMIC */
41162306a36Sopenharmony_ci	{ "NPCE69A", 0 },  /* Asus Transformer keyboard dock */
41262306a36Sopenharmony_ci	{}
41362306a36Sopenharmony_ci};
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_cibool acpi_quirk_skip_i2c_client_enumeration(struct acpi_device *adev)
41662306a36Sopenharmony_ci{
41762306a36Sopenharmony_ci	const struct dmi_system_id *dmi_id;
41862306a36Sopenharmony_ci	long quirks;
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci	dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids);
42162306a36Sopenharmony_ci	if (!dmi_id)
42262306a36Sopenharmony_ci		return false;
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci	quirks = (unsigned long)dmi_id->driver_data;
42562306a36Sopenharmony_ci	if (!(quirks & ACPI_QUIRK_SKIP_I2C_CLIENTS))
42662306a36Sopenharmony_ci		return false;
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci	return acpi_match_device_ids(adev, i2c_acpi_known_good_ids);
42962306a36Sopenharmony_ci}
43062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(acpi_quirk_skip_i2c_client_enumeration);
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ciint acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip)
43362306a36Sopenharmony_ci{
43462306a36Sopenharmony_ci	struct acpi_device *adev = ACPI_COMPANION(controller_parent);
43562306a36Sopenharmony_ci	const struct dmi_system_id *dmi_id;
43662306a36Sopenharmony_ci	long quirks = 0;
43762306a36Sopenharmony_ci	u64 uid;
43862306a36Sopenharmony_ci	int ret;
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci	*skip = false;
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_ci	ret = acpi_dev_uid_to_integer(adev, &uid);
44362306a36Sopenharmony_ci	if (ret)
44462306a36Sopenharmony_ci		return 0;
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ci	/* to not match on PNP enumerated debug UARTs */
44762306a36Sopenharmony_ci	if (!dev_is_platform(controller_parent))
44862306a36Sopenharmony_ci		return 0;
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci	dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids);
45162306a36Sopenharmony_ci	if (dmi_id)
45262306a36Sopenharmony_ci		quirks = (unsigned long)dmi_id->driver_data;
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	if ((quirks & ACPI_QUIRK_UART1_SKIP) && uid == 1)
45562306a36Sopenharmony_ci		*skip = true;
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ci	if (quirks & ACPI_QUIRK_UART1_TTY_UART2_SKIP) {
45862306a36Sopenharmony_ci		if (uid == 1)
45962306a36Sopenharmony_ci			return -ENODEV; /* Create tty cdev instead of serdev */
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci		if (uid == 2)
46262306a36Sopenharmony_ci			*skip = true;
46362306a36Sopenharmony_ci	}
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_ci	return 0;
46662306a36Sopenharmony_ci}
46762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(acpi_quirk_skip_serdev_enumeration);
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_cibool acpi_quirk_skip_gpio_event_handlers(void)
47062306a36Sopenharmony_ci{
47162306a36Sopenharmony_ci	const struct dmi_system_id *dmi_id;
47262306a36Sopenharmony_ci	long quirks;
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci	dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids);
47562306a36Sopenharmony_ci	if (!dmi_id)
47662306a36Sopenharmony_ci		return false;
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci	quirks = (unsigned long)dmi_id->driver_data;
47962306a36Sopenharmony_ci	return (quirks & ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS);
48062306a36Sopenharmony_ci}
48162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(acpi_quirk_skip_gpio_event_handlers);
48262306a36Sopenharmony_ci#endif
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci/* Lists of PMIC ACPI HIDs with an (often better) native charger driver */
48562306a36Sopenharmony_cistatic const struct {
48662306a36Sopenharmony_ci	const char *hid;
48762306a36Sopenharmony_ci	int hrv;
48862306a36Sopenharmony_ci} acpi_skip_ac_and_battery_pmic_ids[] = {
48962306a36Sopenharmony_ci	{ "INT33F4", -1 }, /* X-Powers AXP288 PMIC */
49062306a36Sopenharmony_ci	{ "INT34D3",  3 }, /* Intel Cherrytrail Whiskey Cove PMIC */
49162306a36Sopenharmony_ci};
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_cibool acpi_quirk_skip_acpi_ac_and_battery(void)
49462306a36Sopenharmony_ci{
49562306a36Sopenharmony_ci	const struct dmi_system_id *dmi_id;
49662306a36Sopenharmony_ci	long quirks = 0;
49762306a36Sopenharmony_ci	int i;
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci	dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids);
50062306a36Sopenharmony_ci	if (dmi_id)
50162306a36Sopenharmony_ci		quirks = (unsigned long)dmi_id->driver_data;
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_ci	if (quirks & ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY)
50462306a36Sopenharmony_ci		return true;
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_ci	if (quirks & ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY)
50762306a36Sopenharmony_ci		return false;
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(acpi_skip_ac_and_battery_pmic_ids); i++) {
51062306a36Sopenharmony_ci		if (acpi_dev_present(acpi_skip_ac_and_battery_pmic_ids[i].hid, "1",
51162306a36Sopenharmony_ci				     acpi_skip_ac_and_battery_pmic_ids[i].hrv)) {
51262306a36Sopenharmony_ci			pr_info_once("found native %s PMIC, skipping ACPI AC and battery devices\n",
51362306a36Sopenharmony_ci				     acpi_skip_ac_and_battery_pmic_ids[i].hid);
51462306a36Sopenharmony_ci			return true;
51562306a36Sopenharmony_ci		}
51662306a36Sopenharmony_ci	}
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ci	return false;
51962306a36Sopenharmony_ci}
52062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(acpi_quirk_skip_acpi_ac_and_battery);
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci/* This section provides a workaround for a specific x86 system
52362306a36Sopenharmony_ci * which requires disabling of mwait to work correctly.
52462306a36Sopenharmony_ci */
52562306a36Sopenharmony_cistatic int __init acpi_proc_quirk_set_no_mwait(const struct dmi_system_id *id)
52662306a36Sopenharmony_ci{
52762306a36Sopenharmony_ci	pr_notice("%s detected - disabling mwait for CPU C-states\n",
52862306a36Sopenharmony_ci		  id->ident);
52962306a36Sopenharmony_ci	boot_option_idle_override = IDLE_NOMWAIT;
53062306a36Sopenharmony_ci	return 0;
53162306a36Sopenharmony_ci}
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_cistatic const struct dmi_system_id acpi_proc_quirk_mwait_dmi_table[] __initconst = {
53462306a36Sopenharmony_ci	{
53562306a36Sopenharmony_ci		.callback = acpi_proc_quirk_set_no_mwait,
53662306a36Sopenharmony_ci		.ident = "Extensa 5220",
53762306a36Sopenharmony_ci		.matches =  {
53862306a36Sopenharmony_ci			DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
53962306a36Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
54062306a36Sopenharmony_ci			DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
54162306a36Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "Columbia"),
54262306a36Sopenharmony_ci		},
54362306a36Sopenharmony_ci		.driver_data = NULL,
54462306a36Sopenharmony_ci	},
54562306a36Sopenharmony_ci	{}
54662306a36Sopenharmony_ci};
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_civoid __init acpi_proc_quirk_mwait_check(void)
54962306a36Sopenharmony_ci{
55062306a36Sopenharmony_ci	/*
55162306a36Sopenharmony_ci	 * Check whether the system is DMI table. If yes, OSPM
55262306a36Sopenharmony_ci	 * should not use mwait for CPU-states.
55362306a36Sopenharmony_ci	 */
55462306a36Sopenharmony_ci	dmi_check_system(acpi_proc_quirk_mwait_dmi_table);
55562306a36Sopenharmony_ci}
556