162306a36Sopenharmony_ci// SPDX-License-Identifier: ISC 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2019 Lorenzo Bianconi <lorenzo@kernel.org> 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include "mt76.h" 762306a36Sopenharmony_ci#include <linux/pci.h> 862306a36Sopenharmony_ci 962306a36Sopenharmony_civoid mt76_pci_disable_aspm(struct pci_dev *pdev) 1062306a36Sopenharmony_ci{ 1162306a36Sopenharmony_ci struct pci_dev *parent = pdev->bus->self; 1262306a36Sopenharmony_ci u16 aspm_conf, parent_aspm_conf = 0; 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &aspm_conf); 1562306a36Sopenharmony_ci aspm_conf &= PCI_EXP_LNKCTL_ASPMC; 1662306a36Sopenharmony_ci if (parent) { 1762306a36Sopenharmony_ci pcie_capability_read_word(parent, PCI_EXP_LNKCTL, 1862306a36Sopenharmony_ci &parent_aspm_conf); 1962306a36Sopenharmony_ci parent_aspm_conf &= PCI_EXP_LNKCTL_ASPMC; 2062306a36Sopenharmony_ci } 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci if (!aspm_conf && (!parent || !parent_aspm_conf)) { 2362306a36Sopenharmony_ci /* aspm already disabled */ 2462306a36Sopenharmony_ci return; 2562306a36Sopenharmony_ci } 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci dev_info(&pdev->dev, "disabling ASPM %s %s\n", 2862306a36Sopenharmony_ci (aspm_conf & PCI_EXP_LNKCTL_ASPM_L0S) ? "L0s" : "", 2962306a36Sopenharmony_ci (aspm_conf & PCI_EXP_LNKCTL_ASPM_L1) ? "L1" : ""); 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_PCIEASPM)) { 3262306a36Sopenharmony_ci int err; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci err = pci_disable_link_state(pdev, aspm_conf); 3562306a36Sopenharmony_ci if (!err) 3662306a36Sopenharmony_ci return; 3762306a36Sopenharmony_ci } 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci /* both device and parent should have the same ASPM setting. 4062306a36Sopenharmony_ci * disable ASPM in downstream component first and then upstream. 4162306a36Sopenharmony_ci */ 4262306a36Sopenharmony_ci pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL, aspm_conf); 4362306a36Sopenharmony_ci if (parent) 4462306a36Sopenharmony_ci pcie_capability_clear_word(parent, PCI_EXP_LNKCTL, 4562306a36Sopenharmony_ci aspm_conf); 4662306a36Sopenharmony_ci} 4762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt76_pci_disable_aspm); 48