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/pci-aardvark.c | |
| 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/pci-aardvark.c')
| -rw-r--r-- | drivers/pci/controller/pci-aardvark.c | 108 | 
1 files changed, 69 insertions, 39 deletions
diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c index 1559f79e63b6..0be485a25327 100644 --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c @@ -9,11 +9,12 @@   */  #include <linux/delay.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h>  #include <linux/interrupt.h>  #include <linux/irq.h>  #include <linux/irqdomain.h>  #include <linux/kernel.h> +#include <linux/module.h>  #include <linux/pci.h>  #include <linux/init.h>  #include <linux/phy/phy.h> @@ -251,6 +252,25 @@ static void advk_pcie_wait_for_retrain(struct advk_pcie *pcie)  	}  } +static void advk_pcie_issue_perst(struct advk_pcie *pcie) +{ +	u32 reg; + +	if (!pcie->reset_gpio) +		return; + +	/* PERST does not work for some cards when link training is enabled */ +	reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG); +	reg &= ~LINK_TRAINING_EN; +	advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG); + +	/* 10ms delay is needed for some cards */ +	dev_info(&pcie->pdev->dev, "issuing PERST via reset GPIO for 10ms\n"); +	gpiod_set_value_cansleep(pcie->reset_gpio, 1); +	usleep_range(10000, 11000); +	gpiod_set_value_cansleep(pcie->reset_gpio, 0); +} +  static int advk_pcie_train_at_gen(struct advk_pcie *pcie, int gen)  {  	int ret, neg_gen; @@ -299,6 +319,21 @@ static void advk_pcie_train_link(struct advk_pcie *pcie)  	int neg_gen = -1, gen;  	/* +	 * Reset PCIe card via PERST# signal. Some cards are not detected +	 * during link training when they are in some non-initial state. +	 */ +	advk_pcie_issue_perst(pcie); + +	/* +	 * PERST# signal could have been asserted by pinctrl subsystem before +	 * probe() callback has been called or issued explicitly by reset gpio +	 * function advk_pcie_issue_perst(), making the endpoint going into +	 * fundamental reset. As required by PCI Express spec a delay for at +	 * least 100ms after such a reset before link training is needed. +	 */ +	msleep(PCI_PM_D3COLD_WAIT); + +	/*  	 * Try link training at link gen specified by device tree property  	 * 'max-link-speed'. If this fails, iteratively train at lower gen.  	 */ @@ -330,31 +365,10 @@ err:  	dev_err(dev, "link never came up\n");  } -static void advk_pcie_issue_perst(struct advk_pcie *pcie) -{ -	u32 reg; - -	if (!pcie->reset_gpio) -		return; - -	/* PERST does not work for some cards when link training is enabled */ -	reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG); -	reg &= ~LINK_TRAINING_EN; -	advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG); - -	/* 10ms delay is needed for some cards */ -	dev_info(&pcie->pdev->dev, "issuing PERST via reset GPIO for 10ms\n"); -	gpiod_set_value_cansleep(pcie->reset_gpio, 1); -	usleep_range(10000, 11000); -	gpiod_set_value_cansleep(pcie->reset_gpio, 0); -} -  static void advk_pcie_setup_hw(struct advk_pcie *pcie)  {  	u32 reg; -	advk_pcie_issue_perst(pcie); -  	/* Enable TX */  	reg = advk_readl(pcie, PCIE_CORE_REF_CLK_REG);  	reg |= PCIE_CORE_REF_CLK_TX_ENABLE; @@ -431,15 +445,6 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie)  	reg |= PIO_CTRL_ADDR_WIN_DISABLE;  	advk_writel(pcie, reg, PIO_CTRL); -	/* -	 * PERST# signal could have been asserted by pinctrl subsystem before -	 * probe() callback has been called or issued explicitly by reset gpio -	 * function advk_pcie_issue_perst(), making the endpoint going into -	 * fundamental reset. As required by PCI Express spec a delay for at -	 * least 100ms after such a reset before link training is needed. -	 */ -	msleep(PCI_PM_D3COLD_WAIT); -  	advk_pcie_train_link(pcie);  	/* @@ -607,7 +612,7 @@ static struct pci_bridge_emul_ops advk_pci_bridge_emul_ops = {   * Initialize the configuration space of the PCI-to-PCI bridge   * associated with the given PCIe interface.   */ -static void advk_sw_pci_bridge_init(struct advk_pcie *pcie) +static int advk_sw_pci_bridge_init(struct advk_pcie *pcie)  {  	struct pci_bridge_emul *bridge = &pcie->bridge; @@ -633,8 +638,7 @@ static void advk_sw_pci_bridge_init(struct advk_pcie *pcie)  	bridge->data = pcie;  	bridge->ops = &advk_pci_bridge_emul_ops; -	pci_bridge_emul_init(bridge, 0); - +	return pci_bridge_emul_init(bridge, 0);  }  static bool advk_pcie_valid_device(struct advk_pcie *pcie, struct pci_bus *bus, @@ -1077,7 +1081,9 @@ static int advk_pcie_enable_phy(struct advk_pcie *pcie)  	}  	ret = phy_power_on(pcie->phy); -	if (ret) { +	if (ret == -EOPNOTSUPP) { +		dev_warn(&pcie->pdev->dev, "PHY unsupported by firmware\n"); +	} else if (ret) {  		phy_exit(pcie->phy);  		return ret;  	} @@ -1122,6 +1128,7 @@ static int advk_pcie_probe(struct platform_device *pdev)  	pcie = pci_host_bridge_priv(bridge);  	pcie->pdev = pdev; +	platform_set_drvdata(pdev, pcie);  	pcie->base = devm_platform_ioremap_resource(pdev, 0);  	if (IS_ERR(pcie->base)) @@ -1167,7 +1174,11 @@ static int advk_pcie_probe(struct platform_device *pdev)  	advk_pcie_setup_hw(pcie); -	advk_sw_pci_bridge_init(pcie); +	ret = advk_sw_pci_bridge_init(pcie); +	if (ret) { +		dev_err(dev, "Failed to register emulated root PCI bridge\n"); +		return ret; +	}  	ret = advk_pcie_init_irq_domain(pcie);  	if (ret) { @@ -1195,18 +1206,37 @@ static int advk_pcie_probe(struct platform_device *pdev)  	return 0;  } +static int advk_pcie_remove(struct platform_device *pdev) +{ +	struct advk_pcie *pcie = platform_get_drvdata(pdev); +	struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie); + +	pci_lock_rescan_remove(); +	pci_stop_root_bus(bridge->bus); +	pci_remove_root_bus(bridge->bus); +	pci_unlock_rescan_remove(); + +	advk_pcie_remove_msi_irq_domain(pcie); +	advk_pcie_remove_irq_domain(pcie); + +	return 0; +} +  static const struct of_device_id advk_pcie_of_match_table[] = {  	{ .compatible = "marvell,armada-3700-pcie", },  	{},  }; +MODULE_DEVICE_TABLE(of, advk_pcie_of_match_table);  static struct platform_driver advk_pcie_driver = {  	.driver = {  		.name = "advk-pcie",  		.of_match_table = advk_pcie_of_match_table, -		/* Driver unloading/unbinding currently not supported */ -		.suppress_bind_attrs = true,  	},  	.probe = advk_pcie_probe, +	.remove = advk_pcie_remove,  }; -builtin_platform_driver(advk_pcie_driver); +module_platform_driver(advk_pcie_driver); + +MODULE_DESCRIPTION("Aardvark PCIe controller"); +MODULE_LICENSE("GPL v2");  | 
