]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
PCI: brcmstb: Use swinit reset if available
authorJim Quinlan <james.quinlan@broadcom.com>
Thu, 15 Aug 2024 22:57:19 +0000 (18:57 -0400)
committerKrzysztof Wilczyński <kwilczynski@kernel.org>
Wed, 4 Sep 2024 13:59:28 +0000 (13:59 +0000)
The 7712 SoC adds a software init reset device for the PCIe HW.

If found in the DT node, use it.

Link: https://lore.kernel.org/linux-pci/20240815225731.40276-7-james.quinlan@broadcom.com
Signed-off-by: Jim Quinlan <james.quinlan@broadcom.com>
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
drivers/pci/controller/pcie-brcmstb.c

index f8b6765d2e654407901a866de85940777025335d..926644eff39d3e75da3891a9d37c1ce2832af9a2 100644 (file)
@@ -266,6 +266,7 @@ struct brcm_pcie {
        struct reset_control    *rescal;
        struct reset_control    *perst_reset;
        struct reset_control    *bridge_reset;
+       struct reset_control    *swinit_reset;
        int                     num_memc;
        u64                     memc_size[PCIE_BRCM_MAX_MEMC];
        u32                     hw_rev;
@@ -1635,12 +1636,35 @@ static int brcm_pcie_probe(struct platform_device *pdev)
        if (IS_ERR(pcie->bridge_reset))
                return PTR_ERR(pcie->bridge_reset);
 
+       pcie->swinit_reset = devm_reset_control_get_optional_exclusive(&pdev->dev, "swinit");
+       if (IS_ERR(pcie->swinit_reset))
+               return PTR_ERR(pcie->swinit_reset);
+
        ret = clk_prepare_enable(pcie->clk);
        if (ret)
                return dev_err_probe(&pdev->dev, ret, "could not enable clock\n");
 
        pcie->bridge_sw_init_set(pcie, 0);
 
+       if (pcie->swinit_reset) {
+               ret = reset_control_assert(pcie->swinit_reset);
+               if (ret) {
+                       clk_disable_unprepare(pcie->clk);
+                       return dev_err_probe(&pdev->dev, ret,
+                                            "could not assert reset 'swinit'\n");
+               }
+
+               /* HW team recommends 1us for proper sync and propagation of reset */
+               udelay(1);
+
+               ret = reset_control_deassert(pcie->swinit_reset);
+               if (ret) {
+                       clk_disable_unprepare(pcie->clk);
+                       return dev_err_probe(&pdev->dev, ret,
+                                            "could not de-assert reset 'swinit'\n");
+               }
+       }
+
        ret = reset_control_reset(pcie->rescal);
        if (ret) {
                clk_disable_unprepare(pcie->clk);