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 #include <linux/platform_data/x86/amd-fch.h> 15 16 #include "pmc.h" 17 18 struct quirk_entry { 19 u32 s2idle_bug_mmio; 20 bool spurious_8042; 21 }; 22 23 static struct quirk_entry quirk_s2idle_bug = { 24 .s2idle_bug_mmio = FCH_PM_BASE + FCH_PM_SCRATCH, 25 }; 26 27 static struct quirk_entry quirk_spurious_8042 = { 28 .spurious_8042 = true, 29 }; 30 31 static struct quirk_entry quirk_s2idle_spurious_8042 = { 32 .s2idle_bug_mmio = FCH_PM_BASE + FCH_PM_SCRATCH, 33 .spurious_8042 = true, 34 }; 35 36 static const struct dmi_system_id fwbug_list[] = { 37 { 38 .ident = "L14 Gen2 AMD", 39 .driver_data = &quirk_s2idle_spurious_8042, 40 .matches = { 41 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 42 DMI_MATCH(DMI_PRODUCT_NAME, "20X5"), 43 } 44 }, 45 { 46 .ident = "T14s Gen2 AMD", 47 .driver_data = &quirk_s2idle_spurious_8042, 48 .matches = { 49 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 50 DMI_MATCH(DMI_PRODUCT_NAME, "20XF"), 51 } 52 }, 53 { 54 .ident = "X13 Gen2 AMD", 55 .driver_data = &quirk_s2idle_spurious_8042, 56 .matches = { 57 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 58 DMI_MATCH(DMI_PRODUCT_NAME, "20XH"), 59 } 60 }, 61 { 62 .ident = "T14 Gen2 AMD", 63 .driver_data = &quirk_s2idle_spurious_8042, 64 .matches = { 65 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 66 DMI_MATCH(DMI_PRODUCT_NAME, "20XK"), 67 } 68 }, 69 { 70 .ident = "T14 Gen1 AMD", 71 .driver_data = &quirk_s2idle_spurious_8042, 72 .matches = { 73 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 74 DMI_MATCH(DMI_PRODUCT_NAME, "20UD"), 75 } 76 }, 77 { 78 .ident = "T14 Gen1 AMD", 79 .driver_data = &quirk_s2idle_spurious_8042, 80 .matches = { 81 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 82 DMI_MATCH(DMI_PRODUCT_NAME, "20UE"), 83 } 84 }, 85 { 86 .ident = "T14s Gen1 AMD", 87 .driver_data = &quirk_s2idle_spurious_8042, 88 .matches = { 89 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 90 DMI_MATCH(DMI_PRODUCT_NAME, "20UH"), 91 } 92 }, 93 { 94 .ident = "T14s Gen1 AMD", 95 .driver_data = &quirk_s2idle_spurious_8042, 96 .matches = { 97 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 98 DMI_MATCH(DMI_PRODUCT_NAME, "20UJ"), 99 } 100 }, 101 { 102 .ident = "P14s Gen1 AMD", 103 .driver_data = &quirk_s2idle_spurious_8042, 104 .matches = { 105 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 106 DMI_MATCH(DMI_PRODUCT_NAME, "20Y1"), 107 } 108 }, 109 { 110 .ident = "P14s Gen2 AMD", 111 .driver_data = &quirk_s2idle_spurious_8042, 112 .matches = { 113 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 114 DMI_MATCH(DMI_PRODUCT_NAME, "21A0"), 115 } 116 }, 117 { 118 .ident = "P14s Gen2 AMD", 119 .driver_data = &quirk_s2idle_spurious_8042, 120 .matches = { 121 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 122 DMI_MATCH(DMI_PRODUCT_NAME, "21A1"), 123 } 124 }, 125 { 126 .ident = "ROG Xbox Ally RC73YA", 127 .driver_data = &quirk_spurious_8042, 128 .matches = { 129 DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), 130 DMI_MATCH(DMI_BOARD_NAME, "RC73YA"), 131 } 132 }, 133 /* https://bugzilla.kernel.org/show_bug.cgi?id=218024 */ 134 { 135 .ident = "V14 G4 AMN", 136 .driver_data = &quirk_s2idle_bug, 137 .matches = { 138 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 139 DMI_MATCH(DMI_PRODUCT_NAME, "82YT"), 140 } 141 }, 142 { 143 .ident = "V14 G4 AMN", 144 .driver_data = &quirk_s2idle_bug, 145 .matches = { 146 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 147 DMI_MATCH(DMI_PRODUCT_NAME, "83GE"), 148 } 149 }, 150 { 151 .ident = "V15 G4 AMN", 152 .driver_data = &quirk_s2idle_bug, 153 .matches = { 154 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 155 DMI_MATCH(DMI_PRODUCT_NAME, "82YU"), 156 } 157 }, 158 { 159 .ident = "V15 G4 AMN", 160 .driver_data = &quirk_s2idle_bug, 161 .matches = { 162 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 163 DMI_MATCH(DMI_PRODUCT_NAME, "83CQ"), 164 } 165 }, 166 { 167 .ident = "IdeaPad 1 14AMN7", 168 .driver_data = &quirk_s2idle_spurious_8042, 169 .matches = { 170 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 171 DMI_MATCH(DMI_PRODUCT_NAME, "82VF"), 172 } 173 }, 174 { 175 .ident = "IdeaPad 1 15AMN7", 176 .driver_data = &quirk_s2idle_spurious_8042, 177 .matches = { 178 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 179 DMI_MATCH(DMI_PRODUCT_NAME, "82VG"), 180 } 181 }, 182 { 183 .ident = "IdeaPad 1 15AMN7", 184 .driver_data = &quirk_s2idle_spurious_8042, 185 .matches = { 186 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 187 DMI_MATCH(DMI_PRODUCT_NAME, "82X5"), 188 } 189 }, 190 { 191 .ident = "IdeaPad Slim 3 14AMN8", 192 .driver_data = &quirk_s2idle_spurious_8042, 193 .matches = { 194 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 195 DMI_MATCH(DMI_PRODUCT_NAME, "82XN"), 196 } 197 }, 198 { 199 .ident = "IdeaPad Slim 3 15AMN8", 200 .driver_data = &quirk_s2idle_spurious_8042, 201 .matches = { 202 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 203 DMI_MATCH(DMI_PRODUCT_NAME, "82XQ"), 204 } 205 }, 206 /* https://gitlab.freedesktop.org/drm/amd/-/issues/4434 */ 207 { 208 .ident = "Lenovo Yoga 6 13ALC6", 209 .driver_data = &quirk_s2idle_spurious_8042, 210 .matches = { 211 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 212 DMI_MATCH(DMI_PRODUCT_NAME, "82ND"), 213 } 214 }, 215 /* https://gitlab.freedesktop.org/drm/amd/-/issues/4618 */ 216 { 217 .ident = "Lenovo Legion Go 2", 218 .driver_data = &quirk_s2idle_bug, 219 .matches = { 220 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 221 DMI_MATCH(DMI_PRODUCT_NAME, "83N0"), 222 } 223 }, 224 { 225 .ident = "Lenovo Legion Go 2", 226 .driver_data = &quirk_s2idle_bug, 227 .matches = { 228 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 229 DMI_MATCH(DMI_PRODUCT_NAME, "83N1"), 230 } 231 }, 232 /* https://gitlab.freedesktop.org/drm/amd/-/issues/2684 */ 233 { 234 .ident = "HP Laptop 15s-eq2xxx", 235 .driver_data = &quirk_s2idle_spurious_8042, 236 .matches = { 237 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 238 DMI_MATCH(DMI_PRODUCT_NAME, "HP Laptop 15s-eq2xxx"), 239 } 240 }, 241 /* https://community.frame.work/t/tracking-framework-amd-ryzen-7040-series-lid-wakeup-behavior-feedback/39128 */ 242 { 243 .ident = "Framework Laptop 13 (Phoenix)", 244 .driver_data = &quirk_spurious_8042, 245 .matches = { 246 DMI_MATCH(DMI_SYS_VENDOR, "Framework"), 247 DMI_MATCH(DMI_PRODUCT_NAME, "Laptop 13 (AMD Ryzen 7040Series)"), 248 DMI_MATCH(DMI_BIOS_VERSION, "03.03"), 249 } 250 }, 251 { 252 .ident = "Framework Laptop 13 (Phoenix)", 253 .driver_data = &quirk_spurious_8042, 254 .matches = { 255 DMI_MATCH(DMI_SYS_VENDOR, "Framework"), 256 DMI_MATCH(DMI_PRODUCT_NAME, "Laptop 13 (AMD Ryzen 7040Series)"), 257 DMI_MATCH(DMI_BIOS_VERSION, "03.05"), 258 } 259 }, 260 { 261 .ident = "MECHREVO Wujie 14X (GX4HRXL)", 262 .driver_data = &quirk_spurious_8042, 263 .matches = { 264 DMI_MATCH(DMI_BOARD_NAME, "WUJIE14-GX4HRXL"), 265 } 266 }, 267 { 268 .ident = "MECHREVO Yilong15Pro Series GM5HG7A", 269 .driver_data = &quirk_spurious_8042, 270 .matches = { 271 DMI_MATCH(DMI_SYS_VENDOR, "MECHREVO"), 272 DMI_MATCH(DMI_PRODUCT_NAME, "Yilong15Pro Series GM5HG7A"), 273 } 274 }, 275 /* https://bugzilla.kernel.org/show_bug.cgi?id=220116 */ 276 { 277 .ident = "PCSpecialist Lafite Pro V 14M", 278 .driver_data = &quirk_spurious_8042, 279 .matches = { 280 DMI_MATCH(DMI_SYS_VENDOR, "PCSpecialist"), 281 DMI_MATCH(DMI_PRODUCT_NAME, "Lafite Pro V 14M"), 282 } 283 }, 284 { 285 .ident = "TUXEDO Stellaris Slim 15 AMD Gen6", 286 .driver_data = &quirk_spurious_8042, 287 .matches = { 288 DMI_MATCH(DMI_BOARD_NAME, "GMxHGxx"), 289 } 290 }, 291 { 292 .ident = "TUXEDO InfinityBook Pro 14/15 AMD Gen10", 293 .driver_data = &quirk_spurious_8042, 294 .matches = { 295 DMI_MATCH(DMI_BOARD_NAME, "XxHP4NAx"), 296 } 297 }, 298 { 299 .ident = "TUXEDO InfinityBook Pro 14/15 AMD Gen10", 300 .driver_data = &quirk_spurious_8042, 301 .matches = { 302 DMI_MATCH(DMI_BOARD_NAME, "XxKK4NAx_XxSP4NAx"), 303 } 304 }, 305 {} 306 }; 307 308 /* 309 * Laptops that run a SMI handler during the D3->D0 transition that occurs 310 * specifically when exiting suspend to idle which can cause 311 * large delays during resume when the IOMMU translation layer is enabled (the default 312 * behavior) for NVME devices: 313 * 314 * To avoid this firmware problem, skip the SMI handler on these machines before the 315 * D0 transition occurs. 316 */ 317 static void amd_pmc_skip_nvme_smi_handler(u32 s2idle_bug_mmio) 318 { 319 void __iomem *addr; 320 u8 val; 321 322 if (!request_mem_region_muxed(s2idle_bug_mmio, 1, "amd_pmc_pm80")) 323 return; 324 325 addr = ioremap(s2idle_bug_mmio, 1); 326 if (!addr) 327 goto cleanup_resource; 328 329 val = ioread8(addr); 330 iowrite8(val & ~BIT(0), addr); 331 332 iounmap(addr); 333 cleanup_resource: 334 release_mem_region(s2idle_bug_mmio, 1); 335 } 336 337 void amd_pmc_process_restore_quirks(struct amd_pmc_dev *dev) 338 { 339 if (dev->quirks && dev->quirks->s2idle_bug_mmio) 340 amd_pmc_skip_nvme_smi_handler(dev->quirks->s2idle_bug_mmio); 341 } 342 343 void amd_pmc_quirks_init(struct amd_pmc_dev *dev) 344 { 345 const struct dmi_system_id *dmi_id; 346 347 /* 348 * IRQ1 may cause an interrupt during resume even without a keyboard 349 * press. 350 * 351 * Affects Renoir, Cezanne and Barcelo SoCs 352 * 353 * A solution is available in PMFW 64.66.0, but it must be activated by 354 * SBIOS. If SBIOS is known to have the fix a quirk can be added for 355 * a given system to avoid workaround. 356 */ 357 if (dev->cpu_id == AMD_CPU_ID_CZN) 358 dev->disable_8042_wakeup = true; 359 360 dmi_id = dmi_first_match(fwbug_list); 361 if (!dmi_id) 362 return; 363 dev->quirks = dmi_id->driver_data; 364 if (dev->quirks->s2idle_bug_mmio) 365 pr_info("Using s2idle quirk to avoid %s platform firmware bug\n", 366 dmi_id->ident); 367 dev->disable_8042_wakeup = dev->quirks->spurious_8042; 368 } 369