diff options
Diffstat (limited to 'drivers/pci/controller/dwc/pci-imx6.c')
| -rw-r--r-- | drivers/pci/controller/dwc/pci-imx6.c | 37 | 
1 files changed, 35 insertions, 2 deletions
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c index 9b5cb5b70389..acfbd34032a8 100644 --- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -57,6 +57,7 @@ enum imx6_pcie_variants {  struct imx6_pcie_drvdata {  	enum imx6_pcie_variants variant;  	u32 flags; +	int dbi_length;  };  struct imx6_pcie { @@ -1173,8 +1174,8 @@ static int imx6_pcie_probe(struct platform_device *pdev)  	imx6_pcie->vpcie = devm_regulator_get_optional(&pdev->dev, "vpcie");  	if (IS_ERR(imx6_pcie->vpcie)) { -		if (PTR_ERR(imx6_pcie->vpcie) == -EPROBE_DEFER) -			return -EPROBE_DEFER; +		if (PTR_ERR(imx6_pcie->vpcie) != -ENODEV) +			return PTR_ERR(imx6_pcie->vpcie);  		imx6_pcie->vpcie = NULL;  	} @@ -1212,6 +1213,7 @@ static const struct imx6_pcie_drvdata drvdata[] = {  		.variant = IMX6Q,  		.flags = IMX6_PCIE_FLAG_IMX6_PHY |  			 IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE, +		.dbi_length = 0x200,  	},  	[IMX6SX] = {  		.variant = IMX6SX, @@ -1254,6 +1256,37 @@ static struct platform_driver imx6_pcie_driver = {  	.shutdown = imx6_pcie_shutdown,  }; +static void imx6_pcie_quirk(struct pci_dev *dev) +{ +	struct pci_bus *bus = dev->bus; +	struct pcie_port *pp = bus->sysdata; + +	/* Bus parent is the PCI bridge, its parent is this platform driver */ +	if (!bus->dev.parent || !bus->dev.parent->parent) +		return; + +	/* Make sure we only quirk devices associated with this driver */ +	if (bus->dev.parent->parent->driver != &imx6_pcie_driver.driver) +		return; + +	if (bus->number == pp->root_bus_nr) { +		struct dw_pcie *pci = to_dw_pcie_from_pp(pp); +		struct imx6_pcie *imx6_pcie = to_imx6_pcie(pci); + +		/* +		 * Limit config length to avoid the kernel reading beyond +		 * the register set and causing an abort on i.MX 6Quad +		 */ +		if (imx6_pcie->drvdata->dbi_length) { +			dev->cfg_size = imx6_pcie->drvdata->dbi_length; +			dev_info(&dev->dev, "Limiting cfg_size to %d\n", +					dev->cfg_size); +		} +	} +} +DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_SYNOPSYS, 0xabcd, +			PCI_CLASS_BRIDGE_PCI, 8, imx6_pcie_quirk); +  static int __init imx6_pcie_init(void)  {  #ifdef CONFIG_ARM  |