Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: tegra: cclk: Add helpers for handling PLLX rate changes

CCLK should be re-parented away from PLLX if PLLX's rate is changing.
The PLLP parent is a common safe CPU parent for all Tegra SoCs, thus
CCLK will be re-parented to PLLP before PLLX rate-change begins and then
switched back to PLLX after the rate-change completion. This patch adds
helper functions which perform CCLK re-parenting, these helpers will be
utilized by further patches.

Acked-by: Peter De Schrijver <pdeschrijver@nvidia.com>
Tested-by: Peter Geis <pgwipeout@gmail.com>
Tested-by: Marcel Ziswiler <marcel@ziswiler.com>
Tested-by: Jasper Korten <jja2000@gmail.com>
Tested-by: David Heidelberg <david@ixit.cz>
Tested-by: Nicolas Chauvet <kwizart@gmail.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>

authored by

Dmitry Osipenko and committed by
Thierry Reding
dec15c99 9157abe7

+36
+34
drivers/clk/tegra/clk-tegra-super-cclk.c
··· 25 25 26 26 #define SUPER_CDIV_ENB BIT(31) 27 27 28 + static struct tegra_clk_super_mux *cclk_super; 29 + static bool cclk_on_pllx; 30 + 28 31 static u8 cclk_super_get_parent(struct clk_hw *hw) 29 32 { 30 33 return tegra_clk_super_ops.get_parent(hw); ··· 118 115 struct clk_init_data init; 119 116 u32 val; 120 117 118 + if (WARN_ON(cclk_super)) 119 + return ERR_PTR(-EBUSY); 120 + 121 121 super = kzalloc(sizeof(*super), GFP_KERNEL); 122 122 if (!super) 123 123 return ERR_PTR(-ENOMEM); ··· 179 173 clk = clk_register(NULL, &super->hw); 180 174 if (IS_ERR(clk)) 181 175 kfree(super); 176 + else 177 + cclk_super = super; 182 178 183 179 return clk; 180 + } 181 + 182 + int tegra_cclk_pre_pllx_rate_change(void) 183 + { 184 + if (IS_ERR_OR_NULL(cclk_super)) 185 + return -EINVAL; 186 + 187 + if (cclk_super_get_parent(&cclk_super->hw) == PLLX_INDEX) 188 + cclk_on_pllx = true; 189 + else 190 + cclk_on_pllx = false; 191 + 192 + /* 193 + * CPU needs to be temporarily re-parented away from PLLX if PLLX 194 + * changes its rate. PLLP is a safe parent for CPU on all Tegra SoCs. 195 + */ 196 + if (cclk_on_pllx) 197 + cclk_super_set_parent(&cclk_super->hw, PLLP_INDEX); 198 + 199 + return 0; 200 + } 201 + 202 + void tegra_cclk_post_pllx_rate_change(void) 203 + { 204 + if (cclk_on_pllx) 205 + cclk_super_set_parent(&cclk_super->hw, PLLX_INDEX); 184 206 }
+2
drivers/clk/tegra/clk.h
··· 771 771 const char * const *parent_names, u8 num_parents, 772 772 unsigned long flags, void __iomem *reg, u8 clk_super_flags, 773 773 spinlock_t *lock); 774 + int tegra_cclk_pre_pllx_rate_change(void); 775 + void tegra_cclk_post_pllx_rate_change(void); 774 776 775 777 /** 776 778 * struct tegra_sdmmc_mux - switch divider with Low Jitter inputs for SDMMC