xref: /openbmc/linux/drivers/acpi/x86/utils.c (revision b7ecf663c75eed1e764f57281f9508c49c18516e)
1*b7ecf663SHans de Goede /*
2*b7ecf663SHans de Goede  * X86 ACPI Utility Functions
3*b7ecf663SHans de Goede  *
4*b7ecf663SHans de Goede  * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
5*b7ecf663SHans de Goede  *
6*b7ecf663SHans de Goede  * Based on various non upstream patches to support the CHT Whiskey Cove PMIC:
7*b7ecf663SHans de Goede  * Copyright (C) 2013-2015 Intel Corporation. All rights reserved.
8*b7ecf663SHans de Goede  *
9*b7ecf663SHans de Goede  * This program is free software; you can redistribute it and/or modify
10*b7ecf663SHans de Goede  * it under the terms of the GNU General Public License version 2 as
11*b7ecf663SHans de Goede  * published by the Free Software Foundation.
12*b7ecf663SHans de Goede  */
13*b7ecf663SHans de Goede 
14*b7ecf663SHans de Goede #include <linux/acpi.h>
15*b7ecf663SHans de Goede #include <asm/cpu_device_id.h>
16*b7ecf663SHans de Goede #include <asm/intel-family.h>
17*b7ecf663SHans de Goede #include "../internal.h"
18*b7ecf663SHans de Goede 
19*b7ecf663SHans de Goede /*
20*b7ecf663SHans de Goede  * Some ACPI devices are hidden (status == 0x0) in recent BIOS-es because
21*b7ecf663SHans de Goede  * some recent Windows drivers bind to one device but poke at multiple
22*b7ecf663SHans de Goede  * devices at the same time, so the others get hidden.
23*b7ecf663SHans de Goede  * We work around this by always reporting ACPI_STA_DEFAULT for these
24*b7ecf663SHans de Goede  * devices. Note this MUST only be done for devices where this is safe.
25*b7ecf663SHans de Goede  *
26*b7ecf663SHans de Goede  * This forcing of devices to be present is limited to specific CPU (SoC)
27*b7ecf663SHans de Goede  * models both to avoid potentially causing trouble on other models and
28*b7ecf663SHans de Goede  * because some HIDs are re-used on different SoCs for completely
29*b7ecf663SHans de Goede  * different devices.
30*b7ecf663SHans de Goede  */
31*b7ecf663SHans de Goede struct always_present_id {
32*b7ecf663SHans de Goede 	struct acpi_device_id hid[2];
33*b7ecf663SHans de Goede 	struct x86_cpu_id cpu_ids[2];
34*b7ecf663SHans de Goede 	const char *uid;
35*b7ecf663SHans de Goede };
36*b7ecf663SHans de Goede 
37*b7ecf663SHans de Goede #define ICPU(model)	{ X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, }
38*b7ecf663SHans de Goede 
39*b7ecf663SHans de Goede #define ENTRY(hid, uid, cpu_models) {					\
40*b7ecf663SHans de Goede 	{ { hid, }, {} },						\
41*b7ecf663SHans de Goede 	{ cpu_models, {} },						\
42*b7ecf663SHans de Goede 	uid,								\
43*b7ecf663SHans de Goede }
44*b7ecf663SHans de Goede 
45*b7ecf663SHans de Goede static const struct always_present_id always_present_ids[] = {
46*b7ecf663SHans de Goede 	/*
47*b7ecf663SHans de Goede 	 * Bay / Cherry Trail PWM directly poked by GPU driver in win10,
48*b7ecf663SHans de Goede 	 * but Linux uses a separate PWM driver, harmless if not used.
49*b7ecf663SHans de Goede 	 */
50*b7ecf663SHans de Goede 	ENTRY("80860F09", "1", ICPU(INTEL_FAM6_ATOM_SILVERMONT1)),
51*b7ecf663SHans de Goede 	ENTRY("80862288", "1", ICPU(INTEL_FAM6_ATOM_AIRMONT)),
52*b7ecf663SHans de Goede };
53*b7ecf663SHans de Goede 
54*b7ecf663SHans de Goede bool acpi_device_always_present(struct acpi_device *adev)
55*b7ecf663SHans de Goede {
56*b7ecf663SHans de Goede 	u32 *status = (u32 *)&adev->status;
57*b7ecf663SHans de Goede 	u32 old_status = *status;
58*b7ecf663SHans de Goede 	bool ret = false;
59*b7ecf663SHans de Goede 	unsigned int i;
60*b7ecf663SHans de Goede 
61*b7ecf663SHans de Goede 	/* acpi_match_device_ids checks status, so set it to default */
62*b7ecf663SHans de Goede 	*status = ACPI_STA_DEFAULT;
63*b7ecf663SHans de Goede 	for (i = 0; i < ARRAY_SIZE(always_present_ids); i++) {
64*b7ecf663SHans de Goede 		if (acpi_match_device_ids(adev, always_present_ids[i].hid))
65*b7ecf663SHans de Goede 			continue;
66*b7ecf663SHans de Goede 
67*b7ecf663SHans de Goede 		if (!adev->pnp.unique_id ||
68*b7ecf663SHans de Goede 		    strcmp(adev->pnp.unique_id, always_present_ids[i].uid))
69*b7ecf663SHans de Goede 			continue;
70*b7ecf663SHans de Goede 
71*b7ecf663SHans de Goede 		if (!x86_match_cpu(always_present_ids[i].cpu_ids))
72*b7ecf663SHans de Goede 			continue;
73*b7ecf663SHans de Goede 
74*b7ecf663SHans de Goede 		if (old_status != ACPI_STA_DEFAULT) /* Log only once */
75*b7ecf663SHans de Goede 			dev_info(&adev->dev,
76*b7ecf663SHans de Goede 				 "Device [%s] is in always present list\n",
77*b7ecf663SHans de Goede 				 adev->pnp.bus_id);
78*b7ecf663SHans de Goede 
79*b7ecf663SHans de Goede 		ret = true;
80*b7ecf663SHans de Goede 		break;
81*b7ecf663SHans de Goede 	}
82*b7ecf663SHans de Goede 	*status = old_status;
83*b7ecf663SHans de Goede 
84*b7ecf663SHans de Goede 	return ret;
85*b7ecf663SHans de Goede }
86