diff options
Diffstat (limited to 'drivers/pci/controller')
30 files changed, 1281 insertions, 601 deletions
| diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig index 6012f3059acd..011c57cae4b0 100644 --- a/drivers/pci/controller/Kconfig +++ b/drivers/pci/controller/Kconfig @@ -267,6 +267,7 @@ config PCIE_TANGO_SMP8759  config VMD  	depends on PCI_MSI && X86_64 && SRCU +	select X86_DEV_DMA_OPS  	tristate "Intel Volume Management Device Driver"  	---help---  	  Adds support for the Intel Volume Management Device (VMD). VMD is a diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig index 6ea74b1c0d94..a6ce1ee51b4c 100644 --- a/drivers/pci/controller/dwc/Kconfig +++ b/drivers/pci/controller/dwc/Kconfig @@ -103,15 +103,32 @@ config PCIE_SPEAR13XX  	  Say Y here if you want PCIe support on SPEAr13XX SoCs.  config PCI_KEYSTONE -	bool "TI Keystone PCIe controller" -	depends on ARCH_KEYSTONE || (ARM && COMPILE_TEST) +	bool + +config PCI_KEYSTONE_HOST +	bool "PCI Keystone Host Mode" +	depends on ARCH_KEYSTONE || ARCH_K3 || ((ARM || ARM64) && COMPILE_TEST)  	depends on PCI_MSI_IRQ_DOMAIN  	select PCIE_DW_HOST +	select PCI_KEYSTONE +	default y  	help -	  Say Y here if you want to enable PCI controller support on Keystone -	  SoCs. The PCI controller on Keystone is based on DesignWare hardware -	  and therefore the driver re-uses the DesignWare core functions to -	  implement the driver. +	  Enables support for the PCIe controller in the Keystone SoC to +	  work in host mode. The PCI controller on Keystone is based on +	  DesignWare hardware and therefore the driver re-uses the +	  DesignWare core functions to implement the driver. + +config PCI_KEYSTONE_EP +	bool "PCI Keystone Endpoint Mode" +	depends on ARCH_KEYSTONE || ARCH_K3 || ((ARM || ARM64) && COMPILE_TEST) +	depends on PCI_ENDPOINT +	select PCIE_DW_EP +	select PCI_KEYSTONE +	help +	  Enables support for the PCIe controller in the Keystone SoC to +	  work in endpoint mode. The PCI controller on Keystone is based +	  on DesignWare hardware and therefore the driver re-uses the +	  DesignWare core functions to implement the driver.  config PCI_LAYERSCAPE  	bool "Freescale Layerscape PCIe controller" diff --git a/drivers/pci/controller/dwc/Makefile b/drivers/pci/controller/dwc/Makefile index b5f3b83cc2b3..b085dfd4fab7 100644 --- a/drivers/pci/controller/dwc/Makefile +++ b/drivers/pci/controller/dwc/Makefile @@ -28,5 +28,6 @@ obj-$(CONFIG_PCIE_UNIPHIER) += pcie-uniphier.o  # depending on whether ACPI, the DT driver, or both are enabled.  ifdef CONFIG_PCI +obj-$(CONFIG_ARM64) += pcie-al.o  obj-$(CONFIG_ARM64) += pcie-hisi.o  endif diff --git a/drivers/pci/controller/dwc/pci-dra7xx.c b/drivers/pci/controller/dwc/pci-dra7xx.c index ae84a69ae63a..419451efd58c 100644 --- a/drivers/pci/controller/dwc/pci-dra7xx.c +++ b/drivers/pci/controller/dwc/pci-dra7xx.c @@ -247,6 +247,7 @@ static int dra7xx_pcie_init_irq_domain(struct pcie_port *pp)  	dra7xx->irq_domain = irq_domain_add_linear(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");  		return -ENODEV; @@ -406,7 +407,7 @@ dra7xx_pcie_get_features(struct dw_pcie_ep *ep)  	return &dra7xx_pcie_epc_features;  } -static struct dw_pcie_ep_ops pcie_ep_ops = { +static const struct dw_pcie_ep_ops pcie_ep_ops = {  	.ep_init = dra7xx_pcie_ep_init,  	.raise_irq = dra7xx_pcie_raise_irq,  	.get_features = dra7xx_pcie_get_features, diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c index 3d627f94a166..9b5cb5b70389 100644 --- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -52,6 +52,7 @@ enum imx6_pcie_variants {  #define IMX6_PCIE_FLAG_IMX6_PHY			BIT(0)  #define IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE	BIT(1) +#define IMX6_PCIE_FLAG_SUPPORTS_SUSPEND		BIT(2)  struct imx6_pcie_drvdata {  	enum imx6_pcie_variants variant; @@ -89,9 +90,8 @@ struct imx6_pcie {  };  /* Parameters for the waiting for PCIe PHY PLL to lock on i.MX7 */ -#define PHY_PLL_LOCK_WAIT_MAX_RETRIES	2000 -#define PHY_PLL_LOCK_WAIT_USLEEP_MIN	50  #define PHY_PLL_LOCK_WAIT_USLEEP_MAX	200 +#define PHY_PLL_LOCK_WAIT_TIMEOUT	(2000 * PHY_PLL_LOCK_WAIT_USLEEP_MAX)  /* PCIe Root Complex registers (memory-mapped) */  #define PCIE_RC_IMX6_MSI_CAP			0x50 @@ -104,34 +104,29 @@ struct imx6_pcie {  /* PCIe Port Logic registers (memory-mapped) */  #define PL_OFFSET 0x700 -#define PCIE_PL_PFLR (PL_OFFSET + 0x08) -#define PCIE_PL_PFLR_LINK_STATE_MASK		(0x3f << 16) -#define PCIE_PL_PFLR_FORCE_LINK			(1 << 15) -#define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28) -#define PCIE_PHY_DEBUG_R1 (PL_OFFSET + 0x2c)  #define PCIE_PHY_CTRL (PL_OFFSET + 0x114) -#define PCIE_PHY_CTRL_DATA_LOC 0 -#define PCIE_PHY_CTRL_CAP_ADR_LOC 16 -#define PCIE_PHY_CTRL_CAP_DAT_LOC 17 -#define PCIE_PHY_CTRL_WR_LOC 18 -#define PCIE_PHY_CTRL_RD_LOC 19 +#define PCIE_PHY_CTRL_DATA(x)		FIELD_PREP(GENMASK(15, 0), (x)) +#define PCIE_PHY_CTRL_CAP_ADR		BIT(16) +#define PCIE_PHY_CTRL_CAP_DAT		BIT(17) +#define PCIE_PHY_CTRL_WR		BIT(18) +#define PCIE_PHY_CTRL_RD		BIT(19)  #define PCIE_PHY_STAT (PL_OFFSET + 0x110) -#define PCIE_PHY_STAT_ACK_LOC 16 +#define PCIE_PHY_STAT_ACK		BIT(16)  #define PCIE_LINK_WIDTH_SPEED_CONTROL	0x80C  /* PHY registers (not memory-mapped) */  #define PCIE_PHY_ATEOVRD			0x10 -#define  PCIE_PHY_ATEOVRD_EN			(0x1 << 2) +#define  PCIE_PHY_ATEOVRD_EN			BIT(2)  #define  PCIE_PHY_ATEOVRD_REF_CLKDIV_SHIFT	0  #define  PCIE_PHY_ATEOVRD_REF_CLKDIV_MASK	0x1  #define PCIE_PHY_MPLL_OVRD_IN_LO		0x11  #define  PCIE_PHY_MPLL_MULTIPLIER_SHIFT		2  #define  PCIE_PHY_MPLL_MULTIPLIER_MASK		0x7f -#define  PCIE_PHY_MPLL_MULTIPLIER_OVRD		(0x1 << 9) +#define  PCIE_PHY_MPLL_MULTIPLIER_OVRD		BIT(9)  #define PCIE_PHY_RX_ASIC_OUT 0x100D  #define PCIE_PHY_RX_ASIC_OUT_VALID	(1 << 0) @@ -154,19 +149,19 @@ struct imx6_pcie {  #define PCIE_PHY_CMN_REG26_ATT_MODE	0xBC  #define PHY_RX_OVRD_IN_LO 0x1005 -#define PHY_RX_OVRD_IN_LO_RX_DATA_EN (1 << 5) -#define PHY_RX_OVRD_IN_LO_RX_PLL_EN (1 << 3) +#define PHY_RX_OVRD_IN_LO_RX_DATA_EN		BIT(5) +#define PHY_RX_OVRD_IN_LO_RX_PLL_EN		BIT(3) -static int pcie_phy_poll_ack(struct imx6_pcie *imx6_pcie, int exp_val) +static int pcie_phy_poll_ack(struct imx6_pcie *imx6_pcie, bool exp_val)  {  	struct dw_pcie *pci = imx6_pcie->pci; -	u32 val; +	bool val;  	u32 max_iterations = 10;  	u32 wait_counter = 0;  	do { -		val = dw_pcie_readl_dbi(pci, PCIE_PHY_STAT); -		val = (val >> PCIE_PHY_STAT_ACK_LOC) & 0x1; +		val = dw_pcie_readl_dbi(pci, PCIE_PHY_STAT) & +			PCIE_PHY_STAT_ACK;  		wait_counter++;  		if (val == exp_val) @@ -184,27 +179,27 @@ static int pcie_phy_wait_ack(struct imx6_pcie *imx6_pcie, int addr)  	u32 val;  	int ret; -	val = addr << PCIE_PHY_CTRL_DATA_LOC; +	val = PCIE_PHY_CTRL_DATA(addr);  	dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, val); -	val |= (0x1 << PCIE_PHY_CTRL_CAP_ADR_LOC); +	val |= PCIE_PHY_CTRL_CAP_ADR;  	dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, val); -	ret = pcie_phy_poll_ack(imx6_pcie, 1); +	ret = pcie_phy_poll_ack(imx6_pcie, true);  	if (ret)  		return ret; -	val = addr << PCIE_PHY_CTRL_DATA_LOC; +	val = PCIE_PHY_CTRL_DATA(addr);  	dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, val); -	return pcie_phy_poll_ack(imx6_pcie, 0); +	return pcie_phy_poll_ack(imx6_pcie, false);  }  /* Read from the 16-bit PCIe PHY control registers (not memory-mapped) */ -static int pcie_phy_read(struct imx6_pcie *imx6_pcie, int addr, int *data) +static int pcie_phy_read(struct imx6_pcie *imx6_pcie, int addr, u16 *data)  {  	struct dw_pcie *pci = imx6_pcie->pci; -	u32 val, phy_ctl; +	u32 phy_ctl;  	int ret;  	ret = pcie_phy_wait_ack(imx6_pcie, addr); @@ -212,23 +207,22 @@ static int pcie_phy_read(struct imx6_pcie *imx6_pcie, int addr, int *data)  		return ret;  	/* assert Read signal */ -	phy_ctl = 0x1 << PCIE_PHY_CTRL_RD_LOC; +	phy_ctl = PCIE_PHY_CTRL_RD;  	dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, phy_ctl); -	ret = pcie_phy_poll_ack(imx6_pcie, 1); +	ret = pcie_phy_poll_ack(imx6_pcie, true);  	if (ret)  		return ret; -	val = dw_pcie_readl_dbi(pci, PCIE_PHY_STAT); -	*data = val & 0xffff; +	*data = dw_pcie_readl_dbi(pci, PCIE_PHY_STAT);  	/* deassert Read signal */  	dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, 0x00); -	return pcie_phy_poll_ack(imx6_pcie, 0); +	return pcie_phy_poll_ack(imx6_pcie, false);  } -static int pcie_phy_write(struct imx6_pcie *imx6_pcie, int addr, int data) +static int pcie_phy_write(struct imx6_pcie *imx6_pcie, int addr, u16 data)  {  	struct dw_pcie *pci = imx6_pcie->pci;  	u32 var; @@ -240,41 +234,41 @@ static int pcie_phy_write(struct imx6_pcie *imx6_pcie, int addr, int data)  	if (ret)  		return ret; -	var = data << PCIE_PHY_CTRL_DATA_LOC; +	var = PCIE_PHY_CTRL_DATA(data);  	dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var);  	/* capture data */ -	var |= (0x1 << PCIE_PHY_CTRL_CAP_DAT_LOC); +	var |= PCIE_PHY_CTRL_CAP_DAT;  	dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var); -	ret = pcie_phy_poll_ack(imx6_pcie, 1); +	ret = pcie_phy_poll_ack(imx6_pcie, true);  	if (ret)  		return ret;  	/* deassert cap data */ -	var = data << PCIE_PHY_CTRL_DATA_LOC; +	var = PCIE_PHY_CTRL_DATA(data);  	dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var);  	/* wait for ack de-assertion */ -	ret = pcie_phy_poll_ack(imx6_pcie, 0); +	ret = pcie_phy_poll_ack(imx6_pcie, false);  	if (ret)  		return ret;  	/* assert wr signal */ -	var = 0x1 << PCIE_PHY_CTRL_WR_LOC; +	var = PCIE_PHY_CTRL_WR;  	dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var);  	/* wait for ack */ -	ret = pcie_phy_poll_ack(imx6_pcie, 1); +	ret = pcie_phy_poll_ack(imx6_pcie, true);  	if (ret)  		return ret;  	/* deassert wr signal */ -	var = data << PCIE_PHY_CTRL_DATA_LOC; +	var = PCIE_PHY_CTRL_DATA(data);  	dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var);  	/* wait for ack de-assertion */ -	ret = pcie_phy_poll_ack(imx6_pcie, 0); +	ret = pcie_phy_poll_ack(imx6_pcie, false);  	if (ret)  		return ret; @@ -285,7 +279,7 @@ static int pcie_phy_write(struct imx6_pcie *imx6_pcie, int addr, int data)  static void imx6_pcie_reset_phy(struct imx6_pcie *imx6_pcie)  { -	u32 tmp; +	u16 tmp;  	if (!(imx6_pcie->drvdata->flags & IMX6_PCIE_FLAG_IMX6_PHY))  		return; @@ -455,7 +449,7 @@ static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)  		 * reset time is too short, cannot meet the requirement.  		 * add one ~10us delay here.  		 */ -		udelay(10); +		usleep_range(10, 100);  		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,  				   IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16);  		break; @@ -488,20 +482,14 @@ static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)  static void imx7d_pcie_wait_for_phy_pll_lock(struct imx6_pcie *imx6_pcie)  {  	u32 val; -	unsigned int retries;  	struct device *dev = imx6_pcie->pci->dev; -	for (retries = 0; retries < PHY_PLL_LOCK_WAIT_MAX_RETRIES; retries++) { -		regmap_read(imx6_pcie->iomuxc_gpr, IOMUXC_GPR22, &val); - -		if (val & IMX7D_GPR22_PCIE_PHY_PLL_LOCKED) -			return; - -		usleep_range(PHY_PLL_LOCK_WAIT_USLEEP_MIN, -			     PHY_PLL_LOCK_WAIT_USLEEP_MAX); -	} - -	dev_err(dev, "PCIe PLL lock timeout\n"); +	if (regmap_read_poll_timeout(imx6_pcie->iomuxc_gpr, +				     IOMUXC_GPR22, val, +				     val & IMX7D_GPR22_PCIE_PHY_PLL_LOCKED, +				     PHY_PLL_LOCK_WAIT_USLEEP_MAX, +				     PHY_PLL_LOCK_WAIT_TIMEOUT)) +		dev_err(dev, "PCIe PLL lock timeout\n");  }  static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie) @@ -687,7 +675,7 @@ static int imx6_setup_phy_mpll(struct imx6_pcie *imx6_pcie)  {  	unsigned long phy_rate = clk_get_rate(imx6_pcie->pcie_phy);  	int mult, div; -	u32 val; +	u16 val;  	if (!(imx6_pcie->drvdata->flags & IMX6_PCIE_FLAG_IMX6_PHY))  		return 0; @@ -730,21 +718,6 @@ static int imx6_setup_phy_mpll(struct imx6_pcie *imx6_pcie)  	return 0;  } -static int imx6_pcie_wait_for_link(struct imx6_pcie *imx6_pcie) -{ -	struct dw_pcie *pci = imx6_pcie->pci; -	struct device *dev = pci->dev; - -	/* check if the link is up or not */ -	if (!dw_pcie_wait_for_link(pci)) -		return 0; - -	dev_dbg(dev, "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n", -		dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R0), -		dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R1)); -	return -ETIMEDOUT; -} -  static int imx6_pcie_wait_for_speed_change(struct imx6_pcie *imx6_pcie)  {  	struct dw_pcie *pci = imx6_pcie->pci; @@ -761,7 +734,7 @@ static int imx6_pcie_wait_for_speed_change(struct imx6_pcie *imx6_pcie)  	}  	dev_err(dev, "Speed change timeout\n"); -	return -EINVAL; +	return -ETIMEDOUT;  }  static void imx6_pcie_ltssm_enable(struct device *dev) @@ -803,7 +776,7 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)  	/* Start LTSSM. */  	imx6_pcie_ltssm_enable(dev); -	ret = imx6_pcie_wait_for_link(imx6_pcie); +	ret = dw_pcie_wait_for_link(pci);  	if (ret)  		goto err_reset_phy; @@ -841,7 +814,7 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)  		}  		/* Make sure link training is finished as well! */ -		ret = imx6_pcie_wait_for_link(imx6_pcie); +		ret = dw_pcie_wait_for_link(pci);  		if (ret) {  			dev_err(dev, "Failed to bring link up!\n");  			goto err_reset_phy; @@ -856,8 +829,8 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)  err_reset_phy:  	dev_dbg(dev, "PHY DEBUG_R0=0x%08x DEBUG_R1=0x%08x\n", -		dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R0), -		dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R1)); +		dw_pcie_readl_dbi(pci, PCIE_PORT_DEBUG0), +		dw_pcie_readl_dbi(pci, PCIE_PORT_DEBUG1));  	imx6_pcie_reset_phy(imx6_pcie);  	return ret;  } @@ -993,17 +966,11 @@ static void imx6_pcie_clk_disable(struct imx6_pcie *imx6_pcie)  	}  } -static inline bool imx6_pcie_supports_suspend(struct imx6_pcie *imx6_pcie) -{ -	return (imx6_pcie->drvdata->variant == IMX7D || -		imx6_pcie->drvdata->variant == IMX6SX); -} -  static int imx6_pcie_suspend_noirq(struct device *dev)  {  	struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev); -	if (!imx6_pcie_supports_suspend(imx6_pcie)) +	if (!(imx6_pcie->drvdata->flags & IMX6_PCIE_FLAG_SUPPORTS_SUSPEND))  		return 0;  	imx6_pcie_pm_turnoff(imx6_pcie); @@ -1019,7 +986,7 @@ static int imx6_pcie_resume_noirq(struct device *dev)  	struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);  	struct pcie_port *pp = &imx6_pcie->pci->pp; -	if (!imx6_pcie_supports_suspend(imx6_pcie)) +	if (!(imx6_pcie->drvdata->flags & IMX6_PCIE_FLAG_SUPPORTS_SUSPEND))  		return 0;  	imx6_pcie_assert_core_reset(imx6_pcie); @@ -1249,7 +1216,8 @@ static const struct imx6_pcie_drvdata drvdata[] = {  	[IMX6SX] = {  		.variant = IMX6SX,  		.flags = IMX6_PCIE_FLAG_IMX6_PHY | -			 IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE, +			 IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE | +			 IMX6_PCIE_FLAG_SUPPORTS_SUSPEND,  	},  	[IMX6QP] = {  		.variant = IMX6QP, @@ -1258,6 +1226,7 @@ static const struct imx6_pcie_drvdata drvdata[] = {  	},  	[IMX7D] = {  		.variant = IMX7D, +		.flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND,  	},  	[IMX8MQ] = {  		.variant = IMX8MQ, @@ -1279,6 +1248,7 @@ static struct platform_driver imx6_pcie_driver = {  		.of_match_table = imx6_pcie_of_match,  		.suppress_bind_attrs = true,  		.pm = &imx6_pcie_pm_ops, +		.probe_type = PROBE_PREFER_ASYNCHRONOUS,  	},  	.probe    = imx6_pcie_probe,  	.shutdown = imx6_pcie_shutdown, diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c index 14f2b0b4ed5e..af677254a072 100644 --- a/drivers/pci/controller/dwc/pci-keystone.c +++ b/drivers/pci/controller/dwc/pci-keystone.c @@ -11,6 +11,7 @@  #include <linux/clk.h>  #include <linux/delay.h> +#include <linux/gpio/consumer.h>  #include <linux/init.h>  #include <linux/interrupt.h>  #include <linux/irqchip/chained_irq.h> @@ -18,6 +19,7 @@  #include <linux/mfd/syscon.h>  #include <linux/msi.h>  #include <linux/of.h> +#include <linux/of_device.h>  #include <linux/of_irq.h>  #include <linux/of_pci.h>  #include <linux/phy/phy.h> @@ -26,6 +28,7 @@  #include <linux/resource.h>  #include <linux/signal.h> +#include "../../pci.h"  #include "pcie-designware.h"  #define PCIE_VENDORID_MASK	0xffff @@ -44,28 +47,34 @@  #define CFG_TYPE1			BIT(24)  #define OB_SIZE				0x030 -#define SPACE0_REMOTE_CFG_OFFSET	0x1000  #define OB_OFFSET_INDEX(n)		(0x200 + (8 * (n)))  #define OB_OFFSET_HI(n)			(0x204 + (8 * (n)))  #define OB_ENABLEN			BIT(0)  #define OB_WIN_SIZE			8	/* 8MB */ +#define PCIE_LEGACY_IRQ_ENABLE_SET(n)	(0x188 + (0x10 * ((n) - 1))) +#define PCIE_LEGACY_IRQ_ENABLE_CLR(n)	(0x18c + (0x10 * ((n) - 1))) +#define PCIE_EP_IRQ_SET			0x64 +#define PCIE_EP_IRQ_CLR			0x68 +#define INT_ENABLE			BIT(0) +  /* IRQ register defines */  #define IRQ_EOI				0x050 -#define IRQ_STATUS			0x184 -#define IRQ_ENABLE_SET			0x188 -#define IRQ_ENABLE_CLR			0x18c  #define MSI_IRQ				0x054 -#define MSI0_IRQ_STATUS			0x104 -#define MSI0_IRQ_ENABLE_SET		0x108 -#define MSI0_IRQ_ENABLE_CLR		0x10c -#define IRQ_STATUS			0x184 +#define MSI_IRQ_STATUS(n)		(0x104 + ((n) << 4)) +#define MSI_IRQ_ENABLE_SET(n)		(0x108 + ((n) << 4)) +#define MSI_IRQ_ENABLE_CLR(n)		(0x10c + ((n) << 4))  #define MSI_IRQ_OFFSET			4 +#define IRQ_STATUS(n)			(0x184 + ((n) << 4)) +#define IRQ_ENABLE_SET(n)		(0x188 + ((n) << 4)) +#define INTx_EN				BIT(0) +  #define ERR_IRQ_STATUS			0x1c4  #define ERR_IRQ_ENABLE_SET		0x1c8  #define ERR_AER				BIT(5)	/* ECRC error */ +#define AM6_ERR_AER			BIT(4)	/* AM6 ECRC error */  #define ERR_AXI				BIT(4)	/* AXI tag lookup fatal error */  #define ERR_CORR			BIT(3)	/* Correctable error */  #define ERR_NONFATAL			BIT(2)	/* Non-fatal error */ @@ -74,25 +83,45 @@  #define ERR_IRQ_ALL			(ERR_AER | ERR_AXI | ERR_CORR | \  					 ERR_NONFATAL | ERR_FATAL | ERR_SYS) -#define MAX_MSI_HOST_IRQS		8  /* PCIE controller device IDs */  #define PCIE_RC_K2HK			0xb008  #define PCIE_RC_K2E			0xb009  #define PCIE_RC_K2L			0xb00a  #define PCIE_RC_K2G			0xb00b +#define KS_PCIE_DEV_TYPE_MASK		(0x3 << 1) +#define KS_PCIE_DEV_TYPE(mode)		((mode) << 1) + +#define EP				0x0 +#define LEG_EP				0x1 +#define RC				0x2 + +#define EXP_CAP_ID_OFFSET		0x70 + +#define KS_PCIE_SYSCLOCKOUTEN		BIT(0) + +#define AM654_PCIE_DEV_TYPE_MASK	0x3 +#define AM654_WIN_SIZE			SZ_64K + +#define APP_ADDR_SPACE_0		(16 * SZ_1K) +  #define to_keystone_pcie(x)		dev_get_drvdata((x)->dev) +struct ks_pcie_of_data { +	enum dw_pcie_device_mode mode; +	const struct dw_pcie_host_ops *host_ops; +	const struct dw_pcie_ep_ops *ep_ops; +	unsigned int version; +}; +  struct keystone_pcie {  	struct dw_pcie		*pci;  	/* PCI Device ID */  	u32			device_id; -	int			num_legacy_host_irqs;  	int			legacy_host_irqs[PCI_NUM_INTX];  	struct			device_node *legacy_intc_np; -	int			num_msi_host_irqs; -	int			msi_host_irqs[MAX_MSI_HOST_IRQS]; +	int			msi_host_irq;  	int			num_lanes;  	u32			num_viewport;  	struct phy		**phy; @@ -101,28 +130,12 @@ struct keystone_pcie {  	struct irq_domain	*legacy_irq_domain;  	struct device_node	*np; -	int error_irq; -  	/* Application register space */  	void __iomem		*va_app_base;	/* DT 1st resource */  	struct resource		app; +	bool			is_am6;  }; -static inline void update_reg_offset_bit_pos(u32 offset, u32 *reg_offset, -					     u32 *bit_pos) -{ -	*reg_offset = offset % 8; -	*bit_pos = offset >> 3; -} - -static phys_addr_t ks_pcie_get_msi_addr(struct pcie_port *pp) -{ -	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); -	struct keystone_pcie *ks_pcie = to_keystone_pcie(pci); - -	return ks_pcie->app.start + MSI_IRQ; -} -  static u32 ks_pcie_app_readl(struct keystone_pcie *ks_pcie, u32 offset)  {  	return readl(ks_pcie->va_app_base + offset); @@ -134,81 +147,114 @@ static void ks_pcie_app_writel(struct keystone_pcie *ks_pcie, u32 offset,  	writel(val, ks_pcie->va_app_base + offset);  } -static void ks_pcie_handle_msi_irq(struct keystone_pcie *ks_pcie, int offset) +static void ks_pcie_msi_irq_ack(struct irq_data *data)  { -	struct dw_pcie *pci = ks_pcie->pci; -	struct pcie_port *pp = &pci->pp; -	struct device *dev = pci->dev; -	u32 pending, vector; -	int src, virq; +	struct pcie_port *pp  = irq_data_get_irq_chip_data(data); +	struct keystone_pcie *ks_pcie; +	u32 irq = data->hwirq; +	struct dw_pcie *pci; +	u32 reg_offset; +	u32 bit_pos; -	pending = ks_pcie_app_readl(ks_pcie, MSI0_IRQ_STATUS + (offset << 4)); +	pci = to_dw_pcie_from_pp(pp); +	ks_pcie = to_keystone_pcie(pci); -	/* -	 * MSI0 status bit 0-3 shows vectors 0, 8, 16, 24, MSI1 status bit -	 * shows 1, 9, 17, 25 and so forth -	 */ -	for (src = 0; src < 4; src++) { -		if (BIT(src) & pending) { -			vector = offset + (src << 3); -			virq = irq_linear_revmap(pp->irq_domain, vector); -			dev_dbg(dev, "irq: bit %d, vector %d, virq %d\n", -				src, vector, virq); -			generic_handle_irq(virq); -		} -	} +	reg_offset = irq % 8; +	bit_pos = irq >> 3; + +	ks_pcie_app_writel(ks_pcie, MSI_IRQ_STATUS(reg_offset), +			   BIT(bit_pos)); +	ks_pcie_app_writel(ks_pcie, IRQ_EOI, reg_offset + MSI_IRQ_OFFSET);  } -static void ks_pcie_msi_irq_ack(int irq, struct pcie_port *pp) +static void ks_pcie_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)  { -	u32 reg_offset, bit_pos; +	struct pcie_port *pp = irq_data_get_irq_chip_data(data);  	struct keystone_pcie *ks_pcie;  	struct dw_pcie *pci; +	u64 msi_target;  	pci = to_dw_pcie_from_pp(pp);  	ks_pcie = to_keystone_pcie(pci); -	update_reg_offset_bit_pos(irq, ®_offset, &bit_pos); -	ks_pcie_app_writel(ks_pcie, MSI0_IRQ_STATUS + (reg_offset << 4), -			   BIT(bit_pos)); -	ks_pcie_app_writel(ks_pcie, IRQ_EOI, reg_offset + MSI_IRQ_OFFSET); +	msi_target = ks_pcie->app.start + MSI_IRQ; +	msg->address_lo = lower_32_bits(msi_target); +	msg->address_hi = upper_32_bits(msi_target); +	msg->data = data->hwirq; + +	dev_dbg(pci->dev, "msi#%d address_hi %#x address_lo %#x\n", +		(int)data->hwirq, msg->address_hi, msg->address_lo);  } -static void ks_pcie_msi_set_irq(struct pcie_port *pp, int irq) +static int ks_pcie_msi_set_affinity(struct irq_data *irq_data, +				    const struct cpumask *mask, bool force)  { -	u32 reg_offset, bit_pos; -	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); -	struct keystone_pcie *ks_pcie = to_keystone_pcie(pci); +	return -EINVAL; +} -	update_reg_offset_bit_pos(irq, ®_offset, &bit_pos); -	ks_pcie_app_writel(ks_pcie, MSI0_IRQ_ENABLE_SET + (reg_offset << 4), +static void ks_pcie_msi_mask(struct irq_data *data) +{ +	struct pcie_port *pp = irq_data_get_irq_chip_data(data); +	struct keystone_pcie *ks_pcie; +	u32 irq = data->hwirq; +	struct dw_pcie *pci; +	unsigned long flags; +	u32 reg_offset; +	u32 bit_pos; + +	raw_spin_lock_irqsave(&pp->lock, flags); + +	pci = to_dw_pcie_from_pp(pp); +	ks_pcie = to_keystone_pcie(pci); + +	reg_offset = irq % 8; +	bit_pos = irq >> 3; + +	ks_pcie_app_writel(ks_pcie, MSI_IRQ_ENABLE_CLR(reg_offset),  			   BIT(bit_pos)); + +	raw_spin_unlock_irqrestore(&pp->lock, flags);  } -static void ks_pcie_msi_clear_irq(struct pcie_port *pp, int irq) +static void ks_pcie_msi_unmask(struct irq_data *data)  { -	u32 reg_offset, bit_pos; -	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); -	struct keystone_pcie *ks_pcie = to_keystone_pcie(pci); +	struct pcie_port *pp = irq_data_get_irq_chip_data(data); +	struct keystone_pcie *ks_pcie; +	u32 irq = data->hwirq; +	struct dw_pcie *pci; +	unsigned long flags; +	u32 reg_offset; +	u32 bit_pos; + +	raw_spin_lock_irqsave(&pp->lock, flags); -	update_reg_offset_bit_pos(irq, ®_offset, &bit_pos); -	ks_pcie_app_writel(ks_pcie, MSI0_IRQ_ENABLE_CLR + (reg_offset << 4), +	pci = to_dw_pcie_from_pp(pp); +	ks_pcie = to_keystone_pcie(pci); + +	reg_offset = irq % 8; +	bit_pos = irq >> 3; + +	ks_pcie_app_writel(ks_pcie, MSI_IRQ_ENABLE_SET(reg_offset),  			   BIT(bit_pos)); + +	raw_spin_unlock_irqrestore(&pp->lock, flags);  } +static struct irq_chip ks_pcie_msi_irq_chip = { +	.name = "KEYSTONE-PCI-MSI", +	.irq_ack = ks_pcie_msi_irq_ack, +	.irq_compose_msi_msg = ks_pcie_compose_msi_msg, +	.irq_set_affinity = ks_pcie_msi_set_affinity, +	.irq_mask = ks_pcie_msi_mask, +	.irq_unmask = ks_pcie_msi_unmask, +}; +  static int ks_pcie_msi_host_init(struct pcie_port *pp)  { +	pp->msi_irq_chip = &ks_pcie_msi_irq_chip;  	return dw_pcie_allocate_domains(pp);  } -static void ks_pcie_enable_legacy_irqs(struct keystone_pcie *ks_pcie) -{ -	int i; - -	for (i = 0; i < PCI_NUM_INTX; i++) -		ks_pcie_app_writel(ks_pcie, IRQ_ENABLE_SET + (i << 4), 0x1); -} -  static void ks_pcie_handle_legacy_irq(struct keystone_pcie *ks_pcie,  				      int offset)  { @@ -217,7 +263,7 @@ static void ks_pcie_handle_legacy_irq(struct keystone_pcie *ks_pcie,  	u32 pending;  	int virq; -	pending = ks_pcie_app_readl(ks_pcie, IRQ_STATUS + (offset << 4)); +	pending = ks_pcie_app_readl(ks_pcie, IRQ_STATUS(offset));  	if (BIT(0) & pending) {  		virq = irq_linear_revmap(ks_pcie->legacy_irq_domain, offset); @@ -229,6 +275,14 @@ static void ks_pcie_handle_legacy_irq(struct keystone_pcie *ks_pcie,  	ks_pcie_app_writel(ks_pcie, IRQ_EOI, offset);  } +/* + * Dummy function so that DW core doesn't configure MSI + */ +static int ks_pcie_am654_msi_host_init(struct pcie_port *pp) +{ +	return 0; +} +  static void ks_pcie_enable_error_irq(struct keystone_pcie *ks_pcie)  {  	ks_pcie_app_writel(ks_pcie, ERR_IRQ_ENABLE_SET, ERR_IRQ_ALL); @@ -255,10 +309,10 @@ static irqreturn_t ks_pcie_handle_error_irq(struct keystone_pcie *ks_pcie)  	if (reg & ERR_CORR)  		dev_dbg(dev, "Correctable Error\n"); -	if (reg & ERR_AXI) +	if (!ks_pcie->is_am6 && (reg & ERR_AXI))  		dev_err(dev, "AXI tag lookup fatal Error\n"); -	if (reg & ERR_AER) +	if (reg & ERR_AER || (ks_pcie->is_am6 && (reg & AM6_ERR_AER)))  		dev_err(dev, "ECRC Error\n");  	ks_pcie_app_writel(ks_pcie, ERR_IRQ_STATUS, reg); @@ -356,6 +410,9 @@ static void ks_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)  	dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_1, 0);  	ks_pcie_clear_dbi_mode(ks_pcie); +	if (ks_pcie->is_am6) +		return; +  	val = ilog2(OB_WIN_SIZE);  	ks_pcie_app_writel(ks_pcie, OB_SIZE, val); @@ -445,68 +502,33 @@ static int ks_pcie_link_up(struct dw_pcie *pci)  	return (val == PORT_LOGIC_LTSSM_STATE_L0);  } -static void ks_pcie_initiate_link_train(struct keystone_pcie *ks_pcie) +static void ks_pcie_stop_link(struct dw_pcie *pci)  { +	struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);  	u32 val;  	/* Disable Link training */  	val = ks_pcie_app_readl(ks_pcie, CMD_STATUS);  	val &= ~LTSSM_EN_VAL;  	ks_pcie_app_writel(ks_pcie, CMD_STATUS, LTSSM_EN_VAL | val); - -	/* Initiate Link Training */ -	val = ks_pcie_app_readl(ks_pcie, CMD_STATUS); -	ks_pcie_app_writel(ks_pcie, CMD_STATUS, LTSSM_EN_VAL | val);  } -/** - * ks_pcie_dw_host_init() - initialize host for v3_65 dw hardware - * - * Ioremap the register resources, initialize legacy irq domain - * and call dw_pcie_v3_65_host_init() API to initialize the Keystone - * PCI host controller. - */ -static int __init ks_pcie_dw_host_init(struct keystone_pcie *ks_pcie) +static int ks_pcie_start_link(struct dw_pcie *pci)  { -	struct dw_pcie *pci = ks_pcie->pci; -	struct pcie_port *pp = &pci->pp; +	struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);  	struct device *dev = pci->dev; -	struct platform_device *pdev = to_platform_device(dev); -	struct resource *res; - -	/* Index 0 is the config reg. space address */ -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	pci->dbi_base = devm_pci_remap_cfg_resource(dev, res); -	if (IS_ERR(pci->dbi_base)) -		return PTR_ERR(pci->dbi_base); - -	/* -	 * We set these same and is used in pcie rd/wr_other_conf -	 * functions -	 */ -	pp->va_cfg0_base = pci->dbi_base + SPACE0_REMOTE_CFG_OFFSET; -	pp->va_cfg1_base = pp->va_cfg0_base; - -	/* Index 1 is the application reg. space address */ -	res = platform_get_resource(pdev, IORESOURCE_MEM, 1); -	ks_pcie->va_app_base = devm_ioremap_resource(dev, res); -	if (IS_ERR(ks_pcie->va_app_base)) -		return PTR_ERR(ks_pcie->va_app_base); - -	ks_pcie->app = *res; +	u32 val; -	/* Create legacy IRQ domain */ -	ks_pcie->legacy_irq_domain = -			irq_domain_add_linear(ks_pcie->legacy_intc_np, -					      PCI_NUM_INTX, -					      &ks_pcie_legacy_irq_domain_ops, -					      NULL); -	if (!ks_pcie->legacy_irq_domain) { -		dev_err(dev, "Failed to add irq domain for legacy irqs\n"); -		return -EINVAL; +	if (dw_pcie_link_up(pci)) { +		dev_dbg(dev, "link is already up\n"); +		return 0;  	} -	return dw_pcie_host_init(pp); +	/* Initiate Link Training */ +	val = ks_pcie_app_readl(ks_pcie, CMD_STATUS); +	ks_pcie_app_writel(ks_pcie, CMD_STATUS, LTSSM_EN_VAL | val); + +	return 0;  }  static void ks_pcie_quirk(struct pci_dev *dev) @@ -552,34 +574,16 @@ static void ks_pcie_quirk(struct pci_dev *dev)  }  DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, ks_pcie_quirk); -static int ks_pcie_establish_link(struct keystone_pcie *ks_pcie) -{ -	struct dw_pcie *pci = ks_pcie->pci; -	struct device *dev = pci->dev; - -	if (dw_pcie_link_up(pci)) { -		dev_info(dev, "Link already up\n"); -		return 0; -	} - -	ks_pcie_initiate_link_train(ks_pcie); - -	/* check if the link is up or not */ -	if (!dw_pcie_wait_for_link(pci)) -		return 0; - -	dev_err(dev, "phy link never came up\n"); -	return -ETIMEDOUT; -} -  static void ks_pcie_msi_irq_handler(struct irq_desc *desc)  { -	unsigned int irq = irq_desc_get_irq(desc); +	unsigned int irq = desc->irq_data.hwirq;  	struct keystone_pcie *ks_pcie = irq_desc_get_handler_data(desc); -	u32 offset = irq - ks_pcie->msi_host_irqs[0]; +	u32 offset = irq - ks_pcie->msi_host_irq;  	struct dw_pcie *pci = ks_pcie->pci; +	struct pcie_port *pp = &pci->pp;  	struct device *dev = pci->dev;  	struct irq_chip *chip = irq_desc_get_chip(desc); +	u32 vector, virq, reg, pos;  	dev_dbg(dev, "%s, irq %d\n", __func__, irq); @@ -589,7 +593,23 @@ static void ks_pcie_msi_irq_handler(struct irq_desc *desc)  	 * ack operation.  	 */  	chained_irq_enter(chip, desc); -	ks_pcie_handle_msi_irq(ks_pcie, offset); + +	reg = ks_pcie_app_readl(ks_pcie, MSI_IRQ_STATUS(offset)); +	/* +	 * MSI0 status bit 0-3 shows vectors 0, 8, 16, 24, MSI1 status bit +	 * shows 1, 9, 17, 25 and so forth +	 */ +	for (pos = 0; pos < 4; pos++) { +		if (!(reg & BIT(pos))) +			continue; + +		vector = offset + (pos << 3); +		virq = irq_linear_revmap(pp->irq_domain, vector); +		dev_dbg(dev, "irq: bit %d, vector %d, virq %d\n", pos, vector, +			virq); +		generic_handle_irq(virq); +	} +  	chained_irq_exit(chip, desc);  } @@ -622,89 +642,119 @@ static void ks_pcie_legacy_irq_handler(struct irq_desc *desc)  	chained_irq_exit(chip, desc);  } -static int ks_pcie_get_irq_controller_info(struct keystone_pcie *ks_pcie, -					   char *controller, int *num_irqs) +static int ks_pcie_config_msi_irq(struct keystone_pcie *ks_pcie)  { -	int temp, max_host_irqs, legacy = 1, *host_irqs;  	struct device *dev = ks_pcie->pci->dev; -	struct device_node *np_pcie = dev->of_node, **np_temp; - -	if (!strcmp(controller, "msi-interrupt-controller")) -		legacy = 0; +	struct device_node *np = ks_pcie->np; +	struct device_node *intc_np; +	struct irq_data *irq_data; +	int irq_count, irq, ret, i; -	if (legacy) { -		np_temp = &ks_pcie->legacy_intc_np; -		max_host_irqs = PCI_NUM_INTX; -		host_irqs = &ks_pcie->legacy_host_irqs[0]; -	} else { -		np_temp = &ks_pcie->msi_intc_np; -		max_host_irqs = MAX_MSI_HOST_IRQS; -		host_irqs =  &ks_pcie->msi_host_irqs[0]; -	} +	if (!IS_ENABLED(CONFIG_PCI_MSI)) +		return 0; -	/* interrupt controller is in a child node */ -	*np_temp = of_get_child_by_name(np_pcie, controller); -	if (!(*np_temp)) { -		dev_err(dev, "Node for %s is absent\n", controller); +	intc_np = of_get_child_by_name(np, "msi-interrupt-controller"); +	if (!intc_np) { +		if (ks_pcie->is_am6) +			return 0; +		dev_warn(dev, "msi-interrupt-controller node is absent\n");  		return -EINVAL;  	} -	temp = of_irq_count(*np_temp); -	if (!temp) { -		dev_err(dev, "No IRQ entries in %s\n", controller); -		of_node_put(*np_temp); -		return -EINVAL; +	irq_count = of_irq_count(intc_np); +	if (!irq_count) { +		dev_err(dev, "No IRQ entries in msi-interrupt-controller\n"); +		ret = -EINVAL; +		goto err;  	} -	if (temp > max_host_irqs) -		dev_warn(dev, "Too many %s interrupts defined %u\n", -			(legacy ? "legacy" : "MSI"), temp); - -	/* -	 * support upto max_host_irqs. In dt from index 0 to 3 (legacy) or 0 to -	 * 7 (MSI) -	 */ -	for (temp = 0; temp < max_host_irqs; temp++) { -		host_irqs[temp] = irq_of_parse_and_map(*np_temp, temp); -		if (!host_irqs[temp]) -			break; -	} +	for (i = 0; i < irq_count; i++) { +		irq = irq_of_parse_and_map(intc_np, i); +		if (!irq) { +			ret = -EINVAL; +			goto err; +		} -	of_node_put(*np_temp); +		if (!ks_pcie->msi_host_irq) { +			irq_data = irq_get_irq_data(irq); +			if (!irq_data) { +				ret = -EINVAL; +				goto err; +			} +			ks_pcie->msi_host_irq = irq_data->hwirq; +		} -	if (temp) { -		*num_irqs = temp; -		return 0; +		irq_set_chained_handler_and_data(irq, ks_pcie_msi_irq_handler, +						 ks_pcie);  	} -	return -EINVAL; +	of_node_put(intc_np); +	return 0; + +err: +	of_node_put(intc_np); +	return ret;  } -static void ks_pcie_setup_interrupts(struct keystone_pcie *ks_pcie) +static int ks_pcie_config_legacy_irq(struct keystone_pcie *ks_pcie)  { -	int i; +	struct device *dev = ks_pcie->pci->dev; +	struct irq_domain *legacy_irq_domain; +	struct device_node *np = ks_pcie->np; +	struct device_node *intc_np; +	int irq_count, irq, ret = 0, i; + +	intc_np = of_get_child_by_name(np, "legacy-interrupt-controller"); +	if (!intc_np) { +		/* +		 * Since legacy interrupts are modeled as edge-interrupts in +		 * AM6, keep it disabled for now. +		 */ +		if (ks_pcie->is_am6) +			return 0; +		dev_warn(dev, "legacy-interrupt-controller node is absent\n"); +		return -EINVAL; +	} -	/* Legacy IRQ */ -	for (i = 0; i < ks_pcie->num_legacy_host_irqs; i++) { -		irq_set_chained_handler_and_data(ks_pcie->legacy_host_irqs[i], +	irq_count = of_irq_count(intc_np); +	if (!irq_count) { +		dev_err(dev, "No IRQ entries in legacy-interrupt-controller\n"); +		ret = -EINVAL; +		goto err; +	} + +	for (i = 0; i < irq_count; i++) { +		irq = irq_of_parse_and_map(intc_np, i); +		if (!irq) { +			ret = -EINVAL; +			goto err; +		} +		ks_pcie->legacy_host_irqs[i] = irq; + +		irq_set_chained_handler_and_data(irq,  						 ks_pcie_legacy_irq_handler,  						 ks_pcie);  	} -	ks_pcie_enable_legacy_irqs(ks_pcie); -	/* MSI IRQ */ -	if (IS_ENABLED(CONFIG_PCI_MSI)) { -		for (i = 0; i < ks_pcie->num_msi_host_irqs; i++) { -			irq_set_chained_handler_and_data(ks_pcie->msi_host_irqs[i], -							 ks_pcie_msi_irq_handler, -							 ks_pcie); -		} +	legacy_irq_domain = +		irq_domain_add_linear(intc_np, PCI_NUM_INTX, +				      &ks_pcie_legacy_irq_domain_ops, NULL); +	if (!legacy_irq_domain) { +		dev_err(dev, "Failed to add irq domain for legacy irqs\n"); +		ret = -EINVAL; +		goto err;  	} +	ks_pcie->legacy_irq_domain = legacy_irq_domain; + +	for (i = 0; i < PCI_NUM_INTX; i++) +		ks_pcie_app_writel(ks_pcie, IRQ_ENABLE_SET(i), INTx_EN); -	if (ks_pcie->error_irq > 0) -		ks_pcie_enable_error_irq(ks_pcie); +err: +	of_node_put(intc_np); +	return ret;  } +#ifdef CONFIG_ARM  /*   * When a PCI device does not exist during config cycles, keystone host gets a   * bus error instead of returning 0xffffffff. This handler always returns 0 @@ -724,6 +774,7 @@ static int ks_pcie_fault(unsigned long addr, unsigned int fsr,  	return 0;  } +#endif  static int __init ks_pcie_init_id(struct keystone_pcie *ks_pcie)  { @@ -742,8 +793,10 @@ static int __init ks_pcie_init_id(struct keystone_pcie *ks_pcie)  	if (ret)  		return ret; +	dw_pcie_dbi_ro_wr_en(pci);  	dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, id & PCIE_VENDORID_MASK);  	dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, id >> PCIE_DEVICEID_SHIFT); +	dw_pcie_dbi_ro_wr_dis(pci);  	return 0;  } @@ -754,11 +807,18 @@ static int __init ks_pcie_host_init(struct pcie_port *pp)  	struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);  	int ret; +	ret = ks_pcie_config_legacy_irq(ks_pcie); +	if (ret) +		return ret; + +	ret = ks_pcie_config_msi_irq(ks_pcie); +	if (ret) +		return ret; +  	dw_pcie_setup_rc(pp); -	ks_pcie_establish_link(ks_pcie); +	ks_pcie_stop_link(pci);  	ks_pcie_setup_rc_app_regs(ks_pcie); -	ks_pcie_setup_interrupts(ks_pcie);  	writew(PCI_IO_RANGE_TYPE_32 | (PCI_IO_RANGE_TYPE_32 << 8),  			pci->dbi_base + PCI_IO_BASE); @@ -766,12 +826,17 @@ static int __init ks_pcie_host_init(struct pcie_port *pp)  	if (ret < 0)  		return ret; +#ifdef CONFIG_ARM  	/*  	 * PCIe access errors that result into OCP errors are caught by ARM as  	 * "External aborts"  	 */  	hook_fault_code(17, ks_pcie_fault, SIGBUS, 0,  			"Asynchronous external abort"); +#endif + +	ks_pcie_start_link(pci); +	dw_pcie_wait_for_link(pci);  	return 0;  } @@ -780,14 +845,15 @@ static const struct dw_pcie_host_ops ks_pcie_host_ops = {  	.rd_other_conf = ks_pcie_rd_other_conf,  	.wr_other_conf = ks_pcie_wr_other_conf,  	.host_init = ks_pcie_host_init, -	.msi_set_irq = ks_pcie_msi_set_irq, -	.msi_clear_irq = ks_pcie_msi_clear_irq, -	.get_msi_addr = ks_pcie_get_msi_addr,  	.msi_host_init = ks_pcie_msi_host_init, -	.msi_irq_ack = ks_pcie_msi_irq_ack,  	.scan_bus = ks_pcie_v3_65_scan_bus,  }; +static const struct dw_pcie_host_ops ks_pcie_am654_host_ops = { +	.host_init = ks_pcie_host_init, +	.msi_host_init = ks_pcie_am654_msi_host_init, +}; +  static irqreturn_t ks_pcie_err_irq_handler(int irq, void *priv)  {  	struct keystone_pcie *ks_pcie = priv; @@ -801,41 +867,17 @@ static int __init ks_pcie_add_pcie_port(struct keystone_pcie *ks_pcie,  	struct dw_pcie *pci = ks_pcie->pci;  	struct pcie_port *pp = &pci->pp;  	struct device *dev = &pdev->dev; +	struct resource *res;  	int ret; -	ret = ks_pcie_get_irq_controller_info(ks_pcie, -					"legacy-interrupt-controller", -					&ks_pcie->num_legacy_host_irqs); -	if (ret) -		return ret; - -	if (IS_ENABLED(CONFIG_PCI_MSI)) { -		ret = ks_pcie_get_irq_controller_info(ks_pcie, -						"msi-interrupt-controller", -						&ks_pcie->num_msi_host_irqs); -		if (ret) -			return ret; -	} +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config"); +	pp->va_cfg0_base = devm_pci_remap_cfg_resource(dev, res); +	if (IS_ERR(pp->va_cfg0_base)) +		return PTR_ERR(pp->va_cfg0_base); -	/* -	 * Index 0 is the platform interrupt for error interrupt -	 * from RC.  This is optional. -	 */ -	ks_pcie->error_irq = irq_of_parse_and_map(ks_pcie->np, 0); -	if (ks_pcie->error_irq <= 0) -		dev_info(dev, "no error IRQ defined\n"); -	else { -		ret = request_irq(ks_pcie->error_irq, ks_pcie_err_irq_handler, -				  IRQF_SHARED, "pcie-error-irq", ks_pcie); -		if (ret < 0) { -			dev_err(dev, "failed to request error IRQ %d\n", -				ks_pcie->error_irq); -			return ret; -		} -	} +	pp->va_cfg1_base = pp->va_cfg0_base; -	pp->ops = &ks_pcie_host_ops; -	ret = ks_pcie_dw_host_init(ks_pcie); +	ret = dw_pcie_host_init(pp);  	if (ret) {  		dev_err(dev, "failed to initialize host\n");  		return ret; @@ -844,18 +886,139 @@ static int __init ks_pcie_add_pcie_port(struct keystone_pcie *ks_pcie,  	return 0;  } -static const struct of_device_id ks_pcie_of_match[] = { -	{ -		.type = "pci", -		.compatible = "ti,keystone-pcie", -	}, -	{ }, -}; +static u32 ks_pcie_am654_read_dbi2(struct dw_pcie *pci, void __iomem *base, +				   u32 reg, size_t size) +{ +	struct keystone_pcie *ks_pcie = to_keystone_pcie(pci); +	u32 val; + +	ks_pcie_set_dbi_mode(ks_pcie); +	dw_pcie_read(base + reg, size, &val); +	ks_pcie_clear_dbi_mode(ks_pcie); +	return val; +} + +static void ks_pcie_am654_write_dbi2(struct dw_pcie *pci, void __iomem *base, +				     u32 reg, size_t size, u32 val) +{ +	struct keystone_pcie *ks_pcie = to_keystone_pcie(pci); + +	ks_pcie_set_dbi_mode(ks_pcie); +	dw_pcie_write(base + reg, size, val); +	ks_pcie_clear_dbi_mode(ks_pcie); +}  static const struct dw_pcie_ops ks_pcie_dw_pcie_ops = { +	.start_link = ks_pcie_start_link, +	.stop_link = ks_pcie_stop_link,  	.link_up = ks_pcie_link_up, +	.read_dbi2 = ks_pcie_am654_read_dbi2, +	.write_dbi2 = ks_pcie_am654_write_dbi2, +}; + +static void ks_pcie_am654_ep_init(struct dw_pcie_ep *ep) +{ +	struct dw_pcie *pci = to_dw_pcie_from_ep(ep); +	int flags; + +	ep->page_size = AM654_WIN_SIZE; +	flags = PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_32; +	dw_pcie_writel_dbi2(pci, PCI_BASE_ADDRESS_0, APP_ADDR_SPACE_0 - 1); +	dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, flags); +} + +static void ks_pcie_am654_raise_legacy_irq(struct keystone_pcie *ks_pcie) +{ +	struct dw_pcie *pci = ks_pcie->pci; +	u8 int_pin; + +	int_pin = dw_pcie_readb_dbi(pci, PCI_INTERRUPT_PIN); +	if (int_pin == 0 || int_pin > 4) +		return; + +	ks_pcie_app_writel(ks_pcie, PCIE_LEGACY_IRQ_ENABLE_SET(int_pin), +			   INT_ENABLE); +	ks_pcie_app_writel(ks_pcie, PCIE_EP_IRQ_SET, INT_ENABLE); +	mdelay(1); +	ks_pcie_app_writel(ks_pcie, PCIE_EP_IRQ_CLR, INT_ENABLE); +	ks_pcie_app_writel(ks_pcie, PCIE_LEGACY_IRQ_ENABLE_CLR(int_pin), +			   INT_ENABLE); +} + +static int ks_pcie_am654_raise_irq(struct dw_pcie_ep *ep, u8 func_no, +				   enum pci_epc_irq_type type, +				   u16 interrupt_num) +{ +	struct dw_pcie *pci = to_dw_pcie_from_ep(ep); +	struct keystone_pcie *ks_pcie = to_keystone_pcie(pci); + +	switch (type) { +	case PCI_EPC_IRQ_LEGACY: +		ks_pcie_am654_raise_legacy_irq(ks_pcie); +		break; +	case PCI_EPC_IRQ_MSI: +		dw_pcie_ep_raise_msi_irq(ep, func_no, interrupt_num); +		break; +	default: +		dev_err(pci->dev, "UNKNOWN IRQ type\n"); +		return -EINVAL; +	} + +	return 0; +} + +static const struct pci_epc_features ks_pcie_am654_epc_features = { +	.linkup_notifier = false, +	.msi_capable = true, +	.msix_capable = false, +	.reserved_bar = 1 << BAR_0 | 1 << BAR_1, +	.bar_fixed_64bit = 1 << BAR_0, +	.bar_fixed_size[2] = SZ_1M, +	.bar_fixed_size[3] = SZ_64K, +	.bar_fixed_size[4] = 256, +	.bar_fixed_size[5] = SZ_1M, +	.align = SZ_1M,  }; +static const struct pci_epc_features* +ks_pcie_am654_get_features(struct dw_pcie_ep *ep) +{ +	return &ks_pcie_am654_epc_features; +} + +static const struct dw_pcie_ep_ops ks_pcie_am654_ep_ops = { +	.ep_init = ks_pcie_am654_ep_init, +	.raise_irq = ks_pcie_am654_raise_irq, +	.get_features = &ks_pcie_am654_get_features, +}; + +static int __init ks_pcie_add_pcie_ep(struct keystone_pcie *ks_pcie, +				      struct platform_device *pdev) +{ +	int ret; +	struct dw_pcie_ep *ep; +	struct resource *res; +	struct device *dev = &pdev->dev; +	struct dw_pcie *pci = ks_pcie->pci; + +	ep = &pci->ep; + +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space"); +	if (!res) +		return -EINVAL; + +	ep->phys_base = res->start; +	ep->addr_size = resource_size(res); + +	ret = dw_pcie_ep_init(ep); +	if (ret) { +		dev_err(dev, "failed to initialize endpoint\n"); +		return ret; +	} + +	return 0; +} +  static void ks_pcie_disable_phy(struct keystone_pcie *ks_pcie)  {  	int num_lanes = ks_pcie->num_lanes; @@ -873,6 +1036,10 @@ static int ks_pcie_enable_phy(struct keystone_pcie *ks_pcie)  	int num_lanes = ks_pcie->num_lanes;  	for (i = 0; i < num_lanes; i++) { +		ret = phy_reset(ks_pcie->phy[i]); +		if (ret < 0) +			goto err_phy; +  		ret = phy_init(ks_pcie->phy[i]);  		if (ret < 0)  			goto err_phy; @@ -895,20 +1062,161 @@ err_phy:  	return ret;  } +static int ks_pcie_set_mode(struct device *dev) +{ +	struct device_node *np = dev->of_node; +	struct regmap *syscon; +	u32 val; +	u32 mask; +	int ret = 0; + +	syscon = syscon_regmap_lookup_by_phandle(np, "ti,syscon-pcie-mode"); +	if (IS_ERR(syscon)) +		return 0; + +	mask = KS_PCIE_DEV_TYPE_MASK | KS_PCIE_SYSCLOCKOUTEN; +	val = KS_PCIE_DEV_TYPE(RC) | KS_PCIE_SYSCLOCKOUTEN; + +	ret = regmap_update_bits(syscon, 0, mask, val); +	if (ret) { +		dev_err(dev, "failed to set pcie mode\n"); +		return ret; +	} + +	return 0; +} + +static int ks_pcie_am654_set_mode(struct device *dev, +				  enum dw_pcie_device_mode mode) +{ +	struct device_node *np = dev->of_node; +	struct regmap *syscon; +	u32 val; +	u32 mask; +	int ret = 0; + +	syscon = syscon_regmap_lookup_by_phandle(np, "ti,syscon-pcie-mode"); +	if (IS_ERR(syscon)) +		return 0; + +	mask = AM654_PCIE_DEV_TYPE_MASK; + +	switch (mode) { +	case DW_PCIE_RC_TYPE: +		val = RC; +		break; +	case DW_PCIE_EP_TYPE: +		val = EP; +		break; +	default: +		dev_err(dev, "INVALID device type %d\n", mode); +		return -EINVAL; +	} + +	ret = regmap_update_bits(syscon, 0, mask, val); +	if (ret) { +		dev_err(dev, "failed to set pcie mode\n"); +		return ret; +	} + +	return 0; +} + +static void ks_pcie_set_link_speed(struct dw_pcie *pci, int link_speed) +{ +	u32 val; + +	dw_pcie_dbi_ro_wr_en(pci); + +	val = dw_pcie_readl_dbi(pci, EXP_CAP_ID_OFFSET + PCI_EXP_LNKCAP); +	if ((val & PCI_EXP_LNKCAP_SLS) != link_speed) { +		val &= ~((u32)PCI_EXP_LNKCAP_SLS); +		val |= link_speed; +		dw_pcie_writel_dbi(pci, EXP_CAP_ID_OFFSET + PCI_EXP_LNKCAP, +				   val); +	} + +	val = dw_pcie_readl_dbi(pci, EXP_CAP_ID_OFFSET + PCI_EXP_LNKCTL2); +	if ((val & PCI_EXP_LNKCAP_SLS) != link_speed) { +		val &= ~((u32)PCI_EXP_LNKCAP_SLS); +		val |= link_speed; +		dw_pcie_writel_dbi(pci, EXP_CAP_ID_OFFSET + PCI_EXP_LNKCTL2, +				   val); +	} + +	dw_pcie_dbi_ro_wr_dis(pci); +} + +static const struct ks_pcie_of_data ks_pcie_rc_of_data = { +	.host_ops = &ks_pcie_host_ops, +	.version = 0x365A, +}; + +static const struct ks_pcie_of_data ks_pcie_am654_rc_of_data = { +	.host_ops = &ks_pcie_am654_host_ops, +	.mode = DW_PCIE_RC_TYPE, +	.version = 0x490A, +}; + +static const struct ks_pcie_of_data ks_pcie_am654_ep_of_data = { +	.ep_ops = &ks_pcie_am654_ep_ops, +	.mode = DW_PCIE_EP_TYPE, +	.version = 0x490A, +}; + +static const struct of_device_id ks_pcie_of_match[] = { +	{ +		.type = "pci", +		.data = &ks_pcie_rc_of_data, +		.compatible = "ti,keystone-pcie", +	}, +	{ +		.data = &ks_pcie_am654_rc_of_data, +		.compatible = "ti,am654-pcie-rc", +	}, +	{ +		.data = &ks_pcie_am654_ep_of_data, +		.compatible = "ti,am654-pcie-ep", +	}, +	{ }, +}; +  static int __init ks_pcie_probe(struct platform_device *pdev)  { +	const struct dw_pcie_host_ops *host_ops; +	const struct dw_pcie_ep_ops *ep_ops;  	struct device *dev = &pdev->dev;  	struct device_node *np = dev->of_node; +	const struct ks_pcie_of_data *data; +	const struct of_device_id *match; +	enum dw_pcie_device_mode mode;  	struct dw_pcie *pci;  	struct keystone_pcie *ks_pcie;  	struct device_link **link; +	struct gpio_desc *gpiod; +	void __iomem *atu_base; +	struct resource *res; +	unsigned int version; +	void __iomem *base;  	u32 num_viewport;  	struct phy **phy; +	int link_speed;  	u32 num_lanes;  	char name[10];  	int ret; +	int irq;  	int i; +	match = of_match_device(of_match_ptr(ks_pcie_of_match), dev); +	data = (struct ks_pcie_of_data *)match->data; +	if (!data) +		return -EINVAL; + +	version = data->version; +	host_ops = data->host_ops; +	ep_ops = data->ep_ops; +	mode = data->mode; +  	ks_pcie = devm_kzalloc(dev, sizeof(*ks_pcie), GFP_KERNEL);  	if (!ks_pcie)  		return -ENOMEM; @@ -917,12 +1225,38 @@ static int __init ks_pcie_probe(struct platform_device *pdev)  	if (!pci)  		return -ENOMEM; +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "app"); +	ks_pcie->va_app_base = devm_ioremap_resource(dev, res); +	if (IS_ERR(ks_pcie->va_app_base)) +		return PTR_ERR(ks_pcie->va_app_base); + +	ks_pcie->app = *res; + +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbics"); +	base = devm_pci_remap_cfg_resource(dev, res); +	if (IS_ERR(base)) +		return PTR_ERR(base); + +	if (of_device_is_compatible(np, "ti,am654-pcie-rc")) +		ks_pcie->is_am6 = true; + +	pci->dbi_base = base; +	pci->dbi_base2 = base;  	pci->dev = dev;  	pci->ops = &ks_pcie_dw_pcie_ops; +	pci->version = version; + +	irq = platform_get_irq(pdev, 0); +	if (irq < 0) { +		dev_err(dev, "missing IRQ resource: %d\n", irq); +		return irq; +	} -	ret = of_property_read_u32(np, "num-viewport", &num_viewport); +	ret = request_irq(irq, ks_pcie_err_irq_handler, IRQF_SHARED, +			  "ks-pcie-error-irq", ks_pcie);  	if (ret < 0) { -		dev_err(dev, "unable to read *num-viewport* property\n"); +		dev_err(dev, "failed to request error IRQ %d\n", +			irq);  		return ret;  	} @@ -960,9 +1294,17 @@ static int __init ks_pcie_probe(struct platform_device *pdev)  	ks_pcie->pci = pci;  	ks_pcie->link = link;  	ks_pcie->num_lanes = num_lanes; -	ks_pcie->num_viewport = num_viewport;  	ks_pcie->phy = phy; +	gpiod = devm_gpiod_get_optional(dev, "reset", +					GPIOD_OUT_LOW); +	if (IS_ERR(gpiod)) { +		ret = PTR_ERR(gpiod); +		if (ret != -EPROBE_DEFER) +			dev_err(dev, "Failed to get reset GPIO\n"); +		goto err_link; +	} +  	ret = ks_pcie_enable_phy(ks_pcie);  	if (ret) {  		dev_err(dev, "failed to enable phy\n"); @@ -977,9 +1319,79 @@ static int __init ks_pcie_probe(struct platform_device *pdev)  		goto err_get_sync;  	} -	ret = ks_pcie_add_pcie_port(ks_pcie, pdev); -	if (ret < 0) -		goto err_get_sync; +	if (pci->version >= 0x480A) { +		res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "atu"); +		atu_base = devm_ioremap_resource(dev, res); +		if (IS_ERR(atu_base)) { +			ret = PTR_ERR(atu_base); +			goto err_get_sync; +		} + +		pci->atu_base = atu_base; + +		ret = ks_pcie_am654_set_mode(dev, mode); +		if (ret < 0) +			goto err_get_sync; +	} else { +		ret = ks_pcie_set_mode(dev); +		if (ret < 0) +			goto err_get_sync; +	} + +	link_speed = of_pci_get_max_link_speed(np); +	if (link_speed < 0) +		link_speed = 2; + +	ks_pcie_set_link_speed(pci, link_speed); + +	switch (mode) { +	case DW_PCIE_RC_TYPE: +		if (!IS_ENABLED(CONFIG_PCI_KEYSTONE_HOST)) { +			ret = -ENODEV; +			goto err_get_sync; +		} + +		ret = of_property_read_u32(np, "num-viewport", &num_viewport); +		if (ret < 0) { +			dev_err(dev, "unable to read *num-viewport* property\n"); +			return ret; +		} + +		/* +		 * "Power Sequencing and Reset Signal Timings" table in +		 * PCI EXPRESS CARD ELECTROMECHANICAL SPECIFICATION, REV. 2.0 +		 * indicates PERST# should be deasserted after minimum of 100us +		 * once REFCLK is stable. The REFCLK to the connector in RC +		 * mode is selected while enabling the PHY. So deassert PERST# +		 * after 100 us. +		 */ +		if (gpiod) { +			usleep_range(100, 200); +			gpiod_set_value_cansleep(gpiod, 1); +		} + +		ks_pcie->num_viewport = num_viewport; +		pci->pp.ops = host_ops; +		ret = ks_pcie_add_pcie_port(ks_pcie, pdev); +		if (ret < 0) +			goto err_get_sync; +		break; +	case DW_PCIE_EP_TYPE: +		if (!IS_ENABLED(CONFIG_PCI_KEYSTONE_EP)) { +			ret = -ENODEV; +			goto err_get_sync; +		} + +		pci->ep.ops = ep_ops; +		ret = ks_pcie_add_pcie_ep(ks_pcie, pdev); +		if (ret < 0) +			goto err_get_sync; +		break; +	default: +		dev_err(dev, "INVALID device type %d\n", mode); +	} + +	ks_pcie_enable_error_irq(ks_pcie);  	return 0; diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c b/drivers/pci/controller/dwc/pci-layerscape-ep.c index a42c9c3ae1cc..be61d96cc95e 100644 --- a/drivers/pci/controller/dwc/pci-layerscape-ep.c +++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c @@ -79,7 +79,7 @@ static int ls_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,  	}  } -static struct dw_pcie_ep_ops pcie_ep_ops = { +static const struct dw_pcie_ep_ops pcie_ep_ops = {  	.ep_init = ls_pcie_ep_init,  	.raise_irq = ls_pcie_ep_raise_irq,  	.get_features = ls_pcie_ep_get_features, diff --git a/drivers/pci/controller/dwc/pci-layerscape.c b/drivers/pci/controller/dwc/pci-layerscape.c index ce45bde29bf8..3a5fa26d5e56 100644 --- a/drivers/pci/controller/dwc/pci-layerscape.c +++ b/drivers/pci/controller/dwc/pci-layerscape.c @@ -201,6 +201,7 @@ static int ls_pcie_msi_host_init(struct pcie_port *pp)  		return -EINVAL;  	} +	of_node_put(msi_node);  	return 0;  } diff --git a/drivers/pci/controller/dwc/pcie-al.c b/drivers/pci/controller/dwc/pcie-al.c new file mode 100644 index 000000000000..3ab58f0584a8 --- /dev/null +++ b/drivers/pci/controller/dwc/pcie-al.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * PCIe host controller driver for Amazon's Annapurna Labs IP (used in chips + * such as Graviton and Alpine) + * + * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Author: Jonathan Chocron <[email protected]> + */ + +#include <linux/pci.h> +#include <linux/pci-ecam.h> +#include <linux/pci-acpi.h> +#include "../../pci.h" + +#if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS) + +struct al_pcie_acpi  { +	void __iomem *dbi_base; +}; + +static void __iomem *al_pcie_map_bus(struct pci_bus *bus, unsigned int devfn, +				     int where) +{ +	struct pci_config_window *cfg = bus->sysdata; +	struct al_pcie_acpi *pcie = cfg->priv; +	void __iomem *dbi_base = pcie->dbi_base; + +	if (bus->number == cfg->busr.start) { +		/* +		 * The DW PCIe core doesn't filter out transactions to other +		 * devices/functions on the root bus num, so we do this here. +		 */ +		if (PCI_SLOT(devfn) > 0) +			return NULL; +		else +			return dbi_base + where; +	} + +	return pci_ecam_map_bus(bus, devfn, where); +} + +static int al_pcie_init(struct pci_config_window *cfg) +{ +	struct device *dev = cfg->parent; +	struct acpi_device *adev = to_acpi_device(dev); +	struct acpi_pci_root *root = acpi_driver_data(adev); +	struct al_pcie_acpi *al_pcie; +	struct resource *res; +	int ret; + +	al_pcie = devm_kzalloc(dev, sizeof(*al_pcie), GFP_KERNEL); +	if (!al_pcie) +		return -ENOMEM; + +	res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL); +	if (!res) +		return -ENOMEM; + +	ret = acpi_get_rc_resources(dev, "AMZN0001", root->segment, res); +	if (ret) { +		dev_err(dev, "can't get rc dbi base address for SEG %d\n", +			root->segment); +		return ret; +	} + +	dev_dbg(dev, "Root port dbi res: %pR\n", res); + +	al_pcie->dbi_base = devm_pci_remap_cfg_resource(dev, res); +	if (IS_ERR(al_pcie->dbi_base)) { +		long err = PTR_ERR(al_pcie->dbi_base); + +		dev_err(dev, "couldn't remap dbi base %pR (err:%ld)\n", +			res, err); +		return err; +	} + +	cfg->priv = al_pcie; + +	return 0; +} + +struct pci_ecam_ops al_pcie_ops = { +	.bus_shift    = 20, +	.init         =  al_pcie_init, +	.pci_ops      = { +		.map_bus    = al_pcie_map_bus, +		.read       = pci_generic_config_read, +		.write      = pci_generic_config_write, +	} +}; + +#endif /* defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS) */ diff --git a/drivers/pci/controller/dwc/pcie-artpec6.c b/drivers/pci/controller/dwc/pcie-artpec6.c index dba83abfe764..d00252bd8fae 100644 --- a/drivers/pci/controller/dwc/pcie-artpec6.c +++ b/drivers/pci/controller/dwc/pcie-artpec6.c @@ -444,7 +444,7 @@ static int artpec6_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no,  	return 0;  } -static struct dw_pcie_ep_ops pcie_ep_ops = { +static const struct dw_pcie_ep_ops pcie_ep_ops = {  	.ep_init = artpec6_pcie_ep_init,  	.raise_irq = artpec6_pcie_raise_irq,  }; diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c index 24f5a775ad34..2bf5a35c0570 100644 --- a/drivers/pci/controller/dwc/pcie-designware-ep.c +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c @@ -46,16 +46,19 @@ static u8 __dw_pcie_ep_find_next_cap(struct dw_pcie *pci, u8 cap_ptr,  	u8 cap_id, next_cap_ptr;  	u16 reg; +	if (!cap_ptr) +		return 0; +  	reg = dw_pcie_readw_dbi(pci, cap_ptr); -	next_cap_ptr = (reg & 0xff00) >> 8;  	cap_id = (reg & 0x00ff); -	if (!next_cap_ptr || cap_id > PCI_CAP_ID_MAX) +	if (cap_id > PCI_CAP_ID_MAX)  		return 0;  	if (cap_id == cap)  		return cap_ptr; +	next_cap_ptr = (reg & 0xff00) >> 8;  	return __dw_pcie_ep_find_next_cap(pci, next_cap_ptr, cap);  } @@ -67,9 +70,6 @@ static u8 dw_pcie_ep_find_capability(struct dw_pcie *pci, u8 cap)  	reg = dw_pcie_readw_dbi(pci, PCI_CAPABILITY_LIST);  	next_cap_ptr = (reg & 0x00ff); -	if (!next_cap_ptr) -		return 0; -  	return __dw_pcie_ep_find_next_cap(pci, next_cap_ptr, cap);  } @@ -397,6 +397,7 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,  {  	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);  	struct pci_epc *epc = ep->epc; +	unsigned int aligned_offset;  	u16 msg_ctrl, msg_data;  	u32 msg_addr_lower, msg_addr_upper, reg;  	u64 msg_addr; @@ -422,13 +423,15 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,  		reg = ep->msi_cap + PCI_MSI_DATA_32;  		msg_data = dw_pcie_readw_dbi(pci, reg);  	} -	msg_addr = ((u64) msg_addr_upper) << 32 | msg_addr_lower; +	aligned_offset = msg_addr_lower & (epc->mem->page_size - 1); +	msg_addr = ((u64)msg_addr_upper) << 32 | +			(msg_addr_lower & ~aligned_offset);  	ret = dw_pcie_ep_map_addr(epc, func_no, ep->msi_mem_phys, msg_addr,  				  epc->mem->page_size);  	if (ret)  		return ret; -	writel(msg_data | (interrupt_num - 1), ep->msi_mem); +	writel(msg_data | (interrupt_num - 1), ep->msi_mem + aligned_offset);  	dw_pcie_ep_unmap_addr(epc, func_no, ep->msi_mem_phys); @@ -504,10 +507,32 @@ void dw_pcie_ep_exit(struct dw_pcie_ep *ep)  	pci_epc_mem_exit(epc);  } +static unsigned int dw_pcie_ep_find_ext_capability(struct dw_pcie *pci, int cap) +{ +	u32 header; +	int pos = PCI_CFG_SPACE_SIZE; + +	while (pos) { +		header = dw_pcie_readl_dbi(pci, pos); +		if (PCI_EXT_CAP_ID(header) == cap) +			return pos; + +		pos = PCI_EXT_CAP_NEXT(header); +		if (!pos) +			break; +	} + +	return 0; +} +  int dw_pcie_ep_init(struct dw_pcie_ep *ep)  { +	int i;  	int ret; +	u32 reg;  	void *addr; +	unsigned int nbars; +	unsigned int offset;  	struct pci_epc *epc;  	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);  	struct device *dev = pci->dev; @@ -517,10 +542,6 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)  		dev_err(dev, "dbi_base/dbi_base2 is not populated\n");  		return -EINVAL;  	} -	if (pci->iatu_unroll_enabled && !pci->atu_base) { -		dev_err(dev, "atu_base is not populated\n"); -		return -EINVAL; -	}  	ret = of_property_read_u32(np, "num-ib-windows", &ep->num_ib_windows);  	if (ret < 0) { @@ -595,6 +616,18 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)  	ep->msix_cap = dw_pcie_ep_find_capability(pci, PCI_CAP_ID_MSIX); +	offset = dw_pcie_ep_find_ext_capability(pci, PCI_EXT_CAP_ID_REBAR); +	if (offset) { +		reg = dw_pcie_readl_dbi(pci, offset + PCI_REBAR_CTRL); +		nbars = (reg & PCI_REBAR_CTRL_NBAR_MASK) >> +			PCI_REBAR_CTRL_NBAR_SHIFT; + +		dw_pcie_dbi_ro_wr_en(pci); +		for (i = 0; i < nbars; i++, offset += PCI_REBAR_CTRL) +			dw_pcie_writel_dbi(pci, offset + PCI_REBAR_CAP, 0x0); +		dw_pcie_dbi_ro_wr_dis(pci); +	} +  	dw_pcie_setup(pci);  	return 0; diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c index 25087d3c9a82..77db32529319 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -126,18 +126,12 @@ static void dw_pci_setup_msi_msg(struct irq_data *d, struct msi_msg *msg)  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);  	u64 msi_target; -	if (pp->ops->get_msi_addr) -		msi_target = pp->ops->get_msi_addr(pp); -	else -		msi_target = (u64)pp->msi_data; +	msi_target = (u64)pp->msi_data;  	msg->address_lo = lower_32_bits(msi_target);  	msg->address_hi = upper_32_bits(msi_target); -	if (pp->ops->get_msi_data) -		msg->data = pp->ops->get_msi_data(pp, d->hwirq); -	else -		msg->data = d->hwirq; +	msg->data = d->hwirq;  	dev_dbg(pci->dev, "msi#%d address_hi %#x address_lo %#x\n",  		(int)d->hwirq, msg->address_hi, msg->address_lo); @@ -157,17 +151,13 @@ static void dw_pci_bottom_mask(struct irq_data *d)  	raw_spin_lock_irqsave(&pp->lock, flags); -	if (pp->ops->msi_clear_irq) { -		pp->ops->msi_clear_irq(pp, d->hwirq); -	} else { -		ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL; -		res = ctrl * MSI_REG_CTRL_BLOCK_SIZE; -		bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL; +	ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL; +	res = ctrl * MSI_REG_CTRL_BLOCK_SIZE; +	bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL; -		pp->irq_mask[ctrl] |= BIT(bit); -		dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_MASK + res, 4, -				    pp->irq_mask[ctrl]); -	} +	pp->irq_mask[ctrl] |= BIT(bit); +	dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_MASK + res, 4, +			    pp->irq_mask[ctrl]);  	raw_spin_unlock_irqrestore(&pp->lock, flags);  } @@ -180,17 +170,13 @@ static void dw_pci_bottom_unmask(struct irq_data *d)  	raw_spin_lock_irqsave(&pp->lock, flags); -	if (pp->ops->msi_set_irq) { -		pp->ops->msi_set_irq(pp, d->hwirq); -	} else { -		ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL; -		res = ctrl * MSI_REG_CTRL_BLOCK_SIZE; -		bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL; +	ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL; +	res = ctrl * MSI_REG_CTRL_BLOCK_SIZE; +	bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL; -		pp->irq_mask[ctrl] &= ~BIT(bit); -		dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_MASK + res, 4, -				    pp->irq_mask[ctrl]); -	} +	pp->irq_mask[ctrl] &= ~BIT(bit); +	dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_MASK + res, 4, +			    pp->irq_mask[ctrl]);  	raw_spin_unlock_irqrestore(&pp->lock, flags);  } @@ -199,20 +185,12 @@ static void dw_pci_bottom_ack(struct irq_data *d)  {  	struct pcie_port *pp  = irq_data_get_irq_chip_data(d);  	unsigned int res, bit, ctrl; -	unsigned long flags;  	ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL;  	res = ctrl * MSI_REG_CTRL_BLOCK_SIZE;  	bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL; -	raw_spin_lock_irqsave(&pp->lock, flags); -  	dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_STATUS + res, 4, BIT(bit)); - -	if (pp->ops->msi_irq_ack) -		pp->ops->msi_irq_ack(d->hwirq, pp); - -	raw_spin_unlock_irqrestore(&pp->lock, flags);  }  static struct irq_chip dw_pci_msi_bottom_irq_chip = { @@ -245,7 +223,7 @@ static int dw_pcie_irq_domain_alloc(struct irq_domain *domain,  	for (i = 0; i < nr_irqs; i++)  		irq_domain_set_info(domain, virq + i, bit + i, -				    &dw_pci_msi_bottom_irq_chip, +				    pp->msi_irq_chip,  				    pp, handle_edge_irq,  				    NULL, NULL); @@ -298,25 +276,31 @@ int dw_pcie_allocate_domains(struct pcie_port *pp)  void dw_pcie_free_msi(struct pcie_port *pp)  { -	irq_set_chained_handler(pp->msi_irq, NULL); -	irq_set_handler_data(pp->msi_irq, NULL); +	if (pp->msi_irq) { +		irq_set_chained_handler(pp->msi_irq, NULL); +		irq_set_handler_data(pp->msi_irq, NULL); +	}  	irq_domain_remove(pp->msi_domain);  	irq_domain_remove(pp->irq_domain); + +	if (pp->msi_page) +		__free_page(pp->msi_page);  }  void dw_pcie_msi_init(struct pcie_port *pp)  {  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);  	struct device *dev = pci->dev; -	struct page *page;  	u64 msi_target; -	page = alloc_page(GFP_KERNEL); -	pp->msi_data = dma_map_page(dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE); +	pp->msi_page = alloc_page(GFP_KERNEL); +	pp->msi_data = dma_map_page(dev, pp->msi_page, 0, PAGE_SIZE, +				    DMA_FROM_DEVICE);  	if (dma_mapping_error(dev, pp->msi_data)) {  		dev_err(dev, "Failed to map MSI data\n"); -		__free_page(page); +		__free_page(pp->msi_page); +		pp->msi_page = NULL;  		return;  	}  	msi_target = (u64)pp->msi_data; @@ -335,7 +319,7 @@ int dw_pcie_host_init(struct pcie_port *pp)  	struct device_node *np = dev->of_node;  	struct platform_device *pdev = to_platform_device(dev);  	struct resource_entry *win, *tmp; -	struct pci_bus *bus, *child; +	struct pci_bus *child;  	struct pci_host_bridge *bridge;  	struct resource *cfg_res;  	int ret; @@ -352,7 +336,7 @@ int dw_pcie_host_init(struct pcie_port *pp)  		dev_err(dev, "Missing *config* reg space\n");  	} -	bridge = pci_alloc_host_bridge(0); +	bridge = devm_pci_alloc_host_bridge(dev, 0);  	if (!bridge)  		return -ENOMEM; @@ -363,7 +347,7 @@ int dw_pcie_host_init(struct pcie_port *pp)  	ret = devm_request_pci_bus_resources(dev, &bridge->windows);  	if (ret) -		goto error; +		return ret;  	/* Get the I/O and memory ranges from DT */  	resource_list_for_each_entry_safe(win, tmp, &bridge->windows) { @@ -407,8 +391,7 @@ int dw_pcie_host_init(struct pcie_port *pp)  						resource_size(pp->cfg));  		if (!pci->dbi_base) {  			dev_err(dev, "Error with ioremap\n"); -			ret = -ENOMEM; -			goto error; +			return -ENOMEM;  		}  	} @@ -419,8 +402,7 @@ int dw_pcie_host_init(struct pcie_port *pp)  					pp->cfg0_base, pp->cfg0_size);  		if (!pp->va_cfg0_base) {  			dev_err(dev, "Error with ioremap in function\n"); -			ret = -ENOMEM; -			goto error; +			return -ENOMEM;  		}  	} @@ -430,8 +412,7 @@ int dw_pcie_host_init(struct pcie_port *pp)  						pp->cfg1_size);  		if (!pp->va_cfg1_base) {  			dev_err(dev, "Error with ioremap\n"); -			ret = -ENOMEM; -			goto error; +			return -ENOMEM;  		}  	} @@ -439,7 +420,7 @@ int dw_pcie_host_init(struct pcie_port *pp)  	if (ret)  		pci->num_viewport = 2; -	if (IS_ENABLED(CONFIG_PCI_MSI) && pci_msi_enabled()) { +	if (pci_msi_enabled()) {  		/*  		 * If a specific SoC driver needs to change the  		 * default number of vectors, it needs to implement @@ -454,14 +435,16 @@ int dw_pcie_host_init(struct pcie_port *pp)  			    pp->num_vectors == 0) {  				dev_err(dev,  					"Invalid number of vectors\n"); -				goto error; +				return -EINVAL;  			}  		}  		if (!pp->ops->msi_host_init) { +			pp->msi_irq_chip = &dw_pci_msi_bottom_irq_chip; +  			ret = dw_pcie_allocate_domains(pp);  			if (ret) -				goto error; +				return ret;  			if (pp->msi_irq)  				irq_set_chained_handler_and_data(pp->msi_irq, @@ -470,14 +453,14 @@ int dw_pcie_host_init(struct pcie_port *pp)  		} else {  			ret = pp->ops->msi_host_init(pp);  			if (ret < 0) -				goto error; +				return ret;  		}  	}  	if (pp->ops->host_init) {  		ret = pp->ops->host_init(pp);  		if (ret) -			goto error; +			goto err_free_msi;  	}  	pp->root_bus_nr = pp->busn->start; @@ -491,24 +474,25 @@ int dw_pcie_host_init(struct pcie_port *pp)  	ret = pci_scan_root_bus_bridge(bridge);  	if (ret) -		goto error; +		goto err_free_msi; -	bus = bridge->bus; +	pp->root_bus = bridge->bus;  	if (pp->ops->scan_bus)  		pp->ops->scan_bus(pp); -	pci_bus_size_bridges(bus); -	pci_bus_assign_resources(bus); +	pci_bus_size_bridges(pp->root_bus); +	pci_bus_assign_resources(pp->root_bus); -	list_for_each_entry(child, &bus->children, node) +	list_for_each_entry(child, &pp->root_bus->children, node)  		pcie_bus_configure_settings(child); -	pci_bus_add_devices(bus); +	pci_bus_add_devices(pp->root_bus);  	return 0; -error: -	pci_free_host_bridge(bridge); +err_free_msi: +	if (pci_msi_enabled() && !pp->ops->msi_host_init) +		dw_pcie_free_msi(pp);  	return ret;  } @@ -628,17 +612,6 @@ static struct pci_ops dw_pcie_ops = {  	.write = dw_pcie_wr_conf,  }; -static u8 dw_pcie_iatu_unroll_enabled(struct dw_pcie *pci) -{ -	u32 val; - -	val = dw_pcie_readl_dbi(pci, PCIE_ATU_VIEWPORT); -	if (val == 0xffffffff) -		return 1; - -	return 0; -} -  void dw_pcie_setup_rc(struct pcie_port *pp)  {  	u32 val, ctrl, num_ctrls; @@ -646,17 +619,19 @@ void dw_pcie_setup_rc(struct pcie_port *pp)  	dw_pcie_setup(pci); -	num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL; - -	/* Initialize IRQ Status array */ -	for (ctrl = 0; ctrl < num_ctrls; ctrl++) { -		pp->irq_mask[ctrl] = ~0; -		dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_MASK + -					(ctrl * MSI_REG_CTRL_BLOCK_SIZE), -				    4, pp->irq_mask[ctrl]); -		dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + -					(ctrl * MSI_REG_CTRL_BLOCK_SIZE), -				    4, ~0); +	if (!pp->ops->msi_host_init) { +		num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL; + +		/* Initialize IRQ Status array */ +		for (ctrl = 0; ctrl < num_ctrls; ctrl++) { +			pp->irq_mask[ctrl] = ~0; +			dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_MASK + +					    (ctrl * MSI_REG_CTRL_BLOCK_SIZE), +					    4, pp->irq_mask[ctrl]); +			dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + +					    (ctrl * MSI_REG_CTRL_BLOCK_SIZE), +					    4, ~0); +		}  	}  	/* Setup RC BARs */ @@ -690,14 +665,6 @@ void dw_pcie_setup_rc(struct pcie_port *pp)  	 * we should not program the ATU here.  	 */  	if (!pp->ops->rd_other_conf) { -		/* Get iATU unroll support */ -		pci->iatu_unroll_enabled = dw_pcie_iatu_unroll_enabled(pci); -		dev_dbg(pci->dev, "iATU unroll: %s\n", -			pci->iatu_unroll_enabled ? "enabled" : "disabled"); - -		if (pci->iatu_unroll_enabled && !pci->atu_base) -			pci->atu_base = pci->dbi_base + DEFAULT_DBI_ATU_OFFSET; -  		dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX0,  					  PCIE_ATU_TYPE_MEM, pp->mem_base,  					  pp->mem_bus_addr, pp->mem_size); diff --git a/drivers/pci/controller/dwc/pcie-designware-plat.c b/drivers/pci/controller/dwc/pcie-designware-plat.c index 932dbd0b34b6..b58fdcbc664b 100644 --- a/drivers/pci/controller/dwc/pcie-designware-plat.c +++ b/drivers/pci/controller/dwc/pcie-designware-plat.c @@ -106,7 +106,7 @@ dw_plat_pcie_get_features(struct dw_pcie_ep *ep)  	return &dw_plat_pcie_epc_features;  } -static struct dw_pcie_ep_ops pcie_ep_ops = { +static const struct dw_pcie_ep_ops pcie_ep_ops = {  	.ep_init = dw_plat_pcie_ep_init,  	.raise_irq = dw_plat_pcie_ep_raise_irq,  	.get_features = dw_plat_pcie_get_features, diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c index 31f6331ca46f..9d7c51c32b3b 100644 --- a/drivers/pci/controller/dwc/pcie-designware.c +++ b/drivers/pci/controller/dwc/pcie-designware.c @@ -14,12 +14,6 @@  #include "pcie-designware.h" -/* PCIe Port Logic registers */ -#define PLR_OFFSET			0x700 -#define PCIE_PHY_DEBUG_R1		(PLR_OFFSET + 0x2c) -#define PCIE_PHY_DEBUG_R1_LINK_UP	(0x1 << 4) -#define PCIE_PHY_DEBUG_R1_LINK_IN_TRAINING	(0x1 << 29) -  int dw_pcie_read(void __iomem *addr, int size, u32 *val)  {  	if (!IS_ALIGNED((uintptr_t)addr, size)) { @@ -89,6 +83,37 @@ void __dw_pcie_write_dbi(struct dw_pcie *pci, void __iomem *base, u32 reg,  		dev_err(pci->dev, "Write DBI address failed\n");  } +u32 __dw_pcie_read_dbi2(struct dw_pcie *pci, void __iomem *base, u32 reg, +			size_t size) +{ +	int ret; +	u32 val; + +	if (pci->ops->read_dbi2) +		return pci->ops->read_dbi2(pci, base, reg, size); + +	ret = dw_pcie_read(base + reg, size, &val); +	if (ret) +		dev_err(pci->dev, "read DBI address failed\n"); + +	return val; +} + +void __dw_pcie_write_dbi2(struct dw_pcie *pci, void __iomem *base, u32 reg, +			  size_t size, u32 val) +{ +	int ret; + +	if (pci->ops->write_dbi2) { +		pci->ops->write_dbi2(pci, base, reg, size, val); +		return; +	} + +	ret = dw_pcie_write(base + reg, size, val); +	if (ret) +		dev_err(pci->dev, "write DBI address failed\n"); +} +  static u32 dw_pcie_readl_ob_unroll(struct dw_pcie *pci, u32 index, u32 reg)  {  	u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index); @@ -334,9 +359,20 @@ int dw_pcie_link_up(struct dw_pcie *pci)  	if (pci->ops->link_up)  		return pci->ops->link_up(pci); -	val = readl(pci->dbi_base + PCIE_PHY_DEBUG_R1); -	return ((val & PCIE_PHY_DEBUG_R1_LINK_UP) && -		(!(val & PCIE_PHY_DEBUG_R1_LINK_IN_TRAINING))); +	val = readl(pci->dbi_base + PCIE_PORT_DEBUG1); +	return ((val & PCIE_PORT_DEBUG1_LINK_UP) && +		(!(val & PCIE_PORT_DEBUG1_LINK_IN_TRAINING))); +} + +static u8 dw_pcie_iatu_unroll_enabled(struct dw_pcie *pci) +{ +	u32 val; + +	val = dw_pcie_readl_dbi(pci, PCIE_ATU_VIEWPORT); +	if (val == 0xffffffff) +		return 1; + +	return 0;  }  void dw_pcie_setup(struct dw_pcie *pci) @@ -347,6 +383,16 @@ void dw_pcie_setup(struct dw_pcie *pci)  	struct device *dev = pci->dev;  	struct device_node *np = dev->of_node; +	if (pci->version >= 0x480A || (!pci->version && +				       dw_pcie_iatu_unroll_enabled(pci))) { +		pci->iatu_unroll_enabled = true; +		if (!pci->atu_base) +			pci->atu_base = pci->dbi_base + DEFAULT_DBI_ATU_OFFSET; +	} +	dev_dbg(pci->dev, "iATU unroll: %s\n", pci->iatu_unroll_enabled ? +		"enabled" : "disabled"); + +  	ret = of_property_read_u32(np, "num-lanes", &lanes);  	if (ret)  		lanes = 0; diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index 377f4c0b52da..b8993f2b78df 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -41,6 +41,9 @@  #define PCIE_PORT_DEBUG0		0x728  #define PORT_LOGIC_LTSSM_STATE_MASK	0x1f  #define PORT_LOGIC_LTSSM_STATE_L0	0x11 +#define PCIE_PORT_DEBUG1		0x72C +#define PCIE_PORT_DEBUG1_LINK_UP		BIT(4) +#define PCIE_PORT_DEBUG1_LINK_IN_TRAINING	BIT(29)  #define PCIE_LINK_WIDTH_SPEED_CONTROL	0x80C  #define PORT_LOGIC_SPEED_CHANGE		BIT(17) @@ -145,14 +148,9 @@ struct dw_pcie_host_ops {  	int (*wr_other_conf)(struct pcie_port *pp, struct pci_bus *bus,  			     unsigned int devfn, int where, int size, u32 val);  	int (*host_init)(struct pcie_port *pp); -	void (*msi_set_irq)(struct pcie_port *pp, int irq); -	void (*msi_clear_irq)(struct pcie_port *pp, int irq); -	phys_addr_t (*get_msi_addr)(struct pcie_port *pp); -	u32 (*get_msi_data)(struct pcie_port *pp, int pos);  	void (*scan_bus)(struct pcie_port *pp);  	void (*set_num_vectors)(struct pcie_port *pp);  	int (*msi_host_init)(struct pcie_port *pp); -	void (*msi_irq_ack)(int irq, struct pcie_port *pp);  };  struct pcie_port { @@ -179,8 +177,11 @@ struct pcie_port {  	struct irq_domain	*irq_domain;  	struct irq_domain	*msi_domain;  	dma_addr_t		msi_data; +	struct page		*msi_page; +	struct irq_chip		*msi_irq_chip;  	u32			num_vectors;  	u32			irq_mask[MAX_MSI_CTRLS]; +	struct pci_bus		*root_bus;  	raw_spinlock_t		lock;  	DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS);  }; @@ -200,7 +201,7 @@ struct dw_pcie_ep_ops {  struct dw_pcie_ep {  	struct pci_epc		*epc; -	struct dw_pcie_ep_ops	*ops; +	const struct dw_pcie_ep_ops *ops;  	phys_addr_t		phys_base;  	size_t			addr_size;  	size_t			page_size; @@ -222,6 +223,10 @@ struct dw_pcie_ops {  			    size_t size);  	void	(*write_dbi)(struct dw_pcie *pcie, void __iomem *base, u32 reg,  			     size_t size, u32 val); +	u32     (*read_dbi2)(struct dw_pcie *pcie, void __iomem *base, u32 reg, +			     size_t size); +	void    (*write_dbi2)(struct dw_pcie *pcie, void __iomem *base, u32 reg, +			      size_t size, u32 val);  	int	(*link_up)(struct dw_pcie *pcie);  	int	(*start_link)(struct dw_pcie *pcie);  	void	(*stop_link)(struct dw_pcie *pcie); @@ -238,6 +243,7 @@ struct dw_pcie {  	struct pcie_port	pp;  	struct dw_pcie_ep	ep;  	const struct dw_pcie_ops *ops; +	unsigned int		version;  };  #define to_dw_pcie_from_pp(port) container_of((port), struct dw_pcie, pp) @@ -252,6 +258,10 @@ u32 __dw_pcie_read_dbi(struct dw_pcie *pci, void __iomem *base, u32 reg,  		       size_t size);  void __dw_pcie_write_dbi(struct dw_pcie *pci, void __iomem *base, u32 reg,  			 size_t size, u32 val); +u32 __dw_pcie_read_dbi2(struct dw_pcie *pci, void __iomem *base, u32 reg, +			size_t size); +void __dw_pcie_write_dbi2(struct dw_pcie *pci, void __iomem *base, u32 reg, +			  size_t size, u32 val);  int dw_pcie_link_up(struct dw_pcie *pci);  int dw_pcie_wait_for_link(struct dw_pcie *pci);  void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, @@ -295,12 +305,12 @@ static inline u8 dw_pcie_readb_dbi(struct dw_pcie *pci, u32 reg)  static inline void dw_pcie_writel_dbi2(struct dw_pcie *pci, u32 reg, u32 val)  { -	__dw_pcie_write_dbi(pci, pci->dbi_base2, reg, 0x4, val); +	__dw_pcie_write_dbi2(pci, pci->dbi_base2, reg, 0x4, val);  }  static inline u32 dw_pcie_readl_dbi2(struct dw_pcie *pci, u32 reg)  { -	return __dw_pcie_read_dbi(pci, pci->dbi_base2, reg, 0x4); +	return __dw_pcie_read_dbi2(pci, pci->dbi_base2, reg, 0x4);  }  static inline void dw_pcie_writel_atu(struct dw_pcie *pci, u32 reg, u32 val) diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index a7f703556790..0ed235d560e3 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -1129,25 +1129,8 @@ err_deinit:  	return ret;  } -static int qcom_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, -				 u32 *val) -{ -	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); - -	/* the device class is not reported correctly from the register */ -	if (where == PCI_CLASS_REVISION && size == 4) { -		*val = readl(pci->dbi_base + PCI_CLASS_REVISION); -		*val &= 0xff;	/* keep revision id */ -		*val |= PCI_CLASS_BRIDGE_PCI << 16; -		return PCIBIOS_SUCCESSFUL; -	} - -	return dw_pcie_read(pci->dbi_base + where, size, val); -} -  static const struct dw_pcie_host_ops qcom_pcie_dw_ops = {  	.host_init = qcom_pcie_host_init, -	.rd_own_conf = qcom_pcie_rd_own_conf,  };  /* Qcom IP rev.: 2.1.0	Synopsys IP rev.: 4.01a */ @@ -1309,6 +1292,12 @@ static const struct of_device_id qcom_pcie_match[] = {  	{ }  }; +static void qcom_fixup_class(struct pci_dev *dev) +{ +	dev->class = PCI_CLASS_BRIDGE_PCI << 8; +} +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, PCI_ANY_ID, qcom_fixup_class); +  static struct platform_driver qcom_pcie_driver = {  	.probe = qcom_pcie_probe,  	.driver = { diff --git a/drivers/pci/controller/dwc/pcie-uniphier.c b/drivers/pci/controller/dwc/pcie-uniphier.c index d5dc40289cce..3f30ee4a00b3 100644 --- a/drivers/pci/controller/dwc/pcie-uniphier.c +++ b/drivers/pci/controller/dwc/pcie-uniphier.c @@ -270,6 +270,7 @@ static int uniphier_pcie_config_legacy_irq(struct pcie_port *pp)  	struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci);  	struct device_node *np = pci->dev->of_node;  	struct device_node *np_intc; +	int ret = 0;  	np_intc = of_get_child_by_name(np, "legacy-interrupt-controller");  	if (!np_intc) { @@ -280,20 +281,24 @@ static int uniphier_pcie_config_legacy_irq(struct pcie_port *pp)  	pp->irq = irq_of_parse_and_map(np_intc, 0);  	if (!pp->irq) {  		dev_err(pci->dev, "Failed to get an IRQ entry in legacy-interrupt-controller\n"); -		return -EINVAL; +		ret = -EINVAL; +		goto out_put_node;  	}  	priv->legacy_irq_domain = irq_domain_add_linear(np_intc, PCI_NUM_INTX,  						&uniphier_intx_domain_ops, pp);  	if (!priv->legacy_irq_domain) {  		dev_err(pci->dev, "Failed to get INTx domain\n"); -		return -ENODEV; +		ret = -ENODEV; +		goto out_put_node;  	}  	irq_set_chained_handler_and_data(pp->irq, uniphier_pcie_irq_handler,  					 pp); -	return 0; +out_put_node: +	of_node_put(np_intc); +	return ret;  }  static int uniphier_pcie_host_init(struct pcie_port *pp) diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c index eb58dfdaba1b..134e0306ff00 100644 --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c @@ -794,6 +794,7 @@ static int advk_pcie_init_irq_domain(struct advk_pcie *pcie)  	struct device_node *node = dev->of_node;  	struct device_node *pcie_intc_node;  	struct irq_chip *irq_chip; +	int ret = 0;  	pcie_intc_node =  of_get_next_child(node, NULL);  	if (!pcie_intc_node) { @@ -806,8 +807,8 @@ static int advk_pcie_init_irq_domain(struct advk_pcie *pcie)  	irq_chip->name = devm_kasprintf(dev, GFP_KERNEL, "%s-irq",  					dev_name(dev));  	if (!irq_chip->name) { -		of_node_put(pcie_intc_node); -		return -ENOMEM; +		ret = -ENOMEM; +		goto out_put_node;  	}  	irq_chip->irq_mask = advk_pcie_irq_mask; @@ -819,11 +820,13 @@ static int advk_pcie_init_irq_domain(struct advk_pcie *pcie)  				      &advk_pcie_irq_domain_ops, pcie);  	if (!pcie->irq_domain) {  		dev_err(dev, "Failed to get a INTx IRQ domain\n"); -		of_node_put(pcie_intc_node); -		return -ENOMEM; +		ret = -ENOMEM; +		goto out_put_node;  	} -	return 0; +out_put_node: +	of_node_put(pcie_intc_node); +	return ret;  }  static void advk_pcie_remove_irq_domain(struct advk_pcie *pcie) diff --git a/drivers/pci/controller/pci-host-generic.c b/drivers/pci/controller/pci-host-generic.c index dea3ec7592a2..75a2fb930d4b 100644 --- a/drivers/pci/controller/pci-host-generic.c +++ b/drivers/pci/controller/pci-host-generic.c @@ -1,6 +1,6 @@  // SPDX-License-Identifier: GPL-2.0  /* - * Simple, generic PCI host controller driver targetting firmware-initialised + * Simple, generic PCI host controller driver targeting firmware-initialised   * systems and virtual machines (e.g. the PCI emulation provided by kvmtool).   *   * Copyright (C) 2014 ARM Limited diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c index 95441a35eceb..82acd6155adf 100644 --- a/drivers/pci/controller/pci-hyperv.c +++ b/drivers/pci/controller/pci-hyperv.c @@ -1486,6 +1486,21 @@ static void hv_pci_assign_slots(struct hv_pcibus_device *hbus)  	}  } +/* + * Remove entries in sysfs pci slot directory. + */ +static void hv_pci_remove_slots(struct hv_pcibus_device *hbus) +{ +	struct hv_pci_dev *hpdev; + +	list_for_each_entry(hpdev, &hbus->children, list_entry) { +		if (!hpdev->pci_slot) +			continue; +		pci_destroy_slot(hpdev->pci_slot); +		hpdev->pci_slot = NULL; +	} +} +  /**   * create_root_hv_pci_bus() - Expose a new root PCI bus   * @hbus:	Root PCI bus, as understood by this driver @@ -1761,6 +1776,10 @@ static void pci_devices_present_work(struct work_struct *work)  		hpdev = list_first_entry(&removed, struct hv_pci_dev,  					 list_entry);  		list_del(&hpdev->list_entry); + +		if (hpdev->pci_slot) +			pci_destroy_slot(hpdev->pci_slot); +  		put_pcichild(hpdev);  	} @@ -1900,6 +1919,9 @@ static void hv_eject_device_work(struct work_struct *work)  			 sizeof(*ejct_pkt), (unsigned long)&ctxt.pkt,  			 VM_PKT_DATA_INBAND, 0); +	/* For the get_pcichild() in hv_pci_eject_device() */ +	put_pcichild(hpdev); +	/* For the two refs got in new_pcichild_device() */  	put_pcichild(hpdev);  	put_pcichild(hpdev);  	put_hvpcibus(hpdev->hbus); @@ -2677,6 +2699,7 @@ static int hv_pci_remove(struct hv_device *hdev)  		pci_lock_rescan_remove();  		pci_stop_root_bus(hbus->pci_bus);  		pci_remove_root_bus(hbus->pci_bus); +		hv_pci_remove_slots(hbus);  		pci_unlock_rescan_remove();  		hbus->state = hv_pcibus_removed;  	} diff --git a/drivers/pci/controller/pci-tegra.c b/drivers/pci/controller/pci-tegra.c index f4f53d092e00..464ba2538d52 100644 --- a/drivers/pci/controller/pci-tegra.c +++ b/drivers/pci/controller/pci-tegra.c @@ -231,9 +231,9 @@ struct tegra_msi {  	struct msi_controller chip;  	DECLARE_BITMAP(used, INT_PCI_MSI_NR);  	struct irq_domain *domain; -	unsigned long pages;  	struct mutex lock; -	u64 phys; +	void *virt; +	dma_addr_t phys;  	int irq;  }; @@ -1536,7 +1536,7 @@ static int tegra_pcie_msi_setup(struct tegra_pcie *pcie)  	err = platform_get_irq_byname(pdev, "msi");  	if (err < 0) {  		dev_err(dev, "failed to get IRQ: %d\n", err); -		goto err; +		goto free_irq_domain;  	}  	msi->irq = err; @@ -1545,17 +1545,35 @@ static int tegra_pcie_msi_setup(struct tegra_pcie *pcie)  			  tegra_msi_irq_chip.name, pcie);  	if (err < 0) {  		dev_err(dev, "failed to request IRQ: %d\n", err); -		goto err; +		goto free_irq_domain; +	} + +	/* Though the PCIe controller can address >32-bit address space, to +	 * facilitate endpoints that support only 32-bit MSI target address, +	 * the mask is set to 32-bit to make sure that MSI target address is +	 * always a 32-bit address +	 */ +	err = dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); +	if (err < 0) { +		dev_err(dev, "failed to set DMA coherent mask: %d\n", err); +		goto free_irq; +	} + +	msi->virt = dma_alloc_attrs(dev, PAGE_SIZE, &msi->phys, GFP_KERNEL, +				    DMA_ATTR_NO_KERNEL_MAPPING); +	if (!msi->virt) { +		dev_err(dev, "failed to allocate DMA memory for MSI\n"); +		err = -ENOMEM; +		goto free_irq;  	} -	/* setup AFI/FPCI range */ -	msi->pages = __get_free_pages(GFP_KERNEL, 0); -	msi->phys = virt_to_phys((void *)msi->pages);  	host->msi = &msi->chip;  	return 0; -err: +free_irq: +	free_irq(msi->irq, pcie); +free_irq_domain:  	irq_domain_remove(msi->domain);  	return err;  } @@ -1592,7 +1610,8 @@ static void tegra_pcie_msi_teardown(struct tegra_pcie *pcie)  	struct tegra_msi *msi = &pcie->msi;  	unsigned int i, irq; -	free_pages(msi->pages, 0); +	dma_free_attrs(pcie->dev, PAGE_SIZE, msi->virt, msi->phys, +		       DMA_ATTR_NO_KERNEL_MAPPING);  	if (msi->irq > 0)  		free_irq(msi->irq, pcie); diff --git a/drivers/pci/controller/pcie-iproc-msi.c b/drivers/pci/controller/pcie-iproc-msi.c index cb3401a931f8..0a3f61be5625 100644 --- a/drivers/pci/controller/pcie-iproc-msi.c +++ b/drivers/pci/controller/pcie-iproc-msi.c @@ -367,7 +367,7 @@ static void iproc_msi_handler(struct irq_desc *desc)  		/*  		 * Now go read the tail pointer again to see if there are new -		 * oustanding events that came in during the above window. +		 * outstanding events that came in during the above window.  		 */  	} while (true); diff --git a/drivers/pci/controller/pcie-iproc.c b/drivers/pci/controller/pcie-iproc.c index c20fd6bd68fd..e3ca46497470 100644 --- a/drivers/pci/controller/pcie-iproc.c +++ b/drivers/pci/controller/pcie-iproc.c @@ -60,6 +60,10 @@  #define APB_ERR_EN_SHIFT		0  #define APB_ERR_EN			BIT(APB_ERR_EN_SHIFT) +#define CFG_RD_SUCCESS			0 +#define CFG_RD_UR			1 +#define CFG_RD_CRS			2 +#define CFG_RD_CA			3  #define CFG_RETRY_STATUS		0xffff0001  #define CFG_RETRY_STATUS_TIMEOUT_US	500000 /* 500 milliseconds */ @@ -289,6 +293,9 @@ enum iproc_pcie_reg {  	IPROC_PCIE_IARR4,  	IPROC_PCIE_IMAP4, +	/* config read status */ +	IPROC_PCIE_CFG_RD_STATUS, +  	/* link status */  	IPROC_PCIE_LINK_STATUS, @@ -350,6 +357,7 @@ static const u16 iproc_pcie_reg_paxb_v2[] = {  	[IPROC_PCIE_IMAP3]		= 0xe08,  	[IPROC_PCIE_IARR4]		= 0xe68,  	[IPROC_PCIE_IMAP4]		= 0xe70, +	[IPROC_PCIE_CFG_RD_STATUS]	= 0xee0,  	[IPROC_PCIE_LINK_STATUS]	= 0xf0c,  	[IPROC_PCIE_APB_ERR_EN]		= 0xf40,  }; @@ -474,10 +482,12 @@ static void __iomem *iproc_pcie_map_ep_cfg_reg(struct iproc_pcie *pcie,  	return (pcie->base + offset);  } -static unsigned int iproc_pcie_cfg_retry(void __iomem *cfg_data_p) +static unsigned int iproc_pcie_cfg_retry(struct iproc_pcie *pcie, +					 void __iomem *cfg_data_p)  {  	int timeout = CFG_RETRY_STATUS_TIMEOUT_US;  	unsigned int data; +	u32 status;  	/*  	 * As per PCIe spec r3.1, sec 2.3.2, CRS Software Visibility only @@ -498,6 +508,15 @@ static unsigned int iproc_pcie_cfg_retry(void __iomem *cfg_data_p)  	 */  	data = readl(cfg_data_p);  	while (data == CFG_RETRY_STATUS && timeout--) { +		/* +		 * CRS state is set in CFG_RD status register +		 * This will handle the case where CFG_RETRY_STATUS is +		 * valid config data. +		 */ +		status = iproc_pcie_read_reg(pcie, IPROC_PCIE_CFG_RD_STATUS); +		if (status != CFG_RD_CRS) +			return data; +  		udelay(1);  		data = readl(cfg_data_p);  	} @@ -576,7 +595,7 @@ static int iproc_pcie_config_read(struct pci_bus *bus, unsigned int devfn,  	if (!cfg_data_p)  		return PCIBIOS_DEVICE_NOT_FOUND; -	data = iproc_pcie_cfg_retry(cfg_data_p); +	data = iproc_pcie_cfg_retry(pcie, cfg_data_p);  	*val = data;  	if (size <= 2) @@ -936,8 +955,25 @@ static int iproc_pcie_setup_ob(struct iproc_pcie *pcie, u64 axi_addr,  			resource_size_t window_size =  				ob_map->window_sizes[size_idx] * SZ_1M; -			if (size < window_size) -				continue; +			/* +			 * Keep iterating until we reach the last window and +			 * with the minimal window size at index zero. In this +			 * case, we take a compromise by mapping it using the +			 * minimum window size that can be supported +			 */ +			if (size < window_size) { +				if (size_idx > 0 || window_idx > 0) +					continue; + +				/* +				 * For the corner case of reaching the minimal +				 * window size that can be supported on the +				 * last window +				 */ +				axi_addr = ALIGN_DOWN(axi_addr, window_size); +				pci_addr = ALIGN_DOWN(pci_addr, window_size); +				size = window_size; +			}  			if (!IS_ALIGNED(axi_addr, window_size) ||  			    !IS_ALIGNED(pci_addr, window_size)) { @@ -1146,11 +1182,43 @@ err_ib:  	return ret;  } +static int iproc_pcie_add_dma_range(struct device *dev, +				    struct list_head *resources, +				    struct of_pci_range *range) +{ +	struct resource *res; +	struct resource_entry *entry, *tmp; +	struct list_head *head = resources; + +	res = devm_kzalloc(dev, sizeof(struct resource), GFP_KERNEL); +	if (!res) +		return -ENOMEM; + +	resource_list_for_each_entry(tmp, resources) { +		if (tmp->res->start < range->cpu_addr) +			head = &tmp->node; +	} + +	res->start = range->cpu_addr; +	res->end = res->start + range->size - 1; + +	entry = resource_list_create_entry(res, 0); +	if (!entry) +		return -ENOMEM; + +	entry->offset = res->start - range->cpu_addr; +	resource_list_add(entry, head); + +	return 0; +} +  static int iproc_pcie_map_dma_ranges(struct iproc_pcie *pcie)  { +	struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie);  	struct of_pci_range range;  	struct of_pci_range_parser parser;  	int ret; +	LIST_HEAD(resources);  	/* Get the dma-ranges from DT */  	ret = of_pci_dma_range_parser_init(&parser, pcie->dev->of_node); @@ -1158,13 +1226,23 @@ static int iproc_pcie_map_dma_ranges(struct iproc_pcie *pcie)  		return ret;  	for_each_of_pci_range(&parser, &range) { +		ret = iproc_pcie_add_dma_range(pcie->dev, +					       &resources, +					       &range); +		if (ret) +			goto out;  		/* Each range entry corresponds to an inbound mapping region */  		ret = iproc_pcie_setup_ib(pcie, &range, IPROC_PCIE_IB_MAP_MEM);  		if (ret) -			return ret; +			goto out;  	} +	list_splice_init(&resources, &host->dma_ranges); +  	return 0; +out: +	pci_free_resource_list(&resources); +	return ret;  }  static int iproce_pcie_get_msi(struct iproc_pcie *pcie, @@ -1320,14 +1398,18 @@ static int iproc_pcie_msi_enable(struct iproc_pcie *pcie)  	if (pcie->need_msi_steer) {  		ret = iproc_pcie_msi_steer(pcie, msi_node);  		if (ret) -			return ret; +			goto out_put_node;  	}  	/*  	 * If another MSI controller is being used, the call below should fail  	 * but that is okay  	 */ -	return iproc_msi_init(pcie, msi_node); +	ret = iproc_msi_init(pcie, msi_node); + +out_put_node: +	of_node_put(msi_node); +	return ret;  }  static void iproc_pcie_msi_disable(struct iproc_pcie *pcie) @@ -1347,7 +1429,6 @@ static int iproc_pcie_rev_init(struct iproc_pcie *pcie)  		break;  	case IPROC_PCIE_PAXB:  		regs = iproc_pcie_reg_paxb; -		pcie->iproc_cfg_read = true;  		pcie->has_apb_err_disable = true;  		if (pcie->need_ob_cfg) {  			pcie->ob_map = paxb_ob_map; @@ -1356,6 +1437,7 @@ static int iproc_pcie_rev_init(struct iproc_pcie *pcie)  		break;  	case IPROC_PCIE_PAXB_V2:  		regs = iproc_pcie_reg_paxb_v2; +		pcie->iproc_cfg_read = true;  		pcie->has_apb_err_disable = true;  		if (pcie->need_ob_cfg) {  			pcie->ob_map = paxb_v2_ob_map; diff --git a/drivers/pci/controller/pcie-mediatek.c b/drivers/pci/controller/pcie-mediatek.c index 0b6c72804e03..80601e1b939e 100644 --- a/drivers/pci/controller/pcie-mediatek.c +++ b/drivers/pci/controller/pcie-mediatek.c @@ -578,6 +578,7 @@ static int mtk_pcie_init_irq_domain(struct mtk_pcie_port *port,  	port->irq_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,  						 &intx_domain_ops, port); +	of_node_put(pcie_intc_node);  	if (!port->irq_domain) {  		dev_err(dev, "failed to get INTx IRQ domain\n");  		return -ENODEV; @@ -915,49 +916,29 @@ static int mtk_pcie_parse_port(struct mtk_pcie *pcie,  	/* sys_ck might be divided into the following parts in some chips */  	snprintf(name, sizeof(name), "ahb_ck%d", slot); -	port->ahb_ck = devm_clk_get(dev, name); -	if (IS_ERR(port->ahb_ck)) { -		if (PTR_ERR(port->ahb_ck) == -EPROBE_DEFER) -			return -EPROBE_DEFER; - -		port->ahb_ck = NULL; -	} +	port->ahb_ck = devm_clk_get_optional(dev, name); +	if (IS_ERR(port->ahb_ck)) +		return PTR_ERR(port->ahb_ck);  	snprintf(name, sizeof(name), "axi_ck%d", slot); -	port->axi_ck = devm_clk_get(dev, name); -	if (IS_ERR(port->axi_ck)) { -		if (PTR_ERR(port->axi_ck) == -EPROBE_DEFER) -			return -EPROBE_DEFER; - -		port->axi_ck = NULL; -	} +	port->axi_ck = devm_clk_get_optional(dev, name); +	if (IS_ERR(port->axi_ck)) +		return PTR_ERR(port->axi_ck);  	snprintf(name, sizeof(name), "aux_ck%d", slot); -	port->aux_ck = devm_clk_get(dev, name); -	if (IS_ERR(port->aux_ck)) { -		if (PTR_ERR(port->aux_ck) == -EPROBE_DEFER) -			return -EPROBE_DEFER; - -		port->aux_ck = NULL; -	} +	port->aux_ck = devm_clk_get_optional(dev, name); +	if (IS_ERR(port->aux_ck)) +		return PTR_ERR(port->aux_ck);  	snprintf(name, sizeof(name), "obff_ck%d", slot); -	port->obff_ck = devm_clk_get(dev, name); -	if (IS_ERR(port->obff_ck)) { -		if (PTR_ERR(port->obff_ck) == -EPROBE_DEFER) -			return -EPROBE_DEFER; - -		port->obff_ck = NULL; -	} +	port->obff_ck = devm_clk_get_optional(dev, name); +	if (IS_ERR(port->obff_ck)) +		return PTR_ERR(port->obff_ck);  	snprintf(name, sizeof(name), "pipe_ck%d", slot); -	port->pipe_ck = devm_clk_get(dev, name); -	if (IS_ERR(port->pipe_ck)) { -		if (PTR_ERR(port->pipe_ck) == -EPROBE_DEFER) -			return -EPROBE_DEFER; - -		port->pipe_ck = NULL; -	} +	port->pipe_ck = devm_clk_get_optional(dev, name); +	if (IS_ERR(port->pipe_ck)) +		return PTR_ERR(port->pipe_ck);  	snprintf(name, sizeof(name), "pcie-rst%d", slot);  	port->reset = devm_reset_control_get_optional_exclusive(dev, name); diff --git a/drivers/pci/controller/pcie-rcar.c b/drivers/pci/controller/pcie-rcar.c index c8febb009454..f6a669a9af41 100644 --- a/drivers/pci/controller/pcie-rcar.c +++ b/drivers/pci/controller/pcie-rcar.c @@ -46,14 +46,15 @@  /* Transfer control */  #define PCIETCTLR		0x02000 -#define  CFINIT			1 +#define  DL_DOWN		BIT(3) +#define  CFINIT			BIT(0)  #define PCIETSTR		0x02004 -#define  DATA_LINK_ACTIVE	1 +#define  DATA_LINK_ACTIVE	BIT(0)  #define PCIEERRFR		0x02020  #define  UNSUPPORTED_REQUEST	BIT(4)  #define PCIEMSIFR		0x02044  #define PCIEMSIALR		0x02048 -#define  MSIFE			1 +#define  MSIFE			BIT(0)  #define PCIEMSIAUR		0x0204c  #define PCIEMSIIER		0x02050 @@ -94,6 +95,7 @@  #define MACCTLR			0x011058  #define  SPEED_CHANGE		BIT(24)  #define  SCRAMBLE_DISABLE	BIT(27) +#define PMSR			0x01105c  #define MACS2R			0x011078  #define MACCGSPSETR		0x011084  #define  SPCNGRSN		BIT(31) @@ -152,14 +154,13 @@ struct rcar_pcie {  	struct			rcar_msi msi;  }; -static void rcar_pci_write_reg(struct rcar_pcie *pcie, unsigned long val, -			       unsigned long reg) +static void rcar_pci_write_reg(struct rcar_pcie *pcie, u32 val, +			       unsigned int reg)  {  	writel(val, pcie->base + reg);  } -static unsigned long rcar_pci_read_reg(struct rcar_pcie *pcie, -				       unsigned long reg) +static u32 rcar_pci_read_reg(struct rcar_pcie *pcie, unsigned int reg)  {  	return readl(pcie->base + reg);  } @@ -171,7 +172,7 @@ enum {  static void rcar_rmw32(struct rcar_pcie *pcie, int where, u32 mask, u32 data)  { -	int shift = 8 * (where & 3); +	unsigned int shift = BITS_PER_BYTE * (where & 3);  	u32 val = rcar_pci_read_reg(pcie, where & ~3);  	val &= ~(mask << shift); @@ -181,7 +182,7 @@ static void rcar_rmw32(struct rcar_pcie *pcie, int where, u32 mask, u32 data)  static u32 rcar_read_conf(struct rcar_pcie *pcie, int where)  { -	int shift = 8 * (where & 3); +	unsigned int shift = BITS_PER_BYTE * (where & 3);  	u32 val = rcar_pci_read_reg(pcie, where & ~3);  	return val >> shift; @@ -192,7 +193,7 @@ static int rcar_pcie_config_access(struct rcar_pcie *pcie,  		unsigned char access_type, struct pci_bus *bus,  		unsigned int devfn, int where, u32 *data)  { -	int dev, func, reg, index; +	unsigned int dev, func, reg, index;  	dev = PCI_SLOT(devfn);  	func = PCI_FUNC(devfn); @@ -281,12 +282,12 @@ static int rcar_pcie_read_conf(struct pci_bus *bus, unsigned int devfn,  	}  	if (size == 1) -		*val = (*val >> (8 * (where & 3))) & 0xff; +		*val = (*val >> (BITS_PER_BYTE * (where & 3))) & 0xff;  	else if (size == 2) -		*val = (*val >> (8 * (where & 2))) & 0xffff; +		*val = (*val >> (BITS_PER_BYTE * (where & 2))) & 0xffff; -	dev_dbg(&bus->dev, "pcie-config-read: bus=%3d devfn=0x%04x where=0x%04x size=%d val=0x%08lx\n", -		bus->number, devfn, where, size, (unsigned long)*val); +	dev_dbg(&bus->dev, "pcie-config-read: bus=%3d devfn=0x%04x where=0x%04x size=%d val=0x%08x\n", +		bus->number, devfn, where, size, *val);  	return ret;  } @@ -296,23 +297,24 @@ static int rcar_pcie_write_conf(struct pci_bus *bus, unsigned int devfn,  				int where, int size, u32 val)  {  	struct rcar_pcie *pcie = bus->sysdata; -	int shift, ret; +	unsigned int shift;  	u32 data; +	int ret;  	ret = rcar_pcie_config_access(pcie, RCAR_PCI_ACCESS_READ,  				      bus, devfn, where, &data);  	if (ret != PCIBIOS_SUCCESSFUL)  		return ret; -	dev_dbg(&bus->dev, "pcie-config-write: bus=%3d devfn=0x%04x where=0x%04x size=%d val=0x%08lx\n", -		bus->number, devfn, where, size, (unsigned long)val); +	dev_dbg(&bus->dev, "pcie-config-write: bus=%3d devfn=0x%04x where=0x%04x size=%d val=0x%08x\n", +		bus->number, devfn, where, size, val);  	if (size == 1) { -		shift = 8 * (where & 3); +		shift = BITS_PER_BYTE * (where & 3);  		data &= ~(0xff << shift);  		data |= ((val & 0xff) << shift);  	} else if (size == 2) { -		shift = 8 * (where & 2); +		shift = BITS_PER_BYTE * (where & 2);  		data &= ~(0xffff << shift);  		data |= ((val & 0xffff) << shift);  	} else @@ -507,10 +509,10 @@ static int phy_wait_for_ack(struct rcar_pcie *pcie)  }  static void phy_write_reg(struct rcar_pcie *pcie, -				 unsigned int rate, unsigned int addr, -				 unsigned int lane, unsigned int data) +			  unsigned int rate, u32 addr, +			  unsigned int lane, u32 data)  { -	unsigned long phyaddr; +	u32 phyaddr;  	phyaddr = WRITE_CMD |  		((rate & 1) << RATE_POS) | @@ -738,15 +740,15 @@ static irqreturn_t rcar_pcie_msi_irq(int irq, void *data)  	while (reg) {  		unsigned int index = find_first_bit(®, 32); -		unsigned int irq; +		unsigned int msi_irq;  		/* clear the interrupt */  		rcar_pci_write_reg(pcie, 1 << index, PCIEMSIFR); -		irq = irq_find_mapping(msi->domain, index); -		if (irq) { +		msi_irq = irq_find_mapping(msi->domain, index); +		if (msi_irq) {  			if (test_bit(index, msi->used)) -				generic_handle_irq(irq); +				generic_handle_irq(msi_irq);  			else  				dev_info(dev, "unhandled MSI\n");  		} else { @@ -890,7 +892,7 @@ static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)  {  	struct device *dev = pcie->dev;  	struct rcar_msi *msi = &pcie->msi; -	unsigned long base; +	phys_addr_t base;  	int err, i;  	mutex_init(&msi->lock); @@ -929,10 +931,14 @@ static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)  	/* setup MSI data target */  	msi->pages = __get_free_pages(GFP_KERNEL, 0); +	if (!msi->pages) { +		err = -ENOMEM; +		goto err; +	}  	base = virt_to_phys((void *)msi->pages); -	rcar_pci_write_reg(pcie, base | MSIFE, PCIEMSIALR); -	rcar_pci_write_reg(pcie, 0, PCIEMSIAUR); +	rcar_pci_write_reg(pcie, lower_32_bits(base) | MSIFE, PCIEMSIALR); +	rcar_pci_write_reg(pcie, upper_32_bits(base), PCIEMSIAUR);  	/* enable all MSI interrupts */  	rcar_pci_write_reg(pcie, 0xffffffff, PCIEMSIIER); @@ -1118,7 +1124,7 @@ static int rcar_pcie_probe(struct platform_device *pdev)  {  	struct device *dev = &pdev->dev;  	struct rcar_pcie *pcie; -	unsigned int data; +	u32 data;  	int err;  	int (*phy_init_fn)(struct rcar_pcie *);  	struct pci_host_bridge *bridge; @@ -1130,6 +1136,7 @@ static int rcar_pcie_probe(struct platform_device *pdev)  	pcie = pci_host_bridge_priv(bridge);  	pcie->dev = dev; +	platform_set_drvdata(pdev, pcie);  	err = pci_parse_request_of_pci_ranges(dev, &pcie->resources, NULL);  	if (err) @@ -1221,10 +1228,28 @@ err_free_bridge:  	return err;  } +static int rcar_pcie_resume_noirq(struct device *dev) +{ +	struct rcar_pcie *pcie = dev_get_drvdata(dev); + +	if (rcar_pci_read_reg(pcie, PMSR) && +	    !(rcar_pci_read_reg(pcie, PCIETCTLR) & DL_DOWN)) +		return 0; + +	/* Re-establish the PCIe link */ +	rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR); +	return rcar_pcie_wait_for_dl(pcie); +} + +static const struct dev_pm_ops rcar_pcie_pm_ops = { +	.resume_noirq = rcar_pcie_resume_noirq, +}; +  static struct platform_driver rcar_pcie_driver = {  	.driver = {  		.name = "rcar-pcie",  		.of_match_table = rcar_pcie_of_match, +		.pm = &rcar_pcie_pm_ops,  		.suppress_bind_attrs = true,  	},  	.probe = rcar_pcie_probe, diff --git a/drivers/pci/controller/pcie-rockchip-ep.c b/drivers/pci/controller/pcie-rockchip-ep.c index a5d799e2dff2..d743b0a48988 100644 --- a/drivers/pci/controller/pcie-rockchip-ep.c +++ b/drivers/pci/controller/pcie-rockchip-ep.c @@ -350,7 +350,7 @@ static void rockchip_pcie_ep_assert_intx(struct rockchip_pcie_ep *ep, u8 fn,  	struct rockchip_pcie *rockchip = &ep->rockchip;  	u32 r = ep->max_regions - 1;  	u32 offset; -	u16 status; +	u32 status;  	u8 msg_code;  	if (unlikely(ep->irq_pci_addr != ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR || diff --git a/drivers/pci/controller/pcie-rockchip-host.c b/drivers/pci/controller/pcie-rockchip-host.c index 1372d270764f..8d20f1793a61 100644 --- a/drivers/pci/controller/pcie-rockchip-host.c +++ b/drivers/pci/controller/pcie-rockchip-host.c @@ -724,6 +724,7 @@ static int rockchip_pcie_init_irq_domain(struct rockchip_pcie *rockchip)  	rockchip->irq_domain = irq_domain_add_linear(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");  		return -EINVAL; diff --git a/drivers/pci/controller/pcie-xilinx-nwl.c b/drivers/pci/controller/pcie-xilinx-nwl.c index 81538d77f790..3b031f00a94a 100644 --- a/drivers/pci/controller/pcie-xilinx-nwl.c +++ b/drivers/pci/controller/pcie-xilinx-nwl.c @@ -438,11 +438,10 @@ static const struct irq_domain_ops legacy_domain_ops = {  #ifdef CONFIG_PCI_MSI  static struct irq_chip nwl_msi_irq_chip = {  	.name = "nwl_pcie:msi", -	.irq_enable = unmask_msi_irq, -	.irq_disable = mask_msi_irq, -	.irq_mask = mask_msi_irq, -	.irq_unmask = unmask_msi_irq, - +	.irq_enable = pci_msi_unmask_irq, +	.irq_disable = pci_msi_mask_irq, +	.irq_mask = pci_msi_mask_irq, +	.irq_unmask = pci_msi_unmask_irq,  };  static struct msi_domain_info nwl_msi_domain_info = { diff --git a/drivers/pci/controller/pcie-xilinx.c b/drivers/pci/controller/pcie-xilinx.c index 9bd1a35cd5d8..5bf3af3b28e6 100644 --- a/drivers/pci/controller/pcie-xilinx.c +++ b/drivers/pci/controller/pcie-xilinx.c @@ -336,14 +336,19 @@ static const struct irq_domain_ops msi_domain_ops = {   * xilinx_pcie_enable_msi - Enable MSI support   * @port: PCIe port information   */ -static void xilinx_pcie_enable_msi(struct xilinx_pcie_port *port) +static int xilinx_pcie_enable_msi(struct xilinx_pcie_port *port)  {  	phys_addr_t msg_addr;  	port->msi_pages = __get_free_pages(GFP_KERNEL, 0); +	if (!port->msi_pages) +		return -ENOMEM; +  	msg_addr = virt_to_phys((void *)port->msi_pages);  	pcie_write(port, 0x0, XILINX_PCIE_REG_MSIBASE1);  	pcie_write(port, msg_addr, XILINX_PCIE_REG_MSIBASE2); + +	return 0;  }  /* INTx Functions */ @@ -498,6 +503,7 @@ static int xilinx_pcie_init_irq_domain(struct xilinx_pcie_port *port)  	struct device *dev = port->dev;  	struct device_node *node = dev->of_node;  	struct device_node *pcie_intc_node; +	int ret;  	/* Setup INTx */  	pcie_intc_node = of_get_next_child(node, NULL); @@ -526,7 +532,9 @@ static int xilinx_pcie_init_irq_domain(struct xilinx_pcie_port *port)  			return -ENODEV;  		} -		xilinx_pcie_enable_msi(port); +		ret = xilinx_pcie_enable_msi(port); +		if (ret) +			return ret;  	}  	return 0; diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c index cf6816b55b5e..999a5509e57e 100644 --- a/drivers/pci/controller/vmd.c +++ b/drivers/pci/controller/vmd.c @@ -95,10 +95,8 @@ struct vmd_dev {  	struct irq_domain	*irq_domain;  	struct pci_bus		*bus; -#ifdef CONFIG_X86_DEV_DMA_OPS  	struct dma_map_ops	dma_ops;  	struct dma_domain	dma_domain; -#endif  };  static inline struct vmd_dev *vmd_from_bus(struct pci_bus *bus) @@ -293,7 +291,6 @@ static struct msi_domain_info vmd_msi_domain_info = {  	.chip		= &vmd_msi_controller,  }; -#ifdef CONFIG_X86_DEV_DMA_OPS  /*   * VMD replaces the requester ID with its own.  DMA mappings for devices in a   * VMD domain need to be mapped for the VMD, not the device requiring @@ -438,10 +435,6 @@ static void vmd_setup_dma_ops(struct vmd_dev *vmd)  	add_dma_domain(domain);  }  #undef ASSIGN_VMD_DMA_OPS -#else -static void vmd_teardown_dma_ops(struct vmd_dev *vmd) {} -static void vmd_setup_dma_ops(struct vmd_dev *vmd) {} -#endif  static char __iomem *vmd_cfg_addr(struct vmd_dev *vmd, struct pci_bus *bus,  				  unsigned int devfn, int reg, int len) |