From: Anand Moon <linux.amoon@gmail.com>
To: "Bjorn Helgaas" <bhelgaas@google.com>,
"Lorenzo Pieralisi" <lpieralisi@kernel.org>,
"Krzysztof Wilczyński" <kwilczynski@kernel.org>,
"Manivannan Sadhasivam" <mani@kernel.org>,
"Rob Herring" <robh@kernel.org>,
"Krzysztof Kozlowski" <krzk+dt@kernel.org>,
"Conor Dooley" <conor+dt@kernel.org>,
"Thierry Reding" <thierry.reding@gmail.com>,
"Jonathan Hunter" <jonathanh@nvidia.com>,
linux-pci@vger.kernel.org (open list:PCI SUBSYSTEM),
devicetree@vger.kernel.org (open list:OPEN FIRMWARE AND
FLATTENED DEVICE TREE BINDINGS),
linux-tegra@vger.kernel.org (open list:TEGRA ARCHITECTURE
SUPPORT), linux-kernel@vger.kernel.org (open list)
Cc: Anand Moon <linux.amoon@gmail.com>
Subject: [PATCH v1 2/5] PCI: tegra: Simplify clock handling by using clk_bulk*() functions
Date: Fri, 26 Sep 2025 12:57:43 +0530 [thread overview]
Message-ID: <20250926072905.126737-3-linux.amoon@gmail.com> (raw)
In-Reply-To: <20250926072905.126737-1-linux.amoon@gmail.com>
Currently, the driver acquires clocks and prepare/enable/disable/unprepare
the clocks individually thereby making the driver complex to read.
The driver can be simplified by using the clk_bulk*() APIs.
Use:
- devm_clk_bulk_get() API to acquire all the clocks
- clk_bulk_prepare_enable() to prepare/enable clocks
- clk_bulk_disable_unprepare() APIs to disable/unprepare them in bulk
Following change also removes the legacy has_cml_clk flag and its associated
conditional logic. Instead, the driver now relies on the clock definitions from
the device tree to determine the correct clock sequencing.
This reduces hardcoded dependencies and improves the driver's maintainability.
Cc: Thierry Reding <thierry.reding@gmail.com>
Cc: Jon Hunter <jonathanh@nvidia.com>
Signed-off-by: Anand Moon <linux.amoon@gmail.com>
---
v1: Switch from devm_clk_bulk_get_all() -> devm_clk_bulk_get() with
fix clks array.
nvidia,tegra20-pcie and nvidia,tegra186-pcie uses three clocks
pex, afi, pll_e
where as nvidia,tegra30-pcie, nvidia,tegra124-pcie, nvidia,tegra210-pcie
uses four clks
pex, afi, pll_e, cml
---
---
drivers/pci/controller/pci-tegra.c | 100 +++++++++++++----------------
1 file changed, 45 insertions(+), 55 deletions(-)
diff --git a/drivers/pci/controller/pci-tegra.c b/drivers/pci/controller/pci-tegra.c
index 467ddc701adc..07a61d902eae 100644
--- a/drivers/pci/controller/pci-tegra.c
+++ b/drivers/pci/controller/pci-tegra.c
@@ -287,6 +287,8 @@ struct tegra_pcie_port_soc {
struct tegra_pcie_soc {
unsigned int num_ports;
const struct tegra_pcie_port_soc *ports;
+ const char * const *clk_names;
+ unsigned int num_clks;
unsigned int msi_base_shift;
unsigned long afi_pex2_ctrl;
u32 pads_pll_ctl;
@@ -297,7 +299,6 @@ struct tegra_pcie_soc {
bool has_pex_clkreq_en;
bool has_pex_bias_ctrl;
bool has_intr_prsnt_sense;
- bool has_cml_clk;
bool has_gen2;
bool force_pca_enable;
bool program_uphy;
@@ -330,10 +331,7 @@ struct tegra_pcie {
struct resource cs;
- struct clk *pex_clk;
- struct clk *afi_clk;
- struct clk *pll_e;
- struct clk *cml_clk;
+ struct clk_bulk_data *clks;
struct reset_control *pex_rst;
struct reset_control *afi_rst;
@@ -1158,10 +1156,7 @@ static void tegra_pcie_power_off(struct tegra_pcie *pcie)
reset_control_assert(pcie->afi_rst);
- clk_disable_unprepare(pcie->pll_e);
- if (soc->has_cml_clk)
- clk_disable_unprepare(pcie->cml_clk);
- clk_disable_unprepare(pcie->afi_clk);
+ clk_bulk_disable_unprepare(soc->num_clks, pcie->clks);
if (!dev->pm_domain)
tegra_powergate_power_off(TEGRA_POWERGATE_PCIE);
@@ -1202,35 +1197,16 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie)
}
}
- err = clk_prepare_enable(pcie->afi_clk);
+ err = clk_bulk_prepare_enable(soc->num_clks, pcie->clks);
if (err < 0) {
- dev_err(dev, "failed to enable AFI clock: %d\n", err);
+ dev_err(dev, "filed to enable clocks: %d\n", err);
goto powergate;
}
- if (soc->has_cml_clk) {
- err = clk_prepare_enable(pcie->cml_clk);
- if (err < 0) {
- dev_err(dev, "failed to enable CML clock: %d\n", err);
- goto disable_afi_clk;
- }
- }
-
- err = clk_prepare_enable(pcie->pll_e);
- if (err < 0) {
- dev_err(dev, "failed to enable PLLE clock: %d\n", err);
- goto disable_cml_clk;
- }
-
reset_control_deassert(pcie->afi_rst);
return 0;
-disable_cml_clk:
- if (soc->has_cml_clk)
- clk_disable_unprepare(pcie->cml_clk);
-disable_afi_clk:
- clk_disable_unprepare(pcie->afi_clk);
powergate:
if (!dev->pm_domain)
tegra_powergate_power_off(TEGRA_POWERGATE_PCIE);
@@ -1255,26 +1231,21 @@ static int tegra_pcie_clocks_get(struct tegra_pcie *pcie)
{
struct device *dev = pcie->dev;
const struct tegra_pcie_soc *soc = pcie->soc;
+ int ret, i;
- pcie->pex_clk = devm_clk_get(dev, "pex");
- if (IS_ERR(pcie->pex_clk))
- return PTR_ERR(pcie->pex_clk);
-
- pcie->afi_clk = devm_clk_get(dev, "afi");
- if (IS_ERR(pcie->afi_clk))
- return PTR_ERR(pcie->afi_clk);
+ pcie->clks = devm_kcalloc(dev, soc->num_clks, sizeof(*pcie->clks),
+ GFP_KERNEL);
+ if (!pcie->clks)
+ return -ENOMEM;
- pcie->pll_e = devm_clk_get(dev, "pll_e");
- if (IS_ERR(pcie->pll_e))
- return PTR_ERR(pcie->pll_e);
+ for (i = 0; i < soc->num_clks; i++)
+ pcie->clks[i].id = soc->clk_names[i];
- if (soc->has_cml_clk) {
- pcie->cml_clk = devm_clk_get(dev, "cml");
- if (IS_ERR(pcie->cml_clk))
- return PTR_ERR(pcie->cml_clk);
- }
+ ret = devm_clk_bulk_get(dev, soc->num_clks, pcie->clks);
+ if (ret)
+ dev_err(dev, "failed to get PCIe clocks: %d\n", ret);
- return 0;
+ return ret;
}
static int tegra_pcie_resets_get(struct tegra_pcie *pcie)
@@ -2335,9 +2306,17 @@ static const struct tegra_pcie_port_soc tegra20_pcie_ports[] = {
{ .pme.turnoff_bit = 8, .pme.ack_bit = 10 },
};
+static const char * const tegra20_pcie_clks[] = {
+ "pex",
+ "afi",
+ "pll_e",
+};
+
static const struct tegra_pcie_soc tegra20_pcie = {
.num_ports = 2,
.ports = tegra20_pcie_ports,
+ .clk_names = tegra20_pcie_clks,
+ .num_clks = ARRAY_SIZE(tegra20_pcie_clks),
.msi_base_shift = 0,
.pads_pll_ctl = PADS_PLL_CTL_TEGRA20,
.tx_ref_sel = PADS_PLL_CTL_TXCLKREF_DIV10,
@@ -2345,7 +2324,6 @@ static const struct tegra_pcie_soc tegra20_pcie = {
.has_pex_clkreq_en = false,
.has_pex_bias_ctrl = false,
.has_intr_prsnt_sense = false,
- .has_cml_clk = false,
.has_gen2 = false,
.force_pca_enable = false,
.program_uphy = true,
@@ -2356,6 +2334,13 @@ static const struct tegra_pcie_soc tegra20_pcie = {
.ectl.enable = false,
};
+static const char * const tegra30_pcie_clks[] = {
+ "pex",
+ "afi",
+ "pll_e",
+ "cml",
+};
+
static const struct tegra_pcie_port_soc tegra30_pcie_ports[] = {
{ .pme.turnoff_bit = 0, .pme.ack_bit = 5 },
{ .pme.turnoff_bit = 8, .pme.ack_bit = 10 },
@@ -2365,6 +2350,8 @@ static const struct tegra_pcie_port_soc tegra30_pcie_ports[] = {
static const struct tegra_pcie_soc tegra30_pcie = {
.num_ports = 3,
.ports = tegra30_pcie_ports,
+ .clk_names = tegra30_pcie_clks,
+ .num_clks = ARRAY_SIZE(tegra30_pcie_clks),
.msi_base_shift = 8,
.afi_pex2_ctrl = 0x128,
.pads_pll_ctl = PADS_PLL_CTL_TEGRA30,
@@ -2374,7 +2361,6 @@ static const struct tegra_pcie_soc tegra30_pcie = {
.has_pex_clkreq_en = true,
.has_pex_bias_ctrl = true,
.has_intr_prsnt_sense = true,
- .has_cml_clk = true,
.has_gen2 = false,
.force_pca_enable = false,
.program_uphy = true,
@@ -2388,6 +2374,8 @@ static const struct tegra_pcie_soc tegra30_pcie = {
static const struct tegra_pcie_soc tegra124_pcie = {
.num_ports = 2,
.ports = tegra20_pcie_ports,
+ .clk_names = tegra30_pcie_clks,
+ .num_clks = ARRAY_SIZE(tegra30_pcie_clks),
.msi_base_shift = 8,
.pads_pll_ctl = PADS_PLL_CTL_TEGRA30,
.tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN,
@@ -2395,7 +2383,6 @@ static const struct tegra_pcie_soc tegra124_pcie = {
.has_pex_clkreq_en = true,
.has_pex_bias_ctrl = true,
.has_intr_prsnt_sense = true,
- .has_cml_clk = true,
.has_gen2 = true,
.force_pca_enable = false,
.program_uphy = true,
@@ -2409,6 +2396,8 @@ static const struct tegra_pcie_soc tegra124_pcie = {
static const struct tegra_pcie_soc tegra210_pcie = {
.num_ports = 2,
.ports = tegra20_pcie_ports,
+ .clk_names = tegra30_pcie_clks,
+ .num_clks = ARRAY_SIZE(tegra30_pcie_clks),
.msi_base_shift = 8,
.pads_pll_ctl = PADS_PLL_CTL_TEGRA30,
.tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN,
@@ -2418,7 +2407,6 @@ static const struct tegra_pcie_soc tegra210_pcie = {
.has_pex_clkreq_en = true,
.has_pex_bias_ctrl = true,
.has_intr_prsnt_sense = true,
- .has_cml_clk = true,
.has_gen2 = true,
.force_pca_enable = true,
.program_uphy = true,
@@ -2450,6 +2438,8 @@ static const struct tegra_pcie_port_soc tegra186_pcie_ports[] = {
static const struct tegra_pcie_soc tegra186_pcie = {
.num_ports = 3,
.ports = tegra186_pcie_ports,
+ .clk_names = tegra20_pcie_clks,
+ .num_clks = ARRAY_SIZE(tegra20_pcie_clks),
.msi_base_shift = 8,
.afi_pex2_ctrl = 0x19c,
.pads_pll_ctl = PADS_PLL_CTL_TEGRA30,
@@ -2459,7 +2449,6 @@ static const struct tegra_pcie_soc tegra186_pcie = {
.has_pex_clkreq_en = true,
.has_pex_bias_ctrl = true,
.has_intr_prsnt_sense = true,
- .has_cml_clk = false,
.has_gen2 = true,
.force_pca_enable = false,
.program_uphy = false,
@@ -2651,6 +2640,7 @@ static void tegra_pcie_remove(struct platform_device *pdev)
static int tegra_pcie_pm_suspend(struct device *dev)
{
struct tegra_pcie *pcie = dev_get_drvdata(dev);
+ const struct tegra_pcie_soc *soc = pcie->soc;
struct tegra_pcie_port *port;
int err;
@@ -2672,7 +2662,7 @@ static int tegra_pcie_pm_suspend(struct device *dev)
}
reset_control_assert(pcie->pex_rst);
- clk_disable_unprepare(pcie->pex_clk);
+ clk_bulk_disable_unprepare(soc->num_clks, pcie->clks);
if (IS_ENABLED(CONFIG_PCI_MSI))
tegra_pcie_disable_msi(pcie);
@@ -2686,6 +2676,7 @@ static int tegra_pcie_pm_suspend(struct device *dev)
static int tegra_pcie_pm_resume(struct device *dev)
{
struct tegra_pcie *pcie = dev_get_drvdata(dev);
+ const struct tegra_pcie_soc *soc = pcie->soc;
int err;
err = tegra_pcie_power_on(pcie);
@@ -2706,9 +2697,9 @@ static int tegra_pcie_pm_resume(struct device *dev)
if (IS_ENABLED(CONFIG_PCI_MSI))
tegra_pcie_enable_msi(pcie);
- err = clk_prepare_enable(pcie->pex_clk);
+ err = clk_bulk_prepare_enable(soc->num_clks, pcie->clks);
if (err) {
- dev_err(dev, "failed to enable PEX clock: %d\n", err);
+ dev_err(dev, "failed to enable clock: %d\n", err);
goto pex_dpd_enable;
}
@@ -2729,7 +2720,6 @@ static int tegra_pcie_pm_resume(struct device *dev)
disable_pex_clk:
reset_control_assert(pcie->pex_rst);
- clk_disable_unprepare(pcie->pex_clk);
pex_dpd_enable:
pinctrl_pm_select_idle_state(dev);
poweroff:
--
2.50.1
next prev parent reply other threads:[~2025-09-26 7:29 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-26 7:27 [PATCH v1 0/5] PCI: tegra: A couple of cleanups Anand Moon
2025-09-26 7:27 ` [PATCH v1 1/5] dt-bindings: PCI: Convert the existing nvidia,tegra-pcie.txt bindings documentation into a YAML schema Anand Moon
2025-09-26 13:56 ` Rob Herring
2025-09-29 7:39 ` Anand Moon
2025-09-29 13:48 ` Rob Herring
2025-09-29 15:25 ` Anand Moon
2025-09-30 14:37 ` Rob Herring
2025-09-30 16:32 ` Anand Moon
2025-10-01 15:33 ` Rob Herring
2025-10-01 18:57 ` Anand Moon
2025-09-26 7:27 ` Anand Moon [this message]
2025-09-26 18:12 ` [PATCH v1 2/5] PCI: tegra: Simplify clock handling by using clk_bulk*() functions Frank Li
2025-09-27 5:50 ` Anand Moon
2025-09-29 14:01 ` Manivannan Sadhasivam
2025-09-29 16:12 ` Anand Moon
2025-09-26 7:27 ` [PATCH v1 3/5] PCI: tegra: Use readl_poll_timeout() for link status polling Anand Moon
2025-10-19 7:50 ` Manivannan Sadhasivam
2025-10-20 12:17 ` Anand Moon
2025-10-21 1:43 ` Manivannan Sadhasivam
2025-10-24 6:17 ` Anand Moon
2025-09-26 7:27 ` [PATCH v1 4/5] PCI: tegra: Use BIT() and GENMASK() macros for register definitions Anand Moon
2025-09-26 7:27 ` [PATCH v1 5/5] PCI: tegra: Document map_lock and mask_lock usage Anand Moon
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=20250926072905.126737-3-linux.amoon@gmail.com \
--to=linux.amoon@gmail.com \
--cc=bhelgaas@google.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=jonathanh@nvidia.com \
--cc=krzk+dt@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=robh@kernel.org \
--cc=thierry.reding@gmail.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;
as well as URLs for NNTP newsgroup(s).