Commit af8fefd7 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge branches 'acpi-x86', 'acpi-pmic' and 'acpi-dptf'

Merge x86-specific ACPI updates, PMIC driver ACPI updates and a DPTF
driver update for 5.17-rc1:

 - Rework the handling of device enumeration quirks in the x86-specific
   code and add new quirks for known-broken platforms (Hans de Goede).

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

* acpi-x86:
  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
  mmc: sdhci-acpi: Use the new soc_intel_is_byt() helper
  mmc: sdhci-acpi: Remove special handling for GPD win/pocket devices
  ACPI / x86: Add PWM2 on the Xiaomi Mi Pad 2 to the always_present list
  ACPI / x86: Add not-present quirk for the PCI0.SDHB.BRC1 device on the GPD win
  ACPI / x86: Allow specifying acpi_device_override_status() quirks by path
  ACPI: Change acpi_device_always_present() into acpi_device_override_status()
  ACPI / x86: Drop PWM2 device on Lenovo Yoga Book from always present table

* acpi-pmic:
  ACPI: PMIC: xpower: Fix _TMP ACPI errors
  ACPI: PMIC: allow drivers to provide a custom lpat_raw_to_temp() function
  ACPI: PMIC: constify all struct intel_pmic_opregion_data declarations

* acpi-dptf:
  ACPI: DPTF: Update device ID in a comment
