int (*start)(struct rtw_dev *rtwdev);
        void (*stop)(struct rtw_dev *rtwdev);
        void (*deep_ps)(struct rtw_dev *rtwdev, bool enter);
+       void (*link_ps)(struct rtw_dev *rtwdev, bool enter);
 
        int (*write_data_rsvd_page)(struct rtw_dev *rtwdev, u8 *buf, u32 size);
        int (*write_data_h2c)(struct rtw_dev *rtwdev, u8 *buf, u32 size);
        rtwdev->hci.ops->deep_ps(rtwdev, enter);
 }
 
+static inline void rtw_hci_link_ps(struct rtw_dev *rtwdev, bool enter)
+{
+       rtwdev->hci.ops->link_ps(rtwdev, enter);
+}
+
 static inline int
 rtw_hci_write_data_rsvd_page(struct rtw_dev *rtwdev, u8 *buf, u32 size)
 {
 
        rtw_dbi_write8(rtwdev, RTK_PCIE_LINK_CFG, value);
 }
 
+static void rtw_pci_aspm_set(struct rtw_dev *rtwdev, bool enable)
+{
+       u8 value;
+       int ret;
+
+       ret = rtw_dbi_read8(rtwdev, RTK_PCIE_LINK_CFG, &value);
+       if (ret) {
+               rtw_err(rtwdev, "failed to read ASPM, ret=%d", ret);
+               return;
+       }
+
+       if (enable)
+               value |= BIT_L1_SW_EN;
+       else
+               value &= ~BIT_L1_SW_EN;
+
+       rtw_dbi_write8(rtwdev, RTK_PCIE_LINK_CFG, value);
+}
+
+static void rtw_pci_link_ps(struct rtw_dev *rtwdev, bool enter)
+{
+       struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
+
+       /* Like CLKREQ, ASPM is also implemented by two HW modules, and can
+        * only be enabled when host supports it.
+        *
+        * And ASPM mechanism should be enabled when driver/firmware enters
+        * power save mode, without having heavy traffic. Because we've
+        * experienced some inter-operability issues that the link tends
+        * to enter L1 state on the fly even when driver is having high
+        * throughput. This is probably because the ASPM behavior slightly
+        * varies from different SOC.
+        */
+       if (rtwpci->link_ctrl & PCI_EXP_LNKCTL_ASPM_L1)
+               rtw_pci_aspm_set(rtwdev, enter);
+}
+
 static void rtw_pci_link_cfg(struct rtw_dev *rtwdev)
 {
        struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
        .start = rtw_pci_start,
        .stop = rtw_pci_stop,
        .deep_ps = rtw_pci_deep_ps,
+       .link_ps = rtw_pci_link_ps,
 
        .read8 = rtw_pci_read8,
        .read16 = rtw_pci_read16,
 
        rtw_coex_ips_notify(rtwdev, COEX_IPS_ENTER);
 
        rtw_core_stop(rtwdev);
+       rtw_hci_link_ps(rtwdev, true);
 
        return 0;
 }
 {
        int ret;
 
+       rtw_hci_link_ps(rtwdev, false);
+
        ret = rtw_ips_pwr_up(rtwdev);
        if (ret) {
                rtw_err(rtwdev, "failed to leave ips state\n");
        conf->rlbm = 0;
        conf->smart_ps = 0;
 
+       rtw_hci_link_ps(rtwdev, false);
        rtw_fw_set_pwr_mode(rtwdev);
        rtw_fw_leave_lps_state_check(rtwdev);
 
        rtw_coex_lps_notify(rtwdev, COEX_LPS_ENABLE);
 
        rtw_fw_set_pwr_mode(rtwdev);
+       rtw_hci_link_ps(rtwdev, true);
+
        set_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags);
 }