^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Based on drivers/clk/tegra/clk-emc.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Author: Dmitry Osipenko <digetx@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2019 GRATE-DRIVER project
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #define pr_fmt(fmt) "tegra-emc-clk: " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/bits.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/clk-provider.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/clk/tegra.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "clk.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define CLK_SOURCE_EMC_2X_CLK_DIVISOR_MASK GENMASK(7, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define CLK_SOURCE_EMC_2X_CLK_SRC_MASK GENMASK(31, 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define CLK_SOURCE_EMC_2X_CLK_SRC_SHIFT 30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define MC_EMC_SAME_FREQ BIT(16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define USE_PLLM_UD BIT(29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define EMC_SRC_PLL_M 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define EMC_SRC_PLL_C 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define EMC_SRC_PLL_P 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define EMC_SRC_CLK_M 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static const char * const emc_parent_clk_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) "pll_m", "pll_c", "pll_p", "clk_m",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct tegra_clk_emc {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct clk_hw hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) void __iomem *reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) bool mc_same_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) bool want_low_jitter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) tegra20_clk_emc_round_cb *round_cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) void *cb_arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static inline struct tegra_clk_emc *to_tegra_clk_emc(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return container_of(hw, struct tegra_clk_emc, hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static unsigned long emc_recalc_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct tegra_clk_emc *emc = to_tegra_clk_emc(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) u32 val, div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) val = readl_relaxed(emc->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) div = val & CLK_SOURCE_EMC_2X_CLK_DIVISOR_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return DIV_ROUND_UP(parent_rate * 2, div + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static u8 emc_get_parent(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct tegra_clk_emc *emc = to_tegra_clk_emc(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return readl_relaxed(emc->reg) >> CLK_SOURCE_EMC_2X_CLK_SRC_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static int emc_set_parent(struct clk_hw *hw, u8 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct tegra_clk_emc *emc = to_tegra_clk_emc(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) u32 val, div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) val = readl_relaxed(emc->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) val &= ~CLK_SOURCE_EMC_2X_CLK_SRC_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) val |= index << CLK_SOURCE_EMC_2X_CLK_SRC_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) div = val & CLK_SOURCE_EMC_2X_CLK_DIVISOR_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (index == EMC_SRC_PLL_M && div == 0 && emc->want_low_jitter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) val |= USE_PLLM_UD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) val &= ~USE_PLLM_UD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (emc->mc_same_freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) val |= MC_EMC_SAME_FREQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) val &= ~MC_EMC_SAME_FREQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) writel_relaxed(val, emc->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) fence_udelay(1, emc->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static int emc_set_rate(struct clk_hw *hw, unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct tegra_clk_emc *emc = to_tegra_clk_emc(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) unsigned int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) u32 val, div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) div = div_frac_get(rate, parent_rate, 8, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) val = readl_relaxed(emc->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) val &= ~CLK_SOURCE_EMC_2X_CLK_DIVISOR_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) val |= div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) index = val >> CLK_SOURCE_EMC_2X_CLK_SRC_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (index == EMC_SRC_PLL_M && div == 0 && emc->want_low_jitter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) val |= USE_PLLM_UD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) val &= ~USE_PLLM_UD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (emc->mc_same_freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) val |= MC_EMC_SAME_FREQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) val &= ~MC_EMC_SAME_FREQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) writel_relaxed(val, emc->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) fence_udelay(1, emc->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static int emc_set_rate_and_parent(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) unsigned long parent_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) u8 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) struct tegra_clk_emc *emc = to_tegra_clk_emc(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) u32 val, div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) div = div_frac_get(rate, parent_rate, 8, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) val = readl_relaxed(emc->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) val &= ~CLK_SOURCE_EMC_2X_CLK_SRC_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) val |= index << CLK_SOURCE_EMC_2X_CLK_SRC_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) val &= ~CLK_SOURCE_EMC_2X_CLK_DIVISOR_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) val |= div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (index == EMC_SRC_PLL_M && div == 0 && emc->want_low_jitter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) val |= USE_PLLM_UD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) val &= ~USE_PLLM_UD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (emc->mc_same_freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) val |= MC_EMC_SAME_FREQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) val &= ~MC_EMC_SAME_FREQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) writel_relaxed(val, emc->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) fence_udelay(1, emc->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static int emc_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) struct tegra_clk_emc *emc = to_tegra_clk_emc(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) struct clk_hw *parent_hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) unsigned long divided_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) unsigned long parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) long emc_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) int div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) emc_rate = emc->round_cb(req->rate, req->min_rate, req->max_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) emc->cb_arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (emc_rate < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return emc_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) for (i = 0; i < ARRAY_SIZE(emc_parent_clk_names); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) parent_hw = clk_hw_get_parent_by_index(hw, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (req->best_parent_hw == parent_hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) parent_rate = req->best_parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) parent_rate = clk_hw_get_rate(parent_hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (emc_rate > parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) div = div_frac_get(emc_rate, parent_rate, 8, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) divided_rate = DIV_ROUND_UP(parent_rate * 2, div + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (divided_rate != emc_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) req->best_parent_rate = parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) req->best_parent_hw = parent_hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) req->rate = emc_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (i == ARRAY_SIZE(emc_parent_clk_names)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) pr_err_once("can't find parent for rate %lu emc_rate %lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) req->rate, emc_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) static const struct clk_ops tegra_clk_emc_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) .recalc_rate = emc_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) .get_parent = emc_get_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) .set_parent = emc_set_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) .set_rate = emc_set_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) .set_rate_and_parent = emc_set_rate_and_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) .determine_rate = emc_determine_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) void tegra20_clk_set_emc_round_callback(tegra20_clk_emc_round_cb *round_cb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) void *cb_arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) struct clk *clk = __clk_lookup("emc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) struct tegra_clk_emc *emc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) struct clk_hw *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (clk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) hw = __clk_get_hw(clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) emc = to_tegra_clk_emc(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) emc->round_cb = round_cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) emc->cb_arg = cb_arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) bool tegra20_clk_emc_driver_available(struct clk_hw *emc_hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) return to_tegra_clk_emc(emc_hw)->round_cb != NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) struct clk *tegra20_clk_register_emc(void __iomem *ioaddr, bool low_jitter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) struct tegra_clk_emc *emc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct clk_init_data init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) emc = kzalloc(sizeof(*emc), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (!emc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * EMC stands for External Memory Controller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * We don't want EMC clock to be disabled ever by gating its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * parent and whatnot because system is busted immediately in that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) * case, hence the clock is marked as critical.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) init.name = "emc";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) init.ops = &tegra_clk_emc_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) init.flags = CLK_IS_CRITICAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) init.parent_names = emc_parent_clk_names;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) init.num_parents = ARRAY_SIZE(emc_parent_clk_names);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) emc->reg = ioaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) emc->hw.init = &init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) emc->want_low_jitter = low_jitter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) clk = clk_register(NULL, &emc->hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (IS_ERR(clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) kfree(emc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) int tegra20_clk_prepare_emc_mc_same_freq(struct clk *emc_clk, bool same)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) struct tegra_clk_emc *emc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) struct clk_hw *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (!emc_clk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) hw = __clk_get_hw(emc_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) emc = to_tegra_clk_emc(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) emc->mc_same_freq = same;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }