0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #define pr_fmt(fmt) "tegra-emc-clk: " fmt
0011
0012 #include <linux/bits.h>
0013 #include <linux/clk-provider.h>
0014 #include <linux/clk/tegra.h>
0015 #include <linux/err.h>
0016 #include <linux/export.h>
0017 #include <linux/io.h>
0018 #include <linux/kernel.h>
0019 #include <linux/slab.h>
0020
0021 #include "clk.h"
0022
0023 #define CLK_SOURCE_EMC_2X_CLK_DIVISOR_MASK GENMASK(7, 0)
0024 #define CLK_SOURCE_EMC_2X_CLK_SRC_MASK GENMASK(31, 30)
0025 #define CLK_SOURCE_EMC_2X_CLK_SRC_SHIFT 30
0026
0027 #define MC_EMC_SAME_FREQ BIT(16)
0028 #define USE_PLLM_UD BIT(29)
0029
0030 #define EMC_SRC_PLL_M 0
0031 #define EMC_SRC_PLL_C 1
0032 #define EMC_SRC_PLL_P 2
0033 #define EMC_SRC_CLK_M 3
0034
0035 static const char * const emc_parent_clk_names[] = {
0036 "pll_m", "pll_c", "pll_p", "clk_m",
0037 };
0038
0039 struct tegra_clk_emc {
0040 struct clk_hw hw;
0041 void __iomem *reg;
0042 bool mc_same_freq;
0043 bool want_low_jitter;
0044
0045 tegra20_clk_emc_round_cb *round_cb;
0046 void *cb_arg;
0047 };
0048
0049 static inline struct tegra_clk_emc *to_tegra_clk_emc(struct clk_hw *hw)
0050 {
0051 return container_of(hw, struct tegra_clk_emc, hw);
0052 }
0053
0054 static unsigned long emc_recalc_rate(struct clk_hw *hw,
0055 unsigned long parent_rate)
0056 {
0057 struct tegra_clk_emc *emc = to_tegra_clk_emc(hw);
0058 u32 val, div;
0059
0060 val = readl_relaxed(emc->reg);
0061 div = val & CLK_SOURCE_EMC_2X_CLK_DIVISOR_MASK;
0062
0063 return DIV_ROUND_UP(parent_rate * 2, div + 2);
0064 }
0065
0066 static u8 emc_get_parent(struct clk_hw *hw)
0067 {
0068 struct tegra_clk_emc *emc = to_tegra_clk_emc(hw);
0069
0070 return readl_relaxed(emc->reg) >> CLK_SOURCE_EMC_2X_CLK_SRC_SHIFT;
0071 }
0072
0073 static int emc_set_parent(struct clk_hw *hw, u8 index)
0074 {
0075 struct tegra_clk_emc *emc = to_tegra_clk_emc(hw);
0076 u32 val, div;
0077
0078 val = readl_relaxed(emc->reg);
0079 val &= ~CLK_SOURCE_EMC_2X_CLK_SRC_MASK;
0080 val |= index << CLK_SOURCE_EMC_2X_CLK_SRC_SHIFT;
0081
0082 div = val & CLK_SOURCE_EMC_2X_CLK_DIVISOR_MASK;
0083
0084 if (index == EMC_SRC_PLL_M && div == 0 && emc->want_low_jitter)
0085 val |= USE_PLLM_UD;
0086 else
0087 val &= ~USE_PLLM_UD;
0088
0089 if (emc->mc_same_freq)
0090 val |= MC_EMC_SAME_FREQ;
0091 else
0092 val &= ~MC_EMC_SAME_FREQ;
0093
0094 writel_relaxed(val, emc->reg);
0095
0096 fence_udelay(1, emc->reg);
0097
0098 return 0;
0099 }
0100
0101 static int emc_set_rate(struct clk_hw *hw, unsigned long rate,
0102 unsigned long parent_rate)
0103 {
0104 struct tegra_clk_emc *emc = to_tegra_clk_emc(hw);
0105 unsigned int index;
0106 u32 val, div;
0107
0108 div = div_frac_get(rate, parent_rate, 8, 1, 0);
0109
0110 val = readl_relaxed(emc->reg);
0111 val &= ~CLK_SOURCE_EMC_2X_CLK_DIVISOR_MASK;
0112 val |= div;
0113
0114 index = val >> CLK_SOURCE_EMC_2X_CLK_SRC_SHIFT;
0115
0116 if (index == EMC_SRC_PLL_M && div == 0 && emc->want_low_jitter)
0117 val |= USE_PLLM_UD;
0118 else
0119 val &= ~USE_PLLM_UD;
0120
0121 if (emc->mc_same_freq)
0122 val |= MC_EMC_SAME_FREQ;
0123 else
0124 val &= ~MC_EMC_SAME_FREQ;
0125
0126 writel_relaxed(val, emc->reg);
0127
0128 fence_udelay(1, emc->reg);
0129
0130 return 0;
0131 }
0132
0133 static int emc_set_rate_and_parent(struct clk_hw *hw,
0134 unsigned long rate,
0135 unsigned long parent_rate,
0136 u8 index)
0137 {
0138 struct tegra_clk_emc *emc = to_tegra_clk_emc(hw);
0139 u32 val, div;
0140
0141 div = div_frac_get(rate, parent_rate, 8, 1, 0);
0142
0143 val = readl_relaxed(emc->reg);
0144
0145 val &= ~CLK_SOURCE_EMC_2X_CLK_SRC_MASK;
0146 val |= index << CLK_SOURCE_EMC_2X_CLK_SRC_SHIFT;
0147
0148 val &= ~CLK_SOURCE_EMC_2X_CLK_DIVISOR_MASK;
0149 val |= div;
0150
0151 if (index == EMC_SRC_PLL_M && div == 0 && emc->want_low_jitter)
0152 val |= USE_PLLM_UD;
0153 else
0154 val &= ~USE_PLLM_UD;
0155
0156 if (emc->mc_same_freq)
0157 val |= MC_EMC_SAME_FREQ;
0158 else
0159 val &= ~MC_EMC_SAME_FREQ;
0160
0161 writel_relaxed(val, emc->reg);
0162
0163 fence_udelay(1, emc->reg);
0164
0165 return 0;
0166 }
0167
0168 static int emc_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
0169 {
0170 struct tegra_clk_emc *emc = to_tegra_clk_emc(hw);
0171 struct clk_hw *parent_hw;
0172 unsigned long divided_rate;
0173 unsigned long parent_rate;
0174 unsigned int i;
0175 long emc_rate;
0176 int div;
0177
0178 emc_rate = emc->round_cb(req->rate, req->min_rate, req->max_rate,
0179 emc->cb_arg);
0180 if (emc_rate < 0)
0181 return emc_rate;
0182
0183 for (i = 0; i < ARRAY_SIZE(emc_parent_clk_names); i++) {
0184 parent_hw = clk_hw_get_parent_by_index(hw, i);
0185
0186 if (req->best_parent_hw == parent_hw)
0187 parent_rate = req->best_parent_rate;
0188 else
0189 parent_rate = clk_hw_get_rate(parent_hw);
0190
0191 if (emc_rate > parent_rate)
0192 continue;
0193
0194 div = div_frac_get(emc_rate, parent_rate, 8, 1, 0);
0195 divided_rate = DIV_ROUND_UP(parent_rate * 2, div + 2);
0196
0197 if (divided_rate != emc_rate)
0198 continue;
0199
0200 req->best_parent_rate = parent_rate;
0201 req->best_parent_hw = parent_hw;
0202 req->rate = emc_rate;
0203 break;
0204 }
0205
0206 if (i == ARRAY_SIZE(emc_parent_clk_names)) {
0207 pr_err_once("can't find parent for rate %lu emc_rate %lu\n",
0208 req->rate, emc_rate);
0209 return -EINVAL;
0210 }
0211
0212 return 0;
0213 }
0214
0215 static const struct clk_ops tegra_clk_emc_ops = {
0216 .recalc_rate = emc_recalc_rate,
0217 .get_parent = emc_get_parent,
0218 .set_parent = emc_set_parent,
0219 .set_rate = emc_set_rate,
0220 .set_rate_and_parent = emc_set_rate_and_parent,
0221 .determine_rate = emc_determine_rate,
0222 };
0223
0224 void tegra20_clk_set_emc_round_callback(tegra20_clk_emc_round_cb *round_cb,
0225 void *cb_arg)
0226 {
0227 struct clk *clk = __clk_lookup("emc");
0228 struct tegra_clk_emc *emc;
0229 struct clk_hw *hw;
0230
0231 if (clk) {
0232 hw = __clk_get_hw(clk);
0233 emc = to_tegra_clk_emc(hw);
0234
0235 emc->round_cb = round_cb;
0236 emc->cb_arg = cb_arg;
0237 }
0238 }
0239 EXPORT_SYMBOL_GPL(tegra20_clk_set_emc_round_callback);
0240
0241 bool tegra20_clk_emc_driver_available(struct clk_hw *emc_hw)
0242 {
0243 return to_tegra_clk_emc(emc_hw)->round_cb != NULL;
0244 }
0245
0246 struct clk *tegra20_clk_register_emc(void __iomem *ioaddr, bool low_jitter)
0247 {
0248 struct tegra_clk_emc *emc;
0249 struct clk_init_data init;
0250 struct clk *clk;
0251
0252 emc = kzalloc(sizeof(*emc), GFP_KERNEL);
0253 if (!emc)
0254 return NULL;
0255
0256
0257
0258
0259
0260
0261
0262
0263 init.name = "emc";
0264 init.ops = &tegra_clk_emc_ops;
0265 init.flags = CLK_IS_CRITICAL;
0266 init.parent_names = emc_parent_clk_names;
0267 init.num_parents = ARRAY_SIZE(emc_parent_clk_names);
0268
0269 emc->reg = ioaddr;
0270 emc->hw.init = &init;
0271 emc->want_low_jitter = low_jitter;
0272
0273 clk = clk_register(NULL, &emc->hw);
0274 if (IS_ERR(clk)) {
0275 kfree(emc);
0276 return NULL;
0277 }
0278
0279 return clk;
0280 }
0281
0282 int tegra20_clk_prepare_emc_mc_same_freq(struct clk *emc_clk, bool same)
0283 {
0284 struct tegra_clk_emc *emc;
0285 struct clk_hw *hw;
0286
0287 if (!emc_clk)
0288 return -EINVAL;
0289
0290 hw = __clk_get_hw(emc_clk);
0291 emc = to_tegra_clk_emc(hw);
0292 emc->mc_same_freq = same;
0293
0294 return 0;
0295 }
0296 EXPORT_SYMBOL_GPL(tegra20_clk_prepare_emc_mc_same_freq);