From e43d4db7c057a52fe85843a37950d937670fcb04 Mon Sep 17 00:00:00 2001 From: coolsnowwolf Date: Sun, 16 Mar 2025 23:02:40 +0800 Subject: [PATCH] rockchip: fix RK3399 PCIE reboot issues --- ...01-rk3399-fix-pci-phy-reset-on-probe.patch | 47 +++++++++++++++++++ .../402-rk3399-fix-pci-lanes-location.patch | 44 +++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 target/linux/rockchip/patches-6.6/401-rk3399-fix-pci-phy-reset-on-probe.patch create mode 100644 target/linux/rockchip/patches-6.6/402-rk3399-fix-pci-lanes-location.patch diff --git a/target/linux/rockchip/patches-6.6/401-rk3399-fix-pci-phy-reset-on-probe.patch b/target/linux/rockchip/patches-6.6/401-rk3399-fix-pci-phy-reset-on-probe.patch new file mode 100644 index 000000000..f67184553 --- /dev/null +++ b/target/linux/rockchip/patches-6.6/401-rk3399-fix-pci-phy-reset-on-probe.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Andrey Safonov +Date: Sat, 16 Dec 2023 22:46:35 +0300 +Subject: rk3399 PCIE PHY reset on probe + +This patches the PCIE initialization error after warm reboot. +The root of cause is, when the device is booted after power on, +PHY stays in 'factory' state. After warm boot PHY stays in the +previous state and prevents any training, thus PCIE init fails. + +Signed-off-by: Andrey Safonov +--- + drivers/phy/rockchip/phy-rockchip-pcie.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +--- a/drivers/phy/rockchip/phy-rockchip-pcie.c ++++ b/drivers/phy/rockchip/phy-rockchip-pcie.c +@@ -344,6 +344,20 @@ static const struct of_device_id rockchi + + MODULE_DEVICE_TABLE(of, rockchip_pcie_phy_dt_ids); + ++static void rockchip_pcie_phy_reset(struct rockchip_pcie_phy *rk_phy) ++{ ++ int i; ++ ++ for (i = 0; i < PHY_MAX_LANE_NUM; i++) ++ regmap_write(rk_phy->reg_base, ++ rk_phy->phy_data->pcie_laneoff, ++ HIWORD_UPDATE(PHY_LANE_IDLE_OFF, ++ PHY_LANE_IDLE_MASK, ++ PHY_LANE_IDLE_A_SHIFT + i)); ++ ++ reset_control_assert(rk_phy->phy_rst); ++} ++ + static int rockchip_pcie_phy_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +@@ -393,6 +407,8 @@ static int rockchip_pcie_phy_probe(struc + + phy_num = (phy_num == 0) ? 1 : PHY_MAX_LANE_NUM; + dev_dbg(dev, "phy number is %d\n", phy_num); ++ ++ rockchip_pcie_phy_reset(rk_phy); + + for (i = 0; i < phy_num; i++) { + rk_phy->phys[i].phy = devm_phy_create(dev, dev->of_node, &ops); diff --git a/target/linux/rockchip/patches-6.6/402-rk3399-fix-pci-lanes-location.patch b/target/linux/rockchip/patches-6.6/402-rk3399-fix-pci-lanes-location.patch new file mode 100644 index 000000000..8a9fca10f --- /dev/null +++ b/target/linux/rockchip/patches-6.6/402-rk3399-fix-pci-lanes-location.patch @@ -0,0 +1,44 @@ +From 77f6dfcb20c2dc6a4a2f5303709c6fa0c7b65f30 Mon Sep 17 00:00:00 2001 +From: Valmantas Paliksa +Date: Thu, 12 Dec 2024 12:24:33 +0200 +Subject: [PATCH] Disable PHY_LANE_IDLE_OFF for each instance of rockchip_pcie_phy_power_one + +This patch fixes an issue in the Rockchip PCIe PHY driver where, after +a warm restart of the rockchip_pcie_phy module, PCIe lanes other than +lane 0 could remain stuck in the PHY_LANE_IDLE_OFF state. This resulted +in the PCIe link being restricted to x1 mode, even in configurations +designed to use multiple lanes. + +Signed-off-by: Valmantas Paliksa +--- + drivers/phy/rockchip/phy-rockchip-pcie.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/drivers/phy/rockchip/phy-rockchip-pcie.c ++++ b/drivers/phy/rockchip/phy-rockchip-pcie.c +@@ -166,6 +166,12 @@ static int rockchip_pcie_phy_power_on(st + unsigned long timeout; + + mutex_lock(&rk_phy->pcie_mutex); ++ ++ regmap_write(rk_phy->reg_base, ++ rk_phy->phy_data->pcie_laneoff, ++ HIWORD_UPDATE(!PHY_LANE_IDLE_OFF, ++ PHY_LANE_IDLE_MASK, ++ PHY_LANE_IDLE_A_SHIFT + inst->index)); + + if (rk_phy->pwr_cnt++) + goto err_out; +@@ -181,12 +187,6 @@ static int rockchip_pcie_phy_power_on(st + PHY_CFG_ADDR_MASK, + PHY_CFG_ADDR_SHIFT)); + +- regmap_write(rk_phy->reg_base, +- rk_phy->phy_data->pcie_laneoff, +- HIWORD_UPDATE(!PHY_LANE_IDLE_OFF, +- PHY_LANE_IDLE_MASK, +- PHY_LANE_IDLE_A_SHIFT + inst->index)); +- + /* + * No documented timeout value for phy operation below, + * so we make it large enough here. And we use loop-break