xref: /openbmc/linux/drivers/clk/qcom/krait-cc.c (revision fadbafc1)
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2018, The Linux Foundation. All rights reserved.
3 
4 #include <linux/kernel.h>
5 #include <linux/init.h>
6 #include <linux/module.h>
7 #include <linux/platform_device.h>
8 #include <linux/err.h>
9 #include <linux/io.h>
10 #include <linux/of.h>
11 #include <linux/of_device.h>
12 #include <linux/clk.h>
13 #include <linux/clk-provider.h>
14 #include <linux/slab.h>
15 
16 #include "clk-krait.h"
17 
18 static unsigned int sec_mux_map[] = {
19 	2,
20 	0,
21 };
22 
23 static unsigned int pri_mux_map[] = {
24 	1,
25 	2,
26 	0,
27 };
28 
29 /*
30  * Notifier function for switching the muxes to safe parent
31  * while the hfpll is getting reprogrammed.
32  */
33 static int krait_notifier_cb(struct notifier_block *nb,
34 			     unsigned long event,
35 			     void *data)
36 {
37 	int ret = 0;
38 	struct krait_mux_clk *mux = container_of(nb, struct krait_mux_clk,
39 						 clk_nb);
40 	/* Switch to safe parent */
41 	if (event == PRE_RATE_CHANGE) {
42 		mux->old_index = krait_mux_clk_ops.get_parent(&mux->hw);
43 		ret = krait_mux_clk_ops.set_parent(&mux->hw, mux->safe_sel);
44 		mux->reparent = false;
45 	/*
46 	 * By the time POST_RATE_CHANGE notifier is called,
47 	 * clk framework itself would have changed the parent for the new rate.
48 	 * Only otherwise, put back to the old parent.
49 	 */
50 	} else if (event == POST_RATE_CHANGE) {
51 		if (!mux->reparent)
52 			ret = krait_mux_clk_ops.set_parent(&mux->hw,
53 							   mux->old_index);
54 	}
55 
56 	return notifier_from_errno(ret);
57 }
58 
59 static int krait_notifier_register(struct device *dev, struct clk *clk,
60 				   struct krait_mux_clk *mux)
61 {
62 	int ret = 0;
63 
64 	mux->clk_nb.notifier_call = krait_notifier_cb;
65 	ret = clk_notifier_register(clk, &mux->clk_nb);
66 	if (ret)
67 		dev_err(dev, "failed to register clock notifier: %d\n", ret);
68 
69 	return ret;
70 }
71 
72 static int
73 krait_add_div(struct device *dev, int id, const char *s, unsigned int offset)
74 {
75 	struct krait_div2_clk *div;
76 	struct clk_init_data init = {
77 		.num_parents = 1,
78 		.ops = &krait_div2_clk_ops,
79 		.flags = CLK_SET_RATE_PARENT,
80 	};
81 	const char *p_names[1];
82 	struct clk *clk;
83 
84 	div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL);
85 	if (!div)
86 		return -ENOMEM;
87 
88 	div->width = 2;
89 	div->shift = 6;
90 	div->lpl = id >= 0;
91 	div->offset = offset;
92 	div->hw.init = &init;
93 
94 	init.name = kasprintf(GFP_KERNEL, "hfpll%s_div", s);
95 	if (!init.name)
96 		return -ENOMEM;
97 
98 	init.parent_names = p_names;
99 	p_names[0] = kasprintf(GFP_KERNEL, "hfpll%s", s);
100 	if (!p_names[0]) {
101 		kfree(init.name);
102 		return -ENOMEM;
103 	}
104 
105 	clk = devm_clk_register(dev, &div->hw);
106 	kfree(p_names[0]);
107 	kfree(init.name);
108 
109 	return PTR_ERR_OR_ZERO(clk);
110 }
111 
112 static int
113 krait_add_sec_mux(struct device *dev, int id, const char *s,
114 		  unsigned int offset, bool unique_aux)
115 {
116 	int ret;
117 	struct krait_mux_clk *mux;
118 	static const char *sec_mux_list[] = {
119 		"acpu_aux",
120 		"qsb",
121 	};
122 	struct clk_init_data init = {
123 		.parent_names = sec_mux_list,
124 		.num_parents = ARRAY_SIZE(sec_mux_list),
125 		.ops = &krait_mux_clk_ops,
126 		.flags = CLK_SET_RATE_PARENT,
127 	};
128 	struct clk *clk;
129 
130 	mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
131 	if (!mux)
132 		return -ENOMEM;
133 
134 	mux->offset = offset;
135 	mux->lpl = id >= 0;
136 	mux->mask = 0x3;
137 	mux->shift = 2;
138 	mux->parent_map = sec_mux_map;
139 	mux->hw.init = &init;
140 	mux->safe_sel = 0;
141 
142 	/* Checking for qcom,krait-cc-v1 or qcom,krait-cc-v2 is not
143 	 * enough to limit this to apq/ipq8064. Directly check machine
144 	 * compatible to correctly handle this errata.
145 	 */
146 	if (of_machine_is_compatible("qcom,ipq8064") ||
147 	    of_machine_is_compatible("qcom,apq8064"))
148 		mux->disable_sec_src_gating = true;
149 
150 	init.name = kasprintf(GFP_KERNEL, "krait%s_sec_mux", s);
151 	if (!init.name)
152 		return -ENOMEM;
153 
154 	if (unique_aux) {
155 		sec_mux_list[0] = kasprintf(GFP_KERNEL, "acpu%s_aux", s);
156 		if (!sec_mux_list[0]) {
157 			clk = ERR_PTR(-ENOMEM);
158 			goto err_aux;
159 		}
160 	}
161 
162 	clk = devm_clk_register(dev, &mux->hw);
163 
164 	ret = krait_notifier_register(dev, clk, mux);
165 	if (ret)
166 		goto unique_aux;
167 
168 unique_aux:
169 	if (unique_aux)
170 		kfree(sec_mux_list[0]);
171 err_aux:
172 	kfree(init.name);
173 	return PTR_ERR_OR_ZERO(clk);
174 }
175 
176 static struct clk *
177 krait_add_pri_mux(struct device *dev, int id, const char *s,
178 		  unsigned int offset)
179 {
180 	int ret;
181 	struct krait_mux_clk *mux;
182 	const char *p_names[3];
183 	struct clk_init_data init = {
184 		.parent_names = p_names,
185 		.num_parents = ARRAY_SIZE(p_names),
186 		.ops = &krait_mux_clk_ops,
187 		.flags = CLK_SET_RATE_PARENT,
188 	};
189 	struct clk *clk;
190 
191 	mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
192 	if (!mux)
193 		return ERR_PTR(-ENOMEM);
194 
195 	mux->mask = 0x3;
196 	mux->shift = 0;
197 	mux->offset = offset;
198 	mux->lpl = id >= 0;
199 	mux->parent_map = pri_mux_map;
200 	mux->hw.init = &init;
201 	mux->safe_sel = 2;
202 
203 	init.name = kasprintf(GFP_KERNEL, "krait%s_pri_mux", s);
204 	if (!init.name)
205 		return ERR_PTR(-ENOMEM);
206 
207 	p_names[0] = kasprintf(GFP_KERNEL, "hfpll%s", s);
208 	if (!p_names[0]) {
209 		clk = ERR_PTR(-ENOMEM);
210 		goto err_p0;
211 	}
212 
213 	p_names[1] = kasprintf(GFP_KERNEL, "hfpll%s_div", s);
214 	if (!p_names[1]) {
215 		clk = ERR_PTR(-ENOMEM);
216 		goto err_p1;
217 	}
218 
219 	p_names[2] = kasprintf(GFP_KERNEL, "krait%s_sec_mux", s);
220 	if (!p_names[2]) {
221 		clk = ERR_PTR(-ENOMEM);
222 		goto err_p2;
223 	}
224 
225 	clk = devm_clk_register(dev, &mux->hw);
226 
227 	ret = krait_notifier_register(dev, clk, mux);
228 	if (ret)
229 		goto err_p3;
230 err_p3:
231 	kfree(p_names[2]);
232 err_p2:
233 	kfree(p_names[1]);
234 err_p1:
235 	kfree(p_names[0]);
236 err_p0:
237 	kfree(init.name);
238 	return clk;
239 }
240 
241 /* id < 0 for L2, otherwise id == physical CPU number */
242 static struct clk *krait_add_clks(struct device *dev, int id, bool unique_aux)
243 {
244 	int ret;
245 	unsigned int offset;
246 	void *p = NULL;
247 	const char *s;
248 	struct clk *clk;
249 
250 	if (id >= 0) {
251 		offset = 0x4501 + (0x1000 * id);
252 		s = p = kasprintf(GFP_KERNEL, "%d", id);
253 		if (!s)
254 			return ERR_PTR(-ENOMEM);
255 	} else {
256 		offset = 0x500;
257 		s = "_l2";
258 	}
259 
260 	ret = krait_add_div(dev, id, s, offset);
261 	if (ret) {
262 		clk = ERR_PTR(ret);
263 		goto err;
264 	}
265 
266 	ret = krait_add_sec_mux(dev, id, s, offset, unique_aux);
267 	if (ret) {
268 		clk = ERR_PTR(ret);
269 		goto err;
270 	}
271 
272 	clk = krait_add_pri_mux(dev, id, s, offset);
273 err:
274 	kfree(p);
275 	return clk;
276 }
277 
278 static struct clk *krait_of_get(struct of_phandle_args *clkspec, void *data)
279 {
280 	unsigned int idx = clkspec->args[0];
281 	struct clk **clks = data;
282 
283 	if (idx >= 5) {
284 		pr_err("%s: invalid clock index %d\n", __func__, idx);
285 		return ERR_PTR(-EINVAL);
286 	}
287 
288 	return clks[idx] ? : ERR_PTR(-ENODEV);
289 }
290 
291 static const struct of_device_id krait_cc_match_table[] = {
292 	{ .compatible = "qcom,krait-cc-v1", (void *)1UL },
293 	{ .compatible = "qcom,krait-cc-v2" },
294 	{}
295 };
296 MODULE_DEVICE_TABLE(of, krait_cc_match_table);
297 
298 static int krait_cc_probe(struct platform_device *pdev)
299 {
300 	struct device *dev = &pdev->dev;
301 	const struct of_device_id *id;
302 	unsigned long cur_rate, aux_rate;
303 	int cpu;
304 	struct clk *clk;
305 	struct clk **clks;
306 	struct clk *l2_pri_mux_clk;
307 
308 	id = of_match_device(krait_cc_match_table, dev);
309 	if (!id)
310 		return -ENODEV;
311 
312 	/* Rate is 1 because 0 causes problems for __clk_mux_determine_rate */
313 	clk = clk_register_fixed_rate(dev, "qsb", NULL, 0, 1);
314 	if (IS_ERR(clk))
315 		return PTR_ERR(clk);
316 
317 	if (!id->data) {
318 		clk = clk_register_fixed_factor(dev, "acpu_aux",
319 						"gpll0_vote", 0, 1, 2);
320 		if (IS_ERR(clk))
321 			return PTR_ERR(clk);
322 	}
323 
324 	/* Krait configurations have at most 4 CPUs and one L2 */
325 	clks = devm_kcalloc(dev, 5, sizeof(*clks), GFP_KERNEL);
326 	if (!clks)
327 		return -ENOMEM;
328 
329 	for_each_possible_cpu(cpu) {
330 		clk = krait_add_clks(dev, cpu, id->data);
331 		if (IS_ERR(clk))
332 			return PTR_ERR(clk);
333 		clks[cpu] = clk;
334 	}
335 
336 	l2_pri_mux_clk = krait_add_clks(dev, -1, id->data);
337 	if (IS_ERR(l2_pri_mux_clk))
338 		return PTR_ERR(l2_pri_mux_clk);
339 	clks[4] = l2_pri_mux_clk;
340 
341 	/*
342 	 * We don't want the CPU or L2 clocks to be turned off at late init
343 	 * if CPUFREQ or HOTPLUG configs are disabled. So, bump up the
344 	 * refcount of these clocks. Any cpufreq/hotplug manager can assume
345 	 * that the clocks have already been prepared and enabled by the time
346 	 * they take over.
347 	 */
348 	for_each_online_cpu(cpu) {
349 		clk_prepare_enable(l2_pri_mux_clk);
350 		WARN(clk_prepare_enable(clks[cpu]),
351 		     "Unable to turn on CPU%d clock", cpu);
352 	}
353 
354 	/*
355 	 * Force reinit of HFPLLs and muxes to overwrite any potential
356 	 * incorrect configuration of HFPLLs and muxes by the bootloader.
357 	 * While at it, also make sure the cores are running at known rates
358 	 * and print the current rate.
359 	 *
360 	 * The clocks are set to aux clock rate first to make sure the
361 	 * secondary mux is not sourcing off of QSB. The rate is then set to
362 	 * two different rates to force a HFPLL reinit under all
363 	 * circumstances.
364 	 */
365 	cur_rate = clk_get_rate(l2_pri_mux_clk);
366 	aux_rate = 384000000;
367 	if (cur_rate == 1) {
368 		pr_info("L2 @ QSB rate. Forcing new rate.\n");
369 		cur_rate = aux_rate;
370 	}
371 	clk_set_rate(l2_pri_mux_clk, aux_rate);
372 	clk_set_rate(l2_pri_mux_clk, 2);
373 	clk_set_rate(l2_pri_mux_clk, cur_rate);
374 	pr_info("L2 @ %lu KHz\n", clk_get_rate(l2_pri_mux_clk) / 1000);
375 	for_each_possible_cpu(cpu) {
376 		clk = clks[cpu];
377 		cur_rate = clk_get_rate(clk);
378 		if (cur_rate == 1) {
379 			pr_info("CPU%d @ QSB rate. Forcing new rate.\n", cpu);
380 			cur_rate = aux_rate;
381 		}
382 
383 		clk_set_rate(clk, aux_rate);
384 		clk_set_rate(clk, 2);
385 		clk_set_rate(clk, cur_rate);
386 		pr_info("CPU%d @ %lu KHz\n", cpu, clk_get_rate(clk) / 1000);
387 	}
388 
389 	of_clk_add_provider(dev->of_node, krait_of_get, clks);
390 
391 	return 0;
392 }
393 
394 static struct platform_driver krait_cc_driver = {
395 	.probe = krait_cc_probe,
396 	.driver = {
397 		.name = "krait-cc",
398 		.of_match_table = krait_cc_match_table,
399 	},
400 };
401 module_platform_driver(krait_cc_driver);
402 
403 MODULE_DESCRIPTION("Krait CPU Clock Driver");
404 MODULE_LICENSE("GPL v2");
405 MODULE_ALIAS("platform:krait-cc");
406