1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * X86 ACPI Utility Functions |
4 | * |
5 | * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com> |
6 | * |
7 | * Based on various non upstream patches to support the CHT Whiskey Cove PMIC: |
8 | * Copyright (C) 2013-2015 Intel Corporation. All rights reserved. |
9 | */ |
10 | |
11 | #define pr_fmt(fmt) "ACPI: " fmt |
12 | |
13 | #include <linux/acpi.h> |
14 | #include <linux/dmi.h> |
15 | #include <linux/platform_device.h> |
16 | #include <asm/cpu_device_id.h> |
17 | #include <asm/intel-family.h> |
18 | #include "../internal.h" |
19 | |
20 | /* |
21 | * Some ACPI devices are hidden (status == 0x0) in recent BIOS-es because |
22 | * some recent Windows drivers bind to one device but poke at multiple |
23 | * devices at the same time, so the others get hidden. |
24 | * |
25 | * Some BIOS-es (temporarily) hide specific APCI devices to work around Windows |
26 | * driver bugs. We use DMI matching to match known cases of this. |
27 | * |
28 | * Likewise sometimes some not-actually present devices are sometimes |
29 | * reported as present, which may cause issues. |
30 | * |
31 | * We work around this by using the below quirk list to override the status |
32 | * reported by the _STA method with a fixed value (ACPI_STA_DEFAULT or 0). |
33 | * Note this MUST only be done for devices where this is safe. |
34 | * |
35 | * This status overriding is limited to specific CPU (SoC) models both to |
36 | * avoid potentially causing trouble on other models and because some HIDs |
37 | * are re-used on different SoCs for completely different devices. |
38 | */ |
39 | struct override_status_id { |
40 | struct acpi_device_id hid[2]; |
41 | struct x86_cpu_id cpu_ids[2]; |
42 | struct dmi_system_id dmi_ids[2]; /* Optional */ |
43 | const char *uid; |
44 | const char *path; |
45 | unsigned long long status; |
46 | }; |
47 | |
48 | #define ENTRY(status, hid, uid, path, cpu_model, dmi...) { \ |
49 | { { hid, }, {} }, \ |
50 | { X86_MATCH_INTEL_FAM6_MODEL(cpu_model, NULL), {} }, \ |
51 | { { .matches = dmi }, {} }, \ |
52 | uid, \ |
53 | path, \ |
54 | status, \ |
55 | } |
56 | |
57 | #define PRESENT_ENTRY_HID(hid, uid, cpu_model, dmi...) \ |
58 | ENTRY(ACPI_STA_DEFAULT, hid, uid, NULL, cpu_model, dmi) |
59 | |
60 | #define NOT_PRESENT_ENTRY_HID(hid, uid, cpu_model, dmi...) \ |
61 | ENTRY(0, hid, uid, NULL, cpu_model, dmi) |
62 | |
63 | #define PRESENT_ENTRY_PATH(path, cpu_model, dmi...) \ |
64 | ENTRY(ACPI_STA_DEFAULT, "", NULL, path, cpu_model, dmi) |
65 | |
66 | #define NOT_PRESENT_ENTRY_PATH(path, cpu_model, dmi...) \ |
67 | ENTRY(0, "", NULL, path, cpu_model, dmi) |
68 | |
69 | static const struct override_status_id override_status_ids[] = { |
70 | /* |
71 | * Bay / Cherry Trail PWM directly poked by GPU driver in win10, |
72 | * but Linux uses a separate PWM driver, harmless if not used. |
73 | */ |
74 | PRESENT_ENTRY_HID("80860F09" , "1" , ATOM_SILVERMONT, {}), |
75 | PRESENT_ENTRY_HID("80862288" , "1" , ATOM_AIRMONT, {}), |
76 | |
77 | /* The Xiaomi Mi Pad 2 uses PWM2 for touchkeys backlight control */ |
78 | PRESENT_ENTRY_HID("80862289" , "2" , ATOM_AIRMONT, { |
79 | DMI_MATCH(DMI_SYS_VENDOR, "Xiaomi Inc" ), |
80 | DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2" ), |
81 | }), |
82 | |
83 | /* |
84 | * The INT0002 device is necessary to clear wakeup interrupt sources |
85 | * on Cherry Trail devices, without it we get nobody cared IRQ msgs. |
86 | */ |
87 | PRESENT_ENTRY_HID("INT0002" , "1" , ATOM_AIRMONT, {}), |
88 | /* |
89 | * On the Dell Venue 11 Pro 7130 and 7139, the DSDT hides |
90 | * the touchscreen ACPI device until a certain time |
91 | * after _SB.PCI0.GFX0.LCD.LCD1._ON gets called has passed |
92 | * *and* _STA has been called at least 3 times since. |
93 | */ |
94 | PRESENT_ENTRY_HID("SYNA7500" , "1" , HASWELL_L, { |
95 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc." ), |
96 | DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7130" ), |
97 | }), |
98 | PRESENT_ENTRY_HID("SYNA7500" , "1" , HASWELL_L, { |
99 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc." ), |
100 | DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7139" ), |
101 | }), |
102 | |
103 | /* |
104 | * The GPD win BIOS dated 20170221 has disabled the accelerometer, the |
105 | * drivers sometimes cause crashes under Windows and this is how the |
106 | * manufacturer has solved this :| The DMI match may not seem unique, |
107 | * but it is. In the 67000+ DMI decode dumps from linux-hardware.org |
108 | * only 116 have board_vendor set to "AMI Corporation" and of those 116 |
109 | * only the GPD win and pocket entries' board_name is "Default string". |
110 | * |
111 | * Unfortunately the GPD pocket also uses these strings and its BIOS |
112 | * was copy-pasted from the GPD win, so it has a disabled KIOX000A |
113 | * node which we should not enable, thus we also check the BIOS date. |
114 | */ |
115 | PRESENT_ENTRY_HID("KIOX000A" , "1" , ATOM_AIRMONT, { |
116 | DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation" ), |
117 | DMI_MATCH(DMI_BOARD_NAME, "Default string" ), |
118 | DMI_MATCH(DMI_PRODUCT_NAME, "Default string" ), |
119 | DMI_MATCH(DMI_BIOS_DATE, "02/21/2017" ) |
120 | }), |
121 | PRESENT_ENTRY_HID("KIOX000A" , "1" , ATOM_AIRMONT, { |
122 | DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation" ), |
123 | DMI_MATCH(DMI_BOARD_NAME, "Default string" ), |
124 | DMI_MATCH(DMI_PRODUCT_NAME, "Default string" ), |
125 | DMI_MATCH(DMI_BIOS_DATE, "03/20/2017" ) |
126 | }), |
127 | PRESENT_ENTRY_HID("KIOX000A" , "1" , ATOM_AIRMONT, { |
128 | DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation" ), |
129 | DMI_MATCH(DMI_BOARD_NAME, "Default string" ), |
130 | DMI_MATCH(DMI_PRODUCT_NAME, "Default string" ), |
131 | DMI_MATCH(DMI_BIOS_DATE, "05/25/2017" ) |
132 | }), |
133 | |
134 | /* |
135 | * The GPD win/pocket have a PCI wifi card, but its DSDT has the SDIO |
136 | * mmc controller enabled and that has a child-device which _PS3 |
137 | * method sets a GPIO causing the PCI wifi card to turn off. |
138 | * See above remark about uniqueness of the DMI match. |
139 | */ |
140 | NOT_PRESENT_ENTRY_PATH("\\_SB_.PCI0.SDHB.BRC1" , ATOM_AIRMONT, { |
141 | DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation" ), |
142 | DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string" ), |
143 | DMI_EXACT_MATCH(DMI_BOARD_SERIAL, "Default string" ), |
144 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string" ), |
145 | }), |
146 | |
147 | /* |
148 | * The LSM303D on the Lenovo Yoga Tablet 2 series is present |
149 | * as both ACCL0001 and MAGN0001. As we can only ever register an |
150 | * i2c client for one of them, ignore MAGN0001. |
151 | */ |
152 | NOT_PRESENT_ENTRY_HID("MAGN0001" , "1" , ATOM_SILVERMONT, { |
153 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO" ), |
154 | DMI_MATCH(DMI_PRODUCT_FAMILY, "YOGATablet2" ), |
155 | }), |
156 | }; |
157 | |
158 | bool acpi_device_override_status(struct acpi_device *adev, unsigned long long *status) |
159 | { |
160 | bool ret = false; |
161 | unsigned int i; |
162 | |
163 | for (i = 0; i < ARRAY_SIZE(override_status_ids); i++) { |
164 | if (!x86_match_cpu(match: override_status_ids[i].cpu_ids)) |
165 | continue; |
166 | |
167 | if (override_status_ids[i].dmi_ids[0].matches[0].slot && |
168 | !dmi_check_system(list: override_status_ids[i].dmi_ids)) |
169 | continue; |
170 | |
171 | if (override_status_ids[i].path) { |
172 | struct acpi_buffer path = { ACPI_ALLOCATE_BUFFER, NULL }; |
173 | bool match; |
174 | |
175 | if (acpi_get_name(object: adev->handle, ACPI_FULL_PATHNAME, ret_path_ptr: &path)) |
176 | continue; |
177 | |
178 | match = strcmp((char *)path.pointer, override_status_ids[i].path) == 0; |
179 | kfree(objp: path.pointer); |
180 | |
181 | if (!match) |
182 | continue; |
183 | } else { |
184 | if (acpi_match_device_ids(device: adev, ids: override_status_ids[i].hid)) |
185 | continue; |
186 | |
187 | if (!acpi_dev_uid_match(adev, override_status_ids[i].uid)) |
188 | continue; |
189 | } |
190 | |
191 | *status = override_status_ids[i].status; |
192 | ret = true; |
193 | break; |
194 | } |
195 | |
196 | return ret; |
197 | } |
198 | |
199 | /* |
200 | * AMD systems from Renoir and Lucienne *require* that the NVME controller |
201 | * is put into D3 over a Modern Standby / suspend-to-idle cycle. |
202 | * |
203 | * This is "typically" accomplished using the `StorageD3Enable` |
204 | * property in the _DSD that is checked via the `acpi_storage_d3` function |
205 | * but this property was introduced after many of these systems launched |
206 | * and most OEM systems don't have it in their BIOS. |
207 | * |
208 | * The Microsoft documentation for StorageD3Enable mentioned that Windows has |
209 | * a hardcoded allowlist for D3 support, which was used for these platforms. |
210 | * |
211 | * This allows quirking on Linux in a similar fashion. |
212 | * |
213 | * Cezanne systems shouldn't *normally* need this as the BIOS includes |
214 | * StorageD3Enable. But for two reasons we have added it. |
215 | * 1) The BIOS on a number of Dell systems have ambiguity |
216 | * between the same value used for _ADR on ACPI nodes GPP1.DEV0 and GPP1.NVME. |
217 | * GPP1.NVME is needed to get StorageD3Enable node set properly. |
218 | * https://bugzilla.kernel.org/show_bug.cgi?id=216440 |
219 | * https://bugzilla.kernel.org/show_bug.cgi?id=216773 |
220 | * https://bugzilla.kernel.org/show_bug.cgi?id=217003 |
221 | * 2) On at least one HP system StorageD3Enable is missing on the second NVME |
222 | disk in the system. |
223 | */ |
224 | static const struct x86_cpu_id storage_d3_cpu_ids[] = { |
225 | X86_MATCH_VENDOR_FAM_MODEL(AMD, 23, 24, NULL), /* Picasso */ |
226 | X86_MATCH_VENDOR_FAM_MODEL(AMD, 23, 96, NULL), /* Renoir */ |
227 | X86_MATCH_VENDOR_FAM_MODEL(AMD, 23, 104, NULL), /* Lucienne */ |
228 | X86_MATCH_VENDOR_FAM_MODEL(AMD, 25, 80, NULL), /* Cezanne */ |
229 | {} |
230 | }; |
231 | |
232 | bool force_storage_d3(void) |
233 | { |
234 | return x86_match_cpu(match: storage_d3_cpu_ids); |
235 | } |
236 | |
237 | /* |
238 | * x86 ACPI boards which ship with only Android as their factory image usually |
239 | * declare a whole bunch of bogus I2C devices in their ACPI tables and sometimes |
240 | * there are issues with serdev devices on these boards too, e.g. the resource |
241 | * points to the wrong serdev_controller. |
242 | * |
243 | * Instantiating I2C / serdev devs for these bogus devs causes various issues, |
244 | * e.g. GPIO/IRQ resource conflicts because sometimes drivers do bind to them. |
245 | * The Android x86 kernel fork shipped on these devices has some special code |
246 | * to remove the bogus I2C clients (and AFAICT serdevs are ignored completely). |
247 | * |
248 | * The acpi_quirk_skip_*_enumeration() functions below are used by the I2C or |
249 | * serdev code to skip instantiating any I2C or serdev devs on broken boards. |
250 | * |
251 | * In case of I2C an exception is made for HIDs on the i2c_acpi_known_good_ids |
252 | * list. These are known to always be correct (and in case of the audio-codecs |
253 | * the drivers heavily rely on the codec being enumerated through ACPI). |
254 | * |
255 | * Note these boards typically do actually have I2C and serdev devices, |
256 | * just different ones then the ones described in their DSDT. The devices |
257 | * which are actually present are manually instantiated by the |
258 | * drivers/platform/x86/x86-android-tablets.c kernel module. |
259 | */ |
260 | #define ACPI_QUIRK_SKIP_I2C_CLIENTS BIT(0) |
261 | #define ACPI_QUIRK_UART1_SKIP BIT(1) |
262 | #define ACPI_QUIRK_UART1_TTY_UART2_SKIP BIT(2) |
263 | #define ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY BIT(3) |
264 | #define ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY BIT(4) |
265 | #define ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS BIT(5) |
266 | |
267 | static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = { |
268 | /* |
269 | * 1. Devices with only the skip / don't-skip AC and battery quirks, |
270 | * sorted alphabetically. |
271 | */ |
272 | { |
273 | /* ECS EF20EA, AXP288 PMIC but uses separate fuel-gauge */ |
274 | .matches = { |
275 | DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA" ), |
276 | }, |
277 | .driver_data = (void *)ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY |
278 | }, |
279 | { |
280 | /* Lenovo Ideapad Miix 320, AXP288 PMIC, separate fuel-gauge */ |
281 | .matches = { |
282 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO" ), |
283 | DMI_MATCH(DMI_PRODUCT_NAME, "80XF" ), |
284 | DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR" ), |
285 | }, |
286 | .driver_data = (void *)ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY |
287 | }, |
288 | |
289 | /* |
290 | * 2. Devices which also have the skip i2c/serdev quirks and which |
291 | * need the x86-android-tablets module to properly work. |
292 | */ |
293 | #if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS) |
294 | { |
295 | /* Acer Iconia One 7 B1-750 */ |
296 | .matches = { |
297 | DMI_MATCH(DMI_SYS_VENDOR, "Insyde" ), |
298 | DMI_MATCH(DMI_PRODUCT_NAME, "VESPA2" ), |
299 | }, |
300 | .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | |
301 | ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY | |
302 | ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS), |
303 | }, |
304 | { |
305 | .matches = { |
306 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC." ), |
307 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ME176C" ), |
308 | }, |
309 | .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | |
310 | ACPI_QUIRK_UART1_TTY_UART2_SKIP | |
311 | ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY | |
312 | ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS), |
313 | }, |
314 | { |
315 | /* Lenovo Yoga Book X90F/L */ |
316 | .matches = { |
317 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel Corporation" ), |
318 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM" ), |
319 | DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "YETI-11" ), |
320 | }, |
321 | .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | |
322 | ACPI_QUIRK_UART1_SKIP | |
323 | ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY | |
324 | ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS), |
325 | }, |
326 | { |
327 | .matches = { |
328 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC." ), |
329 | DMI_MATCH(DMI_PRODUCT_NAME, "TF103C" ), |
330 | }, |
331 | .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | |
332 | ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY | |
333 | ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS), |
334 | }, |
335 | { |
336 | /* Lenovo Yoga Tablet 2 1050F/L */ |
337 | .matches = { |
338 | DMI_MATCH(DMI_SYS_VENDOR, "Intel Corp." ), |
339 | DMI_MATCH(DMI_PRODUCT_NAME, "VALLEYVIEW C0 PLATFORM" ), |
340 | DMI_MATCH(DMI_BOARD_NAME, "BYT-T FFD8" ), |
341 | /* Partial match on beginning of BIOS version */ |
342 | DMI_MATCH(DMI_BIOS_VERSION, "BLADE_21" ), |
343 | }, |
344 | .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | |
345 | ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY), |
346 | }, |
347 | { |
348 | /* Lenovo Yoga Tab 3 Pro X90F */ |
349 | .matches = { |
350 | DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation" ), |
351 | DMI_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM" ), |
352 | DMI_MATCH(DMI_PRODUCT_VERSION, "Blade3-10A-001" ), |
353 | }, |
354 | .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | |
355 | ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY), |
356 | }, |
357 | { |
358 | /* Medion Lifetab S10346 */ |
359 | .matches = { |
360 | DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation" ), |
361 | DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB" ), |
362 | /* Way too generic, also match on BIOS data */ |
363 | DMI_MATCH(DMI_BIOS_DATE, "10/22/2015" ), |
364 | }, |
365 | .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | |
366 | ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY), |
367 | }, |
368 | { |
369 | /* Nextbook Ares 8 (BYT version)*/ |
370 | .matches = { |
371 | DMI_MATCH(DMI_SYS_VENDOR, "Insyde" ), |
372 | DMI_MATCH(DMI_PRODUCT_NAME, "M890BAP" ), |
373 | }, |
374 | .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | |
375 | ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY | |
376 | ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS), |
377 | }, |
378 | { |
379 | /* Nextbook Ares 8A (CHT version)*/ |
380 | .matches = { |
381 | DMI_MATCH(DMI_SYS_VENDOR, "Insyde" ), |
382 | DMI_MATCH(DMI_PRODUCT_NAME, "CherryTrail" ), |
383 | DMI_MATCH(DMI_BIOS_VERSION, "M882" ), |
384 | }, |
385 | .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | |
386 | ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY), |
387 | }, |
388 | { |
389 | /* Whitelabel (sold as various brands) TM800A550L */ |
390 | .matches = { |
391 | DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation" ), |
392 | DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB" ), |
393 | /* Above strings are too generic, also match on BIOS version */ |
394 | DMI_MATCH(DMI_BIOS_VERSION, "ZY-8-BI-PX4S70VTR400-X423B-005-D" ), |
395 | }, |
396 | .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS | |
397 | ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY), |
398 | }, |
399 | #endif |
400 | {} |
401 | }; |
402 | |
403 | #if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS) |
404 | static const struct acpi_device_id i2c_acpi_known_good_ids[] = { |
405 | { "10EC5640" , 0 }, /* RealTek ALC5640 audio codec */ |
406 | { "10EC5651" , 0 }, /* RealTek ALC5651 audio codec */ |
407 | { "INT33F4" , 0 }, /* X-Powers AXP288 PMIC */ |
408 | { "INT33FD" , 0 }, /* Intel Crystal Cove PMIC */ |
409 | { "INT34D3" , 0 }, /* Intel Whiskey Cove PMIC */ |
410 | { "NPCE69A" , 0 }, /* Asus Transformer keyboard dock */ |
411 | {} |
412 | }; |
413 | |
414 | bool acpi_quirk_skip_i2c_client_enumeration(struct acpi_device *adev) |
415 | { |
416 | const struct dmi_system_id *dmi_id; |
417 | long quirks; |
418 | |
419 | dmi_id = dmi_first_match(list: acpi_quirk_skip_dmi_ids); |
420 | if (!dmi_id) |
421 | return false; |
422 | |
423 | quirks = (unsigned long)dmi_id->driver_data; |
424 | if (!(quirks & ACPI_QUIRK_SKIP_I2C_CLIENTS)) |
425 | return false; |
426 | |
427 | return acpi_match_device_ids(device: adev, ids: i2c_acpi_known_good_ids); |
428 | } |
429 | EXPORT_SYMBOL_GPL(acpi_quirk_skip_i2c_client_enumeration); |
430 | |
431 | static int acpi_dmi_skip_serdev_enumeration(struct device *controller_parent, bool *skip) |
432 | { |
433 | struct acpi_device *adev = ACPI_COMPANION(controller_parent); |
434 | const struct dmi_system_id *dmi_id; |
435 | long quirks = 0; |
436 | u64 uid; |
437 | int ret; |
438 | |
439 | ret = acpi_dev_uid_to_integer(adev, integer: &uid); |
440 | if (ret) |
441 | return 0; |
442 | |
443 | /* to not match on PNP enumerated debug UARTs */ |
444 | if (!dev_is_platform(controller_parent)) |
445 | return 0; |
446 | |
447 | dmi_id = dmi_first_match(list: acpi_quirk_skip_dmi_ids); |
448 | if (dmi_id) |
449 | quirks = (unsigned long)dmi_id->driver_data; |
450 | |
451 | if ((quirks & ACPI_QUIRK_UART1_SKIP) && uid == 1) |
452 | *skip = true; |
453 | |
454 | if (quirks & ACPI_QUIRK_UART1_TTY_UART2_SKIP) { |
455 | if (uid == 1) |
456 | return -ENODEV; /* Create tty cdev instead of serdev */ |
457 | |
458 | if (uid == 2) |
459 | *skip = true; |
460 | } |
461 | |
462 | return 0; |
463 | } |
464 | |
465 | bool acpi_quirk_skip_gpio_event_handlers(void) |
466 | { |
467 | const struct dmi_system_id *dmi_id; |
468 | long quirks; |
469 | |
470 | dmi_id = dmi_first_match(list: acpi_quirk_skip_dmi_ids); |
471 | if (!dmi_id) |
472 | return false; |
473 | |
474 | quirks = (unsigned long)dmi_id->driver_data; |
475 | return (quirks & ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS); |
476 | } |
477 | EXPORT_SYMBOL_GPL(acpi_quirk_skip_gpio_event_handlers); |
478 | #else |
479 | static int acpi_dmi_skip_serdev_enumeration(struct device *controller_parent, bool *skip) |
480 | { |
481 | return 0; |
482 | } |
483 | #endif |
484 | |
485 | int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip) |
486 | { |
487 | struct acpi_device *adev = ACPI_COMPANION(controller_parent); |
488 | |
489 | *skip = false; |
490 | |
491 | /* |
492 | * The DELL0501 ACPI HID represents an UART (CID is set to PNP0501) with |
493 | * a backlight-controller attached. There is no separate ACPI device with |
494 | * an UartSerialBusV2() resource to model the backlight-controller. |
495 | * Set skip to true so that the tty core creates a serdev ctrl device. |
496 | * The backlight driver will manually create the serdev client device. |
497 | */ |
498 | if (acpi_dev_hid_match(adev, hid2: "DELL0501" )) { |
499 | *skip = true; |
500 | /* |
501 | * Create a platform dev for dell-uart-backlight to bind to. |
502 | * This is a static device, so no need to store the result. |
503 | */ |
504 | platform_device_register_simple(name: "dell-uart-backlight" , PLATFORM_DEVID_NONE, |
505 | NULL, num: 0); |
506 | return 0; |
507 | } |
508 | |
509 | return acpi_dmi_skip_serdev_enumeration(controller_parent, skip); |
510 | } |
511 | EXPORT_SYMBOL_GPL(acpi_quirk_skip_serdev_enumeration); |
512 | |
513 | /* Lists of PMIC ACPI HIDs with an (often better) native charger driver */ |
514 | static const struct { |
515 | const char *hid; |
516 | int hrv; |
517 | } acpi_skip_ac_and_battery_pmic_ids[] = { |
518 | { "INT33F4" , -1 }, /* X-Powers AXP288 PMIC */ |
519 | { "INT34D3" , 3 }, /* Intel Cherrytrail Whiskey Cove PMIC */ |
520 | }; |
521 | |
522 | bool acpi_quirk_skip_acpi_ac_and_battery(void) |
523 | { |
524 | const struct dmi_system_id *dmi_id; |
525 | long quirks = 0; |
526 | int i; |
527 | |
528 | dmi_id = dmi_first_match(list: acpi_quirk_skip_dmi_ids); |
529 | if (dmi_id) |
530 | quirks = (unsigned long)dmi_id->driver_data; |
531 | |
532 | if (quirks & ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY) |
533 | return true; |
534 | |
535 | if (quirks & ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY) |
536 | return false; |
537 | |
538 | for (i = 0; i < ARRAY_SIZE(acpi_skip_ac_and_battery_pmic_ids); i++) { |
539 | if (acpi_dev_present(hid: acpi_skip_ac_and_battery_pmic_ids[i].hid, uid: "1" , |
540 | hrv: acpi_skip_ac_and_battery_pmic_ids[i].hrv)) { |
541 | pr_info_once("found native %s PMIC, skipping ACPI AC and battery devices\n" , |
542 | acpi_skip_ac_and_battery_pmic_ids[i].hid); |
543 | return true; |
544 | } |
545 | } |
546 | |
547 | return false; |
548 | } |
549 | EXPORT_SYMBOL_GPL(acpi_quirk_skip_acpi_ac_and_battery); |
550 | |
551 | /* This section provides a workaround for a specific x86 system |
552 | * which requires disabling of mwait to work correctly. |
553 | */ |
554 | static int __init acpi_proc_quirk_set_no_mwait(const struct dmi_system_id *id) |
555 | { |
556 | pr_notice("%s detected - disabling mwait for CPU C-states\n" , |
557 | id->ident); |
558 | boot_option_idle_override = IDLE_NOMWAIT; |
559 | return 0; |
560 | } |
561 | |
562 | static const struct dmi_system_id acpi_proc_quirk_mwait_dmi_table[] __initconst = { |
563 | { |
564 | .callback = acpi_proc_quirk_set_no_mwait, |
565 | .ident = "Extensa 5220" , |
566 | .matches = { |
567 | DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD" ), |
568 | DMI_MATCH(DMI_SYS_VENDOR, "Acer" ), |
569 | DMI_MATCH(DMI_PRODUCT_VERSION, "0100" ), |
570 | DMI_MATCH(DMI_BOARD_NAME, "Columbia" ), |
571 | }, |
572 | .driver_data = NULL, |
573 | }, |
574 | {} |
575 | }; |
576 | |
577 | void __init acpi_proc_quirk_mwait_check(void) |
578 | { |
579 | /* |
580 | * Check whether the system is DMI table. If yes, OSPM |
581 | * should not use mwait for CPU-states. |
582 | */ |
583 | dmi_check_system(list: acpi_proc_quirk_mwait_dmi_table); |
584 | } |
585 | |