192c2fb8fSShyam Sundar S K // SPDX-License-Identifier: GPL-2.0-or-later
292c2fb8fSShyam Sundar S K /*
392c2fb8fSShyam Sundar S K * AMD SoC Power Management Controller Driver Quirks
492c2fb8fSShyam Sundar S K *
592c2fb8fSShyam Sundar S K * Copyright (c) 2023, Advanced Micro Devices, Inc.
692c2fb8fSShyam Sundar S K * All Rights Reserved.
792c2fb8fSShyam Sundar S K *
892c2fb8fSShyam Sundar S K * Author: Mario Limonciello <mario.limonciello@amd.com>
992c2fb8fSShyam Sundar S K */
1092c2fb8fSShyam Sundar S K
1192c2fb8fSShyam Sundar S K #include <linux/dmi.h>
1292c2fb8fSShyam Sundar S K #include <linux/io.h>
1392c2fb8fSShyam Sundar S K #include <linux/ioport.h>
1492c2fb8fSShyam Sundar S K
1592c2fb8fSShyam Sundar S K #include "pmc.h"
1692c2fb8fSShyam Sundar S K
1792c2fb8fSShyam Sundar S K struct quirk_entry {
1892c2fb8fSShyam Sundar S K u32 s2idle_bug_mmio;
191339559bSMario Limonciello bool spurious_8042;
2092c2fb8fSShyam Sundar S K };
2192c2fb8fSShyam Sundar S K
2292c2fb8fSShyam Sundar S K static struct quirk_entry quirk_s2idle_bug = {
2392c2fb8fSShyam Sundar S K .s2idle_bug_mmio = 0xfed80380,
2492c2fb8fSShyam Sundar S K };
2592c2fb8fSShyam Sundar S K
261339559bSMario Limonciello static struct quirk_entry quirk_spurious_8042 = {
271339559bSMario Limonciello .spurious_8042 = true,
281339559bSMario Limonciello };
291339559bSMario Limonciello
3092c2fb8fSShyam Sundar S K static const struct dmi_system_id fwbug_list[] = {
3192c2fb8fSShyam Sundar S K {
3292c2fb8fSShyam Sundar S K .ident = "L14 Gen2 AMD",
3392c2fb8fSShyam Sundar S K .driver_data = &quirk_s2idle_bug,
3492c2fb8fSShyam Sundar S K .matches = {
3592c2fb8fSShyam Sundar S K DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
3692c2fb8fSShyam Sundar S K DMI_MATCH(DMI_PRODUCT_NAME, "20X5"),
3792c2fb8fSShyam Sundar S K }
3892c2fb8fSShyam Sundar S K },
3992c2fb8fSShyam Sundar S K {
4092c2fb8fSShyam Sundar S K .ident = "T14s Gen2 AMD",
4192c2fb8fSShyam Sundar S K .driver_data = &quirk_s2idle_bug,
4292c2fb8fSShyam Sundar S K .matches = {
4392c2fb8fSShyam Sundar S K DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
4492c2fb8fSShyam Sundar S K DMI_MATCH(DMI_PRODUCT_NAME, "20XF"),
4592c2fb8fSShyam Sundar S K }
4692c2fb8fSShyam Sundar S K },
4792c2fb8fSShyam Sundar S K {
4892c2fb8fSShyam Sundar S K .ident = "X13 Gen2 AMD",
4992c2fb8fSShyam Sundar S K .driver_data = &quirk_s2idle_bug,
5092c2fb8fSShyam Sundar S K .matches = {
5192c2fb8fSShyam Sundar S K DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
5292c2fb8fSShyam Sundar S K DMI_MATCH(DMI_PRODUCT_NAME, "20XH"),
5392c2fb8fSShyam Sundar S K }
5492c2fb8fSShyam Sundar S K },
5592c2fb8fSShyam Sundar S K {
5692c2fb8fSShyam Sundar S K .ident = "T14 Gen2 AMD",
5792c2fb8fSShyam Sundar S K .driver_data = &quirk_s2idle_bug,
5892c2fb8fSShyam Sundar S K .matches = {
5992c2fb8fSShyam Sundar S K DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
6092c2fb8fSShyam Sundar S K DMI_MATCH(DMI_PRODUCT_NAME, "20XK"),
6192c2fb8fSShyam Sundar S K }
6292c2fb8fSShyam Sundar S K },
6392c2fb8fSShyam Sundar S K {
6492c2fb8fSShyam Sundar S K .ident = "T14 Gen1 AMD",
6592c2fb8fSShyam Sundar S K .driver_data = &quirk_s2idle_bug,
6692c2fb8fSShyam Sundar S K .matches = {
6792c2fb8fSShyam Sundar S K DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
6892c2fb8fSShyam Sundar S K DMI_MATCH(DMI_PRODUCT_NAME, "20UD"),
6992c2fb8fSShyam Sundar S K }
7092c2fb8fSShyam Sundar S K },
7192c2fb8fSShyam Sundar S K {
7292c2fb8fSShyam Sundar S K .ident = "T14 Gen1 AMD",
7392c2fb8fSShyam Sundar S K .driver_data = &quirk_s2idle_bug,
7492c2fb8fSShyam Sundar S K .matches = {
7592c2fb8fSShyam Sundar S K DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
7692c2fb8fSShyam Sundar S K DMI_MATCH(DMI_PRODUCT_NAME, "20UE"),
7792c2fb8fSShyam Sundar S K }
7892c2fb8fSShyam Sundar S K },
7992c2fb8fSShyam Sundar S K {
8092c2fb8fSShyam Sundar S K .ident = "T14s Gen1 AMD",
8192c2fb8fSShyam Sundar S K .driver_data = &quirk_s2idle_bug,
8292c2fb8fSShyam Sundar S K .matches = {
8392c2fb8fSShyam Sundar S K DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
8492c2fb8fSShyam Sundar S K DMI_MATCH(DMI_PRODUCT_NAME, "20UH"),
8592c2fb8fSShyam Sundar S K }
8692c2fb8fSShyam Sundar S K },
8792c2fb8fSShyam Sundar S K {
8892c2fb8fSShyam Sundar S K .ident = "T14s Gen1 AMD",
8992c2fb8fSShyam Sundar S K .driver_data = &quirk_s2idle_bug,
9092c2fb8fSShyam Sundar S K .matches = {
9192c2fb8fSShyam Sundar S K DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
9292c2fb8fSShyam Sundar S K DMI_MATCH(DMI_PRODUCT_NAME, "20UJ"),
9392c2fb8fSShyam Sundar S K }
9492c2fb8fSShyam Sundar S K },
9592c2fb8fSShyam Sundar S K {
9692c2fb8fSShyam Sundar S K .ident = "P14s Gen1 AMD",
9792c2fb8fSShyam Sundar S K .driver_data = &quirk_s2idle_bug,
9892c2fb8fSShyam Sundar S K .matches = {
9992c2fb8fSShyam Sundar S K DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
10092c2fb8fSShyam Sundar S K DMI_MATCH(DMI_PRODUCT_NAME, "20Y1"),
10192c2fb8fSShyam Sundar S K }
10292c2fb8fSShyam Sundar S K },
10392c2fb8fSShyam Sundar S K {
10492c2fb8fSShyam Sundar S K .ident = "P14s Gen2 AMD",
10592c2fb8fSShyam Sundar S K .driver_data = &quirk_s2idle_bug,
10692c2fb8fSShyam Sundar S K .matches = {
10792c2fb8fSShyam Sundar S K DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
10892c2fb8fSShyam Sundar S K DMI_MATCH(DMI_PRODUCT_NAME, "21A0"),
10992c2fb8fSShyam Sundar S K }
11092c2fb8fSShyam Sundar S K },
11192c2fb8fSShyam Sundar S K {
11292c2fb8fSShyam Sundar S K .ident = "P14s Gen2 AMD",
11392c2fb8fSShyam Sundar S K .driver_data = &quirk_s2idle_bug,
11492c2fb8fSShyam Sundar S K .matches = {
11592c2fb8fSShyam Sundar S K DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
11692c2fb8fSShyam Sundar S K DMI_MATCH(DMI_PRODUCT_NAME, "21A1"),
11792c2fb8fSShyam Sundar S K }
11892c2fb8fSShyam Sundar S K },
1193bde7ec1SDavid Lazar /* https://bugzilla.kernel.org/show_bug.cgi?id=218024 */
1203bde7ec1SDavid Lazar {
1213bde7ec1SDavid Lazar .ident = "V14 G4 AMN",
1223bde7ec1SDavid Lazar .driver_data = &quirk_s2idle_bug,
1233bde7ec1SDavid Lazar .matches = {
1243bde7ec1SDavid Lazar DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
1253bde7ec1SDavid Lazar DMI_MATCH(DMI_PRODUCT_NAME, "82YT"),
1263bde7ec1SDavid Lazar }
1273bde7ec1SDavid Lazar },
1283bde7ec1SDavid Lazar {
1293bde7ec1SDavid Lazar .ident = "V14 G4 AMN",
1303bde7ec1SDavid Lazar .driver_data = &quirk_s2idle_bug,
1313bde7ec1SDavid Lazar .matches = {
1323bde7ec1SDavid Lazar DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
1333bde7ec1SDavid Lazar DMI_MATCH(DMI_PRODUCT_NAME, "83GE"),
1343bde7ec1SDavid Lazar }
1353bde7ec1SDavid Lazar },
1363bde7ec1SDavid Lazar {
1373bde7ec1SDavid Lazar .ident = "V15 G4 AMN",
1383bde7ec1SDavid Lazar .driver_data = &quirk_s2idle_bug,
1393bde7ec1SDavid Lazar .matches = {
1403bde7ec1SDavid Lazar DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
1413bde7ec1SDavid Lazar DMI_MATCH(DMI_PRODUCT_NAME, "82YU"),
1423bde7ec1SDavid Lazar }
1433bde7ec1SDavid Lazar },
1443bde7ec1SDavid Lazar {
1453bde7ec1SDavid Lazar .ident = "V15 G4 AMN",
1463bde7ec1SDavid Lazar .driver_data = &quirk_s2idle_bug,
1473bde7ec1SDavid Lazar .matches = {
1483bde7ec1SDavid Lazar DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
1493bde7ec1SDavid Lazar DMI_MATCH(DMI_PRODUCT_NAME, "83CQ"),
1503bde7ec1SDavid Lazar }
1513bde7ec1SDavid Lazar },
1523bde7ec1SDavid Lazar {
1533bde7ec1SDavid Lazar .ident = "IdeaPad 1 14AMN7",
1543bde7ec1SDavid Lazar .driver_data = &quirk_s2idle_bug,
1553bde7ec1SDavid Lazar .matches = {
1563bde7ec1SDavid Lazar DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
1573bde7ec1SDavid Lazar DMI_MATCH(DMI_PRODUCT_NAME, "82VF"),
1583bde7ec1SDavid Lazar }
1593bde7ec1SDavid Lazar },
1603bde7ec1SDavid Lazar {
1613bde7ec1SDavid Lazar .ident = "IdeaPad 1 15AMN7",
1623bde7ec1SDavid Lazar .driver_data = &quirk_s2idle_bug,
1633bde7ec1SDavid Lazar .matches = {
1643bde7ec1SDavid Lazar DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
1653bde7ec1SDavid Lazar DMI_MATCH(DMI_PRODUCT_NAME, "82VG"),
1663bde7ec1SDavid Lazar }
1673bde7ec1SDavid Lazar },
1683bde7ec1SDavid Lazar {
1693bde7ec1SDavid Lazar .ident = "IdeaPad 1 15AMN7",
1703bde7ec1SDavid Lazar .driver_data = &quirk_s2idle_bug,
1713bde7ec1SDavid Lazar .matches = {
1723bde7ec1SDavid Lazar DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
1733bde7ec1SDavid Lazar DMI_MATCH(DMI_PRODUCT_NAME, "82X5"),
1743bde7ec1SDavid Lazar }
1753bde7ec1SDavid Lazar },
1763bde7ec1SDavid Lazar {
1773bde7ec1SDavid Lazar .ident = "IdeaPad Slim 3 14AMN8",
1783bde7ec1SDavid Lazar .driver_data = &quirk_s2idle_bug,
1793bde7ec1SDavid Lazar .matches = {
1803bde7ec1SDavid Lazar DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
1813bde7ec1SDavid Lazar DMI_MATCH(DMI_PRODUCT_NAME, "82XN"),
1823bde7ec1SDavid Lazar }
1833bde7ec1SDavid Lazar },
1843bde7ec1SDavid Lazar {
1853bde7ec1SDavid Lazar .ident = "IdeaPad Slim 3 15AMN8",
1863bde7ec1SDavid Lazar .driver_data = &quirk_s2idle_bug,
1873bde7ec1SDavid Lazar .matches = {
1883bde7ec1SDavid Lazar DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
1893bde7ec1SDavid Lazar DMI_MATCH(DMI_PRODUCT_NAME, "82XQ"),
1903bde7ec1SDavid Lazar }
1913bde7ec1SDavid Lazar },
19292c2fb8fSShyam Sundar S K /* https://gitlab.freedesktop.org/drm/amd/-/issues/2684 */
19392c2fb8fSShyam Sundar S K {
19492c2fb8fSShyam Sundar S K .ident = "HP Laptop 15s-eq2xxx",
19592c2fb8fSShyam Sundar S K .driver_data = &quirk_s2idle_bug,
19692c2fb8fSShyam Sundar S K .matches = {
19792c2fb8fSShyam Sundar S K DMI_MATCH(DMI_SYS_VENDOR, "HP"),
19892c2fb8fSShyam Sundar S K DMI_MATCH(DMI_PRODUCT_NAME, "HP Laptop 15s-eq2xxx"),
19992c2fb8fSShyam Sundar S K }
20092c2fb8fSShyam Sundar S K },
2011339559bSMario Limonciello /* https://community.frame.work/t/tracking-framework-amd-ryzen-7040-series-lid-wakeup-behavior-feedback/39128 */
2021339559bSMario Limonciello {
2031339559bSMario Limonciello .ident = "Framework Laptop 13 (Phoenix)",
2041339559bSMario Limonciello .driver_data = &quirk_spurious_8042,
2051339559bSMario Limonciello .matches = {
2061339559bSMario Limonciello DMI_MATCH(DMI_SYS_VENDOR, "Framework"),
2071339559bSMario Limonciello DMI_MATCH(DMI_PRODUCT_NAME, "Laptop 13 (AMD Ryzen 7040Series)"),
2081339559bSMario Limonciello DMI_MATCH(DMI_BIOS_VERSION, "03.03"),
2091339559bSMario Limonciello }
2101339559bSMario Limonciello },
211*d7cc1d72SMario Limonciello {
212*d7cc1d72SMario Limonciello .ident = "Framework Laptop 13 (Phoenix)",
213*d7cc1d72SMario Limonciello .driver_data = &quirk_spurious_8042,
214*d7cc1d72SMario Limonciello .matches = {
215*d7cc1d72SMario Limonciello DMI_MATCH(DMI_SYS_VENDOR, "Framework"),
216*d7cc1d72SMario Limonciello DMI_MATCH(DMI_PRODUCT_NAME, "Laptop 13 (AMD Ryzen 7040Series)"),
217*d7cc1d72SMario Limonciello DMI_MATCH(DMI_BIOS_VERSION, "03.05"),
218*d7cc1d72SMario Limonciello }
219*d7cc1d72SMario Limonciello },
22092c2fb8fSShyam Sundar S K {}
22192c2fb8fSShyam Sundar S K };
22292c2fb8fSShyam Sundar S K
22392c2fb8fSShyam Sundar S K /*
22492c2fb8fSShyam Sundar S K * Laptops that run a SMI handler during the D3->D0 transition that occurs
22592c2fb8fSShyam Sundar S K * specifically when exiting suspend to idle which can cause
22692c2fb8fSShyam Sundar S K * large delays during resume when the IOMMU translation layer is enabled (the default
22792c2fb8fSShyam Sundar S K * behavior) for NVME devices:
22892c2fb8fSShyam Sundar S K *
22992c2fb8fSShyam Sundar S K * To avoid this firmware problem, skip the SMI handler on these machines before the
23092c2fb8fSShyam Sundar S K * D0 transition occurs.
23192c2fb8fSShyam Sundar S K */
amd_pmc_skip_nvme_smi_handler(u32 s2idle_bug_mmio)23292c2fb8fSShyam Sundar S K static void amd_pmc_skip_nvme_smi_handler(u32 s2idle_bug_mmio)
23392c2fb8fSShyam Sundar S K {
23492c2fb8fSShyam Sundar S K void __iomem *addr;
23592c2fb8fSShyam Sundar S K u8 val;
23692c2fb8fSShyam Sundar S K
23792c2fb8fSShyam Sundar S K if (!request_mem_region_muxed(s2idle_bug_mmio, 1, "amd_pmc_pm80"))
23892c2fb8fSShyam Sundar S K return;
23992c2fb8fSShyam Sundar S K
24092c2fb8fSShyam Sundar S K addr = ioremap(s2idle_bug_mmio, 1);
24192c2fb8fSShyam Sundar S K if (!addr)
24292c2fb8fSShyam Sundar S K goto cleanup_resource;
24392c2fb8fSShyam Sundar S K
24492c2fb8fSShyam Sundar S K val = ioread8(addr);
24592c2fb8fSShyam Sundar S K iowrite8(val & ~BIT(0), addr);
24692c2fb8fSShyam Sundar S K
24792c2fb8fSShyam Sundar S K iounmap(addr);
24892c2fb8fSShyam Sundar S K cleanup_resource:
24992c2fb8fSShyam Sundar S K release_mem_region(s2idle_bug_mmio, 1);
25092c2fb8fSShyam Sundar S K }
25192c2fb8fSShyam Sundar S K
amd_pmc_process_restore_quirks(struct amd_pmc_dev * dev)25292c2fb8fSShyam Sundar S K void amd_pmc_process_restore_quirks(struct amd_pmc_dev *dev)
25392c2fb8fSShyam Sundar S K {
25492c2fb8fSShyam Sundar S K if (dev->quirks && dev->quirks->s2idle_bug_mmio)
25592c2fb8fSShyam Sundar S K amd_pmc_skip_nvme_smi_handler(dev->quirks->s2idle_bug_mmio);
25692c2fb8fSShyam Sundar S K }
25792c2fb8fSShyam Sundar S K
amd_pmc_quirks_init(struct amd_pmc_dev * dev)25892c2fb8fSShyam Sundar S K void amd_pmc_quirks_init(struct amd_pmc_dev *dev)
25992c2fb8fSShyam Sundar S K {
26092c2fb8fSShyam Sundar S K const struct dmi_system_id *dmi_id;
26192c2fb8fSShyam Sundar S K
2625b235bbcSMario Limonciello if (dev->cpu_id == AMD_CPU_ID_CZN)
2635b235bbcSMario Limonciello dev->disable_8042_wakeup = true;
2645b235bbcSMario Limonciello
26592c2fb8fSShyam Sundar S K dmi_id = dmi_first_match(fwbug_list);
26692c2fb8fSShyam Sundar S K if (!dmi_id)
26792c2fb8fSShyam Sundar S K return;
26892c2fb8fSShyam Sundar S K dev->quirks = dmi_id->driver_data;
26992c2fb8fSShyam Sundar S K if (dev->quirks->s2idle_bug_mmio)
27092c2fb8fSShyam Sundar S K pr_info("Using s2idle quirk to avoid %s platform firmware bug\n",
27192c2fb8fSShyam Sundar S K dmi_id->ident);
2721339559bSMario Limonciello if (dev->quirks->spurious_8042)
2731339559bSMario Limonciello dev->disable_8042_wakeup = true;
27492c2fb8fSShyam Sundar S K }
275