utils.c 2.7 KB

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