Commit f0d9ac75 authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

Merge branches 'pci/host-dra7xx' and 'pci/host-iproc' into next

* pci/host-dra7xx:
  ARM: dts: am57xx-evm: Add 'gpios' property with gpio2_8
  PCI: dra7xx: Add support to make GPIO drive PERST# line
  PCI: dra7xx: Clear MSE bit during suspend so clocks will idle
  PCI: dra7xx: Add PM support
  PCI: dra7xx: Disable pm_runtime on get_sync failure

* pci/host-iproc:
  PCI: iproc: Allow BCMA bus driver to be built as module
  PCI: iproc: Add arm64 support
  PCI: iproc: Delete unnecessary checks before phy calls
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -23,6 +23,9 @@ PCIe Designware Controller
   interrupt-map-mask,
   interrupt-map : as specified in ../designware-pcie.txt

Optional Property:
 - gpios : Should be added if a gpio line is required to drive PERST# line

Example:
axi {
	compatible = "simple-bus";
+4 −0
Original line number Diff line number Diff line
@@ -693,3 +693,7 @@
		};
	};
};

&pcie1 {
	gpios = <&gpio2 8 GPIO_ACTIVE_LOW>;
};
+1 −1
Original line number Diff line number Diff line
@@ -211,7 +211,7 @@
			#address-cells = <1>;
			ranges = <0x51000000 0x51000000 0x3000
				  0x0	     0x20000000 0x10000000>;
			pcie@51000000 {
			pcie1: pcie@51000000 {
				compatible = "ti,dra7-pcie";
				reg = <0x51000000 0x2000>, <0x51002000 0x14c>, <0x1000 0x2000>;
				reg-names = "rc_dbics", "ti_conf", "config";
+1 −1
Original line number Diff line number Diff line
@@ -135,7 +135,7 @@ config PCIE_IPROC_PLATFORM
	  through the generic platform bus interface

config PCIE_IPROC_BCMA
	bool "Broadcom iProc PCIe BCMA bus driver"
	tristate "Broadcom iProc PCIe BCMA bus driver"
	depends on ARCH_BCM_IPROC || (ARM && COMPILE_TEST)
	select PCIE_IPROC
	select BCMA
+116 −3
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <linux/irqdomain.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/pci.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
@@ -83,6 +84,17 @@ static inline void dra7xx_pcie_writel(struct dra7xx_pcie *pcie, u32 offset,
	writel(value, pcie->base + offset);
}

static inline u32 dra7xx_pcie_readl_rc(struct pcie_port *pp, u32 offset)
{
	return readl(pp->dbi_base + offset);
}

static inline void dra7xx_pcie_writel_rc(struct pcie_port *pp, u32 offset,
					 u32 value)
{
	writel(value, pp->dbi_base + offset);
}

static int dra7xx_pcie_link_up(struct pcie_port *pp)
{
	struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pp);
@@ -324,6 +336,9 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
	struct device *dev = &pdev->dev;
	struct device_node *np = dev->of_node;
	char name[10];
	int gpio_sel;
	enum of_gpio_flags flags;
	unsigned long gpio_flags;

	dra7xx = devm_kzalloc(dev, sizeof(*dra7xx), GFP_KERNEL);
	if (!dra7xx)
@@ -383,7 +398,23 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
	ret = pm_runtime_get_sync(dev);
	if (IS_ERR_VALUE(ret)) {
		dev_err(dev, "pm_runtime_get_sync failed\n");
		goto err_phy;
		goto err_get_sync;
	}

	gpio_sel = of_get_gpio_flags(dev->of_node, 0, &flags);
	if (gpio_is_valid(gpio_sel)) {
		gpio_flags = (flags & OF_GPIO_ACTIVE_LOW) ?
				GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH;
		ret = devm_gpio_request_one(dev, gpio_sel, gpio_flags,
					    "pcie_reset");
		if (ret) {
			dev_err(&pdev->dev, "gpio%d request failed, ret %d\n",
				gpio_sel, ret);
			goto err_gpio;
		}
	} else if (gpio_sel == -EPROBE_DEFER) {
		ret = -EPROBE_DEFER;
		goto err_gpio;
	}

	reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD);
@@ -394,12 +425,14 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)

	ret = dra7xx_add_pcie_port(dra7xx, pdev);
	if (ret < 0)
		goto err_add_port;
		goto err_gpio;

	return 0;

err_add_port:
err_gpio:
	pm_runtime_put(dev);

err_get_sync:
	pm_runtime_disable(dev);

err_phy:
@@ -430,6 +463,85 @@ static int __exit dra7xx_pcie_remove(struct platform_device *pdev)
	return 0;
}

#ifdef CONFIG_PM_SLEEP
static int dra7xx_pcie_suspend(struct device *dev)
{
	struct dra7xx_pcie *dra7xx = dev_get_drvdata(dev);
	struct pcie_port *pp = &dra7xx->pp;
	u32 val;

	/* clear MSE */
	val = dra7xx_pcie_readl_rc(pp, PCI_COMMAND);
	val &= ~PCI_COMMAND_MEMORY;
	dra7xx_pcie_writel_rc(pp, PCI_COMMAND, val);

	return 0;
}

static int dra7xx_pcie_resume(struct device *dev)
{
	struct dra7xx_pcie *dra7xx = dev_get_drvdata(dev);
	struct pcie_port *pp = &dra7xx->pp;
	u32 val;

	/* set MSE */
	val = dra7xx_pcie_readl_rc(pp, PCI_COMMAND);
	val |= PCI_COMMAND_MEMORY;
	dra7xx_pcie_writel_rc(pp, PCI_COMMAND, val);

	return 0;
}

static int dra7xx_pcie_suspend_noirq(struct device *dev)
{
	struct dra7xx_pcie *dra7xx = dev_get_drvdata(dev);
	int count = dra7xx->phy_count;

	while (count--) {
		phy_power_off(dra7xx->phy[count]);
		phy_exit(dra7xx->phy[count]);
	}

	return 0;
}

static int dra7xx_pcie_resume_noirq(struct device *dev)
{
	struct dra7xx_pcie *dra7xx = dev_get_drvdata(dev);
	int phy_count = dra7xx->phy_count;
	int ret;
	int i;

	for (i = 0; i < phy_count; i++) {
		ret = phy_init(dra7xx->phy[i]);
		if (ret < 0)
			goto err_phy;

		ret = phy_power_on(dra7xx->phy[i]);
		if (ret < 0) {
			phy_exit(dra7xx->phy[i]);
			goto err_phy;
		}
	}

	return 0;

err_phy:
	while (--i >= 0) {
		phy_power_off(dra7xx->phy[i]);
		phy_exit(dra7xx->phy[i]);
	}

	return ret;
}
#endif

static const struct dev_pm_ops dra7xx_pcie_pm_ops = {
	SET_SYSTEM_SLEEP_PM_OPS(dra7xx_pcie_suspend, dra7xx_pcie_resume)
	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(dra7xx_pcie_suspend_noirq,
				      dra7xx_pcie_resume_noirq)
};

static const struct of_device_id of_dra7xx_pcie_match[] = {
	{ .compatible = "ti,dra7-pcie", },
	{},
@@ -441,6 +553,7 @@ static struct platform_driver dra7xx_pcie_driver = {
	.driver = {
		.name	= "dra7-pcie",
		.of_match_table = of_dra7xx_pcie_match,
		.pm	= &dra7xx_pcie_pm_ops,
	},
};

Loading