Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bde4a5a0 authored by Andrey Smirnov's avatar Andrey Smirnov Committed by Bjorn Helgaas
Browse files

PCI: imx6: Allow probe deferral by reset GPIO



Some designs implement reset GPIO via a GPIO expander connected to a
peripheral bus.  One such example would be i.MX7 Sabre board where said
GPIO is provided by SPI shift register connected to a bitbanged SPI bus.
To support such designs, allow reset GPIO request to defer probing of the
driver.

Signed-off-by: default avatarAndrey Smirnov <andrew.smirnov@gmail.com>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Reviewed-by: default avatarLucas Stach <l.stach@pengutronix.de>
Cc: yurovsky@gmail.com
Cc: Fabio Estevam <fabio.estevam@nxp.com>
Cc: Dong Aisheng <dongas86@gmail.com>
Cc: linux-arm-kernel@lists.infradead.org
parent 9b3fe679
Loading
Loading
Loading
Loading
+17 −8
Original line number Diff line number Diff line
@@ -595,7 +595,7 @@ static struct dw_pcie_host_ops imx6_pcie_host_ops = {
	.host_init = imx6_pcie_host_init,
};

static int __init imx6_add_pcie_port(struct imx6_pcie *imx6_pcie,
static int imx6_add_pcie_port(struct imx6_pcie *imx6_pcie,
			      struct platform_device *pdev)
{
	struct dw_pcie *pci = imx6_pcie->pci;
@@ -636,7 +636,7 @@ static const struct dw_pcie_ops dw_pcie_ops = {
	.link_up = imx6_pcie_link_up,
};

static int __init imx6_pcie_probe(struct platform_device *pdev)
static int imx6_pcie_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct dw_pcie *pci;
@@ -660,10 +660,6 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
	imx6_pcie->variant =
		(enum imx6_pcie_variants)of_device_get_match_data(dev);

	/* Added for PCI abort handling */
	hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0,
		"imprecise external abort");

	dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	pci->dbi_base = devm_ioremap_resource(dev, dbi_base);
	if (IS_ERR(pci->dbi_base))
@@ -683,6 +679,8 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
			dev_err(dev, "unable to get reset gpio\n");
			return ret;
		}
	} else if (imx6_pcie->reset_gpio == -EPROBE_DEFER) {
		return imx6_pcie->reset_gpio;
	}

	/* Fetch clocks */
@@ -796,11 +794,22 @@ static struct platform_driver imx6_pcie_driver = {
		.name	= "imx6q-pcie",
		.of_match_table = imx6_pcie_of_match,
	},
	.probe    = imx6_pcie_probe,
	.shutdown = imx6_pcie_shutdown,
};

static int __init imx6_pcie_init(void)
{
	return platform_driver_probe(&imx6_pcie_driver, imx6_pcie_probe);
	/*
	 * Since probe() can be deferred we need to make sure that
	 * hook_fault_code is not called after __init memory is freed
	 * by kernel and since imx6q_pcie_abort_handler() is a no-op,
	 * we can install the handler here without risking it
	 * accessing some uninitialized driver state.
	 */
	hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0,
			"imprecise external abort");

	return platform_driver_register(&imx6_pcie_driver);
}
device_initcall(imx6_pcie_init);