utils.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  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 <linux/dmi.h>
  15. #include <asm/cpu_device_id.h>
  16. #include <asm/intel-family.h>
  17. #include "../internal.h"
  18. /*
  19. * Some ACPI devices are hidden (status == 0x0) in recent BIOS-es because
  20. * some recent Windows drivers bind to one device but poke at multiple
  21. * devices at the same time, so the others get hidden.
  22. *
  23. * Some BIOS-es (temporarily) hide specific APCI devices to work around Windows
  24. * driver bugs. We use DMI matching to match known cases of this.
  25. *
  26. * We work around this by always reporting ACPI_STA_DEFAULT for these
  27. * devices. Note this MUST only be done for devices where this is safe.
  28. *
  29. * This forcing of devices to be present is limited to specific CPU (SoC)
  30. * models both to avoid potentially causing trouble on other models and
  31. * because some HIDs are re-used on different SoCs for completely
  32. * different devices.
  33. */
  34. struct always_present_id {
  35. struct acpi_device_id hid[2];
  36. struct x86_cpu_id cpu_ids[2];
  37. struct dmi_system_id dmi_ids[2]; /* Optional */
  38. const char *uid;
  39. };
  40. #define ICPU(model) { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, }
  41. #define ENTRY(hid, uid, cpu_models, dmi...) { \
  42. { { hid, }, {} }, \
  43. { cpu_models, {} }, \
  44. { { .matches = dmi }, {} }, \
  45. uid, \
  46. }
  47. static const struct always_present_id always_present_ids[] = {
  48. /*
  49. * Bay / Cherry Trail PWM directly poked by GPU driver in win10,
  50. * but Linux uses a separate PWM driver, harmless if not used.
  51. */
  52. ENTRY("80860F09", "1", ICPU(INTEL_FAM6_ATOM_SILVERMONT1), {}),
  53. ENTRY("80862288", "1", ICPU(INTEL_FAM6_ATOM_AIRMONT), {}),
  54. /*
  55. * The INT0002 device is necessary to clear wakeup interrupt sources
  56. * on Cherry Trail devices, without it we get nobody cared IRQ msgs.
  57. */
  58. ENTRY("INT0002", "1", ICPU(INTEL_FAM6_ATOM_AIRMONT), {}),
  59. /*
  60. * On the Dell Venue 11 Pro 7130 the DSDT hides the touchscreen ACPI
  61. * device until a certain time after _SB.PCI0.GFX0.LCD.LCD1._ON gets
  62. * called has passed *and* _STA has been called at least 3 times since.
  63. */
  64. ENTRY("SYNA7500", "1", ICPU(INTEL_FAM6_HASWELL_ULT), {
  65. DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
  66. DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7130"),
  67. }),
  68. /*
  69. * The GPD win BIOS dated 20170320 has disabled the accelerometer, the
  70. * drivers sometimes cause crashes under Windows and this is how the
  71. * manufacturer has solved this :| Note that the the DMI data is less
  72. * generic then it seems, a board_vendor of "AMI Corporation" is quite
  73. * rare and a board_name of "Default String" also is rare.
  74. */
  75. ENTRY("KIOX000A", "1", ICPU(INTEL_FAM6_ATOM_AIRMONT), {
  76. DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
  77. DMI_MATCH(DMI_BOARD_NAME, "Default string"),
  78. DMI_MATCH(DMI_PRODUCT_NAME, "Default string"),
  79. DMI_MATCH(DMI_BIOS_DATE, "03/20/2017")
  80. }),
  81. };
  82. bool acpi_device_always_present(struct acpi_device *adev)
  83. {
  84. u32 *status = (u32 *)&adev->status;
  85. u32 old_status = *status;
  86. bool ret = false;
  87. unsigned int i;
  88. /* acpi_match_device_ids checks status, so set it to default */
  89. *status = ACPI_STA_DEFAULT;
  90. for (i = 0; i < ARRAY_SIZE(always_present_ids); i++) {
  91. if (acpi_match_device_ids(adev, always_present_ids[i].hid))
  92. continue;
  93. if (!adev->pnp.unique_id ||
  94. strcmp(adev->pnp.unique_id, always_present_ids[i].uid))
  95. continue;
  96. if (!x86_match_cpu(always_present_ids[i].cpu_ids))
  97. continue;
  98. if (always_present_ids[i].dmi_ids[0].matches[0].slot &&
  99. !dmi_check_system(always_present_ids[i].dmi_ids))
  100. continue;
  101. if (old_status != ACPI_STA_DEFAULT) /* Log only once */
  102. dev_info(&adev->dev,
  103. "Device [%s] is in always present list\n",
  104. adev->pnp.bus_id);
  105. ret = true;
  106. break;
  107. }
  108. *status = old_status;
  109. return ret;
  110. }