From 2f7c68cb55ecb7331f2381deb497c27155f32faf Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Wed, 03 Jan 2024 09:43:39 +0000 Subject: [PATCH] update kernel to 5.10.198 --- kernel/drivers/pci/controller/dwc/pcie-dw-rockchip.c | 177 +++++++++++++++++++++++++++++++---------------------------- 1 files changed, 93 insertions(+), 84 deletions(-) diff --git a/kernel/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/kernel/drivers/pci/controller/dwc/pcie-dw-rockchip.c index 4e5a225..e22295e 100644 --- a/kernel/drivers/pci/controller/dwc/pcie-dw-rockchip.c +++ b/kernel/drivers/pci/controller/dwc/pcie-dw-rockchip.c @@ -8,6 +8,7 @@ * Author: Simon Xue <xxm@rock-chips.com> */ +#include <dt-bindings/phy/phy.h> #include <linux/clk.h> #include <linux/delay.h> #include <linux/fs.h> @@ -142,6 +143,7 @@ #define PCIE_PL_ORDER_RULE_CTRL_OFF 0x8B4 #define RK_PCIE_L2_TMOUT_US 5000 #define RK_PCIE_HOTRESET_TMOUT_US 10000 +#define RK_PCIE_ENUM_HW_RETRYIES 2 enum rk_pcie_ltssm_code { S_L0 = 0x11, @@ -202,6 +204,8 @@ }; #define to_rk_pcie(x) dev_get_drvdata((x)->dev) +static int rk_pcie_disable_power(struct rk_pcie *rk_pcie); +static int rk_pcie_enable_power(struct rk_pcie *rk_pcie); static int rk_pcie_read(void __iomem *addr, int size, u32 *val) { @@ -702,24 +706,6 @@ rk_pcie_writel_apb(rk_pcie, 0x0, 0xC000C); } -static int rk_pcie_link_up(struct dw_pcie *pci) -{ - struct rk_pcie *rk_pcie = to_rk_pcie(pci); - u32 val; - - if (rk_pcie->is_rk1808) { - val = rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_GENERAL_DEBUG); - if ((val & (PCIE_PHY_LINKUP | PCIE_DATA_LINKUP)) == 0x3) - return 1; - } else { - val = rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_LTSSM_STATUS); - if ((val & (RDLH_LINKUP | SMLH_LINKUP)) == 0x30000) - return 1; - } - - return 0; -} - static void rk_pcie_enable_debug(struct rk_pcie *rk_pcie) { if (!IS_ENABLED(CONFIG_DEBUG_FS)) @@ -758,6 +744,8 @@ int retries, power; struct rk_pcie *rk_pcie = to_rk_pcie(pci); bool std_rc = rk_pcie->mode == RK_PCIE_RC_TYPE && !rk_pcie->dma_obj; + int hw_retries = 0; + u32 ltssm; /* * For standard RC, even if the link has been setup by firmware, @@ -769,77 +757,92 @@ return 0; } - /* Rest the device */ - gpiod_set_value_cansleep(rk_pcie->rst_gpio, 0); + for (hw_retries = 0; hw_retries < RK_PCIE_ENUM_HW_RETRYIES; hw_retries++) { + /* Rest the device */ + gpiod_set_value_cansleep(rk_pcie->rst_gpio, 0); - rk_pcie_disable_ltssm(rk_pcie); - rk_pcie_link_status_clear(rk_pcie); - rk_pcie_enable_debug(rk_pcie); + rk_pcie_disable_ltssm(rk_pcie); + rk_pcie_link_status_clear(rk_pcie); + rk_pcie_enable_debug(rk_pcie); - /* Enable client reset or link down interrupt */ - rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_MASK, 0x40000); + /* Enable client reset or link down interrupt */ + rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_MASK, 0x40000); - /* Enable LTSSM */ - rk_pcie_enable_ltssm(rk_pcie); + /* Enable LTSSM */ + rk_pcie_enable_ltssm(rk_pcie); - /* - * In resume routine, function devices' resume function must be late after - * controllers'. Some devices, such as Wi-Fi, need special IO setting before - * finishing training. So there must be timeout here. These kinds of devices - * need rescan devices by its driver when used. So no need to waste time waiting - * for training pass. - */ - if (rk_pcie->in_suspend && rk_pcie->skip_scan_in_resume) { - rfkill_get_wifi_power_state(&power); - if (!power) { - gpiod_set_value_cansleep(rk_pcie->rst_gpio, 1); - return 0; - } - } - - /* - * PCIe requires the refclk to be stable for 100µs prior to releasing - * PERST and T_PVPERL (Power stable to PERST# inactive) should be a - * minimum of 100ms. See table 2-4 in section 2.6.2 AC, the PCI Express - * Card Electromechanical Specification 3.0. So 100ms in total is the min - * requuirement here. We add a 200ms by default for sake of hoping everthings - * work fine. If it doesn't, please add more in DT node by add rockchip,perst-inactive-ms. - */ - msleep(rk_pcie->perst_inactive_ms); - gpiod_set_value_cansleep(rk_pcie->rst_gpio, 1); - - /* - * Add this 1ms delay because we observe link is always up stably after it and - * could help us save 20ms for scanning devices. - */ - usleep_range(1000, 1100); - - for (retries = 0; retries < 100; retries++) { - if (dw_pcie_link_up(pci)) { - /* - * We may be here in case of L0 in Gen1. But if EP is capable - * of Gen2 or Gen3, Gen switch may happen just in this time, but - * we keep on accessing devices in unstable link status. Given - * that LTSSM max timeout is 24ms per period, we can wait a bit - * more for Gen switch. - */ - msleep(50); - /* In case link drop after linkup, double check it */ - if (dw_pcie_link_up(pci)) { - dev_info(pci->dev, "PCIe Link up, LTSSM is 0x%x\n", - rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_LTSSM_STATUS)); - rk_pcie_debug_dump(rk_pcie); + /* + * In resume routine, function devices' resume function must be late after + * controllers'. Some devices, such as Wi-Fi, need special IO setting before + * finishing training. So there must be timeout here. These kinds of devices + * need rescan devices by its driver when used. So no need to waste time waiting + * for training pass. + */ + if (rk_pcie->in_suspend && rk_pcie->skip_scan_in_resume) { + rfkill_get_wifi_power_state(&power); + if (!power) { + gpiod_set_value_cansleep(rk_pcie->rst_gpio, 1); return 0; } } - dev_info_ratelimited(pci->dev, "PCIe Linking... LTSSM is 0x%x\n", - rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_LTSSM_STATUS)); - rk_pcie_debug_dump(rk_pcie); - msleep(20); - } + /* + * PCIe requires the refclk to be stable for 100µs prior to releasing + * PERST and T_PVPERL (Power stable to PERST# inactive) should be a + * minimum of 100ms. See table 2-4 in section 2.6.2 AC, the PCI Express + * Card Electromechanical Specification 3.0. So 100ms in total is the min + * requuirement here. We add a 200ms by default for sake of hoping everthings + * work fine. If it doesn't, please add more in DT node by add rockchip,perst-inactive-ms. + */ + msleep(rk_pcie->perst_inactive_ms); + gpiod_set_value_cansleep(rk_pcie->rst_gpio, 1); - dev_err(pci->dev, "PCIe Link Fail\n"); + /* + * Add this 1ms delay because we observe link is always up stably after it and + * could help us save 20ms for scanning devices. + */ + usleep_range(1000, 1100); + + for (retries = 0; retries < 100; retries++) { + if (dw_pcie_link_up(pci)) { + /* + * We may be here in case of L0 in Gen1. But if EP is capable + * of Gen2 or Gen3, Gen switch may happen just in this time, but + * we keep on accessing devices in unstable link status. Given + * that LTSSM max timeout is 24ms per period, we can wait a bit + * more for Gen switch. + */ + msleep(50); + /* In case link drop after linkup, double check it */ + if (dw_pcie_link_up(pci)) { + dev_info(pci->dev, "PCIe Link up, LTSSM is 0x%x\n", + rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_LTSSM_STATUS)); + rk_pcie_debug_dump(rk_pcie); + return 0; + } + } + + dev_info_ratelimited(pci->dev, "PCIe Linking... LTSSM is 0x%x\n", + rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_LTSSM_STATUS)); + rk_pcie_debug_dump(rk_pcie); + msleep(20); + } + + /* + * In response to the situation where PCIe peripherals cannot be + * enumerated due tosignal abnormalities, reset PERST# and reset + * the peripheral power supply, then restart the enumeration. + */ + ltssm = rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_LTSSM_STATUS); + dev_err(pci->dev, "PCIe Link Fail, LTSSM is 0x%x, hw_retries=%d\n", ltssm, hw_retries); + if (ltssm >= 3 && !rk_pcie->is_signal_test) { + rk_pcie_disable_power(rk_pcie); + msleep(1000); + rk_pcie_enable_power(rk_pcie); + } else { + break; + } + } return rk_pcie->is_signal_test == true ? 0 : -EINVAL; } @@ -1129,8 +1132,8 @@ dw_pcie_setup_rc(pp); /* Disable BAR0 BAR1 */ - dw_pcie_writel_dbi(pci, PCIE_TYPE0_HDR_DBI2_OFFSET + 0x10 + BAR_0 * 4, 0); - dw_pcie_writel_dbi(pci, PCIE_TYPE0_HDR_DBI2_OFFSET + 0x10 + BAR_1 * 4, 0); + dw_pcie_writel_dbi2(pci, PCI_BASE_ADDRESS_0, 0x0); + dw_pcie_writel_dbi2(pci, PCI_BASE_ADDRESS_1, 0x0); ret = rk_pcie_establish_link(pci); @@ -1203,7 +1206,6 @@ return ret; } - rk_pcie->pci->dbi_base2 = rk_pcie->pci->dbi_base + PCIE_TYPE0_HDR_DBI2_OFFSET; rk_pcie->pci->atu_base = rk_pcie->pci->dbi_base + DEFAULT_DBI_ATU_OFFSET; rk_pcie->pci->iatu_unroll_enabled = rk_pcie_iatu_unroll_enabled(rk_pcie->pci); @@ -1263,6 +1265,7 @@ return PTR_ERR(rk_pcie->dbi_base); rk_pcie->pci->dbi_base = rk_pcie->dbi_base; + rk_pcie->pci->dbi_base2 = rk_pcie->pci->dbi_base + PCIE_TYPE0_HDR_DBI2_OFFSET; apb_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcie-apb"); @@ -1601,7 +1604,6 @@ static const struct dw_pcie_ops dw_pcie_ops = { .start_link = rk_pcie_establish_link, - .link_up = rk_pcie_link_up, }; static int rk1808_pcie_fixup(struct rk_pcie *rk_pcie, struct device_node *np) @@ -1988,6 +1990,7 @@ if (!IS_ERR_OR_NULL(rk_pcie->prsnt_gpio)) { if (!gpiod_get_value(rk_pcie->prsnt_gpio)) { + dev_info(dev, "device isn't present\n"); ret = -ENODEV; goto release_driver; } @@ -2354,6 +2357,12 @@ no_l2: rk_pcie_disable_ltssm(rk_pcie); + ret = phy_validate(rk_pcie->phy, PHY_TYPE_PCIE, 0, NULL); + if (ret && ret != -EOPNOTSUPP) { + dev_err(dev, "PHY is reused by other controller, check the dts!\n"); + return ret; + } + /* make sure assert phy success */ usleep_range(200, 300); -- Gitblit v1.6.2