summaryrefslogtreecommitdiff
path: root/drivers/acpi/x86/utils.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-01-10 20:26:56 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2022-01-10 20:26:56 -0800
commitbca21755b9fc00dbe371994b53389eb5d70b8e72 (patch)
tree400369d681f31251007b48d43e4682c68d08769f /drivers/acpi/x86/utils.c
parent63045bfd3c8dbe9c8bee7e33291202725154cb2c (diff)
parent70df8e1bdc941431af2370270f5140291dcbb282 (diff)
Merge tag 'acpi-5.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull ACPI updates from Rafael Wysocki: "These are usual ACPICA code updates (although there are more of them than in the last few releases), a noticeable EC driver update (which mostly consists of cleanups, though), the device enumeration quirks handling rework from Hans, some updates eliminating unnecessary CPU cache flushing in some places (processor idle and system-wide PM code) and a bunch of assorted cleanups and fixes. Specifics: - Update ACPICA code in the kernel to the 20211217 upstream release including the following changes: - iASL/Disassembler: Additional support for NHLT table (Bob Moore). - Change a return_ACPI_STATUS (AE_BAD_PARAMETER) (Bob Moore). - Fix a couple of warnings under MSVC (Bob Moore). - iASL: Add TDEL table to both compiler/disassembler (Bob Moore). - iASL/NHLT table: "Specific Data" field support (Bob Moore). - Use original data_table_region pointer for accesses (Jessica Clarke). - Use original pointer for virtual origin tables (Jessica Clarke). - Macros: Remove ACPI_PHYSADDR_TO_PTR (Jessica Clarke). - Avoid subobject buffer overflow when validating RSDP signature (Jessica Clarke). - iASL: Add suppport for AGDI table (Ilkka Koskinen). - Hardware: Do not flush CPU cache when entering S4 and S5 (Kirill A. Shutemov). - Expand the ACPI_ACCESS_ definitions (Mark Langsdorf). - Utilities: Avoid deleting the same object twice in a row (Rafael Wysocki). - Executer: Fix REFCLASS_REFOF case in acpi_ex_opcode_1A_0T_1R() (Rafael Wysocki). - Fix AEST Processor generic resource substructure data field byte length (Shuuichirou Ishii). - Fix wrong interpretation of PCC address (Sudeep Holla). - Add support for PCC Opregion special context data (Sudeep Holla). - Implement OperationRegion handler for PCC Type 3 subtype (Sudeep Holla). - Introduce acpi_fetch_acpi_dev() as a replacement for acpi_bus_get_device() and use it in the ACPI subsystem (Rafael Wysocki). - Avoid using _CID for device enumaration if _HID is missing or invalid (Rafael Wysocki). - Rework quirk handling during ACPI device enumeration and add some new quirks for known broken platforms (Hans de Goede). - Avoid unnecessary or redundant CPU cache flushing during system PM transitions (Kirill A. Shutemov). - Add PM debug messages related to power resources (Rafael Wysocki). - Fix kernel-doc comment in the PCI host bridge ACPI driver (Yang Li). - Rework flushing of EC work while suspended to idle and clean up the handling of events in the ACPI EC driver (Rafael Wysocki). - Prohibit ec_sys module parameter write_support from being used when the system is locked down (Hans de Goede). - Make the ACPI processor thermal driver use cpufreq_cpu_get() to check for presence of cpufreq policy (Manfred Spraul). - Avoid unnecessary CPU cache flushing in the ACPI processor idle driver (Kirill A. Shutemov). - Replace kernel.h with the necessary inclusions in the ACPI processor driver (Andy Shevchenko). - Use swap() instead of open coding it in the ACPI processor idle driver (Guo Zhengkui). - Fix the handling of defective LPAT in the ACPI xpower PMIC driver and clean up some definitions of PMIC data structures (Hans de Goede). - Fix outdated comment in the ACPI DPTF driver (Sumeet Pawnikar). - Add AEST to the list of known ACPI table signatures (Shuuichirou Ishii). - Make ACPI NUMA code take hotpluggable memblocks into account when CONFIG_MEMORY_HOTPLUG is not set (Vitaly Kuznetsov). - Use default_groups in kobj_type in the ACPI sysfs code (Greg Kroah-Hartman). - Rearrange _CPC structure documentation (Andy Shevchenko). - Drop an always true check from the ACPI thermal driver (Adam Borowski). - Add new "not charging" quirk for Lenovo ThinkPads to the ACPI battery driver (Thomas Weißschuh)" * tag 'acpi-5.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (64 commits) ACPI: PCC: Implement OperationRegion handler for the PCC Type 3 subtype ACPI / x86: Skip AC and battery devices on x86 Android tablets with broken DSDTs ACPI / x86: Introduce an acpi_quirk_skip_acpi_ac_and_battery() helper ACPI: processor: thermal: avoid cpufreq_get_policy() serdev: Do not instantiate serdevs on boards with known bogus DSDT entries i2c: acpi: Do not instantiate I2C-clients on boards with known bogus DSDT entries ACPI / x86: Add acpi_quirk_skip_[i2c_client|serdev]_enumeration() helpers ACPI: scan: Create platform device for BCM4752 and LNV4752 ACPI nodes PCI/ACPI: Fix acpi_pci_osc_control_set() kernel-doc comment ACPI: battery: Add the ThinkPad "Not Charging" quirk ACPI: sysfs: use default_groups in kobj_type ACPICA: Update version to 20211217 ACPICA: iASL/NHLT table: "Specific Data" field support ACPICA: iASL: Add suppport for AGDI table ACPICA: iASL: Add TDEL table to both compiler/disassembler ACPICA: Fixed a couple of warnings under MSVC ACPICA: Change a return_ACPI_STATUS (AE_BAD_PARAMETER) ACPICA: Hardware: Do not flush CPU cache when entering S4 and S5 ACPICA: Add support for PCC Opregion special context data ACPICA: Fix wrong interpretation of PCC address ...
Diffstat (limited to 'drivers/acpi/x86/utils.c')
-rw-r--r--drivers/acpi/x86/utils.c305
1 files changed, 268 insertions, 37 deletions
diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c
index f22f23933063..ffdeed5334d6 100644
--- a/drivers/acpi/x86/utils.c
+++ b/drivers/acpi/x86/utils.c
@@ -8,8 +8,11 @@
* Copyright (C) 2013-2015 Intel Corporation. All rights reserved.
*/
+#define pr_fmt(fmt) "ACPI: " 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"
@@ -22,58 +25,77 @@
* Some BIOS-es (temporarily) hide specific APCI devices to work around Windows
* driver bugs. We use DMI matching to match known cases of this.
*
- * 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.
+ * 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 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.
+ * 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 always_present_id {
+struct override_status_id {
struct acpi_device_id hid[2];
struct x86_cpu_id cpu_ids[2];
struct dmi_system_id dmi_ids[2]; /* Optional */
const char *uid;
+ const char *path;
+ unsigned long long status;
};
-#define X86_MATCH(model) X86_MATCH_INTEL_FAM6_MODEL(model, NULL)
-
-#define ENTRY(hid, uid, cpu_models, dmi...) { \
+#define ENTRY(status, hid, uid, path, cpu_model, dmi...) { \
{ { hid, }, {} }, \
- { cpu_models, {} }, \
+ { X86_MATCH_INTEL_FAM6_MODEL(cpu_model, NULL), {} }, \
{ { .matches = dmi }, {} }, \
uid, \
+ path, \
+ status, \
}
-static const struct always_present_id always_present_ids[] = {
+#define PRESENT_ENTRY_HID(hid, uid, cpu_model, dmi...) \
+ ENTRY(ACPI_STA_DEFAULT, hid, uid, NULL, cpu_model, dmi)
+
+#define NOT_PRESENT_ENTRY_HID(hid, uid, cpu_model, dmi...) \
+ ENTRY(0, hid, uid, NULL, cpu_model, dmi)
+
+#define PRESENT_ENTRY_PATH(path, cpu_model, dmi...) \
+ ENTRY(ACPI_STA_DEFAULT, "", NULL, path, cpu_model, dmi)
+
+#define NOT_PRESENT_ENTRY_PATH(path, cpu_model, dmi...) \
+ ENTRY(0, "", NULL, path, cpu_model, dmi)
+
+static const struct override_status_id override_status_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", X86_MATCH(ATOM_SILVERMONT), {}),
- ENTRY("80862288", "1", X86_MATCH(ATOM_AIRMONT), {}),
+ PRESENT_ENTRY_HID("80860F09", "1", ATOM_SILVERMONT, {}),
+ PRESENT_ENTRY_HID("80862288", "1", ATOM_AIRMONT, {}),
+
+ /* The Xiaomi Mi Pad 2 uses PWM2 for touchkeys backlight control */
+ PRESENT_ENTRY_HID("80862289", "2", ATOM_AIRMONT, {
+ DMI_MATCH(DMI_SYS_VENDOR, "Xiaomi Inc"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"),
+ }),
- /* Lenovo Yoga Book uses PWM2 for keyboard backlight control */
- ENTRY("80862289", "2", X86_MATCH(ATOM_AIRMONT), {
- DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X9"),
- }),
/*
* 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", X86_MATCH(ATOM_AIRMONT), {}),
+ PRESENT_ENTRY_HID("INT0002", "1", ATOM_AIRMONT, {}),
/*
* On the Dell Venue 11 Pro 7130 and 7139, the DSDT hides
* the touchscreen ACPI device until a certain time
* after _SB.PCI0.GFX0.LCD.LCD1._ON gets called has passed
* *and* _STA has been called at least 3 times since.
*/
- ENTRY("SYNA7500", "1", X86_MATCH(HASWELL_L), {
+ PRESENT_ENTRY_HID("SYNA7500", "1", HASWELL_L, {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7130"),
}),
- ENTRY("SYNA7500", "1", X86_MATCH(HASWELL_L), {
+ PRESENT_ENTRY_HID("SYNA7500", "1", HASWELL_L, {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7139"),
}),
@@ -81,54 +103,83 @@ static const struct always_present_id always_present_ids[] = {
/*
* The GPD win BIOS dated 20170221 has disabled the accelerometer, the
* drivers sometimes cause crashes under Windows and this is how the
- * manufacturer has solved this :| Note that the the DMI data is less
- * generic then it seems, a board_vendor of "AMI Corporation" is quite
- * rare and a board_name of "Default String" also is rare.
+ * manufacturer has solved this :| The DMI match may not seem unique,
+ * but it is. In the 67000+ DMI decode dumps from linux-hardware.org
+ * only 116 have board_vendor set to "AMI Corporation" and of those 116
+ * only the GPD win and pocket entries' board_name is "Default string".
*
* Unfortunately the GPD pocket also uses these strings and its BIOS
* was copy-pasted from the GPD win, so it has a disabled KIOX000A
* node which we should not enable, thus we also check the BIOS date.
*/
- ENTRY("KIOX000A", "1", X86_MATCH(ATOM_AIRMONT), {
+ PRESENT_ENTRY_HID("KIOX000A", "1", ATOM_AIRMONT, {
DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
DMI_MATCH(DMI_BOARD_NAME, "Default string"),
DMI_MATCH(DMI_PRODUCT_NAME, "Default string"),
DMI_MATCH(DMI_BIOS_DATE, "02/21/2017")
}),
- ENTRY("KIOX000A", "1", X86_MATCH(ATOM_AIRMONT), {
+ PRESENT_ENTRY_HID("KIOX000A", "1", ATOM_AIRMONT, {
DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
DMI_MATCH(DMI_BOARD_NAME, "Default string"),
DMI_MATCH(DMI_PRODUCT_NAME, "Default string"),
DMI_MATCH(DMI_BIOS_DATE, "03/20/2017")
}),
- ENTRY("KIOX000A", "1", X86_MATCH(ATOM_AIRMONT), {
+ PRESENT_ENTRY_HID("KIOX000A", "1", ATOM_AIRMONT, {
DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
DMI_MATCH(DMI_BOARD_NAME, "Default string"),
DMI_MATCH(DMI_PRODUCT_NAME, "Default string"),
DMI_MATCH(DMI_BIOS_DATE, "05/25/2017")
}),
+
+ /*
+ * The GPD win/pocket have a PCI wifi card, but its DSDT has the SDIO
+ * mmc controller enabled and that has a child-device which _PS3
+ * method sets a GPIO causing the PCI wifi card to turn off.
+ * See above remark about uniqueness of the DMI match.
+ */
+ NOT_PRESENT_ENTRY_PATH("\\_SB_.PCI0.SDHB.BRC1", ATOM_AIRMONT, {
+ DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"),
+ DMI_EXACT_MATCH(DMI_BOARD_SERIAL, "Default string"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"),
+ }),
};
-bool acpi_device_always_present(struct acpi_device *adev)
+bool acpi_device_override_status(struct acpi_device *adev, unsigned long long *status)
{
bool ret = false;
unsigned int i;
- for (i = 0; i < ARRAY_SIZE(always_present_ids); i++) {
- if (acpi_match_device_ids(adev, always_present_ids[i].hid))
+ for (i = 0; i < ARRAY_SIZE(override_status_ids); i++) {
+ if (!x86_match_cpu(override_status_ids[i].cpu_ids))
continue;
- if (!adev->pnp.unique_id ||
- strcmp(adev->pnp.unique_id, always_present_ids[i].uid))
+ if (override_status_ids[i].dmi_ids[0].matches[0].slot &&
+ !dmi_check_system(override_status_ids[i].dmi_ids))
continue;
- if (!x86_match_cpu(always_present_ids[i].cpu_ids))
- continue;
+ if (override_status_ids[i].path) {
+ struct acpi_buffer path = { ACPI_ALLOCATE_BUFFER, NULL };
+ bool match;
- if (always_present_ids[i].dmi_ids[0].matches[0].slot &&
- !dmi_check_system(always_present_ids[i].dmi_ids))
- continue;
+ if (acpi_get_name(adev->handle, ACPI_FULL_PATHNAME, &path))
+ continue;
+
+ match = strcmp((char *)path.pointer, override_status_ids[i].path) == 0;
+ kfree(path.pointer);
+ if (!match)
+ continue;
+ } else {
+ if (acpi_match_device_ids(adev, override_status_ids[i].hid))
+ continue;
+
+ if (!adev->pnp.unique_id ||
+ strcmp(adev->pnp.unique_id, override_status_ids[i].uid))
+ continue;
+ }
+
+ *status = override_status_ids[i].status;
ret = true;
break;
}
@@ -160,3 +211,183 @@ bool force_storage_d3(void)
{
return x86_match_cpu(storage_d3_cpu_ids);
}
+
+/*
+ * 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 BIT(0)
+#define ACPI_QUIRK_UART1_TTY_UART2_SKIP BIT(1)
+#define ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY BIT(2)
+#define ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY BIT(3)
+
+static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
+ /*
+ * 1. Devices with only the skip / don't-skip AC and battery quirks,
+ * sorted alphabetically.
+ */
+ {
+ /* ECS EF20EA, AXP288 PMIC but uses separate fuel-gauge */
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"),
+ },
+ .driver_data = (void *)ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY
+ },
+ {
+ /* Lenovo Ideapad Miix 320, AXP288 PMIC, separate fuel-gauge */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "80XF"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"),
+ },
+ .driver_data = (void *)ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY
+ },
+
+ /*
+ * 2. Devices which also have the skip i2c/serdev quirks and which
+ * need the x86-android-tablets module to properly work.
+ */
+#if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS)
+ {
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ME176C"),
+ },
+ .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
+ ACPI_QUIRK_UART1_TTY_UART2_SKIP |
+ ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "TF103C"),
+ },
+ .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
+ ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
+ },
+ {
+ /* Whitelabel (sold as various brands) TM800A550L */
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
+ DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
+ /* Above strings are too generic, also match on BIOS version */
+ DMI_MATCH(DMI_BIOS_VERSION, "ZY-8-BI-PX4S70VTR400-X423B-005-D"),
+ },
+ .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
+ ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
+ },
+#endif
+ {}
+};
+
+#if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS)
+static const struct acpi_device_id i2c_acpi_known_good_ids[] = {
+ { "10EC5640", 0 }, /* RealTek ALC5640 audio codec */
+ { "INT33F4", 0 }, /* X-Powers AXP288 PMIC */
+ { "INT33FD", 0 }, /* Intel Crystal Cove PMIC */
+ { "NPCE69A", 0 }, /* Asus Transformer keyboard dock */
+ {}
+};
+
+bool acpi_quirk_skip_i2c_client_enumeration(struct acpi_device *adev)
+{
+ const struct dmi_system_id *dmi_id;
+ long quirks;
+
+ dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids);
+ if (!dmi_id)
+ return false;
+
+ quirks = (unsigned long)dmi_id->driver_data;
+ if (!(quirks & ACPI_QUIRK_SKIP_I2C_CLIENTS))
+ return false;
+
+ return acpi_match_device_ids(adev, i2c_acpi_known_good_ids);
+}
+EXPORT_SYMBOL_GPL(acpi_quirk_skip_i2c_client_enumeration);
+
+int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip)
+{
+ struct acpi_device *adev = ACPI_COMPANION(controller_parent);
+ const struct dmi_system_id *dmi_id;
+ long quirks = 0;
+
+ *skip = false;
+
+ /* !dev_is_platform() to not match on PNP enumerated debug UARTs */
+ if (!adev || !adev->pnp.unique_id || !dev_is_platform(controller_parent))
+ return 0;
+
+ dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids);
+ if (dmi_id)
+ quirks = (unsigned long)dmi_id->driver_data;
+
+ if (quirks & ACPI_QUIRK_UART1_TTY_UART2_SKIP) {
+ if (!strcmp(adev->pnp.unique_id, "1"))
+ return -ENODEV; /* Create tty cdev instead of serdev */
+
+ if (!strcmp(adev->pnp.unique_id, "2"))
+ *skip = true;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(acpi_quirk_skip_serdev_enumeration);
+#endif
+
+/* Lists of PMIC ACPI HIDs with an (often better) native charger driver */
+static const struct {
+ const char *hid;
+ int hrv;
+} acpi_skip_ac_and_battery_pmic_ids[] = {
+ { "INT33F4", -1 }, /* X-Powers AXP288 PMIC */
+ { "INT34D3", 3 }, /* Intel Cherrytrail Whiskey Cove PMIC */
+};
+
+bool acpi_quirk_skip_acpi_ac_and_battery(void)
+{
+ const struct dmi_system_id *dmi_id;
+ long quirks = 0;
+ int i;
+
+ dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids);
+ if (dmi_id)
+ quirks = (unsigned long)dmi_id->driver_data;
+
+ if (quirks & ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY)
+ return true;
+
+ if (quirks & ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY)
+ return false;
+
+ for (i = 0; i < ARRAY_SIZE(acpi_skip_ac_and_battery_pmic_ids); i++) {
+ if (acpi_dev_present(acpi_skip_ac_and_battery_pmic_ids[i].hid, "1",
+ acpi_skip_ac_and_battery_pmic_ids[i].hrv)) {
+ pr_info_once("found native %s PMIC, skipping ACPI AC and battery devices\n",
+ acpi_skip_ac_and_battery_pmic_ids[i].hid);
+ return true;
+ }
+ }
+
+ return false;
+}
+EXPORT_SYMBOL_GPL(acpi_quirk_skip_acpi_ac_and_battery);