diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/dwc/pci-imx6.c | 156 | ||||
-rw-r--r-- | drivers/pci/probe.c | 7 | ||||
-rw-r--r-- | drivers/pci/quirks.c | 24 |
3 files changed, 99 insertions, 88 deletions
diff --git a/drivers/pci/dwc/pci-imx6.c b/drivers/pci/dwc/pci-imx6.c index 54459b52f526..7855ded3102f 100644 --- a/drivers/pci/dwc/pci-imx6.c +++ b/drivers/pci/dwc/pci-imx6.c @@ -70,19 +70,19 @@ struct imx_pcie { u32 ctrl_id; u32 cpu_base; u32 hard_wired; - int clkreq_gpio; - int dis_gpio; - int power_on_gpio; - int reset_gpio; + struct gpio_desc *clkreq_gpiod; + struct gpio_desc *dis_gpiod; + struct gpio_desc *power_on_gpiod; + struct gpio_desc *reset_gpiod; bool gpio_active_high; struct clk *pcie_bus; struct clk *pcie_phy; struct clk *pcie_inbound_axi; - struct clk *pcie_per; struct clk *pcie; + struct clk *pcie_ext; struct clk *pcie_ext_src; struct regmap *iomuxc_gpr; - enum imx_pcie_variants variant; + enum imx_pcie_variants variant; u32 hsio_cfg; u32 tx_deemph_gen1; u32 tx_deemph_gen2_3p5db; @@ -640,17 +640,8 @@ static int imx_pcie_enable_ref_clk(struct imx_pcie *imx_pcie) case IMX8QXP: case IMX8QM: ret = clk_prepare_enable(imx_pcie->pcie_inbound_axi); - if (ret) { + if (ret) dev_err(dev, "unable to enable pcie_axi clock\n"); - break; - } - ret = clk_prepare_enable(imx_pcie->pcie_per); - if (ret) { - dev_err(dev, "unable to enable pcie_per clock\n"); - clk_disable_unprepare(imx_pcie->pcie_inbound_axi); - break; - } - break; } @@ -764,8 +755,15 @@ static int imx_pcie_deassert_core_reset(struct imx_pcie *imx_pcie) } } - if (gpio_is_valid(imx_pcie->power_on_gpio)) - gpio_set_value_cansleep(imx_pcie->power_on_gpio, 1); + if (imx_pcie->power_on_gpiod) + gpiod_set_value_cansleep(imx_pcie->power_on_gpiod, 1); + + if (imx_pcie->clkreq_gpiod) + gpiod_set_value_cansleep(imx_pcie->clkreq_gpiod, 1); + + mdelay(2); + if (imx_pcie->dis_gpiod) + gpiod_set_value_cansleep(imx_pcie->dis_gpiod, 0); ret = clk_prepare_enable(imx_pcie->pcie); if (ret) { @@ -782,6 +780,12 @@ static int imx_pcie_deassert_core_reset(struct imx_pcie *imx_pcie) goto err_pcie_bus; } + ret = clk_prepare_enable(imx_pcie->pcie_ext); + if (ret) { + dev_err(dev, "unable to enable pcie_ext clock\n"); + goto err_pcie_bus; + } + ret = clk_prepare_enable(imx_pcie->pcie_phy); if (ret) { dev_err(dev, "unable to enable pcie_phy clock\n"); @@ -955,12 +959,12 @@ static int imx_pcie_deassert_core_reset(struct imx_pcie *imx_pcie) } /* Some boards don't have PCIe reset GPIO. */ - if (gpio_is_valid(imx_pcie->reset_gpio)) { - gpio_set_value_cansleep(imx_pcie->reset_gpio, - imx_pcie->gpio_active_high); - mdelay(20); - gpio_set_value_cansleep(imx_pcie->reset_gpio, + if (imx_pcie->reset_gpiod) { + gpiod_set_value_cansleep(imx_pcie->reset_gpiod, !imx_pcie->gpio_active_high); + mdelay(100); + gpiod_set_value_cansleep(imx_pcie->reset_gpiod, + imx_pcie->gpio_active_high); mdelay(20); } @@ -1495,7 +1499,6 @@ static void pci_imx_clk_disable(struct device *dev) break; case IMX8QXP: case IMX8QM: - clk_disable_unprepare(imx_pcie->pcie_per); clk_disable_unprepare(imx_pcie->pcie_inbound_axi); break; } @@ -2049,8 +2052,9 @@ static void pci_imx_pm_turn_off(struct imx_pcie *imx_pcie) } udelay(1000); - if (gpio_is_valid(imx_pcie->reset_gpio)) - gpio_set_value_cansleep(imx_pcie->reset_gpio, 0); + if (imx_pcie->reset_gpiod) + gpiod_set_value_cansleep(imx_pcie->reset_gpiod, + !imx_pcie->gpio_active_high); } static int pci_imx_suspend_noirq(struct device *dev) @@ -2074,6 +2078,8 @@ static int pci_imx_suspend_noirq(struct device *dev) IMX6Q_GPR1_PCIE_TEST_PD, IMX6Q_GPR1_PCIE_TEST_PD); } else { + pm_runtime_put_sync(dev); + pci_imx_clk_disable(dev); imx_pcie_phy_pwr_dn(imx_pcie); @@ -2142,6 +2148,8 @@ static int pci_imx_resume_noirq(struct device *dev) regmap_update_bits(imx_pcie->iomuxc_gpr, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_TEST_PD, 0); } else { + pm_runtime_get_sync(dev); + pci_imx_ltssm_disable(dev); imx_pcie_assert_core_reset(imx_pcie); imx_pcie_init_phy(imx_pcie); @@ -2335,59 +2343,42 @@ static int imx_pcie_probe(struct platform_device *pdev) } /* Fetch GPIOs */ - imx_pcie->clkreq_gpio = of_get_named_gpio(node, "clkreq-gpio", 0); - if (gpio_is_valid(imx_pcie->clkreq_gpio)) { - ret = devm_gpio_request_one(&pdev->dev, imx_pcie->clkreq_gpio, - GPIOF_OUT_INIT_LOW, "PCIe CLKREQ"); - if (ret) { + imx_pcie->clkreq_gpiod = devm_gpiod_get_optional(dev, "clkreq", + GPIOD_OUT_LOW); + if (IS_ERR(imx_pcie->clkreq_gpiod)) { + ret = PTR_ERR(imx_pcie->clkreq_gpiod); + if (ret != -EPROBE_DEFER) dev_err(&pdev->dev, "unable to get clkreq gpio\n"); - return ret; - } - } else if (imx_pcie->clkreq_gpio == -EPROBE_DEFER) { - return imx_pcie->clkreq_gpio; + return ret; } - imx_pcie->dis_gpio = of_get_named_gpio(node, "disable-gpio", 0); - if (gpio_is_valid(imx_pcie->dis_gpio)) { - ret = devm_gpio_request_one(&pdev->dev, imx_pcie->dis_gpio, - GPIOF_OUT_INIT_HIGH, "PCIe DIS"); - if (ret) { + imx_pcie->dis_gpiod = devm_gpiod_get_optional(dev, "disable", + GPIOD_OUT_LOW); + if (IS_ERR(imx_pcie->dis_gpiod)) { + ret = PTR_ERR(imx_pcie->dis_gpiod); + if (ret != -EPROBE_DEFER) dev_err(&pdev->dev, "unable to get disable gpio\n"); - return ret; - } - } else if (imx_pcie->dis_gpio == -EPROBE_DEFER) { - return imx_pcie->dis_gpio; + return ret; } - imx_pcie->power_on_gpio = of_get_named_gpio(node, "power-on-gpio", 0); - if (gpio_is_valid(imx_pcie->power_on_gpio)) { - ret = devm_gpio_request_one(&pdev->dev, - imx_pcie->power_on_gpio, - GPIOF_OUT_INIT_LOW, - "PCIe power enable"); - if (ret) { + imx_pcie->power_on_gpiod = devm_gpiod_get_optional(dev, "power-on", + GPIOD_OUT_LOW); + if (IS_ERR(imx_pcie->power_on_gpiod)) { + ret = PTR_ERR(imx_pcie->power_on_gpiod); + if (ret != -EPROBE_DEFER) dev_err(&pdev->dev, "unable to get power-on gpio\n"); - return ret; - } - } else if (imx_pcie->power_on_gpio == -EPROBE_DEFER) { - return imx_pcie->power_on_gpio; - } - - imx_pcie->reset_gpio = of_get_named_gpio(node, "reset-gpio", 0); - imx_pcie->gpio_active_high = of_property_read_bool(node, - "reset-gpio-active-high"); - if (gpio_is_valid(imx_pcie->reset_gpio)) { - ret = devm_gpio_request_one(dev, imx_pcie->reset_gpio, - imx_pcie->gpio_active_high ? - GPIOF_OUT_INIT_HIGH : - GPIOF_OUT_INIT_LOW, - "PCIe reset"); - if (ret) { + return ret; + } + + imx_pcie->reset_gpiod = devm_gpiod_get_optional(dev, "reset", + imx_pcie->gpio_active_high ? + GPIOD_OUT_LOW : + GPIOD_OUT_HIGH); + if (IS_ERR(imx_pcie->reset_gpiod)) { + ret = PTR_ERR(imx_pcie->reset_gpiod); + if (ret != -EPROBE_DEFER) dev_err(dev, "unable to get reset gpio\n"); - return ret; - } - } else if (imx_pcie->reset_gpio == -EPROBE_DEFER) { - return imx_pcie->reset_gpio; + return ret; } imx_pcie->epdev_on = devm_regulator_get(&pdev->dev, "epdev_on"); @@ -2418,15 +2409,18 @@ static int imx_pcie_probe(struct platform_device *pdev) if (of_property_read_u32(node, "ext_osc", &imx_pcie->ext_osc) < 0) imx_pcie->ext_osc = 0; - if (imx_pcie->ext_osc && (imx_pcie->variant == IMX6QP)) { + if (imx_pcie->ext_osc && (imx_pcie->variant == IMX6QP || + imx_pcie->variant == IMX8QM)) { /* Change the pcie_bus clock to pcie external OSC */ - imx_pcie->pcie_bus = devm_clk_get(&pdev->dev, "pcie_ext"); - if (IS_ERR(imx_pcie->pcie_bus)) { + imx_pcie->pcie_ext = devm_clk_get(&pdev->dev, "pcie_ext"); + if (IS_ERR(imx_pcie->pcie_ext)) { dev_err(&pdev->dev, - "pcie_bus clock source missing or invalid\n"); - return PTR_ERR(imx_pcie->pcie_bus); + "pcie_ext clock source missing or invalid\n"); + return PTR_ERR(imx_pcie->pcie_ext); } + } + if (imx_pcie->ext_osc && (imx_pcie->variant == IMX6QP)) { imx_pcie->pcie_ext_src = devm_clk_get(&pdev->dev, "pcie_ext_src"); if (IS_ERR(imx_pcie->pcie_ext_src)) { @@ -2502,12 +2496,6 @@ static int imx_pcie_probe(struct platform_device *pdev) ("fsl,imx6sx-iomuxc-gpr"); } else if (imx_pcie->variant == IMX8QM || imx_pcie->variant == IMX8QXP) { - imx_pcie->pcie_per = devm_clk_get(dev, "pcie_per"); - if (IS_ERR(imx_pcie->pcie_per)) { - dev_err(dev, "pcie_per clock source missing or invalid\n"); - return PTR_ERR(imx_pcie->pcie_per); - } - imx_pcie->iomuxc_gpr = syscon_regmap_lookup_by_phandle(node, "hsio"); imx_pcie->pcie_inbound_axi = devm_clk_get(&pdev->dev, @@ -2823,6 +2811,8 @@ static int imx_pcie_probe(struct platform_device *pdev) && (imx_pcie->hard_wired == 0)) imx_pcie_regions_setup(&pdev->dev); } + pm_runtime_get_sync(&pdev->dev); + return 0; } @@ -2833,6 +2823,8 @@ static void imx_pcie_shutdown(struct platform_device *pdev) /* bring down link, so bootloader gets clean state in case of reboot */ if (imx_pcie->variant == IMX6Q) imx_pcie_assert_core_reset(imx_pcie); + + pm_runtime_put_sync(&pdev->dev); } static const struct of_device_id imx_pcie_of_match[] = { diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index e23bfd9845b1..537d5db15781 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1078,8 +1078,7 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass) child = pci_add_new_bus(bus, dev, max+1); if (!child) goto out; - pci_bus_insert_busn_res(child, max+1, - bus->busn_res.end); + pci_bus_insert_busn_res(child, max+1, 0xff); } max++; buses = (buses & 0xff000000) @@ -2440,10 +2439,6 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus) if (bus->self && bus->self->is_hotplug_bridge && pci_hotplug_bus_size) { if (max - bus->busn_res.start < pci_hotplug_bus_size - 1) max = bus->busn_res.start + pci_hotplug_bus_size - 1; - - /* Do not allocate more buses than we have room left */ - if (max > bus->busn_res.end) - max = bus->busn_res.end; } /* diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 754073ff99cc..0d09e358412d 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2358,6 +2358,21 @@ static void quirk_tile_plx_gen1(struct pci_dev *dev) DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8624, quirk_tile_plx_gen1); #endif /* CONFIG_TILEPRO */ +#ifdef CONFIG_PCI_FORCE_GEN1 +/* + * The Apalis evaluation board needs to set the link speed to 2.5 GT/s (GEN1). + * The default link speed setting is 5 GT/s (GEN2). 0x98 is the Link Control 2 + * PCIe Capability Register of the PEX8605 PCIe switch. The switch supports + * link speed auto negotiation, but falsely sets the link speed to 5 GT/s. + */ +static void quirk_apalis_plx_gen1(struct pci_dev *dev) +{ + pci_write_config_dword(dev, 0x98, 0x1); + mdelay(50); +} +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8605, quirk_apalis_plx_gen1); +#endif /* CONFIG_PCI_FORCE_GEN1 */ + #ifdef CONFIG_PCI_MSI /* Some chipsets do not support MSI. We cannot easily rely on setting * PCI_BUS_FLAGS_NO_MSI in its bus flags because there are actually @@ -3015,6 +3030,15 @@ static void fixup_ti816x_class(struct pci_dev *dev) DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_TI, 0xb800, PCI_CLASS_NOT_DEFINED, 8, fixup_ti816x_class); +/* TW6869 Frame grabber has same problem as ti816x */ +static void fixup_tw6869_class(struct pci_dev* dev) +{ + dev_info(&dev->dev, "Setting PCI class for tw6869 PCIe device\n"); + dev->class = PCI_CLASS_MULTIMEDIA_VIDEO; +} +DECLARE_PCI_FIXUP_CLASS_EARLY(0x1797, 0x6869, + PCI_CLASS_NOT_DEFINED, 0, fixup_tw6869_class); + /* Some PCIe devices do not work reliably with the claimed maximum * payload size supported. */ |