clk: tegra: Changes for v6.20-rc1

This series updates the Tegra clock driver to improve hardware support
 and code correctness. Key changes include fixing camera and display
 clock hierarchies for Tegra20/30 (adding CSI pad gates, reparenting
 DSI/CSUS), resolving a memory leak in the Tegra124 EMC driver, and
 optimizing system suspend/resume callbacks to remove redundant runtime
 PM overhead.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEiOrDCAFJzPfAjcif3SOs138+s6EFAmlsj9AACgkQ3SOs138+
 s6EN7w//dYLyM/NEnwmFYs+8TaGJ0VfxTrhs9W3N55E2Q3NPmQ3m4GbBe7IXM2W3
 5LnNPwEdCgqadhUbFSCj+0APchm42xIEJNa96VaPEb91NWVUk73WVN1SWctdwyC5
 DV6e8fhsgOCv0sI5DpkJ8qOBms3vq0LiIVSCXXjFrUiYF95XAGEENKRHHNj3I7tb
 Nh3/DjQ95xohbCJxJ8D1KWkZi81LSET3nLO4GSxBHqg/7Hb3dbnRQYK5nnG2QUnk
 eEbnTr2Nn7MFl04Wp50tor5TTi4levCNfYoU+Gw3KuL+KkmrMgf75mzRDpmD+0h/
 KDYqOILwVZVjJdmz02tvrZ5E//MxkCpgeG42k2Kq7Rk2ECXQu6MF0NfUyu+miVVS
 tjZ+cQJnMRTXpd3dog5vYdcwNSiHitLtVWmPCj8LACFLZQxjfvwYFBiQbeZXdnts
 7WjZ8IcUybRf3KLXwpqZLXfiYjky6GVpo8YRag1IrzsIf6AQLRFfVoOIbw9ToGrY
 SUht6ljmCfoxP0KzcySXxg9gdNWCCnZCfOOss+I7rT4lSGPRwWLxlEaVTFR7fFGm
 Z87hdH7nS9Zzq3/uorXyCCUoQovAuxyb8H+xv3FSnqX2e4reMk66/mASiyAGaltK
 Hs1EKrvhfmxm81q2JAALQbQ8eaaUWa1cK2ad7tGUmX6pDSI7dZg=
 =HyTR
 -----END PGP SIGNATURE-----
gpgsig -----BEGIN PGP SIGNATURE-----
 
 iQJIBAABCAAyFiEE9L57QeeUxqYDyoaDrQKIl8bklSUFAmlxJiAUHHN3Ym95ZEBj
 aHJvbWl1bS5vcmcACgkQrQKIl8bklSWNKRAA1AB4NDDoCvLkB7VKwfY8U/102Plj
 aXkoBPJj0E7zMEBPFmLqbv4K3zh/gdSjBAR55kZYWYRzScUwH4JI/HK/o7OEsa/b
 ndhePL7ehuVIni3Ga9+70Zh940LcRftRCfOYqs87Zxta74wvl5sopdHnooHuZODS
 LMOzylOMDKQvJtsrpvq47cGdU+e0Gsw1h6XCS+T2B3qMhU0LpSRIMtmuwiwoVM5k
 2YBWHb7gP/dXkSd58o3K8KKVPiQn2+7PlTdhoatjO4p7errLA1QZHFzqpJ4WiWnb
 Wpav4z5Uq5vWxlo481hRpkbgvewi3DGnbw0pM2EXLYDn4XKwEbKItGI698OJN3EB
 GMXti5wnx49f4XYSBBSn+UDFlgF9FvyQ7bnuylwCUZxuvjnNZBkil8Ar97lmrGRf
 0owptxV6jNmS/8Sfp/N/hYv+WW2qyleMV9fg+FHa5/x0tzLfxko5hxjaf/tI7b6l
 W6L4cJYJwTHUf2nN+C9/tBVIBlNI6jrJSYtFR0fPGu5BbK179nJY70jQS6A2usEP
 0kwuJl0XwZ4Hh5Pvhb6C8w1M6lnZhlKw7WHycZb1BGJOuVoRr1TuTzJJXz46eKzl
 KpP7GCTNY0v3nlcElI56GctOhoSj/BEdQ8IKtN+AWVJmctLMX6roLoSnwozsMJJu
 EImeu0e9TSqrsGE=
 =Nh6Y
 -----END PGP SIGNATURE-----

Merge tag 'for-6.20-clk' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into clk-tegra

Pull Tegra clk driver updates from Thierry Reding:

This series updates the Tegra clock driver to improve hardware support
and code correctness. Key changes include fixing camera and display
clock hierarchies for Tegra20/30 (adding CSI pad gates, reparenting
DSI/CSUS), resolving a memory leak in the Tegra124 EMC driver, and
optimizing system suspend/resume callbacks to remove redundant runtime
PM overhead.

