mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Manikanta Maddireddy <mmaddireddy@nvidia.com>
To: <lpieralisi@kernel.org>, <kwilczynski@kernel.org>,
	<mani@kernel.org>, <bhelgaas@google.com>,
	<linux-pci@vger.kernel.org>
Cc: <robh@kernel.org>, <thierry.reding@kernel.org>,
	<jonathanh@nvidia.com>, <kishon@kernel.org>,
	<Frank.Li@kernel.org>, <vidyas@nvidia.com>, <cassel@kernel.org>,
	<den@valinux.co.jp>, <marco.crivellari@suse.com>,
	<andriy.shevchenko@linux.intel.com>,
	<linux-tegra@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
	<mmaddireddy@nvidia.com>
Subject: [PATCH v3 09/10] PCI: tegra194: Enable core monitor clock after link setup
Date: Mon, 2 Nov 2026 16:57:18 +0530	[thread overview]
Message-ID: <20261102112719.4022633-10-mmaddireddy@nvidia.com> (raw)
In-Reply-To: <20261102112719.4022633-1-mmaddireddy@nvidia.com>

Commit a86ca8698c88 ("PCI: tegra194: Add core monitor clock support")
enables the monitor clock in tegra_pcie_dw_host_init(), before link
training completes and the core clock rate is adjusted for the negotiated
speed. Monitoring during these transitions can cause false frequency
monitor faults.

The existing initialization also enables the core clock before requesting
its initial rate. Boot and Power Management Processor (BPMP) firmware uses
the requested rate to determine the voltage requirement, so enabling the
clock first can leave a window where the voltage requirement does not
cover the rate needed during link training.

Monitor clock ownership is also spread across the host initialization
callback, DLF retry and teardown paths. Monitor enable failures are only
logged, while some later initialization failures can unconfigure the
controller without releasing the acquired monitor clock reference.

Use the following sequence:

  1. Set the core clock rate to 500 MHz, the highest supported rate.
  2. Enable the core clock only.
  3. Program the PCIe registers.
  4. Train the PCIe link to the target speed.
  5. Set the core clock rate for the negotiated link speed.
  6. Enable the monitor clock.

Requesting 500 MHz before enabling core establishes the voltage requirement
for the highest possible training speed. Once training completes, reduce
the requested rate as appropriate for the negotiated speed.

The monitor clock is a virtual clock controlling the PCIe frequency
monitor. Its rate must not be programmed separately. Enable it only after
the final core rate has been selected, avoiding monitoring faults during
configuration and training.

Move the initial core rate request into controller configuration and
propagate rate-setting errors. Enable the monitor clock after successful
Root Port initialization and at the end of resume, propagating enable
failures. Keep monitor clock operations out of the host initialization
callback and DLF retry path.

Release the monitor clock during remove, suspend and shutdown. Failures
before monitor enable unwind the controller without disabling an
unacquired monitor clock reference.

Fixes: a86ca8698c88 ("PCI: tegra194: Add core monitor clock support")
Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
---
Changes V2 -> V3:
- Rename the patch to "Enable core monitor clock after link setup".
- Request the 500 MHz core rate before enabling core so BPMP firmware
  establishes the voltage requirement before link training.
- Keep the monitor disabled through register setup, link training and
  negotiated core rate selection; enable it after Root Port initialization
  and at the end of resume.
- Return core rate-setting errors and monitor enable failures.
- Remove the reference-state flag and common monitor-disable helper;
  balance monitor operations in remove, suspend and shutdown, keeping
  host initialization and DLF retry free of monitor-clock operations.
- Explain the required sequencing and the risk of false frequency-monitor
  faults during clock-rate transitions.

Changes V1 -> V2: None

 drivers/pci/controller/dwc/pcie-tegra194.c | 51 +++++++++++++++-------
 1 file changed, 36 insertions(+), 15 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
index e08d99efd616..981cff740cd2 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -305,10 +305,11 @@ static inline u32 appl_readl(struct tegra_pcie_dw *pcie, const u32 reg)
 	return readl_relaxed(pcie->appl_base + reg);
 }
 
-static void tegra_pcie_icc_set(struct tegra_pcie_dw *pcie)
+static int tegra_pcie_icc_set(struct tegra_pcie_dw *pcie)
 {
 	struct dw_pcie *pci = &pcie->pci;
 	u32 val, speed, width;
+	int ret;
 
 	val = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKSTA);
 
@@ -323,7 +324,13 @@ static void tegra_pcie_icc_set(struct tegra_pcie_dw *pcie)
 	if (speed >= ARRAY_SIZE(pcie_gen_freq))
 		speed = 0;
 
-	clk_set_rate(pcie->core_clk, pcie_gen_freq[speed]);
+	ret = clk_set_rate(pcie->core_clk, pcie_gen_freq[speed]);
+	if (ret) {
+		dev_err(pcie->dev, "Failed to set core clock rate: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
 }
 
 static void apply_bad_link_workaround(struct dw_pcie_rp *pp)
@@ -965,10 +972,6 @@ static int tegra_pcie_dw_host_init(struct dw_pcie_rp *pp)
 		dw_pcie_writel_dbi(pci, CFG_TIMER_CTRL_MAX_FUNC_NUM_OFF, val);
 	}
 
