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 bool spurious_8042; 20 }; 21 22 static struct quirk_entry quirk_s2idle_bug = { 23 .s2idle_bug_mmio = 0xfed80380, 24 }; 25 26 static struct quirk_entry quirk_spurious_8042 = { 27 .spurious_8042 = true, 28 }; 29 30 static const struct dmi_system_id fwbug_list[] = { 31 { 32 .ident = "L14 Gen2 AMD", 33 .driver_data = &quirk_s2idle_bug, 34 .matches = { 35 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 36 DMI_MATCH(DMI_PRODUCT_NAME, "20X5"), 37 } 38 }, 39 { 40 .ident = "T14s Gen2 AMD", 41 .driver_data = &quirk_s2idle_bug, 42 .matches = { 43 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 44 DMI_MATCH(DMI_PRODUCT_NAME, "20XF"), 45 } 46 }, 47 { 48 .ident = "X13 Gen2 AMD", 49 .driver_data = &quirk_s2idle_bug, 50 .matches = { 51 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 52 DMI_MATCH(DMI_PRODUCT_NAME, "20XH"), 53 } 54 }, 55 { 56 .ident = "T14 Gen2 AMD", 57 .driver_data = &quirk_s2idle_bug, 58 .matches = { 59 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 60 DMI_MATCH(DMI_PRODUCT_NAME, "20XK"), 61 } 62 }, 63 { 64 .ident = "T14 Gen1 AMD", 65 .driver_data = &quirk_s2idle_bug, 66 .matches = { 67 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 68 DMI_MATCH(DMI_PRODUCT_NAME, "20UD"), 69 } 70 }, 71 { 72 .ident = "T14 Gen1 AMD", 73 .driver_data = &quirk_s2idle_bug, 74 .matches = { 75 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 76 DMI_MATCH(DMI_PRODUCT_NAME, "20UE"), 77 } 78 }, 79 { 80 .ident = "T14s Gen1 AMD", 81 .driver_data = &quirk_s2idle_bug, 82 .matches = { 83 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 84 DMI_MATCH(DMI_PRODUCT_NAME, "20UH"), 85 } 86 }, 87 { 88 .ident = "T14s Gen1 AMD", 89 .driver_data = &quirk_s2idle_bug, 90 .matches = { 91 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 92 DMI_MATCH(DMI_PRODUCT_NAME, "20UJ"), 93 } 94 }, 95 { 96 .ident = "P14s Gen1 AMD", 97 .driver_data = &quirk_s2idle_bug, 98 .matches = { 99 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 100 DMI_MATCH(DMI_PRODUCT_NAME, "20Y1"), 101 } 102 }, 103 { 104 .ident = "P14s Gen2 AMD", 105 .driver_data = &quirk_s2idle_bug, 106 .matches = { 107 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 108 DMI_MATCH(DMI_PRODUCT_NAME, "21A0"), 109 } 110 }, 111 { 112 .ident = "P14s Gen2 AMD", 113 .driver_data = &quirk_s2idle_bug, 114 .matches = { 115 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 116 DMI_MATCH(DMI_PRODUCT_NAME, "21A1"), 117 } 118 }, 119 /* https://bugzilla.kernel.org/show_bug.cgi?id=218024 */ 120 { 121 .ident = "V14 G4 AMN", 122 .driver_data = &quirk_s2idle_bug, 123 .matches = { 124 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 125 DMI_MATCH(DMI_PRODUCT_NAME, "82YT"), 126 } 127 }, 128 { 129 .ident = "V14 G4 AMN", 130 .driver_data = &quirk_s2idle_bug, 131 .matches = { 132 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 133 DMI_MATCH(DMI_PRODUCT_NAME, "83GE"), 134 } 135 }, 136 { 137 .ident = "V15 G4 AMN", 138 .driver_data = &quirk_s2idle_bug, 139 .matches = { 140 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 141 DMI_MATCH(DMI_PRODUCT_NAME, "82YU"), 142 } 143 }, 144 { 145 .ident = "V15 G4 AMN", 146 .driver_data = &quirk_s2idle_bug, 147 .matches = { 148 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 149 DMI_MATCH(DMI_PRODUCT_NAME, "83CQ"), 150 } 151 }, 152 { 153 .ident = "IdeaPad 1 14AMN7", 154 .driver_data = &quirk_s2idle_bug, 155 .matches = { 156 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 157 DMI_MATCH(DMI_PRODUCT_NAME, "82VF"), 158 } 159 }, 160 { 161 .ident = "IdeaPad 1 15AMN7", 162 .driver_data = &quirk_s2idle_bug, 163 .matches = { 164 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 165 DMI_MATCH(DMI_PRODUCT_NAME, "82VG"), 166 } 167 }, 168 { 169 .ident = "IdeaPad 1 15AMN7", 170 .driver_data = &quirk_s2idle_bug, 171 .matches = { 172 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 173 DMI_MATCH(DMI_PRODUCT_NAME, "82X5"), 174 } 175 }, 176 { 177 .ident = "IdeaPad Slim 3 14AMN8", 178 .driver_data = &quirk_s2idle_bug, 179 .matches = { 180 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 181 DMI_MATCH(DMI_PRODUCT_NAME, "82XN"), 182 } 183 }, 184 { 185 .ident = "IdeaPad Slim 3 15AMN8", 186 .driver_data = &quirk_s2idle_bug, 187 .matches = { 188 DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 189 DMI_MATCH(DMI_PRODUCT_NAME, "82XQ"), 190 } 191 }, 192 /* https://gitlab.freedesktop.org/drm/amd/-/issues/2684 */ 193 { 194 .ident = "HP Laptop 15s-eq2xxx", 195 .driver_data = &quirk_s2idle_bug, 196 .matches = { 197 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 198 DMI_MATCH(DMI_PRODUCT_NAME, "HP Laptop 15s-eq2xxx"), 199 } 200 }, 201 /* https://community.frame.work/t/tracking-framework-amd-ryzen-7040-series-lid-wakeup-behavior-feedback/39128 */ 202 { 203 .ident = "Framework Laptop 13 (Phoenix)", 204 .driver_data = &quirk_spurious_8042, 205 .matches = { 206 DMI_MATCH(DMI_SYS_VENDOR, "Framework"), 207 DMI_MATCH(DMI_PRODUCT_NAME, "Laptop 13 (AMD Ryzen 7040Series)"), 208 DMI_MATCH(DMI_BIOS_VERSION, "03.03"), 209 } 210 }, 211 {} 212 }; 213 214 /* 215 * Laptops that run a SMI handler during the D3->D0 transition that occurs 216 * specifically when exiting suspend to idle which can cause 217 * large delays during resume when the IOMMU translation layer is enabled (the default 218 * behavior) for NVME devices: 219 * 220 * To avoid this firmware problem, skip the SMI handler on these machines before the 221 * D0 transition occurs. 222 */ 223 static void amd_pmc_skip_nvme_smi_handler(u32 s2idle_bug_mmio) 224 { 225 void __iomem *addr; 226 u8 val; 227 228 if (!request_mem_region_muxed(s2idle_bug_mmio, 1, "amd_pmc_pm80")) 229 return; 230 231 addr = ioremap(s2idle_bug_mmio, 1); 232 if (!addr) 233 goto cleanup_resource; 234 235 val = ioread8(addr); 236 iowrite8(val & ~BIT(0), addr); 237 238 iounmap(addr); 239 cleanup_resource: 240 release_mem_region(s2idle_bug_mmio, 1); 241 } 242 243 void amd_pmc_process_restore_quirks(struct amd_pmc_dev *dev) 244 { 245 if (dev->quirks && dev->quirks->s2idle_bug_mmio) 246 amd_pmc_skip_nvme_smi_handler(dev->quirks->s2idle_bug_mmio); 247 } 248 249 void amd_pmc_quirks_init(struct amd_pmc_dev *dev) 250 { 251 const struct dmi_system_id *dmi_id; 252 253 if (dev->cpu_id == AMD_CPU_ID_CZN) 254 dev->disable_8042_wakeup = true; 255 256 dmi_id = dmi_first_match(fwbug_list); 257 if (!dmi_id) 258 return; 259 dev->quirks = dmi_id->driver_data; 260 if (dev->quirks->s2idle_bug_mmio) 261 pr_info("Using s2idle quirk to avoid %s platform firmware bug\n", 262 dmi_id->ident); 263 if (dev->quirks->spurious_8042) 264 dev->disable_8042_wakeup = true; 265 } 266