......@@ -48,19 +48,12 @@ static const struct acpi_device_id ac_device_ids[] = {
};
MODULE_DEVICE_TABLE(acpi, ac_device_ids);
/* Lists of PMIC ACPI HIDs with an (often better) native charger driver */
static const struct acpi_ac_bl acpi_ac_blacklist[] = {
{ "INT33F4", -1 }, /* X-Powers AXP288 PMIC */
{ "INT34D3", 3 }, /* Intel Cherrytrail Whiskey Cove PMIC */
};
#ifdef CONFIG_PM_SLEEP
static int acpi_ac_resume(struct device *dev);
#endif
static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume);
static int ac_sleep_before_get_state_ms;
static int ac_check_pmic = 1;
static int ac_only;
static struct acpi_driver acpi_ac_driver = {
......@@ -200,12 +193,6 @@ static int __init thinkpad_e530_quirk(const struct dmi_system_id *d)
return 0;
}
static int __init ac_do_not_check_pmic_quirk(const struct dmi_system_id *d)
{
ac_check_pmic = 0;
return 0;
}
static int __init ac_only_quirk(const struct dmi_system_id *d)
{
ac_only = 1;
......@@ -214,13 +201,6 @@ static int __init ac_only_quirk(const struct dmi_system_id *d)
/* Please keep this list alphabetically sorted */
static const struct dmi_system_id ac_dmi_table[] __initconst = {
{
/* ECS EF20EA, AXP288 PMIC but uses separate fuel-gauge */
.callback = ac_do_not_check_pmic_quirk,
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"),
},
},
{
/* Kodlix GK45 returning incorrect state */
.callback = ac_only_quirk,
......@@ -228,15 +208,6 @@ static const struct dmi_system_id ac_dmi_table[] __initconst = {
DMI_MATCH(DMI_PRODUCT_NAME, "GK45"),
},
},
{
/* Lenovo Ideapad Miix 320, AXP288 PMIC, separate fuel-gauge */
.callback = ac_do_not_check_pmic_quirk,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "80XF"),
DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"),
},
},
{
/* Lenovo Thinkpad e530, see comment in acpi_ac_notify() */
.callback = thinkpad_e530_quirk,
......@@ -341,23 +312,15 @@ static int acpi_ac_remove(struct acpi_device *device)
static int __init acpi_ac_init(void)
{
unsigned int i;
int result;
if (acpi_disabled)
return -ENODEV;
dmi_check_system(ac_dmi_table);
if (ac_check_pmic) {
for (i = 0; i < ARRAY_SIZE(acpi_ac_blacklist); i++)
if (acpi_dev_present(acpi_ac_blacklist[i].hid, "1",
acpi_ac_blacklist[i].hrv)) {
pr_info("found native %s PMIC, not loading\n",
acpi_ac_blacklist[i].hid);
if (acpi_quirk_skip_acpi_ac_and_battery())
return -ENODEV;
}
}
dmi_check_system(ac_dmi_table);
result = acpi_bus_register_driver(&acpi_ac_driver);
if (result < 0)
......
......@@ -52,7 +52,6 @@ static bool battery_driver_registered;
static int battery_bix_broken_package;
static int battery_notification_delay_ms;
static int battery_ac_is_broken;
static int battery_check_pmic = 1;
static unsigned int cache_time = 1000;
module_param(cache_time, uint, 0644);
MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
......@@ -64,11 +63,6 @@ static const struct acpi_device_id battery_device_ids[] = {
MODULE_DEVICE_TABLE(acpi, battery_device_ids);
/* Lists of PMIC ACPI HIDs with an (often better) native battery driver */
static const char * const acpi_battery_blacklist[] = {
"INT33F4", /* X-Powers AXP288 PMIC */
};
enum {
ACPI_BATTERY_ALARM_PRESENT,
ACPI_BATTERY_XINFO_PRESENT,
......@@ -1104,13 +1098,6 @@ battery_ac_is_broken_quirk(const struct dmi_system_id *d)
return 0;
}
static int __init
battery_do_not_check_pmic_quirk(const struct dmi_system_id *d)
{
battery_check_pmic = 0;
return 0;
}
static const struct dmi_system_id bat_dmi_table[] __initconst = {
{
/* NEC LZ750/LS */
......@@ -1139,22 +1126,6 @@ static const struct dmi_system_id bat_dmi_table[] __initconst = {
DMI_MATCH(DMI_BIOS_DATE, "08/22/2014"),
},
},
{
/* ECS EF20EA, AXP288 PMIC but uses separate fuel-gauge */
.callback = battery_do_not_check_pmic_quirk,
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"),
},
},
{
/* Lenovo Ideapad Miix 320, AXP288 PMIC, separate fuel-gauge */
.callback = battery_do_not_check_pmic_quirk,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "80XF"),
DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"),
},
},
{},
};
......@@ -1279,19 +1250,12 @@ static struct acpi_driver acpi_battery_driver = {
static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
{
unsigned int i;
int result;
dmi_check_system(bat_dmi_table);
if (battery_check_pmic) {
for (i = 0; i < ARRAY_SIZE(acpi_battery_blacklist); i++)
if (acpi_dev_present(acpi_battery_blacklist[i], "1", -1)) {
pr_info("found native %s PMIC, not loading\n",
acpi_battery_blacklist[i]);
if (acpi_quirk_skip_acpi_ac_and_battery())
return;
}
}
dmi_check_system(bat_dmi_table);
result = acpi_bus_register_driver(&acpi_battery_driver);
battery_driver_registered = (result == 0);
......
......@@ -98,8 +98,8 @@ 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);
if (acpi_device_override_status(device, &sta)) {
acpi_set_device_status(device, sta);
return 0;
}
......
......@@ -46,7 +46,7 @@ static int pch_fivr_read(acpi_handle handle, char *method, struct pch_fivr_resp
}
/*
* Presentation of attributes which are defined for INT1045
* Presentation of attributes which are defined for INTC10xx
* They are:
* freq_mhz_low_clock : Set PCH FIVR switching freq for
* FIVR clock 19.2MHz and 24MHz
......
......@@ -25,7 +25,7 @@ struct intel_pmic_opregion {
struct mutex lock;
struct acpi_lpat_conversion_table *lpat_table;
struct regmap *regmap;
struct intel_pmic_opregion_data *data;
const struct intel_pmic_opregion_data *data;
struct intel_pmic_regs_handler_ctx ctx;
};
......@@ -53,7 +53,7 @@ static acpi_status intel_pmic_power_handler(u32 function,
{
struct intel_pmic_opregion *opregion = region_context;
struct regmap *regmap = opregion->regmap;
struct intel_pmic_opregion_data *d = opregion->data;
const struct intel_pmic_opregion_data *d = opregion->data;
int reg, bit, result;
if (bits != 32 || !value64)
......@@ -95,7 +95,7 @@ static int pmic_read_temp(struct intel_pmic_opregion *opregion,
return 0;
}
temp = acpi_lpat_raw_to_temp(opregion->lpat_table, raw_temp);
temp = opregion->data->lpat_raw_to_temp(opregion->lpat_table, raw_temp);
if (temp < 0)
return temp;
......@@ -135,7 +135,7 @@ static int pmic_thermal_aux(struct intel_pmic_opregion *opregion, int reg,
static int pmic_thermal_pen(struct intel_pmic_opregion *opregion, int reg,
int bit, u32 function, u64 *value)
{
struct intel_pmic_opregion_data *d = opregion->data;
const struct intel_pmic_opregion_data *d = opregion->data;
struct regmap *regmap = opregion->regmap;
if (!d->get_policy || !d->update_policy)
......@@ -171,7 +171,7 @@ static acpi_status intel_pmic_thermal_handler(u32 function,
void *handler_context, void *region_context)
{
struct intel_pmic_opregion *opregion = region_context;
struct intel_pmic_opregion_data *d = opregion->data;
const struct intel_pmic_opregion_data *d = opregion->data;
int reg, bit, result;
if (bits != 32 || !value64)
......@@ -255,7 +255,7 @@ static acpi_status intel_pmic_regs_handler(u32 function,
int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle,
struct regmap *regmap,
struct intel_pmic_opregion_data *d)
const struct intel_pmic_opregion_data *d)
{
acpi_status status = AE_OK;
struct intel_pmic_opregion *opregion;
......@@ -344,7 +344,7 @@ EXPORT_SYMBOL_GPL(intel_pmic_install_opregion_handler);
int intel_soc_pmic_exec_mipi_pmic_seq_element(u16 i2c_address, u32 reg_address,
u32 value, u32 mask)
{
struct intel_pmic_opregion_data *d;
const struct intel_pmic_opregion_data *d;
int ret;
if (!intel_pmic_opregion) {
......
......@@ -2,6 +2,8 @@
#ifndef __INTEL_PMIC_H
#define __INTEL_PMIC_H
#include <acpi/acpi_lpat.h>
struct pmic_table {
int address; /* operation region address */
int reg; /* corresponding thermal register */
......@@ -17,6 +19,8 @@ struct intel_pmic_opregion_data {
int (*update_policy)(struct regmap *r, int reg, int bit, int enable);
int (*exec_mipi_pmic_seq_element)(struct regmap *r, u16 i2c_address,
u32 reg_address, u32 value, u32 mask);
int (*lpat_raw_to_temp)(struct acpi_lpat_conversion_table *lpat_table,
int raw);
struct pmic_table *power_table;
int power_table_count;
struct pmic_table *thermal_table;
......@@ -25,6 +29,8 @@ struct intel_pmic_opregion_data {
int pmic_i2c_address;
};
int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle, struct regmap *regmap, struct intel_pmic_opregion_data *d);
int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle,
struct regmap *regmap,
const struct intel_pmic_opregion_data *d);
#endif
......@@ -369,13 +369,14 @@ intel_bxtwc_pmic_update_policy(struct regmap *regmap,
return regmap_update_bits(regmap, reg, mask, val);
}
static struct intel_pmic_opregion_data intel_bxtwc_pmic_opregion_data = {
static const struct intel_pmic_opregion_data intel_bxtwc_pmic_opregion_data = {
.get_power = intel_bxtwc_pmic_get_power,
.update_power = intel_bxtwc_pmic_update_power,
.get_raw_temp = intel_bxtwc_pmic_get_raw_temp,
.update_aux = intel_bxtwc_pmic_update_aux,
.get_policy = intel_bxtwc_pmic_get_policy,
.update_policy = intel_bxtwc_pmic_update_policy,
.lpat_raw_to_temp = acpi_lpat_raw_to_temp,
.power_table = power_table,
.power_table_count = ARRAY_SIZE(power_table),
.thermal_table = thermal_table,
......
......@@ -271,13 +271,14 @@ static int intel_crc_pmic_update_policy(struct regmap *regmap,
return 0;
}
static struct intel_pmic_opregion_data intel_crc_pmic_opregion_data = {
static const struct intel_pmic_opregion_data intel_crc_pmic_opregion_data = {
.get_power = intel_crc_pmic_get_power,
.update_power = intel_crc_pmic_update_power,
.get_raw_temp = intel_crc_pmic_get_raw_temp,
.update_aux = intel_crc_pmic_update_aux,
.get_policy = intel_crc_pmic_get_policy,
.update_policy = intel_crc_pmic_update_policy,
.lpat_raw_to_temp = acpi_lpat_raw_to_temp,
.power_table = power_table,
.power_table_count= ARRAY_SIZE(power_table),
.thermal_table = thermal_table,
......
......@@ -23,7 +23,8 @@
* intel_soc_pmic_exec_mipi_pmic_seq_element work on devices with a
* CHT Crystal Cove PMIC.
*/
static struct intel_pmic_opregion_data intel_chtcrc_pmic_opregion_data = {
static const struct intel_pmic_opregion_data intel_chtcrc_pmic_opregion_data = {
.lpat_raw_to_temp = acpi_lpat_raw_to_temp,
.pmic_i2c_address = 0x6e,
};
......
......@@ -94,10 +94,11 @@ static int chtdc_ti_pmic_get_raw_temp(struct regmap *regmap, int reg)
return ((buf[0] & 0x03) << 8) | buf[1];
}
static struct intel_pmic_opregion_data chtdc_ti_pmic_opregion_data = {
static const struct intel_pmic_opregion_data chtdc_ti_pmic_opregion_data = {
.get_power = chtdc_ti_pmic_get_power,
.update_power = chtdc_ti_pmic_update_power,
.get_raw_temp = chtdc_ti_pmic_get_raw_temp,
.lpat_raw_to_temp = acpi_lpat_raw_to_temp,
.power_table = chtdc_ti_power_table,
.power_table_count = ARRAY_SIZE(chtdc_ti_power_table),
.thermal_table = chtdc_ti_thermal_table,
......
......@@ -253,10 +253,11 @@ static int intel_cht_wc_exec_mipi_pmic_seq_element(struct regmap *regmap,
* The thermal table and ops are empty, we do not support the Thermal opregion
* (DPTF) due to lacking documentation.
*/
static struct intel_pmic_opregion_data intel_cht_wc_pmic_opregion_data = {
static const struct intel_pmic_opregion_data intel_cht_wc_pmic_opregion_data = {
.get_power = intel_cht_wc_pmic_get_power,
.update_power = intel_cht_wc_pmic_update_power,
.exec_mipi_pmic_seq_element = intel_cht_wc_exec_mipi_pmic_seq_element,
.lpat_raw_to_temp = acpi_lpat_raw_to_temp,
.power_table = power_table,
.power_table_count = ARRAY_SIZE(power_table),
};
......
......@@ -293,11 +293,33 @@ static int intel_xpower_exec_mipi_pmic_seq_element(struct regmap *regmap,
return ret;
}
static struct intel_pmic_opregion_data intel_xpower_pmic_opregion_data = {
static int intel_xpower_lpat_raw_to_temp(struct acpi_lpat_conversion_table *lpat_table,
int raw)
{
struct acpi_lpat first = lpat_table->lpat[0];
struct acpi_lpat last = lpat_table->lpat[lpat_table->lpat_count - 1];
/*
* Some LPAT tables in the ACPI Device for the AXP288 PMIC for some
* reason only describe a small temperature range, e.g. 27° - 37°
* Celcius. Resulting in errors when the tablet is idle in a cool room.
*
* To avoid these errors clamp the raw value to be inside the LPAT.
*/
if (first.raw < last.raw)
raw = clamp(raw, first.raw, last.raw);
else
raw = clamp(raw, last.raw, first.raw);
return acpi_lpat_raw_to_temp(lpat_table, raw);
}
static const struct intel_pmic_opregion_data intel_xpower_pmic_opregion_data = {
.get_power = intel_xpower_pmic_get_power,
.update_power = intel_xpower_pmic_update_power,
.get_raw_temp = intel_xpower_pmic_get_raw_temp,
.exec_mipi_pmic_seq_element = intel_xpower_exec_mipi_pmic_seq_element,
.lpat_raw_to_temp = intel_xpower_lpat_raw_to_temp,
.power_table = power_table,
.power_table_count = ARRAY_SIZE(power_table),
.thermal_table = thermal_table,
......
......@@ -8,6 +8,8 @@
* 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>
......@@ -23,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, {}),
/* 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 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"),
}),
/*
* 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"),
}),
......@@ -82,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))
if (override_status_ids[i].path) {
struct acpi_buffer path = { ACPI_ALLOCATE_BUFFER, NULL };
bool match;
if (acpi_get_name(adev->handle, ACPI_FULL_PATHNAME, &path))
continue;
if (always_present_ids[i].dmi_ids[0].matches[0].slot &&
!dmi_check_system(always_present_ids[i].dmi_ids))
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;
}
......@@ -162,7 +212,6 @@ bool force_storage_d3(void)
return x86_match_cpu(storage_d3_cpu_ids);
}
#if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS)
/*
* 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
......@@ -188,22 +237,52 @@ bool force_storage_d3(void)
*/
#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_skip_serial_bus_enumeration_ids[] = {
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_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,
.driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
},
{
/* Whitelabel (sold as various brands) TM800A550L */
......@@ -213,11 +292,14 @@ static const struct dmi_system_id acpi_skip_serial_bus_enumeration_ids[] = {
/* 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,
.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 */
......@@ -231,7 +313,7 @@ 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_skip_serial_bus_enumeration_ids);
dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids);
if (!dmi_id)
return false;
......@@ -255,7 +337,7 @@ int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *s
if (!adev || !adev->pnp.unique_id || !dev_is_platform(controller_parent))
return 0;
dmi_id = dmi_first_match(acpi_skip_serial_bus_enumeration_ids);
dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids);
if (dmi_id)
quirks = (unsigned long)dmi_id->driver_data;
......@@ -271,3 +353,41 @@ int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *s
}
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);
......@@ -31,10 +31,8 @@
#include <linux/mmc/slot-gpio.h>
#ifdef CONFIG_X86
#include <asm/cpu_device_id.h>
#include <asm/intel-family.h>
#include <linux/platform_data/x86/soc.h>
#include <asm/iosf_mbi.h>
#include <linux/pci.h>
#endif
#include "sdhci.h"
......@@ -240,26 +238,6 @@ static const struct sdhci_acpi_chip sdhci_acpi_chip_int = {
#ifdef CONFIG_X86
static bool sdhci_acpi_byt(void)
{
static const struct x86_cpu_id byt[] = {
X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT, NULL),
{}
};
return x86_match_cpu(byt);
}
static bool sdhci_acpi_cht(void)
{
static const struct x86_cpu_id cht[] = {
X86_MATCH_INTEL_FAM6_MODEL(ATOM_AIRMONT, NULL),
{}
};
return x86_match_cpu(cht);
}
#define BYT_IOSF_SCCEP 0x63
#define BYT_IOSF_OCP_NETCTRL0 0x1078
#define BYT_IOSF_OCP_TIMEOUT_BASE GENMASK(10, 8)
......@@ -268,7 +246,7 @@ static void sdhci_acpi_byt_setting(struct device *dev)
{
u32 val = 0;
if (!sdhci_acpi_byt())
if (!soc_intel_is_byt())
return;
if (iosf_mbi_read(BYT_IOSF_SCCEP, MBI_CR_READ, BYT_IOSF_OCP_NETCTRL0,
......@@ -293,7 +271,7 @@ static void sdhci_acpi_byt_setting(struct device *dev)
static bool sdhci_acpi_byt_defer(struct device *dev)
{
if (!sdhci_acpi_byt())
if (!soc_intel_is_byt())
return false;
if (!iosf_mbi_available())
......@@ -304,43 +282,6 @@ static bool sdhci_acpi_byt_defer(struct device *dev)
return false;
}
static bool sdhci_acpi_cht_pci_wifi(unsigned int vendor, unsigned int device,
unsigned int slot, unsigned int parent_slot)
{
struct pci_dev *dev, *parent, *from = NULL;
while (1) {
dev = pci_get_device(vendor, device, from);
pci_dev_put(from);
if (!dev)
break;
parent = pci_upstream_bridge(dev);
if (ACPI_COMPANION(&dev->dev) && PCI_SLOT(dev->devfn) == slot &&
parent && PCI_SLOT(parent->devfn) == parent_slot &&
!pci_upstream_bridge(parent)) {
pci_dev_put(dev);
return true;
}
from = dev;
}
return false;
}
/*
* GPDwin uses PCI wifi which conflicts with SDIO's use of
* acpi_device_fix_up_power() on child device nodes. Identifying GPDwin is
* problematic, but since SDIO is only used for wifi, the presence of the PCI
* wifi card in the expected slot with an ACPI companion node, is used to
* indicate that acpi_device_fix_up_power() should be avoided.
*/
static inline bool sdhci_acpi_no_fixup_child_power(struct acpi_device *adev)
{
return sdhci_acpi_cht() &&
acpi_dev_hid_uid_match(adev, "80860F14", "2") &&
sdhci_acpi_cht_pci_wifi(0x14e4, 0x43ec, 0, 28);
}
#else
static inline void sdhci_acpi_byt_setting(struct device *dev)
......@@ -352,11 +293,6 @@ static inline bool sdhci_acpi_byt_defer(struct device *dev)
return false;
}
static inline bool sdhci_acpi_no_fixup_child_power(struct acpi_device *adev)
{
return false;
}
#endif
static int bxt_get_cd(struct mmc_host *mmc)
......@@ -861,11 +797,9 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
/* Power on the SDHCI controller and its children */
acpi_device_fix_up_power(device);
if (!sdhci_acpi_no_fixup_child_power(device)) {
list_for_each_entry(child, &device->children, node)
if (child->status.present && child->status.enabled)
acpi_device_fix_up_power(child);
}
if (sdhci_acpi_byt_defer(dev))
return -EPROBE_DEFER;
......
......@@ -614,9 +614,15 @@ 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);
bool acpi_device_override_status(struct acpi_device *adev, unsigned long long *status);
bool acpi_quirk_skip_acpi_ac_and_battery(void);
#else
static inline bool acpi_device_always_present(struct acpi_device *adev)
static inline bool acpi_device_override_status(struct acpi_device *adev,
unsigned long long *status)
{
return false;
}
static inline bool acpi_quirk_skip_acpi_ac_and_battery(void)
{
return false;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment