18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: ISC 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2019 Lorenzo Bianconi <lorenzo@kernel.org> 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include "mt76.h" 78c2ecf20Sopenharmony_ci#include <linux/pci.h> 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_civoid mt76_pci_disable_aspm(struct pci_dev *pdev) 108c2ecf20Sopenharmony_ci{ 118c2ecf20Sopenharmony_ci struct pci_dev *parent = pdev->bus->self; 128c2ecf20Sopenharmony_ci u16 aspm_conf, parent_aspm_conf = 0; 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &aspm_conf); 158c2ecf20Sopenharmony_ci aspm_conf &= PCI_EXP_LNKCTL_ASPMC; 168c2ecf20Sopenharmony_ci if (parent) { 178c2ecf20Sopenharmony_ci pcie_capability_read_word(parent, PCI_EXP_LNKCTL, 188c2ecf20Sopenharmony_ci &parent_aspm_conf); 198c2ecf20Sopenharmony_ci parent_aspm_conf &= PCI_EXP_LNKCTL_ASPMC; 208c2ecf20Sopenharmony_ci } 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci if (!aspm_conf && (!parent || !parent_aspm_conf)) { 238c2ecf20Sopenharmony_ci /* aspm already disabled */ 248c2ecf20Sopenharmony_ci return; 258c2ecf20Sopenharmony_ci } 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "disabling ASPM %s %s\n", 288c2ecf20Sopenharmony_ci (aspm_conf & PCI_EXP_LNKCTL_ASPM_L0S) ? "L0s" : "", 298c2ecf20Sopenharmony_ci (aspm_conf & PCI_EXP_LNKCTL_ASPM_L1) ? "L1" : ""); 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_PCIEASPM)) { 328c2ecf20Sopenharmony_ci int err; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci err = pci_disable_link_state(pdev, aspm_conf); 358c2ecf20Sopenharmony_ci if (!err) 368c2ecf20Sopenharmony_ci return; 378c2ecf20Sopenharmony_ci } 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci /* both device and parent should have the same ASPM setting. 408c2ecf20Sopenharmony_ci * disable ASPM in downstream component first and then upstream. 418c2ecf20Sopenharmony_ci */ 428c2ecf20Sopenharmony_ci pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL, aspm_conf); 438c2ecf20Sopenharmony_ci if (parent) 448c2ecf20Sopenharmony_ci pcie_capability_clear_word(parent, PCI_EXP_LNKCTL, 458c2ecf20Sopenharmony_ci aspm_conf); 468c2ecf20Sopenharmony_ci} 478c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(mt76_pci_disable_aspm); 48