From 5a0cf0dd73a12522337bec07d7fa65895389d105 Mon Sep 17 00:00:00 2001 From: "Kevin.xie" Date: Mon, 11 Sep 2023 18:07:36 +0800 Subject: riscv: dts: Add link state register to PCIe syscon nodes. Signed-off-by: Kevin.xie --- arch/riscv/dts/jh7110.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/riscv/dts/jh7110.dtsi b/arch/riscv/dts/jh7110.dtsi index 1022a08db5..3f3098b96b 100644 --- a/arch/riscv/dts/jh7110.dtsi +++ b/arch/riscv/dts/jh7110.dtsi @@ -1197,7 +1197,7 @@ <0x9 0x40000000 0x0 0x10000000>; reg-names = "reg", "config"; device_type = "pci"; - starfive,stg-syscon = <&stg_syscon 0xc0 0xc4 0x130>; + starfive,stg-syscon = <&stg_syscon 0xc0 0xc4 0x130 0x1b8>; bus-range = <0x0 0xff>; ranges = <0x82000000 0x0 0x30000000 0x0 0x30000000 0x0 0x08000000>, <0xc3000000 0x9 0x00000000 0x9 0x00000000 0x0 0x40000000>; @@ -1236,7 +1236,7 @@ <0x9 0xc0000000 0x0 0x10000000>; reg-names = "reg", "config"; device_type = "pci"; - starfive,stg-syscon = <&stg_syscon 0x270 0x274 0x2e0>; + starfive,stg-syscon = <&stg_syscon 0x270 0x274 0x2e0 0x368>; bus-range = <0x0 0xff>; ranges = <0x82000000 0x0 0x38000000 0x0 0x38000000 0x0 0x08000000>, <0xc3000000 0x9 0x80000000 0x9 0x80000000 0x0 0x40000000>; -- cgit v1.2.3 From 0c0a3017a28d4583e7d2e1d9265912fe4cc850ff Mon Sep 17 00:00:00 2001 From: "Kevin.xie" Date: Mon, 11 Sep 2023 18:09:20 +0800 Subject: drivers: pci: Update reset & link wait timing as spec required. 1. Modified reset assert duration to 100ms. 2. Wait 10-100 ms for link training. 3. If link is up, delay 100ms before doing any configuration space access. Reference spec: PCIe Base Spec r6.0 & CEM 2.0. Signed-off-by: Kevin.xie --- drivers/pci/pcie_starfive.c | 49 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/drivers/pci/pcie_starfive.c b/drivers/pci/pcie_starfive.c index d31d8b6e3a..d5a812d36a 100644 --- a/drivers/pci/pcie_starfive.c +++ b/drivers/pci/pcie_starfive.c @@ -40,6 +40,10 @@ DECLARE_GLOBAL_DATA_PTR; #define IDS_PCI_TO_PCI_BRIDGE 0x060400 #define IDS_CLASS_CODE_SHIFT 8 +#define PLDA_LINK_UP 1 +#define PLDA_LINK_DOWN 0 + +#define PLDA_DATA_LINK_ACTIVE BIT(5) #define PREF_MEM_WIN_64_SUPPORT BIT(3) #define PMSG_LTR_SUPPORT BIT(2) #define PLDA_FUNCTION_DIS BIT(15) @@ -92,6 +96,7 @@ struct starfive_pcie { u32 stg_arfun; u32 stg_awfun; u32 stg_rp_nep; + u32 stg_lnksta; struct clk_bulk clks; struct reset_ctl_bulk rsts; @@ -267,7 +272,7 @@ static int starfive_pcie_get_syscon(struct udevice *dev) struct starfive_pcie *priv = dev_get_priv(dev); struct udevice *syscon; struct ofnode_phandle_args syscfg_phandle; - u32 cells[4]; + u32 cells[5]; int ret; /* get corresponding syscon phandle */ @@ -300,11 +305,12 @@ static int starfive_pcie_get_syscon(struct udevice *dev) return -EINVAL; } - dev_dbg(dev, "Get syscon values: %x, %x, %x\n", - cells[1], cells[2], cells[3]); + dev_dbg(dev, "Get syscon values: %x, %x, %x, %x\n", + cells[1], cells[2], cells[3], cells[4]); priv->stg_arfun = cells[1]; priv->stg_awfun = cells[2]; priv->stg_rp_nep = cells[3]; + priv->stg_lnksta = cells[4]; return 0; } @@ -431,7 +437,7 @@ static int starfive_pcie_init_port(struct udevice *dev) starfive_pcie_atr_init(priv); /* Ensure that PERST has been asserted for at least 300 ms */ - mdelay(300); + mdelay(100); ret = pinctrl_select_state(dev, "perst-default"); if (ret) { dev_err(dev, "Set perst-default pinctrl failed: %d\n", ret); @@ -450,6 +456,33 @@ err_deassert_clk: return ret; } +static int plda_pcie_is_link_up(struct udevice *dev) +{ + struct starfive_pcie *priv = dev_get_priv(dev); + int ret; + u32 stg_reg_val; + + /* 100ms timeout value should be enough for Gen1/2 training */ + ret = regmap_read_poll_timeout(priv->regmap, + priv->stg_lnksta, + stg_reg_val, + stg_reg_val & PLDA_DATA_LINK_ACTIVE, + 10 * 1000, 100); + + /* If the link is down (no device in slot), then exit. */ + if (ret == -ETIMEDOUT) { + dev_err(dev, "Port link down.\n"); + return PLDA_LINK_DOWN; + } else if (ret == 0) { + dev_err(dev, "Port link up.\n"); + return PLDA_LINK_UP; + } + + dev_warn(dev, "Read stg_linksta failed.\n"); + return ret; +} + + static int starfive_pcie_probe(struct udevice *dev) { struct starfive_pcie *priv = dev_get_priv(dev); @@ -482,6 +515,14 @@ static int starfive_pcie_probe(struct udevice *dev) if (ret) return ret; + if (plda_pcie_is_link_up(dev) == PLDA_LINK_UP) { + /* As the requirement in PCIe base spec r6.0, system (<=5GT/s) must + * wait a minimum of 100 ms following exit from a conventional reset + * before sending a configuration request to the device. + */ + mdelay(100); + } + dev_err(dev, "Starfive PCIe bus probed.\n"); return 0; -- cgit v1.2.3