0171-clk-qcom-Add-Krait-clock-controller-driver.patch 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. From 6912e27d97ba5671e8c2434bed0ebd23fde5e13d Mon Sep 17 00:00:00 2001
  2. From: Stephen Boyd <[email protected]>
  3. Date: Wed, 18 Jun 2014 14:29:29 -0700
  4. Subject: [PATCH 171/182] clk: qcom: Add Krait clock controller driver
  5. The Krait CPU clocks are made up of a primary mux and secondary
  6. mux for each CPU and the L2, controlled via cp15 accessors. For
  7. Kraits within KPSSv1 each secondary mux accepts a different aux
  8. source, but on KPSSv2 each secondary mux accepts the same aux
  9. source.
  10. Signed-off-by: Stephen Boyd <[email protected]>
  11. ---
  12. drivers/clk/qcom/Kconfig | 8 +
  13. drivers/clk/qcom/Makefile | 1 +
  14. drivers/clk/qcom/krait-cc.c | 364 +++++++++++++++++++++++++++++++++++++++++++
  15. 3 files changed, 373 insertions(+)
  16. create mode 100644 drivers/clk/qcom/krait-cc.c
  17. --- a/drivers/clk/qcom/Kconfig
  18. +++ b/drivers/clk/qcom/Kconfig
  19. @@ -70,6 +70,14 @@ config KPSS_XCC
  20. if you want to support CPU frequency scaling on devices such
  21. as MSM8960, APQ8064, etc.
  22. +config KRAITCC
  23. + tristate "Krait Clock Controller"
  24. + depends on COMMON_CLK_QCOM && ARM
  25. + select KRAIT_CLOCKS
  26. + help
  27. + Support for the Krait CPU clocks on Qualcomm devices.
  28. + Say Y if you want to support CPU frequency scaling.
  29. +
  30. config KRAIT_CLOCKS
  31. bool
  32. select KRAIT_L2_ACCESSORS
  33. --- a/drivers/clk/qcom/Makefile
  34. +++ b/drivers/clk/qcom/Makefile
  35. @@ -19,3 +19,4 @@ obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8
  36. obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o
  37. obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o
  38. obj-$(CONFIG_QCOM_HFPLL) += hfpll.o
  39. +obj-$(CONFIG_KRAITCC) += krait-cc.o
  40. --- /dev/null
  41. +++ b/drivers/clk/qcom/krait-cc.c
  42. @@ -0,0 +1,364 @@
  43. +/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
  44. + *
  45. + * This program is free software; you can redistribute it and/or modify
  46. + * it under the terms of the GNU General Public License version 2 and
  47. + * only version 2 as published by the Free Software Foundation.
  48. + *
  49. + * This program is distributed in the hope that it will be useful,
  50. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  51. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  52. + * GNU General Public License for more details.
  53. + */
  54. +
  55. +#include <linux/kernel.h>
  56. +#include <linux/init.h>
  57. +#include <linux/module.h>
  58. +#include <linux/platform_device.h>
  59. +#include <linux/err.h>
  60. +#include <linux/io.h>
  61. +#include <linux/of.h>
  62. +#include <linux/of_device.h>
  63. +#include <linux/clk.h>
  64. +#include <linux/clk-provider.h>
  65. +#include <linux/slab.h>
  66. +
  67. +#include <asm/smp_plat.h>
  68. +
  69. +#include "clk-krait.h"
  70. +
  71. +DEFINE_FIXED_DIV_CLK(acpu_aux, 2, "gpll0_vote");
  72. +
  73. +static u8 sec_mux_map[] = {
  74. + 2,
  75. + 0,
  76. +};
  77. +
  78. +static u8 pri_mux_map[] = {
  79. + 1,
  80. + 2,
  81. + 0,
  82. +};
  83. +
  84. +static int
  85. +krait_add_div(struct device *dev, int id, const char *s, unsigned offset)
  86. +{
  87. + struct div_clk *div;
  88. + struct clk_init_data init = {
  89. + .num_parents = 1,
  90. + .ops = &clk_ops_div,
  91. + .flags = CLK_SET_RATE_PARENT,
  92. + };
  93. + const char *p_names[1];
  94. + struct clk *clk;
  95. +
  96. + div = devm_kzalloc(dev, sizeof(*dev), GFP_KERNEL);
  97. + if (!div)
  98. + return -ENOMEM;
  99. +
  100. + div->data.div = 2;
  101. + div->data.min_div = 2;
  102. + div->data.max_div = 2;
  103. + div->ops = &clk_div_ops_kpss_div2;
  104. + div->mask = 0x3;
  105. + div->shift = 6;
  106. + div->priv = (void *)(id >= 0);
  107. + div->offset = offset;
  108. + div->hw.init = &init;
  109. +
  110. + init.name = kasprintf(GFP_KERNEL, "hfpll%s_div", s);
  111. + if (!init.name)
  112. + return -ENOMEM;
  113. +
  114. + init.parent_names = p_names;
  115. + p_names[0] = kasprintf(GFP_KERNEL, "hfpll%s", s);
  116. + if (!p_names[0]) {
  117. + kfree(init.name);
  118. + return -ENOMEM;
  119. + }
  120. +
  121. + clk = devm_clk_register(dev, &div->hw);
  122. + kfree(p_names[0]);
  123. + kfree(init.name);
  124. +
  125. + return PTR_ERR_OR_ZERO(clk);
  126. +}
  127. +
  128. +static int
  129. +krait_add_sec_mux(struct device *dev, int id, const char *s, unsigned offset,
  130. + bool unique_aux)
  131. +{
  132. + struct mux_clk *mux;
  133. + static const char *sec_mux_list[] = {
  134. + "acpu_aux",
  135. + "qsb",
  136. + };
  137. + struct clk_init_data init = {
  138. + .parent_names = sec_mux_list,
  139. + .num_parents = ARRAY_SIZE(sec_mux_list),
  140. + .ops = &clk_ops_gen_mux,
  141. + .flags = CLK_SET_RATE_PARENT,
  142. + };
  143. + struct clk *clk;
  144. +
  145. + mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
  146. + if (!mux)
  147. + return -ENOMEM;
  148. +
  149. + mux->offset = offset;
  150. + mux->priv = (void *)(id >= 0);
  151. + mux->has_safe_parent = true;
  152. + mux->safe_sel = 2;
  153. + mux->ops = &clk_mux_ops_kpss;
  154. + mux->mask = 0x3;
  155. + mux->shift = 2;
  156. + mux->parent_map = sec_mux_map;
  157. + mux->hw.init = &init;
  158. +
  159. + init.name = kasprintf(GFP_KERNEL, "krait%s_sec_mux", s);
  160. + if (!init.name)
  161. + return -ENOMEM;
  162. +
  163. + if (unique_aux) {
  164. + sec_mux_list[0] = kasprintf(GFP_KERNEL, "acpu%s_aux", s);
  165. + if (!sec_mux_list[0]) {
  166. + clk = ERR_PTR(-ENOMEM);
  167. + goto err_aux;
  168. + }
  169. + }
  170. +
  171. + clk = devm_clk_register(dev, &mux->hw);
  172. +
  173. + if (unique_aux)
  174. + kfree(sec_mux_list[0]);
  175. +err_aux:
  176. + kfree(init.name);
  177. + return PTR_ERR_OR_ZERO(clk);
  178. +}
  179. +
  180. +static struct clk *
  181. +krait_add_pri_mux(struct device *dev, int id, const char * s, unsigned offset)
  182. +{
  183. + struct mux_clk *mux;
  184. + const char *p_names[3];
  185. + struct clk_init_data init = {
  186. + .parent_names = p_names,
  187. + .num_parents = ARRAY_SIZE(p_names),
  188. + .ops = &clk_ops_gen_mux,
  189. + .flags = CLK_SET_RATE_PARENT,
  190. + };
  191. + struct clk *clk;
  192. +
  193. + mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
  194. + if (!mux)
  195. + return ERR_PTR(-ENOMEM);
  196. +
  197. + mux->has_safe_parent = true;
  198. + mux->safe_sel = 0;
  199. + mux->ops = &clk_mux_ops_kpss;
  200. + mux->mask = 0x3;
  201. + mux->shift = 0;
  202. + mux->offset = offset;
  203. + mux->priv = (void *)(id >= 0);
  204. + mux->parent_map = pri_mux_map;
  205. + mux->hw.init = &init;
  206. +
  207. + init.name = kasprintf(GFP_KERNEL, "krait%s_pri_mux", s);
  208. + if (!init.name)
  209. + return ERR_PTR(-ENOMEM);
  210. +
  211. + p_names[0] = kasprintf(GFP_KERNEL, "hfpll%s", s);
  212. + if (!p_names[0]) {
  213. + clk = ERR_PTR(-ENOMEM);
  214. + goto err_p0;
  215. + }
  216. +
  217. + p_names[1] = kasprintf(GFP_KERNEL, "hfpll%s_div", s);
  218. + if (!p_names[1]) {
  219. + clk = ERR_PTR(-ENOMEM);
  220. + goto err_p1;
  221. + }
  222. +
  223. + p_names[2] = kasprintf(GFP_KERNEL, "krait%s_sec_mux", s);
  224. + if (!p_names[2]) {
  225. + clk = ERR_PTR(-ENOMEM);
  226. + goto err_p2;
  227. + }
  228. +
  229. + clk = devm_clk_register(dev, &mux->hw);
  230. +
  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 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 i, 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, &pdev->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, CLK_IS_ROOT, 1);
  314. + if (IS_ERR(clk))
  315. + return PTR_ERR(clk);
  316. +
  317. + if (!id->data) {
  318. + clk = devm_clk_register(dev, &acpu_aux.hw);
  319. + if (IS_ERR(clk))
  320. + return PTR_ERR(clk);
  321. + }
  322. +
  323. + /* Krait configurations have at most 4 CPUs and one L2 */
  324. + clks = devm_kcalloc(dev, 5, sizeof(*clks), GFP_KERNEL);
  325. + if (!clks)
  326. + return -ENOMEM;
  327. +
  328. + for_each_possible_cpu(i) {
  329. + cpu = cpu_logical_map(i);
  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(i) {
  349. + cpu = cpu_logical_map(i);
  350. + clk_prepare_enable(l2_pri_mux_clk);
  351. + WARN(clk_prepare_enable(clks[cpu]),
  352. + "Unable to turn on CPU%d clock", cpu);
  353. + }
  354. +
  355. + /*
  356. + * Force reinit of HFPLLs and muxes to overwrite any potential
  357. + * incorrect configuration of HFPLLs and muxes by the bootloader.
  358. + * While at it, also make sure the cores are running at known rates
  359. + * and print the current rate.
  360. + *
  361. + * The clocks are set to aux clock rate first to make sure the
  362. + * secondary mux is not sourcing off of QSB. The rate is then set to
  363. + * two different rates to force a HFPLL reinit under all
  364. + * circumstances.
  365. + */
  366. + cur_rate = clk_get_rate(l2_pri_mux_clk);
  367. + aux_rate = 384000000;
  368. + if (cur_rate == 1) {
  369. + pr_info("L2 @ QSB rate. Forcing new rate.\n");
  370. + cur_rate = aux_rate;
  371. + }
  372. + clk_set_rate(l2_pri_mux_clk, aux_rate);
  373. + clk_set_rate(l2_pri_mux_clk, 2);
  374. + clk_set_rate(l2_pri_mux_clk, cur_rate);
  375. + pr_info("L2 @ %lu KHz\n", clk_get_rate(l2_pri_mux_clk) / 1000);
  376. + for_each_possible_cpu(i) {
  377. + cpu = cpu_logical_map(i);
  378. + clk = clks[cpu];
  379. + cur_rate = clk_get_rate(clk);
  380. + if (cur_rate == 1) {
  381. + pr_info("CPU%d @ QSB rate. Forcing new rate.\n", i);
  382. + cur_rate = aux_rate;
  383. + }
  384. + clk_set_rate(clk, aux_rate);
  385. + clk_set_rate(clk, 2);
  386. + clk_set_rate(clk, cur_rate);
  387. + pr_info("CPU%d @ %lu KHz\n", i, clk_get_rate(clk) / 1000);
  388. + }
  389. +
  390. + of_clk_add_provider(dev->of_node, krait_of_get, clks);
  391. +
  392. + return 0;
  393. +}
  394. +
  395. +static struct platform_driver krait_cc_driver = {
  396. + .probe = krait_cc_probe,
  397. + .driver = {
  398. + .name = "clock-krait",
  399. + .of_match_table = krait_cc_match_table,
  400. + .owner = THIS_MODULE,
  401. + },
  402. +};
  403. +module_platform_driver(krait_cc_driver);
  404. +
  405. +MODULE_DESCRIPTION("Krait CPU Clock Driver");
  406. +MODULE_LICENSE("GPL v2");