diff options
| author | Bjorn Helgaas <bhelgaas@google.com> | 2026-06-23 17:32:16 -0500 |
|---|---|---|
| committer | Bjorn Helgaas <bhelgaas@google.com> | 2026-06-23 17:32:16 -0500 |
| commit | 4e38ddba805ab84e65d6854133f1a98f77da0db0 (patch) | |
| tree | 59e78795233fe5af75de68008b117e1b41816a17 /drivers/pci | |
| parent | 7b900190125920e9e7e480a3075c9ee9c9de63bd (diff) | |
| parent | 8ba433753d9b131c2e43b1ff7ba8c5730cef8231 (diff) | |
| download | linux-next-4e38ddba805ab84e65d6854133f1a98f77da0db0.tar.gz linux-next-4e38ddba805ab84e65d6854133f1a98f77da0db0.zip | |
Merge branch 'pci/controller/mediatek-gen3'
- Deassert PCIE_PHY_RSTB so REFCLK is stable for at least 100ms
(PCIE_T_PVPERL_MS) before deasserting PERST# (Jian Yang)
- Add .shutdown() to assert PERST# before powering down device (Jian Yang)
- Do full device power down on removal, including asserting PERST#, when
removing driver (Chen-Yu Tsai)
- Fix a 'failed to create pwrctrl devices' error message that was
inadvertently skipped (Chen-Yu Tsai)
* pci/controller/mediatek-gen3:
PCI: mediatek-gen3: Fix incorrectly skipped pwrctrl error message
PCI: mediatek-gen3: Do full device power down on removal
PCI: mediatek-gen3: Add a .shutdown() callback to control PERST# signal
PCI: mediatek-gen3: Fix PERST# control timing during system startup
Diffstat (limited to 'drivers/pci')
| -rw-r--r-- | drivers/pci/controller/pcie-mediatek-gen3.c | 39 |
1 files changed, 34 insertions, 5 deletions
diff --git a/drivers/pci/controller/pcie-mediatek-gen3.c b/drivers/pci/controller/pcie-mediatek-gen3.c index b0accd828589..654e63f8fb57 100644 --- a/drivers/pci/controller/pcie-mediatek-gen3.c +++ b/drivers/pci/controller/pcie-mediatek-gen3.c @@ -63,6 +63,12 @@ #define PCIE_BRG_RSTB BIT(2) #define PCIE_PE_RSTB BIT(3) +/* + * As described in the datasheet of MediaTek PCIe Gen3 controller, wait 10ms + * after setting PCIE_BRG_RSTB, and before accessing PCIe internal registers. + */ +#define PCIE_BRG_RST_RDY_MS 10 + #define PCIE_LTSSM_STATUS_REG 0x150 #define PCIE_LTSSM_STATE_MASK GENMASK(28, 24) #define PCIE_LTSSM_STATE(val) ((val & PCIE_LTSSM_STATE_MASK) >> 24) @@ -431,6 +437,21 @@ static int mtk_pcie_devices_power_up(struct mtk_gen3_pcie *pcie) } /* + * Some of MediaTek's chips won't output REFCLK when PCIE_PHY_RSTB is + * asserted, we have to de-assert MAC & PHY & BRG reset signals first + * to allow the REFCLK to be stable. While PCIE_BRG_RSTB is asserted, + * there is a short period during which the PCIe internal register + * cannot be accessed, so we need to wait 10ms here. + */ + msleep(PCIE_BRG_RST_RDY_MS); + + if (!(pcie->soc->flags & SKIP_PCIE_RSTB)) { + /* De-assert MAC, PHY and BRG reset signals */ + val &= ~(PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB); + writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG); + } + + /* * Described in PCIe CEM specification revision 6.0. * * The deassertion of PERST# should be delayed 100ms (TPVPERL) @@ -439,9 +460,8 @@ static int mtk_pcie_devices_power_up(struct mtk_gen3_pcie *pcie) msleep(PCIE_T_PVPERL_MS); if (!(pcie->soc->flags & SKIP_PCIE_RSTB)) { - /* De-assert reset signals */ - val &= ~(PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB | - PCIE_PE_RSTB); + /* De-assert PERST# signal */ + val &= ~PCIE_PE_RSTB; writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG); } @@ -1222,8 +1242,8 @@ static int mtk_pcie_probe(struct platform_device *pdev) err = pci_pwrctrl_create_devices(pcie->dev); if (err) { - goto err_tear_down_irq; dev_err_probe(dev, err, "failed to create pwrctrl devices\n"); + goto err_tear_down_irq; } err = mtk_pcie_setup(pcie); @@ -1260,12 +1280,20 @@ static void mtk_pcie_remove(struct platform_device *pdev) pci_remove_root_bus(host->bus); pci_unlock_rescan_remove(); - pci_pwrctrl_power_off_devices(pcie->dev); + mtk_pcie_devices_power_down(pcie); mtk_pcie_power_down(pcie); pci_pwrctrl_destroy_devices(pcie->dev); mtk_pcie_irq_teardown(pcie); } +static void mtk_pcie_shutdown(struct platform_device *pdev) +{ + struct mtk_gen3_pcie *pcie = platform_get_drvdata(pdev); + + mtk_pcie_devices_power_down(pcie); + mtk_pcie_power_down(pcie); +} + static void mtk_pcie_irq_save(struct mtk_gen3_pcie *pcie) { int i; @@ -1404,6 +1432,7 @@ MODULE_DEVICE_TABLE(of, mtk_pcie_of_match); static struct platform_driver mtk_pcie_driver = { .probe = mtk_pcie_probe, .remove = mtk_pcie_remove, + .shutdown = mtk_pcie_shutdown, .driver = { .name = "mtk-pcie-gen3", .of_match_table = mtk_pcie_of_match, |
