1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * AMD SoC Power Management Controller Driver Quirks
5 * Copyright (c) 2023, Advanced Micro Devices, Inc.
8 * Author: Mario Limonciello <mario.limonciello@amd.com>
11 #include <linux/dmi.h>
13 #include <linux/ioport.h>
21 static struct quirk_entry quirk_s2idle_bug = {
22 .s2idle_bug_mmio = 0xfed80380,
25 static const struct dmi_system_id fwbug_list[] = {
27 .ident = "L14 Gen2 AMD",
28 .driver_data = &quirk_s2idle_bug,
30 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
31 DMI_MATCH(DMI_PRODUCT_NAME, "20X5"),
35 .ident = "T14s Gen2 AMD",
36 .driver_data = &quirk_s2idle_bug,
38 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
39 DMI_MATCH(DMI_PRODUCT_NAME, "20XF"),
43 .ident = "X13 Gen2 AMD",
44 .driver_data = &quirk_s2idle_bug,
46 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
47 DMI_MATCH(DMI_PRODUCT_NAME, "20XH"),
51 .ident = "T14 Gen2 AMD",
52 .driver_data = &quirk_s2idle_bug,
54 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
55 DMI_MATCH(DMI_PRODUCT_NAME, "20XK"),
59 .ident = "T14 Gen1 AMD",
60 .driver_data = &quirk_s2idle_bug,
62 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
63 DMI_MATCH(DMI_PRODUCT_NAME, "20UD"),
67 .ident = "T14 Gen1 AMD",
68 .driver_data = &quirk_s2idle_bug,
70 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
71 DMI_MATCH(DMI_PRODUCT_NAME, "20UE"),
75 .ident = "T14s Gen1 AMD",
76 .driver_data = &quirk_s2idle_bug,
78 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
79 DMI_MATCH(DMI_PRODUCT_NAME, "20UH"),
83 .ident = "T14s Gen1 AMD",
84 .driver_data = &quirk_s2idle_bug,
86 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
87 DMI_MATCH(DMI_PRODUCT_NAME, "20UJ"),
91 .ident = "P14s Gen1 AMD",
92 .driver_data = &quirk_s2idle_bug,
94 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
95 DMI_MATCH(DMI_PRODUCT_NAME, "20Y1"),
99 .ident = "P14s Gen2 AMD",
100 .driver_data = &quirk_s2idle_bug,
102 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
103 DMI_MATCH(DMI_PRODUCT_NAME, "21A0"),
107 .ident = "P14s Gen2 AMD",
108 .driver_data = &quirk_s2idle_bug,
110 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
111 DMI_MATCH(DMI_PRODUCT_NAME, "21A1"),
114 /* https://gitlab.freedesktop.org/drm/amd/-/issues/2684 */
116 .ident = "HP Laptop 15s-eq2xxx",
117 .driver_data = &quirk_s2idle_bug,
119 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
120 DMI_MATCH(DMI_PRODUCT_NAME, "HP Laptop 15s-eq2xxx"),
127 * Laptops that run a SMI handler during the D3->D0 transition that occurs
128 * specifically when exiting suspend to idle which can cause
129 * large delays during resume when the IOMMU translation layer is enabled (the default
130 * behavior) for NVME devices:
132 * To avoid this firmware problem, skip the SMI handler on these machines before the
133 * D0 transition occurs.
135 static void amd_pmc_skip_nvme_smi_handler(u32 s2idle_bug_mmio)
140 if (!request_mem_region_muxed(s2idle_bug_mmio, 1, "amd_pmc_pm80"))
143 addr = ioremap(s2idle_bug_mmio, 1);
145 goto cleanup_resource;
148 iowrite8(val & ~BIT(0), addr);
152 release_mem_region(s2idle_bug_mmio, 1);
155 void amd_pmc_process_restore_quirks(struct amd_pmc_dev *dev)
157 if (dev->quirks && dev->quirks->s2idle_bug_mmio)
158 amd_pmc_skip_nvme_smi_handler(dev->quirks->s2idle_bug_mmio);
161 void amd_pmc_quirks_init(struct amd_pmc_dev *dev)
163 const struct dmi_system_id *dmi_id;
165 dmi_id = dmi_first_match(fwbug_list);
168 dev->quirks = dmi_id->driver_data;
169 if (dev->quirks->s2idle_bug_mmio)
170 pr_info("Using s2idle quirk to avoid %s platform firmware bug\n",