diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-10-22 12:41:00 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-10-22 12:41:00 -0700 | 
| commit | 00937f36b09e89c74e4a059dbb8acbf4b971d5eb (patch) | |
| tree | ff2e5f5fa6736460437f57680405a20124d1e969 /drivers/pci/controller/dwc | |
| parent | 96485e4462604744d66bf4301557d996d80b85eb (diff) | |
| parent | 28e34e751f6c50098d9bcecb30c97634b6126730 (diff) | |
Merge tag 'pci-v5.10-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull PCI updates from Bjorn Helgaas:
 "Enumeration:
   - Print IRQ number used by PCIe Link Bandwidth Notification (Dongdong
     Liu)
   - Add schedule point in pci_read_config() to reduce max latency
     (Jiang Biao)
   - Add Kconfig options for MPS/MRRS strategy (Jim Quinlan)
  Resource management:
   - Fix pci_iounmap() memory leak when !CONFIG_GENERIC_IOMAP (Lorenzo
     Pieralisi)
  PCIe native device hotplug:
   - Reduce noisiness on hot removal (Lukas Wunner)
  Power management:
   - Revert "PCI/PM: Apply D2 delay as milliseconds, not microseconds"
     that was done on the basis of spec typo (Bjorn Helgaas)
   - Rename pci_dev.d3_delay to d3hot_delay to remove D3hot/D3cold
     ambiguity (Krzysztof Wilczyński)
   - Remove unused pcibios_pm_ops (Vaibhav Gupta)
  IOMMU:
   - Enable Translation Blocking for external devices to harden against
     DMA attacks (Rajat Jain)
  Error handling:
   - Add an ACPI APEI notifier chain for vendor CPER records to enable
     device-specific error handling (Shiju Jose)
  ASPM:
   - Remove struct aspm_register_info to simplify code (Saheed O.
     Bolarinwa)
  Amlogic Meson PCIe controller driver:
   - Build as module by default (Kevin Hilman)
  Ampere Altra PCIe controller driver:
   - Add MCFG quirk to work around non-standard ECAM implementation
     (Tuan Phan)
  Broadcom iProc PCIe controller driver:
   - Set affinity mask on MSI interrupts (Mark Tomlinson)
  Broadcom STB PCIe controller driver:
   - Make PCIE_BRCMSTB depend on ARCH_BRCMSTB (Jim Quinlan)
   - Add DT bindings for more Brcmstb chips (Jim Quinlan)
   - Add bcm7278 register info (Jim Quinlan)
   - Add bcm7278 PERST# support (Jim Quinlan)
   - Add suspend and resume pm_ops (Jim Quinlan)
   - Add control of rescal reset (Jim Quinlan)
   - Set additional internal memory DMA viewport sizes (Jim Quinlan)
   - Accommodate MSI for older chips (Jim Quinlan)
   - Set bus max burst size by chip type (Jim Quinlan)
   - Add support for bcm7211, bcm7216, bcm7445, bcm7278 (Jim Quinlan)
  Freescale i.MX6 PCIe controller driver:
   - Use dev_err_probe() to reduce redundant messages (Anson Huang)
  Freescale Layerscape PCIe controller driver:
   - Enforce 4K DMA buffer alignment in endpoint test (Hou Zhiqiang)
   - Add DT compatible strings for ls1088a, ls2088a (Xiaowei Bao)
   - Add endpoint support for ls1088a, ls2088a (Xiaowei Bao)
   - Add endpoint test support for lS1088a (Xiaowei Bao)
   - Add MSI-X support for ls1088a (Xiaowei Bao)
  HiSilicon HIP PCIe controller driver:
   - Handle HIP-specific errors via ACPI APEI (Yicong Yang)
  HiSilicon Kirin PCIe controller driver:
   - Return -EPROBE_DEFER if the GPIO isn't ready (Bean Huo)
  Intel VMD host bridge driver:
   - Factor out physical offset, bus offset, IRQ domain, IRQ allocation
     (Jon Derrick)
   - Use generic PCI PM correctly (Jon Derrick)
  Marvell Aardvark PCIe controller driver:
   - Fix compilation on s390 (Pali Rohár)
   - Implement driver 'remove' function and allow to build it as module
     (Pali Rohár)
   - Move PCIe reset card code to advk_pcie_train_link() (Pali Rohár)
   - Convert mvebu a3700 internal SMCC firmware return codes to errno
     (Pali Rohár)
   - Fix initialization with old Marvell's Arm Trusted Firmware (Pali
     Rohár)
  Microsoft Hyper-V host bridge driver:
   - Fix hibernation in case interrupts are not re-created (Dexuan Cui)
  NVIDIA Tegra PCIe controller driver:
   - Stop checking return value of debugfs_create() functions (Greg
     Kroah-Hartman)
   - Convert to use DEFINE_SEQ_ATTRIBUTE macro (Liu Shixin)
  Qualcomm PCIe controller driver:
   - Reset PCIe to work around Qsdk U-Boot issue (Ansuel Smith)
  Renesas R-Car PCIe controller driver:
   - Add DT documentation for r8a774a1, r8a774b1, r8a774e1 endpoints
     (Lad Prabhakar)
   - Add RZ/G2M, RZ/G2N, RZ/G2H IDs to endpoint test (Lad Prabhakar)
   - Add DT support for r8a7742 (Lad Prabhakar)
  Socionext UniPhier Pro5 controller driver:
   - Add DT descriptions of iATU register (host and endpoint) (Kunihiko
     Hayashi)
  Synopsys DesignWare PCIe controller driver:
   - Add link up check in dw_child_pcie_ops.map_bus() (racy, but seems
     unavoidable) (Hou Zhiqiang)
   - Fix endpoint Header Type check so multi-function devices work (Hou
     Zhiqiang)
   - Skip PCIE_MSI_INTR0* programming if MSI is disabled (Jisheng Zhang)
   - Stop leaking MSI page in suspend/resume (Jisheng Zhang)
   - Add common iATU register support instead of keystone-specific code
     (Kunihiko Hayashi)
   - Major config space access and other cleanups in dwc core and
     drivers that use it (al, exynos, histb, imx6, intel-gw, keystone,
     kirin, meson, qcom, tegra) (Rob Herring)
   - Add multiple PFs support for endpoint (Xiaowei Bao)
   - Add MSI-X doorbell mode in endpoint mode (Xiaowei Bao)
  Miscellaneous:
   - Use fallthrough pseudo-keyword (Gustavo A. R. Silva)
   - Fix "0 used as NULL pointer" warnings (Gustavo Pimentel)
   - Fix "cast truncates bits from constant value" warnings (Gustavo
     Pimentel)
   - Remove redundant zeroing for sg_init_table() (Julia Lawall)
   - Use scnprintf(), not snprintf(), in sysfs "show" functions
     (Krzysztof Wilczyński)
   - Remove unused assignments (Krzysztof Wilczyński)
   - Fix "0 used as NULL pointer" warning (Krzysztof Wilczyński)
   - Simplify bool comparisons (Krzysztof Wilczyński)
   - Use for_each_child_of_node() and for_each_node_by_name() (Qinglang
     Miao)
   - Simplify return expressions (Qinglang Miao)"
* tag 'pci-v5.10-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (147 commits)
  PCI: vmd: Update VMD PM to correctly use generic PCI PM
  PCI: vmd: Create IRQ allocation helper
  PCI: vmd: Create IRQ Domain configuration helper
  PCI: vmd: Create bus offset configuration helper
  PCI: vmd: Create physical offset helper
  PCI: v3-semi: Remove unneeded break
  PCI: dwc: Add link up check in dw_child_pcie_ops.map_bus()
  PCI/ASPM: Remove struct pcie_link_state.l1ss
  PCI/ASPM: Remove struct aspm_register_info.l1ss_cap
  PCI/ASPM: Pass L1SS Capabilities value, not struct aspm_register_info
  PCI/ASPM: Remove struct aspm_register_info.l1ss_ctl1
  PCI/ASPM: Remove struct aspm_register_info.l1ss_ctl2 (unused)
  PCI/ASPM: Remove struct aspm_register_info.l1ss_cap_ptr
  PCI/ASPM: Remove struct aspm_register_info.latency_encoding
  PCI/ASPM: Remove struct aspm_register_info.enabled
  PCI/ASPM: Remove struct aspm_register_info.support
  PCI/ASPM: Use 'parent' and 'child' for readability
  PCI/ASPM: Move LTR path check to where it's used
  PCI/ASPM: Move pci_clear_and_set_dword() earlier
  PCI: dwc: Fix MSI page leakage in suspend/resume
  ...