-	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;
 }
 
@@ -1045,20 +1048,19 @@ static int tegra_pcie_dw_start_link(struct dw_pcie *pci)
 		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);
+		ret = tegra_pcie_dw_host_init(pp);
+		if (ret)
+			return ret;
+
 		dw_pcie_setup_rc(pp);
 
 		retry = false;
 		goto retry_link;
 	}
 
-	tegra_pcie_icc_set(pcie);
+	ret = tegra_pcie_icc_set(pcie);
+	if (ret)
+		return ret;
 
 	tegra_pcie_enable_interrupts(pp);
 
@@ -1413,6 +1415,12 @@ static int tegra_pcie_config_controller(struct tegra_pcie_dw *pcie,
 		goto fail_reg_en;
 	}
 
+	ret = clk_set_rate(pcie->core_clk, GEN4_CORE_CLK_FREQ);
+	if (ret) {
+		dev_err(pcie->dev, "Failed to set initial core clock rate: %d\n", ret);
+		goto fail_core_clk;
+	}
+
 	ret = clk_prepare_enable(pcie->core_clk);
 	if (ret) {
 		dev_err(pcie->dev, "Failed to enable core clock: %d\n", ret);
@@ -1654,7 +1662,6 @@ 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);
@@ -1692,6 +1699,12 @@ static int tegra_pcie_config_rp(struct tegra_pcie_dw *pcie)
 		goto fail_host_init;
 	}
 
+	ret = clk_prepare_enable(pcie->core_clk_m);
+	if (ret) {
+		dev_err(dev, "Failed to enable core monitor clock: %d\n", ret);
+		goto fail_host_init;
+	}
+
 	init_debugfs(pcie);
 
 	return ret;
@@ -2379,6 +2392,7 @@ static void tegra_pcie_dw_remove(struct platform_device *pdev)
 	if (pcie->of_data->mode == DW_PCIE_RC_TYPE) {
 		if (pcie->link_state) {
 			debugfs_remove_recursive(pcie->debugfs);
+			clk_disable_unprepare(pcie->core_clk_m);
 			tegra_pcie_deinit_controller(pcie);
 			pm_runtime_put_sync(pcie->dev);
 			pm_runtime_disable(pcie->dev);
@@ -2486,6 +2500,12 @@ static int tegra_pcie_dw_resume_noirq(struct device *dev)
 	if (ret < 0)
 		goto fail_host_init;
 
+	ret = clk_prepare_enable(pcie->core_clk_m);
+	if (ret) {
+		dev_err(dev, "Failed to enable core monitor clock: %d\n", ret);
+		goto fail_host_init;
+	}
+
 	return 0;
 
 fail_host_init:
@@ -2530,6 +2550,7 @@ static void tegra_pcie_dw_shutdown(struct platform_device *pdev)
 		if (IS_ENABLED(CONFIG_PCI_MSI))
 			disable_irq(pcie->pci.pp.msi_irq[0]);
 
+		clk_disable_unprepare(pcie->core_clk_m);
 		tegra_pcie_dw_pme_turnoff(pcie);
 		tegra_pcie_unconfig_controller(pcie);
 		pm_runtime_put_sync(pcie->dev);
-- 
2.34.1


  parent reply	other threads:[~2026-11-02 11:28 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-02 11:27 [PATCH v3 00/10] PCI: tegra194: Fix EP and Root Port corner cases Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 01/10] PCI: tegra194: Propagate REFCLK select GPIO errors Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 02/10] PCI: tegra194: Check core reset deassertion Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 03/10] PCI: tegra194: Fix Endpoint PERST# IRQ suspend race Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 04/10] PCI: tegra194: Do not skip no-link Root Port remove cleanup Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 05/10] PCI: tegra194: Check for 16 GT/s capability before programming Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 06/10] PCI: tegra194: Check for L1SS " Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 07/10] PCI: tegra194: Always disable Tegra234 Endpoint L1.2 Manikanta Maddireddy
2026-11-02 11:27 ` [PATCH v3 08/10] PCI: tegra194: Guard Endpoint PLL-off error path Manikanta Maddireddy
2026-11-02 11:27 ` Manikanta Maddireddy [this message]
2026-11-02 11:27 ` [PATCH v3 10/10] PCI: tegra194: Reject zero MSI interrupt number Manikanta Maddireddy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261102112719.4022633-10-mmaddireddy@nvidia.com \
    --to=mmaddireddy@nvidia.com \
    --cc=Frank.Li@kernel.org \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=bhelgaas@google.com \
    --cc=cassel@kernel.org \
    --cc=den@valinux.co.jp \
    --cc=jonathanh@nvidia.com \
    --cc=kishon@kernel.org \
    --cc=kwilczynski@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=linux-tegra@vger.kernel.org \
    --cc=lpieralisi@kernel.org \
    --cc=mani@kernel.org \
    --cc=marco.crivellari@suse.com \
    --cc=robh@kernel.org \
    --cc=thierry.reding@kernel.org \
    --cc=vidyas@nvidia.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®