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