]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
PCI: tegra194: Add core monitor clock support
authorVidya Sagar <vidyas@nvidia.com>
Tue, 24 Mar 2026 19:09:58 +0000 (00:39 +0530)
committerBjorn Helgaas <bhelgaas@google.com>
Wed, 8 Apr 2026 22:00:24 +0000 (17:00 -0500)
Add support for Tegra PCIe core clock monitoring. Monitoring tracks rate
changes that may occur due to link speed changes and is useful for
detecting core clock changes not initiated by software. Parse the monitor
clock from device tree and enable it when present.

Signed-off-by: Vidya Sagar <vidyas@nvidia.com>
Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Tested-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
Link: https://patch.msgid.link/20260324191000.1095768-8-mmaddireddy@nvidia.com
drivers/pci/controller/dwc/pcie-tegra194.c

index eeb93cc1200a373dc5964506a1a554504750ca56..b00b58914b228d78fe458b226113f3695d363aa6 100644 (file)
@@ -249,6 +249,7 @@ struct tegra_pcie_dw {
        struct resource *atu_dma_res;
        void __iomem *appl_base;
        struct clk *core_clk;
+       struct clk *core_clk_m;
        struct reset_control *core_apb_rst;
        struct reset_control *core_rst;
        struct dw_pcie pci;
@@ -950,6 +951,8 @@ static int tegra_pcie_dw_host_init(struct dw_pcie_rp *pp)
        }
 
        clk_set_rate(pcie->core_clk, GEN4_CORE_CLK_FREQ);
+       if (clk_prepare_enable(pcie->core_clk_m))
+               dev_err(pci->dev, "Failed to enable core monitor clock\n");
 
        return 0;
 }
@@ -1022,6 +1025,12 @@ retry_link:
                val &= ~PCI_DLF_EXCHANGE_ENABLE;
                dw_pcie_writel_dbi(pci, offset + PCI_DLF_CAP, val);
 
+               /*
+                * core_clk_m is enabled as part of host_init callback in
+                * dw_pcie_host_init(). Disable the clock since below
+                * tegra_pcie_dw_host_init() will enable it again.
+                */
+               clk_disable_unprepare(pcie->core_clk_m);
                tegra_pcie_dw_host_init(pp);
                dw_pcie_setup_rc(pp);
 
@@ -1615,6 +1624,7 @@ static void tegra_pcie_dw_pme_turnoff(struct tegra_pcie_dw *pcie)
 
 static void tegra_pcie_deinit_controller(struct tegra_pcie_dw *pcie)
 {
+       clk_disable_unprepare(pcie->core_clk_m);
        dw_pcie_host_deinit(&pcie->pci.pp);
        tegra_pcie_dw_pme_turnoff(pcie);
        tegra_pcie_unconfig_controller(pcie);
@@ -2166,6 +2176,11 @@ static int tegra_pcie_dw_probe(struct platform_device *pdev)
                return PTR_ERR(pcie->core_clk);
        }
 
+       pcie->core_clk_m = devm_clk_get_optional(dev, "core_m");
+       if (IS_ERR(pcie->core_clk_m))
+               return dev_err_probe(dev, PTR_ERR(pcie->core_clk_m),
+                                    "Failed to get monitor clock\n");
+
        pcie->appl_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
                                                      "appl");
        if (!pcie->appl_res) {
@@ -2362,6 +2377,7 @@ static int tegra_pcie_dw_suspend_noirq(struct device *dev)
        if (!pcie->link_state)
                return 0;
 
+       clk_disable_unprepare(pcie->core_clk_m);
        tegra_pcie_dw_pme_turnoff(pcie);
        tegra_pcie_unconfig_controller(pcie);