rockchip: Add ROCKCHIP PCIe ASPM interface
This commit is contained in:
parent
7901702c49
commit
f0e7802be6
@ -513,7 +513,8 @@ CONFIG_PCI=y
|
||||
CONFIG_PCIEAER=y
|
||||
CONFIG_PCIEASPM=y
|
||||
CONFIG_PCIEASPM_DEFAULT=y
|
||||
# CONFIG_PCIEASPM_PERFORMANCE is not set
|
||||
CONFIG_PCIEASPM_EXT=y
|
||||
CONFIG_PCIEASPM_PERFORMANCE=y
|
||||
# CONFIG_PCIEASPM_POWERSAVE is not set
|
||||
# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set
|
||||
CONFIG_PCIEPORTBUS=y
|
||||
|
@ -529,8 +529,9 @@ CONFIG_PARTITION_PERCPU=y
|
||||
CONFIG_PCI=y
|
||||
CONFIG_PCIEAER=y
|
||||
CONFIG_PCIEASPM=y
|
||||
CONFIG_PCIEASPM_DEFAULT=y
|
||||
# CONFIG_PCIEASPM_PERFORMANCE is not set
|
||||
# CONFIG_PCIEASPM_DEFAULT is not set
|
||||
CONFIG_PCIEASPM_EXT=y
|
||||
CONFIG_PCIEASPM_PERFORMANCE=y
|
||||
# CONFIG_PCIEASPM_POWERSAVE is not set
|
||||
# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set
|
||||
CONFIG_PCIEPORTBUS=y
|
||||
|
@ -0,0 +1,59 @@
|
||||
From 59e0ec5e5916ed4fac238a3da39aa0659831c41c Mon Sep 17 00:00:00 2001
|
||||
From: Heiko Stuebner <heiko@sntech.de>
|
||||
Date: Sun, 30 Oct 2022 20:34:42 +0100
|
||||
Subject: [PATCH 6/7] arm64: dts: rockchip: fix spdif@fe460000 ordering on
|
||||
rk356x
|
||||
|
||||
Move the node to its correct position, based on its
|
||||
mmio-address.
|
||||
|
||||
Link: https://lore.kernel.org/all/20221030193708.1671069-1-heiko@sntech.de
|
||||
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
|
||||
---
|
||||
arch/arm64/boot/dts/rockchip/rk356x.dtsi | 28 ++++++++++++------------
|
||||
1 file changed, 14 insertions(+), 14 deletions(-)
|
||||
|
||||
--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
|
||||
+++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
|
||||
@@ -1049,20 +1049,6 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
- spdif: spdif@fe460000 {
|
||||
- compatible = "rockchip,rk3568-spdif";
|
||||
- reg = <0x0 0xfe460000 0x0 0x1000>;
|
||||
- interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
|
||||
- clock-names = "mclk", "hclk";
|
||||
- clocks = <&cru MCLK_SPDIF_8CH>, <&cru HCLK_SPDIF_8CH>;
|
||||
- dmas = <&dmac1 1>;
|
||||
- dma-names = "tx";
|
||||
- pinctrl-names = "default";
|
||||
- pinctrl-0 = <&spdifm0_tx>;
|
||||
- #sound-dai-cells = <0>;
|
||||
- status = "disabled";
|
||||
- };
|
||||
-
|
||||
i2s0_8ch: i2s@fe400000 {
|
||||
compatible = "rockchip,rk3568-i2s-tdm";
|
||||
reg = <0x0 0xfe400000 0x0 0x1000>;
|
||||
@@ -1141,6 +1127,20 @@
|
||||
#sound-dai-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
+
|
||||
+ spdif: spdif@fe460000 {
|
||||
+ compatible = "rockchip,rk3568-spdif";
|
||||
+ reg = <0x0 0xfe460000 0x0 0x1000>;
|
||||
+ interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ clock-names = "mclk", "hclk";
|
||||
+ clocks = <&cru MCLK_SPDIF_8CH>, <&cru HCLK_SPDIF_8CH>;
|
||||
+ dmas = <&dmac1 1>;
|
||||
+ dma-names = "tx";
|
||||
+ pinctrl-names = "default";
|
||||
+ pinctrl-0 = <&spdifm0_tx>;
|
||||
+ #sound-dai-cells = <0>;
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
|
||||
dmac0: dma-controller@fe530000 {
|
||||
compatible = "arm,pl330", "arm,primecell";
|
@ -0,0 +1,45 @@
|
||||
From 6c51234cd4e1bfd637c3aab0a94893e832670fe5 Mon Sep 17 00:00:00 2001
|
||||
From: Shengyu Qu <wiagn233@outlook.com>
|
||||
Date: Sun, 30 Oct 2022 01:09:04 +0800
|
||||
Subject: [PATCH 7/7] arm64: dts: rockchip: RK356x: Add I2S2 device node
|
||||
|
||||
This patch adds I2S2 device tree node for RK3566/RK3568.
|
||||
|
||||
Signed-off-by: Shengyu Qu <wiagn233@outlook.com>
|
||||
Link: https://lore.kernel.org/r/OS3P286MB259771C12F2B15A4DDF435FE98359@OS3P286MB2597.JPNP286.PROD.OUTLOOK.COM
|
||||
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
|
||||
---
|
||||
arch/arm64/boot/dts/rockchip/rk356x.dtsi | 22 ++++++++++++++++++++++
|
||||
1 file changed, 22 insertions(+)
|
||||
|
||||
--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
|
||||
+++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
|
||||
@@ -1091,6 +1091,28 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
+ i2s2_2ch: i2s@fe420000 {
|
||||
+ compatible = "rockchip,rk3568-i2s-tdm";
|
||||
+ reg = <0x0 0xfe420000 0x0 0x1000>;
|
||||
+ interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ assigned-clocks = <&cru CLK_I2S2_2CH_SRC>;
|
||||
+ assigned-clock-rates = <1188000000>;
|
||||
+ clocks = <&cru MCLK_I2S2_2CH>, <&cru MCLK_I2S2_2CH>, <&cru HCLK_I2S2_2CH>;
|
||||
+ clock-names = "mclk_tx", "mclk_rx", "hclk";
|
||||
+ dmas = <&dmac1 4>, <&dmac1 5>;
|
||||
+ dma-names = "tx", "rx";
|
||||
+ resets = <&cru SRST_M_I2S2_2CH>;
|
||||
+ reset-names = "m";
|
||||
+ rockchip,grf = <&grf>;
|
||||
+ pinctrl-names = "default";
|
||||
+ pinctrl-0 = <&i2s2m0_sclktx
|
||||
+ &i2s2m0_lrcktx
|
||||
+ &i2s2m0_sdi
|
||||
+ &i2s2m0_sdo>;
|
||||
+ #sound-dai-cells = <0>;
|
||||
+ status = "disabled";
|
||||
+ };
|
||||
+
|
||||
i2s3_2ch: i2s@fe430000 {
|
||||
compatible = "rockchip,rk3568-i2s-tdm";
|
||||
reg = <0x0 0xfe430000 0x0 0x1000>;
|
402
patches-6.1/220-PCI-Add-ROCKCHIP-PCIe-ASPM-interface.patch
Normal file
402
patches-6.1/220-PCI-Add-ROCKCHIP-PCIe-ASPM-interface.patch
Normal file
@ -0,0 +1,402 @@
|
||||
From d591c3f6efef5f50fc970aeeedbf9e03b7bd5d21 Mon Sep 17 00:00:00 2001
|
||||
From: Jon Lin <jon.lin@rock-chips.com>
|
||||
Date: Fri, 17 Jun 2022 10:38:30 +0800
|
||||
Subject: [PATCH] PCI: Add ROCKCHIP PCIe ASPM interface
|
||||
|
||||
Change-Id: I1156bd10e352145d745899067bf43afda92d5a30
|
||||
Signed-off-by: Jon Lin <jon.lin@rock-chips.com>
|
||||
---
|
||||
drivers/pci/pcie/Kconfig | 6 +
|
||||
drivers/pci/pcie/Makefile | 1 +
|
||||
drivers/pci/pcie/aspm_ext.c | 339 ++++++++++++++++++++++++++++++++++++
|
||||
include/linux/aspm_ext.h | 16 ++
|
||||
4 files changed, 362 insertions(+)
|
||||
create mode 100644 drivers/pci/pcie/aspm_ext.c
|
||||
create mode 100644 include/linux/aspm_ext.h
|
||||
|
||||
--- a/drivers/pci/pcie/Kconfig
|
||||
+++ b/drivers/pci/pcie/Kconfig
|
||||
@@ -110,6 +110,12 @@ config PCIEASPM_PERFORMANCE
|
||||
Disable PCI Express ASPM L0s and L1, even if the BIOS enabled them.
|
||||
endchoice
|
||||
|
||||
+config PCIEASPM_EXT
|
||||
+ tristate "Extend ASPM function"
|
||||
+ depends on PCIEASPM
|
||||
+ help
|
||||
+ This enables the extensions APIs for ASPM control.
|
||||
+
|
||||
config PCIE_PME
|
||||
def_bool y
|
||||
depends on PCIEPORTBUS && PM
|
||||
--- a/drivers/pci/pcie/Makefile
|
||||
+++ b/drivers/pci/pcie/Makefile
|
||||
@@ -7,6 +7,7 @@ pcieportdrv-y := portdrv_core.o portdr
|
||||
obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o
|
||||
|
||||
obj-$(CONFIG_PCIEASPM) += aspm.o
|
||||
+obj-$(CONFIG_PCIEASPM_EXT) += aspm_ext.o
|
||||
obj-$(CONFIG_PCIEAER) += aer.o err.o
|
||||
obj-$(CONFIG_PCIEAER_INJECT) += aer_inject.o
|
||||
obj-$(CONFIG_PCIE_PME) += pme.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/pci/pcie/aspm_ext.c
|
||||
@@ -0,0 +1,339 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+/*
|
||||
+ * Rockchip PCIe Apis For WIFI
|
||||
+ *
|
||||
+ * Copyright (c) 2022 Rockchip Electronics Co., Ltd.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/pci.h>
|
||||
+#include <linux/aspm_ext.h>
|
||||
+#include <linux/errno.h>
|
||||
+
|
||||
+
|
||||
+static u32 rockchip_pcie_pcie_access_cap(struct pci_dev *pdev, int cap, uint offset,
|
||||
+ bool is_ext, bool is_write, u32 writeval)
|
||||
+{
|
||||
+ int cap_ptr = 0;
|
||||
+ u32 ret = -1;
|
||||
+ u32 readval;
|
||||
+
|
||||
+ if (!(pdev)) {
|
||||
+ pci_err(pdev, "%s: pdev is NULL\n", __func__);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Find Capability offset */
|
||||
+ if (is_ext) {
|
||||
+ /* removing max EXT_CAP_ID check as
|
||||
+ * linux kernel definition's max value is not updated yet as per spec
|
||||
+ */
|
||||
+ cap_ptr = pci_find_ext_capability(pdev, cap);
|
||||
+
|
||||
+ } else {
|
||||
+ /* removing max PCI_CAP_ID_MAX check as
|
||||
+ * previous kernel versions dont have this definition
|
||||
+ */
|
||||
+ cap_ptr = pci_find_capability(pdev, cap);
|
||||
+ }
|
||||
+
|
||||
+ /* Return if capability with given ID not found */
|
||||
+ if (cap_ptr == 0) {
|
||||
+ pci_err(pdev, "%s: PCI Cap(0x%02x) not supported.\n",
|
||||
+ __func__, cap);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (is_write) {
|
||||
+ pci_write_config_dword(pdev, (cap_ptr + offset), writeval);
|
||||
+ ret = 0;
|
||||
+
|
||||
+ } else {
|
||||
+ pci_read_config_dword(pdev, (cap_ptr + offset), &readval);
|
||||
+ ret = readval;
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static bool rockchip_pcie_bus_aspm_enable_dev(char *device, struct pci_dev *dev, bool enable)
|
||||
+{
|
||||
+ u32 linkctrl_before;
|
||||
+ u32 linkctrl_after = 0;
|
||||
+ u8 linkctrl_asm;
|
||||
+
|
||||
+ linkctrl_before = rockchip_pcie_pcie_access_cap(dev, PCI_CAP_ID_EXP, PCI_EXP_LNKCTL,
|
||||
+ false, false, 0);
|
||||
+ linkctrl_asm = (linkctrl_before & PCI_EXP_LNKCTL_ASPMC);
|
||||
+
|
||||
+ if (enable) {
|
||||
+ if (linkctrl_asm == PCI_EXP_LNKCTL_ASPM_L1) {
|
||||
+ pci_err(dev, "%s: %s already enabled linkctrl: 0x%x\n",
|
||||
+ __func__, device, linkctrl_before);
|
||||
+ return false;
|
||||
+ }
|
||||
+ /* Enable only L1 ASPM (bit 1) */
|
||||
+ rockchip_pcie_pcie_access_cap(dev, PCI_CAP_ID_EXP, PCI_EXP_LNKCTL, false,
|
||||
+ true, (linkctrl_before | PCI_EXP_LNKCTL_ASPM_L1));
|
||||
+ } else {
|
||||
+ if (linkctrl_asm == 0) {
|
||||
+ pci_err(dev, "%s: %s already disabled linkctrl: 0x%x\n",
|
||||
+ __func__, device, linkctrl_before);
|
||||
+ return false;
|
||||
+ }
|
||||
+ /* Disable complete ASPM (bit 1 and bit 0) */
|
||||
+ rockchip_pcie_pcie_access_cap(dev, PCI_CAP_ID_EXP, PCI_EXP_LNKCTL, false,
|
||||
+ true, (linkctrl_before & (~PCI_EXP_LNKCTL_ASPMC)));
|
||||
+ }
|
||||
+
|
||||
+ linkctrl_after = rockchip_pcie_pcie_access_cap(dev, PCI_CAP_ID_EXP, PCI_EXP_LNKCTL,
|
||||
+ false, false, 0);
|
||||
+ pci_err(dev, "%s: %s %s, linkctrl_before: 0x%x linkctrl_after: 0x%x\n",
|
||||
+ __func__, device, (enable ? "ENABLE " : "DISABLE"),
|
||||
+ linkctrl_before, linkctrl_after);
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+bool rockchip_pcie_bus_aspm_enable_rc_ep(struct pci_dev *child, struct pci_dev *parent, bool enable)
|
||||
+{
|
||||
+ bool ret;
|
||||
+
|
||||
+ if (enable) {
|
||||
+ /* Enable only L1 ASPM first RC then EP */
|
||||
+ ret = rockchip_pcie_bus_aspm_enable_dev("RC", parent, enable);
|
||||
+ ret = rockchip_pcie_bus_aspm_enable_dev("EP", child, enable);
|
||||
+ } else {
|
||||
+ /* Disable complete ASPM first EP then RC */
|
||||
+ ret = rockchip_pcie_bus_aspm_enable_dev("EP", child, enable);
|
||||
+ ret = rockchip_pcie_bus_aspm_enable_dev("RC", parent, enable);
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void pci_clear_and_set_dword(struct pci_dev *pdev, int pos,
|
||||
+ u32 clear, u32 set)
|
||||
+{
|
||||
+ u32 val;
|
||||
+
|
||||
+ pci_read_config_dword(pdev, pos, &val);
|
||||
+ val &= ~clear;
|
||||
+ val |= set;
|
||||
+ pci_write_config_dword(pdev, pos, val);
|
||||
+}
|
||||
+
|
||||
+/* Convert L1SS T_pwr encoding to usec */
|
||||
+static u32 calc_l1ss_pwron(struct pci_dev *pdev, u32 scale, u32 val)
|
||||
+{
|
||||
+ switch (scale) {
|
||||
+ case 0:
|
||||
+ return val * 2;
|
||||
+ case 1:
|
||||
+ return val * 10;
|
||||
+ case 2:
|
||||
+ return val * 100;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void encode_l12_threshold(u32 threshold_us, u32 *scale, u32 *value)
|
||||
+{
|
||||
+ u32 threshold_ns = threshold_us * 1000;
|
||||
+
|
||||
+ /* See PCIe r3.1, sec 7.33.3 and sec 6.18 */
|
||||
+ if (threshold_ns < 32) {
|
||||
+ *scale = 0;
|
||||
+ *value = threshold_ns;
|
||||
+ } else if (threshold_ns < 1024) {
|
||||
+ *scale = 1;
|
||||
+ *value = threshold_ns >> 5;
|
||||
+ } else if (threshold_ns < 32768) {
|
||||
+ *scale = 2;
|
||||
+ *value = threshold_ns >> 10;
|
||||
+ } else if (threshold_ns < 1048576) {
|
||||
+ *scale = 3;
|
||||
+ *value = threshold_ns >> 15;
|
||||
+ } else if (threshold_ns < 33554432) {
|
||||
+ *scale = 4;
|
||||
+ *value = threshold_ns >> 20;
|
||||
+ } else {
|
||||
+ *scale = 5;
|
||||
+ *value = threshold_ns >> 25;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* Calculate L1.2 PM substate timing parameters */
|
||||
+static void aspm_calc_l1ss_info(struct pci_dev *child, struct pci_dev *parent)
|
||||
+{
|
||||
+ u32 val1, val2, scale1, scale2;
|
||||
+ u32 t_common_mode, t_power_on, l1_2_threshold, scale, value;
|
||||
+ u32 ctl1 = 0, ctl2 = 0;
|
||||
+ u32 pctl1, pctl2, cctl1, cctl2;
|
||||
+ u32 pl1_2_enables, cl1_2_enables;
|
||||
+ u32 parent_l1ss_cap, child_l1ss_cap;
|
||||
+
|
||||
+ /* Setup L1 substate */
|
||||
+ pci_read_config_dword(parent, parent->l1ss + PCI_L1SS_CAP,
|
||||
+ &parent_l1ss_cap);
|
||||
+ pci_read_config_dword(child, child->l1ss + PCI_L1SS_CAP,
|
||||
+ &child_l1ss_cap);
|
||||
+
|
||||
+ /* Choose the greater of the two Port Common_Mode_Restore_Times */
|
||||
+ val1 = (parent_l1ss_cap & PCI_L1SS_CAP_CM_RESTORE_TIME) >> 8;
|
||||
+ val2 = (child_l1ss_cap & PCI_L1SS_CAP_CM_RESTORE_TIME) >> 8;
|
||||
+ t_common_mode = max(val1, val2);
|
||||
+
|
||||
+ /* Choose the greater of the two Port T_POWER_ON times */
|
||||
+ val1 = (parent_l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_VALUE) >> 19;
|
||||
+ scale1 = (parent_l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_SCALE) >> 16;
|
||||
+ val2 = (child_l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_VALUE) >> 19;
|
||||
+ scale2 = (child_l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_SCALE) >> 16;
|
||||
+
|
||||
+ if (calc_l1ss_pwron(parent, scale1, val1) >
|
||||
+ calc_l1ss_pwron(child, scale2, val2)) {
|
||||
+ ctl2 |= scale1 | (val1 << 3);
|
||||
+ t_power_on = calc_l1ss_pwron(parent, scale1, val1);
|
||||
+ } else {
|
||||
+ ctl2 |= scale2 | (val2 << 3);
|
||||
+ t_power_on = calc_l1ss_pwron(child, scale2, val2);
|
||||
+ }
|
||||
+
|
||||
+ /* Set LTR_L1.2_THRESHOLD to the time required to transition the
|
||||
+ * Link from L0 to L1.2 and back to L0 so we enter L1.2 only if
|
||||
+ * downstream devices report (via LTR) that they can tolerate at
|
||||
+ * least that much latency.
|
||||
+ *
|
||||
+ * Based on PCIe r3.1, sec 5.5.3.3.1, Figures 5-16 and 5-17, and
|
||||
+ * Table 5-11. T(POWER_OFF) is at most 2us and T(L1.2) is at
|
||||
+ * least 4us.
|
||||
+ */
|
||||
+ l1_2_threshold = 2 + 4 + t_common_mode + t_power_on;
|
||||
+ encode_l12_threshold(l1_2_threshold, &scale, &value);
|
||||
+ ctl1 |= t_common_mode << 8 | scale << 29 | value << 16;
|
||||
+
|
||||
+ pci_read_config_dword(parent, parent->l1ss + PCI_L1SS_CTL1, &pctl1);
|
||||
+ pci_read_config_dword(parent, parent->l1ss + PCI_L1SS_CTL2, &pctl2);
|
||||
+ pci_read_config_dword(child, child->l1ss + PCI_L1SS_CTL1, &cctl1);
|
||||
+ pci_read_config_dword(child, child->l1ss + PCI_L1SS_CTL2, &cctl2);
|
||||
+
|
||||
+ if (ctl1 == pctl1 && ctl1 == cctl1 &&
|
||||
+ ctl2 == pctl2 && ctl2 == cctl2)
|
||||
+ return;
|
||||
+
|
||||
+ /* Disable L1.2 while updating. See PCIe r5.0, sec 5.5.4, 7.8.3.3 */
|
||||
+ pl1_2_enables = pctl1 & PCI_L1SS_CTL1_L1_2_MASK;
|
||||
+ cl1_2_enables = cctl1 & PCI_L1SS_CTL1_L1_2_MASK;
|
||||
+
|
||||
+ if (pl1_2_enables || cl1_2_enables) {
|
||||
+ pci_clear_and_set_dword(child, child->l1ss + PCI_L1SS_CTL1,
|
||||
+ PCI_L1SS_CTL1_L1_2_MASK, 0);
|
||||
+ pci_clear_and_set_dword(parent, parent->l1ss + PCI_L1SS_CTL1,
|
||||
+ PCI_L1SS_CTL1_L1_2_MASK, 0);
|
||||
+ }
|
||||
+
|
||||
+ /* Program T_POWER_ON times in both ports */
|
||||
+ pci_write_config_dword(parent, parent->l1ss + PCI_L1SS_CTL2, ctl2);
|
||||
+ pci_write_config_dword(child, child->l1ss + PCI_L1SS_CTL2, ctl2);
|
||||
+
|
||||
+ /* Program Common_Mode_Restore_Time in upstream device */
|
||||
+ pci_clear_and_set_dword(parent, parent->l1ss + PCI_L1SS_CTL1,
|
||||
+ PCI_L1SS_CTL1_CM_RESTORE_TIME, ctl1);
|
||||
+
|
||||
+ /* Program LTR_L1.2_THRESHOLD time in both ports */
|
||||
+ pci_clear_and_set_dword(parent, parent->l1ss + PCI_L1SS_CTL1,
|
||||
+ PCI_L1SS_CTL1_LTR_L12_TH_VALUE |
|
||||
+ PCI_L1SS_CTL1_LTR_L12_TH_SCALE, ctl1);
|
||||
+ pci_clear_and_set_dword(child, child->l1ss + PCI_L1SS_CTL1,
|
||||
+ PCI_L1SS_CTL1_LTR_L12_TH_VALUE |
|
||||
+ PCI_L1SS_CTL1_LTR_L12_TH_SCALE, ctl1);
|
||||
+
|
||||
+ if (pl1_2_enables || cl1_2_enables) {
|
||||
+ pci_clear_and_set_dword(parent, parent->l1ss + PCI_L1SS_CTL1, 0,
|
||||
+ pl1_2_enables);
|
||||
+ pci_clear_and_set_dword(child, child->l1ss + PCI_L1SS_CTL1, 0,
|
||||
+ cl1_2_enables);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void rockchip_pcie_bus_l1ss_enable_dev(char *device, struct pci_dev *dev, bool enable)
|
||||
+{
|
||||
+ u32 l1ssctrl_before;
|
||||
+ u32 l1ssctrl_after = 0;
|
||||
+ u8 l1ss_ep;
|
||||
+
|
||||
+ /* Extendend Capacility Reg */
|
||||
+ l1ssctrl_before = rockchip_pcie_pcie_access_cap(dev, PCI_EXT_CAP_ID_L1SS,
|
||||
+ PCI_L1SS_CTL1, true, false, 0);
|
||||
+ l1ss_ep = (l1ssctrl_before & PCI_L1SS_CTL1_L1SS_MASK);
|
||||
+
|
||||
+ if (enable) {
|
||||
+ if (l1ss_ep == PCI_L1SS_CTL1_L1SS_MASK) {
|
||||
+ pci_err(dev, "%s: %s already enabled, l1ssctrl: 0x%x\n",
|
||||
+ __func__, device, l1ssctrl_before);
|
||||
+ return;
|
||||
+ }
|
||||
+ rockchip_pcie_pcie_access_cap(dev, PCI_EXT_CAP_ID_L1SS, PCI_L1SS_CTL1,
|
||||
+ true, true, (l1ssctrl_before | PCI_L1SS_CTL1_L1SS_MASK));
|
||||
+ } else {
|
||||
+ if (l1ss_ep == 0) {
|
||||
+ pci_err(dev, "%s: %s already disabled, l1ssctrl: 0x%x\n",
|
||||
+ __func__, device, l1ssctrl_before);
|
||||
+ return;
|
||||
+ }
|
||||
+ rockchip_pcie_pcie_access_cap(dev, PCI_EXT_CAP_ID_L1SS, PCI_L1SS_CTL1,
|
||||
+ true, true, (l1ssctrl_before & (~PCI_L1SS_CTL1_L1SS_MASK)));
|
||||
+ }
|
||||
+ l1ssctrl_after = rockchip_pcie_pcie_access_cap(dev, PCI_EXT_CAP_ID_L1SS,
|
||||
+ PCI_L1SS_CTL1, true, false, 0);
|
||||
+ pci_err(dev, "%s: %s %s, l1ssctrl_before: 0x%x l1ssctrl_after: 0x%x\n",
|
||||
+ __func__, device, (enable ? "ENABLE " : "DISABLE"),
|
||||
+ l1ssctrl_before, l1ssctrl_after);
|
||||
+}
|
||||
+
|
||||
+bool pcie_aspm_ext_is_rc_ep_l1ss_capable(struct pci_dev *child, struct pci_dev *parent)
|
||||
+{
|
||||
+ u32 parent_l1ss_cap, child_l1ss_cap;
|
||||
+
|
||||
+ /* Setup L1 substate */
|
||||
+ pci_read_config_dword(parent, parent->l1ss + PCI_L1SS_CAP,
|
||||
+ &parent_l1ss_cap);
|
||||
+ pci_read_config_dword(child, child->l1ss + PCI_L1SS_CAP,
|
||||
+ &child_l1ss_cap);
|
||||
+
|
||||
+ if (!(parent_l1ss_cap & PCI_L1SS_CAP_L1_PM_SS))
|
||||
+ parent_l1ss_cap = 0;
|
||||
+ if (!(child_l1ss_cap & PCI_L1SS_CAP_L1_PM_SS))
|
||||
+ child_l1ss_cap = 0;
|
||||
+
|
||||
+ if (parent_l1ss_cap && child_l1ss_cap)
|
||||
+ return true;
|
||||
+ else
|
||||
+ return false;
|
||||
+}
|
||||
+EXPORT_SYMBOL(pcie_aspm_ext_is_rc_ep_l1ss_capable);
|
||||
+
|
||||
+void pcie_aspm_ext_l1ss_enable(struct pci_dev *child, struct pci_dev *parent, bool enable)
|
||||
+{
|
||||
+ bool ret;
|
||||
+
|
||||
+ /* Disable ASPM of RC and EP */
|
||||
+ ret = rockchip_pcie_bus_aspm_enable_rc_ep(child, parent, false);
|
||||
+
|
||||
+ if (enable) {
|
||||
+ /* Enable RC then EP */
|
||||
+ aspm_calc_l1ss_info(child, parent);
|
||||
+ rockchip_pcie_bus_l1ss_enable_dev("RC", parent, enable);
|
||||
+ rockchip_pcie_bus_l1ss_enable_dev("EP", child, enable);
|
||||
+ } else {
|
||||
+ /* Disable EP then RC */
|
||||
+ rockchip_pcie_bus_l1ss_enable_dev("EP", child, enable);
|
||||
+ rockchip_pcie_bus_l1ss_enable_dev("RC", parent, enable);
|
||||
+ }
|
||||
+
|
||||
+ /* Enable ASPM of RC and EP only if this API disabled */
|
||||
+ if (ret)
|
||||
+ rockchip_pcie_bus_aspm_enable_rc_ep(child, parent, true);
|
||||
+}
|
||||
+EXPORT_SYMBOL(pcie_aspm_ext_l1ss_enable);
|
||||
--- /dev/null
|
||||
+++ b/include/linux/aspm_ext.h
|
||||
@@ -0,0 +1,16 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0 */
|
||||
+
|
||||
+/* Copyright (c) 2022 Rockchip Electronics Co., Ltd. */
|
||||
+
|
||||
+#ifndef _ASPM_EXT_H
|
||||
+#define _ASPM_EXT_H
|
||||
+
|
||||
+#if IS_REACHABLE(CONFIG_PCIEASPM_EXT)
|
||||
+bool pcie_aspm_ext_is_rc_ep_l1ss_capable(struct pci_dev *child, struct pci_dev *parent);
|
||||
+void pcie_aspm_ext_l1ss_enable(struct pci_dev *child, struct pci_dev *parent, bool enable);
|
||||
+#else
|
||||
+static inline bool pcie_aspm_ext_is_rc_ep_l1ss_capable(struct pci_dev *child, struct pci_dev *parent) { return false; }
|
||||
+static inline void pcie_aspm_ext_l1ss_enable(struct pci_dev *child, struct pci_dev *parent, bool enable) {}
|
||||
+#endif
|
||||
+
|
||||
+#endif
|
@ -0,0 +1,24 @@
|
||||
From a6c71606de486944c5fb028f47604fb22292312b Mon Sep 17 00:00:00 2001
|
||||
From: Jon Lin <jon.lin@rock-chips.com>
|
||||
Date: Fri, 24 Jun 2022 21:32:11 +0800
|
||||
Subject: [PATCH] PCI: aspm_ext: Re-enable LRT for L1SS after power loss
|
||||
|
||||
Change-Id: Iedb72ee74660a8f11f38895e06766c3b77728ba3
|
||||
Signed-off-by: Jon Lin <jon.lin@rock-chips.com>
|
||||
---
|
||||
drivers/pci/pcie/aspm_ext.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
--- a/drivers/pci/pcie/aspm_ext.c
|
||||
+++ b/drivers/pci/pcie/aspm_ext.c
|
||||
@@ -322,6 +322,10 @@ void pcie_aspm_ext_l1ss_enable(struct pc
|
||||
ret = rockchip_pcie_bus_aspm_enable_rc_ep(child, parent, false);
|
||||
|
||||
if (enable) {
|
||||
+ /* LRT enable bits loss after wifi off, enable it after power on */
|
||||
+ if (parent->ltr_path)
|
||||
+ pcie_capability_set_word(parent, PCI_EXP_DEVCTL2, PCI_EXP_DEVCTL2_LTR_EN);
|
||||
+
|
||||
/* Enable RC then EP */
|
||||
aspm_calc_l1ss_info(child, parent);
|
||||
rockchip_pcie_bus_l1ss_enable_dev("RC", parent, enable);
|
@ -0,0 +1,38 @@
|
||||
From cf03561e5ec9f2f8b41a992f3b8ca19b9c3b9e47 Mon Sep 17 00:00:00 2001
|
||||
From: Tao Huang <huangtao@rock-chips.com>
|
||||
Date: Fri, 15 Jul 2022 20:56:15 +0800
|
||||
Subject: [PATCH] PCI: aspm_ext: Fix Add missing MODULE_LICENSE()
|
||||
|
||||
ERROR: modpost: missing MODULE_LICENSE() in drivers/pci/pcie/aspm_ext.o
|
||||
|
||||
Signed-off-by: Tao Huang <huangtao@rock-chips.com>
|
||||
Change-Id: Id365aba7a73f02cc2c61882b46937250e64af01c
|
||||
---
|
||||
drivers/pci/pcie/aspm_ext.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/pci/pcie/aspm_ext.c
|
||||
+++ b/drivers/pci/pcie/aspm_ext.c
|
||||
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/aspm_ext.h>
|
||||
#include <linux/errno.h>
|
||||
@@ -95,7 +96,7 @@ static bool rockchip_pcie_bus_aspm_enabl
|
||||
return true;
|
||||
}
|
||||
|
||||
-bool rockchip_pcie_bus_aspm_enable_rc_ep(struct pci_dev *child, struct pci_dev *parent, bool enable)
|
||||
+static bool rockchip_pcie_bus_aspm_enable_rc_ep(struct pci_dev *child, struct pci_dev *parent, bool enable)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
@@ -341,3 +342,5 @@ void pcie_aspm_ext_l1ss_enable(struct pc
|
||||
rockchip_pcie_bus_aspm_enable_rc_ep(child, parent, true);
|
||||
}
|
||||
EXPORT_SYMBOL(pcie_aspm_ext_l1ss_enable);
|
||||
+
|
||||
+MODULE_LICENSE("GPL");
|
@ -0,0 +1,58 @@
|
||||
From 6e57e8b78939b4d849511fa96467d09d77ce8a26 Mon Sep 17 00:00:00 2001
|
||||
From: Shawn Lin <shawn.lin@rock-chips.com>
|
||||
Date: Tue, 31 Jan 2023 08:46:29 +0800
|
||||
Subject: [PATCH 1/3] mmc: sdhci-of-dwcmshc: Update DLL and pre-change delay
|
||||
for rockchip platform
|
||||
|
||||
For Rockchip platform, DLL bypass bit and start bit need to be set if
|
||||
DLL is not locked. And adjust pre-change delay to 0x3 for better signal
|
||||
test result.
|
||||
|
||||
Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
|
||||
---
|
||||
drivers/mmc/host/sdhci-of-dwcmshc.c | 13 +++++++++----
|
||||
1 file changed, 9 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/mmc/host/sdhci-of-dwcmshc.c
|
||||
+++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
|
||||
@@ -48,6 +48,7 @@
|
||||
#define DWCMSHC_EMMC_DLL_RXCLK_SRCSEL 29
|
||||
#define DWCMSHC_EMMC_DLL_START_POINT 16
|
||||
#define DWCMSHC_EMMC_DLL_INC 8
|
||||
+#define DWCMSHC_EMMC_DLL_BYPASS BIT(24)
|
||||
#define DWCMSHC_EMMC_DLL_DLYENA BIT(27)
|
||||
#define DLL_TXCLK_TAPNUM_DEFAULT 0x10
|
||||
#define DLL_TXCLK_TAPNUM_90_DEGREES 0xA
|
||||
@@ -60,6 +61,7 @@
|
||||
#define DLL_RXCLK_NO_INVERTER 1
|
||||
#define DLL_RXCLK_INVERTER 0
|
||||
#define DLL_CMDOUT_TAPNUM_90_DEGREES 0x8
|
||||
+#define DLL_RXCLK_ORI_GATE BIT(31)
|
||||
#define DLL_CMDOUT_TAPNUM_FROM_SW BIT(24)
|
||||
#define DLL_CMDOUT_SRC_CLK_NEG BIT(28)
|
||||
#define DLL_CMDOUT_EN_SRC_CLK_NEG BIT(29)
|
||||
@@ -234,9 +236,12 @@ static void dwcmshc_rk3568_set_clock(str
|
||||
sdhci_writel(host, extra, reg);
|
||||
|
||||
if (clock <= 52000000) {
|
||||
- /* Disable DLL and reset both of sample and drive clock */
|
||||
- sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL);
|
||||
- sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_RXCLK);
|
||||
+ /*
|
||||
+ * Disable DLL and reset both of sample and drive clock.
|
||||
+ * The bypass bit and start bit need to be set if DLL is not locked.
|
||||
+ */
|
||||
+ sdhci_writel(host, DWCMSHC_EMMC_DLL_BYPASS | DWCMSHC_EMMC_DLL_START, DWCMSHC_EMMC_DLL_CTRL);
|
||||
+ sdhci_writel(host, DLL_RXCLK_ORI_GATE, DWCMSHC_EMMC_DLL_RXCLK);
|
||||
sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_TXCLK);
|
||||
sdhci_writel(host, 0, DECMSHC_EMMC_DLL_CMDOUT);
|
||||
/*
|
||||
@@ -279,7 +284,7 @@ static void dwcmshc_rk3568_set_clock(str
|
||||
}
|
||||
|
||||
extra = 0x1 << 16 | /* tune clock stop en */
|
||||
- 0x2 << 17 | /* pre-change delay */
|
||||
+ 0x3 << 17 | /* pre-change delay */
|
||||
0x3 << 19; /* post-change delay */
|
||||
sdhci_writel(host, extra, dwc_priv->vendor_specific_area1 + DWCMSHC_EMMC_ATCTRL);
|
||||
|
@ -0,0 +1,93 @@
|
||||
From ce8180045daea68c45ba5bd2495885410b7b9dc8 Mon Sep 17 00:00:00 2001
|
||||
From: Shawn Lin <shawn.lin@rock-chips.com>
|
||||
Date: Tue, 31 Jan 2023 08:46:30 +0800
|
||||
Subject: [PATCH 2/3] mmc: sdhci-of-dwcmshc: Add runtime PM support
|
||||
|
||||
This patch adds runtime PM support.
|
||||
|
||||
Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
|
||||
---
|
||||
drivers/mmc/host/sdhci-of-dwcmshc.c | 51 ++++++++++++++++++++++++++++-
|
||||
1 file changed, 50 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/mmc/host/sdhci-of-dwcmshc.c
|
||||
+++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
+#include <linux/pm_runtime.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/sizes.h>
|
||||
|
||||
@@ -546,6 +547,13 @@ static int dwcmshc_probe(struct platform
|
||||
if (err)
|
||||
goto err_setup_host;
|
||||
|
||||
+ pm_runtime_get_noresume(&pdev->dev);
|
||||
+ pm_runtime_set_active(&pdev->dev);
|
||||
+ pm_runtime_enable(&pdev->dev);
|
||||
+ pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
|
||||
+ pm_runtime_use_autosuspend(&pdev->dev);
|
||||
+ pm_runtime_put_autosuspend(&pdev->dev);
|
||||
+
|
||||
return 0;
|
||||
|
||||
err_setup_host:
|
||||
@@ -575,6 +583,11 @@ static int dwcmshc_remove(struct platfor
|
||||
if (rk_priv)
|
||||
clk_bulk_disable_unprepare(RK35xx_MAX_CLKS,
|
||||
rk_priv->rockchip_clks);
|
||||
+
|
||||
+ pm_runtime_get_sync(&pdev->dev);
|
||||
+ pm_runtime_disable(&pdev->dev);
|
||||
+ pm_runtime_put_noidle(&pdev->dev);
|
||||
+
|
||||
sdhci_pltfm_free(pdev);
|
||||
|
||||
return 0;
|
||||
@@ -633,7 +646,43 @@ static int dwcmshc_resume(struct device
|
||||
}
|
||||
#endif
|
||||
|
||||
-static SIMPLE_DEV_PM_OPS(dwcmshc_pmops, dwcmshc_suspend, dwcmshc_resume);
|
||||
+#ifdef CONFIG_PM
|
||||
+static int dwcmshc_runtime_suspend(struct device *dev)
|
||||
+{
|
||||
+ struct sdhci_host *host = dev_get_drvdata(dev);
|
||||
+ u16 data;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = sdhci_runtime_suspend_host(host);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ data = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
|
||||
+ data &= ~SDHCI_CLOCK_CARD_EN;
|
||||
+ sdhci_writew(host, data, SDHCI_CLOCK_CONTROL);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int dwcmshc_runtime_resume(struct device *dev)
|
||||
+{
|
||||
+ struct sdhci_host *host = dev_get_drvdata(dev);
|
||||
+ u16 data;
|
||||
+
|
||||
+ data = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
|
||||
+ data |= SDHCI_CLOCK_CARD_EN;
|
||||
+ sdhci_writew(host, data, SDHCI_CLOCK_CONTROL);
|
||||
+
|
||||
+ return sdhci_runtime_resume_host(host, 0);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+static const struct dev_pm_ops dwcmshc_pmops = {
|
||||
+ SET_SYSTEM_SLEEP_PM_OPS(dwcmshc_suspend,
|
||||
+ dwcmshc_resume)
|
||||
+ SET_RUNTIME_PM_OPS(dwcmshc_runtime_suspend,
|
||||
+ dwcmshc_runtime_resume, NULL)
|
||||
+};
|
||||
|
||||
static struct platform_driver sdhci_dwcmshc_driver = {
|
||||
.driver = {
|
@ -0,0 +1,90 @@
|
||||
From 55c88b9f9ed2ba17fe5a4b095fd0fbd9c38b1c4b Mon Sep 17 00:00:00 2001
|
||||
From: Shawn Lin <shawn.lin@rock-chips.com>
|
||||
Date: Tue, 31 Jan 2023 08:46:31 +0800
|
||||
Subject: [PATCH 3/3] mmc: sdhci-of-dwcmshc: Add host software queue support
|
||||
|
||||
Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
|
||||
---
|
||||
drivers/mmc/host/sdhci-of-dwcmshc.c | 29 ++++++++++++++++++++++++++++-
|
||||
1 file changed, 28 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/mmc/host/sdhci-of-dwcmshc.c
|
||||
+++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <linux/sizes.h>
|
||||
|
||||
#include "sdhci-pltfm.h"
|
||||
+#include "mmc_hsq.h"
|
||||
|
||||
#define SDHCI_DWCMSHC_ARG2_STUFF GENMASK(31, 16)
|
||||
|
||||
@@ -331,6 +332,14 @@ static void rk35xx_sdhci_reset(struct sd
|
||||
sdhci_reset(host, mask);
|
||||
}
|
||||
|
||||
+static void sdhci_dwcmshc_request_done(struct sdhci_host *host, struct mmc_request *mrq)
|
||||
+{
|
||||
+ if (mmc_hsq_finalize_request(host->mmc, mrq))
|
||||
+ return;
|
||||
+
|
||||
+ mmc_request_done(host->mmc, mrq);
|
||||
+}
|
||||
+
|
||||
static const struct sdhci_ops sdhci_dwcmshc_ops = {
|
||||
.set_clock = sdhci_set_clock,
|
||||
.set_bus_width = sdhci_set_bus_width,
|
||||
@@ -347,6 +356,7 @@ static const struct sdhci_ops sdhci_dwcm
|
||||
.get_max_clock = sdhci_pltfm_clk_get_max_clock,
|
||||
.reset = rk35xx_sdhci_reset,
|
||||
.adma_write_desc = dwcmshc_adma_write_desc,
|
||||
+ .request_done = sdhci_dwcmshc_request_done,
|
||||
};
|
||||
|
||||
static const struct sdhci_pltfm_data sdhci_dwcmshc_pdata = {
|
||||
@@ -462,6 +472,7 @@ static int dwcmshc_probe(struct platform
|
||||
struct dwcmshc_priv *priv;
|
||||
struct rk35xx_priv *rk_priv = NULL;
|
||||
const struct sdhci_pltfm_data *pltfm_data;
|
||||
+ struct mmc_hsq *hsq;
|
||||
int err;
|
||||
u32 extra;
|
||||
|
||||
@@ -515,6 +526,16 @@ static int dwcmshc_probe(struct platform
|
||||
host->mmc_host_ops.request = dwcmshc_request;
|
||||
host->mmc_host_ops.hs400_enhanced_strobe = dwcmshc_hs400_enhanced_strobe;
|
||||
|
||||
+ hsq = devm_kzalloc(&pdev->dev, sizeof(*hsq), GFP_KERNEL);
|
||||
+ if (!hsq) {
|
||||
+ err = -ENOMEM;
|
||||
+ goto err_clk;
|
||||
+ }
|
||||
+
|
||||
+ err = mmc_hsq_init(hsq, host->mmc);
|
||||
+ if (err)
|
||||
+ goto err_clk;
|
||||
+
|
||||
if (pltfm_data == &sdhci_dwcmshc_rk35xx_pdata) {
|
||||
rk_priv = devm_kzalloc(&pdev->dev, sizeof(struct rk35xx_priv), GFP_KERNEL);
|
||||
if (!rk_priv) {
|
||||
@@ -602,6 +623,8 @@ static int dwcmshc_suspend(struct device
|
||||
struct rk35xx_priv *rk_priv = priv->priv;
|
||||
int ret;
|
||||
|
||||
+ mmc_hsq_suspend(host->mmc);
|
||||
+
|
||||
ret = sdhci_suspend_host(host);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -642,7 +665,11 @@ static int dwcmshc_resume(struct device
|
||||
return ret;
|
||||
}
|
||||
|
||||
- return sdhci_resume_host(host);
|
||||
+ ret = sdhci_resume_host(host);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return mmc_hsq_resume(host->mmc);
|
||||
}
|
||||
#endif
|
||||
|
402
patches-6.2/220-PCI-Add-ROCKCHIP-PCIe-ASPM-interface.patch
Normal file
402
patches-6.2/220-PCI-Add-ROCKCHIP-PCIe-ASPM-interface.patch
Normal file
@ -0,0 +1,402 @@
|
||||
From d591c3f6efef5f50fc970aeeedbf9e03b7bd5d21 Mon Sep 17 00:00:00 2001
|
||||
From: Jon Lin <jon.lin@rock-chips.com>
|
||||
Date: Fri, 17 Jun 2022 10:38:30 +0800
|
||||
Subject: [PATCH] PCI: Add ROCKCHIP PCIe ASPM interface
|
||||
|
||||
Change-Id: I1156bd10e352145d745899067bf43afda92d5a30
|
||||
Signed-off-by: Jon Lin <jon.lin@rock-chips.com>
|
||||
---
|
||||
drivers/pci/pcie/Kconfig | 6 +
|
||||
drivers/pci/pcie/Makefile | 1 +
|
||||
drivers/pci/pcie/aspm_ext.c | 339 ++++++++++++++++++++++++++++++++++++
|
||||
include/linux/aspm_ext.h | 16 ++
|
||||
4 files changed, 362 insertions(+)
|
||||
create mode 100644 drivers/pci/pcie/aspm_ext.c
|
||||
create mode 100644 include/linux/aspm_ext.h
|
||||
|
||||
--- a/drivers/pci/pcie/Kconfig
|
||||
+++ b/drivers/pci/pcie/Kconfig
|
||||
@@ -114,6 +114,12 @@ config PCIEASPM_PERFORMANCE
|
||||
Disable PCI Express ASPM L0s and L1, even if the BIOS enabled them.
|
||||
endchoice
|
||||
|
||||
+config PCIEASPM_EXT
|
||||
+ tristate "Extend ASPM function"
|
||||
+ depends on PCIEASPM
|
||||
+ help
|
||||
+ This enables the extensions APIs for ASPM control.
|
||||
+
|
||||
config PCIE_PME
|
||||
def_bool y
|
||||
depends on PCIEPORTBUS && PM
|
||||
--- a/drivers/pci/pcie/Makefile
|
||||
+++ b/drivers/pci/pcie/Makefile
|
||||
@@ -7,6 +7,7 @@ pcieportdrv-y := portdrv.o rcec.o
|
||||
obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o
|
||||
|
||||
obj-$(CONFIG_PCIEASPM) += aspm.o
|
||||
+obj-$(CONFIG_PCIEASPM_EXT) += aspm_ext.o
|
||||
obj-$(CONFIG_PCIEAER) += aer.o err.o
|
||||
obj-$(CONFIG_PCIEAER_INJECT) += aer_inject.o
|
||||
obj-$(CONFIG_PCIE_PME) += pme.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/pci/pcie/aspm_ext.c
|
||||
@@ -0,0 +1,339 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+/*
|
||||
+ * Rockchip PCIe Apis For WIFI
|
||||
+ *
|
||||
+ * Copyright (c) 2022 Rockchip Electronics Co., Ltd.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/pci.h>
|
||||
+#include <linux/aspm_ext.h>
|
||||
+#include <linux/errno.h>
|
||||
+
|
||||
+
|
||||
+static u32 rockchip_pcie_pcie_access_cap(struct pci_dev *pdev, int cap, uint offset,
|
||||
+ bool is_ext, bool is_write, u32 writeval)
|
||||
+{
|
||||
+ int cap_ptr = 0;
|
||||
+ u32 ret = -1;
|
||||
+ u32 readval;
|
||||
+
|
||||
+ if (!(pdev)) {
|
||||
+ pci_err(pdev, "%s: pdev is NULL\n", __func__);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Find Capability offset */
|
||||
+ if (is_ext) {
|
||||
+ /* removing max EXT_CAP_ID check as
|
||||
+ * linux kernel definition's max value is not updated yet as per spec
|
||||
+ */
|
||||
+ cap_ptr = pci_find_ext_capability(pdev, cap);
|
||||
+
|
||||
+ } else {
|
||||
+ /* removing max PCI_CAP_ID_MAX check as
|
||||
+ * previous kernel versions dont have this definition
|
||||
+ */
|
||||
+ cap_ptr = pci_find_capability(pdev, cap);
|
||||
+ }
|
||||
+
|
||||
+ /* Return if capability with given ID not found */
|
||||
+ if (cap_ptr == 0) {
|
||||
+ pci_err(pdev, "%s: PCI Cap(0x%02x) not supported.\n",
|
||||
+ __func__, cap);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (is_write) {
|
||||
+ pci_write_config_dword(pdev, (cap_ptr + offset), writeval);
|
||||
+ ret = 0;
|
||||
+
|
||||
+ } else {
|
||||
+ pci_read_config_dword(pdev, (cap_ptr + offset), &readval);
|
||||
+ ret = readval;
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static bool rockchip_pcie_bus_aspm_enable_dev(char *device, struct pci_dev *dev, bool enable)
|
||||
+{
|
||||
+ u32 linkctrl_before;
|
||||
+ u32 linkctrl_after = 0;
|
||||
+ u8 linkctrl_asm;
|
||||
+
|
||||
+ linkctrl_before = rockchip_pcie_pcie_access_cap(dev, PCI_CAP_ID_EXP, PCI_EXP_LNKCTL,
|
||||
+ false, false, 0);
|
||||
+ linkctrl_asm = (linkctrl_before & PCI_EXP_LNKCTL_ASPMC);
|
||||
+
|
||||
+ if (enable) {
|
||||
+ if (linkctrl_asm == PCI_EXP_LNKCTL_ASPM_L1) {
|
||||
+ pci_err(dev, "%s: %s already enabled linkctrl: 0x%x\n",
|
||||
+ __func__, device, linkctrl_before);
|
||||
+ return false;
|
||||
+ }
|
||||
+ /* Enable only L1 ASPM (bit 1) */
|
||||
+ rockchip_pcie_pcie_access_cap(dev, PCI_CAP_ID_EXP, PCI_EXP_LNKCTL, false,
|
||||
+ true, (linkctrl_before | PCI_EXP_LNKCTL_ASPM_L1));
|
||||
+ } else {
|
||||
+ if (linkctrl_asm == 0) {
|
||||
+ pci_err(dev, "%s: %s already disabled linkctrl: 0x%x\n",
|
||||
+ __func__, device, linkctrl_before);
|
||||
+ return false;
|
||||
+ }
|
||||
+ /* Disable complete ASPM (bit 1 and bit 0) */
|
||||
+ rockchip_pcie_pcie_access_cap(dev, PCI_CAP_ID_EXP, PCI_EXP_LNKCTL, false,
|
||||
+ true, (linkctrl_before & (~PCI_EXP_LNKCTL_ASPMC)));
|
||||
+ }
|
||||
+
|
||||
+ linkctrl_after = rockchip_pcie_pcie_access_cap(dev, PCI_CAP_ID_EXP, PCI_EXP_LNKCTL,
|
||||
+ false, false, 0);
|
||||
+ pci_err(dev, "%s: %s %s, linkctrl_before: 0x%x linkctrl_after: 0x%x\n",
|
||||
+ __func__, device, (enable ? "ENABLE " : "DISABLE"),
|
||||
+ linkctrl_before, linkctrl_after);
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+bool rockchip_pcie_bus_aspm_enable_rc_ep(struct pci_dev *child, struct pci_dev *parent, bool enable)
|
||||
+{
|
||||
+ bool ret;
|
||||
+
|
||||
+ if (enable) {
|
||||
+ /* Enable only L1 ASPM first RC then EP */
|
||||
+ ret = rockchip_pcie_bus_aspm_enable_dev("RC", parent, enable);
|
||||
+ ret = rockchip_pcie_bus_aspm_enable_dev("EP", child, enable);
|
||||
+ } else {
|
||||
+ /* Disable complete ASPM first EP then RC */
|
||||
+ ret = rockchip_pcie_bus_aspm_enable_dev("EP", child, enable);
|
||||
+ ret = rockchip_pcie_bus_aspm_enable_dev("RC", parent, enable);
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void pci_clear_and_set_dword(struct pci_dev *pdev, int pos,
|
||||
+ u32 clear, u32 set)
|
||||
+{
|
||||
+ u32 val;
|
||||
+
|
||||
+ pci_read_config_dword(pdev, pos, &val);
|
||||
+ val &= ~clear;
|
||||
+ val |= set;
|
||||
+ pci_write_config_dword(pdev, pos, val);
|
||||
+}
|
||||
+
|
||||
+/* Convert L1SS T_pwr encoding to usec */
|
||||
+static u32 calc_l1ss_pwron(struct pci_dev *pdev, u32 scale, u32 val)
|
||||
+{
|
||||
+ switch (scale) {
|
||||
+ case 0:
|
||||
+ return val * 2;
|
||||
+ case 1:
|
||||
+ return val * 10;
|
||||
+ case 2:
|
||||
+ return val * 100;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void encode_l12_threshold(u32 threshold_us, u32 *scale, u32 *value)
|
||||
+{
|
||||
+ u32 threshold_ns = threshold_us * 1000;
|
||||
+
|
||||
+ /* See PCIe r3.1, sec 7.33.3 and sec 6.18 */
|
||||
+ if (threshold_ns < 32) {
|
||||
+ *scale = 0;
|
||||
+ *value = threshold_ns;
|
||||
+ } else if (threshold_ns < 1024) {
|
||||
+ *scale = 1;
|
||||
+ *value = threshold_ns >> 5;
|
||||
+ } else if (threshold_ns < 32768) {
|
||||
+ *scale = 2;
|
||||
+ *value = threshold_ns >> 10;
|
||||
+ } else if (threshold_ns < 1048576) {
|
||||
+ *scale = 3;
|
||||
+ *value = threshold_ns >> 15;
|
||||
+ } else if (threshold_ns < 33554432) {
|
||||
+ *scale = 4;
|
||||
+ *value = threshold_ns >> 20;
|
||||
+ } else {
|
||||
+ *scale = 5;
|
||||
+ *value = threshold_ns >> 25;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* Calculate L1.2 PM substate timing parameters */
|
||||
+static void aspm_calc_l1ss_info(struct pci_dev *child, struct pci_dev *parent)
|
||||
+{
|
||||
+ u32 val1, val2, scale1, scale2;
|
||||
+ u32 t_common_mode, t_power_on, l1_2_threshold, scale, value;
|
||||
+ u32 ctl1 = 0, ctl2 = 0;
|
||||
+ u32 pctl1, pctl2, cctl1, cctl2;
|
||||
+ u32 pl1_2_enables, cl1_2_enables;
|
||||
+ u32 parent_l1ss_cap, child_l1ss_cap;
|
||||
+
|
||||
+ /* Setup L1 substate */
|
||||
+ pci_read_config_dword(parent, parent->l1ss + PCI_L1SS_CAP,
|
||||
+ &parent_l1ss_cap);
|
||||
+ pci_read_config_dword(child, child->l1ss + PCI_L1SS_CAP,
|
||||
+ &child_l1ss_cap);
|
||||
+
|
||||
+ /* Choose the greater of the two Port Common_Mode_Restore_Times */
|
||||
+ val1 = (parent_l1ss_cap & PCI_L1SS_CAP_CM_RESTORE_TIME) >> 8;
|
||||
+ val2 = (child_l1ss_cap & PCI_L1SS_CAP_CM_RESTORE_TIME) >> 8;
|
||||
+ t_common_mode = max(val1, val2);
|
||||
+
|
||||
+ /* Choose the greater of the two Port T_POWER_ON times */
|
||||
+ val1 = (parent_l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_VALUE) >> 19;
|
||||
+ scale1 = (parent_l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_SCALE) >> 16;
|
||||
+ val2 = (child_l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_VALUE) >> 19;
|
||||
+ scale2 = (child_l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_SCALE) >> 16;
|
||||
+
|
||||
+ if (calc_l1ss_pwron(parent, scale1, val1) >
|
||||
+ calc_l1ss_pwron(child, scale2, val2)) {
|
||||
+ ctl2 |= scale1 | (val1 << 3);
|
||||
+ t_power_on = calc_l1ss_pwron(parent, scale1, val1);
|
||||
+ } else {
|
||||
+ ctl2 |= scale2 | (val2 << 3);
|
||||
+ t_power_on = calc_l1ss_pwron(child, scale2, val2);
|
||||
+ }
|
||||
+
|
||||
+ /* Set LTR_L1.2_THRESHOLD to the time required to transition the
|
||||
+ * Link from L0 to L1.2 and back to L0 so we enter L1.2 only if
|
||||
+ * downstream devices report (via LTR) that they can tolerate at
|
||||
+ * least that much latency.
|
||||
+ *
|
||||
+ * Based on PCIe r3.1, sec 5.5.3.3.1, Figures 5-16 and 5-17, and
|
||||
+ * Table 5-11. T(POWER_OFF) is at most 2us and T(L1.2) is at
|
||||
+ * least 4us.
|
||||
+ */
|
||||
+ l1_2_threshold = 2 + 4 + t_common_mode + t_power_on;
|
||||
+ encode_l12_threshold(l1_2_threshold, &scale, &value);
|
||||
+ ctl1 |= t_common_mode << 8 | scale << 29 | value << 16;
|
||||
+
|
||||
+ pci_read_config_dword(parent, parent->l1ss + PCI_L1SS_CTL1, &pctl1);
|
||||
+ pci_read_config_dword(parent, parent->l1ss + PCI_L1SS_CTL2, &pctl2);
|
||||
+ pci_read_config_dword(child, child->l1ss + PCI_L1SS_CTL1, &cctl1);
|
||||
+ pci_read_config_dword(child, child->l1ss + PCI_L1SS_CTL2, &cctl2);
|
||||
+
|
||||
+ if (ctl1 == pctl1 && ctl1 == cctl1 &&
|
||||
+ ctl2 == pctl2 && ctl2 == cctl2)
|
||||
+ return;
|
||||
+
|
||||
+ /* Disable L1.2 while updating. See PCIe r5.0, sec 5.5.4, 7.8.3.3 */
|
||||
+ pl1_2_enables = pctl1 & PCI_L1SS_CTL1_L1_2_MASK;
|
||||
+ cl1_2_enables = cctl1 & PCI_L1SS_CTL1_L1_2_MASK;
|
||||
+
|
||||
+ if (pl1_2_enables || cl1_2_enables) {
|
||||
+ pci_clear_and_set_dword(child, child->l1ss + PCI_L1SS_CTL1,
|
||||
+ PCI_L1SS_CTL1_L1_2_MASK, 0);
|
||||
+ pci_clear_and_set_dword(parent, parent->l1ss + PCI_L1SS_CTL1,
|
||||
+ PCI_L1SS_CTL1_L1_2_MASK, 0);
|
||||
+ }
|
||||
+
|
||||
+ /* Program T_POWER_ON times in both ports */
|
||||
+ pci_write_config_dword(parent, parent->l1ss + PCI_L1SS_CTL2, ctl2);
|
||||
+ pci_write_config_dword(child, child->l1ss + PCI_L1SS_CTL2, ctl2);
|
||||
+
|
||||
+ /* Program Common_Mode_Restore_Time in upstream device */
|
||||
+ pci_clear_and_set_dword(parent, parent->l1ss + PCI_L1SS_CTL1,
|
||||
+ PCI_L1SS_CTL1_CM_RESTORE_TIME, ctl1);
|
||||
+
|
||||
+ /* Program LTR_L1.2_THRESHOLD time in both ports */
|
||||
+ pci_clear_and_set_dword(parent, parent->l1ss + PCI_L1SS_CTL1,
|
||||
+ PCI_L1SS_CTL1_LTR_L12_TH_VALUE |
|
||||
+ PCI_L1SS_CTL1_LTR_L12_TH_SCALE, ctl1);
|
||||
+ pci_clear_and_set_dword(child, child->l1ss + PCI_L1SS_CTL1,
|
||||
+ PCI_L1SS_CTL1_LTR_L12_TH_VALUE |
|
||||
+ PCI_L1SS_CTL1_LTR_L12_TH_SCALE, ctl1);
|
||||
+
|
||||
+ if (pl1_2_enables || cl1_2_enables) {
|
||||
+ pci_clear_and_set_dword(parent, parent->l1ss + PCI_L1SS_CTL1, 0,
|
||||
+ pl1_2_enables);
|
||||
+ pci_clear_and_set_dword(child, child->l1ss + PCI_L1SS_CTL1, 0,
|
||||
+ cl1_2_enables);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void rockchip_pcie_bus_l1ss_enable_dev(char *device, struct pci_dev *dev, bool enable)
|
||||
+{
|
||||
+ u32 l1ssctrl_before;
|
||||
+ u32 l1ssctrl_after = 0;
|
||||
+ u8 l1ss_ep;
|
||||
+
|
||||
+ /* Extendend Capacility Reg */
|
||||
+ l1ssctrl_before = rockchip_pcie_pcie_access_cap(dev, PCI_EXT_CAP_ID_L1SS,
|
||||
+ PCI_L1SS_CTL1, true, false, 0);
|
||||
+ l1ss_ep = (l1ssctrl_before & PCI_L1SS_CTL1_L1SS_MASK);
|
||||
+
|
||||
+ if (enable) {
|
||||
+ if (l1ss_ep == PCI_L1SS_CTL1_L1SS_MASK) {
|
||||
+ pci_err(dev, "%s: %s already enabled, l1ssctrl: 0x%x\n",
|
||||
+ __func__, device, l1ssctrl_before);
|
||||
+ return;
|
||||
+ }
|
||||
+ rockchip_pcie_pcie_access_cap(dev, PCI_EXT_CAP_ID_L1SS, PCI_L1SS_CTL1,
|
||||
+ true, true, (l1ssctrl_before | PCI_L1SS_CTL1_L1SS_MASK));
|
||||
+ } else {
|
||||
+ if (l1ss_ep == 0) {
|
||||
+ pci_err(dev, "%s: %s already disabled, l1ssctrl: 0x%x\n",
|
||||
+ __func__, device, l1ssctrl_before);
|
||||
+ return;
|
||||
+ }
|
||||
+ rockchip_pcie_pcie_access_cap(dev, PCI_EXT_CAP_ID_L1SS, PCI_L1SS_CTL1,
|
||||
+ true, true, (l1ssctrl_before & (~PCI_L1SS_CTL1_L1SS_MASK)));
|
||||
+ }
|
||||
+ l1ssctrl_after = rockchip_pcie_pcie_access_cap(dev, PCI_EXT_CAP_ID_L1SS,
|
||||
+ PCI_L1SS_CTL1, true, false, 0);
|
||||
+ pci_err(dev, "%s: %s %s, l1ssctrl_before: 0x%x l1ssctrl_after: 0x%x\n",
|
||||
+ __func__, device, (enable ? "ENABLE " : "DISABLE"),
|
||||
+ l1ssctrl_before, l1ssctrl_after);
|
||||
+}
|
||||
+
|
||||
+bool pcie_aspm_ext_is_rc_ep_l1ss_capable(struct pci_dev *child, struct pci_dev *parent)
|
||||
+{
|
||||
+ u32 parent_l1ss_cap, child_l1ss_cap;
|
||||
+
|
||||
+ /* Setup L1 substate */
|
||||
+ pci_read_config_dword(parent, parent->l1ss + PCI_L1SS_CAP,
|
||||
+ &parent_l1ss_cap);
|
||||
+ pci_read_config_dword(child, child->l1ss + PCI_L1SS_CAP,
|
||||
+ &child_l1ss_cap);
|
||||
+
|
||||
+ if (!(parent_l1ss_cap & PCI_L1SS_CAP_L1_PM_SS))
|
||||
+ parent_l1ss_cap = 0;
|
||||
+ if (!(child_l1ss_cap & PCI_L1SS_CAP_L1_PM_SS))
|
||||
+ child_l1ss_cap = 0;
|
||||
+
|
||||
+ if (parent_l1ss_cap && child_l1ss_cap)
|
||||
+ return true;
|
||||
+ else
|
||||
+ return false;
|
||||
+}
|
||||
+EXPORT_SYMBOL(pcie_aspm_ext_is_rc_ep_l1ss_capable);
|
||||
+
|
||||
+void pcie_aspm_ext_l1ss_enable(struct pci_dev *child, struct pci_dev *parent, bool enable)
|
||||
+{
|
||||
+ bool ret;
|
||||
+
|
||||
+ /* Disable ASPM of RC and EP */
|
||||
+ ret = rockchip_pcie_bus_aspm_enable_rc_ep(child, parent, false);
|
||||
+
|
||||
+ if (enable) {
|
||||
+ /* Enable RC then EP */
|
||||
+ aspm_calc_l1ss_info(child, parent);
|
||||
+ rockchip_pcie_bus_l1ss_enable_dev("RC", parent, enable);
|
||||
+ rockchip_pcie_bus_l1ss_enable_dev("EP", child, enable);
|
||||
+ } else {
|
||||
+ /* Disable EP then RC */
|
||||
+ rockchip_pcie_bus_l1ss_enable_dev("EP", child, enable);
|
||||
+ rockchip_pcie_bus_l1ss_enable_dev("RC", parent, enable);
|
||||
+ }
|
||||
+
|
||||
+ /* Enable ASPM of RC and EP only if this API disabled */
|
||||
+ if (ret)
|
||||
+ rockchip_pcie_bus_aspm_enable_rc_ep(child, parent, true);
|
||||
+}
|
||||
+EXPORT_SYMBOL(pcie_aspm_ext_l1ss_enable);
|
||||
--- /dev/null
|
||||
+++ b/include/linux/aspm_ext.h
|
||||
@@ -0,0 +1,16 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0 */
|
||||
+
|
||||
+/* Copyright (c) 2022 Rockchip Electronics Co., Ltd. */
|
||||
+
|
||||
+#ifndef _ASPM_EXT_H
|
||||
+#define _ASPM_EXT_H
|
||||
+
|
||||
+#if IS_REACHABLE(CONFIG_PCIEASPM_EXT)
|
||||
+bool pcie_aspm_ext_is_rc_ep_l1ss_capable(struct pci_dev *child, struct pci_dev *parent);
|
||||
+void pcie_aspm_ext_l1ss_enable(struct pci_dev *child, struct pci_dev *parent, bool enable);
|
||||
+#else
|
||||
+static inline bool pcie_aspm_ext_is_rc_ep_l1ss_capable(struct pci_dev *child, struct pci_dev *parent) { return false; }
|
||||
+static inline void pcie_aspm_ext_l1ss_enable(struct pci_dev *child, struct pci_dev *parent, bool enable) {}
|
||||
+#endif
|
||||
+
|
||||
+#endif
|
@ -0,0 +1,24 @@
|
||||
From a6c71606de486944c5fb028f47604fb22292312b Mon Sep 17 00:00:00 2001
|
||||
From: Jon Lin <jon.lin@rock-chips.com>
|
||||
Date: Fri, 24 Jun 2022 21:32:11 +0800
|
||||
Subject: [PATCH] PCI: aspm_ext: Re-enable LRT for L1SS after power loss
|
||||
|
||||
Change-Id: Iedb72ee74660a8f11f38895e06766c3b77728ba3
|
||||
Signed-off-by: Jon Lin <jon.lin@rock-chips.com>
|
||||
---
|
||||
drivers/pci/pcie/aspm_ext.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
--- a/drivers/pci/pcie/aspm_ext.c
|
||||
+++ b/drivers/pci/pcie/aspm_ext.c
|
||||
@@ -322,6 +322,10 @@ void pcie_aspm_ext_l1ss_enable(struct pc
|
||||
ret = rockchip_pcie_bus_aspm_enable_rc_ep(child, parent, false);
|
||||
|
||||
if (enable) {
|
||||
+ /* LRT enable bits loss after wifi off, enable it after power on */
|
||||
+ if (parent->ltr_path)
|
||||
+ pcie_capability_set_word(parent, PCI_EXP_DEVCTL2, PCI_EXP_DEVCTL2_LTR_EN);
|
||||
+
|
||||
/* Enable RC then EP */
|
||||
aspm_calc_l1ss_info(child, parent);
|
||||
rockchip_pcie_bus_l1ss_enable_dev("RC", parent, enable);
|
@ -0,0 +1,38 @@
|
||||
From cf03561e5ec9f2f8b41a992f3b8ca19b9c3b9e47 Mon Sep 17 00:00:00 2001
|
||||
From: Tao Huang <huangtao@rock-chips.com>
|
||||
Date: Fri, 15 Jul 2022 20:56:15 +0800
|
||||
Subject: [PATCH] PCI: aspm_ext: Fix Add missing MODULE_LICENSE()
|
||||
|
||||
ERROR: modpost: missing MODULE_LICENSE() in drivers/pci/pcie/aspm_ext.o
|
||||
|
||||
Signed-off-by: Tao Huang <huangtao@rock-chips.com>
|
||||
Change-Id: Id365aba7a73f02cc2c61882b46937250e64af01c
|
||||
---
|
||||
drivers/pci/pcie/aspm_ext.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/pci/pcie/aspm_ext.c
|
||||
+++ b/drivers/pci/pcie/aspm_ext.c
|
||||
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/aspm_ext.h>
|
||||
#include <linux/errno.h>
|
||||
@@ -95,7 +96,7 @@ static bool rockchip_pcie_bus_aspm_enabl
|
||||
return true;
|
||||
}
|
||||
|
||||
-bool rockchip_pcie_bus_aspm_enable_rc_ep(struct pci_dev *child, struct pci_dev *parent, bool enable)
|
||||
+static bool rockchip_pcie_bus_aspm_enable_rc_ep(struct pci_dev *child, struct pci_dev *parent, bool enable)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
@@ -341,3 +342,5 @@ void pcie_aspm_ext_l1ss_enable(struct pc
|
||||
rockchip_pcie_bus_aspm_enable_rc_ep(child, parent, true);
|
||||
}
|
||||
EXPORT_SYMBOL(pcie_aspm_ext_l1ss_enable);
|
||||
+
|
||||
+MODULE_LICENSE("GPL");
|
Loading…
Reference in New Issue
Block a user