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 /* https://bugzilla.kernel.org/show_bug.cgi?id=220116 */ 243 { 244 .ident = "PCSpecialist Lafite Pro V 14M", 245 .driver_data = &quirk_spurious_8042, 246 .matches = { 247 DMI_MATCH(DMI_SYS_VENDOR, "PCSpecialist"), 248 DMI_MATCH(DMI_PRODUCT_NAME, "Lafite Pro V 14M"), 249 } 250 }, 251 {} 252 }; 253 254 /* 255 * Laptops that run a SMI handler during the D3->D0 transition that occurs 256 * specifically when exiting suspend to idle which can cause 257 * large delays during resume when the IOMMU translation layer is enabled (the default 258 * behavior) for NVME devices: 259 * 260 * To avoid this firmware problem, skip the SMI handler on these machines before the 261 * D0 transition occurs. 262 */ 263 static void amd_pmc_skip_nvme_smi_handler(u32 s2idle_bug_mmio) 264 { 265 void __iomem *addr; 266 u8 val; 267 268 if (!request_mem_region_muxed(s2idle_bug_mmio, 1, "amd_pmc_pm80")) 269 return; 270 271 addr = ioremap(s2idle_bug_mmio, 1); 272 if (!addr) 273 goto cleanup_resource; 274 275 val = ioread8(addr); 276 iowrite8(val & ~BIT(0), addr); 277 278 iounmap(addr); 279 cleanup_resource: 280 release_mem_region(s2idle_bug_mmio, 1); 281 } 282 283 void amd_pmc_process_restore_quirks(struct amd_pmc_dev *dev) 284 { 285 if (dev->quirks && dev->quirks->s2idle_bug_mmio) 286 amd_pmc_skip_nvme_smi_handler(dev->quirks->s2idle_bug_mmio); 287 } 288 289 void amd_pmc_quirks_init(struct amd_pmc_dev *dev) 290 { 291 const struct dmi_system_id *dmi_id; 292 293 /* 294 * IRQ1 may cause an interrupt during resume even without a keyboard 295 * press. 296 * 297 * Affects Renoir, Cezanne and Barcelo SoCs 298 * 299 * A solution is available in PMFW 64.66.0, but it must be activated by 300 * SBIOS. If SBIOS is known to have the fix a quirk can be added for 301 * a given system to avoid workaround. 302 */ 303 if (dev->cpu_id == AMD_CPU_ID_CZN) 304 dev->disable_8042_wakeup = true; 305 306 dmi_id = dmi_first_match(fwbug_list); 307 if (!dmi_id) 308 return; 309 dev->quirks = dmi_id->driver_data; 310 if (dev->quirks->s2idle_bug_mmio) 311 pr_info("Using s2idle quirk to avoid %s platform firmware bug\n", 312 dmi_id->ident); 313 dev->disable_8042_wakeup = dev->quirks->spurious_8042; 314 } 315