0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #define pr_fmt(fmt) "ACPI: " fmt
0012
0013 #include <linux/acpi.h>
0014 #include <linux/dmi.h>
0015 #include <linux/platform_device.h>
0016 #include <asm/cpu_device_id.h>
0017 #include <asm/intel-family.h>
0018 #include "../internal.h"
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 struct override_status_id {
0040 struct acpi_device_id hid[2];
0041 struct x86_cpu_id cpu_ids[2];
0042 struct dmi_system_id dmi_ids[2];
0043 const char *uid;
0044 const char *path;
0045 unsigned long long status;
0046 };
0047
0048 #define ENTRY(status, hid, uid, path, cpu_model, dmi...) { \
0049 { { hid, }, {} }, \
0050 { X86_MATCH_INTEL_FAM6_MODEL(cpu_model, NULL), {} }, \
0051 { { .matches = dmi }, {} }, \
0052 uid, \
0053 path, \
0054 status, \
0055 }
0056
0057 #define PRESENT_ENTRY_HID(hid, uid, cpu_model, dmi...) \
0058 ENTRY(ACPI_STA_DEFAULT, hid, uid, NULL, cpu_model, dmi)
0059
0060 #define NOT_PRESENT_ENTRY_HID(hid, uid, cpu_model, dmi...) \
0061 ENTRY(0, hid, uid, NULL, cpu_model, dmi)
0062
0063 #define PRESENT_ENTRY_PATH(path, cpu_model, dmi...) \
0064 ENTRY(ACPI_STA_DEFAULT, "", NULL, path, cpu_model, dmi)
0065
0066 #define NOT_PRESENT_ENTRY_PATH(path, cpu_model, dmi...) \
0067 ENTRY(0, "", NULL, path, cpu_model, dmi)
0068
0069 static const struct override_status_id override_status_ids[] = {
0070
0071
0072
0073
0074 PRESENT_ENTRY_HID("80860F09", "1", ATOM_SILVERMONT, {}),
0075 PRESENT_ENTRY_HID("80862288", "1", ATOM_AIRMONT, {}),
0076
0077
0078 PRESENT_ENTRY_HID("80862289", "2", ATOM_AIRMONT, {
0079 DMI_MATCH(DMI_SYS_VENDOR, "Xiaomi Inc"),
0080 DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"),
0081 }),
0082
0083
0084
0085
0086
0087 PRESENT_ENTRY_HID("INT0002", "1", ATOM_AIRMONT, {}),
0088
0089
0090
0091
0092
0093
0094 PRESENT_ENTRY_HID("SYNA7500", "1", HASWELL_L, {
0095 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
0096 DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7130"),
0097 }),
0098 PRESENT_ENTRY_HID("SYNA7500", "1", HASWELL_L, {
0099 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
0100 DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7139"),
0101 }),
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115 PRESENT_ENTRY_HID("KIOX000A", "1", ATOM_AIRMONT, {
0116 DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
0117 DMI_MATCH(DMI_BOARD_NAME, "Default string"),
0118 DMI_MATCH(DMI_PRODUCT_NAME, "Default string"),
0119 DMI_MATCH(DMI_BIOS_DATE, "02/21/2017")
0120 }),
0121 PRESENT_ENTRY_HID("KIOX000A", "1", ATOM_AIRMONT, {
0122 DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
0123 DMI_MATCH(DMI_BOARD_NAME, "Default string"),
0124 DMI_MATCH(DMI_PRODUCT_NAME, "Default string"),
0125 DMI_MATCH(DMI_BIOS_DATE, "03/20/2017")
0126 }),
0127 PRESENT_ENTRY_HID("KIOX000A", "1", ATOM_AIRMONT, {
0128 DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
0129 DMI_MATCH(DMI_BOARD_NAME, "Default string"),
0130 DMI_MATCH(DMI_PRODUCT_NAME, "Default string"),
0131 DMI_MATCH(DMI_BIOS_DATE, "05/25/2017")
0132 }),
0133
0134
0135
0136
0137
0138
0139
0140 NOT_PRESENT_ENTRY_PATH("\\_SB_.PCI0.SDHB.BRC1", ATOM_AIRMONT, {
0141 DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
0142 DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"),
0143 DMI_EXACT_MATCH(DMI_BOARD_SERIAL, "Default string"),
0144 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"),
0145 }),
0146 };
0147
0148 bool acpi_device_override_status(struct acpi_device *adev, unsigned long long *status)
0149 {
0150 bool ret = false;
0151 unsigned int i;
0152
0153 for (i = 0; i < ARRAY_SIZE(override_status_ids); i++) {
0154 if (!x86_match_cpu(override_status_ids[i].cpu_ids))
0155 continue;
0156
0157 if (override_status_ids[i].dmi_ids[0].matches[0].slot &&
0158 !dmi_check_system(override_status_ids[i].dmi_ids))
0159 continue;
0160
0161 if (override_status_ids[i].path) {
0162 struct acpi_buffer path = { ACPI_ALLOCATE_BUFFER, NULL };
0163 bool match;
0164
0165 if (acpi_get_name(adev->handle, ACPI_FULL_PATHNAME, &path))
0166 continue;
0167
0168 match = strcmp((char *)path.pointer, override_status_ids[i].path) == 0;
0169 kfree(path.pointer);
0170
0171 if (!match)
0172 continue;
0173 } else {
0174 if (acpi_match_device_ids(adev, override_status_ids[i].hid))
0175 continue;
0176
0177 if (!adev->pnp.unique_id ||
0178 strcmp(adev->pnp.unique_id, override_status_ids[i].uid))
0179 continue;
0180 }
0181
0182 *status = override_status_ids[i].status;
0183 ret = true;
0184 break;
0185 }
0186
0187 return ret;
0188 }
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204 static const struct x86_cpu_id storage_d3_cpu_ids[] = {
0205 X86_MATCH_VENDOR_FAM_MODEL(AMD, 23, 96, NULL),
0206 X86_MATCH_VENDOR_FAM_MODEL(AMD, 23, 104, NULL),
0207 {}
0208 };
0209
0210 bool force_storage_d3(void)
0211 {
0212 return x86_match_cpu(storage_d3_cpu_ids);
0213 }
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238 #define ACPI_QUIRK_SKIP_I2C_CLIENTS BIT(0)
0239 #define ACPI_QUIRK_UART1_TTY_UART2_SKIP BIT(1)
0240 #define ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY BIT(2)
0241 #define ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY BIT(3)
0242
0243 static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
0244
0245
0246
0247
0248 {
0249
0250 .matches = {
0251 DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"),
0252 },
0253 .driver_data = (void *)ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY
0254 },
0255 {
0256
0257 .matches = {
0258 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
0259 DMI_MATCH(DMI_PRODUCT_NAME, "80XF"),
0260 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"),
0261 },
0262 .driver_data = (void *)ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY
0263 },
0264
0265
0266
0267
0268
0269 #if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS)
0270 {
0271 .matches = {
0272 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
0273 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ME176C"),
0274 },
0275 .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
0276 ACPI_QUIRK_UART1_TTY_UART2_SKIP |
0277 ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
0278 },
0279 {
0280 .matches = {
0281 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
0282 DMI_MATCH(DMI_PRODUCT_NAME, "TF103C"),
0283 },
0284 .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
0285 ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
0286 },
0287 {
0288
0289 .matches = {
0290 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corp."),
0291 DMI_MATCH(DMI_PRODUCT_NAME, "VALLEYVIEW C0 PLATFORM"),
0292 DMI_MATCH(DMI_BOARD_NAME, "BYT-T FFD8"),
0293
0294 DMI_MATCH(DMI_BIOS_VERSION, "BLADE_21"),
0295 },
0296 .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
0297 ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
0298 },
0299 {
0300
0301 .matches = {
0302 DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
0303 DMI_MATCH(DMI_PRODUCT_NAME, "M890BAP"),
0304 },
0305 .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
0306 ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
0307 },
0308 {
0309
0310 .matches = {
0311 DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
0312 DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
0313
0314 DMI_MATCH(DMI_BIOS_VERSION, "ZY-8-BI-PX4S70VTR400-X423B-005-D"),
0315 },
0316 .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
0317 ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
0318 },
0319 #endif
0320 {}
0321 };
0322
0323 #if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS)
0324 static const struct acpi_device_id i2c_acpi_known_good_ids[] = {
0325 { "10EC5640", 0 },
0326 { "INT33F4", 0 },
0327 { "INT33FD", 0 },
0328 { "NPCE69A", 0 },
0329 {}
0330 };
0331
0332 bool acpi_quirk_skip_i2c_client_enumeration(struct acpi_device *adev)
0333 {
0334 const struct dmi_system_id *dmi_id;
0335 long quirks;
0336
0337 dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids);
0338 if (!dmi_id)
0339 return false;
0340
0341 quirks = (unsigned long)dmi_id->driver_data;
0342 if (!(quirks & ACPI_QUIRK_SKIP_I2C_CLIENTS))
0343 return false;
0344
0345 return acpi_match_device_ids(adev, i2c_acpi_known_good_ids);
0346 }
0347 EXPORT_SYMBOL_GPL(acpi_quirk_skip_i2c_client_enumeration);
0348
0349 int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip)
0350 {
0351 struct acpi_device *adev = ACPI_COMPANION(controller_parent);
0352 const struct dmi_system_id *dmi_id;
0353 long quirks = 0;
0354
0355 *skip = false;
0356
0357
0358 if (!adev || !adev->pnp.unique_id || !dev_is_platform(controller_parent))
0359 return 0;
0360
0361 dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids);
0362 if (dmi_id)
0363 quirks = (unsigned long)dmi_id->driver_data;
0364
0365 if (quirks & ACPI_QUIRK_UART1_TTY_UART2_SKIP) {
0366 if (!strcmp(adev->pnp.unique_id, "1"))
0367 return -ENODEV;
0368
0369 if (!strcmp(adev->pnp.unique_id, "2"))
0370 *skip = true;
0371 }
0372
0373 return 0;
0374 }
0375 EXPORT_SYMBOL_GPL(acpi_quirk_skip_serdev_enumeration);
0376 #endif
0377
0378
0379 static const struct {
0380 const char *hid;
0381 int hrv;
0382 } acpi_skip_ac_and_battery_pmic_ids[] = {
0383 { "INT33F4", -1 },
0384 { "INT34D3", 3 },
0385 };
0386
0387 bool acpi_quirk_skip_acpi_ac_and_battery(void)
0388 {
0389 const struct dmi_system_id *dmi_id;
0390 long quirks = 0;
0391 int i;
0392
0393 dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids);
0394 if (dmi_id)
0395 quirks = (unsigned long)dmi_id->driver_data;
0396
0397 if (quirks & ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY)
0398 return true;
0399
0400 if (quirks & ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY)
0401 return false;
0402
0403 for (i = 0; i < ARRAY_SIZE(acpi_skip_ac_and_battery_pmic_ids); i++) {
0404 if (acpi_dev_present(acpi_skip_ac_and_battery_pmic_ids[i].hid, "1",
0405 acpi_skip_ac_and_battery_pmic_ids[i].hrv)) {
0406 pr_info_once("found native %s PMIC, skipping ACPI AC and battery devices\n",
0407 acpi_skip_ac_and_battery_pmic_ids[i].hid);
0408 return true;
0409 }
0410 }
0411
0412 return false;
0413 }
0414 EXPORT_SYMBOL_GPL(acpi_quirk_skip_acpi_ac_and_battery);