1 From 7fb5976eb0231a06f484a6bde5e5fbfee7ee4f4a Mon Sep 17 00:00:00 2001
2 From: Stephen Boyd <sboyd@codeaurora.org>
3 Date: Fri, 20 Mar 2015 23:45:30 -0700
4 Subject: [PATCH 43/69] clk: qcom: Add Krait clock controller driver
6 The Krait CPU clocks are made up of a primary mux and secondary
7 mux for each CPU and the L2, controlled via cp15 accessors. For
8 Kraits within KPSSv1 each secondary mux accepts a different aux
9 source, but on KPSSv2 each secondary mux accepts the same aux
12 Cc: <devicetree@vger.kernel.org>
13 Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
15 .../devicetree/bindings/clock/qcom,krait-cc.txt | 22 ++
16 drivers/clk/qcom/Kconfig | 8 +
17 drivers/clk/qcom/Makefile | 1 +
18 drivers/clk/qcom/krait-cc.c | 352 +++++++++++++++++++++
19 4 files changed, 383 insertions(+)
20 create mode 100644 Documentation/devicetree/bindings/clock/qcom,krait-cc.txt
21 create mode 100644 drivers/clk/qcom/krait-cc.c
23 diff --git a/Documentation/devicetree/bindings/clock/qcom,krait-cc.txt b/Documentation/devicetree/bindings/clock/qcom,krait-cc.txt
25 index 000000000000..874138f88ec6
27 +++ b/Documentation/devicetree/bindings/clock/qcom,krait-cc.txt
29 +Krait Clock Controller
35 + Value type: <string>
36 + Definition: must be one of:
43 + Definition: must be 1
47 + kraitcc: clock-controller {
48 + compatible = "qcom,krait-cc-v1";
51 diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
52 index 747d979f6be7..0484ce46009d 100644
53 --- a/drivers/clk/qcom/Kconfig
54 +++ b/drivers/clk/qcom/Kconfig
55 @@ -196,6 +196,14 @@ config KPSS_XCC
56 if you want to support CPU frequency scaling on devices such
57 as MSM8960, APQ8064, etc.
60 + tristate "Krait Clock Controller"
61 + depends on COMMON_CLK_QCOM && ARM
64 + Support for the Krait CPU clocks on Qualcomm devices.
65 + Say Y if you want to support CPU frequency scaling.
69 select KRAIT_L2_ACCESSORS
70 diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
71 index f3d5ae4fc6cd..5fec2aeb2f55 100644
72 --- a/drivers/clk/qcom/Makefile
73 +++ b/drivers/clk/qcom/Makefile
74 @@ -35,3 +35,4 @@ obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o
75 obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
76 obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o
77 obj-$(CONFIG_QCOM_HFPLL) += hfpll.o
78 +obj-$(CONFIG_KRAITCC) += krait-cc.o
79 diff --git a/drivers/clk/qcom/krait-cc.c b/drivers/clk/qcom/krait-cc.c
81 index 000000000000..f55b5ecd0df8
83 +++ b/drivers/clk/qcom/krait-cc.c
85 +/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
87 + * This program is free software; you can redistribute it and/or modify
88 + * it under the terms of the GNU General Public License version 2 and
89 + * only version 2 as published by the Free Software Foundation.
91 + * This program is distributed in the hope that it will be useful,
92 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
93 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
94 + * GNU General Public License for more details.
97 +#include <linux/kernel.h>
98 +#include <linux/init.h>
99 +#include <linux/module.h>
100 +#include <linux/platform_device.h>
101 +#include <linux/err.h>
102 +#include <linux/io.h>
103 +#include <linux/of.h>
104 +#include <linux/of_device.h>
105 +#include <linux/clk.h>
106 +#include <linux/clk-provider.h>
107 +#include <linux/slab.h>
109 +#include "clk-krait.h"
111 +static unsigned int sec_mux_map[] = {
116 +static unsigned int pri_mux_map[] = {
123 +krait_add_div(struct device *dev, int id, const char *s, unsigned offset)
125 + struct krait_div2_clk *div;
126 + struct clk_init_data init = {
128 + .ops = &krait_div2_clk_ops,
129 + .flags = CLK_SET_RATE_PARENT,
131 + const char *p_names[1];
134 + div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL);
140 + div->lpl = id >= 0;
141 + div->offset = offset;
142 + div->hw.init = &init;
144 + init.name = kasprintf(GFP_KERNEL, "hfpll%s_div", s);
148 + init.parent_names = p_names;
149 + p_names[0] = kasprintf(GFP_KERNEL, "hfpll%s", s);
155 + clk = devm_clk_register(dev, &div->hw);
159 + return PTR_ERR_OR_ZERO(clk);
163 +krait_add_sec_mux(struct device *dev, int id, const char *s, unsigned offset,
166 + struct krait_mux_clk *mux;
167 + static const char *sec_mux_list[] = {
171 + struct clk_init_data init = {
172 + .parent_names = sec_mux_list,
173 + .num_parents = ARRAY_SIZE(sec_mux_list),
174 + .ops = &krait_mux_clk_ops,
175 + .flags = CLK_SET_RATE_PARENT,
179 + mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
183 + mux->offset = offset;
184 + mux->lpl = id >= 0;
185 + mux->has_safe_parent = true;
189 + mux->parent_map = sec_mux_map;
190 + mux->hw.init = &init;
192 + init.name = kasprintf(GFP_KERNEL, "krait%s_sec_mux", s);
197 + sec_mux_list[0] = kasprintf(GFP_KERNEL, "acpu%s_aux", s);
198 + if (!sec_mux_list[0]) {
199 + clk = ERR_PTR(-ENOMEM);
204 + clk = devm_clk_register(dev, &mux->hw);
207 + kfree(sec_mux_list[0]);
210 + return PTR_ERR_OR_ZERO(clk);
214 +krait_add_pri_mux(struct device *dev, int id, const char *s, unsigned offset)
216 + struct krait_mux_clk *mux;
217 + const char *p_names[3];
218 + struct clk_init_data init = {
219 + .parent_names = p_names,
220 + .num_parents = ARRAY_SIZE(p_names),
221 + .ops = &krait_mux_clk_ops,
222 + .flags = CLK_SET_RATE_PARENT,
226 + mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
228 + return ERR_PTR(-ENOMEM);
230 + mux->has_safe_parent = true;
234 + mux->offset = offset;
235 + mux->lpl = id >= 0;
236 + mux->parent_map = pri_mux_map;
237 + mux->hw.init = &init;
239 + init.name = kasprintf(GFP_KERNEL, "krait%s_pri_mux", s);
241 + return ERR_PTR(-ENOMEM);
243 + p_names[0] = kasprintf(GFP_KERNEL, "hfpll%s", s);
245 + clk = ERR_PTR(-ENOMEM);
249 + p_names[1] = kasprintf(GFP_KERNEL, "hfpll%s_div", s);
251 + clk = ERR_PTR(-ENOMEM);
255 + p_names[2] = kasprintf(GFP_KERNEL, "krait%s_sec_mux", s);
257 + clk = ERR_PTR(-ENOMEM);
261 + clk = devm_clk_register(dev, &mux->hw);
273 +/* id < 0 for L2, otherwise id == physical CPU number */
274 +static struct clk *krait_add_clks(struct device *dev, int id, bool unique_aux)
283 + offset = 0x4501 + (0x1000 * id);
284 + s = p = kasprintf(GFP_KERNEL, "%d", id);
286 + return ERR_PTR(-ENOMEM);
292 + ret = krait_add_div(dev, id, s, offset);
294 + clk = ERR_PTR(ret);
298 + ret = krait_add_sec_mux(dev, id, s, offset, unique_aux);
300 + clk = ERR_PTR(ret);
304 + clk = krait_add_pri_mux(dev, id, s, offset);
310 +static struct clk *krait_of_get(struct of_phandle_args *clkspec, void *data)
312 + unsigned int idx = clkspec->args[0];
313 + struct clk **clks = data;
316 + pr_err("%s: invalid clock index %d\n", __func__, idx);
317 + return ERR_PTR(-EINVAL);
320 + return clks[idx] ? : ERR_PTR(-ENODEV);
323 +static const struct of_device_id krait_cc_match_table[] = {
324 + { .compatible = "qcom,krait-cc-v1", (void *)1UL },
325 + { .compatible = "qcom,krait-cc-v2" },
328 +MODULE_DEVICE_TABLE(of, krait_cc_match_table);
330 +static int krait_cc_probe(struct platform_device *pdev)
332 + struct device *dev = &pdev->dev;
333 + const struct of_device_id *id;
334 + unsigned long cur_rate, aux_rate;
338 + struct clk *l2_pri_mux_clk;
340 + id = of_match_device(krait_cc_match_table, dev);
344 + /* Rate is 1 because 0 causes problems for __clk_mux_determine_rate */
345 + clk = clk_register_fixed_rate(dev, "qsb", NULL, CLK_IS_ROOT, 1);
347 + return PTR_ERR(clk);
350 + clk = clk_register_fixed_factor(dev, "acpu_aux",
351 + "gpll0_vote", 0, 1, 2);
353 + return PTR_ERR(clk);
356 + /* Krait configurations have at most 4 CPUs and one L2 */
357 + clks = devm_kcalloc(dev, 5, sizeof(*clks), GFP_KERNEL);
361 + for_each_possible_cpu(cpu) {
362 + clk = krait_add_clks(dev, cpu, id->data);
364 + return PTR_ERR(clk);
368 + l2_pri_mux_clk = krait_add_clks(dev, -1, id->data);
369 + if (IS_ERR(l2_pri_mux_clk))
370 + return PTR_ERR(l2_pri_mux_clk);
371 + clks[4] = l2_pri_mux_clk;
374 + * We don't want the CPU or L2 clocks to be turned off at late init
375 + * if CPUFREQ or HOTPLUG configs are disabled. So, bump up the
376 + * refcount of these clocks. Any cpufreq/hotplug manager can assume
377 + * that the clocks have already been prepared and enabled by the time
380 + for_each_online_cpu(cpu) {
381 + clk_prepare_enable(l2_pri_mux_clk);
382 + WARN(clk_prepare_enable(clks[cpu]),
383 + "Unable to turn on CPU%d clock", cpu);
387 + * Force reinit of HFPLLs and muxes to overwrite any potential
388 + * incorrect configuration of HFPLLs and muxes by the bootloader.
389 + * While at it, also make sure the cores are running at known rates
390 + * and print the current rate.
392 + * The clocks are set to aux clock rate first to make sure the
393 + * secondary mux is not sourcing off of QSB. The rate is then set to
394 + * two different rates to force a HFPLL reinit under all
397 + cur_rate = clk_get_rate(l2_pri_mux_clk);
398 + aux_rate = 384000000;
399 + if (cur_rate == 1) {
400 + pr_info("L2 @ QSB rate. Forcing new rate.\n");
401 + cur_rate = aux_rate;
403 + clk_set_rate(l2_pri_mux_clk, aux_rate);
404 + clk_set_rate(l2_pri_mux_clk, 2);
405 + clk_set_rate(l2_pri_mux_clk, cur_rate);
406 + pr_info("L2 @ %lu KHz\n", clk_get_rate(l2_pri_mux_clk) / 1000);
407 + for_each_possible_cpu(cpu) {
409 + cur_rate = clk_get_rate(clk);
410 + if (cur_rate == 1) {
411 + pr_info("CPU%d @ QSB rate. Forcing new rate.\n", cpu);
412 + cur_rate = aux_rate;
414 + clk_set_rate(clk, aux_rate);
415 + clk_set_rate(clk, 2);
416 + clk_set_rate(clk, cur_rate);
417 + pr_info("CPU%d @ %lu KHz\n", cpu, clk_get_rate(clk) / 1000);
420 + of_clk_add_provider(dev->of_node, krait_of_get, clks);
425 +static struct platform_driver krait_cc_driver = {
426 + .probe = krait_cc_probe,
428 + .name = "krait-cc",
429 + .of_match_table = krait_cc_match_table,
432 +module_platform_driver(krait_cc_driver);
434 +MODULE_DESCRIPTION("Krait CPU Clock Driver");
435 +MODULE_LICENSE("GPL v2");
436 +MODULE_ALIAS("platform:krait-cc");