* tag 'for-6.20-clk' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux:
  clk: tegra30: Add CSI pad clock gates
  clk: tegra: Set CSUS as vi_sensor's gate for Tegra20, Tegra30 and Tegra114
  clk: tegra20: Reparent dsi clock to pll_d_out0
  clk: tegra: tegra124-emc: Simplify with scoped for each OF child loop
  clk: tegra: Adjust callbacks in tegra_clock_pm
  clk: tegra: tegra124-emc: Fix potential memory leak in tegra124_clk_register_emc()
This commit is contained in:
Stephen Boyd 2026-01-21 11:16:11 -08:00
commit 2d4235b189
5 changed files with 56 additions and 18 deletions

View File

@ -174,8 +174,19 @@ static int tegra_clock_probe(struct platform_device *pdev)
* problem. In practice this makes no difference from a power management
* perspective since voltage is kept at a nominal level during suspend anyways.
*/
static inline int tegra_clock_suspend(struct device *dev)
{
int ret;
ret = pm_runtime_resume(dev);
if (ret < 0)
return ret;
return 0;
}
static const struct dev_pm_ops tegra_clock_pm = {
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_resume_and_get, pm_runtime_put)
SET_SYSTEM_SLEEP_PM_OPS(tegra_clock_suspend, NULL)
};
static const struct of_device_id tegra_clock_match[] = {

View File

@ -690,7 +690,6 @@ static struct tegra_clk tegra114_clks[tegra_clk_max] __initdata = {
[tegra_clk_tsec] = { .dt_id = TEGRA114_CLK_TSEC, .present = true },
[tegra_clk_xusb_host] = { .dt_id = TEGRA114_CLK_XUSB_HOST, .present = true },
[tegra_clk_msenc] = { .dt_id = TEGRA114_CLK_MSENC, .present = true },
[tegra_clk_csus] = { .dt_id = TEGRA114_CLK_CSUS, .present = true },
[tegra_clk_mselect] = { .dt_id = TEGRA114_CLK_MSELECT, .present = true },
[tegra_clk_tsensor] = { .dt_id = TEGRA114_CLK_TSENSOR, .present = true },
[tegra_clk_i2s3] = { .dt_id = TEGRA114_CLK_I2S3, .present = true },
@ -1046,6 +1045,12 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base,
0, 82, periph_clk_enb_refcnt);
clks[TEGRA114_CLK_DSIB] = clk;
/* csus */
clk = tegra_clk_register_periph_gate("csus", "vi_sensor", 0,
clk_base, 0, TEGRA114_CLK_CSUS,
periph_clk_enb_refcnt);
clks[TEGRA114_CLK_CSUS] = clk;
/* emc mux */
clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
ARRAY_SIZE(mux_pllmcp_clkm),

View File

@ -444,7 +444,6 @@ static int load_timings_from_dt(struct tegra_clk_emc *tegra,
u32 ram_code)
{
struct emc_timing *timings_ptr;
struct device_node *child;
int child_count = of_get_child_count(node);
int i = 0, err;
size_t size;
@ -458,12 +457,11 @@ static int load_timings_from_dt(struct tegra_clk_emc *tegra,
timings_ptr = tegra->timings + tegra->num_timings;
tegra->num_timings += child_count;
for_each_child_of_node(node, child) {
for_each_child_of_node_scoped(node, child) {
struct emc_timing *timing = timings_ptr + (i++);
err = load_one_timing_from_dt(tegra, timing, child);
if (err) {
of_node_put(child);
kfree(tegra->timings);
return err;
}
@ -538,8 +536,10 @@ struct clk *tegra124_clk_register_emc(void __iomem *base, struct device_node *np
tegra->hw.init = &init;
clk = clk_register(NULL, &tegra->hw);
if (IS_ERR(clk))
if (IS_ERR(clk)) {
kfree(tegra);
return clk;
}
tegra->prev_parent = clk_hw_get_parent_by_index(
&tegra->hw, emc_get_parent(&tegra->hw))->clk;

View File

@ -530,7 +530,6 @@ static struct tegra_clk tegra20_clks[tegra_clk_max] __initdata = {
[tegra_clk_rtc] = { .dt_id = TEGRA20_CLK_RTC, .present = true },
[tegra_clk_timer] = { .dt_id = TEGRA20_CLK_TIMER, .present = true },
[tegra_clk_kbc] = { .dt_id = TEGRA20_CLK_KBC, .present = true },
[tegra_clk_csus] = { .dt_id = TEGRA20_CLK_CSUS, .present = true },
[tegra_clk_vcp] = { .dt_id = TEGRA20_CLK_VCP, .present = true },
[tegra_clk_bsea] = { .dt_id = TEGRA20_CLK_BSEA, .present = true },
[tegra_clk_bsev] = { .dt_id = TEGRA20_CLK_BSEV, .present = true },
@ -802,9 +801,9 @@ static void __init tegra20_periph_clk_init(void)
clks[TEGRA20_CLK_MC] = clk;
/* dsi */
clk = tegra_clk_register_periph_gate("dsi", "pll_d", 0, clk_base, 0,
48, periph_clk_enb_refcnt);
clk_register_clkdev(clk, NULL, "dsi");
clk = tegra_clk_register_periph_gate("dsi", "pll_d_out0", 0,
clk_base, 0, TEGRA20_CLK_DSI,
periph_clk_enb_refcnt);
clks[TEGRA20_CLK_DSI] = clk;
/* pex */
@ -834,6 +833,12 @@ static void __init tegra20_periph_clk_init(void)
clk_base, 0, 93, periph_clk_enb_refcnt);
clks[TEGRA20_CLK_CDEV2] = clk;
/* csus */
clk = tegra_clk_register_periph_gate("csus", "csus_mux", 0,
clk_base, 0, TEGRA20_CLK_CSUS,
periph_clk_enb_refcnt);
clks[TEGRA20_CLK_CSUS] = clk;
for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) {
data = &tegra_periph_clk_list[i];
clk = tegra_clk_register_periph_data(clk_base, data);
@ -1093,14 +1098,15 @@ static struct clk *tegra20_clk_src_onecell_get(struct of_phandle_args *clkspec,
hw = __clk_get_hw(clk);
/*
* Tegra20 CDEV1 and CDEV2 clocks are a bit special case, their parent
* clock is created by the pinctrl driver. It is possible for clk user
* to request these clocks before pinctrl driver got probed and hence
* user will get an orphaned clock. That might be undesirable because
* user may expect parent clock to be enabled by the child.
* Tegra20 CDEV1, CDEV2 and CSUS clocks are a bit special case, their
* parent clock is created by the pinctrl driver. It is possible for
* clk user to request these clocks before pinctrl driver got probed
* and hence user will get an orphaned clock. That might be undesirable
* because user may expect parent clock to be enabled by the child.
*/
if (clkspec->args[0] == TEGRA20_CLK_CDEV1 ||
clkspec->args[0] == TEGRA20_CLK_CDEV2) {
clkspec->args[0] == TEGRA20_CLK_CDEV2 ||
clkspec->args[0] == TEGRA20_CLK_CSUS) {
parent_hw = clk_hw_get_parent(hw);
if (!parent_hw)
return ERR_PTR(-EPROBE_DEFER);

View File

@ -154,6 +154,7 @@ static unsigned long input_freq;
static DEFINE_SPINLOCK(cml_lock);
static DEFINE_SPINLOCK(pll_d_lock);
static DEFINE_SPINLOCK(pll_d2_lock);
#define TEGRA_INIT_DATA_MUX(_name, _parents, _offset, \
_clk_num, _gate_flags, _clk_id) \
@ -780,7 +781,6 @@ static struct tegra_clk tegra30_clks[tegra_clk_max] __initdata = {
[tegra_clk_rtc] = { .dt_id = TEGRA30_CLK_RTC, .present = true },
[tegra_clk_timer] = { .dt_id = TEGRA30_CLK_TIMER, .present = true },
[tegra_clk_kbc] = { .dt_id = TEGRA30_CLK_KBC, .present = true },
[tegra_clk_csus] = { .dt_id = TEGRA30_CLK_CSUS, .present = true },
[tegra_clk_vcp] = { .dt_id = TEGRA30_CLK_VCP, .present = true },
[tegra_clk_bsea] = { .dt_id = TEGRA30_CLK_BSEA, .present = true },
[tegra_clk_bsev] = { .dt_id = TEGRA30_CLK_BSEV, .present = true },
@ -860,7 +860,7 @@ static void __init tegra30_pll_init(void)
/* PLLD2 */
clk = tegra_clk_register_pll("pll_d2", "pll_ref", clk_base, pmc_base, 0,
&pll_d2_params, NULL);
&pll_d2_params, &pll_d2_lock);
clks[TEGRA30_CLK_PLL_D2] = clk;
/* PLLD2_OUT0 */
@ -1009,6 +1009,22 @@ static void __init tegra30_periph_clk_init(void)
0, 48, periph_clk_enb_refcnt);
clks[TEGRA30_CLK_DSIA] = clk;
/* csia_pad */
clk = clk_register_gate(NULL, "csia_pad", "pll_d", CLK_SET_RATE_PARENT,
clk_base + PLLD_BASE, 26, 0, &pll_d_lock);
clks[TEGRA30_CLK_CSIA_PAD] = clk;
/* csib_pad */
clk = clk_register_gate(NULL, "csib_pad", "pll_d2", CLK_SET_RATE_PARENT,
clk_base + PLLD2_BASE, 26, 0, &pll_d2_lock);
clks[TEGRA30_CLK_CSIB_PAD] = clk;
/* csus */
clk = tegra_clk_register_periph_gate("csus", "vi_sensor", 0,
clk_base, 0, TEGRA30_CLK_CSUS,
periph_clk_enb_refcnt);
clks[TEGRA30_CLK_CSUS] = clk;
/* pcie */
clk = tegra_clk_register_periph_gate("pcie", "clk_m", 0, clk_base, 0,
70, periph_clk_enb_refcnt);