diff options
| author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2025-08-06 10:08:54 -0700 | 
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2025-08-06 10:08:54 -0700 | 
| commit | ab93e0dd72c37d378dd936f031ffb83ff2bd87ce (patch) | |
| tree | 4e5ed022e3c48cedd519954e4fb529dac0240c94 /drivers/pci/controller/dwc | |
| parent | bcce05041b21888f10b80ea903dcfe51a25c586e (diff) | |
| parent | 4f67c41894674d351a4b4e7dd3471380b71b5bb3 (diff) | |
Merge branch 'next' into for-linus
Prepare input updates for 6.17 merge window.
Diffstat (limited to 'drivers/pci/controller/dwc')
24 files changed, 705 insertions, 156 deletions
| diff --git a/drivers/pci/controller/dwc/pci-dra7xx.c b/drivers/pci/controller/dwc/pci-dra7xx.c index 33d6bf460ffe..f97f5266d196 100644 --- a/drivers/pci/controller/dwc/pci-dra7xx.c +++ b/drivers/pci/controller/dwc/pci-dra7xx.c @@ -118,12 +118,12 @@ static u64 dra7xx_pcie_cpu_addr_fixup(struct dw_pcie *pci, u64 cpu_addr)  	return cpu_addr & DRA7XX_CPU_TO_BUS_ADDR;  } -static int dra7xx_pcie_link_up(struct dw_pcie *pci) +static bool dra7xx_pcie_link_up(struct dw_pcie *pci)  {  	struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci);  	u32 reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_PHY_CS); -	return !!(reg & LINK_UP); +	return reg & LINK_UP;  }  static void dra7xx_pcie_stop_link(struct dw_pcie *pci) @@ -359,8 +359,8 @@ static int dra7xx_pcie_init_irq_domain(struct dw_pcie_rp *pp)  	irq_set_chained_handler_and_data(pp->irq, dra7xx_pcie_msi_irq_handler,  					 pp); -	dra7xx->irq_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX, -						   &intx_domain_ops, pp); +	dra7xx->irq_domain = irq_domain_create_linear(of_fwnode_handle(pcie_intc_node), +						      PCI_NUM_INTX, &intx_domain_ops, pp);  	of_node_put(pcie_intc_node);  	if (!dra7xx->irq_domain) {  		dev_err(dev, "Failed to get a INTx IRQ domain\n"); diff --git a/drivers/pci/controller/dwc/pci-exynos.c b/drivers/pci/controller/dwc/pci-exynos.c index ace736b025b1..1f0e98d07109 100644 --- a/drivers/pci/controller/dwc/pci-exynos.c +++ b/drivers/pci/controller/dwc/pci-exynos.c @@ -209,12 +209,12 @@ static struct pci_ops exynos_pci_ops = {  	.write = exynos_pcie_wr_own_conf,  }; -static int exynos_pcie_link_up(struct dw_pcie *pci) +static bool exynos_pcie_link_up(struct dw_pcie *pci)  {  	struct exynos_pcie *ep = to_exynos_pcie(pci);  	u32 val = exynos_pcie_readl(ep->elbi_base, PCIE_ELBI_RDLH_LINKUP); -	return (val & PCIE_ELBI_XMLH_LINKUP); +	return val & PCIE_ELBI_XMLH_LINKUP;  }  static int exynos_pcie_host_init(struct dw_pcie_rp *pp) diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c index 5f267dd261b5..5a38cfaf989b 100644 --- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -45,9 +45,14 @@  #define IMX95_PCIE_PHY_GEN_CTRL			0x0  #define IMX95_PCIE_REF_USE_PAD			BIT(17) +#define IMX95_PCIE_PHY_MPLLA_CTRL		0x10 +#define IMX95_PCIE_PHY_MPLL_STATE		BIT(30) +  #define IMX95_PCIE_SS_RW_REG_0			0xf0  #define IMX95_PCIE_REF_CLKEN			BIT(23)  #define IMX95_PCIE_PHY_CR_PARA_SEL		BIT(9) +#define IMX95_PCIE_SS_RW_REG_1			0xf4 +#define IMX95_PCIE_SYS_AUX_PWR_DET		BIT(31)  #define IMX95_PE0_GEN_CTRL_1			0x1050  #define IMX95_PCIE_DEVICE_TYPE			GENMASK(3, 0) @@ -71,6 +76,9 @@  #define IMX95_SID_MASK				GENMASK(5, 0)  #define IMX95_MAX_LUT				32 +#define IMX95_PCIE_RST_CTRL			0x3010 +#define IMX95_PCIE_COLD_RST			BIT(0) +  #define to_imx_pcie(x)	dev_get_drvdata((x)->dev)  enum imx_pcie_variants { @@ -91,7 +99,7 @@ enum imx_pcie_variants {  };  #define IMX_PCIE_FLAG_IMX_PHY			BIT(0) -#define IMX_PCIE_FLAG_IMX_SPEED_CHANGE		BIT(1) +#define IMX_PCIE_FLAG_SPEED_CHANGE_WORKAROUND	BIT(1)  #define IMX_PCIE_FLAG_SUPPORTS_SUSPEND		BIT(2)  #define IMX_PCIE_FLAG_HAS_PHYDRV		BIT(3)  #define IMX_PCIE_FLAG_HAS_APP_RESET		BIT(4) @@ -105,6 +113,7 @@ enum imx_pcie_variants {   */  #define IMX_PCIE_FLAG_BROKEN_SUSPEND		BIT(9)  #define IMX_PCIE_FLAG_HAS_LUT			BIT(10) +#define IMX_PCIE_FLAG_8GT_ECN_ERR051586		BIT(11)  #define imx_check_flag(pci, val)	(pci->drvdata->flags & val) @@ -126,9 +135,15 @@ struct imx_pcie_drvdata {  	int (*init_phy)(struct imx_pcie *pcie);  	int (*enable_ref_clk)(struct imx_pcie *pcie, bool enable);  	int (*core_reset)(struct imx_pcie *pcie, bool assert); +	int (*wait_pll_lock)(struct imx_pcie *pcie);  	const struct dw_pcie_host_ops *ops;  }; +struct imx_lut_data { +	u32 data1; +	u32 data2; +}; +  struct imx_pcie {  	struct dw_pcie		*pci;  	struct gpio_desc	*reset_gpiod; @@ -148,6 +163,8 @@ struct imx_pcie {  	struct regulator	*vph;  	void __iomem		*phy_base; +	/* LUT data for pcie */ +	struct imx_lut_data	luts[IMX95_MAX_LUT];  	/* power domain for pcie */  	struct device		*pd_pcie;  	/* power domain for pcie phy */ @@ -224,6 +241,19 @@ static unsigned int imx_pcie_grp_offset(const struct imx_pcie *imx_pcie)  static int imx95_pcie_init_phy(struct imx_pcie *imx_pcie)  { +	/* +	 * ERR051624: The Controller Without Vaux Cannot Exit L23 Ready +	 * Through Beacon or PERST# De-assertion +	 * +	 * When the auxiliary power is not available, the controller +	 * cannot exit from L23 Ready with beacon or PERST# de-assertion +	 * when main power is not removed. +	 * +	 * Workaround: Set SS_RW_REG_1[SYS_AUX_PWR_DET] to 1. +	 */ +	regmap_set_bits(imx_pcie->iomuxc_gpr, IMX95_PCIE_SS_RW_REG_1, +			IMX95_PCIE_SYS_AUX_PWR_DET); +  	regmap_update_bits(imx_pcie->iomuxc_gpr,  			IMX95_PCIE_SS_RW_REG_0,  			IMX95_PCIE_PHY_CR_PARA_SEL, @@ -460,6 +490,23 @@ static void imx7d_pcie_wait_for_phy_pll_lock(struct imx_pcie *imx_pcie)  		dev_err(dev, "PCIe PLL lock timeout\n");  } +static int imx95_pcie_wait_for_phy_pll_lock(struct imx_pcie *imx_pcie) +{ +	u32 val; +	struct device *dev = imx_pcie->pci->dev; + +	if (regmap_read_poll_timeout(imx_pcie->iomuxc_gpr, +				     IMX95_PCIE_PHY_MPLLA_CTRL, val, +				     val & IMX95_PCIE_PHY_MPLL_STATE, +				     PHY_PLL_LOCK_WAIT_USLEEP_MAX, +				     PHY_PLL_LOCK_WAIT_TIMEOUT)) { +		dev_err(dev, "PCIe PLL lock timeout\n"); +		return -ETIMEDOUT; +	} + +	return 0; +} +  static int imx_setup_phy_mpll(struct imx_pcie *imx_pcie)  {  	unsigned long phy_rate = 0; @@ -773,6 +820,43 @@ static int imx7d_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert)  	return 0;  } +static int imx95_pcie_core_reset(struct imx_pcie *imx_pcie, bool assert) +{ +	u32 val; + +	if (assert) { +		/* +		 * From i.MX95 PCIe PHY perspective, the COLD reset toggle +		 * should be complete after power-up by the following sequence. +		 *                 > 10us(at power-up) +		 *                 > 10ns(warm reset) +		 *               |<------------>| +		 *                ______________ +		 * phy_reset ____/              \________________ +		 *                                   ____________ +		 * ref_clk_en_______________________/ +		 * Toggle COLD reset aligned with this sequence for i.MX95 PCIe. +		 */ +		regmap_set_bits(imx_pcie->iomuxc_gpr, IMX95_PCIE_RST_CTRL, +				IMX95_PCIE_COLD_RST); +		/* +		 * Make sure the write to IMX95_PCIE_RST_CTRL is flushed to the +		 * hardware by doing a read. Otherwise, there is no guarantee +		 * that the write has reached the hardware before udelay(). +		 */ +		regmap_read_bypassed(imx_pcie->iomuxc_gpr, IMX95_PCIE_RST_CTRL, +				     &val); +		udelay(15); +		regmap_clear_bits(imx_pcie->iomuxc_gpr, IMX95_PCIE_RST_CTRL, +				  IMX95_PCIE_COLD_RST); +		regmap_read_bypassed(imx_pcie->iomuxc_gpr, IMX95_PCIE_RST_CTRL, +				     &val); +		udelay(10); +	} + +	return 0; +} +  static void imx_pcie_assert_core_reset(struct imx_pcie *imx_pcie)  {  	reset_control_assert(imx_pcie->pciephy_reset); @@ -860,6 +944,12 @@ static int imx_pcie_start_link(struct dw_pcie *pci)  	u32 tmp;  	int ret; +	if (!(imx_pcie->drvdata->flags & +	    IMX_PCIE_FLAG_SPEED_CHANGE_WORKAROUND)) { +		imx_pcie_ltssm_enable(dev); +		return 0; +	} +  	/*  	 * Force Gen1 operation when starting the link.  In case the link is  	 * started in Gen2 mode, there is a possibility the devices on the @@ -875,11 +965,11 @@ static int imx_pcie_start_link(struct dw_pcie *pci)  	/* Start LTSSM. */  	imx_pcie_ltssm_enable(dev); -	ret = dw_pcie_wait_for_link(pci); -	if (ret) -		goto err_reset_phy; -  	if (pci->max_link_speed > 1) { +		ret = dw_pcie_wait_for_link(pci); +		if (ret) +			goto err_reset_phy; +  		/* Allow faster modes after the link is up */  		dw_pcie_dbi_ro_wr_en(pci);  		tmp = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP); @@ -896,34 +986,15 @@ static int imx_pcie_start_link(struct dw_pcie *pci)  		dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp);  		dw_pcie_dbi_ro_wr_dis(pci); -		if (imx_pcie->drvdata->flags & -		    IMX_PCIE_FLAG_IMX_SPEED_CHANGE) { - -			/* -			 * On i.MX7, DIRECT_SPEED_CHANGE behaves differently -			 * from i.MX6 family when no link speed transition -			 * occurs and we go Gen1 -> yep, Gen1. The difference -			 * is that, in such case, it will not be cleared by HW -			 * which will cause the following code to report false -			 * failure. -			 */ -			ret = imx_pcie_wait_for_speed_change(imx_pcie); -			if (ret) { -				dev_err(dev, "Failed to bring link up!\n"); -				goto err_reset_phy; -			} -		} - -		/* Make sure link training is finished as well! */ -		ret = dw_pcie_wait_for_link(pci); -		if (ret) +		ret = imx_pcie_wait_for_speed_change(imx_pcie); +		if (ret) { +			dev_err(dev, "Failed to bring link up!\n");  			goto err_reset_phy; +		}  	} else {  		dev_info(dev, "Link: Only Gen1 is enabled\n");  	} -	tmp = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA); -	dev_info(dev, "Link up, Gen%i\n", tmp & PCI_EXP_LNKSTA_CLS);  	return 0;  err_reset_phy: @@ -1182,6 +1253,12 @@ static int imx_pcie_host_init(struct dw_pcie_rp *pp)  		goto err_phy_off;  	} +	if (imx_pcie->drvdata->wait_pll_lock) { +		ret = imx_pcie->drvdata->wait_pll_lock(imx_pcie); +		if (ret < 0) +			goto err_phy_off; +	} +  	imx_setup_phy_mpll(imx_pcie);  	return 0; @@ -1214,6 +1291,32 @@ static void imx_pcie_host_exit(struct dw_pcie_rp *pp)  		regulator_disable(imx_pcie->vpcie);  } +static void imx_pcie_host_post_init(struct dw_pcie_rp *pp) +{ +	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); +	struct imx_pcie *imx_pcie = to_imx_pcie(pci); +	u32 val; + +	if (imx_pcie->drvdata->flags & IMX_PCIE_FLAG_8GT_ECN_ERR051586) { +		/* +		 * ERR051586: Compliance with 8GT/s Receiver Impedance ECN +		 * +		 * The default value of GEN3_RELATED_OFF[GEN3_ZRXDC_NONCOMPL] +		 * is 1 which makes receiver non-compliant with the ZRX-DC +		 * parameter for 2.5 GT/s when operating at 8 GT/s or higher. +		 * It causes unnecessary timeout in L1. +		 * +		 * Workaround: Program GEN3_RELATED_OFF[GEN3_ZRXDC_NONCOMPL] +		 * to 0. +		 */ +		dw_pcie_dbi_ro_wr_en(pci); +		val = dw_pcie_readl_dbi(pci, GEN3_RELATED_OFF); +		val &= ~GEN3_RELATED_OFF_GEN3_ZRXDC_NONCOMPL; +		dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, val); +		dw_pcie_dbi_ro_wr_dis(pci); +	} +} +  /*   * In old DWC implementations, PCIE_ATU_INHIBIT_PAYLOAD in iATU Ctrl2   * register is reserved, so the generic DWC implementation of sending the @@ -1239,6 +1342,7 @@ static const struct dw_pcie_host_ops imx_pcie_host_ops = {  static const struct dw_pcie_host_ops imx_pcie_host_dw_pme_ops = {  	.init = imx_pcie_host_init,  	.deinit = imx_pcie_host_exit, +	.post_init = imx_pcie_host_post_init,  };  static const struct dw_pcie_ops dw_pcie_ops = { @@ -1350,6 +1454,7 @@ static int imx_add_pcie_ep(struct imx_pcie *imx_pcie,  		dev_err(dev, "failed to initialize endpoint\n");  		return ret;  	} +	imx_pcie_host_post_init(pp);  	ret = dw_pcie_ep_init_registers(ep);  	if (ret) { @@ -1386,6 +1491,42 @@ static void imx_pcie_msi_save_restore(struct imx_pcie *imx_pcie, bool save)  	}  } +static void imx_pcie_lut_save(struct imx_pcie *imx_pcie) +{ +	u32 data1, data2; +	int i; + +	for (i = 0; i < IMX95_MAX_LUT; i++) { +		regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_ACSCTRL, +			     IMX95_PEO_LUT_RWA | i); +		regmap_read(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA1, &data1); +		regmap_read(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA2, &data2); +		if (data1 & IMX95_PE0_LUT_VLD) { +			imx_pcie->luts[i].data1 = data1; +			imx_pcie->luts[i].data2 = data2; +		} else { +			imx_pcie->luts[i].data1 = 0; +			imx_pcie->luts[i].data2 = 0; +		} +	} +} + +static void imx_pcie_lut_restore(struct imx_pcie *imx_pcie) +{ +	int i; + +	for (i = 0; i < IMX95_MAX_LUT; i++) { +		if ((imx_pcie->luts[i].data1 & IMX95_PE0_LUT_VLD) == 0) +			continue; + +		regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA1, +			     imx_pcie->luts[i].data1); +		regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_DATA2, +			     imx_pcie->luts[i].data2); +		regmap_write(imx_pcie->iomuxc_gpr, IMX95_PE0_LUT_ACSCTRL, i); +	} +} +  static int imx_pcie_suspend_noirq(struct device *dev)  {  	struct imx_pcie *imx_pcie = dev_get_drvdata(dev); @@ -1394,6 +1535,8 @@ static int imx_pcie_suspend_noirq(struct device *dev)  		return 0;  	imx_pcie_msi_save_restore(imx_pcie, true); +	if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT)) +		imx_pcie_lut_save(imx_pcie);  	if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_BROKEN_SUSPEND)) {  		/*  		 * The minimum for a workaround would be to set PERST# and to @@ -1438,6 +1581,8 @@ static int imx_pcie_resume_noirq(struct device *dev)  		if (ret)  			return ret;  	} +	if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT)) +		imx_pcie_lut_restore(imx_pcie);  	imx_pcie_msi_save_restore(imx_pcie, false);  	return 0; @@ -1649,7 +1794,7 @@ static const struct imx_pcie_drvdata drvdata[] = {  	[IMX6Q] = {  		.variant = IMX6Q,  		.flags = IMX_PCIE_FLAG_IMX_PHY | -			 IMX_PCIE_FLAG_IMX_SPEED_CHANGE | +			 IMX_PCIE_FLAG_SPEED_CHANGE_WORKAROUND |  			 IMX_PCIE_FLAG_BROKEN_SUSPEND |  			 IMX_PCIE_FLAG_SUPPORTS_SUSPEND,  		.dbi_length = 0x200, @@ -1665,7 +1810,7 @@ static const struct imx_pcie_drvdata drvdata[] = {  	[IMX6SX] = {  		.variant = IMX6SX,  		.flags = IMX_PCIE_FLAG_IMX_PHY | -			 IMX_PCIE_FLAG_IMX_SPEED_CHANGE | +			 IMX_PCIE_FLAG_SPEED_CHANGE_WORKAROUND |  			 IMX_PCIE_FLAG_SUPPORTS_SUSPEND,  		.gpr = "fsl,imx6q-iomuxc-gpr",  		.ltssm_off = IOMUXC_GPR12, @@ -1680,7 +1825,7 @@ static const struct imx_pcie_drvdata drvdata[] = {  	[IMX6QP] = {  		.variant = IMX6QP,  		.flags = IMX_PCIE_FLAG_IMX_PHY | -			 IMX_PCIE_FLAG_IMX_SPEED_CHANGE | +			 IMX_PCIE_FLAG_SPEED_CHANGE_WORKAROUND |  			 IMX_PCIE_FLAG_SUPPORTS_SUSPEND,  		.dbi_length = 0x200,  		.gpr = "fsl,imx6q-iomuxc-gpr", @@ -1747,12 +1892,15 @@ static const struct imx_pcie_drvdata drvdata[] = {  		.variant = IMX95,  		.flags = IMX_PCIE_FLAG_HAS_SERDES |  			 IMX_PCIE_FLAG_HAS_LUT | +			 IMX_PCIE_FLAG_8GT_ECN_ERR051586 |  			 IMX_PCIE_FLAG_SUPPORTS_SUSPEND,  		.ltssm_off = IMX95_PE0_GEN_CTRL_3,  		.ltssm_mask = IMX95_PCIE_LTSSM_EN,  		.mode_off[0]  = IMX95_PE0_GEN_CTRL_1,  		.mode_mask[0] = IMX95_PCIE_DEVICE_TYPE, +		.core_reset = imx95_pcie_core_reset,  		.init_phy = imx95_pcie_init_phy, +		.wait_pll_lock = imx95_pcie_wait_for_phy_pll_lock,  	},  	[IMX8MQ_EP] = {  		.variant = IMX8MQ_EP, @@ -1799,12 +1947,15 @@ static const struct imx_pcie_drvdata drvdata[] = {  	[IMX95_EP] = {  		.variant = IMX95_EP,  		.flags = IMX_PCIE_FLAG_HAS_SERDES | +			 IMX_PCIE_FLAG_8GT_ECN_ERR051586 |  			 IMX_PCIE_FLAG_SUPPORT_64BIT,  		.ltssm_off = IMX95_PE0_GEN_CTRL_3,  		.ltssm_mask = IMX95_PCIE_LTSSM_EN,  		.mode_off[0]  = IMX95_PE0_GEN_CTRL_1,  		.mode_mask[0] = IMX95_PCIE_DEVICE_TYPE,  		.init_phy = imx95_pcie_init_phy, +		.core_reset = imx95_pcie_core_reset, +		.wait_pll_lock = imx95_pcie_wait_for_phy_pll_lock,  		.epc_features = &imx95_pcie_epc_features,  		.mode = DW_PCIE_EP_TYPE,  	}, diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c index 76a37368ae4f..2b2632e513b5 100644 --- a/drivers/pci/controller/dwc/pci-keystone.c +++ b/drivers/pci/controller/dwc/pci-keystone.c @@ -492,13 +492,12 @@ static struct pci_ops ks_pcie_ops = {   * @pci: A pointer to the dw_pcie structure which holds the DesignWare PCIe host   *	 controller driver information.   */ -static int ks_pcie_link_up(struct dw_pcie *pci) +static bool ks_pcie_link_up(struct dw_pcie *pci)  {  	u32 val;  	val = dw_pcie_readl_dbi(pci, PCIE_PORT_DEBUG0); -	val &= PORT_LOGIC_LTSSM_STATE_MASK; -	return (val == PORT_LOGIC_LTSSM_STATE_L0); +	return (val & PORT_LOGIC_LTSSM_STATE_MASK) == PORT_LOGIC_LTSSM_STATE_L0;  }  static void ks_pcie_stop_link(struct dw_pcie *pci) @@ -761,7 +760,7 @@ static int ks_pcie_config_intx_irq(struct keystone_pcie *ks_pcie)  						 ks_pcie);  	} -	intx_irq_domain = irq_domain_add_linear(intc_np, PCI_NUM_INTX, +	intx_irq_domain = irq_domain_create_linear(of_fwnode_handle(intc_np), PCI_NUM_INTX,  					&ks_pcie_intx_irq_domain_ops, NULL);  	if (!intx_irq_domain) {  		dev_err(dev, "Failed to add irq domain for INTX irqs\n"); diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c index db9482a113e9..787469d1b396 100644 --- a/drivers/pci/controller/dwc/pci-meson.c +++ b/drivers/pci/controller/dwc/pci-meson.c @@ -335,7 +335,7 @@ static struct pci_ops meson_pci_ops = {  	.write = pci_generic_config_write,  }; -static int meson_pcie_link_up(struct dw_pcie *pci) +static bool meson_pcie_link_up(struct dw_pcie *pci)  {  	struct meson_pcie *mp = to_meson_pcie(pci);  	struct device *dev = pci->dev; @@ -363,7 +363,7 @@ static int meson_pcie_link_up(struct dw_pcie *pci)  			dev_dbg(dev, "speed_okay\n");  		if (smlh_up && rdlh_up && ltssm_up && speed_okay) -			return 1; +			return true;  		cnt++; @@ -371,7 +371,7 @@ static int meson_pcie_link_up(struct dw_pcie *pci)  	} while (cnt < WAIT_LINKUP_TIMEOUT);  	dev_err(dev, "error: wait linkup timeout\n"); -	return 0; +	return false;  }  static int meson_pcie_host_init(struct dw_pcie_rp *pp) diff --git a/drivers/pci/controller/dwc/pcie-amd-mdb.c b/drivers/pci/controller/dwc/pcie-amd-mdb.c index 4eb2a4e8189d..9f7251a16d32 100644 --- a/drivers/pci/controller/dwc/pcie-amd-mdb.c +++ b/drivers/pci/controller/dwc/pcie-amd-mdb.c @@ -290,8 +290,8 @@ static int amd_mdb_pcie_init_irq_domains(struct amd_mdb_pcie *pcie,  		return -ENODEV;  	} -	pcie->mdb_domain = irq_domain_add_linear(pcie_intc_node, 32, -						 &event_domain_ops, pcie); +	pcie->mdb_domain = irq_domain_create_linear(of_fwnode_handle(pcie_intc_node), 32, +						    &event_domain_ops, pcie);  	if (!pcie->mdb_domain) {  		err = -ENOMEM;  		dev_err(dev, "Failed to add MDB domain\n"); @@ -300,8 +300,8 @@ static int amd_mdb_pcie_init_irq_domains(struct amd_mdb_pcie *pcie,  	irq_domain_update_bus_token(pcie->mdb_domain, DOMAIN_BUS_NEXUS); -	pcie->intx_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX, -						  &amd_intx_domain_ops, pcie); +	pcie->intx_domain = irq_domain_create_linear(of_fwnode_handle(pcie_intc_node), +						     PCI_NUM_INTX, &amd_intx_domain_ops, pcie);  	if (!pcie->intx_domain) {  		err = -ENOMEM;  		dev_err(dev, "Failed to add INTx domain\n"); diff --git a/drivers/pci/controller/dwc/pcie-armada8k.c b/drivers/pci/controller/dwc/pcie-armada8k.c index b5c599ccaacf..c2650fd0d458 100644 --- a/drivers/pci/controller/dwc/pcie-armada8k.c +++ b/drivers/pci/controller/dwc/pcie-armada8k.c @@ -139,7 +139,7 @@ static int armada8k_pcie_setup_phys(struct armada8k_pcie *pcie)  	return ret;  } -static int armada8k_pcie_link_up(struct dw_pcie *pci) +static bool armada8k_pcie_link_up(struct dw_pcie *pci)  {  	u32 reg;  	u32 mask = PCIE_GLB_STS_RDLH_LINK_UP | PCIE_GLB_STS_PHY_LINK_UP; @@ -147,10 +147,10 @@ static int armada8k_pcie_link_up(struct dw_pcie *pci)  	reg = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_STATUS_REG);  	if ((reg & mask) == mask) -		return 1; +		return true;  	dev_dbg(pci->dev, "No link detected (Global-Status: 0x%08x).\n", reg); -	return 0; +	return false;  }  static int armada8k_pcie_start_link(struct dw_pcie *pci) diff --git a/drivers/pci/controller/dwc/pcie-designware-debugfs.c b/drivers/pci/controller/dwc/pcie-designware-debugfs.c index 9e6f4d00f262..c67601096c48 100644 --- a/drivers/pci/controller/dwc/pcie-designware-debugfs.c +++ b/drivers/pci/controller/dwc/pcie-designware-debugfs.c @@ -642,16 +642,262 @@ static void dwc_pcie_ltssm_debugfs_init(struct dw_pcie *pci, struct dentry *dir)  			    &dwc_pcie_ltssm_status_ops);  } +static int dw_pcie_ptm_check_capability(void *drvdata) +{ +	struct dw_pcie *pci = drvdata; + +	pci->ptm_vsec_offset = dw_pcie_find_ptm_capability(pci); + +	return pci->ptm_vsec_offset; +} + +static int dw_pcie_ptm_context_update_write(void *drvdata, u8 mode) +{ +	struct dw_pcie *pci = drvdata; +	u32 val; + +	if (mode == PCIE_PTM_CONTEXT_UPDATE_AUTO) { +		val = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_RES_REQ_CTRL); +		val |= PTM_REQ_AUTO_UPDATE_ENABLED; +		dw_pcie_writel_dbi(pci, pci->ptm_vsec_offset + PTM_RES_REQ_CTRL, val); +	} else if (mode == PCIE_PTM_CONTEXT_UPDATE_MANUAL) { +		val = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_RES_REQ_CTRL); +		val &= ~PTM_REQ_AUTO_UPDATE_ENABLED; +		val |= PTM_REQ_START_UPDATE; +		dw_pcie_writel_dbi(pci, pci->ptm_vsec_offset + PTM_RES_REQ_CTRL, val); +	} else { +		return -EINVAL; +	} + +	return 0; +} + +static int dw_pcie_ptm_context_update_read(void *drvdata, u8 *mode) +{ +	struct dw_pcie *pci = drvdata; +	u32 val; + +	val = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_RES_REQ_CTRL); +	if (FIELD_GET(PTM_REQ_AUTO_UPDATE_ENABLED, val)) +		*mode = PCIE_PTM_CONTEXT_UPDATE_AUTO; +	else +		/* +		 * PTM_REQ_START_UPDATE is a self clearing register bit. So if +		 * PTM_REQ_AUTO_UPDATE_ENABLED is not set, then it implies that +		 * manual update is used. +		 */ +		*mode = PCIE_PTM_CONTEXT_UPDATE_MANUAL; + +	return 0; +} + +static int dw_pcie_ptm_context_valid_write(void *drvdata, bool valid) +{ +	struct dw_pcie *pci = drvdata; +	u32 val; + +	if (valid) { +		val = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_RES_REQ_CTRL); +		val |= PTM_RES_CCONTEXT_VALID; +		dw_pcie_writel_dbi(pci, pci->ptm_vsec_offset + PTM_RES_REQ_CTRL, val); +	} else { +		val = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_RES_REQ_CTRL); +		val &= ~PTM_RES_CCONTEXT_VALID; +		dw_pcie_writel_dbi(pci, pci->ptm_vsec_offset + PTM_RES_REQ_CTRL, val); +	} + +	return 0; +} + +static int dw_pcie_ptm_context_valid_read(void *drvdata, bool *valid) +{ +	struct dw_pcie *pci = drvdata; +	u32 val; + +	val = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_RES_REQ_CTRL); +	*valid = !!FIELD_GET(PTM_RES_CCONTEXT_VALID, val); + +	return 0; +} + +static int dw_pcie_ptm_local_clock_read(void *drvdata, u64 *clock) +{ +	struct dw_pcie *pci = drvdata; +	u32 msb, lsb; + +	do { +		msb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_LOCAL_MSB); +		lsb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_LOCAL_LSB); +	} while (msb != dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_LOCAL_MSB)); + +	*clock = ((u64) msb) << 32 | lsb; + +	return 0; +} + +static int dw_pcie_ptm_master_clock_read(void *drvdata, u64 *clock) +{ +	struct dw_pcie *pci = drvdata; +	u32 msb, lsb; + +	do { +		msb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_MASTER_MSB); +		lsb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_MASTER_LSB); +	} while (msb != dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_MASTER_MSB)); + +	*clock = ((u64) msb) << 32 | lsb; + +	return 0; +} + +static int dw_pcie_ptm_t1_read(void *drvdata, u64 *clock) +{ +	struct dw_pcie *pci = drvdata; +	u32 msb, lsb; + +	do { +		msb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T1_T2_MSB); +		lsb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T1_T2_LSB); +	} while (msb != dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T1_T2_MSB)); + +	*clock = ((u64) msb) << 32 | lsb; + +	return 0; +} + +static int dw_pcie_ptm_t2_read(void *drvdata, u64 *clock) +{ +	struct dw_pcie *pci = drvdata; +	u32 msb, lsb; + +	do { +		msb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T1_T2_MSB); +		lsb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T1_T2_LSB); +	} while (msb != dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T1_T2_MSB)); + +	*clock = ((u64) msb) << 32 | lsb; + +	return 0; +} + +static int dw_pcie_ptm_t3_read(void *drvdata, u64 *clock) +{ +	struct dw_pcie *pci = drvdata; +	u32 msb, lsb; + +	do { +		msb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T3_T4_MSB); +		lsb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T3_T4_LSB); +	} while (msb != dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T3_T4_MSB)); + +	*clock = ((u64) msb) << 32 | lsb; + +	return 0; +} + +static int dw_pcie_ptm_t4_read(void *drvdata, u64 *clock) +{ +	struct dw_pcie *pci = drvdata; +	u32 msb, lsb; + +	do { +		msb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T3_T4_MSB); +		lsb = dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T3_T4_LSB); +	} while (msb != dw_pcie_readl_dbi(pci, pci->ptm_vsec_offset + PTM_T3_T4_MSB)); + +	*clock = ((u64) msb) << 32 | lsb; + +	return 0; +} + +static bool dw_pcie_ptm_context_update_visible(void *drvdata) +{ +	struct dw_pcie *pci = drvdata; + +	return (pci->mode == DW_PCIE_EP_TYPE) ? true : false; +} + +static bool dw_pcie_ptm_context_valid_visible(void *drvdata) +{ +	struct dw_pcie *pci = drvdata; + +	return (pci->mode == DW_PCIE_RC_TYPE) ? true : false; +} + +static bool dw_pcie_ptm_local_clock_visible(void *drvdata) +{ +	/* PTM local clock is always visible */ +	return true; +} + +static bool dw_pcie_ptm_master_clock_visible(void *drvdata) +{ +	struct dw_pcie *pci = drvdata; + +	return (pci->mode == DW_PCIE_EP_TYPE) ? true : false; +} + +static bool dw_pcie_ptm_t1_visible(void *drvdata) +{ +	struct dw_pcie *pci = drvdata; + +	return (pci->mode == DW_PCIE_EP_TYPE) ? true : false; +} + +static bool dw_pcie_ptm_t2_visible(void *drvdata) +{ +	struct dw_pcie *pci = drvdata; + +	return (pci->mode == DW_PCIE_RC_TYPE) ? true : false; +} + +static bool dw_pcie_ptm_t3_visible(void *drvdata) +{ +	struct dw_pcie *pci = drvdata; + +	return (pci->mode == DW_PCIE_RC_TYPE) ? true : false; +} + +static bool dw_pcie_ptm_t4_visible(void *drvdata) +{ +	struct dw_pcie *pci = drvdata; + +	return (pci->mode == DW_PCIE_EP_TYPE) ? true : false; +} + +const struct pcie_ptm_ops dw_pcie_ptm_ops = { +	.check_capability = dw_pcie_ptm_check_capability, +	.context_update_write = dw_pcie_ptm_context_update_write, +	.context_update_read = dw_pcie_ptm_context_update_read, +	.context_valid_write = dw_pcie_ptm_context_valid_write, +	.context_valid_read = dw_pcie_ptm_context_valid_read, +	.local_clock_read = dw_pcie_ptm_local_clock_read, +	.master_clock_read = dw_pcie_ptm_master_clock_read, +	.t1_read = dw_pcie_ptm_t1_read, +	.t2_read = dw_pcie_ptm_t2_read, +	.t3_read = dw_pcie_ptm_t3_read, +	.t4_read = dw_pcie_ptm_t4_read, +	.context_update_visible = dw_pcie_ptm_context_update_visible, +	.context_valid_visible = dw_pcie_ptm_context_valid_visible, +	.local_clock_visible = dw_pcie_ptm_local_clock_visible, +	.master_clock_visible = dw_pcie_ptm_master_clock_visible, +	.t1_visible = dw_pcie_ptm_t1_visible, +	.t2_visible = dw_pcie_ptm_t2_visible, +	.t3_visible = dw_pcie_ptm_t3_visible, +	.t4_visible = dw_pcie_ptm_t4_visible, +}; +  void dwc_pcie_debugfs_deinit(struct dw_pcie *pci)  {  	if (!pci->debugfs)  		return; +	pcie_ptm_destroy_debugfs(pci->ptm_debugfs);  	dwc_pcie_rasdes_debugfs_deinit(pci);  	debugfs_remove_recursive(pci->debugfs->debug_dir);  } -void dwc_pcie_debugfs_init(struct dw_pcie *pci) +void dwc_pcie_debugfs_init(struct dw_pcie *pci, enum dw_pcie_device_mode mode)  {  	char dirname[DWC_DEBUGFS_BUF_MAX];  	struct device *dev = pci->dev; @@ -674,4 +920,8 @@ void dwc_pcie_debugfs_init(struct dw_pcie *pci)  			err);  	dwc_pcie_ltssm_debugfs_init(pci, dir); + +	pci->mode = mode; +	pci->ptm_debugfs = pcie_ptm_create_debugfs(pci->dev, pci, +						   &dw_pcie_ptm_ops);  } diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c index 1a0bf9341542..0ae54a94809b 100644 --- a/drivers/pci/controller/dwc/pcie-designware-ep.c +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c @@ -256,11 +256,11 @@ static unsigned int dw_pcie_ep_get_rebar_offset(struct dw_pcie *pci,  		return offset;  	reg = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL); -	nbars = (reg & PCI_REBAR_CTRL_NBAR_MASK) >> PCI_REBAR_CTRL_NBAR_SHIFT; +	nbars = FIELD_GET(PCI_REBAR_CTRL_NBAR_MASK, reg);  	for (i = 0; i < nbars; i++, offset += PCI_REBAR_CTRL) {  		reg = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL); -		bar_index = reg & PCI_REBAR_CTRL_BAR_IDX; +		bar_index = FIELD_GET(PCI_REBAR_CTRL_BAR_IDX, reg);  		if (bar_index == bar)  			return offset;  	} @@ -532,15 +532,16 @@ static int dw_pcie_ep_get_msi(struct pci_epc *epc, u8 func_no, u8 vfunc_no)  	val = FIELD_GET(PCI_MSI_FLAGS_QSIZE, val); -	return val; +	return 1 << val;  }  static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 func_no, u8 vfunc_no, -			      u8 interrupts) +			      u8 nr_irqs)  {  	struct dw_pcie_ep *ep = epc_get_drvdata(epc);  	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);  	struct dw_pcie_ep_func *ep_func; +	u8 mmc = order_base_2(nr_irqs);  	u32 val, reg;  	ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no); @@ -550,7 +551,7 @@ static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 func_no, u8 vfunc_no,  	reg = ep_func->msi_cap + PCI_MSI_FLAGS;  	val = dw_pcie_ep_readw_dbi(ep, func_no, reg);  	val &= ~PCI_MSI_FLAGS_QMASK; -	val |= FIELD_PREP(PCI_MSI_FLAGS_QMASK, interrupts); +	val |= FIELD_PREP(PCI_MSI_FLAGS_QMASK, mmc);  	dw_pcie_dbi_ro_wr_en(pci);  	dw_pcie_ep_writew_dbi(ep, func_no, reg, val);  	dw_pcie_dbi_ro_wr_dis(pci); @@ -575,11 +576,11 @@ static int dw_pcie_ep_get_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no)  	val &= PCI_MSIX_FLAGS_QSIZE; -	return val; +	return val + 1;  }  static int dw_pcie_ep_set_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no, -			       u16 interrupts, enum pci_barno bir, u32 offset) +			       u16 nr_irqs, enum pci_barno bir, u32 offset)  {  	struct dw_pcie_ep *ep = epc_get_drvdata(epc);  	struct dw_pcie *pci = to_dw_pcie_from_ep(ep); @@ -595,7 +596,7 @@ static int dw_pcie_ep_set_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no,  	reg = ep_func->msix_cap + PCI_MSIX_FLAGS;  	val = dw_pcie_ep_readw_dbi(ep, func_no, reg);  	val &= ~PCI_MSIX_FLAGS_QSIZE; -	val |= interrupts; +	val |= nr_irqs - 1; /* encoded as N-1 */  	dw_pcie_writew_dbi(pci, reg, val);  	reg = ep_func->msix_cap + PCI_MSIX_TABLE; @@ -603,7 +604,7 @@ static int dw_pcie_ep_set_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no,  	dw_pcie_ep_writel_dbi(ep, func_no, reg, val);  	reg = ep_func->msix_cap + PCI_MSIX_PBA; -	val = (offset + (interrupts * PCI_MSIX_ENTRY_SIZE)) | bir; +	val = (offset + (nr_irqs * PCI_MSIX_ENTRY_SIZE)) | bir;  	dw_pcie_ep_writel_dbi(ep, func_no, reg, val);  	dw_pcie_dbi_ro_wr_dis(pci); @@ -671,7 +672,7 @@ static const struct pci_epc_ops epc_ops = {   * @ep: DWC EP device   * @func_no: Function number of the endpoint   * - * Return: 0 if success, errono otherwise. + * Return: 0 if success, errno otherwise.   */  int dw_pcie_ep_raise_intx_irq(struct dw_pcie_ep *ep, u8 func_no)  { @@ -690,7 +691,7 @@ EXPORT_SYMBOL_GPL(dw_pcie_ep_raise_intx_irq);   * @func_no: Function number of the endpoint   * @interrupt_num: Interrupt number to be raised   * - * Return: 0 if success, errono otherwise. + * Return: 0 if success, errno otherwise.   */  int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,  			     u8 interrupt_num) @@ -875,8 +876,7 @@ static void dw_pcie_ep_init_non_sticky_registers(struct dw_pcie *pci)  	if (offset) {  		reg = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL); -		nbars = (reg & PCI_REBAR_CTRL_NBAR_MASK) >> -			PCI_REBAR_CTRL_NBAR_SHIFT; +		nbars = FIELD_GET(PCI_REBAR_CTRL_NBAR_MASK, reg);  		/*  		 * PCIe r6.0, sec 7.8.6.2 require us to support at least one @@ -897,7 +897,7 @@ static void dw_pcie_ep_init_non_sticky_registers(struct dw_pcie *pci)  			 * is why RESBAR_CAP_REG is written here.  			 */  			val = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL); -			bar = val & PCI_REBAR_CTRL_BAR_IDX; +			bar = FIELD_GET(PCI_REBAR_CTRL_BAR_IDX, val);  			if (ep->epf_bar[bar])  				pci_epc_bar_size_to_rebar_cap(ep->epf_bar[bar]->size, &val);  			else @@ -1013,7 +1013,7 @@ int dw_pcie_ep_init_registers(struct dw_pcie_ep *ep)  	dw_pcie_ep_init_non_sticky_registers(pci); -	dwc_pcie_debugfs_init(pci); +	dwc_pcie_debugfs_init(pci, DW_PCIE_EP_TYPE);  	return 0; diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c index ecc33f6789e3..906277f9ffaf 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -227,7 +227,7 @@ static const struct irq_domain_ops dw_pcie_msi_domain_ops = {  int dw_pcie_allocate_domains(struct dw_pcie_rp *pp)  {  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); -	struct fwnode_handle *fwnode = of_node_to_fwnode(pci->dev->of_node); +	struct fwnode_handle *fwnode = of_fwnode_handle(pci->dev->of_node);  	pp->irq_domain = irq_domain_create_linear(fwnode, pp->num_vectors,  					       &dw_pcie_msi_domain_ops, pp); @@ -523,6 +523,13 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)  	dw_pcie_iatu_detect(pci); +	if (pci->num_lanes < 1) +		pci->num_lanes = dw_pcie_link_get_max_link_width(pci); + +	ret = of_pci_get_equalization_presets(dev, &pp->presets, pci->num_lanes); +	if (ret) +		goto err_free_msi; +  	/*  	 * Allocate the resource for MSG TLP before programming the iATU  	 * outbound window in dw_pcie_setup_rc(). Since the allocation depends @@ -567,7 +574,7 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)  	if (pp->ops->post_init)  		pp->ops->post_init(pp); -	dwc_pcie_debugfs_init(pci); +	dwc_pcie_debugfs_init(pci, DW_PCIE_RC_TYPE);  	return 0; @@ -828,6 +835,77 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)  	return 0;  } +static void dw_pcie_program_presets(struct dw_pcie_rp *pp, enum pci_bus_speed speed) +{ +	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); +	u8 lane_eq_offset, lane_reg_size, cap_id; +	u8 *presets; +	u32 cap; +	int i; + +	if (speed == PCIE_SPEED_8_0GT) { +		presets = (u8 *)pp->presets.eq_presets_8gts; +		lane_eq_offset =  PCI_SECPCI_LE_CTRL; +		cap_id = PCI_EXT_CAP_ID_SECPCI; +		/* For data rate of 8 GT/S each lane equalization control is 16bits wide*/ +		lane_reg_size = 0x2; +	} else if (speed == PCIE_SPEED_16_0GT) { +		presets = pp->presets.eq_presets_Ngts[EQ_PRESET_TYPE_16GTS - 1]; +		lane_eq_offset = PCI_PL_16GT_LE_CTRL; +		cap_id = PCI_EXT_CAP_ID_PL_16GT; +		lane_reg_size = 0x1; +	} else if (speed == PCIE_SPEED_32_0GT) { +		presets =  pp->presets.eq_presets_Ngts[EQ_PRESET_TYPE_32GTS - 1]; +		lane_eq_offset = PCI_PL_32GT_LE_CTRL; +		cap_id = PCI_EXT_CAP_ID_PL_32GT; +		lane_reg_size = 0x1; +	} else if (speed == PCIE_SPEED_64_0GT) { +		presets =  pp->presets.eq_presets_Ngts[EQ_PRESET_TYPE_64GTS - 1]; +		lane_eq_offset = PCI_PL_64GT_LE_CTRL; +		cap_id = PCI_EXT_CAP_ID_PL_64GT; +		lane_reg_size = 0x1; +	} else { +		return; +	} + +	if (presets[0] == PCI_EQ_RESV) +		return; + +	cap = dw_pcie_find_ext_capability(pci, cap_id); +	if (!cap) +		return; + +	/* +	 * Write preset values to the registers byte-by-byte for the given +	 * number of lanes and register size. +	 */ +	for (i = 0; i < pci->num_lanes * lane_reg_size; i++) +		dw_pcie_writeb_dbi(pci, cap + lane_eq_offset + i, presets[i]); +} + +static void dw_pcie_config_presets(struct dw_pcie_rp *pp) +{ +	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); +	enum pci_bus_speed speed = pcie_link_speed[pci->max_link_speed]; + +	/* +	 * Lane equalization settings need to be applied for all data rates the +	 * controller supports and for all supported lanes. +	 */ + +	if (speed >= PCIE_SPEED_8_0GT) +		dw_pcie_program_presets(pp, PCIE_SPEED_8_0GT); + +	if (speed >= PCIE_SPEED_16_0GT) +		dw_pcie_program_presets(pp, PCIE_SPEED_16_0GT); + +	if (speed >= PCIE_SPEED_32_0GT) +		dw_pcie_program_presets(pp, PCIE_SPEED_32_0GT); + +	if (speed >= PCIE_SPEED_64_0GT) +		dw_pcie_program_presets(pp, PCIE_SPEED_64_0GT); +} +  int dw_pcie_setup_rc(struct dw_pcie_rp *pp)  {  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); @@ -881,6 +959,7 @@ int dw_pcie_setup_rc(struct dw_pcie_rp *pp)  		PCI_COMMAND_MASTER | PCI_COMMAND_SERR;  	dw_pcie_writel_dbi(pci, PCI_COMMAND, val); +	dw_pcie_config_presets(pp);  	/*  	 * If the platform provides its own child bus config accesses, it means  	 * the platform uses its own address translation component rather than diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c index 97d76d3dc066..4d794964fa0f 100644 --- a/drivers/pci/controller/dwc/pcie-designware.c +++ b/drivers/pci/controller/dwc/pcie-designware.c @@ -54,6 +54,14 @@ static const char * const dw_pcie_core_rsts[DW_PCIE_NUM_CORE_RSTS] = {  	[DW_PCIE_PWR_RST] = "pwr",  }; +static const struct dwc_pcie_vsec_id dwc_pcie_ptm_vsec_ids[] = { +	{ .vendor_id = PCI_VENDOR_ID_QCOM, /* EP */ +	  .vsec_id = 0x03, .vsec_rev = 0x1 }, +	{ .vendor_id = PCI_VENDOR_ID_QCOM, /* RC */ +	  .vsec_id = 0x04, .vsec_rev = 0x1 }, +	{ } +}; +  static int dw_pcie_get_clocks(struct dw_pcie *pci)  {  	int i, ret; @@ -330,6 +338,12 @@ u16 dw_pcie_find_rasdes_capability(struct dw_pcie *pci)  }  EXPORT_SYMBOL_GPL(dw_pcie_find_rasdes_capability); +u16 dw_pcie_find_ptm_capability(struct dw_pcie *pci) +{ +	return dw_pcie_find_vsec_capability(pci, dwc_pcie_ptm_vsec_ids); +} +EXPORT_SYMBOL_GPL(dw_pcie_find_ptm_capability); +  int dw_pcie_read(void __iomem *addr, int size, u32 *val)  {  	if (!IS_ALIGNED((uintptr_t)addr, size)) { @@ -711,7 +725,7 @@ int dw_pcie_wait_for_link(struct dw_pcie *pci)  }  EXPORT_SYMBOL_GPL(dw_pcie_wait_for_link); -int dw_pcie_link_up(struct dw_pcie *pci) +bool dw_pcie_link_up(struct dw_pcie *pci)  {  	u32 val; @@ -781,6 +795,14 @@ static void dw_pcie_link_set_max_speed(struct dw_pcie *pci)  } +int dw_pcie_link_get_max_link_width(struct dw_pcie *pci) +{ +	u8 cap = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); +	u32 lnkcap = dw_pcie_readl_dbi(pci, cap + PCI_EXP_LNKCAP); + +	return FIELD_GET(PCI_EXP_LNKCAP_MLW, lnkcap); +} +  static void dw_pcie_link_set_max_link_width(struct dw_pcie *pci, u32 num_lanes)  {  	u32 lnkcap, lwsc, plc; @@ -797,22 +819,19 @@ static void dw_pcie_link_set_max_link_width(struct dw_pcie *pci, u32 num_lanes)  	/* Set link width speed control register */  	lwsc = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL);  	lwsc &= ~PORT_LOGIC_LINK_WIDTH_MASK; +	lwsc |= PORT_LOGIC_LINK_WIDTH_1_LANES;  	switch (num_lanes) {  	case 1:  		plc |= PORT_LINK_MODE_1_LANES; -		lwsc |= PORT_LOGIC_LINK_WIDTH_1_LANES;  		break;  	case 2:  		plc |= PORT_LINK_MODE_2_LANES; -		lwsc |= PORT_LOGIC_LINK_WIDTH_2_LANES;  		break;  	case 4:  		plc |= PORT_LINK_MODE_4_LANES; -		lwsc |= PORT_LOGIC_LINK_WIDTH_4_LANES;  		break;  	case 8:  		plc |= PORT_LINK_MODE_8_LANES; -		lwsc |= PORT_LOGIC_LINK_WIDTH_8_LANES;  		break;  	default:  		dev_err(pci->dev, "num-lanes %u: invalid value\n", num_lanes); diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index 56aafdbcdaca..ce9e18554e42 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -25,6 +25,8 @@  #include <linux/pci-epc.h>  #include <linux/pci-epf.h> +#include "../../pci.h" +  /* DWC PCIe IP-core versions (native support since v4.70a) */  #define DW_PCIE_VER_365A		0x3336352a  #define DW_PCIE_VER_460A		0x3436302a @@ -260,6 +262,21 @@  #define PCIE_RAS_DES_EVENT_COUNTER_DATA		0xc +/* PTM register definitions */ +#define PTM_RES_REQ_CTRL		0x8 +#define PTM_RES_CCONTEXT_VALID		BIT(0) +#define PTM_REQ_AUTO_UPDATE_ENABLED	BIT(0) +#define PTM_REQ_START_UPDATE		BIT(1) + +#define PTM_LOCAL_LSB			0x10 +#define PTM_LOCAL_MSB			0x14 +#define PTM_T1_T2_LSB			0x18 +#define PTM_T1_T2_MSB			0x1c +#define PTM_T3_T4_LSB			0x28 +#define PTM_T3_T4_MSB			0x2c +#define PTM_MASTER_LSB			0x38 +#define PTM_MASTER_MSB			0x3c +  /*   * The default address offset between dbi_base and atu_base. Root controller   * drivers are not required to initialize atu_base if the offset matches this @@ -412,6 +429,7 @@ struct dw_pcie_rp {  	int			msg_atu_index;  	struct resource		*msg_res;  	bool			use_linkup_irq; +	struct pci_eq_presets	presets;  };  struct dw_pcie_ep_ops { @@ -462,7 +480,7 @@ struct dw_pcie_ops {  			     size_t size, u32 val);  	void    (*write_dbi2)(struct dw_pcie *pcie, void __iomem *base, u32 reg,  			      size_t size, u32 val); -	int	(*link_up)(struct dw_pcie *pcie); +	bool	(*link_up)(struct dw_pcie *pcie);  	enum dw_pcie_ltssm (*get_ltssm)(struct dw_pcie *pcie);  	int	(*start_link)(struct dw_pcie *pcie);  	void	(*stop_link)(struct dw_pcie *pcie); @@ -503,6 +521,9 @@ struct dw_pcie {  	struct gpio_desc		*pe_rst;  	bool			suspended;  	struct debugfs_info	*debugfs; +	enum			dw_pcie_device_mode mode; +	u16			ptm_vsec_offset; +	struct pci_ptm_debugfs	*ptm_debugfs;  	/*  	 * If iATU input addresses are offset from CPU physical addresses, @@ -530,6 +551,7 @@ void dw_pcie_version_detect(struct dw_pcie *pci);  u8 dw_pcie_find_capability(struct dw_pcie *pci, u8 cap);  u16 dw_pcie_find_ext_capability(struct dw_pcie *pci, u8 cap);  u16 dw_pcie_find_rasdes_capability(struct dw_pcie *pci); +u16 dw_pcie_find_ptm_capability(struct dw_pcie *pci);  int dw_pcie_read(void __iomem *addr, int size, u32 *val);  int dw_pcie_write(void __iomem *addr, int size, u32 val); @@ -537,9 +559,10 @@ int dw_pcie_write(void __iomem *addr, int size, u32 val);  u32 dw_pcie_read_dbi(struct dw_pcie *pci, u32 reg, size_t size);  void dw_pcie_write_dbi(struct dw_pcie *pci, u32 reg, size_t size, u32 val);  void dw_pcie_write_dbi2(struct dw_pcie *pci, u32 reg, size_t size, u32 val); -int dw_pcie_link_up(struct dw_pcie *pci); +bool dw_pcie_link_up(struct dw_pcie *pci);  void dw_pcie_upconfig_setup(struct dw_pcie *pci);  int dw_pcie_wait_for_link(struct dw_pcie *pci); +int dw_pcie_link_get_max_link_width(struct dw_pcie *pci);  int dw_pcie_prog_outbound_atu(struct dw_pcie *pci,  			      const struct dw_pcie_ob_atu_cfg *atu);  int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int type, @@ -871,10 +894,11 @@ dw_pcie_ep_get_func_from_ep(struct dw_pcie_ep *ep, u8 func_no)  #endif  #ifdef CONFIG_PCIE_DW_DEBUGFS -void dwc_pcie_debugfs_init(struct dw_pcie *pci); +void dwc_pcie_debugfs_init(struct dw_pcie *pci, enum dw_pcie_device_mode mode);  void dwc_pcie_debugfs_deinit(struct dw_pcie *pci);  #else -static inline void dwc_pcie_debugfs_init(struct dw_pcie *pci) +static inline void dwc_pcie_debugfs_init(struct dw_pcie *pci, +					 enum dw_pcie_device_mode mode)  {  }  static inline void dwc_pcie_debugfs_deinit(struct dw_pcie *pci) diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c index c624b7ebd118..93171a392879 100644 --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c @@ -8,6 +8,7 @@   * Author: Simon Xue <xxm@rock-chips.com>   */ +#include <linux/bitfield.h>  #include <linux/clk.h>  #include <linux/gpio/consumer.h>  #include <linux/irqchip/chained_irq.h> @@ -21,6 +22,7 @@  #include <linux/regmap.h>  #include <linux/reset.h> +#include "../../pci.h"  #include "pcie-designware.h"  /* @@ -33,26 +35,36 @@  #define to_rockchip_pcie(x) dev_get_drvdata((x)->dev) -#define PCIE_CLIENT_RC_MODE		HIWORD_UPDATE_BIT(0x40) -#define PCIE_CLIENT_EP_MODE		HIWORD_UPDATE(0xf0, 0x0) -#define PCIE_CLIENT_ENABLE_LTSSM	HIWORD_UPDATE_BIT(0xc) -#define PCIE_CLIENT_DISABLE_LTSSM	HIWORD_UPDATE(0x0c, 0x8) -#define PCIE_CLIENT_INTR_STATUS_MISC	0x10 -#define PCIE_CLIENT_INTR_MASK_MISC	0x24 -#define PCIE_SMLH_LINKUP		BIT(16) -#define PCIE_RDLH_LINKUP		BIT(17) -#define PCIE_LINKUP			(PCIE_SMLH_LINKUP | PCIE_RDLH_LINKUP) -#define PCIE_RDLH_LINK_UP_CHGED		BIT(1) -#define PCIE_LINK_REQ_RST_NOT_INT	BIT(2) -#define PCIE_L0S_ENTRY			0x11 -#define PCIE_CLIENT_GENERAL_CONTROL	0x0 +/* General Control Register */ +#define PCIE_CLIENT_GENERAL_CON		0x0 +#define  PCIE_CLIENT_RC_MODE		HIWORD_UPDATE_BIT(0x40) +#define  PCIE_CLIENT_EP_MODE		HIWORD_UPDATE(0xf0, 0x0) +#define  PCIE_CLIENT_ENABLE_LTSSM	HIWORD_UPDATE_BIT(0xc) +#define  PCIE_CLIENT_DISABLE_LTSSM	HIWORD_UPDATE(0x0c, 0x8) + +/* Interrupt Status Register Related to Legacy Interrupt */  #define PCIE_CLIENT_INTR_STATUS_LEGACY	0x8 + +/* Interrupt Status Register Related to Miscellaneous Operation */ +#define PCIE_CLIENT_INTR_STATUS_MISC	0x10 +#define  PCIE_RDLH_LINK_UP_CHGED	BIT(1) +#define  PCIE_LINK_REQ_RST_NOT_INT	BIT(2) + +/* Interrupt Mask Register Related to Legacy Interrupt */  #define PCIE_CLIENT_INTR_MASK_LEGACY	0x1c -#define PCIE_CLIENT_GENERAL_DEBUG	0x104 + +/* Interrupt Mask Register Related to Miscellaneous Operation */ +#define PCIE_CLIENT_INTR_MASK_MISC	0x24 + +/* Hot Reset Control Register */  #define PCIE_CLIENT_HOT_RESET_CTRL	0x180 +#define  PCIE_LTSSM_ENABLE_ENHANCE	BIT(4) + +/* LTSSM Status Register */  #define PCIE_CLIENT_LTSSM_STATUS	0x300 -#define PCIE_LTSSM_ENABLE_ENHANCE	BIT(4) -#define PCIE_LTSSM_STATUS_MASK		GENMASK(5, 0) +#define  PCIE_LINKUP			0x3 +#define  PCIE_LINKUP_MASK		GENMASK(17, 16) +#define  PCIE_LTSSM_STATUS_MASK		GENMASK(5, 0)  struct rockchip_pcie {  	struct dw_pcie pci; @@ -144,8 +156,8 @@ static int rockchip_pcie_init_irq_domain(struct rockchip_pcie *rockchip)  		return -EINVAL;  	} -	rockchip->irq_domain = irq_domain_add_linear(intc, PCI_NUM_INTX, -						    &intx_domain_ops, rockchip); +	rockchip->irq_domain = irq_domain_create_linear(of_fwnode_handle(intc), PCI_NUM_INTX, +							&intx_domain_ops, rockchip);  	of_node_put(intc);  	if (!rockchip->irq_domain) {  		dev_err(dev, "failed to get a INTx IRQ domain\n"); @@ -163,25 +175,36 @@ static u32 rockchip_pcie_get_ltssm(struct rockchip_pcie *rockchip)  static void rockchip_pcie_enable_ltssm(struct rockchip_pcie *rockchip)  {  	rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_ENABLE_LTSSM, -				 PCIE_CLIENT_GENERAL_CONTROL); +				 PCIE_CLIENT_GENERAL_CON);  }  static void rockchip_pcie_disable_ltssm(struct rockchip_pcie *rockchip)  {  	rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_DISABLE_LTSSM, -				 PCIE_CLIENT_GENERAL_CONTROL); +				 PCIE_CLIENT_GENERAL_CON);  } -static int rockchip_pcie_link_up(struct dw_pcie *pci) +static bool rockchip_pcie_link_up(struct dw_pcie *pci)  {  	struct rockchip_pcie *rockchip = to_rockchip_pcie(pci);  	u32 val = rockchip_pcie_get_ltssm(rockchip); -	if ((val & PCIE_LINKUP) == PCIE_LINKUP && -	    (val & PCIE_LTSSM_STATUS_MASK) == PCIE_L0S_ENTRY) -		return 1; +	return FIELD_GET(PCIE_LINKUP_MASK, val) == PCIE_LINKUP; +} -	return 0; +static void rockchip_pcie_enable_l0s(struct dw_pcie *pci) +{ +	u32 cap, lnkcap; + +	/* Enable L0S capability for all SoCs */ +	cap = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); +	if (cap) { +		lnkcap = dw_pcie_readl_dbi(pci, cap + PCI_EXP_LNKCAP); +		lnkcap |= PCI_EXP_LNKCAP_ASPM_L0S; +		dw_pcie_dbi_ro_wr_en(pci); +		dw_pcie_writel_dbi(pci, cap + PCI_EXP_LNKCAP, lnkcap); +		dw_pcie_dbi_ro_wr_dis(pci); +	}  }  static int rockchip_pcie_start_link(struct dw_pcie *pci) @@ -202,7 +225,7 @@ static int rockchip_pcie_start_link(struct dw_pcie *pci)  	 * We need more extra time as before, rather than setting just  	 * 100us as we don't know how long should the device need to reset.  	 */ -	msleep(100); +	msleep(PCIE_T_PVPERL_MS);  	gpiod_set_value_cansleep(rockchip->rst_gpio, 1);  	return 0; @@ -233,6 +256,8 @@ static int rockchip_pcie_host_init(struct dw_pcie_rp *pp)  	irq_set_chained_handler_and_data(irq, rockchip_pcie_intx_handler,  					 rockchip); +	rockchip_pcie_enable_l0s(pci); +  	return 0;  } @@ -263,16 +288,14 @@ static void rockchip_pcie_ep_hide_broken_ats_cap_rk3588(struct dw_pcie_ep *ep)  		dev_err(dev, "failed to hide ATS capability\n");  } -static void rockchip_pcie_ep_pre_init(struct dw_pcie_ep *ep) -{ -	rockchip_pcie_ep_hide_broken_ats_cap_rk3588(ep); -} -  static void rockchip_pcie_ep_init(struct dw_pcie_ep *ep)  {  	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);  	enum pci_barno bar; +	rockchip_pcie_enable_l0s(pci); +	rockchip_pcie_ep_hide_broken_ats_cap_rk3588(ep); +  	for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)  		dw_pcie_ep_reset_bar(pci, bar);  }; @@ -342,7 +365,6 @@ rockchip_pcie_get_features(struct dw_pcie_ep *ep)  static const struct dw_pcie_ep_ops rockchip_pcie_ep_ops = {  	.init = rockchip_pcie_ep_init, -	.pre_init = rockchip_pcie_ep_pre_init,  	.raise_irq = rockchip_pcie_raise_irq,  	.get_features = rockchip_pcie_get_features,  }; @@ -410,8 +432,8 @@ static int rockchip_pcie_phy_init(struct rockchip_pcie *rockchip)  static void rockchip_pcie_phy_deinit(struct rockchip_pcie *rockchip)  { -	phy_exit(rockchip->phy);  	phy_power_off(rockchip->phy); +	phy_exit(rockchip->phy);  }  static const struct dw_pcie_ops dw_pcie_ops = { @@ -426,7 +448,7 @@ static irqreturn_t rockchip_pcie_rc_sys_irq_thread(int irq, void *arg)  	struct dw_pcie *pci = &rockchip->pci;  	struct dw_pcie_rp *pp = &pci->pp;  	struct device *dev = pci->dev; -	u32 reg, val; +	u32 reg;  	reg = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_INTR_STATUS_MISC);  	rockchip_pcie_writel_apb(rockchip, reg, PCIE_CLIENT_INTR_STATUS_MISC); @@ -435,8 +457,7 @@ static irqreturn_t rockchip_pcie_rc_sys_irq_thread(int irq, void *arg)  	dev_dbg(dev, "LTSSM_STATUS: %#x\n", rockchip_pcie_get_ltssm(rockchip));  	if (reg & PCIE_RDLH_LINK_UP_CHGED) { -		val = rockchip_pcie_get_ltssm(rockchip); -		if ((val & PCIE_LINKUP) == PCIE_LINKUP) { +		if (rockchip_pcie_link_up(pci)) {  			dev_dbg(dev, "Received Link up event. Starting enumeration!\n");  			/* Rescan the bus to enumerate endpoint devices */  			pci_lock_rescan_remove(); @@ -453,7 +474,7 @@ static irqreturn_t rockchip_pcie_ep_sys_irq_thread(int irq, void *arg)  	struct rockchip_pcie *rockchip = arg;  	struct dw_pcie *pci = &rockchip->pci;  	struct device *dev = pci->dev; -	u32 reg, val; +	u32 reg;  	reg = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_INTR_STATUS_MISC);  	rockchip_pcie_writel_apb(rockchip, reg, PCIE_CLIENT_INTR_STATUS_MISC); @@ -467,8 +488,7 @@ static irqreturn_t rockchip_pcie_ep_sys_irq_thread(int irq, void *arg)  	}  	if (reg & PCIE_RDLH_LINK_UP_CHGED) { -		val = rockchip_pcie_get_ltssm(rockchip); -		if ((val & PCIE_LINKUP) == PCIE_LINKUP) { +		if (rockchip_pcie_link_up(pci)) {  			dev_dbg(dev, "link up\n");  			dw_pcie_ep_linkup(&pci->ep);  		} @@ -505,7 +525,7 @@ static int rockchip_pcie_configure_rc(struct platform_device *pdev,  	rockchip_pcie_writel_apb(rockchip, val, PCIE_CLIENT_HOT_RESET_CTRL);  	rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_RC_MODE, -				 PCIE_CLIENT_GENERAL_CONTROL); +				 PCIE_CLIENT_GENERAL_CON);  	pp = &rockchip->pci.pp;  	pp->ops = &rockchip_pcie_host_ops; @@ -551,7 +571,7 @@ static int rockchip_pcie_configure_ep(struct platform_device *pdev,  	rockchip_pcie_writel_apb(rockchip, val, PCIE_CLIENT_HOT_RESET_CTRL);  	rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_EP_MODE, -				 PCIE_CLIENT_GENERAL_CONTROL); +				 PCIE_CLIENT_GENERAL_CON);  	rockchip->pci.ep.ops = &rockchip_pcie_ep_ops;  	rockchip->pci.ep.page_size = SZ_64K; @@ -601,6 +621,10 @@ static int rockchip_pcie_probe(struct platform_device *pdev)  	rockchip->pci.ops = &dw_pcie_ops;  	rockchip->data = data; +	/* Default N_FTS value (210) is broken, override it to 255 */ +	rockchip->pci.n_fts[0] = 255; /* Gen1 */ +	rockchip->pci.n_fts[1] = 255; /* Gen2+ */ +  	ret = rockchip_pcie_resource_get(pdev, rockchip);  	if (ret)  		return ret; diff --git a/drivers/pci/controller/dwc/pcie-hisi.c b/drivers/pci/controller/dwc/pcie-hisi.c index 8904b5b85ee5..3c17897e56fc 100644 --- a/drivers/pci/controller/dwc/pcie-hisi.c +++ b/drivers/pci/controller/dwc/pcie-hisi.c @@ -15,6 +15,7 @@  #include <linux/pci-acpi.h>  #include <linux/pci-ecam.h>  #include "../../pci.h" +#include "../pci-host-common.h"  #if defined(CONFIG_PCI_HISI) || (defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)) diff --git a/drivers/pci/controller/dwc/pcie-histb.c b/drivers/pci/controller/dwc/pcie-histb.c index 1f2f4c28a949..a52071589377 100644 --- a/drivers/pci/controller/dwc/pcie-histb.c +++ b/drivers/pci/controller/dwc/pcie-histb.c @@ -151,7 +151,7 @@ static struct pci_ops histb_pci_ops = {  	.write = histb_pcie_wr_own_conf,  }; -static int histb_pcie_link_up(struct dw_pcie *pci) +static bool histb_pcie_link_up(struct dw_pcie *pci)  {  	struct histb_pcie *hipcie = to_histb_pcie(pci);  	u32 regval; @@ -160,11 +160,8 @@ static int histb_pcie_link_up(struct dw_pcie *pci)  	regval = histb_pcie_readl(hipcie, PCIE_SYS_STAT0);  	status = histb_pcie_readl(hipcie, PCIE_SYS_STAT4);  	status &= PCIE_LTSSM_STATE_MASK; -	if ((regval & PCIE_XMLH_LINK_UP) && (regval & PCIE_RDLH_LINK_UP) && -	    (status == PCIE_LTSSM_STATE_ACTIVE)) -		return 1; - -	return 0; +	return ((regval & PCIE_XMLH_LINK_UP) && (regval & PCIE_RDLH_LINK_UP) && +		(status == PCIE_LTSSM_STATE_ACTIVE));  }  static int histb_pcie_start_link(struct dw_pcie *pci) diff --git a/drivers/pci/controller/dwc/pcie-keembay.c b/drivers/pci/controller/dwc/pcie-keembay.c index 278205db60a2..67dd3337b447 100644 --- a/drivers/pci/controller/dwc/pcie-keembay.c +++ b/drivers/pci/controller/dwc/pcie-keembay.c @@ -101,7 +101,7 @@ static void keembay_pcie_ltssm_set(struct keembay_pcie *pcie, bool enable)  	writel(val, pcie->apb_base + PCIE_REGS_PCIE_APP_CNTRL);  } -static int keembay_pcie_link_up(struct dw_pcie *pci) +static bool keembay_pcie_link_up(struct dw_pcie *pci)  {  	struct keembay_pcie *pcie = dev_get_drvdata(pci->dev);  	u32 val; diff --git a/drivers/pci/controller/dwc/pcie-kirin.c b/drivers/pci/controller/dwc/pcie-kirin.c index d0e6a3811b00..91559c8b1866 100644 --- a/drivers/pci/controller/dwc/pcie-kirin.c +++ b/drivers/pci/controller/dwc/pcie-kirin.c @@ -586,16 +586,13 @@ static void kirin_pcie_write_dbi(struct dw_pcie *pci, void __iomem *base,  	kirin_pcie_sideband_dbi_w_mode(kirin_pcie, false);  } -static int kirin_pcie_link_up(struct dw_pcie *pci) +static bool kirin_pcie_link_up(struct dw_pcie *pci)  {  	struct kirin_pcie *kirin_pcie = to_kirin_pcie(pci);  	u32 val;  	regmap_read(kirin_pcie->apb, PCIE_APB_PHY_STATUS0, &val); -	if ((val & PCIE_LINKUP_ENABLE) == PCIE_LINKUP_ENABLE) -		return 1; - -	return 0; +	return (val & PCIE_LINKUP_ENABLE) == PCIE_LINKUP_ENABLE;  }  static int kirin_pcie_start_link(struct dw_pcie *pci) diff --git a/drivers/pci/controller/dwc/pcie-qcom-ep.c b/drivers/pci/controller/dwc/pcie-qcom-ep.c index 46b1c6d19974..bf7c6ac0f3e3 100644 --- a/drivers/pci/controller/dwc/pcie-qcom-ep.c +++ b/drivers/pci/controller/dwc/pcie-qcom-ep.c @@ -60,6 +60,7 @@  #define PARF_DEVICE_TYPE			0x1000  #define PARF_BDF_TO_SID_CFG			0x2c00  #define PARF_INT_ALL_5_MASK			0x2dcc +#define PARF_INT_ALL_3_MASK			0x2e18  /* PARF_INT_ALL_{STATUS/CLEAR/MASK} register fields */  #define PARF_INT_ALL_LINK_DOWN			BIT(1) @@ -132,6 +133,9 @@  /* PARF_INT_ALL_5_MASK fields */  #define PARF_INT_ALL_5_MHI_RAM_DATA_PARITY_ERR	BIT(0) +/* PARF_INT_ALL_3_MASK fields */ +#define PARF_INT_ALL_3_PTM_UPDATING		BIT(4) +  /* ELBI registers */  #define ELBI_SYS_STTS				0x08  #define ELBI_CS2_ENABLE				0xa4 @@ -261,7 +265,7 @@ static void qcom_pcie_ep_configure_tcsr(struct qcom_pcie_ep *pcie_ep)  	}  } -static int qcom_pcie_dw_link_up(struct dw_pcie *pci) +static bool qcom_pcie_dw_link_up(struct dw_pcie *pci)  {  	struct qcom_pcie_ep *pcie_ep = to_pcie_ep(pci);  	u32 reg; @@ -497,6 +501,10 @@ static int qcom_pcie_perst_deassert(struct dw_pcie *pci)  		writel_relaxed(val, pcie_ep->parf + PARF_INT_ALL_5_MASK);  	} +	val = readl_relaxed(pcie_ep->parf + PARF_INT_ALL_3_MASK); +	val &= ~PARF_INT_ALL_3_PTM_UPDATING; +	writel_relaxed(val, pcie_ep->parf + PARF_INT_ALL_3_MASK); +  	ret = dw_pcie_ep_init_registers(&pcie_ep->pci.ep);  	if (ret) {  		dev_err(dev, "Failed to complete initialization: %d\n", ret); diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index dc98ae63362d..c789e3f85655 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -289,7 +289,7 @@ static void qcom_ep_reset_assert(struct qcom_pcie *pcie)  static void qcom_ep_reset_deassert(struct qcom_pcie *pcie)  {  	/* Ensure that PERST has been asserted for at least 100 ms */ -	msleep(100); +	msleep(PCIE_T_PVPERL_MS);  	gpiod_set_value_cansleep(pcie->reset, 0);  	usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500);  } @@ -1221,12 +1221,12 @@ static int qcom_pcie_post_init_2_9_0(struct qcom_pcie *pcie)  	return 0;  } -static int qcom_pcie_link_up(struct dw_pcie *pci) +static bool qcom_pcie_link_up(struct dw_pcie *pci)  {  	u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);  	u16 val = readw(pci->dbi_base + offset + PCI_EXP_LNKSTA); -	return !!(val & PCI_EXP_LNKSTA_DLLLA); +	return val & PCI_EXP_LNKSTA_DLLLA;  }  static int qcom_pcie_host_init(struct dw_pcie_rp *pp) @@ -1840,6 +1840,7 @@ static const struct of_device_id qcom_pcie_match[] = {  	{ .compatible = "qcom,pcie-apq8064", .data = &cfg_2_1_0 },  	{ .compatible = "qcom,pcie-apq8084", .data = &cfg_1_0_0 },  	{ .compatible = "qcom,pcie-ipq4019", .data = &cfg_2_4_0 }, +	{ .compatible = "qcom,pcie-ipq5018", .data = &cfg_2_9_0 },  	{ .compatible = "qcom,pcie-ipq6018", .data = &cfg_2_9_0 },  	{ .compatible = "qcom,pcie-ipq8064", .data = &cfg_2_1_0 },  	{ .compatible = "qcom,pcie-ipq8064-v2", .data = &cfg_2_1_0 }, diff --git a/drivers/pci/controller/dwc/pcie-rcar-gen4.c b/drivers/pci/controller/dwc/pcie-rcar-gen4.c index fc872dd35029..18055807a4f5 100644 --- a/drivers/pci/controller/dwc/pcie-rcar-gen4.c +++ b/drivers/pci/controller/dwc/pcie-rcar-gen4.c @@ -87,7 +87,7 @@ struct rcar_gen4_pcie {  #define to_rcar_gen4_pcie(_dw)	container_of(_dw, struct rcar_gen4_pcie, dw)  /* Common */ -static int rcar_gen4_pcie_link_up(struct dw_pcie *dw) +static bool rcar_gen4_pcie_link_up(struct dw_pcie *dw)  {  	struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw);  	u32 val, mask; @@ -403,6 +403,7 @@ static const struct pci_epc_features rcar_gen4_pcie_epc_features = {  	.msix_capable = false,  	.bar[BAR_1] = { .type = BAR_RESERVED, },  	.bar[BAR_3] = { .type = BAR_RESERVED, }, +	.bar[BAR_4] = { .type = BAR_FIXED, .fixed_size = 256 },  	.bar[BAR_5] = { .type = BAR_RESERVED, },  	.align = SZ_1M,  }; diff --git a/drivers/pci/controller/dwc/pcie-spear13xx.c b/drivers/pci/controller/dwc/pcie-spear13xx.c index ff986ced56b2..01794a9d3ad2 100644 --- a/drivers/pci/controller/dwc/pcie-spear13xx.c +++ b/drivers/pci/controller/dwc/pcie-spear13xx.c @@ -110,15 +110,12 @@ static void spear13xx_pcie_enable_interrupts(struct spear13xx_pcie *spear13xx_pc  				MSI_CTRL_INT, &app_reg->int_mask);  } -static int spear13xx_pcie_link_up(struct dw_pcie *pci) +static bool spear13xx_pcie_link_up(struct dw_pcie *pci)  {  	struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pci);  	struct pcie_app_reg __iomem *app_reg = spear13xx_pcie->app_base; -	if (readl(&app_reg->app_status_1) & XMLH_LINK_UP) -		return 1; - -	return 0; +	return readl(&app_reg->app_status_1) & XMLH_LINK_UP;  }  static int spear13xx_pcie_host_init(struct dw_pcie_rp *pp) diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c index 5103995cd6c7..4f26086f25da 100644 --- a/drivers/pci/controller/dwc/pcie-tegra194.c +++ b/drivers/pci/controller/dwc/pcie-tegra194.c @@ -713,7 +713,16 @@ static void init_host_aspm(struct tegra_pcie_dw *pcie)  static void init_debugfs(struct tegra_pcie_dw *pcie)  { -	debugfs_create_devm_seqfile(pcie->dev, "aspm_state_cnt", pcie->debugfs, +	struct device *dev = pcie->dev; +	char *name; + +	name = devm_kasprintf(dev, GFP_KERNEL, "%pOFP", dev->of_node); +	if (!name) +		return; + +	pcie->debugfs = debugfs_create_dir(name, NULL); + +	debugfs_create_devm_seqfile(dev, "aspm_state_cnt", pcie->debugfs,  				    aspm_state_cnt);  }  #else @@ -1027,12 +1036,12 @@ retry_link:  	return 0;  } -static int tegra_pcie_dw_link_up(struct dw_pcie *pci) +static bool tegra_pcie_dw_link_up(struct dw_pcie *pci)  {  	struct tegra_pcie_dw *pcie = to_tegra_pcie(pci);  	u32 val = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKSTA); -	return !!(val & PCI_EXP_LNKSTA_DLLLA); +	return val & PCI_EXP_LNKSTA_DLLLA;  }  static void tegra_pcie_dw_stop_link(struct dw_pcie *pci) @@ -1634,7 +1643,6 @@ static void tegra_pcie_deinit_controller(struct tegra_pcie_dw *pcie)  static int tegra_pcie_config_rp(struct tegra_pcie_dw *pcie)  {  	struct device *dev = pcie->dev; -	char *name;  	int ret;  	pm_runtime_enable(dev); @@ -1664,13 +1672,6 @@ static int tegra_pcie_config_rp(struct tegra_pcie_dw *pcie)  		goto fail_host_init;  	} -	name = devm_kasprintf(dev, GFP_KERNEL, "%pOFP", dev->of_node); -	if (!name) { -		ret = -ENOMEM; -		goto fail_host_init; -	} - -	pcie->debugfs = debugfs_create_dir(name, NULL);  	init_debugfs(pcie);  	return ret; diff --git a/drivers/pci/controller/dwc/pcie-uniphier.c b/drivers/pci/controller/dwc/pcie-uniphier.c index 5757ca3803c9..297e7a3d9b36 100644 --- a/drivers/pci/controller/dwc/pcie-uniphier.c +++ b/drivers/pci/controller/dwc/pcie-uniphier.c @@ -135,7 +135,7 @@ static int uniphier_pcie_wait_rc(struct uniphier_pcie *pcie)  	return 0;  } -static int uniphier_pcie_link_up(struct dw_pcie *pci) +static bool uniphier_pcie_link_up(struct dw_pcie *pci)  {  	struct uniphier_pcie *pcie = to_uniphier_pcie(pci);  	u32 val, mask; @@ -279,7 +279,7 @@ static int uniphier_pcie_config_intx_irq(struct dw_pcie_rp *pp)  		goto out_put_node;  	} -	pcie->intx_irq_domain = irq_domain_add_linear(np_intc, PCI_NUM_INTX, +	pcie->intx_irq_domain = irq_domain_create_linear(of_fwnode_handle(np_intc), PCI_NUM_INTX,  						&uniphier_intx_domain_ops, pp);  	if (!pcie->intx_irq_domain) {  		dev_err(pci->dev, "Failed to get INTx domain\n"); diff --git a/drivers/pci/controller/dwc/pcie-visconti.c b/drivers/pci/controller/dwc/pcie-visconti.c index 318c278e65c8..cdeac6177143 100644 --- a/drivers/pci/controller/dwc/pcie-visconti.c +++ b/drivers/pci/controller/dwc/pcie-visconti.c @@ -121,13 +121,13 @@ static u32 visconti_mpu_readl(struct visconti_pcie *pcie, u32 reg)  	return readl_relaxed(pcie->mpu_base + reg);  } -static int visconti_pcie_link_up(struct dw_pcie *pci) +static bool visconti_pcie_link_up(struct dw_pcie *pci)  {  	struct visconti_pcie *pcie = dev_get_drvdata(pci->dev);  	void __iomem *addr = pcie->ulreg_base;  	u32 val = readl_relaxed(addr + PCIE_UL_REG_V_PHY_ST_02); -	return !!(val & PCIE_UL_S_L0); +	return val & PCIE_UL_S_L0;  }  static int visconti_pcie_start_link(struct dw_pcie *pci) | 
