]> git.ipfire.org Git - thirdparty/kernel/stable.git/blob - drivers/platform/x86/amd/pmc/pmc-quirks.c
Merge tag 'kvm-x86-mmu-6.7' of https://github.com/kvm-x86/linux into HEAD
[thirdparty/kernel/stable.git] / drivers / platform / x86 / amd / pmc / pmc-quirks.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * AMD SoC Power Management Controller Driver Quirks
4 *
5 * Copyright (c) 2023, Advanced Micro Devices, Inc.
6 * All Rights Reserved.
7 *
8 * Author: Mario Limonciello <mario.limonciello@amd.com>
9 */
10
11 #include <linux/dmi.h>
12 #include <linux/io.h>
13 #include <linux/ioport.h>
14
15 #include "pmc.h"
16
17 struct quirk_entry {
18 u32 s2idle_bug_mmio;
19 };
20
21 static struct quirk_entry quirk_s2idle_bug = {
22 .s2idle_bug_mmio = 0xfed80380,
23 };
24
25 static const struct dmi_system_id fwbug_list[] = {
26 {
27 .ident = "L14 Gen2 AMD",
28 .driver_data = &quirk_s2idle_bug,
29 .matches = {
30 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
31 DMI_MATCH(DMI_PRODUCT_NAME, "20X5"),
32 }
33 },
34 {
35 .ident = "T14s Gen2 AMD",
36 .driver_data = &quirk_s2idle_bug,
37 .matches = {
38 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
39 DMI_MATCH(DMI_PRODUCT_NAME, "20XF"),
40 }
41 },
42 {
43 .ident = "X13 Gen2 AMD",
44 .driver_data = &quirk_s2idle_bug,
45 .matches = {
46 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
47 DMI_MATCH(DMI_PRODUCT_NAME, "20XH"),
48 }
49 },
50 {
51 .ident = "T14 Gen2 AMD",
52 .driver_data = &quirk_s2idle_bug,
53 .matches = {
54 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
55 DMI_MATCH(DMI_PRODUCT_NAME, "20XK"),
56 }
57 },
58 {
59 .ident = "T14 Gen1 AMD",
60 .driver_data = &quirk_s2idle_bug,
61 .matches = {
62 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
63 DMI_MATCH(DMI_PRODUCT_NAME, "20UD"),
64 }
65 },
66 {
67 .ident = "T14 Gen1 AMD",
68 .driver_data = &quirk_s2idle_bug,
69 .matches = {
70 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
71 DMI_MATCH(DMI_PRODUCT_NAME, "20UE"),
72 }
73 },
74 {
75 .ident = "T14s Gen1 AMD",
76 .driver_data = &quirk_s2idle_bug,
77 .matches = {
78 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
79 DMI_MATCH(DMI_PRODUCT_NAME, "20UH"),
80 }
81 },
82 {
83 .ident = "T14s Gen1 AMD",
84 .driver_data = &quirk_s2idle_bug,
85 .matches = {
86 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
87 DMI_MATCH(DMI_PRODUCT_NAME, "20UJ"),
88 }
89 },
90 {
91 .ident = "P14s Gen1 AMD",
92 .driver_data = &quirk_s2idle_bug,
93 .matches = {
94 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
95 DMI_MATCH(DMI_PRODUCT_NAME, "20Y1"),
96 }
97 },
98 {
99 .ident = "P14s Gen2 AMD",
100 .driver_data = &quirk_s2idle_bug,
101 .matches = {
102 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
103 DMI_MATCH(DMI_PRODUCT_NAME, "21A0"),
104 }
105 },
106 {
107 .ident = "P14s Gen2 AMD",
108 .driver_data = &quirk_s2idle_bug,
109 .matches = {
110 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
111 DMI_MATCH(DMI_PRODUCT_NAME, "21A1"),
112 }
113 },
114 /* https://bugzilla.kernel.org/show_bug.cgi?id=218024 */
115 {
116 .ident = "V14 G4 AMN",
117 .driver_data = &quirk_s2idle_bug,
118 .matches = {
119 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
120 DMI_MATCH(DMI_PRODUCT_NAME, "82YT"),
121 }
122 },
123 {
124 .ident = "V14 G4 AMN",
125 .driver_data = &quirk_s2idle_bug,
126 .matches = {
127 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
128 DMI_MATCH(DMI_PRODUCT_NAME, "83GE"),
129 }
130 },
131 {
132 .ident = "V15 G4 AMN",
133 .driver_data = &quirk_s2idle_bug,
134 .matches = {
135 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
136 DMI_MATCH(DMI_PRODUCT_NAME, "82YU"),
137 }
138 },
139 {
140 .ident = "V15 G4 AMN",
141 .driver_data = &quirk_s2idle_bug,
142 .matches = {
143 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
144 DMI_MATCH(DMI_PRODUCT_NAME, "83CQ"),
145 }
146 },
147 {
148 .ident = "IdeaPad 1 14AMN7",
149 .driver_data = &quirk_s2idle_bug,
150 .matches = {
151 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
152 DMI_MATCH(DMI_PRODUCT_NAME, "82VF"),
153 }
154 },
155 {
156 .ident = "IdeaPad 1 15AMN7",
157 .driver_data = &quirk_s2idle_bug,
158 .matches = {
159 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
160 DMI_MATCH(DMI_PRODUCT_NAME, "82VG"),
161 }
162 },
163 {
164 .ident = "IdeaPad 1 15AMN7",
165 .driver_data = &quirk_s2idle_bug,
166 .matches = {
167 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
168 DMI_MATCH(DMI_PRODUCT_NAME, "82X5"),
169 }
170 },
171 {
172 .ident = "IdeaPad Slim 3 14AMN8",
173 .driver_data = &quirk_s2idle_bug,
174 .matches = {
175 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
176 DMI_MATCH(DMI_PRODUCT_NAME, "82XN"),
177 }
178 },
179 {
180 .ident = "IdeaPad Slim 3 15AMN8",
181 .driver_data = &quirk_s2idle_bug,
182 .matches = {
183 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
184 DMI_MATCH(DMI_PRODUCT_NAME, "82XQ"),
185 }
186 },
187 /* https://gitlab.freedesktop.org/drm/amd/-/issues/2684 */
188 {
189 .ident = "HP Laptop 15s-eq2xxx",
190 .driver_data = &quirk_s2idle_bug,
191 .matches = {
192 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
193 DMI_MATCH(DMI_PRODUCT_NAME, "HP Laptop 15s-eq2xxx"),
194 }
195 },
196 {}
197 };
198
199 /*
200 * Laptops that run a SMI handler during the D3->D0 transition that occurs
201 * specifically when exiting suspend to idle which can cause
202 * large delays during resume when the IOMMU translation layer is enabled (the default
203 * behavior) for NVME devices:
204 *
205 * To avoid this firmware problem, skip the SMI handler on these machines before the
206 * D0 transition occurs.
207 */
208 static void amd_pmc_skip_nvme_smi_handler(u32 s2idle_bug_mmio)
209 {
210 void __iomem *addr;
211 u8 val;
212
213 if (!request_mem_region_muxed(s2idle_bug_mmio, 1, "amd_pmc_pm80"))
214 return;
215
216 addr = ioremap(s2idle_bug_mmio, 1);
217 if (!addr)
218 goto cleanup_resource;
219
220 val = ioread8(addr);
221 iowrite8(val & ~BIT(0), addr);
222
223 iounmap(addr);
224 cleanup_resource:
225 release_mem_region(s2idle_bug_mmio, 1);
226 }
227
228 void amd_pmc_process_restore_quirks(struct amd_pmc_dev *dev)
229 {
230 if (dev->quirks && dev->quirks->s2idle_bug_mmio)
231 amd_pmc_skip_nvme_smi_handler(dev->quirks->s2idle_bug_mmio);
232 }
233
234 void amd_pmc_quirks_init(struct amd_pmc_dev *dev)
235 {
236 const struct dmi_system_id *dmi_id;
237
238 dmi_id = dmi_first_match(fwbug_list);
239 if (!dmi_id)
240 return;
241 dev->quirks = dmi_id->driver_data;
242 if (dev->quirks->s2idle_bug_mmio)
243 pr_info("Using s2idle quirk to avoid %s platform firmware bug\n",
244 dmi_id->ident);
245 }