1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2015-2020, NVIDIA CORPORATION.  All rights reserved.
4  */
5 
6 #include <linux/bitfield.h>
7 #include <linux/clk.h>
8 #include <linux/clk-provider.h>
9 #include <linux/clk/tegra.h>
10 #include <linux/device.h>
11 #include <linux/module.h>
12 #include <linux/io.h>
13 #include <linux/slab.h>
14 
15 #define CLK_SOURCE_EMC 0x19c
16 #define  CLK_SOURCE_EMC_2X_CLK_SRC GENMASK(31, 29)
17 #define  CLK_SOURCE_EMC_MC_EMC_SAME_FREQ BIT(16)
18 #define  CLK_SOURCE_EMC_2X_CLK_DIVISOR GENMASK(7, 0)
19 
20 #define CLK_SRC_PLLM 0
21 #define CLK_SRC_PLLC 1
22 #define CLK_SRC_PLLP 2
23 #define CLK_SRC_CLK_M 3
24 #define CLK_SRC_PLLM_UD 4
25 #define CLK_SRC_PLLMB_UD 5
26 #define CLK_SRC_PLLMB 6
27 #define CLK_SRC_PLLP_UD 7
28 
29 struct tegra210_clk_emc {
30 	struct clk_hw hw;
31 	void __iomem *regs;
32 
33 	struct tegra210_clk_emc_provider *provider;
34 
35 	struct clk *parents[8];
36 };
37 
38 static inline struct tegra210_clk_emc *
39 to_tegra210_clk_emc(struct clk_hw *hw)
40 {
41 	return container_of(hw, struct tegra210_clk_emc, hw);
42 }
43 
44 static const char *tegra210_clk_emc_parents[] = {
45 	"pll_m", "pll_c", "pll_p", "clk_m", "pll_m_ud", "pll_mb_ud",
46 	"pll_mb", "pll_p_ud",
47 };
48 
49 static u8 tegra210_clk_emc_get_parent(struct clk_hw *hw)
50 {
51 	struct tegra210_clk_emc *emc = to_tegra210_clk_emc(hw);
52 	u32 value;
53 	u8 src;
54 
55 	value = readl_relaxed(emc->regs + CLK_SOURCE_EMC);
56 	src = FIELD_GET(CLK_SOURCE_EMC_2X_CLK_SRC, value);
57 
58 	return src;
59 }
60 
61 static unsigned long tegra210_clk_emc_recalc_rate(struct clk_hw *hw,
62 						  unsigned long parent_rate)
63 {
64 	struct tegra210_clk_emc *emc = to_tegra210_clk_emc(hw);
65 	u32 value, div;
66 
67 	/*
68 	 * CCF assumes that neither the parent nor its rate will change during
69 	 * ->set_rate(), so the parent rate passed in here was cached from the
70 	 * parent before the ->set_rate() call.
71 	 *
72 	 * This can lead to wrong results being reported for the EMC clock if
73 	 * the parent and/or parent rate have changed as part of the EMC rate
74 	 * change sequence. Fix this by overriding the parent clock with what
75 	 * we know to be the correct value after the rate change.
76 	 */
77 	parent_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
78 
79 	value = readl_relaxed(emc->regs + CLK_SOURCE_EMC);
80 
81 	div = FIELD_GET(CLK_SOURCE_EMC_2X_CLK_DIVISOR, value);
82 	div += 2;
83 
84 	return DIV_ROUND_UP(parent_rate * 2, div);
85 }
86 
87 static long tegra210_clk_emc_round_rate(struct clk_hw *hw, unsigned long rate,
88 					unsigned long *prate)
89 {
90 	struct tegra210_clk_emc *emc = to_tegra210_clk_emc(hw);
91 	struct tegra210_clk_emc_provider *provider = emc->provider;
92 	unsigned int i;
93 
94 	if (!provider || !provider->configs || provider->num_configs == 0)
95 		return clk_hw_get_rate(hw);
96 
97 	for (i = 0; i < provider->num_configs; i++) {
98 		if (provider->configs[i].rate >= rate)
99 			return provider->configs[i].rate;
100 	}
101 
102 	return provider->configs[i - 1].rate;
103 }
104 
105 static struct clk *tegra210_clk_emc_find_parent(struct tegra210_clk_emc *emc,
106 						u8 index)
107 {
108 	struct clk_hw *parent = clk_hw_get_parent_by_index(&emc->hw, index);
109 	const char *name = clk_hw_get_name(parent);
110 
111 	/* XXX implement cache? */
112 
113 	return __clk_lookup(name);
114 }
115 
116 static int tegra210_clk_emc_set_rate(struct clk_hw *hw, unsigned long rate,
117 				     unsigned long parent_rate)
118 {
119 	struct tegra210_clk_emc *emc = to_tegra210_clk_emc(hw);
120 	struct tegra210_clk_emc_provider *provider = emc->provider;
121 	struct tegra210_clk_emc_config *config;
122 	struct device *dev = provider->dev;
123 	struct clk_hw *old, *new, *parent;
124 	u8 old_idx, new_idx, index;
125 	struct clk *clk;
126 	unsigned int i;
127 	int err;
128 
129 	if (!provider || !provider->configs || provider->num_configs == 0)
130 		return -EINVAL;
131 
132 	for (i = 0; i < provider->num_configs; i++) {
133 		if (provider->configs[i].rate >= rate) {
134 			config = &provider->configs[i];
135 			break;
136 		}
137 	}
138 
139 	if (i == provider->num_configs)
140 		config = &provider->configs[i - 1];
141 
142 	old_idx = tegra210_clk_emc_get_parent(hw);
143 	new_idx = FIELD_GET(CLK_SOURCE_EMC_2X_CLK_SRC, config->value);
144 
145 	old = clk_hw_get_parent_by_index(hw, old_idx);
146 	new = clk_hw_get_parent_by_index(hw, new_idx);
147 
148 	/* if the rate has changed... */
149 	if (config->parent_rate != clk_hw_get_rate(old)) {
150 		/* ... but the clock source remains the same ... */
151 		if (new_idx == old_idx) {
152 			/* ... switch to the alternative clock source. */
153 			switch (new_idx) {
154 			case CLK_SRC_PLLM:
155 				new_idx = CLK_SRC_PLLMB;
156 				break;
157 
158 			case CLK_SRC_PLLM_UD:
159 				new_idx = CLK_SRC_PLLMB_UD;
160 				break;
161 
162 			case CLK_SRC_PLLMB_UD:
163 				new_idx = CLK_SRC_PLLM_UD;
164 				break;
165 
166 			case CLK_SRC_PLLMB:
167 				new_idx = CLK_SRC_PLLM;
168 				break;
169 			}
170 
171 			/*
172 			 * This should never happen because we can't deal with
173 			 * it.
174 			 */
175 			if (WARN_ON(new_idx == old_idx))
176 				return -EINVAL;
177 
178 			new = clk_hw_get_parent_by_index(hw, new_idx);
179 		}
180 
181 		index = new_idx;
182 		parent = new;
183 	} else {
184 		index = old_idx;
185 		parent = old;
186 	}
187 
188 	clk = tegra210_clk_emc_find_parent(emc, index);
189 	if (IS_ERR(clk)) {
190 		err = PTR_ERR(clk);
191 		dev_err(dev, "failed to get parent clock for index %u: %d\n",
192 			index, err);
193 		return err;
194 	}
195 
196 	/* set the new parent clock to the required rate */
197 	if (clk_get_rate(clk) != config->parent_rate) {
198 		err = clk_set_rate(clk, config->parent_rate);
199 		if (err < 0) {
200 			dev_err(dev, "failed to set rate %lu Hz for %pC: %d\n",
201 				config->parent_rate, clk, err);
202 			return err;
203 		}
204 	}
205 
206 	/* enable the new parent clock */
207 	if (parent != old) {
208 		err = clk_prepare_enable(clk);
209 		if (err < 0) {
210 			dev_err(dev, "failed to enable parent clock %pC: %d\n",
211 				clk, err);
212 			return err;
213 		}
214 	}
215 
216 	/* update the EMC source configuration to reflect the new parent */
217 	config->value &= ~CLK_SOURCE_EMC_2X_CLK_SRC;
218 	config->value |= FIELD_PREP(CLK_SOURCE_EMC_2X_CLK_SRC, index);
219 
220 	/*
221 	 * Finally, switch the EMC programming with both old and new parent
222 	 * clocks enabled.
223 	 */
224 	err = provider->set_rate(dev, config);
225 	if (err < 0) {
226 		dev_err(dev, "failed to set EMC rate to %lu Hz: %d\n", rate,
227 			err);
228 
229 		/*
230 		 * If we're unable to switch to the new EMC frequency, we no
231 		 * longer need the new parent to be enabled.
232 		 */
233 		if (parent != old)
234 			clk_disable_unprepare(clk);
235 
236 		return err;
237 	}
238 
239 	/* reparent to new parent clock and disable the old parent clock */
240 	if (parent != old) {
241 		clk = tegra210_clk_emc_find_parent(emc, old_idx);
242 		if (IS_ERR(clk)) {
243 			err = PTR_ERR(clk);
244 			dev_err(dev,
245 				"failed to get parent clock for index %u: %d\n",
246 				old_idx, err);
247 			return err;
248 		}
249 
250 		clk_hw_reparent(hw, parent);
251 		clk_disable_unprepare(clk);
252 	}
253 
254 	return err;
255 }
256 
257 static const struct clk_ops tegra210_clk_emc_ops = {
258 	.get_parent = tegra210_clk_emc_get_parent,
259 	.recalc_rate = tegra210_clk_emc_recalc_rate,
260 	.round_rate = tegra210_clk_emc_round_rate,
261 	.set_rate = tegra210_clk_emc_set_rate,
262 };
263 
264 struct clk *tegra210_clk_register_emc(struct device_node *np,
265 				      void __iomem *regs)
266 {
267 	struct tegra210_clk_emc *emc;
268 	struct clk_init_data init;
269 	struct clk *clk;
270 
271 	emc = kzalloc(sizeof(*emc), GFP_KERNEL);
272 	if (!emc)
273 		return ERR_PTR(-ENOMEM);
274 
275 	emc->regs = regs;
276 
277 	init.name = "emc";
278 	init.ops = &tegra210_clk_emc_ops;
279 	init.flags = CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE;
280 	init.parent_names = tegra210_clk_emc_parents;
281 	init.num_parents = ARRAY_SIZE(tegra210_clk_emc_parents);
282 	emc->hw.init = &init;
283 
284 	clk = clk_register(NULL, &emc->hw);
285 	if (IS_ERR(clk)) {
286 		kfree(emc);
287 		return clk;
288 	}
289 
290 	return clk;
291 }
292 
293 int tegra210_clk_emc_attach(struct clk *clk,
294 			    struct tegra210_clk_emc_provider *provider)
295 {
296 	struct clk_hw *hw = __clk_get_hw(clk);
297 	struct tegra210_clk_emc *emc = to_tegra210_clk_emc(hw);
298 	struct device *dev = provider->dev;
299 	unsigned int i;
300 	int err;
301 
302 	if (!try_module_get(provider->owner))
303 		return -ENODEV;
304 
305 	for (i = 0; i < provider->num_configs; i++) {
306 		struct tegra210_clk_emc_config *config = &provider->configs[i];
307 		struct clk_hw *parent;
308 		bool same_freq;
309 		u8 div, src;
310 
311 		div = FIELD_GET(CLK_SOURCE_EMC_2X_CLK_DIVISOR, config->value);
312 		src = FIELD_GET(CLK_SOURCE_EMC_2X_CLK_SRC, config->value);
313 
314 		/* do basic sanity checking on the EMC timings */
315 		if (div & 0x1) {
316 			dev_err(dev, "invalid odd divider %u for rate %lu Hz\n",
317 				div, config->rate);
318 			err = -EINVAL;
319 			goto put;
320 		}
321 
322 		same_freq = config->value & CLK_SOURCE_EMC_MC_EMC_SAME_FREQ;
323 
324 		if (same_freq != config->same_freq) {
325 			dev_err(dev,
326 				"ambiguous EMC to MC ratio for rate %lu Hz\n",
327 				config->rate);
328 			err = -EINVAL;
329 			goto put;
330 		}
331 
332 		parent = clk_hw_get_parent_by_index(hw, src);
333 		config->parent = src;
334 
335 		if (src == CLK_SRC_PLLM || src == CLK_SRC_PLLM_UD) {
336 			config->parent_rate = config->rate * (1 + div / 2);
337 		} else {
338 			unsigned long rate = config->rate * (1 + div / 2);
339 
340 			config->parent_rate = clk_hw_get_rate(parent);
341 
342 			if (config->parent_rate != rate) {
343 				dev_err(dev,
344 					"rate %lu Hz does not match input\n",
345 					config->rate);
346 				err = -EINVAL;
347 				goto put;
348 			}
349 		}
350 	}
351 
352 	emc->provider = provider;
353 
354 	return 0;
355 
356 put:
357 	module_put(provider->owner);
358 	return err;
359 }
360 EXPORT_SYMBOL_GPL(tegra210_clk_emc_attach);
361 
362 void tegra210_clk_emc_detach(struct clk *clk)
363 {
364 	struct tegra210_clk_emc *emc = to_tegra210_clk_emc(__clk_get_hw(clk));
365 
366 	module_put(emc->provider->owner);
367 	emc->provider = NULL;
368 }
369 EXPORT_SYMBOL_GPL(tegra210_clk_emc_detach);
370