1178172Simp// SPDX-License-Identifier: GPL-2.0 2178172Simp/* 3178172Simp * Copyright (c) 2015-2020, NVIDIA CORPORATION. All rights reserved. 4178172Simp */ 5178172Simp 6178172Simp#include <linux/bitfield.h> 7178172Simp#include <linux/clk.h> 8178172Simp#include <linux/clk-provider.h> 9178172Simp#include <linux/clk/tegra.h> 10178172Simp#include <linux/device.h> 11178172Simp#include <linux/module.h> 12178172Simp#include <linux/io.h> 13178172Simp#include <linux/slab.h> 14178172Simp 15178172Simp#include "clk.h" 16178172Simp 17178172Simp#define CLK_SOURCE_EMC 0x19c 18178172Simp#define CLK_SOURCE_EMC_2X_CLK_SRC GENMASK(31, 29) 19178172Simp#define CLK_SOURCE_EMC_MC_EMC_SAME_FREQ BIT(16) 20178172Simp#define CLK_SOURCE_EMC_2X_CLK_DIVISOR GENMASK(7, 0) 21178172Simp 22178172Simp#define CLK_SRC_PLLM 0 23178172Simp#define CLK_SRC_PLLC 1 24178172Simp#define CLK_SRC_PLLP 2 25178172Simp#define CLK_SRC_CLK_M 3 26178172Simp#define CLK_SRC_PLLM_UD 4 27178172Simp#define CLK_SRC_PLLMB_UD 5 28178172Simp#define CLK_SRC_PLLMB 6 29178172Simp#define CLK_SRC_PLLP_UD 7 30178172Simp 31178172Simpstruct tegra210_clk_emc { 32178172Simp struct clk_hw hw; 33178172Simp void __iomem *regs; 34178172Simp 35178172Simp struct tegra210_clk_emc_provider *provider; 36178172Simp 37178172Simp struct clk *parents[8]; 38178172Simp}; 39178172Simp 40178172Simpstatic inline struct tegra210_clk_emc * 41178172Simpto_tegra210_clk_emc(struct clk_hw *hw) 42202046Simp{ 43178172Simp return container_of(hw, struct tegra210_clk_emc, hw); 44178172Simp} 45178172Simp 46178172Simpstatic const char *tegra210_clk_emc_parents[] = { 47178172Simp "pll_m", "pll_c", "pll_p", "clk_m", "pll_m_ud", "pll_mb_ud", 48178172Simp "pll_mb", "pll_p_ud", 49178172Simp}; 50178172Simp 51178172Simpstatic u8 tegra210_clk_emc_get_parent(struct clk_hw *hw) 52178172Simp{ 53209613Sjhb struct tegra210_clk_emc *emc = to_tegra210_clk_emc(hw); 54178172Simp u32 value; 55178172Simp u8 src; 56178172Simp 57178172Simp value = readl_relaxed(emc->regs + CLK_SOURCE_EMC); 58178172Simp src = FIELD_GET(CLK_SOURCE_EMC_2X_CLK_SRC, value); 59178172Simp 60178172Simp return src; 61178172Simp} 62178172Simp 63178172Simpstatic unsigned long tegra210_clk_emc_recalc_rate(struct clk_hw *hw, 64178172Simp unsigned long parent_rate) 65178172Simp{ 66178172Simp struct tegra210_clk_emc *emc = to_tegra210_clk_emc(hw); 67178172Simp u32 value, div; 68178172Simp 69178172Simp /* 70178172Simp * CCF assumes that neither the parent nor its rate will change during 71178172Simp * ->set_rate(), so the parent rate passed in here was cached from the 72178172Simp * parent before the ->set_rate() call. 73178172Simp * 74178172Simp * This can lead to wrong results being reported for the EMC clock if 75178172Simp * the parent and/or parent rate have changed as part of the EMC rate 76178172Simp * change sequence. Fix this by overriding the parent clock with what 77178172Simp * we know to be the correct value after the rate change. 78178172Simp */ 79178172Simp parent_rate = clk_hw_get_rate(clk_hw_get_parent(hw)); 80178172Simp 81178172Simp value = readl_relaxed(emc->regs + CLK_SOURCE_EMC); 82178172Simp 83178172Simp div = FIELD_GET(CLK_SOURCE_EMC_2X_CLK_DIVISOR, value); 84178172Simp div += 2; 85178172Simp 86178172Simp return DIV_ROUND_UP(parent_rate * 2, div); 87178172Simp} 88178172Simp 89178172Simpstatic long tegra210_clk_emc_round_rate(struct clk_hw *hw, unsigned long rate, 90178172Simp unsigned long *prate) 91178172Simp{ 92178172Simp struct tegra210_clk_emc *emc = to_tegra210_clk_emc(hw); 93178172Simp struct tegra210_clk_emc_provider *provider = emc->provider; 94178172Simp unsigned int i; 95178172Simp 96178172Simp if (!provider || !provider->configs || provider->num_configs == 0) 97178172Simp return clk_hw_get_rate(hw); 98178172Simp 99178172Simp for (i = 0; i < provider->num_configs; i++) { 100178172Simp if (provider->configs[i].rate >= rate) 101178172Simp return provider->configs[i].rate; 102178172Simp } 103178172Simp 104178172Simp return provider->configs[i - 1].rate; 105178172Simp} 106178172Simp 107178172Simpstatic struct clk *tegra210_clk_emc_find_parent(struct tegra210_clk_emc *emc, 108178172Simp u8 index) 109178172Simp{ 110178172Simp struct clk_hw *parent = clk_hw_get_parent_by_index(&emc->hw, index); 111178172Simp const char *name = clk_hw_get_name(parent); 112232585Sjmallett 113178172Simp /* XXX implement cache? */ 114178172Simp 115178172Simp return __clk_lookup(name); 116178172Simp} 117178172Simp 118178172Simpstatic int tegra210_clk_emc_set_rate(struct clk_hw *hw, unsigned long rate, 119178172Simp unsigned long parent_rate) 120178172Simp{ 121178172Simp struct tegra210_clk_emc *emc = to_tegra210_clk_emc(hw); 122178172Simp struct tegra210_clk_emc_provider *provider = emc->provider; 123178172Simp struct tegra210_clk_emc_config *config; 124178172Simp struct device *dev = provider->dev; 125178172Simp struct clk_hw *old, *new, *parent; 126178172Simp u8 old_idx, new_idx, index; 127178172Simp struct clk *clk; 128178172Simp unsigned int i; 129294930Sjhb int err; 130178172Simp 131178172Simp if (!provider->configs || provider->num_configs == 0) 132178172Simp return -EINVAL; 133178172Simp 134178172Simp for (i = 0; i < provider->num_configs; i++) { 135178172Simp if (provider->configs[i].rate >= rate) { 136178172Simp config = &provider->configs[i]; 137178172Simp break; 138209500Sjchandra } 139178172Simp } 140178172Simp 141209500Sjchandra if (i == provider->num_configs) 142178172Simp config = &provider->configs[i - 1]; 143178172Simp 144178172Simp old_idx = tegra210_clk_emc_get_parent(hw); 145178172Simp new_idx = FIELD_GET(CLK_SOURCE_EMC_2X_CLK_SRC, config->value); 146178172Simp 147209500Sjchandra old = clk_hw_get_parent_by_index(hw, old_idx); 148178172Simp new = clk_hw_get_parent_by_index(hw, new_idx); 149178172Simp 150178172Simp /* if the rate has changed... */ 151178172Simp if (config->parent_rate != clk_hw_get_rate(old)) { 152178172Simp /* ... but the clock source remains the same ... */ 153178172Simp if (new_idx == old_idx) { 154178172Simp /* ... switch to the alternative clock source. */ 155178172Simp switch (new_idx) { 156178172Simp case CLK_SRC_PLLM: 157178172Simp new_idx = CLK_SRC_PLLMB; 158178172Simp break; 159178172Simp 160178172Simp case CLK_SRC_PLLM_UD: 161178172Simp new_idx = CLK_SRC_PLLMB_UD; 162178172Simp break; 163178172Simp 164178172Simp case CLK_SRC_PLLMB_UD: 165178172Simp new_idx = CLK_SRC_PLLM_UD; 166178172Simp break; 167178172Simp 168178172Simp case CLK_SRC_PLLMB: 169178172Simp new_idx = CLK_SRC_PLLM; 170209500Sjchandra break; 171209500Sjchandra } 172209500Sjchandra 173178172Simp /* 174178172Simp * This should never happen because we can't deal with 175178172Simp * it. 176209500Sjchandra */ 177178172Simp if (WARN_ON(new_idx == old_idx)) 178178172Simp return -EINVAL; 179178172Simp 180178172Simp new = clk_hw_get_parent_by_index(hw, new_idx); 181178172Simp } 182178172Simp 183178172Simp index = new_idx; 184178172Simp parent = new; 185178172Simp } else { 186178172Simp index = old_idx; 187178172Simp parent = old; 188178172Simp } 189225617Skmacy 190178172Simp clk = tegra210_clk_emc_find_parent(emc, index); 191178172Simp if (IS_ERR(clk)) { 192178172Simp err = PTR_ERR(clk); 193178172Simp dev_err(dev, "failed to get parent clock for index %u: %d\n", 194178172Simp index, err); 195178172Simp return err; 196178172Simp } 197178172Simp 198232586Sjmallett /* set the new parent clock to the required rate */ 199232586Sjmallett if (clk_get_rate(clk) != config->parent_rate) { 200232586Sjmallett err = clk_set_rate(clk, config->parent_rate); 201178172Simp if (err < 0) { 202232586Sjmallett dev_err(dev, "failed to set rate %lu Hz for %pC: %d\n", 203178172Simp config->parent_rate, clk, err); 204232586Sjmallett return err; 205178172Simp } 206178172Simp } 207178172Simp 208178172Simp /* enable the new parent clock */ 209178172Simp if (parent != old) { 210178172Simp err = clk_prepare_enable(clk); 211178172Simp if (err < 0) { 212178172Simp dev_err(dev, "failed to enable parent clock %pC: %d\n", 213178172Simp clk, err); 214178172Simp return err; 215178172Simp } 216178172Simp } 217178172Simp 218291961Smarkj /* update the EMC source configuration to reflect the new parent */ 219291961Smarkj config->value &= ~CLK_SOURCE_EMC_2X_CLK_SRC; 220291961Smarkj config->value |= FIELD_PREP(CLK_SOURCE_EMC_2X_CLK_SRC, index); 221178172Simp 222178172Simp /* 223178172Simp * Finally, switch the EMC programming with both old and new parent 224178172Simp * clocks enabled. 225178172Simp */ 226178172Simp err = provider->set_rate(dev, config); 227291961Smarkj if (err < 0) { 228291961Smarkj dev_err(dev, "failed to set EMC rate to %lu Hz: %d\n", rate, 229291961Smarkj err); 230178172Simp 231178172Simp /* 232178172Simp * If we're unable to switch to the new EMC frequency, we no 233178172Simp * longer need the new parent to be enabled. 234178172Simp */ 235178172Simp if (parent != old) 236178172Simp clk_disable_unprepare(clk); 237178172Simp 238210038Simp return err; 239178172Simp } 240178172Simp 241178172Simp /* reparent to new parent clock and disable the old parent clock */ 242178172Simp if (parent != old) { 243178172Simp clk = tegra210_clk_emc_find_parent(emc, old_idx); 244178172Simp if (IS_ERR(clk)) { 245178172Simp err = PTR_ERR(clk); 246178172Simp dev_err(dev, 247178172Simp "failed to get parent clock for index %u: %d\n", 248178172Simp old_idx, err); 249178172Simp return err; 250178172Simp } 251178172Simp 252202046Simp clk_hw_reparent(hw, parent); 253178172Simp clk_disable_unprepare(clk); 254178172Simp } 255178172Simp 256178172Simp return err; 257178172Simp} 258178172Simp 259178172Simpstatic const struct clk_ops tegra210_clk_emc_ops = { 260178172Simp .get_parent = tegra210_clk_emc_get_parent, 261178172Simp .recalc_rate = tegra210_clk_emc_recalc_rate, 262178172Simp .round_rate = tegra210_clk_emc_round_rate, 263178172Simp .set_rate = tegra210_clk_emc_set_rate, 264178172Simp}; 265178172Simp 266178172Simpstruct clk *tegra210_clk_register_emc(struct device_node *np, 267178172Simp void __iomem *regs) 268178172Simp{ 269178172Simp struct tegra210_clk_emc *emc; 270178172Simp struct clk_init_data init; 271178172Simp struct clk *clk; 272178172Simp 273178172Simp emc = kzalloc(sizeof(*emc), GFP_KERNEL); 274178172Simp if (!emc) 275178172Simp return ERR_PTR(-ENOMEM); 276178172Simp 277178172Simp emc->regs = regs; 278178172Simp 279178172Simp init.name = "emc"; 280178172Simp init.ops = &tegra210_clk_emc_ops; 281178172Simp init.flags = CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE; 282178172Simp init.parent_names = tegra210_clk_emc_parents; 283178172Simp init.num_parents = ARRAY_SIZE(tegra210_clk_emc_parents); 284178172Simp emc->hw.init = &init; 285178172Simp 286178172Simp clk = clk_register(NULL, &emc->hw); 287178172Simp if (IS_ERR(clk)) { 288178172Simp kfree(emc); 289178172Simp return clk; 290178172Simp } 291178172Simp 292178172Simp return clk; 293178172Simp} 294178172Simp 295178172Simpint tegra210_clk_emc_attach(struct clk *clk, 296178172Simp struct tegra210_clk_emc_provider *provider) 297178172Simp{ 298178172Simp struct clk_hw *hw = __clk_get_hw(clk); 299178172Simp struct tegra210_clk_emc *emc = to_tegra210_clk_emc(hw); 300178172Simp struct device *dev = provider->dev; 301178172Simp unsigned int i; 302178172Simp int err; 303178172Simp 304178172Simp if (!try_module_get(provider->owner)) 305178172Simp return -ENODEV; 306178172Simp 307178172Simp for (i = 0; i < provider->num_configs; i++) { 308178172Simp struct tegra210_clk_emc_config *config = &provider->configs[i]; 309178172Simp struct clk_hw *parent; 310178172Simp bool same_freq; 311178172Simp u8 div, src; 312178172Simp 313178172Simp div = FIELD_GET(CLK_SOURCE_EMC_2X_CLK_DIVISOR, config->value); 314178172Simp src = FIELD_GET(CLK_SOURCE_EMC_2X_CLK_SRC, config->value); 315178172Simp 316178172Simp /* do basic sanity checking on the EMC timings */ 317178172Simp if (div & 0x1) { 318178172Simp dev_err(dev, "invalid odd divider %u for rate %lu Hz\n", 319178172Simp div, config->rate); 320178172Simp err = -EINVAL; 321178172Simp goto put; 322178172Simp } 323178172Simp 324178172Simp same_freq = config->value & CLK_SOURCE_EMC_MC_EMC_SAME_FREQ; 325178172Simp 326178172Simp if (same_freq != config->same_freq) { 327178172Simp dev_err(dev, 328178172Simp "ambiguous EMC to MC ratio for rate %lu Hz\n", 329178172Simp config->rate); 330178172Simp err = -EINVAL; 331178172Simp goto put; 332178172Simp } 333178172Simp 334178172Simp parent = clk_hw_get_parent_by_index(hw, src); 335178172Simp config->parent = src; 336178172Simp 337178172Simp if (src == CLK_SRC_PLLM || src == CLK_SRC_PLLM_UD) { 338202046Simp config->parent_rate = config->rate * (1 + div / 2); 339202046Simp } else { 340202046Simp unsigned long rate = config->rate * (1 + div / 2); 341202046Simp 342202046Simp config->parent_rate = clk_hw_get_rate(parent); 343202046Simp 344178172Simp if (config->parent_rate != rate) { 345178172Simp dev_err(dev, 346178172Simp "rate %lu Hz does not match input\n", 347202046Simp config->rate); 348178172Simp err = -EINVAL; 349178172Simp goto put; 350178172Simp } 351178172Simp } 352278001Skib } 353178172Simp 354178172Simp emc->provider = provider; 355178172Simp 356178172Simp return 0; 357178172Simp 358178172Simpput: 359178172Simp module_put(provider->owner); 360178172Simp return err; 361178172Simp} 362178172SimpEXPORT_SYMBOL_GPL(tegra210_clk_emc_attach); 363178172Simp 364178172Simpvoid tegra210_clk_emc_detach(struct clk *clk) 365178172Simp{ 366178172Simp struct tegra210_clk_emc *emc = to_tegra210_clk_emc(__clk_get_hw(clk)); 367178172Simp 368202046Simp module_put(emc->provider->owner); 369264625Srwatson emc->provider = NULL; 370178172Simp} 371178172SimpEXPORT_SYMBOL_GPL(tegra210_clk_emc_detach); 372178172Simp