Diffstat (limited to 'drivers/pci/controller/dwc')
21 files changed, 895 insertions, 1104 deletions
diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig index 044a3761c44f..bc049865f8e0 100644 --- a/drivers/pci/controller/dwc/Kconfig +++ b/drivers/pci/controller/dwc/Kconfig @@ -237,8 +237,9 @@ config PCIE_HISI_STB  	  Say Y here if you want PCIe controller support on HiSilicon STB SoCs  config PCI_MESON -	bool "MESON PCIe controller" +	tristate "MESON PCIe controller"  	depends on PCI_MSI_IRQ_DOMAIN +	default m if ARCH_MESON  	select PCIE_DW_HOST  	help  	  Say Y here if you want to enable PCI controller support on Amlogic diff --git a/drivers/pci/controller/dwc/pci-dra7xx.c b/drivers/pci/controller/dwc/pci-dra7xx.c index dc387724cf08..6d012d2b1e90 100644 --- a/drivers/pci/controller/dwc/pci-dra7xx.c +++ b/drivers/pci/controller/dwc/pci-dra7xx.c @@ -73,8 +73,6 @@  #define	LINK_UP						BIT(16)  #define	DRA7XX_CPU_TO_BUS_ADDR				0x0FFFFFFF -#define EXP_CAP_ID_OFFSET				0x70 -  #define	PCIECTRL_TI_CONF_INTX_ASSERT			0x0124  #define	PCIECTRL_TI_CONF_INTX_DEASSERT			0x0128 @@ -91,7 +89,6 @@ struct dra7xx_pcie {  	void __iomem		*base;		/* DT ti_conf */  	int			phy_count;	/* DT phy-names count */  	struct phy		**phy; -	int			link_gen;  	struct irq_domain	*irq_domain;  	enum dw_pcie_device_mode mode;  }; @@ -142,33 +139,12 @@ static int dra7xx_pcie_establish_link(struct dw_pcie *pci)  	struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci);  	struct device *dev = pci->dev;  	u32 reg; -	u32 exp_cap_off = EXP_CAP_ID_OFFSET;  	if (dw_pcie_link_up(pci)) {  		dev_err(dev, "link is already up\n");  		return 0;  	} -	if (dra7xx->link_gen == 1) { -		dw_pcie_read(pci->dbi_base + exp_cap_off + PCI_EXP_LNKCAP, -			     4, ®); -		if ((reg & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_2_5GB) { -			reg &= ~((u32)PCI_EXP_LNKCAP_SLS); -			reg |= PCI_EXP_LNKCAP_SLS_2_5GB; -			dw_pcie_write(pci->dbi_base + exp_cap_off + -				      PCI_EXP_LNKCAP, 4, reg); -		} - -		dw_pcie_read(pci->dbi_base + exp_cap_off + PCI_EXP_LNKCTL2, -			     2, ®); -		if ((reg & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_2_5GB) { -			reg &= ~((u32)PCI_EXP_LNKCAP_SLS); -			reg |= PCI_EXP_LNKCAP_SLS_2_5GB; -			dw_pcie_write(pci->dbi_base + exp_cap_off + -				      PCI_EXP_LNKCTL2, 2, reg); -		} -	} -  	reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD);  	reg |= LTSSM_EN;  	dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD, reg); @@ -490,7 +466,9 @@ static struct irq_chip dra7xx_pci_msi_bottom_irq_chip = {  static int dra7xx_pcie_msi_host_init(struct pcie_port *pp)  {  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); +	struct device *dev = pci->dev;  	u32 ctrl, num_ctrls; +	int ret;  	pp->msi_irq_chip = &dra7xx_pci_msi_bottom_irq_chip; @@ -506,7 +484,21 @@ static int dra7xx_pcie_msi_host_init(struct pcie_port *pp)  				    ~0);  	} -	return dw_pcie_allocate_domains(pp); +	ret = dw_pcie_allocate_domains(pp); +	if (ret) +		return ret; + +	pp->msi_data = dma_map_single_attrs(dev, &pp->msi_msg, +					   sizeof(pp->msi_msg), +					   DMA_FROM_DEVICE, +					   DMA_ATTR_SKIP_CPU_SYNC); +	ret = dma_mapping_error(dev, pp->msi_data); +	if (ret) { +		dev_err(dev, "Failed to map MSI data\n"); +		pp->msi_data = 0; +		dw_pcie_free_msi(pp); +	} +	return ret;  }  static const struct dw_pcie_host_ops dra7xx_pcie_host_ops = { @@ -937,10 +929,6 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)  	reg &= ~LTSSM_EN;  	dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD, reg); -	dra7xx->link_gen = of_pci_get_max_link_speed(np); -	if (dra7xx->link_gen < 0 || dra7xx->link_gen > 2) -		dra7xx->link_gen = 2; -  	switch (mode) {  	case DW_PCIE_RC_TYPE:  		if (!IS_ENABLED(CONFIG_PCI_DRA7XX_HOST)) { diff --git a/drivers/pci/controller/dwc/pci-exynos.c b/drivers/pci/controller/dwc/pci-exynos.c index 8d82c43ae299..242683cde04a 100644 --- a/drivers/pci/controller/dwc/pci-exynos.c +++ b/drivers/pci/controller/dwc/pci-exynos.c @@ -336,32 +336,37 @@ static void exynos_pcie_write_dbi(struct dw_pcie *pci, void __iomem *base,  	exynos_pcie_sideband_dbi_w_mode(ep, false);  } -static int exynos_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, -				u32 *val) +static int exynos_pcie_rd_own_conf(struct pci_bus *bus, unsigned int devfn, +				   int where, int size, u32 *val)  { -	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); -	struct exynos_pcie *ep = to_exynos_pcie(pci); -	int ret; +	struct dw_pcie *pci = to_dw_pcie_from_pp(bus->sysdata); -	exynos_pcie_sideband_dbi_r_mode(ep, true); -	ret = dw_pcie_read(pci->dbi_base + where, size, val); -	exynos_pcie_sideband_dbi_r_mode(ep, false); -	return ret; +	if (PCI_SLOT(devfn)) { +		*val = ~0; +		return PCIBIOS_DEVICE_NOT_FOUND; +	} + +	*val = dw_pcie_read_dbi(pci, where, size); +	return PCIBIOS_SUCCESSFUL;  } -static int exynos_pcie_wr_own_conf(struct pcie_port *pp, int where, int size, -				u32 val) +static int exynos_pcie_wr_own_conf(struct pci_bus *bus, unsigned int devfn, +				   int where, int size, u32 val)  { -	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); -	struct exynos_pcie *ep = to_exynos_pcie(pci); -	int ret; +	struct dw_pcie *pci = to_dw_pcie_from_pp(bus->sysdata); -	exynos_pcie_sideband_dbi_w_mode(ep, true); -	ret = dw_pcie_write(pci->dbi_base + where, size, val); -	exynos_pcie_sideband_dbi_w_mode(ep, false); -	return ret; +	if (PCI_SLOT(devfn)) +		return PCIBIOS_DEVICE_NOT_FOUND; + +	dw_pcie_write_dbi(pci, where, size, val); +	return PCIBIOS_SUCCESSFUL;  } +static struct pci_ops exynos_pci_ops = { +	.read = exynos_pcie_rd_own_conf, +	.write = exynos_pcie_wr_own_conf, +}; +  static int exynos_pcie_link_up(struct dw_pcie *pci)  {  	struct exynos_pcie *ep = to_exynos_pcie(pci); @@ -379,6 +384,8 @@ static int exynos_pcie_host_init(struct pcie_port *pp)  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);  	struct exynos_pcie *ep = to_exynos_pcie(pci); +	pp->bridge->ops = &exynos_pci_ops; +  	exynos_pcie_establish_link(ep);  	exynos_pcie_enable_interrupts(ep); @@ -386,8 +393,6 @@ static int exynos_pcie_host_init(struct pcie_port *pp)  }  static const struct dw_pcie_host_ops exynos_pcie_host_ops = { -	.rd_own_conf = exynos_pcie_rd_own_conf, -	.wr_own_conf = exynos_pcie_wr_own_conf,  	.host_init = exynos_pcie_host_init,  }; diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c index 5fef2613b223..5cf1ef12fb9b 100644 --- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -79,7 +79,6 @@ struct imx6_pcie {  	u32			tx_deemph_gen2_6db;  	u32			tx_swing_full;  	u32			tx_swing_low; -	int			link_gen;  	struct regulator	*vpcie;  	void __iomem		*phy_base; @@ -94,15 +93,6 @@ struct imx6_pcie {  #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 -#define PCIE_RC_LCR				0x7c -#define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1	0x1 -#define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2	0x2 -#define PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK	0xf - -#define PCIE_RC_LCSR				0x80 -  /* PCIe Port Logic registers (memory-mapped) */  #define PL_OFFSET 0x700 @@ -116,8 +106,6 @@ struct imx6_pcie {  #define PCIE_PHY_STAT (PL_OFFSET + 0x110)  #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			BIT(2) @@ -761,6 +749,7 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)  {  	struct dw_pcie *pci = imx6_pcie->pci;  	struct device *dev = pci->dev; +	u8 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);  	u32 tmp;  	int ret; @@ -769,10 +758,10 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)  	 * started in Gen2 mode, there is a possibility the devices on the  	 * bus will not be detected at all.  This happens with PCIe switches.  	 */ -	tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCR); -	tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK; -	tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1; -	dw_pcie_writel_dbi(pci, PCIE_RC_LCR, tmp); +	tmp = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP); +	tmp &= ~PCI_EXP_LNKCAP_SLS; +	tmp |= PCI_EXP_LNKCAP_SLS_2_5GB; +	dw_pcie_writel_dbi(pci, offset + PCI_EXP_LNKCAP, tmp);  	/* Start LTSSM. */  	imx6_pcie_ltssm_enable(dev); @@ -781,12 +770,12 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)  	if (ret)  		goto err_reset_phy; -	if (imx6_pcie->link_gen == 2) { +	if (pci->link_gen == 2) {  		/* Allow Gen2 mode after the link is up. */ -		tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCR); -		tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK; -		tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2; -		dw_pcie_writel_dbi(pci, PCIE_RC_LCR, tmp); +		tmp = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP); +		tmp &= ~PCI_EXP_LNKCAP_SLS; +		tmp |= PCI_EXP_LNKCAP_SLS_5_0GB; +		dw_pcie_writel_dbi(pci, offset + PCI_EXP_LNKCAP, tmp);  		/*  		 * Start Directed Speed Change so the best possible @@ -824,8 +813,8 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)  		dev_info(dev, "Link: Gen2 disabled\n");  	} -	tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCSR); -	dev_info(dev, "Link up, Gen%i\n", (tmp >> 16) & 0xf); +	tmp = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA); +	dev_info(dev, "Link up, Gen%i\n", tmp & PCI_EXP_LNKSTA_CLS);  	return 0;  err_reset_phy: @@ -847,9 +836,7 @@ static int imx6_pcie_host_init(struct pcie_port *pp)  	imx6_setup_phy_mpll(imx6_pcie);  	dw_pcie_setup_rc(pp);  	imx6_pcie_establish_link(imx6_pcie); - -	if (IS_ENABLED(CONFIG_PCI_MSI)) -		dw_pcie_msi_init(pp); +	dw_pcie_msi_init(pp);  	return 0;  } @@ -1073,38 +1060,33 @@ static int imx6_pcie_probe(struct platform_device *pdev)  	/* Fetch clocks */  	imx6_pcie->pcie_phy = devm_clk_get(dev, "pcie_phy"); -	if (IS_ERR(imx6_pcie->pcie_phy)) { -		dev_err(dev, "pcie_phy clock source missing or invalid\n"); -		return PTR_ERR(imx6_pcie->pcie_phy); -	} +	if (IS_ERR(imx6_pcie->pcie_phy)) +		return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_phy), +				     "pcie_phy clock source missing or invalid\n");  	imx6_pcie->pcie_bus = devm_clk_get(dev, "pcie_bus"); -	if (IS_ERR(imx6_pcie->pcie_bus)) { -		dev_err(dev, "pcie_bus clock source missing or invalid\n"); -		return PTR_ERR(imx6_pcie->pcie_bus); -	} +	if (IS_ERR(imx6_pcie->pcie_bus)) +		return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_bus), +				     "pcie_bus clock source missing or invalid\n");  	imx6_pcie->pcie = devm_clk_get(dev, "pcie"); -	if (IS_ERR(imx6_pcie->pcie)) { -		dev_err(dev, "pcie clock source missing or invalid\n"); -		return PTR_ERR(imx6_pcie->pcie); -	} +	if (IS_ERR(imx6_pcie->pcie)) +		return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie), +				     "pcie clock source missing or invalid\n");  	switch (imx6_pcie->drvdata->variant) {  	case IMX6SX:  		imx6_pcie->pcie_inbound_axi = devm_clk_get(dev,  							   "pcie_inbound_axi"); -		if (IS_ERR(imx6_pcie->pcie_inbound_axi)) { -			dev_err(dev, "pcie_inbound_axi clock missing or invalid\n"); -			return PTR_ERR(imx6_pcie->pcie_inbound_axi); -		} +		if (IS_ERR(imx6_pcie->pcie_inbound_axi)) +			return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_inbound_axi), +					     "pcie_inbound_axi clock missing or invalid\n");  		break;  	case IMX8MQ:  		imx6_pcie->pcie_aux = devm_clk_get(dev, "pcie_aux"); -		if (IS_ERR(imx6_pcie->pcie_aux)) { -			dev_err(dev, "pcie_aux clock source missing or invalid\n"); -			return PTR_ERR(imx6_pcie->pcie_aux); -		} +		if (IS_ERR(imx6_pcie->pcie_aux)) +			return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_aux), +					     "pcie_aux clock source missing or invalid\n");  		fallthrough;  	case IMX7D:  		if (dbi_base->start == IMX8MQ_PCIE2_BASE_ADDR) @@ -1165,10 +1147,8 @@ static int imx6_pcie_probe(struct platform_device *pdev)  		imx6_pcie->tx_swing_low = 127;  	/* Limit link speed */ -	ret = of_property_read_u32(node, "fsl,max-link-speed", -				   &imx6_pcie->link_gen); -	if (ret) -		imx6_pcie->link_gen = 1; +	pci->link_gen = 1; +	ret = of_property_read_u32(node, "fsl,max-link-speed", &pci->link_gen);  	imx6_pcie->vpcie = devm_regulator_get_optional(&pdev->dev, "vpcie");  	if (IS_ERR(imx6_pcie->vpcie)) { @@ -1188,11 +1168,10 @@ static int imx6_pcie_probe(struct platform_device *pdev)  		return ret;  	if (pci_msi_enabled()) { -		val = dw_pcie_readw_dbi(pci, PCIE_RC_IMX6_MSI_CAP + -					PCI_MSI_FLAGS); +		u8 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_MSI); +		val = dw_pcie_readw_dbi(pci, offset + PCI_MSI_FLAGS);  		val |= PCI_MSI_FLAGS_ENABLE; -		dw_pcie_writew_dbi(pci, PCIE_RC_IMX6_MSI_CAP + PCI_MSI_FLAGS, -				   val); +		dw_pcie_writew_dbi(pci, offset + PCI_MSI_FLAGS, val);  	}  	return 0; diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c index c8c9d6a75f17..a222728238ca 100644 --- a/drivers/pci/controller/dwc/pci-keystone.c +++ b/drivers/pci/controller/dwc/pci-keystone.c @@ -96,8 +96,6 @@  #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 @@ -123,7 +121,6 @@ struct keystone_pcie {  	int			msi_host_irq;  	int			num_lanes; -	u32			num_viewport;  	struct phy		**phy;  	struct device_link	**link;  	struct			device_node *msi_intc_np; @@ -397,13 +394,17 @@ static void ks_pcie_clear_dbi_mode(struct keystone_pcie *ks_pcie)  static void ks_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)  {  	u32 val; -	u32 num_viewport = ks_pcie->num_viewport;  	struct dw_pcie *pci = ks_pcie->pci;  	struct pcie_port *pp = &pci->pp; -	u64 start = pp->mem->start; -	u64 end = pp->mem->end; +	u32 num_viewport = pci->num_viewport; +	u64 start, end; +	struct resource *mem;  	int i; +	mem = resource_list_first_type(&pp->bridge->windows, IORESOURCE_MEM)->res; +	start = mem->start; +	end = mem->end; +  	/* Disable BARs for inbound access */  	ks_pcie_set_dbi_mode(ks_pcie);  	dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0); @@ -430,10 +431,10 @@ static void ks_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)  	ks_pcie_app_writel(ks_pcie, CMD_STATUS, val);  } -static int ks_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus, -				 unsigned int devfn, int where, int size, -				 u32 *val) +static void __iomem *ks_pcie_other_map_bus(struct pci_bus *bus, +					   unsigned int devfn, int where)  { +	struct pcie_port *pp = bus->sysdata;  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);  	struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);  	u32 reg; @@ -444,36 +445,29 @@ static int ks_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,  		reg |= CFG_TYPE1;  	ks_pcie_app_writel(ks_pcie, CFG_SETUP, reg); -	return dw_pcie_read(pp->va_cfg0_base + where, size, val); +	return pp->va_cfg0_base + where;  } -static int ks_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus, -				 unsigned int devfn, int where, int size, -				 u32 val) -{ -	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); -	struct keystone_pcie *ks_pcie = to_keystone_pcie(pci); -	u32 reg; - -	reg = CFG_BUS(bus->number) | CFG_DEVICE(PCI_SLOT(devfn)) | -		CFG_FUNC(PCI_FUNC(devfn)); -	if (!pci_is_root_bus(bus->parent)) -		reg |= CFG_TYPE1; -	ks_pcie_app_writel(ks_pcie, CFG_SETUP, reg); - -	return dw_pcie_write(pp->va_cfg0_base + where, size, val); -} +static struct pci_ops ks_child_pcie_ops = { +	.map_bus = ks_pcie_other_map_bus, +	.read = pci_generic_config_read, +	.write = pci_generic_config_write, +};  /** - * ks_pcie_v3_65_scan_bus() - keystone scan_bus post initialization + * ks_pcie_v3_65_add_bus() - keystone add_bus post initialization   *   * This sets BAR0 to enable inbound access for MSI_IRQ register   */ -static void ks_pcie_v3_65_scan_bus(struct pcie_port *pp) +static int ks_pcie_v3_65_add_bus(struct pci_bus *bus)  { +	struct pcie_port *pp = bus->sysdata;  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);  	struct keystone_pcie *ks_pcie = to_keystone_pcie(pci); +	if (!pci_is_root_bus(bus)) +		return 0; +  	/* Configure and set up BAR0 */  	ks_pcie_set_dbi_mode(ks_pcie); @@ -488,8 +482,17 @@ static void ks_pcie_v3_65_scan_bus(struct pcie_port *pp)  	  * be sufficient.  Use physical address to avoid any conflicts.  	  */  	dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, ks_pcie->app.start); + +	return 0;  } +static struct pci_ops ks_pcie_ops = { +	.map_bus = dw_pcie_own_conf_map_bus, +	.read = pci_generic_config_read, +	.write = pci_generic_config_write, +	.add_bus = ks_pcie_v3_65_add_bus, +}; +  /**   * ks_pcie_link_up() - Check if link up   */ @@ -807,6 +810,9 @@ static int __init ks_pcie_host_init(struct pcie_port *pp)  	struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);  	int ret; +	pp->bridge->ops = &ks_pcie_ops; +	pp->bridge->child_ops = &ks_child_pcie_ops; +  	ret = ks_pcie_config_legacy_irq(ks_pcie);  	if (ret)  		return ret; @@ -842,11 +848,8 @@ static int __init ks_pcie_host_init(struct pcie_port *pp)  }  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_host_init = ks_pcie_msi_host_init, -	.scan_bus = ks_pcie_v3_65_scan_bus,  };  static const struct dw_pcie_host_ops ks_pcie_am654_host_ops = { @@ -867,16 +870,8 @@ 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; -	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); - -	pp->va_cfg1_base = pp->va_cfg0_base; -  	ret = dw_pcie_host_init(pp);  	if (ret) {  		dev_err(dev, "failed to initialize host\n"); @@ -886,18 +881,6 @@ static int __init ks_pcie_add_pcie_port(struct keystone_pcie *ks_pcie,  	return 0;  } -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)  { @@ -912,7 +895,6 @@ 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,  }; @@ -1125,31 +1107,6 @@ static int ks_pcie_am654_set_mode(struct device *dev,  	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, @@ -1197,13 +1154,10 @@ static int __init ks_pcie_probe(struct platform_device *pdev)  	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; @@ -1320,29 +1274,12 @@ static int __init ks_pcie_probe(struct platform_device *pdev)  		goto err_get_sync;  	} -	if (pci->version >= 0x480A) { -		atu_base = devm_platform_ioremap_resource_byname(pdev, "atu"); -		if (IS_ERR(atu_base)) { -			ret = PTR_ERR(atu_base); -			goto err_get_sync; -		} - -		pci->atu_base = atu_base; - +	if (pci->version >= 0x480A)  		ret = ks_pcie_am654_set_mode(dev, mode); -		if (ret < 0) -			goto err_get_sync; -	} else { +	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); +	if (ret < 0) +		goto err_get_sync;  	switch (mode) {  	case DW_PCIE_RC_TYPE: @@ -1351,12 +1288,6 @@ static int __init ks_pcie_probe(struct platform_device *pdev)  			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"); -			goto err_get_sync; -		} -  		/*  		 * "Power Sequencing and Reset Signal Timings" table in  		 * PCI EXPRESS CARD ELECTROMECHANICAL SPECIFICATION, REV. 2.0 @@ -1370,7 +1301,6 @@ static int __init ks_pcie_probe(struct platform_device *pdev)  			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) diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c b/drivers/pci/controller/dwc/pci-layerscape-ep.c index 0d151cead1b7..84206f265e54 100644 --- a/drivers/pci/controller/dwc/pci-layerscape-ep.c +++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c @@ -20,50 +20,58 @@  #define PCIE_DBI2_OFFSET		0x1000	/* DBI2 base address*/ -struct ls_pcie_ep { -	struct dw_pcie		*pci; +#define to_ls_pcie_ep(x)	dev_get_drvdata((x)->dev) + +struct ls_pcie_ep_drvdata { +	u32				func_offset; +	const struct dw_pcie_ep_ops	*ops; +	const struct dw_pcie_ops	*dw_pcie_ops;  }; -#define to_ls_pcie_ep(x)	dev_get_drvdata((x)->dev) +struct ls_pcie_ep { +	struct dw_pcie			*pci; +	struct pci_epc_features		*ls_epc; +	const struct ls_pcie_ep_drvdata *drvdata; +};  static int ls_pcie_establish_link(struct dw_pcie *pci)  {  	return 0;  } -static const struct dw_pcie_ops ls_pcie_ep_ops = { +static const struct dw_pcie_ops dw_ls_pcie_ep_ops = {  	.start_link = ls_pcie_establish_link,  }; -static const struct of_device_id ls_pcie_ep_of_match[] = { -	{ .compatible = "fsl,ls-pcie-ep",}, -	{ }, -}; - -static const struct pci_epc_features ls_pcie_epc_features = { -	.linkup_notifier = false, -	.msi_capable = true, -	.msix_capable = false, -	.bar_fixed_64bit = (1 << BAR_2) | (1 << BAR_4), -}; -  static const struct pci_epc_features*  ls_pcie_ep_get_features(struct dw_pcie_ep *ep)  { -	return &ls_pcie_epc_features; +	struct dw_pcie *pci = to_dw_pcie_from_ep(ep); +	struct ls_pcie_ep *pcie = to_ls_pcie_ep(pci); + +	return pcie->ls_epc;  }  static void ls_pcie_ep_init(struct dw_pcie_ep *ep)  {  	struct dw_pcie *pci = to_dw_pcie_from_ep(ep); +	struct ls_pcie_ep *pcie = to_ls_pcie_ep(pci); +	struct dw_pcie_ep_func *ep_func;  	enum pci_barno bar; +	ep_func = dw_pcie_ep_get_func_from_ep(ep, 0); +	if (!ep_func) +		return; +  	for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)  		dw_pcie_ep_reset_bar(pci, bar); + +	pcie->ls_epc->msi_capable = ep_func->msi_cap ? true : false; +	pcie->ls_epc->msix_capable = ep_func->msix_cap ? true : false;  }  static int ls_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no, -				  enum pci_epc_irq_type type, u16 interrupt_num) +				enum pci_epc_irq_type type, u16 interrupt_num)  {  	struct dw_pcie *pci = to_dw_pcie_from_ep(ep); @@ -73,21 +81,51 @@ static int ls_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,  	case PCI_EPC_IRQ_MSI:  		return dw_pcie_ep_raise_msi_irq(ep, func_no, interrupt_num);  	case PCI_EPC_IRQ_MSIX: -		return dw_pcie_ep_raise_msix_irq(ep, func_no, interrupt_num); +		return dw_pcie_ep_raise_msix_irq_doorbell(ep, func_no, +							  interrupt_num);  	default:  		dev_err(pci->dev, "UNKNOWN IRQ type\n");  		return -EINVAL;  	}  } -static const struct dw_pcie_ep_ops pcie_ep_ops = { +static unsigned int ls_pcie_ep_func_conf_select(struct dw_pcie_ep *ep, +						u8 func_no) +{ +	struct dw_pcie *pci = to_dw_pcie_from_ep(ep); +	struct ls_pcie_ep *pcie = to_ls_pcie_ep(pci); + +	WARN_ON(func_no && !pcie->drvdata->func_offset); +	return pcie->drvdata->func_offset * func_no; +} + +static const struct dw_pcie_ep_ops ls_pcie_ep_ops = {  	.ep_init = ls_pcie_ep_init,  	.raise_irq = ls_pcie_ep_raise_irq,  	.get_features = ls_pcie_ep_get_features, +	.func_conf_select = ls_pcie_ep_func_conf_select, +}; + +static const struct ls_pcie_ep_drvdata ls1_ep_drvdata = { +	.ops = &ls_pcie_ep_ops, +	.dw_pcie_ops = &dw_ls_pcie_ep_ops, +}; + +static const struct ls_pcie_ep_drvdata ls2_ep_drvdata = { +	.func_offset = 0x20000, +	.ops = &ls_pcie_ep_ops, +	.dw_pcie_ops = &dw_ls_pcie_ep_ops, +}; + +static const struct of_device_id ls_pcie_ep_of_match[] = { +	{ .compatible = "fsl,ls1046a-pcie-ep", .data = &ls1_ep_drvdata }, +	{ .compatible = "fsl,ls1088a-pcie-ep", .data = &ls2_ep_drvdata }, +	{ .compatible = "fsl,ls2088a-pcie-ep", .data = &ls2_ep_drvdata }, +	{ },  };  static int __init ls_add_pcie_ep(struct ls_pcie_ep *pcie, -					struct platform_device *pdev) +				 struct platform_device *pdev)  {  	struct dw_pcie *pci = pcie->pci;  	struct device *dev = pci->dev; @@ -96,7 +134,7 @@ static int __init ls_add_pcie_ep(struct ls_pcie_ep *pcie,  	int ret;  	ep = &pci->ep; -	ep->ops = &pcie_ep_ops; +	ep->ops = pcie->drvdata->ops;  	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space");  	if (!res) @@ -119,6 +157,7 @@ static int __init ls_pcie_ep_probe(struct platform_device *pdev)  	struct device *dev = &pdev->dev;  	struct dw_pcie *pci;  	struct ls_pcie_ep *pcie; +	struct pci_epc_features *ls_epc;  	struct resource *dbi_base;  	int ret; @@ -130,15 +169,26 @@ static int __init ls_pcie_ep_probe(struct platform_device *pdev)  	if (!pci)  		return -ENOMEM; +	ls_epc = devm_kzalloc(dev, sizeof(*ls_epc), GFP_KERNEL); +	if (!ls_epc) +		return -ENOMEM; + +	pcie->drvdata = of_device_get_match_data(dev); + +	pci->dev = dev; +	pci->ops = pcie->drvdata->dw_pcie_ops; + +	ls_epc->bar_fixed_64bit = (1 << BAR_2) | (1 << BAR_4), + +	pcie->pci = pci; +	pcie->ls_epc = ls_epc; +  	dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");  	pci->dbi_base = devm_pci_remap_cfg_resource(dev, dbi_base);  	if (IS_ERR(pci->dbi_base))  		return PTR_ERR(pci->dbi_base);  	pci->dbi_base2 = pci->dbi_base + PCIE_DBI2_OFFSET; -	pci->dev = dev; -	pci->ops = &ls_pcie_ep_ops; -	pcie->pci = pci;  	platform_set_drvdata(pdev, pcie); diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c index 4f183b96afbb..1913dc2c8fa0 100644 --- a/drivers/pci/controller/dwc/pci-meson.c +++ b/drivers/pci/controller/dwc/pci-meson.c @@ -17,37 +17,13 @@  #include <linux/resource.h>  #include <linux/types.h>  #include <linux/phy/phy.h> +#include <linux/module.h>  #include "pcie-designware.h"  #define to_meson_pcie(x) dev_get_drvdata((x)->dev) -/* External local bus interface registers */ -#define PLR_OFFSET			0x700 -#define PCIE_PORT_LINK_CTRL_OFF		(PLR_OFFSET + 0x10) -#define FAST_LINK_MODE			BIT(7) -#define LINK_CAPABLE_MASK		GENMASK(21, 16) -#define LINK_CAPABLE_X1			BIT(16) - -#define PCIE_GEN2_CTRL_OFF		(PLR_OFFSET + 0x10c) -#define NUM_OF_LANES_MASK		GENMASK(12, 8) -#define NUM_OF_LANES_X1			BIT(8) -#define DIRECT_SPEED_CHANGE		BIT(17) - -#define TYPE1_HDR_OFFSET		0x0 -#define PCIE_STATUS_COMMAND		(TYPE1_HDR_OFFSET + 0x04) -#define PCI_IO_EN			BIT(0) -#define PCI_MEM_SPACE_EN		BIT(1) -#define PCI_BUS_MASTER_EN		BIT(2) - -#define PCIE_BASE_ADDR0			(TYPE1_HDR_OFFSET + 0x10) -#define PCIE_BASE_ADDR1			(TYPE1_HDR_OFFSET + 0x14) - -#define PCIE_CAP_OFFSET			0x70 -#define PCIE_DEV_CTRL_DEV_STUS		(PCIE_CAP_OFFSET + 0x08) -#define PCIE_CAP_MAX_PAYLOAD_MASK	GENMASK(7, 5)  #define PCIE_CAP_MAX_PAYLOAD_SIZE(x)	((x) << 5) -#define PCIE_CAP_MAX_READ_REQ_MASK	GENMASK(14, 12)  #define PCIE_CAP_MAX_READ_REQ_SIZE(x)	((x) << 12)  /* PCIe specific config registers */ @@ -77,11 +53,6 @@ enum pcie_data_rate {  	PCIE_GEN4  }; -struct meson_pcie_mem_res { -	void __iomem *elbi_base; -	void __iomem *cfg_base; -}; -  struct meson_pcie_clk_res {  	struct clk *clk;  	struct clk *port_clk; @@ -95,7 +66,7 @@ struct meson_pcie_rc_reset {  struct meson_pcie {  	struct dw_pcie pci; -	struct meson_pcie_mem_res mem_res; +	void __iomem *cfg_base;  	struct meson_pcie_clk_res clk_res;  	struct meson_pcie_rc_reset mrst;  	struct gpio_desc *reset_gpio; @@ -134,28 +105,18 @@ static int meson_pcie_get_resets(struct meson_pcie *mp)  	return 0;  } -static void __iomem *meson_pcie_get_mem(struct platform_device *pdev, -					struct meson_pcie *mp, -					const char *id) -{ -	struct device *dev = mp->pci.dev; -	struct resource *res; - -	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, id); - -	return devm_ioremap_resource(dev, res); -} -  static int meson_pcie_get_mems(struct platform_device *pdev,  			       struct meson_pcie *mp)  { -	mp->mem_res.elbi_base = meson_pcie_get_mem(pdev, mp, "elbi"); -	if (IS_ERR(mp->mem_res.elbi_base)) -		return PTR_ERR(mp->mem_res.elbi_base); +	struct dw_pcie *pci = &mp->pci; + +	pci->dbi_base = devm_platform_ioremap_resource_byname(pdev, "elbi"); +	if (IS_ERR(pci->dbi_base)) +		return PTR_ERR(pci->dbi_base); -	mp->mem_res.cfg_base = meson_pcie_get_mem(pdev, mp, "cfg"); -	if (IS_ERR(mp->mem_res.cfg_base)) -		return PTR_ERR(mp->mem_res.cfg_base); +	mp->cfg_base = devm_platform_ioremap_resource_byname(pdev, "cfg"); +	if (IS_ERR(mp->cfg_base)) +		return PTR_ERR(mp->cfg_base);  	return 0;  } @@ -253,24 +214,14 @@ static int meson_pcie_probe_clocks(struct meson_pcie *mp)  	return 0;  } -static inline void meson_elb_writel(struct meson_pcie *mp, u32 val, u32 reg) -{ -	writel(val, mp->mem_res.elbi_base + reg); -} - -static inline u32 meson_elb_readl(struct meson_pcie *mp, u32 reg) -{ -	return readl(mp->mem_res.elbi_base + reg); -} -  static inline u32 meson_cfg_readl(struct meson_pcie *mp, u32 reg)  { -	return readl(mp->mem_res.cfg_base + reg); +	return readl(mp->cfg_base + reg);  }  static inline void meson_cfg_writel(struct meson_pcie *mp, u32 val, u32 reg)  { -	writel(val, mp->mem_res.cfg_base + reg); +	writel(val, mp->cfg_base + reg);  }  static void meson_pcie_assert_reset(struct meson_pcie *mp) @@ -287,25 +238,6 @@ static void meson_pcie_init_dw(struct meson_pcie *mp)  	val = meson_cfg_readl(mp, PCIE_CFG0);  	val |= APP_LTSSM_ENABLE;  	meson_cfg_writel(mp, val, PCIE_CFG0); - -	val = meson_elb_readl(mp, PCIE_PORT_LINK_CTRL_OFF); -	val &= ~(LINK_CAPABLE_MASK | FAST_LINK_MODE); -	meson_elb_writel(mp, val, PCIE_PORT_LINK_CTRL_OFF); - -	val = meson_elb_readl(mp, PCIE_PORT_LINK_CTRL_OFF); -	val |= LINK_CAPABLE_X1; -	meson_elb_writel(mp, val, PCIE_PORT_LINK_CTRL_OFF); - -	val = meson_elb_readl(mp, PCIE_GEN2_CTRL_OFF); -	val &= ~NUM_OF_LANES_MASK; -	meson_elb_writel(mp, val, PCIE_GEN2_CTRL_OFF); - -	val = meson_elb_readl(mp, PCIE_GEN2_CTRL_OFF); -	val |= NUM_OF_LANES_X1 | DIRECT_SPEED_CHANGE; -	meson_elb_writel(mp, val, PCIE_GEN2_CTRL_OFF); - -	meson_elb_writel(mp, 0x0, PCIE_BASE_ADDR0); -	meson_elb_writel(mp, 0x0, PCIE_BASE_ADDR1);  }  static int meson_size_to_payload(struct meson_pcie *mp, int size) @@ -327,37 +259,34 @@ static int meson_size_to_payload(struct meson_pcie *mp, int size)  static void meson_set_max_payload(struct meson_pcie *mp, int size)  { +	struct dw_pcie *pci = &mp->pci;  	u32 val; +	u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);  	int max_payload_size = meson_size_to_payload(mp, size); -	val = meson_elb_readl(mp, PCIE_DEV_CTRL_DEV_STUS); -	val &= ~PCIE_CAP_MAX_PAYLOAD_MASK; -	meson_elb_writel(mp, val, PCIE_DEV_CTRL_DEV_STUS); +	val = dw_pcie_readl_dbi(pci, offset + PCI_EXP_DEVCTL); +	val &= ~PCI_EXP_DEVCTL_PAYLOAD; +	dw_pcie_writel_dbi(pci, offset + PCI_EXP_DEVCTL, val); -	val = meson_elb_readl(mp, PCIE_DEV_CTRL_DEV_STUS); +	val = dw_pcie_readl_dbi(pci, offset + PCI_EXP_DEVCTL);  	val |= PCIE_CAP_MAX_PAYLOAD_SIZE(max_payload_size); -	meson_elb_writel(mp, val, PCIE_DEV_CTRL_DEV_STUS); +	dw_pcie_writel_dbi(pci, offset + PCI_EXP_DEVCTL, val);  }  static void meson_set_max_rd_req_size(struct meson_pcie *mp, int size)  { +	struct dw_pcie *pci = &mp->pci;  	u32 val; +	u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);  	int max_rd_req_size = meson_size_to_payload(mp, size); -	val = meson_elb_readl(mp, PCIE_DEV_CTRL_DEV_STUS); -	val &= ~PCIE_CAP_MAX_READ_REQ_MASK; -	meson_elb_writel(mp, val, PCIE_DEV_CTRL_DEV_STUS); +	val = dw_pcie_readl_dbi(pci, offset + PCI_EXP_DEVCTL); +	val &= ~PCI_EXP_DEVCTL_READRQ; +	dw_pcie_writel_dbi(pci, offset + PCI_EXP_DEVCTL, val); -	val = meson_elb_readl(mp, PCIE_DEV_CTRL_DEV_STUS); +	val = dw_pcie_readl_dbi(pci, offset + PCI_EXP_DEVCTL);  	val |= PCIE_CAP_MAX_READ_REQ_SIZE(max_rd_req_size); -	meson_elb_writel(mp, val, PCIE_DEV_CTRL_DEV_STUS); -} - -static inline void meson_enable_memory_space(struct meson_pcie *mp) -{ -	/* Set the RC Bus Master, Memory Space and I/O Space enables */ -	meson_elb_writel(mp, PCI_IO_EN | PCI_MEM_SPACE_EN | PCI_BUS_MASTER_EN, -			 PCIE_STATUS_COMMAND); +	dw_pcie_writel_dbi(pci, offset + PCI_EXP_DEVCTL, val);  }  static int meson_pcie_establish_link(struct meson_pcie *mp) @@ -370,26 +299,18 @@ static int meson_pcie_establish_link(struct meson_pcie *mp)  	meson_set_max_rd_req_size(mp, MAX_READ_REQ_SIZE);  	dw_pcie_setup_rc(pp); -	meson_enable_memory_space(mp);  	meson_pcie_assert_reset(mp);  	return dw_pcie_wait_for_link(pci);  } -static void meson_pcie_enable_interrupts(struct meson_pcie *mp) +static int meson_pcie_rd_own_conf(struct pci_bus *bus, u32 devfn, +				  int where, int size, u32 *val)  { -	if (IS_ENABLED(CONFIG_PCI_MSI)) -		dw_pcie_msi_init(&mp->pci.pp); -} - -static int meson_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, -				  u32 *val) -{ -	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);  	int ret; -	ret = dw_pcie_read(pci->dbi_base + where, size, val); +	ret = pci_generic_config_read(bus, devfn, where, size, val);  	if (ret != PCIBIOS_SUCCESSFUL)  		return ret; @@ -410,13 +331,11 @@ static int meson_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,  	return PCIBIOS_SUCCESSFUL;  } -static int meson_pcie_wr_own_conf(struct pcie_port *pp, int where, -				  int size, u32 val) -{ -	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); - -	return dw_pcie_write(pci->dbi_base + where, size, val); -} +static struct pci_ops meson_pci_ops = { +	.map_bus = dw_pcie_own_conf_map_bus, +	.read = meson_pcie_rd_own_conf, +	.write = pci_generic_config_write, +};  static int meson_pcie_link_up(struct dw_pcie *pci)  { @@ -463,18 +382,18 @@ static int meson_pcie_host_init(struct pcie_port *pp)  	struct meson_pcie *mp = to_meson_pcie(pci);  	int ret; +	pp->bridge->ops = &meson_pci_ops; +  	ret = meson_pcie_establish_link(mp);  	if (ret)  		return ret; -	meson_pcie_enable_interrupts(mp); +	dw_pcie_msi_init(pp);  	return 0;  }  static const struct dw_pcie_host_ops meson_pcie_host_ops = { -	.rd_own_conf = meson_pcie_rd_own_conf, -	.wr_own_conf = meson_pcie_wr_own_conf,  	.host_init = meson_pcie_host_init,  }; @@ -493,7 +412,6 @@ static int meson_add_pcie_port(struct meson_pcie *mp,  	}  	pp->ops = &meson_pcie_host_ops; -	pci->dbi_base = mp->mem_res.elbi_base;  	ret = dw_pcie_host_init(pp);  	if (ret) { @@ -522,6 +440,7 @@ static int meson_pcie_probe(struct platform_device *pdev)  	pci = &mp->pci;  	pci->dev = dev;  	pci->ops = &dw_pcie_ops; +	pci->num_lanes = 1;  	mp->phy = devm_phy_get(dev, "pcie");  	if (IS_ERR(mp->phy)) { @@ -589,6 +508,7 @@ static const struct of_device_id meson_pcie_of_match[] = {  	},  	{},  }; +MODULE_DEVICE_TABLE(of, meson_pcie_of_match);  static struct platform_driver meson_pcie_driver = {  	.probe = meson_pcie_probe, @@ -598,4 +518,8 @@ static struct platform_driver meson_pcie_driver = {  	},  }; -builtin_platform_driver(meson_pcie_driver); +module_platform_driver(meson_pcie_driver); + +MODULE_AUTHOR("Yue Wang <yue.wang@amlogic.com>"); +MODULE_DESCRIPTION("Amlogic PCIe Controller driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/pci/controller/dwc/pcie-al.c b/drivers/pci/controller/dwc/pcie-al.c index d57d4ee15848..f973fbca90cf 100644 --- a/drivers/pci/controller/dwc/pcie-al.c +++ b/drivers/pci/controller/dwc/pcie-al.c @@ -217,14 +217,15 @@ static inline void al_pcie_target_bus_set(struct al_pcie *pcie,  				  reg);  } -static void __iomem *al_pcie_conf_addr_map(struct al_pcie *pcie, -					   unsigned int busnr, -					   unsigned int devfn) +static void __iomem *al_pcie_conf_addr_map_bus(struct pci_bus *bus, +					       unsigned int devfn, int where)  { +	struct pcie_port *pp = bus->sysdata; +	struct al_pcie *pcie = to_al_pcie(to_dw_pcie_from_pp(pp)); +	unsigned int busnr = bus->number;  	struct al_pcie_target_bus_cfg *target_bus_cfg = &pcie->target_bus_cfg;  	unsigned int busnr_ecam = busnr & target_bus_cfg->ecam_mask;  	unsigned int busnr_reg = busnr & target_bus_cfg->reg_mask; -	struct pcie_port *pp = &pcie->pci->pp;  	void __iomem *pci_base_addr;  	pci_base_addr = (void __iomem *)((uintptr_t)pp->va_cfg0_base + @@ -240,52 +241,14 @@ static void __iomem *al_pcie_conf_addr_map(struct al_pcie *pcie,  				       target_bus_cfg->reg_mask);  	} -	return pci_base_addr; -} - -static int al_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus, -				 unsigned int devfn, int where, int size, -				 u32 *val) -{ -	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); -	struct al_pcie *pcie = to_al_pcie(pci); -	unsigned int busnr = bus->number; -	void __iomem *pci_addr; -	int rc; - -	pci_addr = al_pcie_conf_addr_map(pcie, busnr, devfn); - -	rc = dw_pcie_read(pci_addr + where, size, val); - -	dev_dbg(pci->dev, "%d-byte config read from %04x:%02x:%02x.%d offset 0x%x (pci_addr: 0x%px) - val:0x%x\n", -		size, pci_domain_nr(bus), bus->number, -		PCI_SLOT(devfn), PCI_FUNC(devfn), where, -		(pci_addr + where), *val); - -	return rc; +	return pci_base_addr + where;  } -static int al_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus, -				 unsigned int devfn, int where, int size, -				 u32 val) -{ -	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); -	struct al_pcie *pcie = to_al_pcie(pci); -	unsigned int busnr = bus->number; -	void __iomem *pci_addr; -	int rc; - -	pci_addr = al_pcie_conf_addr_map(pcie, busnr, devfn); - -	rc = dw_pcie_write(pci_addr + where, size, val); - -	dev_dbg(pci->dev, "%d-byte config write to %04x:%02x:%02x.%d offset 0x%x (pci_addr: 0x%px) - val:0x%x\n", -		size, pci_domain_nr(bus), bus->number, -		PCI_SLOT(devfn), PCI_FUNC(devfn), where, -		(pci_addr + where), val); - -	return rc; -} +static struct pci_ops al_child_pci_ops = { +	.map_bus = al_pcie_conf_addr_map_bus, +	.read = pci_generic_config_read, +	.write = pci_generic_config_write, +};  static void al_pcie_config_prepare(struct al_pcie *pcie)  { @@ -297,6 +260,7 @@ static void al_pcie_config_prepare(struct al_pcie *pcie)  	u8 secondary_bus;  	u32 cfg_control;  	u32 reg; +	struct resource *bus = resource_list_first_type(&pp->bridge->windows, IORESOURCE_BUS)->res;  	target_bus_cfg = &pcie->target_bus_cfg; @@ -310,13 +274,13 @@ static void al_pcie_config_prepare(struct al_pcie *pcie)  	target_bus_cfg->ecam_mask = ecam_bus_mask;  	/* This portion is taken from the cfg_target_bus reg */  	target_bus_cfg->reg_mask = ~target_bus_cfg->ecam_mask; -	target_bus_cfg->reg_val = pp->busn->start & target_bus_cfg->reg_mask; +	target_bus_cfg->reg_val = bus->start & target_bus_cfg->reg_mask;  	al_pcie_target_bus_set(pcie, target_bus_cfg->reg_val,  			       target_bus_cfg->reg_mask); -	secondary_bus = pp->busn->start + 1; -	subordinate_bus = pp->busn->end; +	secondary_bus = bus->start + 1; +	subordinate_bus = bus->end;  	/* Set the valid values of secondary and subordinate buses */  	cfg_control_offset = AXI_BASE_OFFSET + pcie->reg_offsets.ob_ctrl + @@ -339,6 +303,8 @@ static int al_pcie_host_init(struct pcie_port *pp)  	struct al_pcie *pcie = to_al_pcie(pci);  	int rc; +	pp->bridge->child_ops = &al_child_pci_ops; +  	rc = al_pcie_rev_id_get(pcie, &pcie->controller_rev_id);  	if (rc)  		return rc; @@ -353,8 +319,6 @@ static int al_pcie_host_init(struct pcie_port *pp)  }  static const struct dw_pcie_host_ops al_pcie_host_ops = { -	.rd_other_conf = al_pcie_rd_other_conf, -	.wr_other_conf = al_pcie_wr_other_conf,  	.host_init = al_pcie_host_init,  }; diff --git a/drivers/pci/controller/dwc/pcie-artpec6.c b/drivers/pci/controller/dwc/pcie-artpec6.c index 97d50bb50f06..929448e9e0bc 100644 --- a/drivers/pci/controller/dwc/pcie-artpec6.c +++ b/drivers/pci/controller/dwc/pcie-artpec6.c @@ -44,13 +44,6 @@ struct artpec_pcie_of_data {  static const struct of_device_id artpec6_pcie_of_match[]; -/* PCIe Port Logic registers (memory-mapped) */ -#define PL_OFFSET			0x700 - -#define ACK_F_ASPM_CTRL_OFF		(PL_OFFSET + 0xc) -#define ACK_N_FTS_MASK			GENMASK(15, 8) -#define ACK_N_FTS(x)			(((x) << 8) & ACK_N_FTS_MASK) -  /* ARTPEC-6 specific registers */  #define PCIECFG				0x18  #define  PCIECFG_DBG_OEN		BIT(24) @@ -289,30 +282,6 @@ static void artpec6_pcie_init_phy(struct artpec6_pcie *artpec6_pcie)  	}  } -static void artpec6_pcie_set_nfts(struct artpec6_pcie *artpec6_pcie) -{ -	struct dw_pcie *pci = artpec6_pcie->pci; -	u32 val; - -	if (artpec6_pcie->variant != ARTPEC7) -		return; - -	/* -	 * Increase the N_FTS (Number of Fast Training Sequences) -	 * to be transmitted when transitioning from L0s to L0. -	 */ -	val = dw_pcie_readl_dbi(pci, ACK_F_ASPM_CTRL_OFF); -	val &= ~ACK_N_FTS_MASK; -	val |= ACK_N_FTS(180); -	dw_pcie_writel_dbi(pci, ACK_F_ASPM_CTRL_OFF, val); - -	/* -	 * Set the Number of Fast Training Sequences that the core -	 * advertises as its N_FTS during Gen2 or Gen3 link training. -	 */ -	dw_pcie_link_set_n_fts(pci, 180); -} -  static void artpec6_pcie_assert_core_reset(struct artpec6_pcie *artpec6_pcie)  {  	u32 val; @@ -346,29 +315,23 @@ static void artpec6_pcie_deassert_core_reset(struct artpec6_pcie *artpec6_pcie)  	usleep_range(100, 200);  } -static void artpec6_pcie_enable_interrupts(struct artpec6_pcie *artpec6_pcie) -{ -	struct dw_pcie *pci = artpec6_pcie->pci; -	struct pcie_port *pp = &pci->pp; - -	if (IS_ENABLED(CONFIG_PCI_MSI)) -		dw_pcie_msi_init(pp); -} -  static int artpec6_pcie_host_init(struct pcie_port *pp)  {  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);  	struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci); +	if (artpec6_pcie->variant == ARTPEC7) { +		pci->n_fts[0] = 180; +		pci->n_fts[1] = 180; +	}  	artpec6_pcie_assert_core_reset(artpec6_pcie);  	artpec6_pcie_init_phy(artpec6_pcie);  	artpec6_pcie_deassert_core_reset(artpec6_pcie);  	artpec6_pcie_wait_for_phy(artpec6_pcie); -	artpec6_pcie_set_nfts(artpec6_pcie);  	dw_pcie_setup_rc(pp);  	artpec6_pcie_establish_link(pci);  	dw_pcie_wait_for_link(pci); -	artpec6_pcie_enable_interrupts(artpec6_pcie); +	dw_pcie_msi_init(pp);  	return 0;  } @@ -412,7 +375,6 @@ static void artpec6_pcie_ep_init(struct dw_pcie_ep *ep)  	artpec6_pcie_init_phy(artpec6_pcie);  	artpec6_pcie_deassert_core_reset(artpec6_pcie);  	artpec6_pcie_wait_for_phy(artpec6_pcie); -	artpec6_pcie_set_nfts(artpec6_pcie);  	for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)  		dw_pcie_ep_reset_bar(pci, bar); diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c index 305bfec2424d..ad7da4ea43a5 100644 --- a/drivers/pci/controller/dwc/pcie-designware-ep.c +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c @@ -12,6 +12,8 @@  #include <linux/pci-epc.h>  #include <linux/pci-epf.h> +#include "../../pci.h" +  void dw_pcie_ep_linkup(struct dw_pcie_ep *ep)  {  	struct pci_epc *epc = ep->epc; @@ -28,12 +30,39 @@ void dw_pcie_ep_init_notify(struct dw_pcie_ep *ep)  }  EXPORT_SYMBOL_GPL(dw_pcie_ep_init_notify); -static void __dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar, -				   int flags) +struct dw_pcie_ep_func * +dw_pcie_ep_get_func_from_ep(struct dw_pcie_ep *ep, u8 func_no) +{ +	struct dw_pcie_ep_func *ep_func; + +	list_for_each_entry(ep_func, &ep->func_list, list) { +		if (ep_func->func_no == func_no) +			return ep_func; +	} + +	return NULL; +} + +static unsigned int dw_pcie_ep_func_select(struct dw_pcie_ep *ep, u8 func_no) +{ +	unsigned int func_offset = 0; + +	if (ep->ops->func_conf_select) +		func_offset = ep->ops->func_conf_select(ep, func_no); + +	return func_offset; +} + +static void __dw_pcie_ep_reset_bar(struct dw_pcie *pci, u8 func_no, +				   enum pci_barno bar, int flags)  {  	u32 reg; +	unsigned int func_offset = 0; +	struct dw_pcie_ep *ep = &pci->ep; -	reg = PCI_BASE_ADDRESS_0 + (4 * bar); +	func_offset = dw_pcie_ep_func_select(ep, func_no); + +	reg = func_offset + PCI_BASE_ADDRESS_0 + (4 * bar);  	dw_pcie_dbi_ro_wr_en(pci);  	dw_pcie_writel_dbi2(pci, reg, 0x0);  	dw_pcie_writel_dbi(pci, reg, 0x0); @@ -46,7 +75,53 @@ static void __dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar,  void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar)  { -	__dw_pcie_ep_reset_bar(pci, bar, 0); +	u8 func_no, funcs; + +	funcs = pci->ep.epc->max_functions; + +	for (func_no = 0; func_no < funcs; func_no++) +		__dw_pcie_ep_reset_bar(pci, func_no, bar, 0); +} + +static u8 __dw_pcie_ep_find_next_cap(struct dw_pcie_ep *ep, u8 func_no, +		u8 cap_ptr, u8 cap) +{ +	struct dw_pcie *pci = to_dw_pcie_from_ep(ep); +	unsigned int func_offset = 0; +	u8 cap_id, next_cap_ptr; +	u16 reg; + +	if (!cap_ptr) +		return 0; + +	func_offset = dw_pcie_ep_func_select(ep, func_no); + +	reg = dw_pcie_readw_dbi(pci, func_offset + cap_ptr); +	cap_id = (reg & 0x00ff); + +	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(ep, func_no, next_cap_ptr, cap); +} + +static u8 dw_pcie_ep_find_capability(struct dw_pcie_ep *ep, u8 func_no, u8 cap) +{ +	struct dw_pcie *pci = to_dw_pcie_from_ep(ep); +	unsigned int func_offset = 0; +	u8 next_cap_ptr; +	u16 reg; + +	func_offset = dw_pcie_ep_func_select(ep, func_no); + +	reg = dw_pcie_readw_dbi(pci, func_offset + PCI_CAPABILITY_LIST); +	next_cap_ptr = (reg & 0x00ff); + +	return __dw_pcie_ep_find_next_cap(ep, func_no, next_cap_ptr, cap);  }  static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no, @@ -54,28 +129,31 @@ static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no,  {  	struct dw_pcie_ep *ep = epc_get_drvdata(epc);  	struct dw_pcie *pci = to_dw_pcie_from_ep(ep); +	unsigned int func_offset = 0; + +	func_offset = dw_pcie_ep_func_select(ep, func_no);  	dw_pcie_dbi_ro_wr_en(pci); -	dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, hdr->vendorid); -	dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, hdr->deviceid); -	dw_pcie_writeb_dbi(pci, PCI_REVISION_ID, hdr->revid); -	dw_pcie_writeb_dbi(pci, PCI_CLASS_PROG, hdr->progif_code); -	dw_pcie_writew_dbi(pci, PCI_CLASS_DEVICE, +	dw_pcie_writew_dbi(pci, func_offset + PCI_VENDOR_ID, hdr->vendorid); +	dw_pcie_writew_dbi(pci, func_offset + PCI_DEVICE_ID, hdr->deviceid); +	dw_pcie_writeb_dbi(pci, func_offset + PCI_REVISION_ID, hdr->revid); +	dw_pcie_writeb_dbi(pci, func_offset + PCI_CLASS_PROG, hdr->progif_code); +	dw_pcie_writew_dbi(pci, func_offset + PCI_CLASS_DEVICE,  			   hdr->subclass_code | hdr->baseclass_code << 8); -	dw_pcie_writeb_dbi(pci, PCI_CACHE_LINE_SIZE, +	dw_pcie_writeb_dbi(pci, func_offset + PCI_CACHE_LINE_SIZE,  			   hdr->cache_line_size); -	dw_pcie_writew_dbi(pci, PCI_SUBSYSTEM_VENDOR_ID, +	dw_pcie_writew_dbi(pci, func_offset + PCI_SUBSYSTEM_VENDOR_ID,  			   hdr->subsys_vendor_id); -	dw_pcie_writew_dbi(pci, PCI_SUBSYSTEM_ID, hdr->subsys_id); -	dw_pcie_writeb_dbi(pci, PCI_INTERRUPT_PIN, +	dw_pcie_writew_dbi(pci, func_offset + PCI_SUBSYSTEM_ID, hdr->subsys_id); +	dw_pcie_writeb_dbi(pci, func_offset + PCI_INTERRUPT_PIN,  			   hdr->interrupt_pin);  	dw_pcie_dbi_ro_wr_dis(pci);  	return 0;  } -static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, enum pci_barno bar, -				  dma_addr_t cpu_addr, +static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, u8 func_no, +				  enum pci_barno bar, dma_addr_t cpu_addr,  				  enum dw_pcie_as_type as_type)  {  	int ret; @@ -88,7 +166,7 @@ static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, enum pci_barno bar,  		return -EINVAL;  	} -	ret = dw_pcie_prog_inbound_atu(pci, free_win, bar, cpu_addr, +	ret = dw_pcie_prog_inbound_atu(pci, func_no, free_win, bar, cpu_addr,  				       as_type);  	if (ret < 0) {  		dev_err(pci->dev, "Failed to program IB window\n"); @@ -101,7 +179,8 @@ static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, enum pci_barno bar,  	return 0;  } -static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep, phys_addr_t phys_addr, +static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep, u8 func_no, +				   phys_addr_t phys_addr,  				   u64 pci_addr, size_t size)  {  	u32 free_win; @@ -113,8 +192,8 @@ static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep, phys_addr_t phys_addr,  		return -EINVAL;  	} -	dw_pcie_prog_outbound_atu(pci, free_win, PCIE_ATU_TYPE_MEM, -				  phys_addr, pci_addr, size); +	dw_pcie_prog_ep_outbound_atu(pci, func_no, free_win, PCIE_ATU_TYPE_MEM, +				     phys_addr, pci_addr, size);  	set_bit(free_win, ep->ob_window_map);  	ep->outbound_addr[free_win] = phys_addr; @@ -130,7 +209,7 @@ static void dw_pcie_ep_clear_bar(struct pci_epc *epc, u8 func_no,  	enum pci_barno bar = epf_bar->barno;  	u32 atu_index = ep->bar_to_atu[bar]; -	__dw_pcie_ep_reset_bar(pci, bar, epf_bar->flags); +	__dw_pcie_ep_reset_bar(pci, func_no, bar, epf_bar->flags);  	dw_pcie_disable_atu(pci, atu_index, DW_PCIE_REGION_INBOUND);  	clear_bit(atu_index, ep->ib_window_map); @@ -147,14 +226,20 @@ static int dw_pcie_ep_set_bar(struct pci_epc *epc, u8 func_no,  	size_t size = epf_bar->size;  	int flags = epf_bar->flags;  	enum dw_pcie_as_type as_type; -	u32 reg = PCI_BASE_ADDRESS_0 + (4 * bar); +	u32 reg; +	unsigned int func_offset = 0; + +	func_offset = dw_pcie_ep_func_select(ep, func_no); + +	reg = PCI_BASE_ADDRESS_0 + (4 * bar) + func_offset;  	if (!(flags & PCI_BASE_ADDRESS_SPACE))  		as_type = DW_PCIE_AS_MEM;  	else  		as_type = DW_PCIE_AS_IO; -	ret = dw_pcie_ep_inbound_atu(ep, bar, epf_bar->phys_addr, as_type); +	ret = dw_pcie_ep_inbound_atu(ep, func_no, bar, +				     epf_bar->phys_addr, as_type);  	if (ret)  		return ret; @@ -213,7 +298,7 @@ static int dw_pcie_ep_map_addr(struct pci_epc *epc, u8 func_no,  	struct dw_pcie_ep *ep = epc_get_drvdata(epc);  	struct dw_pcie *pci = to_dw_pcie_from_ep(ep); -	ret = dw_pcie_ep_outbound_atu(ep, addr, pci_addr, size); +	ret = dw_pcie_ep_outbound_atu(ep, func_no, addr, pci_addr, size);  	if (ret) {  		dev_err(pci->dev, "Failed to enable address\n");  		return ret; @@ -227,11 +312,16 @@ static int dw_pcie_ep_get_msi(struct pci_epc *epc, u8 func_no)  	struct dw_pcie_ep *ep = epc_get_drvdata(epc);  	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);  	u32 val, reg; +	unsigned int func_offset = 0; +	struct dw_pcie_ep_func *ep_func; -	if (!ep->msi_cap) +	ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no); +	if (!ep_func || !ep_func->msi_cap)  		return -EINVAL; -	reg = ep->msi_cap + PCI_MSI_FLAGS; +	func_offset = dw_pcie_ep_func_select(ep, func_no); + +	reg = ep_func->msi_cap + func_offset + PCI_MSI_FLAGS;  	val = dw_pcie_readw_dbi(pci, reg);  	if (!(val & PCI_MSI_FLAGS_ENABLE))  		return -EINVAL; @@ -246,11 +336,16 @@ static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts)  	struct dw_pcie_ep *ep = epc_get_drvdata(epc);  	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);  	u32 val, reg; +	unsigned int func_offset = 0; +	struct dw_pcie_ep_func *ep_func; -	if (!ep->msi_cap) +	ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no); +	if (!ep_func || !ep_func->msi_cap)  		return -EINVAL; -	reg = ep->msi_cap + PCI_MSI_FLAGS; +	func_offset = dw_pcie_ep_func_select(ep, func_no); + +	reg = ep_func->msi_cap + func_offset + PCI_MSI_FLAGS;  	val = dw_pcie_readw_dbi(pci, reg);  	val &= ~PCI_MSI_FLAGS_QMASK;  	val |= (interrupts << 1) & PCI_MSI_FLAGS_QMASK; @@ -266,11 +361,16 @@ static int dw_pcie_ep_get_msix(struct pci_epc *epc, u8 func_no)  	struct dw_pcie_ep *ep = epc_get_drvdata(epc);  	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);  	u32 val, reg; +	unsigned int func_offset = 0; +	struct dw_pcie_ep_func *ep_func; -	if (!ep->msix_cap) +	ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no); +	if (!ep_func || !ep_func->msix_cap)  		return -EINVAL; -	reg = ep->msix_cap + PCI_MSIX_FLAGS; +	func_offset = dw_pcie_ep_func_select(ep, func_no); + +	reg = ep_func->msix_cap + func_offset + PCI_MSIX_FLAGS;  	val = dw_pcie_readw_dbi(pci, reg);  	if (!(val & PCI_MSIX_FLAGS_ENABLE))  		return -EINVAL; @@ -286,23 +386,28 @@ static int dw_pcie_ep_set_msix(struct pci_epc *epc, u8 func_no, u16 interrupts,  	struct dw_pcie_ep *ep = epc_get_drvdata(epc);  	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);  	u32 val, reg; +	unsigned int func_offset = 0; +	struct dw_pcie_ep_func *ep_func; -	if (!ep->msix_cap) +	ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no); +	if (!ep_func || !ep_func->msix_cap)  		return -EINVAL;  	dw_pcie_dbi_ro_wr_en(pci); -	reg = ep->msix_cap + PCI_MSIX_FLAGS; +	func_offset = dw_pcie_ep_func_select(ep, func_no); + +	reg = ep_func->msix_cap + func_offset + PCI_MSIX_FLAGS;  	val = dw_pcie_readw_dbi(pci, reg);  	val &= ~PCI_MSIX_FLAGS_QSIZE;  	val |= interrupts;  	dw_pcie_writew_dbi(pci, reg, val); -	reg = ep->msix_cap + PCI_MSIX_TABLE; +	reg = ep_func->msix_cap + func_offset + PCI_MSIX_TABLE;  	val = offset | bir;  	dw_pcie_writel_dbi(pci, reg, val); -	reg = ep->msix_cap + PCI_MSIX_PBA; +	reg = ep_func->msix_cap + func_offset + PCI_MSIX_PBA;  	val = (offset + (interrupts * PCI_MSIX_ENTRY_SIZE)) | bir;  	dw_pcie_writel_dbi(pci, reg, val); @@ -385,31 +490,36 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,  			     u8 interrupt_num)  {  	struct dw_pcie *pci = to_dw_pcie_from_ep(ep); +	struct dw_pcie_ep_func *ep_func;  	struct pci_epc *epc = ep->epc;  	unsigned int aligned_offset; +	unsigned int func_offset = 0;  	u16 msg_ctrl, msg_data;  	u32 msg_addr_lower, msg_addr_upper, reg;  	u64 msg_addr;  	bool has_upper;  	int ret; -	if (!ep->msi_cap) +	ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no); +	if (!ep_func || !ep_func->msi_cap)  		return -EINVAL; +	func_offset = dw_pcie_ep_func_select(ep, func_no); +  	/* Raise MSI per the PCI Local Bus Specification Revision 3.0, 6.8.1. */ -	reg = ep->msi_cap + PCI_MSI_FLAGS; +	reg = ep_func->msi_cap + func_offset + PCI_MSI_FLAGS;  	msg_ctrl = dw_pcie_readw_dbi(pci, reg);  	has_upper = !!(msg_ctrl & PCI_MSI_FLAGS_64BIT); -	reg = ep->msi_cap + PCI_MSI_ADDRESS_LO; +	reg = ep_func->msi_cap + func_offset + PCI_MSI_ADDRESS_LO;  	msg_addr_lower = dw_pcie_readl_dbi(pci, reg);  	if (has_upper) { -		reg = ep->msi_cap + PCI_MSI_ADDRESS_HI; +		reg = ep_func->msi_cap + func_offset + PCI_MSI_ADDRESS_HI;  		msg_addr_upper = dw_pcie_readl_dbi(pci, reg); -		reg = ep->msi_cap + PCI_MSI_DATA_64; +		reg = ep_func->msi_cap + func_offset + PCI_MSI_DATA_64;  		msg_data = dw_pcie_readw_dbi(pci, reg);  	} else {  		msg_addr_upper = 0; -		reg = ep->msi_cap + PCI_MSI_DATA_32; +		reg = ep_func->msi_cap + func_offset + PCI_MSI_DATA_32;  		msg_data = dw_pcie_readw_dbi(pci, reg);  	}  	aligned_offset = msg_addr_lower & (epc->mem->window.page_size - 1); @@ -427,12 +537,33 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,  	return 0;  } +int dw_pcie_ep_raise_msix_irq_doorbell(struct dw_pcie_ep *ep, u8 func_no, +				       u16 interrupt_num) +{ +	struct dw_pcie *pci = to_dw_pcie_from_ep(ep); +	struct dw_pcie_ep_func *ep_func; +	u32 msg_data; + +	ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no); +	if (!ep_func || !ep_func->msix_cap) +		return -EINVAL; + +	msg_data = (func_no << PCIE_MSIX_DOORBELL_PF_SHIFT) | +		   (interrupt_num - 1); + +	dw_pcie_writel_dbi(pci, PCIE_MSIX_DOORBELL, msg_data); + +	return 0; +} +  int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no, -			     u16 interrupt_num) +			      u16 interrupt_num)  {  	struct dw_pcie *pci = to_dw_pcie_from_ep(ep); +	struct dw_pcie_ep_func *ep_func;  	struct pci_epf_msix_tbl *msix_tbl;  	struct pci_epc *epc = ep->epc; +	unsigned int func_offset = 0;  	u32 reg, msg_data, vec_ctrl;  	unsigned int aligned_offset;  	u32 tbl_offset; @@ -440,7 +571,13 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,  	int ret;  	u8 bir; -	reg = ep->msix_cap + PCI_MSIX_TABLE; +	ep_func = dw_pcie_ep_get_func_from_ep(ep, func_no); +	if (!ep_func || !ep_func->msix_cap) +		return -EINVAL; + +	func_offset = dw_pcie_ep_func_select(ep, func_no); + +	reg = ep_func->msix_cap + func_offset + PCI_MSIX_TABLE;  	tbl_offset = dw_pcie_readl_dbi(pci, reg);  	bir = (tbl_offset & PCI_MSIX_TABLE_BIR);  	tbl_offset &= PCI_MSIX_TABLE_OFFSET; @@ -505,7 +642,8 @@ int dw_pcie_ep_init_complete(struct dw_pcie_ep *ep)  	u32 reg;  	int i; -	hdr_type = dw_pcie_readb_dbi(pci, PCI_HEADER_TYPE); +	hdr_type = dw_pcie_readb_dbi(pci, PCI_HEADER_TYPE) & +		   PCI_HEADER_TYPE_MASK;  	if (hdr_type != PCI_HEADER_TYPE_NORMAL) {  		dev_err(pci->dev,  			"PCIe controller is not set to EP mode (hdr_type:0x%x)!\n", @@ -513,23 +651,21 @@ int dw_pcie_ep_init_complete(struct dw_pcie_ep *ep)  		return -EIO;  	} -	ep->msi_cap = dw_pcie_find_capability(pci, PCI_CAP_ID_MSI); +	offset = dw_pcie_ep_find_ext_capability(pci, PCI_EXT_CAP_ID_REBAR); -	ep->msix_cap = dw_pcie_find_capability(pci, PCI_CAP_ID_MSIX); +	dw_pcie_dbi_ro_wr_en(pci); -	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); +	dw_pcie_dbi_ro_wr_dis(pci);  	return 0;  } @@ -539,11 +675,15 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)  {  	int ret;  	void *addr; +	u8 func_no;  	struct pci_epc *epc;  	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);  	struct device *dev = pci->dev;  	struct device_node *np = dev->of_node;  	const struct pci_epc_features *epc_features; +	struct dw_pcie_ep_func *ep_func; + +	INIT_LIST_HEAD(&ep->func_list);  	if (!pci->dbi_base || !pci->dbi_base2) {  		dev_err(dev, "dbi_base/dbi_base2 is not populated\n"); @@ -590,6 +730,9 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)  		return -ENOMEM;  	ep->outbound_addr = addr; +	if (pci->link_gen < 1) +		pci->link_gen = of_pci_get_max_link_speed(np); +  	epc = devm_pci_epc_create(dev, &epc_ops);  	if (IS_ERR(epc)) {  		dev_err(dev, "Failed to create epc device\n"); @@ -599,13 +742,27 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)  	ep->epc = epc;  	epc_set_drvdata(epc, ep); -	if (ep->ops->ep_init) -		ep->ops->ep_init(ep); -  	ret = of_property_read_u8(np, "max-functions", &epc->max_functions);  	if (ret < 0)  		epc->max_functions = 1; +	for (func_no = 0; func_no < epc->max_functions; func_no++) { +		ep_func = devm_kzalloc(dev, sizeof(*ep_func), GFP_KERNEL); +		if (!ep_func) +			return -ENOMEM; + +		ep_func->func_no = func_no; +		ep_func->msi_cap = dw_pcie_ep_find_capability(ep, func_no, +							      PCI_CAP_ID_MSI); +		ep_func->msix_cap = dw_pcie_ep_find_capability(ep, func_no, +							       PCI_CAP_ID_MSIX); + +		list_add_tail(&ep_func->list, &ep->func_list); +	} + +	if (ep->ops->ep_init) +		ep->ops->ep_init(ep); +  	ret = pci_epc_mem_init(epc, ep->phys_base, ep->addr_size,  			       ep->page_size);  	if (ret < 0) { diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c index 9dafecba347f..674f32db85ca 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -20,30 +20,7 @@  #include "pcie-designware.h"  static struct pci_ops dw_pcie_ops; - -static int dw_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, -			       u32 *val) -{ -	struct dw_pcie *pci; - -	if (pp->ops->rd_own_conf) -		return pp->ops->rd_own_conf(pp, where, size, val); - -	pci = to_dw_pcie_from_pp(pp); -	return dw_pcie_read(pci->dbi_base + where, size, val); -} - -static int dw_pcie_wr_own_conf(struct pcie_port *pp, int where, int size, -			       u32 val) -{ -	struct dw_pcie *pci; - -	if (pp->ops->wr_own_conf) -		return pp->ops->wr_own_conf(pp, where, size, val); - -	pci = to_dw_pcie_from_pp(pp); -	return dw_pcie_write(pci->dbi_base + where, size, val); -} +static struct pci_ops dw_child_pcie_ops;  static void dw_msi_ack_irq(struct irq_data *d)  { @@ -82,13 +59,13 @@ irqreturn_t dw_handle_msi_irq(struct pcie_port *pp)  	unsigned long val;  	u32 status, num_ctrls;  	irqreturn_t ret = IRQ_NONE; +	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);  	num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL;  	for (i = 0; i < num_ctrls; i++) { -		dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_STATUS + -					(i * MSI_REG_CTRL_BLOCK_SIZE), -				    4, &status); +		status = dw_pcie_readl_dbi(pci, PCIE_MSI_INTR0_STATUS + +					   (i * MSI_REG_CTRL_BLOCK_SIZE));  		if (!status)  			continue; @@ -148,6 +125,7 @@ static int dw_pci_msi_set_affinity(struct irq_data *d,  static void dw_pci_bottom_mask(struct irq_data *d)  {  	struct pcie_port *pp = irq_data_get_irq_chip_data(d); +	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);  	unsigned int res, bit, ctrl;  	unsigned long flags; @@ -158,8 +136,7 @@ static void dw_pci_bottom_mask(struct irq_data *d)  	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]); +	dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_MASK + res, pp->irq_mask[ctrl]);  	raw_spin_unlock_irqrestore(&pp->lock, flags);  } @@ -167,6 +144,7 @@ static void dw_pci_bottom_mask(struct irq_data *d)  static void dw_pci_bottom_unmask(struct irq_data *d)  {  	struct pcie_port *pp = irq_data_get_irq_chip_data(d); +	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);  	unsigned int res, bit, ctrl;  	unsigned long flags; @@ -177,8 +155,7 @@ static void dw_pci_bottom_unmask(struct irq_data *d)  	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]); +	dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_MASK + res, pp->irq_mask[ctrl]);  	raw_spin_unlock_irqrestore(&pp->lock, flags);  } @@ -186,13 +163,14 @@ static void dw_pci_bottom_unmask(struct irq_data *d)  static void dw_pci_bottom_ack(struct irq_data *d)  {  	struct pcie_port *pp  = irq_data_get_irq_chip_data(d); +	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);  	unsigned int res, bit, ctrl;  	ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL;  	res = ctrl * MSI_REG_CTRL_BLOCK_SIZE;  	bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL; -	dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_STATUS + res, 4, BIT(bit)); +	dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_STATUS + res, BIT(bit));  }  static struct irq_chip dw_pci_msi_bottom_irq_chip = { @@ -288,32 +266,26 @@ void dw_pcie_free_msi(struct pcie_port *pp)  	irq_domain_remove(pp->msi_domain);  	irq_domain_remove(pp->irq_domain); -	if (pp->msi_page) -		__free_page(pp->msi_page); +	if (pp->msi_data) { +		struct dw_pcie *pci = to_dw_pcie_from_pp(pp); +		struct device *dev = pci->dev; + +		dma_unmap_single_attrs(dev, pp->msi_data, sizeof(pp->msi_msg), +				       DMA_FROM_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); +	}  }  void dw_pcie_msi_init(struct pcie_port *pp)  {  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); -	struct device *dev = pci->dev; -	u64 msi_target; +	u64 msi_target = (u64)pp->msi_data; -	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(pp->msi_page); -		pp->msi_page = NULL; +	if (!IS_ENABLED(CONFIG_PCI_MSI))  		return; -	} -	msi_target = (u64)pp->msi_data;  	/* Program the msi_data */ -	dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_LO, 4, -			    lower_32_bits(msi_target)); -	dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_HI, 4, -			    upper_32_bits(msi_target)); +	dw_pcie_writel_dbi(pci, PCIE_MSI_ADDR_LO, lower_32_bits(msi_target)); +	dw_pcie_writel_dbi(pci, PCIE_MSI_ADDR_HI, upper_32_bits(msi_target));  }  EXPORT_SYMBOL_GPL(dw_pcie_msi_init); @@ -324,20 +296,16 @@ 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; -	struct pci_bus *child;  	struct pci_host_bridge *bridge;  	struct resource *cfg_res; -	u32 hdr_type;  	int ret;  	raw_spin_lock_init(&pci->pp.lock);  	cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");  	if (cfg_res) { -		pp->cfg0_size = resource_size(cfg_res) >> 1; -		pp->cfg1_size = resource_size(cfg_res) >> 1; +		pp->cfg0_size = resource_size(cfg_res);  		pp->cfg0_base = cfg_res->start; -		pp->cfg1_base = cfg_res->start + pp->cfg0_size;  	} else if (!pp->va_cfg0_base) {  		dev_err(dev, "Missing *config* reg space\n");  	} @@ -346,47 +314,33 @@ int dw_pcie_host_init(struct pcie_port *pp)  	if (!bridge)  		return -ENOMEM; +	pp->bridge = bridge; +  	/* Get the I/O and memory ranges from DT */  	resource_list_for_each_entry(win, &bridge->windows) {  		switch (resource_type(win->res)) {  		case IORESOURCE_IO: -			pp->io = win->res; -			pp->io->name = "I/O"; -			pp->io_size = resource_size(pp->io); -			pp->io_bus_addr = pp->io->start - win->offset; -			pp->io_base = pci_pio_to_address(pp->io->start); -			break; -		case IORESOURCE_MEM: -			pp->mem = win->res; -			pp->mem->name = "MEM"; -			pp->mem_size = resource_size(pp->mem); -			pp->mem_bus_addr = pp->mem->start - win->offset; +			pp->io_size = resource_size(win->res); +			pp->io_bus_addr = win->res->start - win->offset; +			pp->io_base = pci_pio_to_address(win->res->start);  			break;  		case 0: -			pp->cfg = win->res; -			pp->cfg0_size = resource_size(pp->cfg) >> 1; -			pp->cfg1_size = resource_size(pp->cfg) >> 1; -			pp->cfg0_base = pp->cfg->start; -			pp->cfg1_base = pp->cfg->start + pp->cfg0_size; -			break; -		case IORESOURCE_BUS: -			pp->busn = win->res; +			dev_err(dev, "Missing *config* reg space\n"); +			pp->cfg0_size = resource_size(win->res); +			pp->cfg0_base = win->res->start; +			if (!pci->dbi_base) { +				pci->dbi_base = devm_pci_remap_cfgspace(dev, +								pp->cfg0_base, +								pp->cfg0_size); +				if (!pci->dbi_base) { +					dev_err(dev, "Error with ioremap\n"); +					return -ENOMEM; +				} +			}  			break;  		}  	} -	if (!pci->dbi_base) { -		pci->dbi_base = devm_pci_remap_cfgspace(dev, -						pp->cfg->start, -						resource_size(pp->cfg)); -		if (!pci->dbi_base) { -			dev_err(dev, "Error with ioremap\n"); -			return -ENOMEM; -		} -	} - -	pp->mem_base = pp->mem->start; -  	if (!pp->va_cfg0_base) {  		pp->va_cfg0_base = devm_pci_remap_cfgspace(dev,  					pp->cfg0_base, pp->cfg0_size); @@ -396,20 +350,13 @@ int dw_pcie_host_init(struct pcie_port *pp)  		}  	} -	if (!pp->va_cfg1_base) { -		pp->va_cfg1_base = devm_pci_remap_cfgspace(dev, -						pp->cfg1_base, -						pp->cfg1_size); -		if (!pp->va_cfg1_base) { -			dev_err(dev, "Error with ioremap\n"); -			return -ENOMEM; -		} -	} -  	ret = of_property_read_u32(np, "num-viewport", &pci->num_viewport);  	if (ret)  		pci->num_viewport = 2; +	if (pci->link_gen < 1) +		pci->link_gen = of_pci_get_max_link_speed(np); +  	if (pci_msi_enabled()) {  		/*  		 * If a specific SoC driver needs to change the @@ -440,6 +387,16 @@ int dw_pcie_host_init(struct pcie_port *pp)  				irq_set_chained_handler_and_data(pp->msi_irq,  							    dw_chained_msi_isr,  							    pp); + +			pp->msi_data = dma_map_single_attrs(pci->dev, &pp->msi_msg, +						      sizeof(pp->msi_msg), +						      DMA_FROM_DEVICE, +						      DMA_ATTR_SKIP_CPU_SYNC); +			if (dma_mapping_error(pci->dev, pp->msi_data)) { +				dev_err(pci->dev, "Failed to map MSI data\n"); +				pp->msi_data = 0; +				goto err_free_msi; +			}  		} else {  			ret = pp->ops->msi_host_init(pp);  			if (ret < 0) @@ -447,47 +404,21 @@ int dw_pcie_host_init(struct pcie_port *pp)  		}  	} +	/* Set default bus ops */ +	bridge->ops = &dw_pcie_ops; +	bridge->child_ops = &dw_child_pcie_ops; +  	if (pp->ops->host_init) {  		ret = pp->ops->host_init(pp);  		if (ret)  			goto err_free_msi;  	} -	ret = dw_pcie_rd_own_conf(pp, PCI_HEADER_TYPE, 1, &hdr_type); -	if (ret != PCIBIOS_SUCCESSFUL) { -		dev_err(pci->dev, "Failed reading PCI_HEADER_TYPE cfg space reg (ret: 0x%x)\n", -			ret); -		ret = pcibios_err_to_errno(ret); -		goto err_free_msi; -	} -	if (hdr_type != PCI_HEADER_TYPE_BRIDGE) { -		dev_err(pci->dev, -			"PCIe controller is not set to bridge type (hdr_type: 0x%x)!\n", -			hdr_type); -		ret = -EIO; -		goto err_free_msi; -	} -  	bridge->sysdata = pp; -	bridge->ops = &dw_pcie_ops; - -	ret = pci_scan_root_bus_bridge(bridge); -	if (ret) -		goto err_free_msi; - -	pp->root_bus = bridge->bus; - -	if (pp->ops->scan_bus) -		pp->ops->scan_bus(pp); -	pci_bus_size_bridges(pp->root_bus); -	pci_bus_assign_resources(pp->root_bus); - -	list_for_each_entry(child, &pp->root_bus->children, node) -		pcie_bus_configure_settings(child); - -	pci_bus_add_devices(pp->root_bus); -	return 0; +	ret = pci_host_probe(bridge); +	if (!ret) +		return 0;  err_free_msi:  	if (pci_msi_enabled() && !pp->ops->msi_host_init) @@ -498,125 +429,104 @@ EXPORT_SYMBOL_GPL(dw_pcie_host_init);  void dw_pcie_host_deinit(struct pcie_port *pp)  { -	pci_stop_root_bus(pp->root_bus); -	pci_remove_root_bus(pp->root_bus); +	pci_stop_root_bus(pp->bridge->bus); +	pci_remove_root_bus(pp->bridge->bus);  	if (pci_msi_enabled() && !pp->ops->msi_host_init)  		dw_pcie_free_msi(pp);  }  EXPORT_SYMBOL_GPL(dw_pcie_host_deinit); -static int dw_pcie_access_other_conf(struct pcie_port *pp, struct pci_bus *bus, -				     u32 devfn, int where, int size, u32 *val, -				     bool write) +static void __iomem *dw_pcie_other_conf_map_bus(struct pci_bus *bus, +						unsigned int devfn, int where)  { -	int ret, type; -	u32 busdev, cfg_size; -	u64 cpu_addr; -	void __iomem *va_cfg_base; +	int type; +	u32 busdev; +	struct pcie_port *pp = bus->sysdata;  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); +	/* +	 * Checking whether the link is up here is a last line of defense +	 * against platforms that forward errors on the system bus as +	 * SError upon PCI configuration transactions issued when the link +	 * is down. This check is racy by definition and does not stop +	 * the system from triggering an SError if the link goes down +	 * after this check is performed. +	 */ +	if (!dw_pcie_link_up(pci)) +		return NULL; +  	busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) |  		 PCIE_ATU_FUNC(PCI_FUNC(devfn)); -	if (pci_is_root_bus(bus->parent)) { +	if (pci_is_root_bus(bus->parent))  		type = PCIE_ATU_TYPE_CFG0; -		cpu_addr = pp->cfg0_base; -		cfg_size = pp->cfg0_size; -		va_cfg_base = pp->va_cfg0_base; -	} else { -		type = PCIE_ATU_TYPE_CFG1; -		cpu_addr = pp->cfg1_base; -		cfg_size = pp->cfg1_size; -		va_cfg_base = pp->va_cfg1_base; -	} - -	dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX1, -				  type, cpu_addr, -				  busdev, cfg_size); -	if (write) -		ret = dw_pcie_write(va_cfg_base + where, size, *val);  	else -		ret = dw_pcie_read(va_cfg_base + where, size, val); - -	if (pci->num_viewport <= 2) -		dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX1, -					  PCIE_ATU_TYPE_IO, pp->io_base, -					  pp->io_bus_addr, pp->io_size); - -	return ret; -} - -static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus, -				 u32 devfn, int where, int size, u32 *val) -{ -	if (pp->ops->rd_other_conf) -		return pp->ops->rd_other_conf(pp, bus, devfn, where, -					      size, val); +		type = PCIE_ATU_TYPE_CFG1; -	return dw_pcie_access_other_conf(pp, bus, devfn, where, size, val, -					 false); -} -static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus, -				 u32 devfn, int where, int size, u32 val) -{ -	if (pp->ops->wr_other_conf) -		return pp->ops->wr_other_conf(pp, bus, devfn, where, -					      size, val); +	dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX1, +				  type, pp->cfg0_base, +				  busdev, pp->cfg0_size); -	return dw_pcie_access_other_conf(pp, bus, devfn, where, size, &val, -					 true); +	return pp->va_cfg0_base + where;  } -static int dw_pcie_valid_device(struct pcie_port *pp, struct pci_bus *bus, -				int dev) +static int dw_pcie_rd_other_conf(struct pci_bus *bus, unsigned int devfn, +				 int where, int size, u32 *val)  { +	int ret; +	struct pcie_port *pp = bus->sysdata;  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); -	/* If there is no link, then there is no device */ -	if (!pci_is_root_bus(bus)) { -		if (!dw_pcie_link_up(pci)) -			return 0; -	} else if (dev > 0) -		/* Access only one slot on each root port */ -		return 0; +	ret = pci_generic_config_read(bus, devfn, where, size, val); -	return 1; +	if (!ret && pci->num_viewport <= 2) +		dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX1, +					  PCIE_ATU_TYPE_IO, pp->io_base, +					  pp->io_bus_addr, pp->io_size); + +	return ret;  } -static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, -			   int size, u32 *val) +static int dw_pcie_wr_other_conf(struct pci_bus *bus, unsigned int devfn, +				 int where, int size, u32 val)  { +	int ret;  	struct pcie_port *pp = bus->sysdata; +	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); -	if (!dw_pcie_valid_device(pp, bus, PCI_SLOT(devfn))) { -		*val = 0xffffffff; -		return PCIBIOS_DEVICE_NOT_FOUND; -	} +	ret = pci_generic_config_write(bus, devfn, where, size, val); -	if (pci_is_root_bus(bus)) -		return dw_pcie_rd_own_conf(pp, where, size, val); +	if (!ret && pci->num_viewport <= 2) +		dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX1, +					  PCIE_ATU_TYPE_IO, pp->io_base, +					  pp->io_bus_addr, pp->io_size); -	return dw_pcie_rd_other_conf(pp, bus, devfn, where, size, val); +	return ret;  } -static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn, -			   int where, int size, u32 val) +static struct pci_ops dw_child_pcie_ops = { +	.map_bus = dw_pcie_other_conf_map_bus, +	.read = dw_pcie_rd_other_conf, +	.write = dw_pcie_wr_other_conf, +}; + +void __iomem *dw_pcie_own_conf_map_bus(struct pci_bus *bus, unsigned int devfn, int where)  {  	struct pcie_port *pp = bus->sysdata; +	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); -	if (!dw_pcie_valid_device(pp, bus, PCI_SLOT(devfn))) -		return PCIBIOS_DEVICE_NOT_FOUND; - -	if (pci_is_root_bus(bus)) -		return dw_pcie_wr_own_conf(pp, where, size, val); +	if (PCI_SLOT(devfn) > 0) +		return NULL; -	return dw_pcie_wr_other_conf(pp, bus, devfn, where, size, val); +	return pci->dbi_base + where;  } +EXPORT_SYMBOL_GPL(dw_pcie_own_conf_map_bus);  static struct pci_ops dw_pcie_ops = { -	.read = dw_pcie_rd_conf, -	.write = dw_pcie_wr_conf, +	.map_bus = dw_pcie_own_conf_map_bus, +	.read = pci_generic_config_read, +	.write = pci_generic_config_write,  };  void dw_pcie_setup_rc(struct pcie_port *pp) @@ -632,18 +542,18 @@ void dw_pcie_setup_rc(struct pcie_port *pp)  	dw_pcie_setup(pci); -	if (!pp->ops->msi_host_init) { +	if (pci_msi_enabled() && !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 + +			dw_pcie_writel_dbi(pci, 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 + +					    pp->irq_mask[ctrl]); +			dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_ENABLE +  					    (ctrl * MSI_REG_CTRL_BLOCK_SIZE), -					    4, ~0); +					    ~0);  		}  	} @@ -671,28 +581,32 @@ void dw_pcie_setup_rc(struct pcie_port *pp)  	dw_pcie_writel_dbi(pci, PCI_COMMAND, val);  	/* -	 * If the platform provides ->rd_other_conf, it means the platform -	 * uses its own address translation component rather than ATU, so -	 * we should not program the ATU here. +	 * If the platform provides its own child bus config accesses, it means +	 * the platform uses its own address translation component rather than +	 * ATU, so we should not program the ATU here.  	 */ -	if (!pp->ops->rd_other_conf) { +	if (pp->bridge->child_ops == &dw_child_pcie_ops) { +		struct resource_entry *entry = +			resource_list_first_type(&pp->bridge->windows, IORESOURCE_MEM); +  		dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX0, -					  PCIE_ATU_TYPE_MEM, pp->mem_base, -					  pp->mem_bus_addr, pp->mem_size); +					  PCIE_ATU_TYPE_MEM, entry->res->start, +					  entry->res->start - entry->offset, +					  resource_size(entry->res));  		if (pci->num_viewport > 2)  			dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX2,  						  PCIE_ATU_TYPE_IO, pp->io_base,  						  pp->io_bus_addr, pp->io_size);  	} -	dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0); +	dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0);  	/* Program correct class for RC */ -	dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2, PCI_CLASS_BRIDGE_PCI); +	dw_pcie_writew_dbi(pci, PCI_CLASS_DEVICE, PCI_CLASS_BRIDGE_PCI); -	dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val); +	val = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL);  	val |= PORT_LOGIC_SPEED_CHANGE; -	dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val); +	dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, val);  	dw_pcie_dbi_ro_wr_dis(pci);  } diff --git a/drivers/pci/controller/dwc/pcie-designware-plat.c b/drivers/pci/controller/dwc/pcie-designware-plat.c index 712456f6ce36..e3e300669ed5 100644 --- a/drivers/pci/controller/dwc/pcie-designware-plat.c +++ b/drivers/pci/controller/dwc/pcie-designware-plat.c @@ -39,9 +39,7 @@ static int dw_plat_pcie_host_init(struct pcie_port *pp)  	dw_pcie_setup_rc(pp);  	dw_pcie_wait_for_link(pci); - -	if (IS_ENABLED(CONFIG_PCI_MSI)) -		dw_pcie_msi_init(pp); +	dw_pcie_msi_init(pp);  	return 0;  } diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c index b723e0cc41fb..c2dea8fc97c8 100644 --- a/drivers/pci/controller/dwc/pcie-designware.c +++ b/drivers/pci/controller/dwc/pcie-designware.c @@ -10,6 +10,7 @@  #include <linux/delay.h>  #include <linux/of.h> +#include <linux/of_platform.h>  #include <linux/types.h>  #include "../../pci.h" @@ -166,21 +167,6 @@ void dw_pcie_write_dbi(struct dw_pcie *pci, u32 reg, size_t size, u32 val)  }  EXPORT_SYMBOL_GPL(dw_pcie_write_dbi); -u32 dw_pcie_read_dbi2(struct dw_pcie *pci, u32 reg, size_t size) -{ -	int ret; -	u32 val; - -	if (pci->ops->read_dbi2) -		return pci->ops->read_dbi2(pci, pci->dbi_base2, reg, size); - -	ret = dw_pcie_read(pci->dbi_base2 + 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, u32 reg, size_t size, u32 val)  {  	int ret; @@ -195,31 +181,31 @@ void dw_pcie_write_dbi2(struct dw_pcie *pci, u32 reg, size_t size, u32 val)  		dev_err(pci->dev, "write DBI address failed\n");  } -u32 dw_pcie_read_atu(struct dw_pcie *pci, u32 reg, size_t size) +static u32 dw_pcie_readl_atu(struct dw_pcie *pci, u32 reg)  {  	int ret;  	u32 val;  	if (pci->ops->read_dbi) -		return pci->ops->read_dbi(pci, pci->atu_base, reg, size); +		return pci->ops->read_dbi(pci, pci->atu_base, reg, 4); -	ret = dw_pcie_read(pci->atu_base + reg, size, &val); +	ret = dw_pcie_read(pci->atu_base + reg, 4, &val);  	if (ret)  		dev_err(pci->dev, "Read ATU address failed\n");  	return val;  } -void dw_pcie_write_atu(struct dw_pcie *pci, u32 reg, size_t size, u32 val) +static void dw_pcie_writel_atu(struct dw_pcie *pci, u32 reg, u32 val)  {  	int ret;  	if (pci->ops->write_dbi) { -		pci->ops->write_dbi(pci, pci->atu_base, reg, size, val); +		pci->ops->write_dbi(pci, pci->atu_base, reg, 4, val);  		return;  	} -	ret = dw_pcie_write(pci->atu_base + reg, size, val); +	ret = dw_pcie_write(pci->atu_base + reg, 4, val);  	if (ret)  		dev_err(pci->dev, "Write ATU address failed\n");  } @@ -239,9 +225,10 @@ static void dw_pcie_writel_ob_unroll(struct dw_pcie *pci, u32 index, u32 reg,  	dw_pcie_writel_atu(pci, offset + reg, val);  } -static void dw_pcie_prog_outbound_atu_unroll(struct dw_pcie *pci, int index, -					     int type, u64 cpu_addr, -					     u64 pci_addr, u32 size) +static void dw_pcie_prog_outbound_atu_unroll(struct dw_pcie *pci, u8 func_no, +					     int index, int type, +					     u64 cpu_addr, u64 pci_addr, +					     u32 size)  {  	u32 retries, val;  	u64 limit_addr = cpu_addr + size - 1; @@ -259,7 +246,7 @@ static void dw_pcie_prog_outbound_atu_unroll(struct dw_pcie *pci, int index,  	dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_TARGET,  				 upper_32_bits(pci_addr));  	dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1, -				 type); +				 type | PCIE_ATU_FUNC_NUM(func_no));  	dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2,  				 PCIE_ATU_ENABLE); @@ -278,8 +265,9 @@ static void dw_pcie_prog_outbound_atu_unroll(struct dw_pcie *pci, int index,  	dev_err(pci->dev, "Outbound iATU is not being enabled\n");  } -void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type, -			       u64 cpu_addr, u64 pci_addr, u32 size) +static void __dw_pcie_prog_outbound_atu(struct dw_pcie *pci, u8 func_no, +					int index, int type, u64 cpu_addr, +					u64 pci_addr, u32 size)  {  	u32 retries, val; @@ -287,8 +275,8 @@ void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type,  		cpu_addr = pci->ops->cpu_addr_fixup(pci, cpu_addr);  	if (pci->iatu_unroll_enabled) { -		dw_pcie_prog_outbound_atu_unroll(pci, index, type, cpu_addr, -						 pci_addr, size); +		dw_pcie_prog_outbound_atu_unroll(pci, func_no, index, type, +						 cpu_addr, pci_addr, size);  		return;  	} @@ -304,7 +292,8 @@ void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type,  			   lower_32_bits(pci_addr));  	dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_TARGET,  			   upper_32_bits(pci_addr)); -	dw_pcie_writel_dbi(pci, PCIE_ATU_CR1, type); +	dw_pcie_writel_dbi(pci, PCIE_ATU_CR1, type | +			   PCIE_ATU_FUNC_NUM(func_no));  	dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, PCIE_ATU_ENABLE);  	/* @@ -321,6 +310,21 @@ void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type,  	dev_err(pci->dev, "Outbound iATU is not being enabled\n");  } +void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type, +			       u64 cpu_addr, u64 pci_addr, u32 size) +{ +	__dw_pcie_prog_outbound_atu(pci, 0, index, type, +				    cpu_addr, pci_addr, size); +} + +void dw_pcie_prog_ep_outbound_atu(struct dw_pcie *pci, u8 func_no, int index, +				  int type, u64 cpu_addr, u64 pci_addr, +				  u32 size) +{ +	__dw_pcie_prog_outbound_atu(pci, func_no, index, type, +				    cpu_addr, pci_addr, size); +} +  static u32 dw_pcie_readl_ib_unroll(struct dw_pcie *pci, u32 index, u32 reg)  {  	u32 offset = PCIE_GET_ATU_INB_UNR_REG_OFFSET(index); @@ -336,8 +340,8 @@ static void dw_pcie_writel_ib_unroll(struct dw_pcie *pci, u32 index, u32 reg,  	dw_pcie_writel_atu(pci, offset + reg, val);  } -static int dw_pcie_prog_inbound_atu_unroll(struct dw_pcie *pci, int index, -					   int bar, u64 cpu_addr, +static int dw_pcie_prog_inbound_atu_unroll(struct dw_pcie *pci, u8 func_no, +					   int index, int bar, u64 cpu_addr,  					   enum dw_pcie_as_type as_type)  {  	int type; @@ -359,8 +363,10 @@ static int dw_pcie_prog_inbound_atu_unroll(struct dw_pcie *pci, int index,  		return -EINVAL;  	} -	dw_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1, type); +	dw_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1, type | +				 PCIE_ATU_FUNC_NUM(func_no));  	dw_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2, +				 PCIE_ATU_FUNC_NUM_MATCH_EN |  				 PCIE_ATU_ENABLE |  				 PCIE_ATU_BAR_MODE_ENABLE | (bar << 8)); @@ -381,14 +387,15 @@ static int dw_pcie_prog_inbound_atu_unroll(struct dw_pcie *pci, int index,  	return -EBUSY;  } -int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int bar, -			     u64 cpu_addr, enum dw_pcie_as_type as_type) +int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, u8 func_no, int index, +			     int bar, u64 cpu_addr, +			     enum dw_pcie_as_type as_type)  {  	int type;  	u32 retries, val;  	if (pci->iatu_unroll_enabled) -		return dw_pcie_prog_inbound_atu_unroll(pci, index, bar, +		return dw_pcie_prog_inbound_atu_unroll(pci, func_no, index, bar,  						       cpu_addr, as_type);  	dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT, PCIE_ATU_REGION_INBOUND | @@ -407,9 +414,11 @@ int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int bar,  		return -EINVAL;  	} -	dw_pcie_writel_dbi(pci, PCIE_ATU_CR1, type); -	dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, PCIE_ATU_ENABLE -			   | PCIE_ATU_BAR_MODE_ENABLE | (bar << 8)); +	dw_pcie_writel_dbi(pci, PCIE_ATU_CR1, type | +			   PCIE_ATU_FUNC_NUM(func_no)); +	dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, PCIE_ATU_ENABLE | +			   PCIE_ATU_FUNC_NUM_MATCH_EN | +			   PCIE_ATU_BAR_MODE_ENABLE | (bar << 8));  	/*  	 * Make sure ATU enable takes effect before any subsequent config @@ -444,7 +453,7 @@ void dw_pcie_disable_atu(struct dw_pcie *pci, int index,  	}  	dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT, region | index); -	dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, (u32)~PCIE_ATU_ENABLE); +	dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, ~(u32)PCIE_ATU_ENABLE);  }  int dw_pcie_wait_for_link(struct dw_pcie *pci) @@ -488,50 +497,41 @@ void dw_pcie_upconfig_setup(struct dw_pcie *pci)  }  EXPORT_SYMBOL_GPL(dw_pcie_upconfig_setup); -void dw_pcie_link_set_max_speed(struct dw_pcie *pci, u32 link_gen) +static void dw_pcie_link_set_max_speed(struct dw_pcie *pci, u32 link_gen)  { -	u32 reg, val; +	u32 cap, ctrl2, link_speed;  	u8 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); -	reg = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCTL2); -	reg &= ~PCI_EXP_LNKCTL2_TLS; +	cap = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP); +	ctrl2 = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCTL2); +	ctrl2 &= ~PCI_EXP_LNKCTL2_TLS;  	switch (pcie_link_speed[link_gen]) {  	case PCIE_SPEED_2_5GT: -		reg |= PCI_EXP_LNKCTL2_TLS_2_5GT; +		link_speed = PCI_EXP_LNKCTL2_TLS_2_5GT;  		break;  	case PCIE_SPEED_5_0GT: -		reg |= PCI_EXP_LNKCTL2_TLS_5_0GT; +		link_speed = PCI_EXP_LNKCTL2_TLS_5_0GT;  		break;  	case PCIE_SPEED_8_0GT: -		reg |= PCI_EXP_LNKCTL2_TLS_8_0GT; +		link_speed = PCI_EXP_LNKCTL2_TLS_8_0GT;  		break;  	case PCIE_SPEED_16_0GT: -		reg |= PCI_EXP_LNKCTL2_TLS_16_0GT; +		link_speed = PCI_EXP_LNKCTL2_TLS_16_0GT;  		break;  	default:  		/* Use hardware capability */ -		val = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP); -		val = FIELD_GET(PCI_EXP_LNKCAP_SLS, val); -		reg &= ~PCI_EXP_LNKCTL2_HASD; -		reg |= FIELD_PREP(PCI_EXP_LNKCTL2_TLS, val); +		link_speed = FIELD_GET(PCI_EXP_LNKCAP_SLS, cap); +		ctrl2 &= ~PCI_EXP_LNKCTL2_HASD;  		break;  	} -	dw_pcie_writel_dbi(pci, offset + PCI_EXP_LNKCTL2, reg); -} -EXPORT_SYMBOL_GPL(dw_pcie_link_set_max_speed); +	dw_pcie_writel_dbi(pci, offset + PCI_EXP_LNKCTL2, ctrl2 | link_speed); -void dw_pcie_link_set_n_fts(struct dw_pcie *pci, u32 n_fts) -{ -	u32 val; +	cap &= ~((u32)PCI_EXP_LNKCAP_SLS); +	dw_pcie_writel_dbi(pci, offset + PCI_EXP_LNKCAP, cap | link_speed); -	val = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL); -	val &= ~PORT_LOGIC_N_FTS_MASK; -	val |= n_fts & PORT_LOGIC_N_FTS_MASK; -	dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, val);  } -EXPORT_SYMBOL_GPL(dw_pcie_link_set_n_fts);  static u8 dw_pcie_iatu_unroll_enabled(struct dw_pcie *pci)  { @@ -546,32 +546,58 @@ static u8 dw_pcie_iatu_unroll_enabled(struct dw_pcie *pci)  void dw_pcie_setup(struct dw_pcie *pci)  { -	int ret;  	u32 val; -	u32 lanes;  	struct device *dev = pci->dev;  	struct device_node *np = dev->of_node; +	struct platform_device *pdev = to_platform_device(dev);  	if (pci->version >= 0x480A || (!pci->version &&  				       dw_pcie_iatu_unroll_enabled(pci))) {  		pci->iatu_unroll_enabled = true;  		if (!pci->atu_base) +			pci->atu_base = +			    devm_platform_ioremap_resource_byname(pdev, "atu"); +		if (IS_ERR(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"); +	if (pci->link_gen > 0) +		dw_pcie_link_set_max_speed(pci, pci->link_gen); -	ret = of_property_read_u32(np, "num-lanes", &lanes); -	if (ret) { -		dev_dbg(pci->dev, "property num-lanes isn't found\n"); +	/* Configure Gen1 N_FTS */ +	if (pci->n_fts[0]) { +		val = dw_pcie_readl_dbi(pci, PCIE_PORT_AFR); +		val &= ~(PORT_AFR_N_FTS_MASK | PORT_AFR_CC_N_FTS_MASK); +		val |= PORT_AFR_N_FTS(pci->n_fts[0]); +		val |= PORT_AFR_CC_N_FTS(pci->n_fts[0]); +		dw_pcie_writel_dbi(pci, PCIE_PORT_AFR, val); +	} + +	/* Configure Gen2+ N_FTS */ +	if (pci->n_fts[1]) { +		val = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL); +		val &= ~PORT_LOGIC_N_FTS_MASK; +		val |= pci->n_fts[pci->link_gen - 1]; +		dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, val); +	} + +	val = dw_pcie_readl_dbi(pci, PCIE_PORT_LINK_CONTROL); +	val &= ~PORT_LINK_FAST_LINK_MODE; +	val |= PORT_LINK_DLL_LINK_EN; +	dw_pcie_writel_dbi(pci, PCIE_PORT_LINK_CONTROL, val); + +	of_property_read_u32(np, "num-lanes", &pci->num_lanes); +	if (!pci->num_lanes) { +		dev_dbg(pci->dev, "Using h/w default number of lanes\n");  		return;  	}  	/* Set the number of lanes */ -	val = dw_pcie_readl_dbi(pci, PCIE_PORT_LINK_CONTROL); +	val &= ~PORT_LINK_FAST_LINK_MODE;  	val &= ~PORT_LINK_MODE_MASK; -	switch (lanes) { +	switch (pci->num_lanes) {  	case 1:  		val |= PORT_LINK_MODE_1_LANES;  		break; @@ -585,7 +611,7 @@ void dw_pcie_setup(struct dw_pcie *pci)  		val |= PORT_LINK_MODE_8_LANES;  		break;  	default: -		dev_err(pci->dev, "num-lanes %u: invalid value\n", lanes); +		dev_err(pci->dev, "num-lanes %u: invalid value\n", pci->num_lanes);  		return;  	}  	dw_pcie_writel_dbi(pci, PCIE_PORT_LINK_CONTROL, val); @@ -593,7 +619,7 @@ void dw_pcie_setup(struct dw_pcie *pci)  	/* Set link width speed control register */  	val = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL);  	val &= ~PORT_LOGIC_LINK_WIDTH_MASK; -	switch (lanes) { +	switch (pci->num_lanes) {  	case 1:  		val |= PORT_LOGIC_LINK_WIDTH_1_LANES;  		break; diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index f911760dcc69..9d2f511f13fa 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -32,10 +32,18 @@  /* Synopsys-specific PCIe configuration registers */  #define PCIE_PORT_AFR			0x70C  #define PORT_AFR_N_FTS_MASK		GENMASK(15, 8) +#define PORT_AFR_N_FTS(n)		FIELD_PREP(PORT_AFR_N_FTS_MASK, n)  #define PORT_AFR_CC_N_FTS_MASK		GENMASK(23, 16) +#define PORT_AFR_CC_N_FTS(n)		FIELD_PREP(PORT_AFR_CC_N_FTS_MASK, n) +#define PORT_AFR_ENTER_ASPM		BIT(30) +#define PORT_AFR_L0S_ENTRANCE_LAT_SHIFT	24 +#define PORT_AFR_L0S_ENTRANCE_LAT_MASK	GENMASK(26, 24) +#define PORT_AFR_L1_ENTRANCE_LAT_SHIFT	27 +#define PORT_AFR_L1_ENTRANCE_LAT_MASK	GENMASK(29, 27)  #define PCIE_PORT_LINK_CONTROL		0x710  #define PORT_LINK_DLL_LINK_EN		BIT(5) +#define PORT_LINK_FAST_LINK_MODE	BIT(7)  #define PORT_LINK_MODE_MASK		GENMASK(21, 16)  #define PORT_LINK_MODE(n)		FIELD_PREP(PORT_LINK_MODE_MASK, n)  #define PORT_LINK_MODE_1_LANES		PORT_LINK_MODE(0x1) @@ -80,9 +88,11 @@  #define PCIE_ATU_TYPE_IO		0x2  #define PCIE_ATU_TYPE_CFG0		0x4  #define PCIE_ATU_TYPE_CFG1		0x5 +#define PCIE_ATU_FUNC_NUM(pf)           ((pf) << 20)  #define PCIE_ATU_CR2			0x908  #define PCIE_ATU_ENABLE			BIT(31)  #define PCIE_ATU_BAR_MODE_ENABLE	BIT(30) +#define PCIE_ATU_FUNC_NUM_MATCH_EN      BIT(19)  #define PCIE_ATU_LOWER_BASE		0x90C  #define PCIE_ATU_UPPER_BASE		0x910  #define PCIE_ATU_LIMIT			0x914 @@ -95,6 +105,9 @@  #define PCIE_MISC_CONTROL_1_OFF		0x8BC  #define PCIE_DBI_RO_WR_EN		BIT(0) +#define PCIE_MSIX_DOORBELL		0x948 +#define PCIE_MSIX_DOORBELL_PF_SHIFT	24 +  #define PCIE_PL_CHK_REG_CONTROL_STATUS			0xB20  #define PCIE_PL_CHK_REG_CHK_REG_START			BIT(0)  #define PCIE_PL_CHK_REG_CHK_REG_CONTINUOUS		BIT(1) @@ -160,14 +173,7 @@ enum dw_pcie_device_mode {  };  struct dw_pcie_host_ops { -	int (*rd_own_conf)(struct pcie_port *pp, int where, int size, u32 *val); -	int (*wr_own_conf)(struct pcie_port *pp, int where, int size, u32 val); -	int (*rd_other_conf)(struct pcie_port *pp, struct pci_bus *bus, -			     unsigned int devfn, int where, int size, u32 *val); -	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 (*scan_bus)(struct pcie_port *pp);  	void (*set_num_vectors)(struct pcie_port *pp);  	int (*msi_host_init)(struct pcie_port *pp);  }; @@ -176,30 +182,20 @@ struct pcie_port {  	u64			cfg0_base;  	void __iomem		*va_cfg0_base;  	u32			cfg0_size; -	u64			cfg1_base; -	void __iomem		*va_cfg1_base; -	u32			cfg1_size;  	resource_size_t		io_base;  	phys_addr_t		io_bus_addr;  	u32			io_size; -	u64			mem_base; -	phys_addr_t		mem_bus_addr; -	u32			mem_size; -	struct resource		*cfg; -	struct resource		*io; -	struct resource		*mem; -	struct resource		*busn;  	int			irq;  	const struct dw_pcie_host_ops *ops;  	int			msi_irq;  	struct irq_domain	*irq_domain;  	struct irq_domain	*msi_domain; +	u16			msi_msg;  	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; +	struct pci_host_bridge  *bridge;  	raw_spinlock_t		lock;  	DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS);  }; @@ -215,10 +211,26 @@ struct dw_pcie_ep_ops {  	int	(*raise_irq)(struct dw_pcie_ep *ep, u8 func_no,  			     enum pci_epc_irq_type type, u16 interrupt_num);  	const struct pci_epc_features* (*get_features)(struct dw_pcie_ep *ep); +	/* +	 * Provide a method to implement the different func config space +	 * access for different platform, if different func have different +	 * offset, return the offset of func. if use write a register way +	 * return a 0, and implement code in callback function of platform +	 * driver. +	 */ +	unsigned int (*func_conf_select)(struct dw_pcie_ep *ep, u8 func_no); +}; + +struct dw_pcie_ep_func { +	struct list_head	list; +	u8			func_no; +	u8			msi_cap;	/* MSI capability offset */ +	u8			msix_cap;	/* MSI-X capability offset */  };  struct dw_pcie_ep {  	struct pci_epc		*epc; +	struct list_head	func_list;  	const struct dw_pcie_ep_ops *ops;  	phys_addr_t		phys_base;  	size_t			addr_size; @@ -231,8 +243,6 @@ struct dw_pcie_ep {  	u32			num_ob_windows;  	void __iomem		*msi_mem;  	phys_addr_t		msi_mem_phys; -	u8			msi_cap;	/* MSI capability offset */ -	u8			msix_cap;	/* MSI-X capability offset */  	struct pci_epf_bar	*epf_bar[PCI_STD_NUM_BARS];  }; @@ -242,8 +252,6 @@ 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); @@ -263,6 +271,9 @@ struct dw_pcie {  	struct dw_pcie_ep	ep;  	const struct dw_pcie_ops *ops;  	unsigned int		version; +	int			num_lanes; +	int			link_gen; +	u8			n_fts[2];  };  #define to_dw_pcie_from_pp(port) container_of((port), struct dw_pcie, pp) @@ -278,20 +289,19 @@ int dw_pcie_write(void __iomem *addr, int size, u32 val);  u32 dw_pcie_read_dbi(struct dw_pcie *pci, u32 reg, size_t size);  void dw_pcie_write_dbi(struct dw_pcie *pci, u32 reg, size_t size, u32 val); -u32 dw_pcie_read_dbi2(struct dw_pcie *pci, u32 reg, size_t size);  void dw_pcie_write_dbi2(struct dw_pcie *pci, u32 reg, size_t size, u32 val); -u32 dw_pcie_read_atu(struct dw_pcie *pci, u32 reg, size_t size); -void dw_pcie_write_atu(struct dw_pcie *pci, u32 reg, size_t size, u32 val);  int dw_pcie_link_up(struct dw_pcie *pci);  void dw_pcie_upconfig_setup(struct dw_pcie *pci); -void dw_pcie_link_set_max_speed(struct dw_pcie *pci, u32 link_gen); -void dw_pcie_link_set_n_fts(struct dw_pcie *pci, u32 n_fts);  int dw_pcie_wait_for_link(struct dw_pcie *pci);  void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index,  			       int type, u64 cpu_addr, u64 pci_addr,  			       u32 size); -int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int bar, -			     u64 cpu_addr, enum dw_pcie_as_type as_type); +void dw_pcie_prog_ep_outbound_atu(struct dw_pcie *pci, u8 func_no, int index, +				  int type, u64 cpu_addr, u64 pci_addr, +				  u32 size); +int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, u8 func_no, int index, +			     int bar, u64 cpu_addr, +			     enum dw_pcie_as_type as_type);  void dw_pcie_disable_atu(struct dw_pcie *pci, int index,  			 enum dw_pcie_region_type type);  void dw_pcie_setup(struct dw_pcie *pci); @@ -331,21 +341,6 @@ static inline void dw_pcie_writel_dbi2(struct dw_pcie *pci, u32 reg, u32 val)  	dw_pcie_write_dbi2(pci, reg, 0x4, val);  } -static inline u32 dw_pcie_readl_dbi2(struct dw_pcie *pci, u32 reg) -{ -	return dw_pcie_read_dbi2(pci, reg, 0x4); -} - -static inline void dw_pcie_writel_atu(struct dw_pcie *pci, u32 reg, u32 val) -{ -	dw_pcie_write_atu(pci, reg, 0x4, val); -} - -static inline u32 dw_pcie_readl_atu(struct dw_pcie *pci, u32 reg) -{ -	return dw_pcie_read_atu(pci, reg, 0x4); -} -  static inline void dw_pcie_dbi_ro_wr_en(struct dw_pcie *pci)  {  	u32 reg; @@ -376,6 +371,8 @@ void dw_pcie_setup_rc(struct pcie_port *pp);  int dw_pcie_host_init(struct pcie_port *pp);  void dw_pcie_host_deinit(struct pcie_port *pp);  int dw_pcie_allocate_domains(struct pcie_port *pp); +void __iomem *dw_pcie_own_conf_map_bus(struct pci_bus *bus, unsigned int devfn, +				       int where);  #else  static inline irqreturn_t dw_handle_msi_irq(struct pcie_port *pp)  { @@ -407,6 +404,12 @@ static inline int dw_pcie_allocate_domains(struct pcie_port *pp)  {  	return 0;  } +static inline void __iomem *dw_pcie_own_conf_map_bus(struct pci_bus *bus, +						     unsigned int devfn, +						     int where) +{ +	return NULL; +}  #endif  #ifdef CONFIG_PCIE_DW_EP @@ -420,7 +423,11 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,  			     u8 interrupt_num);  int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,  			     u16 interrupt_num); +int dw_pcie_ep_raise_msix_irq_doorbell(struct dw_pcie_ep *ep, u8 func_no, +				       u16 interrupt_num);  void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar); +struct dw_pcie_ep_func * +dw_pcie_ep_get_func_from_ep(struct dw_pcie_ep *ep, u8 func_no);  #else  static inline void dw_pcie_ep_linkup(struct dw_pcie_ep *ep)  { @@ -461,8 +468,21 @@ static inline int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,  	return 0;  } +static inline int dw_pcie_ep_raise_msix_irq_doorbell(struct dw_pcie_ep *ep, +						     u8 func_no, +						     u16 interrupt_num) +{ +	return 0; +} +  static inline void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar)  {  } + +static inline struct dw_pcie_ep_func * +dw_pcie_ep_get_func_from_ep(struct dw_pcie_ep *ep, u8 func_no) +{ +	return NULL; +}  #endif  #endif /* _PCIE_DESIGNWARE_H */ diff --git a/drivers/pci/controller/dwc/pcie-histb.c b/drivers/pci/controller/dwc/pcie-histb.c index 2a2835746077..afc1abbe49aa 100644 --- a/drivers/pci/controller/dwc/pcie-histb.c +++ b/drivers/pci/controller/dwc/pcie-histb.c @@ -122,32 +122,37 @@ static void histb_pcie_write_dbi(struct dw_pcie *pci, void __iomem *base,  	histb_pcie_dbi_w_mode(&pci->pp, false);  } -static int histb_pcie_rd_own_conf(struct pcie_port *pp, int where, -				  int size, u32 *val) +static int histb_pcie_rd_own_conf(struct pci_bus *bus, unsigned int devfn, +				  int where, int size, u32 *val)  { -	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); -	int ret; +	struct dw_pcie *pci = to_dw_pcie_from_pp(bus->sysdata); -	histb_pcie_dbi_r_mode(pp, true); -	ret = dw_pcie_read(pci->dbi_base + where, size, val); -	histb_pcie_dbi_r_mode(pp, false); +	if (PCI_SLOT(devfn)) { +		*val = ~0; +		return PCIBIOS_DEVICE_NOT_FOUND; +	} -	return ret; +	*val = dw_pcie_read_dbi(pci, where, size); +	return PCIBIOS_SUCCESSFUL;  } -static int histb_pcie_wr_own_conf(struct pcie_port *pp, int where, -				  int size, u32 val) +static int histb_pcie_wr_own_conf(struct pci_bus *bus, unsigned int devfn, +				  int where, int size, u32 val)  { -	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); -	int ret; +	struct dw_pcie *pci = to_dw_pcie_from_pp(bus->sysdata); -	histb_pcie_dbi_w_mode(pp, true); -	ret = dw_pcie_write(pci->dbi_base + where, size, val); -	histb_pcie_dbi_w_mode(pp, false); +	if (PCI_SLOT(devfn)) +		return PCIBIOS_DEVICE_NOT_FOUND; -	return ret; +	dw_pcie_write_dbi(pci, where, size, val); +	return PCIBIOS_SUCCESSFUL;  } +static struct pci_ops histb_pci_ops = { +	.read = histb_pcie_rd_own_conf, +	.write = histb_pcie_wr_own_conf, +}; +  static int histb_pcie_link_up(struct dw_pcie *pci)  {  	struct histb_pcie *hipcie = to_histb_pcie(pci); @@ -194,17 +199,15 @@ static int histb_pcie_establish_link(struct pcie_port *pp)  static int histb_pcie_host_init(struct pcie_port *pp)  { -	histb_pcie_establish_link(pp); +	pp->bridge->ops = &histb_pci_ops; -	if (IS_ENABLED(CONFIG_PCI_MSI)) -		dw_pcie_msi_init(pp); +	histb_pcie_establish_link(pp); +	dw_pcie_msi_init(pp);  	return 0;  }  static const struct dw_pcie_host_ops histb_pcie_host_ops = { -	.rd_own_conf = histb_pcie_rd_own_conf, -	.wr_own_conf = histb_pcie_wr_own_conf,  	.host_init = histb_pcie_host_init,  }; diff --git a/drivers/pci/controller/dwc/pcie-intel-gw.c b/drivers/pci/controller/dwc/pcie-intel-gw.c index c3b3a1d162b5..5650cb78acba 100644 --- a/drivers/pci/controller/dwc/pcie-intel-gw.c +++ b/drivers/pci/controller/dwc/pcie-intel-gw.c @@ -67,14 +67,9 @@ struct intel_pcie_port {  	void __iomem		*app_base;  	struct gpio_desc	*reset_gpio;  	u32			rst_intrvl; -	u32			max_speed; -	u32			link_gen; -	u32			max_width; -	u32			n_fts;  	struct clk		*core_clk;  	struct reset_control	*core_rst;  	struct phy		*phy; -	u8			pcie_cap_ofst;  };  static void pcie_update_bits(void __iomem *base, u32 ofs, u32 mask, u32 val) @@ -134,11 +129,7 @@ static void intel_pcie_ltssm_disable(struct intel_pcie_port *lpp)  static void intel_pcie_link_setup(struct intel_pcie_port *lpp)  {  	u32 val; -	u8 offset = lpp->pcie_cap_ofst; - -	val = pcie_rc_cfg_rd(lpp, offset + PCI_EXP_LNKCAP); -	lpp->max_speed = FIELD_GET(PCI_EXP_LNKCAP_SLS, val); -	lpp->max_width = FIELD_GET(PCI_EXP_LNKCAP_MLW, val); +	u8 offset = dw_pcie_find_capability(&lpp->pci, PCI_CAP_ID_EXP);  	val = pcie_rc_cfg_rd(lpp, offset + PCI_EXP_LNKCTL); @@ -146,41 +137,29 @@ static void intel_pcie_link_setup(struct intel_pcie_port *lpp)  	pcie_rc_cfg_wr(lpp, offset + PCI_EXP_LNKCTL, val);  } -static void intel_pcie_port_logic_setup(struct intel_pcie_port *lpp) +static void intel_pcie_init_n_fts(struct dw_pcie *pci)  { -	u32 val, mask; - -	switch (pcie_link_speed[lpp->max_speed]) { -	case PCIE_SPEED_8_0GT: -		lpp->n_fts = PORT_AFR_N_FTS_GEN3; +	switch (pci->link_gen) { +	case 3: +		pci->n_fts[1] = PORT_AFR_N_FTS_GEN3;  		break; -	case PCIE_SPEED_16_0GT: -		lpp->n_fts = PORT_AFR_N_FTS_GEN4; +	case 4: +		pci->n_fts[1] = PORT_AFR_N_FTS_GEN4;  		break;  	default: -		lpp->n_fts = PORT_AFR_N_FTS_GEN12_DFT; +		pci->n_fts[1] = PORT_AFR_N_FTS_GEN12_DFT;  		break;  	} - -	mask = PORT_AFR_N_FTS_MASK | PORT_AFR_CC_N_FTS_MASK; -	val = FIELD_PREP(PORT_AFR_N_FTS_MASK, lpp->n_fts) | -	       FIELD_PREP(PORT_AFR_CC_N_FTS_MASK, lpp->n_fts); -	pcie_rc_cfg_wr_mask(lpp, PCIE_PORT_AFR, mask, val); - -	/* Port Link Control Register */ -	pcie_rc_cfg_wr_mask(lpp, PCIE_PORT_LINK_CONTROL, PORT_LINK_DLL_LINK_EN, -			    PORT_LINK_DLL_LINK_EN); +	pci->n_fts[0] = PORT_AFR_N_FTS_GEN12_DFT;  }  static void intel_pcie_rc_setup(struct intel_pcie_port *lpp)  {  	intel_pcie_ltssm_disable(lpp);  	intel_pcie_link_setup(lpp); +	intel_pcie_init_n_fts(&lpp->pci);  	dw_pcie_setup_rc(&lpp->pci.pp);  	dw_pcie_upconfig_setup(&lpp->pci); -	intel_pcie_port_logic_setup(lpp); -	dw_pcie_link_set_max_speed(&lpp->pci, lpp->link_gen); -	dw_pcie_link_set_n_fts(&lpp->pci, lpp->n_fts);  }  static int intel_pcie_ep_rst_init(struct intel_pcie_port *lpp) @@ -275,20 +254,11 @@ static int intel_pcie_get_resources(struct platform_device *pdev)  		return ret;  	} -	ret = device_property_match_string(dev, "device_type", "pci"); -	if (ret) { -		dev_err(dev, "Failed to find pci device type: %d\n", ret); -		return ret; -	} -  	ret = device_property_read_u32(dev, "reset-assert-ms",  				       &lpp->rst_intrvl);  	if (ret)  		lpp->rst_intrvl = RESET_INTERVAL_MS; -	ret = of_pci_get_max_link_speed(dev->of_node); -	lpp->link_gen = ret < 0 ? 0 : ret; -  	lpp->app_base = devm_platform_ioremap_resource_byname(pdev, "app");  	if (IS_ERR(lpp->app_base))  		return PTR_ERR(lpp->app_base); @@ -313,8 +283,9 @@ static int intel_pcie_wait_l2(struct intel_pcie_port *lpp)  {  	u32 value;  	int ret; +	struct dw_pcie *pci = &lpp->pci; -	if (pcie_link_speed[lpp->max_speed] < PCIE_SPEED_8_0GT) +	if (pci->link_gen < 3)  		return 0;  	/* Send PME_TURN_OFF message */ @@ -343,7 +314,6 @@ static void intel_pcie_turn_off(struct intel_pcie_port *lpp)  static int intel_pcie_host_setup(struct intel_pcie_port *lpp)  { -	struct device *dev = lpp->pci.dev;  	int ret;  	intel_pcie_core_rst_assert(lpp); @@ -361,17 +331,6 @@ static int intel_pcie_host_setup(struct intel_pcie_port *lpp)  		goto clk_err;  	} -	if (!lpp->pcie_cap_ofst) { -		ret = dw_pcie_find_capability(&lpp->pci, PCI_CAP_ID_EXP); -		if (!ret) { -			ret = -ENXIO; -			dev_err(dev, "Invalid PCIe capability offset\n"); -			goto app_init_err; -		} - -		lpp->pcie_cap_ofst = ret; -	} -  	intel_pcie_rc_setup(lpp);  	ret = intel_pcie_app_logic_setup(lpp);  	if (ret) diff --git a/drivers/pci/controller/dwc/pcie-kirin.c b/drivers/pci/controller/dwc/pcie-kirin.c index e496f51e0152..d0a6a2dee6f5 100644 --- a/drivers/pci/controller/dwc/pcie-kirin.c +++ b/drivers/pci/controller/dwc/pcie-kirin.c @@ -330,34 +330,37 @@ static void kirin_pcie_sideband_dbi_r_mode(struct kirin_pcie *kirin_pcie,  	kirin_apb_ctrl_writel(kirin_pcie, val, SOC_PCIECTRL_CTRL1_ADDR);  } -static int kirin_pcie_rd_own_conf(struct pcie_port *pp, +static int kirin_pcie_rd_own_conf(struct pci_bus *bus, unsigned int devfn,  				  int where, int size, u32 *val)  { -	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); -	struct kirin_pcie *kirin_pcie = to_kirin_pcie(pci); -	int ret; +	struct dw_pcie *pci = to_dw_pcie_from_pp(bus->sysdata); -	kirin_pcie_sideband_dbi_r_mode(kirin_pcie, true); -	ret = dw_pcie_read(pci->dbi_base + where, size, val); -	kirin_pcie_sideband_dbi_r_mode(kirin_pcie, false); +	if (PCI_SLOT(devfn)) { +		*val = ~0; +		return PCIBIOS_DEVICE_NOT_FOUND; +	} -	return ret; +	*val = dw_pcie_read_dbi(pci, where, size); +	return PCIBIOS_SUCCESSFUL;  } -static int kirin_pcie_wr_own_conf(struct pcie_port *pp, +static int kirin_pcie_wr_own_conf(struct pci_bus *bus, unsigned int devfn,  				  int where, int size, u32 val)  { -	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); -	struct kirin_pcie *kirin_pcie = to_kirin_pcie(pci); -	int ret; +	struct dw_pcie *pci = to_dw_pcie_from_pp(bus->sysdata); -	kirin_pcie_sideband_dbi_w_mode(kirin_pcie, true); -	ret = dw_pcie_write(pci->dbi_base + where, size, val); -	kirin_pcie_sideband_dbi_w_mode(kirin_pcie, false); +	if (PCI_SLOT(devfn)) +		return PCIBIOS_DEVICE_NOT_FOUND; -	return ret; +	dw_pcie_write_dbi(pci, where, size, val); +	return PCIBIOS_SUCCESSFUL;  } +static struct pci_ops kirin_pci_ops = { +	.read = kirin_pcie_rd_own_conf, +	.write = kirin_pcie_wr_own_conf, +}; +  static u32 kirin_pcie_read_dbi(struct dw_pcie *pci, void __iomem *base,  			       u32 reg, size_t size)  { @@ -423,10 +426,10 @@ static int kirin_pcie_establish_link(struct pcie_port *pp)  static int kirin_pcie_host_init(struct pcie_port *pp)  { -	kirin_pcie_establish_link(pp); +	pp->bridge->ops = &kirin_pci_ops; -	if (IS_ENABLED(CONFIG_PCI_MSI)) -		dw_pcie_msi_init(pp); +	kirin_pcie_establish_link(pp); +	dw_pcie_msi_init(pp);  	return 0;  } @@ -438,8 +441,6 @@ static const struct dw_pcie_ops kirin_dw_pcie_ops = {  };  static const struct dw_pcie_host_ops kirin_pcie_host_ops = { -	.rd_own_conf = kirin_pcie_rd_own_conf, -	.wr_own_conf = kirin_pcie_wr_own_conf,  	.host_init = kirin_pcie_host_init,  }; @@ -507,8 +508,12 @@ static int kirin_pcie_probe(struct platform_device *pdev)  	kirin_pcie->gpio_id_reset = of_get_named_gpio(dev->of_node,  						      "reset-gpios", 0); -	if (kirin_pcie->gpio_id_reset < 0) +	if (kirin_pcie->gpio_id_reset == -EPROBE_DEFER) { +		return -EPROBE_DEFER; +	} else if (!gpio_is_valid(kirin_pcie->gpio_id_reset)) { +		dev_err(dev, "unable to get a valid gpio pin\n");  		return -ENODEV; +	}  	ret = kirin_pcie_power_on(kirin_pcie);  	if (ret) diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index 3aac77a295ba..b4761640ffd9 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -67,10 +67,6 @@  #define PCIE20_AXI_MSTR_RESP_COMP_CTRL1		0x81c  #define CFG_BRIDGE_SB_INIT			BIT(0) -#define PCIE20_CAP				0x70 -#define PCIE20_DEVICE_CONTROL2_STATUS2		(PCIE20_CAP + PCI_EXP_DEVCTL2) -#define PCIE20_CAP_LINK_CAPABILITIES		(PCIE20_CAP + PCI_EXP_LNKCAP) -#define PCIE20_CAP_LINK_1			(PCIE20_CAP + 0x14)  #define PCIE_CAP_LINK1_VAL			0x2FD7F  #define PCIE20_PARF_Q2A_FLUSH			0x1AC @@ -193,7 +189,6 @@ struct qcom_pcie {  	struct phy *phy;  	struct gpio_desc *reset;  	const struct qcom_pcie_ops *ops; -	int gen;  };  #define to_qcom_pcie(x)		dev_get_drvdata((x)->dev) @@ -302,6 +297,9 @@ static void qcom_pcie_deinit_2_1_0(struct qcom_pcie *pcie)  	reset_control_assert(res->por_reset);  	reset_control_assert(res->ext_reset);  	reset_control_assert(res->phy_reset); + +	writel(1, pcie->parf + PCIE20_PARF_PHY_CTRL); +  	regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies);  } @@ -314,6 +312,16 @@ static int qcom_pcie_init_2_1_0(struct qcom_pcie *pcie)  	u32 val;  	int ret; +	/* reset the PCIe interface as uboot can leave it undefined state */ +	reset_control_assert(res->pci_reset); +	reset_control_assert(res->axi_reset); +	reset_control_assert(res->ahb_reset); +	reset_control_assert(res->por_reset); +	reset_control_assert(res->ext_reset); +	reset_control_assert(res->phy_reset); + +	writel(1, pcie->parf + PCIE20_PARF_PHY_CTRL); +  	ret = regulator_bulk_enable(ARRAY_SIZE(res->supplies), res->supplies);  	if (ret < 0) {  		dev_err(dev, "cannot enable regulators\n"); @@ -394,12 +402,6 @@ static int qcom_pcie_init_2_1_0(struct qcom_pcie *pcie)  	/* wait for clock acquisition */  	usleep_range(1000, 1500); -	if (pcie->gen == 1) { -		val = readl(pci->dbi_base + PCIE20_LNK_CONTROL2_LINK_STATUS2); -		val |= PCI_EXP_LNKSTA_CLS_2_5GB; -		writel(val, pci->dbi_base + PCIE20_LNK_CONTROL2_LINK_STATUS2); -	} -  	/* Set the Max TLP size to 2K, instead of using default of 4K */  	writel(CFG_REMOTE_RD_REQ_BRIDGE_SIZE_2K,  	       pci->dbi_base + PCIE20_AXI_MSTR_RESP_COMP_CTRL0); @@ -1017,6 +1019,7 @@ static int qcom_pcie_init_2_3_3(struct qcom_pcie *pcie)  	struct qcom_pcie_resources_2_3_3 *res = &pcie->res.v2_3_3;  	struct dw_pcie *pci = pcie->pci;  	struct device *dev = pci->dev; +	u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);  	int i, ret;  	u32 val; @@ -1092,14 +1095,14 @@ static int qcom_pcie_init_2_3_3(struct qcom_pcie *pcie)  	writel(PCI_COMMAND_MASTER, pci->dbi_base + PCI_COMMAND);  	writel(DBI_RO_WR_EN, pci->dbi_base + PCIE20_MISC_CONTROL_1_REG); -	writel(PCIE_CAP_LINK1_VAL, pci->dbi_base + PCIE20_CAP_LINK_1); +	writel(PCIE_CAP_LINK1_VAL, pci->dbi_base + offset + PCI_EXP_SLTCAP); -	val = readl(pci->dbi_base + PCIE20_CAP_LINK_CAPABILITIES); +	val = readl(pci->dbi_base + offset + PCI_EXP_LNKCAP);  	val &= ~PCI_EXP_LNKCAP_ASPMS; -	writel(val, pci->dbi_base + PCIE20_CAP_LINK_CAPABILITIES); +	writel(val, pci->dbi_base + offset + PCI_EXP_LNKCAP); -	writel(PCI_EXP_DEVCTL2_COMP_TMOUT_DIS, pci->dbi_base + -		PCIE20_DEVICE_CONTROL2_STATUS2); +	writel(PCI_EXP_DEVCTL2_COMP_TMOUT_DIS, pci->dbi_base + offset + +		PCI_EXP_DEVCTL2);  	return 0; @@ -1252,7 +1255,8 @@ static void qcom_pcie_post_deinit_2_7_0(struct qcom_pcie *pcie)  static int qcom_pcie_link_up(struct dw_pcie *pci)  { -	u16 val = readw(pci->dbi_base + PCIE20_CAP + PCI_EXP_LNKSTA); +	u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); +	u16 val = readw(pci->dbi_base + offset + PCI_EXP_LNKSTA);  	return !!(val & PCI_EXP_LNKSTA_DLLLA);  } @@ -1280,9 +1284,7 @@ static int qcom_pcie_host_init(struct pcie_port *pp)  	}  	dw_pcie_setup_rc(pp); - -	if (IS_ENABLED(CONFIG_PCI_MSI)) -		dw_pcie_msi_init(pp); +	dw_pcie_msi_init(pp);  	qcom_ep_reset_deassert(pcie); @@ -1399,10 +1401,6 @@ static int qcom_pcie_probe(struct platform_device *pdev)  		goto err_pm_runtime_put;  	} -	pcie->gen = of_pci_get_max_link_speed(pdev->dev.of_node); -	if (pcie->gen < 0) -		pcie->gen = 2; -  	pcie->parf = devm_platform_ioremap_resource_byname(pdev, "parf");  	if (IS_ERR(pcie->parf)) {  		ret = PTR_ERR(pcie->parf); diff --git a/drivers/pci/controller/dwc/pcie-spear13xx.c b/drivers/pci/controller/dwc/pcie-spear13xx.c index 62846562da0b..e348225f651f 100644 --- a/drivers/pci/controller/dwc/pcie-spear13xx.c +++ b/drivers/pci/controller/dwc/pcie-spear13xx.c @@ -26,7 +26,6 @@ struct spear13xx_pcie {  	void __iomem		*app_base;  	struct phy		*phy;  	struct clk		*clk; -	bool			is_gen1;  };  struct pcie_app_reg { @@ -65,8 +64,6 @@ struct pcie_app_reg {  /* CR6 */  #define MSI_CTRL_INT				(1 << 26) -#define EXP_CAP_ID_OFFSET			0x70 -  #define to_spear13xx_pcie(x)	dev_get_drvdata((x)->dev)  static int spear13xx_pcie_establish_link(struct spear13xx_pcie *spear13xx_pcie) @@ -75,7 +72,7 @@ static int spear13xx_pcie_establish_link(struct spear13xx_pcie *spear13xx_pcie)  	struct pcie_port *pp = &pci->pp;  	struct pcie_app_reg *app_reg = spear13xx_pcie->app_base;  	u32 val; -	u32 exp_cap_off = EXP_CAP_ID_OFFSET; +	u32 exp_cap_off = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);  	if (dw_pcie_link_up(pci)) {  		dev_err(pci->dev, "link already up\n"); @@ -89,36 +86,12 @@ static int spear13xx_pcie_establish_link(struct spear13xx_pcie *spear13xx_pcie)  	 * default value in capability register is 512 bytes. So force  	 * it to 128 here.  	 */ -	dw_pcie_read(pci->dbi_base + exp_cap_off + PCI_EXP_DEVCTL, 2, &val); +	val = dw_pcie_readw_dbi(pci, exp_cap_off + PCI_EXP_DEVCTL);  	val &= ~PCI_EXP_DEVCTL_READRQ; -	dw_pcie_write(pci->dbi_base + exp_cap_off + PCI_EXP_DEVCTL, 2, val); - -	dw_pcie_write(pci->dbi_base + PCI_VENDOR_ID, 2, 0x104A); -	dw_pcie_write(pci->dbi_base + PCI_DEVICE_ID, 2, 0xCD80); +	dw_pcie_writew_dbi(pci, exp_cap_off + PCI_EXP_DEVCTL, val); -	/* -	 * if is_gen1 is set then handle it, so that some buggy card -	 * also works -	 */ -	if (spear13xx_pcie->is_gen1) { -		dw_pcie_read(pci->dbi_base + exp_cap_off + PCI_EXP_LNKCAP, -			     4, &val); -		if ((val & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_2_5GB) { -			val &= ~((u32)PCI_EXP_LNKCAP_SLS); -			val |= PCI_EXP_LNKCAP_SLS_2_5GB; -			dw_pcie_write(pci->dbi_base + exp_cap_off + -				      PCI_EXP_LNKCAP, 4, val); -		} - -		dw_pcie_read(pci->dbi_base + exp_cap_off + PCI_EXP_LNKCTL2, -			     2, &val); -		if ((val & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_2_5GB) { -			val &= ~((u32)PCI_EXP_LNKCAP_SLS); -			val |= PCI_EXP_LNKCAP_SLS_2_5GB; -			dw_pcie_write(pci->dbi_base + exp_cap_off + -				      PCI_EXP_LNKCTL2, 2, val); -		} -	} +	dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, 0x104A); +	dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, 0xCD80);  	/* enable ltssm */  	writel(DEVICE_TYPE_RC | (1 << MISCTRL_EN_ID) @@ -278,7 +251,7 @@ static int spear13xx_pcie_probe(struct platform_device *pdev)  	spear13xx_pcie->app_base = pci->dbi_base + 0x2000;  	if (of_property_read_bool(np, "st,pcie-is-gen1")) -		spear13xx_pcie->is_gen1 = true; +		pci->link_gen = 1;  	platform_set_drvdata(pdev, spear13xx_pcie); diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c index 70498689d0c0..f920e7efe118 100644 --- a/drivers/pci/controller/dwc/pcie-tegra194.c +++ b/drivers/pci/controller/dwc/pcie-tegra194.c @@ -183,19 +183,7 @@  #define EVENT_COUNTER_GROUP_SEL_SHIFT	24  #define EVENT_COUNTER_GROUP_5		0x5 -#define PORT_LOGIC_ACK_F_ASPM_CTRL			0x70C -#define ENTER_ASPM					BIT(30) -#define L0S_ENTRANCE_LAT_SHIFT				24 -#define L0S_ENTRANCE_LAT_MASK				GENMASK(26, 24) -#define L1_ENTRANCE_LAT_SHIFT				27 -#define L1_ENTRANCE_LAT_MASK				GENMASK(29, 27) -#define N_FTS_SHIFT					8 -#define N_FTS_MASK					GENMASK(7, 0)  #define N_FTS_VAL					52 - -#define PORT_LOGIC_GEN2_CTRL				0x80C -#define PORT_LOGIC_GEN2_CTRL_DIRECT_SPEED_CHANGE	BIT(17) -#define FTS_MASK					GENMASK(7, 0)  #define FTS_VAL						52  #define PORT_LOGIC_MSI_CTRL_INT_0_EN		0x828 @@ -296,7 +284,6 @@ struct tegra_pcie_dw {  	u8 init_link_width;  	u32 msi_ctrl_int;  	u32 num_lanes; -	u32 max_speed;  	u32 cid;  	u32 cfg_link_cap_l1sub;  	u32 pcie_cap_base; @@ -401,9 +388,9 @@ static irqreturn_t tegra_pcie_rp_irq_handler(int irq, void *arg)  			val |= APPL_CAR_RESET_OVRD_CYA_OVERRIDE_CORE_RST_N;  			appl_writel(pcie, val, APPL_CAR_RESET_OVRD); -			val = dw_pcie_readl_dbi(pci, PORT_LOGIC_GEN2_CTRL); -			val |= PORT_LOGIC_GEN2_CTRL_DIRECT_SPEED_CHANGE; -			dw_pcie_writel_dbi(pci, PORT_LOGIC_GEN2_CTRL, val); +			val = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL); +			val |= PORT_LOGIC_SPEED_CHANGE; +			dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, val);  		}  	} @@ -568,42 +555,44 @@ static irqreturn_t tegra_pcie_ep_hard_irq(int irq, void *arg)  	return IRQ_HANDLED;  } -static int tegra_pcie_dw_rd_own_conf(struct pcie_port *pp, int where, int size, -				     u32 *val) +static int tegra_pcie_dw_rd_own_conf(struct pci_bus *bus, u32 devfn, int where, +				     int size, u32 *val)  { -	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); -  	/*  	 * This is an endpoint mode specific register happen to appear even  	 * when controller is operating in root port mode and system hangs  	 * when it is accessed with link being in ASPM-L1 state.  	 * So skip accessing it altogether  	 */ -	if (where == PORT_LOGIC_MSIX_DOORBELL) { +	if (!PCI_SLOT(devfn) && where == PORT_LOGIC_MSIX_DOORBELL) {  		*val = 0x00000000;  		return PCIBIOS_SUCCESSFUL;  	} -	return dw_pcie_read(pci->dbi_base + where, size, val); +	return pci_generic_config_read(bus, devfn, where, size, val);  } -static int tegra_pcie_dw_wr_own_conf(struct pcie_port *pp, int where, int size, -				     u32 val) +static int tegra_pcie_dw_wr_own_conf(struct pci_bus *bus, u32 devfn, int where, +				     int size, u32 val)  { -	struct dw_pcie *pci = to_dw_pcie_from_pp(pp); -  	/*  	 * This is an endpoint mode specific register happen to appear even  	 * when controller is operating in root port mode and system hangs  	 * when it is accessed with link being in ASPM-L1 state.  	 * So skip accessing it altogether  	 */ -	if (where == PORT_LOGIC_MSIX_DOORBELL) +	if (!PCI_SLOT(devfn) && where == PORT_LOGIC_MSIX_DOORBELL)  		return PCIBIOS_SUCCESSFUL; -	return dw_pcie_write(pci->dbi_base + where, size, val); +	return pci_generic_config_write(bus, devfn, where, size, val);  } +static struct pci_ops tegra_pci_ops = { +	.map_bus = dw_pcie_own_conf_map_bus, +	.read = tegra_pcie_dw_rd_own_conf, +	.write = tegra_pcie_dw_wr_own_conf, +}; +  #if defined(CONFIG_PCIEASPM)  static void disable_aspm_l11(struct tegra_pcie_dw *pcie)  { @@ -692,30 +681,23 @@ static void init_host_aspm(struct tegra_pcie_dw *pcie)  	dw_pcie_writel_dbi(pci, pcie->cfg_link_cap_l1sub, val);  	/* Program L0s and L1 entrance latencies */ -	val = dw_pcie_readl_dbi(pci, PORT_LOGIC_ACK_F_ASPM_CTRL); -	val &= ~L0S_ENTRANCE_LAT_MASK; -	val |= (pcie->aspm_l0s_enter_lat << L0S_ENTRANCE_LAT_SHIFT); -	val |= ENTER_ASPM; -	dw_pcie_writel_dbi(pci, PORT_LOGIC_ACK_F_ASPM_CTRL, val); +	val = dw_pcie_readl_dbi(pci, PCIE_PORT_AFR); +	val &= ~PORT_AFR_L0S_ENTRANCE_LAT_MASK; +	val |= (pcie->aspm_l0s_enter_lat << PORT_AFR_L0S_ENTRANCE_LAT_SHIFT); +	val |= PORT_AFR_ENTER_ASPM; +	dw_pcie_writel_dbi(pci, PCIE_PORT_AFR, val);  } -static int init_debugfs(struct tegra_pcie_dw *pcie) +static void init_debugfs(struct tegra_pcie_dw *pcie)  { -	struct dentry *d; - -	d = debugfs_create_devm_seqfile(pcie->dev, "aspm_state_cnt", -					pcie->debugfs, aspm_state_cnt); -	if (IS_ERR_OR_NULL(d)) -		dev_err(pcie->dev, -			"Failed to create debugfs file \"aspm_state_cnt\"\n"); - -	return 0; +	debugfs_create_devm_seqfile(pcie->dev, "aspm_state_cnt", pcie->debugfs, +				    aspm_state_cnt);  }  #else  static inline void disable_aspm_l12(struct tegra_pcie_dw *pcie) { return; }  static inline void disable_aspm_l11(struct tegra_pcie_dw *pcie) { return; }  static inline void init_host_aspm(struct tegra_pcie_dw *pcie) { return; } -static inline int init_debugfs(struct tegra_pcie_dw *pcie) { return 0; } +static inline void init_debugfs(struct tegra_pcie_dw *pcie) { return; }  #endif  static void tegra_pcie_enable_system_interrupts(struct pcie_port *pp) @@ -827,26 +809,24 @@ static void config_gen3_gen4_eq_presets(struct tegra_pcie_dw *pcie)  	/* Program init preset */  	for (i = 0; i < pcie->num_lanes; i++) { -		dw_pcie_read(pci->dbi_base + CAP_SPCIE_CAP_OFF -				 + (i * 2), 2, &val); +		val = dw_pcie_readw_dbi(pci, CAP_SPCIE_CAP_OFF + (i * 2));  		val &= ~CAP_SPCIE_CAP_OFF_DSP_TX_PRESET0_MASK;  		val |= GEN3_GEN4_EQ_PRESET_INIT;  		val &= ~CAP_SPCIE_CAP_OFF_USP_TX_PRESET0_MASK;  		val |= (GEN3_GEN4_EQ_PRESET_INIT <<  			   CAP_SPCIE_CAP_OFF_USP_TX_PRESET0_SHIFT); -		dw_pcie_write(pci->dbi_base + CAP_SPCIE_CAP_OFF -				 + (i * 2), 2, val); +		dw_pcie_writew_dbi(pci, CAP_SPCIE_CAP_OFF + (i * 2), val);  		offset = dw_pcie_find_ext_capability(pci,  						     PCI_EXT_CAP_ID_PL_16GT) +  				PCI_PL_16GT_LE_CTRL; -		dw_pcie_read(pci->dbi_base + offset + i, 1, &val); +		val = dw_pcie_readb_dbi(pci, offset + i);  		val &= ~PCI_PL_16GT_LE_CTRL_DSP_TX_PRESET_MASK;  		val |= GEN3_GEN4_EQ_PRESET_INIT;  		val &= ~PCI_PL_16GT_LE_CTRL_USP_TX_PRESET_MASK;  		val |= (GEN3_GEN4_EQ_PRESET_INIT <<  			PCI_PL_16GT_LE_CTRL_USP_TX_PRESET_SHIFT); -		dw_pcie_write(pci->dbi_base + offset + i, 1, val); +		dw_pcie_writeb_dbi(pci, offset + i, val);  	}  	val = dw_pcie_readl_dbi(pci, GEN3_RELATED_OFF); @@ -892,17 +872,6 @@ static void tegra_pcie_prepare_host(struct pcie_port *pp)  	dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0); -	/* Configure FTS */ -	val = dw_pcie_readl_dbi(pci, PORT_LOGIC_ACK_F_ASPM_CTRL); -	val &= ~(N_FTS_MASK << N_FTS_SHIFT); -	val |= N_FTS_VAL << N_FTS_SHIFT; -	dw_pcie_writel_dbi(pci, PORT_LOGIC_ACK_F_ASPM_CTRL, val); - -	val = dw_pcie_readl_dbi(pci, PORT_LOGIC_GEN2_CTRL); -	val &= ~FTS_MASK; -	val |= FTS_VAL; -	dw_pcie_writel_dbi(pci, PORT_LOGIC_GEN2_CTRL, val); -  	/* Enable as 0xFFFF0001 response for CRS */  	val = dw_pcie_readl_dbi(pci, PORT_LOGIC_AMBA_ERROR_RESPONSE_DEFAULT);  	val &= ~(AMBA_ERROR_RESPONSE_CRS_MASK << AMBA_ERROR_RESPONSE_CRS_SHIFT); @@ -910,16 +879,6 @@ static void tegra_pcie_prepare_host(struct pcie_port *pp)  		AMBA_ERROR_RESPONSE_CRS_SHIFT);  	dw_pcie_writel_dbi(pci, PORT_LOGIC_AMBA_ERROR_RESPONSE_DEFAULT, val); -	/* Configure Max Speed from DT */ -	if (pcie->max_speed && pcie->max_speed != -EINVAL) { -		val = dw_pcie_readl_dbi(pci, pcie->pcie_cap_base + -					PCI_EXP_LNKCAP); -		val &= ~PCI_EXP_LNKCAP_SLS; -		val |= pcie->max_speed; -		dw_pcie_writel_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKCAP, -				   val); -	} -  	/* Configure Max lane width from DT */  	val = dw_pcie_readl_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKCAP);  	val &= ~PCI_EXP_LNKCAP_MLW; @@ -970,6 +929,8 @@ static int tegra_pcie_dw_host_init(struct pcie_port *pp)  	struct tegra_pcie_dw *pcie = to_tegra_pcie(pci);  	u32 val, tmp, offset, speed; +	pp->bridge->ops = &tegra_pci_ops; +  	tegra_pcie_prepare_host(pp);  	if (dw_pcie_wait_for_link(pci)) { @@ -1057,8 +1018,6 @@ static const struct dw_pcie_ops tegra_dw_pcie_ops = {  };  static struct dw_pcie_host_ops tegra_pcie_dw_host_ops = { -	.rd_own_conf = tegra_pcie_dw_rd_own_conf, -	.wr_own_conf = tegra_pcie_dw_wr_own_conf,  	.host_init = tegra_pcie_dw_host_init,  	.set_num_vectors = tegra_pcie_set_msi_vec_num,  }; @@ -1129,8 +1088,6 @@ static int tegra_pcie_dw_parse_dt(struct tegra_pcie_dw *pcie)  		return ret;  	} -	pcie->max_speed = of_pci_get_max_link_speed(np); -  	ret = of_property_read_u32_index(np, "nvidia,bpmp", 1, &pcie->cid);  	if (ret) {  		dev_err(pcie->dev, "Failed to read Controller-ID: %d\n", ret); @@ -1262,9 +1219,9 @@ static void tegra_pcie_downstream_dev_to_D0(struct tegra_pcie_dw *pcie)  	 * 5.2 Link State Power Management (Page #428).  	 */ -	list_for_each_entry(child, &pp->root_bus->children, node) { +	list_for_each_entry(child, &pp->bridge->bus->children, node) {  		/* Bring downstream devices to D0 if they are not already in */ -		if (child->parent == pp->root_bus) { +		if (child->parent == pp->bridge->bus) {  			root_bus = child;  			break;  		} @@ -1641,10 +1598,7 @@ static int tegra_pcie_config_rp(struct tegra_pcie_dw *pcie)  	}  	pcie->debugfs = debugfs_create_dir(name, NULL); -	if (!pcie->debugfs) -		dev_err(dev, "Failed to create debugfs\n"); -	else -		init_debugfs(pcie); +	init_debugfs(pcie);  	return ret; @@ -1817,27 +1771,6 @@ static void pex_ep_event_pex_rst_deassert(struct tegra_pcie_dw *pcie)  	val &= ~GEN3_RELATED_OFF_GEN3_ZRXDC_NONCOMPL;  	dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, val); -	/* Configure N_FTS & FTS */ -	val = dw_pcie_readl_dbi(pci, PORT_LOGIC_ACK_F_ASPM_CTRL); -	val &= ~(N_FTS_MASK << N_FTS_SHIFT); -	val |= N_FTS_VAL << N_FTS_SHIFT; -	dw_pcie_writel_dbi(pci, PORT_LOGIC_ACK_F_ASPM_CTRL, val); - -	val = dw_pcie_readl_dbi(pci, PORT_LOGIC_GEN2_CTRL); -	val &= ~FTS_MASK; -	val |= FTS_VAL; -	dw_pcie_writel_dbi(pci, PORT_LOGIC_GEN2_CTRL, val); - -	/* Configure Max Speed from DT */ -	if (pcie->max_speed && pcie->max_speed != -EINVAL) { -		val = dw_pcie_readl_dbi(pci, pcie->pcie_cap_base + -					PCI_EXP_LNKCAP); -		val &= ~PCI_EXP_LNKCAP_SLS; -		val |= pcie->max_speed; -		dw_pcie_writel_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKCAP, -				   val); -	} -  	pcie->pcie_cap_base = dw_pcie_find_capability(&pcie->pci,  						      PCI_CAP_ID_EXP);  	clk_set_rate(pcie->core_clk, GEN4_CORE_CLK_FREQ); @@ -2066,6 +1999,9 @@ static int tegra_pcie_dw_probe(struct platform_device *pdev)  	pci = &pcie->pci;  	pci->dev = &pdev->dev;  	pci->ops = &tegra_dw_pcie_ops; +	pci->n_fts[0] = N_FTS_VAL; +	pci->n_fts[1] = FTS_VAL; +  	pp = &pci->pp;  	pcie->dev = &pdev->dev;  	pcie->mode = (enum dw_pcie_device_mode)data->mode; diff --git a/drivers/pci/controller/dwc/pcie-uniphier.c b/drivers/pci/controller/dwc/pcie-uniphier.c index 3a7f403b57b8..48176265c867 100644 --- a/drivers/pci/controller/dwc/pcie-uniphier.c +++ b/drivers/pci/controller/dwc/pcie-uniphier.c @@ -322,8 +322,7 @@ static int uniphier_pcie_host_init(struct pcie_port *pp)  	if (ret)  		return ret; -	if (IS_ENABLED(CONFIG_PCI_MSI)) -		dw_pcie_msi_init(pp); +	dw_pcie_msi_init(pp);  	return 0;  }  | 
