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 } 246