162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * AMD SoC Power Management Controller Driver Quirks 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2023, Advanced Micro Devices, Inc. 662306a36Sopenharmony_ci * All Rights Reserved. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Author: Mario Limonciello <mario.limonciello@amd.com> 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/dmi.h> 1262306a36Sopenharmony_ci#include <linux/io.h> 1362306a36Sopenharmony_ci#include <linux/ioport.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include "pmc.h" 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_cistruct quirk_entry { 1862306a36Sopenharmony_ci u32 s2idle_bug_mmio; 1962306a36Sopenharmony_ci bool spurious_8042; 2062306a36Sopenharmony_ci}; 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_cistatic struct quirk_entry quirk_s2idle_bug = { 2362306a36Sopenharmony_ci .s2idle_bug_mmio = 0xfed80380, 2462306a36Sopenharmony_ci}; 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistatic struct quirk_entry quirk_spurious_8042 = { 2762306a36Sopenharmony_ci .spurious_8042 = true, 2862306a36Sopenharmony_ci}; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistatic const struct dmi_system_id fwbug_list[] = { 3162306a36Sopenharmony_ci { 3262306a36Sopenharmony_ci .ident = "L14 Gen2 AMD", 3362306a36Sopenharmony_ci .driver_data = &quirk_s2idle_bug, 3462306a36Sopenharmony_ci .matches = { 3562306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 3662306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "20X5"), 3762306a36Sopenharmony_ci } 3862306a36Sopenharmony_ci }, 3962306a36Sopenharmony_ci { 4062306a36Sopenharmony_ci .ident = "T14s Gen2 AMD", 4162306a36Sopenharmony_ci .driver_data = &quirk_s2idle_bug, 4262306a36Sopenharmony_ci .matches = { 4362306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 4462306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "20XF"), 4562306a36Sopenharmony_ci } 4662306a36Sopenharmony_ci }, 4762306a36Sopenharmony_ci { 4862306a36Sopenharmony_ci .ident = "X13 Gen2 AMD", 4962306a36Sopenharmony_ci .driver_data = &quirk_s2idle_bug, 5062306a36Sopenharmony_ci .matches = { 5162306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 5262306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "20XH"), 5362306a36Sopenharmony_ci } 5462306a36Sopenharmony_ci }, 5562306a36Sopenharmony_ci { 5662306a36Sopenharmony_ci .ident = "T14 Gen2 AMD", 5762306a36Sopenharmony_ci .driver_data = &quirk_s2idle_bug, 5862306a36Sopenharmony_ci .matches = { 5962306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 6062306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "20XK"), 6162306a36Sopenharmony_ci } 6262306a36Sopenharmony_ci }, 6362306a36Sopenharmony_ci { 6462306a36Sopenharmony_ci .ident = "T14 Gen1 AMD", 6562306a36Sopenharmony_ci .driver_data = &quirk_s2idle_bug, 6662306a36Sopenharmony_ci .matches = { 6762306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 6862306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "20UD"), 6962306a36Sopenharmony_ci } 7062306a36Sopenharmony_ci }, 7162306a36Sopenharmony_ci { 7262306a36Sopenharmony_ci .ident = "T14 Gen1 AMD", 7362306a36Sopenharmony_ci .driver_data = &quirk_s2idle_bug, 7462306a36Sopenharmony_ci .matches = { 7562306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 7662306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "20UE"), 7762306a36Sopenharmony_ci } 7862306a36Sopenharmony_ci }, 7962306a36Sopenharmony_ci { 8062306a36Sopenharmony_ci .ident = "T14s Gen1 AMD", 8162306a36Sopenharmony_ci .driver_data = &quirk_s2idle_bug, 8262306a36Sopenharmony_ci .matches = { 8362306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 8462306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "20UH"), 8562306a36Sopenharmony_ci } 8662306a36Sopenharmony_ci }, 8762306a36Sopenharmony_ci { 8862306a36Sopenharmony_ci .ident = "T14s Gen1 AMD", 8962306a36Sopenharmony_ci .driver_data = &quirk_s2idle_bug, 9062306a36Sopenharmony_ci .matches = { 9162306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 9262306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "20UJ"), 9362306a36Sopenharmony_ci } 9462306a36Sopenharmony_ci }, 9562306a36Sopenharmony_ci { 9662306a36Sopenharmony_ci .ident = "P14s Gen1 AMD", 9762306a36Sopenharmony_ci .driver_data = &quirk_s2idle_bug, 9862306a36Sopenharmony_ci .matches = { 9962306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 10062306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "20Y1"), 10162306a36Sopenharmony_ci } 10262306a36Sopenharmony_ci }, 10362306a36Sopenharmony_ci { 10462306a36Sopenharmony_ci .ident = "P14s Gen2 AMD", 10562306a36Sopenharmony_ci .driver_data = &quirk_s2idle_bug, 10662306a36Sopenharmony_ci .matches = { 10762306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 10862306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "21A0"), 10962306a36Sopenharmony_ci } 11062306a36Sopenharmony_ci }, 11162306a36Sopenharmony_ci { 11262306a36Sopenharmony_ci .ident = "P14s Gen2 AMD", 11362306a36Sopenharmony_ci .driver_data = &quirk_s2idle_bug, 11462306a36Sopenharmony_ci .matches = { 11562306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 11662306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "21A1"), 11762306a36Sopenharmony_ci } 11862306a36Sopenharmony_ci }, 11962306a36Sopenharmony_ci /* https://bugzilla.kernel.org/show_bug.cgi?id=218024 */ 12062306a36Sopenharmony_ci { 12162306a36Sopenharmony_ci .ident = "V14 G4 AMN", 12262306a36Sopenharmony_ci .driver_data = &quirk_s2idle_bug, 12362306a36Sopenharmony_ci .matches = { 12462306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 12562306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "82YT"), 12662306a36Sopenharmony_ci } 12762306a36Sopenharmony_ci }, 12862306a36Sopenharmony_ci { 12962306a36Sopenharmony_ci .ident = "V14 G4 AMN", 13062306a36Sopenharmony_ci .driver_data = &quirk_s2idle_bug, 13162306a36Sopenharmony_ci .matches = { 13262306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 13362306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "83GE"), 13462306a36Sopenharmony_ci } 13562306a36Sopenharmony_ci }, 13662306a36Sopenharmony_ci { 13762306a36Sopenharmony_ci .ident = "V15 G4 AMN", 13862306a36Sopenharmony_ci .driver_data = &quirk_s2idle_bug, 13962306a36Sopenharmony_ci .matches = { 14062306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 14162306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "82YU"), 14262306a36Sopenharmony_ci } 14362306a36Sopenharmony_ci }, 14462306a36Sopenharmony_ci { 14562306a36Sopenharmony_ci .ident = "V15 G4 AMN", 14662306a36Sopenharmony_ci .driver_data = &quirk_s2idle_bug, 14762306a36Sopenharmony_ci .matches = { 14862306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 14962306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "83CQ"), 15062306a36Sopenharmony_ci } 15162306a36Sopenharmony_ci }, 15262306a36Sopenharmony_ci { 15362306a36Sopenharmony_ci .ident = "IdeaPad 1 14AMN7", 15462306a36Sopenharmony_ci .driver_data = &quirk_s2idle_bug, 15562306a36Sopenharmony_ci .matches = { 15662306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 15762306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "82VF"), 15862306a36Sopenharmony_ci } 15962306a36Sopenharmony_ci }, 16062306a36Sopenharmony_ci { 16162306a36Sopenharmony_ci .ident = "IdeaPad 1 15AMN7", 16262306a36Sopenharmony_ci .driver_data = &quirk_s2idle_bug, 16362306a36Sopenharmony_ci .matches = { 16462306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 16562306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "82VG"), 16662306a36Sopenharmony_ci } 16762306a36Sopenharmony_ci }, 16862306a36Sopenharmony_ci { 16962306a36Sopenharmony_ci .ident = "IdeaPad 1 15AMN7", 17062306a36Sopenharmony_ci .driver_data = &quirk_s2idle_bug, 17162306a36Sopenharmony_ci .matches = { 17262306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 17362306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "82X5"), 17462306a36Sopenharmony_ci } 17562306a36Sopenharmony_ci }, 17662306a36Sopenharmony_ci { 17762306a36Sopenharmony_ci .ident = "IdeaPad Slim 3 14AMN8", 17862306a36Sopenharmony_ci .driver_data = &quirk_s2idle_bug, 17962306a36Sopenharmony_ci .matches = { 18062306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 18162306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "82XN"), 18262306a36Sopenharmony_ci } 18362306a36Sopenharmony_ci }, 18462306a36Sopenharmony_ci { 18562306a36Sopenharmony_ci .ident = "IdeaPad Slim 3 15AMN8", 18662306a36Sopenharmony_ci .driver_data = &quirk_s2idle_bug, 18762306a36Sopenharmony_ci .matches = { 18862306a36Sopenharmony_ci DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), 18962306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "82XQ"), 19062306a36Sopenharmony_ci } 19162306a36Sopenharmony_ci }, 19262306a36Sopenharmony_ci /* https://gitlab.freedesktop.org/drm/amd/-/issues/2684 */ 19362306a36Sopenharmony_ci { 19462306a36Sopenharmony_ci .ident = "HP Laptop 15s-eq2xxx", 19562306a36Sopenharmony_ci .driver_data = &quirk_s2idle_bug, 19662306a36Sopenharmony_ci .matches = { 19762306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "HP"), 19862306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "HP Laptop 15s-eq2xxx"), 19962306a36Sopenharmony_ci } 20062306a36Sopenharmony_ci }, 20162306a36Sopenharmony_ci /* https://community.frame.work/t/tracking-framework-amd-ryzen-7040-series-lid-wakeup-behavior-feedback/39128 */ 20262306a36Sopenharmony_ci { 20362306a36Sopenharmony_ci .ident = "Framework Laptop 13 (Phoenix)", 20462306a36Sopenharmony_ci .driver_data = &quirk_spurious_8042, 20562306a36Sopenharmony_ci .matches = { 20662306a36Sopenharmony_ci DMI_MATCH(DMI_SYS_VENDOR, "Framework"), 20762306a36Sopenharmony_ci DMI_MATCH(DMI_PRODUCT_NAME, "Laptop 13 (AMD Ryzen 7040Series)"), 20862306a36Sopenharmony_ci DMI_MATCH(DMI_BIOS_VERSION, "03.03"), 20962306a36Sopenharmony_ci } 21062306a36Sopenharmony_ci }, 21162306a36Sopenharmony_ci {} 21262306a36Sopenharmony_ci}; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci/* 21562306a36Sopenharmony_ci * Laptops that run a SMI handler during the D3->D0 transition that occurs 21662306a36Sopenharmony_ci * specifically when exiting suspend to idle which can cause 21762306a36Sopenharmony_ci * large delays during resume when the IOMMU translation layer is enabled (the default 21862306a36Sopenharmony_ci * behavior) for NVME devices: 21962306a36Sopenharmony_ci * 22062306a36Sopenharmony_ci * To avoid this firmware problem, skip the SMI handler on these machines before the 22162306a36Sopenharmony_ci * D0 transition occurs. 22262306a36Sopenharmony_ci */ 22362306a36Sopenharmony_cistatic void amd_pmc_skip_nvme_smi_handler(u32 s2idle_bug_mmio) 22462306a36Sopenharmony_ci{ 22562306a36Sopenharmony_ci void __iomem *addr; 22662306a36Sopenharmony_ci u8 val; 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci if (!request_mem_region_muxed(s2idle_bug_mmio, 1, "amd_pmc_pm80")) 22962306a36Sopenharmony_ci return; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci addr = ioremap(s2idle_bug_mmio, 1); 23262306a36Sopenharmony_ci if (!addr) 23362306a36Sopenharmony_ci goto cleanup_resource; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci val = ioread8(addr); 23662306a36Sopenharmony_ci iowrite8(val & ~BIT(0), addr); 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci iounmap(addr); 23962306a36Sopenharmony_cicleanup_resource: 24062306a36Sopenharmony_ci release_mem_region(s2idle_bug_mmio, 1); 24162306a36Sopenharmony_ci} 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_civoid amd_pmc_process_restore_quirks(struct amd_pmc_dev *dev) 24462306a36Sopenharmony_ci{ 24562306a36Sopenharmony_ci if (dev->quirks && dev->quirks->s2idle_bug_mmio) 24662306a36Sopenharmony_ci amd_pmc_skip_nvme_smi_handler(dev->quirks->s2idle_bug_mmio); 24762306a36Sopenharmony_ci} 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_civoid amd_pmc_quirks_init(struct amd_pmc_dev *dev) 25062306a36Sopenharmony_ci{ 25162306a36Sopenharmony_ci const struct dmi_system_id *dmi_id; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci if (dev->cpu_id == AMD_CPU_ID_CZN) 25462306a36Sopenharmony_ci dev->disable_8042_wakeup = true; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci dmi_id = dmi_first_match(fwbug_list); 25762306a36Sopenharmony_ci if (!dmi_id) 25862306a36Sopenharmony_ci return; 25962306a36Sopenharmony_ci dev->quirks = dmi_id->driver_data; 26062306a36Sopenharmony_ci if (dev->quirks->s2idle_bug_mmio) 26162306a36Sopenharmony_ci pr_info("Using s2idle quirk to avoid %s platform firmware bug\n", 26262306a36Sopenharmony_ci dmi_id->ident); 26362306a36Sopenharmony_ci if (dev->quirks->spurious_8042) 26462306a36Sopenharmony_ci dev->disable_8042_wakeup = true; 26562306a36Sopenharmony_ci} 266