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 /* https://bugzilla.kernel.org/show_bug.cgi?id=218024 */ 126 { 127 .ident = "V14 G4 AMN", 128 .driver_data = &quirk_s2idle_bug, 129 .matches = { 130 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 131 DMI_MATCH(DMI_PRODUCT_NAME, "82YT"), 132 } 133 }, 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, "83GE"), 140 } 141 }, 142 { 143 .ident = "V15 G4 AMN", 144 .driver_data = &quirk_s2idle_bug, 145 .matches = { 146 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 147 DMI_MATCH(DMI_PRODUCT_NAME, "82YU"), 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, "83CQ"), 156 } 157 }, 158 { 159 .ident = "IdeaPad 1 14AMN7", 160 .driver_data = &quirk_s2idle_spurious_8042, 161 .matches = { 162 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 163 DMI_MATCH(DMI_PRODUCT_NAME, "82VF"), 164 } 165 }, 166 { 167 .ident = "IdeaPad 1 15AMN7", 168 .driver_data = &quirk_s2idle_spurious_8042, 169 .matches = { 170 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 171 DMI_MATCH(DMI_PRODUCT_NAME, "82VG"), 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, "82X5"), 180 } 181 }, 182 { 183 .ident = "IdeaPad Slim 3 14AMN8", 184 .driver_data = &quirk_s2idle_spurious_8042, 185 .matches = { 186 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 187 DMI_MATCH(DMI_PRODUCT_NAME, "82XN"), 188 } 189 }, 190 { 191 .ident = "IdeaPad Slim 3 15AMN8", 192 .driver_data = &quirk_s2idle_spurious_8042, 193 .matches = { 194 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 195 DMI_MATCH(DMI_PRODUCT_NAME, "82XQ"), 196 } 197 }, 198 /* https://gitlab.freedesktop.org/drm/amd/-/issues/4434 */ 199 { 200 .ident = "Lenovo Yoga 6 13ALC6", 201 .driver_data = &quirk_s2idle_spurious_8042, 202 .matches = { 203 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 204 DMI_MATCH(DMI_PRODUCT_NAME, "82ND"), 205 } 206 }, 207 /* https://gitlab.freedesktop.org/drm/amd/-/issues/2684 */ 208 { 209 .ident = "HP Laptop 15s-eq2xxx", 210 .driver_data = &quirk_s2idle_spurious_8042, 211 .matches = { 212 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 213 DMI_MATCH(DMI_PRODUCT_NAME, "HP Laptop 15s-eq2xxx"), 214 } 215 }, 216 /* https://community.frame.work/t/tracking-framework-amd-ryzen-7040-series-lid-wakeup-behavior-feedback/39128 */ 217 { 218 .ident = "Framework Laptop 13 (Phoenix)", 219 .driver_data = &quirk_spurious_8042, 220 .matches = { 221 DMI_MATCH(DMI_SYS_VENDOR, "Framework"), 222 DMI_MATCH(DMI_PRODUCT_NAME, "Laptop 13 (AMD Ryzen 7040Series)"), 223 DMI_MATCH(DMI_BIOS_VERSION, "03.03"), 224 } 225 }, 226 { 227 .ident = "Framework Laptop 13 (Phoenix)", 228 .driver_data = &quirk_spurious_8042, 229 .matches = { 230 DMI_MATCH(DMI_SYS_VENDOR, "Framework"), 231 DMI_MATCH(DMI_PRODUCT_NAME, "Laptop 13 (AMD Ryzen 7040Series)"), 232 DMI_MATCH(DMI_BIOS_VERSION, "03.05"), 233 } 234 }, 235 { 236 .ident = "MECHREVO Wujie 14X (GX4HRXL)", 237 .driver_data = &quirk_spurious_8042, 238 .matches = { 239 DMI_MATCH(DMI_BOARD_NAME, "WUJIE14-GX4HRXL"), 240 } 241 }, 242 { 243 .ident = "MECHREVO Yilong15Pro Series GM5HG7A", 244 .driver_data = &quirk_spurious_8042, 245 .matches = { 246 DMI_MATCH(DMI_SYS_VENDOR, "MECHREVO"), 247 DMI_MATCH(DMI_PRODUCT_NAME, "Yilong15Pro Series GM5HG7A"), 248 } 249 }, 250 /* https://bugzilla.kernel.org/show_bug.cgi?id=220116 */ 251 { 252 .ident = "PCSpecialist Lafite Pro V 14M", 253 .driver_data = &quirk_spurious_8042, 254 .matches = { 255 DMI_MATCH(DMI_SYS_VENDOR, "PCSpecialist"), 256 DMI_MATCH(DMI_PRODUCT_NAME, "Lafite Pro V 14M"), 257 } 258 }, 259 { 260 .ident = "TUXEDO InfinityBook Pro 14/15 AMD Gen10", 261 .driver_data = &quirk_spurious_8042, 262 .matches = { 263 DMI_MATCH(DMI_BOARD_NAME, "XxHP4NAx"), 264 } 265 }, 266 { 267 .ident = "TUXEDO InfinityBook Pro 14/15 AMD Gen10", 268 .driver_data = &quirk_spurious_8042, 269 .matches = { 270 DMI_MATCH(DMI_BOARD_NAME, "XxKK4NAx_XxSP4NAx"), 271 } 272 }, 273 {} 274 }; 275 276 /* 277 * Laptops that run a SMI handler during the D3->D0 transition that occurs 278 * specifically when exiting suspend to idle which can cause 279 * large delays during resume when the IOMMU translation layer is enabled (the default 280 * behavior) for NVME devices: 281 * 282 * To avoid this firmware problem, skip the SMI handler on these machines before the 283 * D0 transition occurs. 284 */ 285 static void amd_pmc_skip_nvme_smi_handler(u32 s2idle_bug_mmio) 286 { 287 void __iomem *addr; 288 u8 val; 289 290 if (!request_mem_region_muxed(s2idle_bug_mmio, 1, "amd_pmc_pm80")) 291 return; 292 293 addr = ioremap(s2idle_bug_mmio, 1); 294 if (!addr) 295 goto cleanup_resource; 296 297 val = ioread8(addr); 298 iowrite8(val & ~BIT(0), addr); 299 300 iounmap(addr); 301 cleanup_resource: 302 release_mem_region(s2idle_bug_mmio, 1); 303 } 304 305 void amd_pmc_process_restore_quirks(struct amd_pmc_dev *dev) 306 { 307 if (dev->quirks && dev->quirks->s2idle_bug_mmio) 308 amd_pmc_skip_nvme_smi_handler(dev->quirks->s2idle_bug_mmio); 309 } 310 311 void amd_pmc_quirks_init(struct amd_pmc_dev *dev) 312 { 313 const struct dmi_system_id *dmi_id; 314 315 /* 316 * IRQ1 may cause an interrupt during resume even without a keyboard 317 * press. 318 * 319 * Affects Renoir, Cezanne and Barcelo SoCs 320 * 321 * A solution is available in PMFW 64.66.0, but it must be activated by 322 * SBIOS. If SBIOS is known to have the fix a quirk can be added for 323 * a given system to avoid workaround. 324 */ 325 if (dev->cpu_id == AMD_CPU_ID_CZN) 326 dev->disable_8042_wakeup = true; 327 328 dmi_id = dmi_first_match(fwbug_list); 329 if (!dmi_id) 330 return; 331 dev->quirks = dmi_id->driver_data; 332 if (dev->quirks->s2idle_bug_mmio) 333 pr_info("Using s2idle quirk to avoid %s platform firmware bug\n", 334 dmi_id->ident); 335 dev->disable_8042_wakeup = dev->quirks->spurious_8042; 336 } 337