142-clk-qcom-Add-Krait-clock-controller-driver.patch 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. Content-Type: text/plain; charset="utf-8"
  2. MIME-Version: 1.0
  3. Content-Transfer-Encoding: 7bit
  4. Subject: [v3,11/13] clk: qcom: Add Krait clock controller driver
  5. From: Stephen Boyd <sboyd@codeaurora.org>
  6. X-Patchwork-Id: 6063121
  7. Message-Id: <1426920332-9340-12-git-send-email-sboyd@codeaurora.org>
  8. To: Mike Turquette <mturquette@linaro.org>, Stephen Boyd <sboyd@codeaurora.org>
  9. Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,
  10. linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
  11. Viresh Kumar <viresh.kumar@linaro.org>, <devicetree@vger.kernel.org>
  12. Date: Fri, 20 Mar 2015 23:45:30 -0700
  13. The Krait CPU clocks are made up of a primary mux and secondary
  14. mux for each CPU and the L2, controlled via cp15 accessors. For
  15. Kraits within KPSSv1 each secondary mux accepts a different aux
  16. source, but on KPSSv2 each secondary mux accepts the same aux
  17. source.
  18. Cc: <devicetree@vger.kernel.org>
  19. Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
  20. ---
  21. .../devicetree/bindings/clock/qcom,krait-cc.txt | 22 ++
  22. drivers/clk/qcom/Kconfig | 8 +
  23. drivers/clk/qcom/Makefile | 1 +
  24. drivers/clk/qcom/krait-cc.c | 352 +++++++++++++++++++++
  25. 4 files changed, 383 insertions(+)
  26. create mode 100644 Documentation/devicetree/bindings/clock/qcom,krait-cc.txt
  27. create mode 100644 drivers/clk/qcom/krait-cc.c
  28. --- /dev/null
  29. +++ b/Documentation/devicetree/bindings/clock/qcom,krait-cc.txt
  30. @@ -0,0 +1,22 @@
  31. +Krait Clock Controller
  32. +
  33. +PROPERTIES
  34. +
  35. +- compatible:
  36. + Usage: required
  37. + Value type: <string>
  38. + Definition: must be one of:
  39. + "qcom,krait-cc-v1"
  40. + "qcom,krait-cc-v2"
  41. +
  42. +- #clock-cells:
  43. + Usage: required
  44. + Value type: <u32>
  45. + Definition: must be 1
  46. +
  47. +Example:
  48. +
  49. + kraitcc: clock-controller {
  50. + compatible = "qcom,krait-cc-v1";
  51. + #clock-cells = <1>;
  52. + };
  53. --- a/drivers/clk/qcom/Kconfig
  54. +++ b/drivers/clk/qcom/Kconfig
  55. @@ -152,6 +152,14 @@ config KPSS_XCC
  56. if you want to support CPU frequency scaling on devices such
  57. as MSM8960, APQ8064, etc.
  58. +config KRAITCC
  59. + tristate "Krait Clock Controller"
  60. + depends on COMMON_CLK_QCOM && ARM
  61. + select KRAIT_CLOCKS
  62. + help
  63. + Support for the Krait CPU clocks on Qualcomm devices.
  64. + Say Y if you want to support CPU frequency scaling.
  65. +
  66. config KRAIT_CLOCKS
  67. bool
  68. select KRAIT_L2_ACCESSORS
  69. --- a/drivers/clk/qcom/Makefile
  70. +++ b/drivers/clk/qcom/Makefile
  71. @@ -28,3 +28,4 @@ obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8
  72. obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
  73. obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o
  74. obj-$(CONFIG_QCOM_HFPLL) += hfpll.o
  75. +obj-$(CONFIG_KRAITCC) += krait-cc.o
  76. --- /dev/null
  77. +++ b/drivers/clk/qcom/krait-cc.c
  78. @@ -0,0 +1,352 @@
  79. +/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
  80. + *
  81. + * This program is free software; you can redistribute it and/or modify
  82. + * it under the terms of the GNU General Public License version 2 and
  83. + * only version 2 as published by the Free Software Foundation.
  84. + *
  85. + * This program is distributed in the hope that it will be useful,
  86. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  87. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  88. + * GNU General Public License for more details.
  89. + */
  90. +
  91. +#include <linux/kernel.h>
  92. +#include <linux/init.h>
  93. +#include <linux/module.h>
  94. +#include <linux/platform_device.h>
  95. +#include <linux/err.h>
  96. +#include <linux/io.h>
  97. +#include <linux/of.h>
  98. +#include <linux/of_device.h>
  99. +#include <linux/clk.h>
  100. +#include <linux/clk-provider.h>
  101. +#include <linux/slab.h>
  102. +
  103. +#include "clk-krait.h"
  104. +
  105. +static unsigned int sec_mux_map[] = {
  106. + 2,
  107. + 0,
  108. +};
  109. +
  110. +static unsigned int pri_mux_map[] = {
  111. + 1,
  112. + 2,
  113. + 0,
  114. +};
  115. +
  116. +static int
  117. +krait_add_div(struct device *dev, int id, const char *s, unsigned offset)
  118. +{
  119. + struct krait_div2_clk *div;
  120. + struct clk_init_data init = {
  121. + .num_parents = 1,
  122. + .ops = &krait_div2_clk_ops,
  123. + .flags = CLK_SET_RATE_PARENT,
  124. + };
  125. + const char *p_names[1];
  126. + struct clk *clk;
  127. +
  128. + div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL);
  129. + if (!div)
  130. + return -ENOMEM;
  131. +
  132. + div->width = 2;
  133. + div->shift = 6;
  134. + div->lpl = id >= 0;
  135. + div->offset = offset;
  136. + div->hw.init = &init;
  137. +
  138. + init.name = kasprintf(GFP_KERNEL, "hfpll%s_div", s);
  139. + if (!init.name)
  140. + return -ENOMEM;
  141. +
  142. + init.parent_names = p_names;
  143. + p_names[0] = kasprintf(GFP_KERNEL, "hfpll%s", s);
  144. + if (!p_names[0]) {
  145. + kfree(init.name);
  146. + return -ENOMEM;
  147. + }
  148. +
  149. + clk = devm_clk_register(dev, &div->hw);
  150. + kfree(p_names[0]);
  151. + kfree(init.name);
  152. +
  153. + return PTR_ERR_OR_ZERO(clk);
  154. +}
  155. +
  156. +static int
  157. +krait_add_sec_mux(struct device *dev, int id, const char *s, unsigned offset,
  158. + bool unique_aux)
  159. +{
  160. + struct krait_mux_clk *mux;
  161. + static const char *sec_mux_list[] = {
  162. + "acpu_aux",
  163. + "qsb",
  164. + };
  165. + struct clk_init_data init = {
  166. + .parent_names = sec_mux_list,
  167. + .num_parents = ARRAY_SIZE(sec_mux_list),
  168. + .ops = &krait_mux_clk_ops,
  169. + .flags = CLK_SET_RATE_PARENT,
  170. + };
  171. + struct clk *clk;
  172. +
  173. + mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
  174. + if (!mux)
  175. + return -ENOMEM;
  176. +
  177. + mux->offset = offset;
  178. + mux->lpl = id >= 0;
  179. + mux->has_safe_parent = true;
  180. + mux->safe_sel = 2;
  181. + mux->mask = 0x3;
  182. + mux->shift = 2;
  183. + mux->parent_map = sec_mux_map;
  184. + mux->hw.init = &init;
  185. +
  186. + init.name = kasprintf(GFP_KERNEL, "krait%s_sec_mux", s);
  187. + if (!init.name)
  188. + return -ENOMEM;
  189. +
  190. + if (unique_aux) {
  191. + sec_mux_list[0] = kasprintf(GFP_KERNEL, "acpu%s_aux", s);
  192. + if (!sec_mux_list[0]) {
  193. + clk = ERR_PTR(-ENOMEM);
  194. + goto err_aux;
  195. + }
  196. + }
  197. +
  198. + clk = devm_clk_register(dev, &mux->hw);
  199. +
  200. + if (unique_aux)
  201. + kfree(sec_mux_list[0]);
  202. +err_aux:
  203. + kfree(init.name);
  204. + return PTR_ERR_OR_ZERO(clk);
  205. +}
  206. +
  207. +static struct clk *
  208. +krait_add_pri_mux(struct device *dev, int id, const char *s, unsigned offset)
  209. +{
  210. + struct krait_mux_clk *mux;
  211. + const char *p_names[3];
  212. + struct clk_init_data init = {
  213. + .parent_names = p_names,
  214. + .num_parents = ARRAY_SIZE(p_names),
  215. + .ops = &krait_mux_clk_ops,
  216. + .flags = CLK_SET_RATE_PARENT,
  217. + };
  218. + struct clk *clk;
  219. +
  220. + mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
  221. + if (!mux)
  222. + return ERR_PTR(-ENOMEM);
  223. +
  224. + mux->has_safe_parent = true;
  225. + mux->safe_sel = 0;
  226. + mux->mask = 0x3;
  227. + mux->shift = 0;
  228. + mux->offset = offset;
  229. + mux->lpl = id >= 0;
  230. + mux->parent_map = pri_mux_map;
  231. + mux->hw.init = &init;
  232. +
  233. + init.name = kasprintf(GFP_KERNEL, "krait%s_pri_mux", s);
  234. + if (!init.name)
  235. + return ERR_PTR(-ENOMEM);
  236. +
  237. + p_names[0] = kasprintf(GFP_KERNEL, "hfpll%s", s);
  238. + if (!p_names[0]) {
  239. + clk = ERR_PTR(-ENOMEM);
  240. + goto err_p0;
  241. + }
  242. +
  243. + p_names[1] = kasprintf(GFP_KERNEL, "hfpll%s_div", s);
  244. + if (!p_names[1]) {
  245. + clk = ERR_PTR(-ENOMEM);
  246. + goto err_p1;
  247. + }
  248. +
  249. + p_names[2] = kasprintf(GFP_KERNEL, "krait%s_sec_mux", s);
  250. + if (!p_names[2]) {
  251. + clk = ERR_PTR(-ENOMEM);
  252. + goto err_p2;
  253. + }
  254. +
  255. + clk = devm_clk_register(dev, &mux->hw);
  256. +
  257. + kfree(p_names[2]);
  258. +err_p2:
  259. + kfree(p_names[1]);
  260. +err_p1:
  261. + kfree(p_names[0]);
  262. +err_p0:
  263. + kfree(init.name);
  264. + return clk;
  265. +}
  266. +
  267. +/* id < 0 for L2, otherwise id == physical CPU number */
  268. +static struct clk *krait_add_clks(struct device *dev, int id, bool unique_aux)
  269. +{
  270. + int ret;
  271. + unsigned offset;
  272. + void *p = NULL;
  273. + const char *s;
  274. + struct clk *clk;
  275. +
  276. + if (id >= 0) {
  277. + offset = 0x4501 + (0x1000 * id);
  278. + s = p = kasprintf(GFP_KERNEL, "%d", id);
  279. + if (!s)
  280. + return ERR_PTR(-ENOMEM);
  281. + } else {
  282. + offset = 0x500;
  283. + s = "_l2";
  284. + }
  285. +
  286. + ret = krait_add_div(dev, id, s, offset);
  287. + if (ret) {
  288. + clk = ERR_PTR(ret);
  289. + goto err;
  290. + }
  291. +
  292. + ret = krait_add_sec_mux(dev, id, s, offset, unique_aux);
  293. + if (ret) {
  294. + clk = ERR_PTR(ret);
  295. + goto err;
  296. + }
  297. +
  298. + clk = krait_add_pri_mux(dev, id, s, offset);
  299. +err:
  300. + kfree(p);
  301. + return clk;
  302. +}
  303. +
  304. +static struct clk *krait_of_get(struct of_phandle_args *clkspec, void *data)
  305. +{
  306. + unsigned int idx = clkspec->args[0];
  307. + struct clk **clks = data;
  308. +
  309. + if (idx >= 5) {
  310. + pr_err("%s: invalid clock index %d\n", __func__, idx);
  311. + return ERR_PTR(-EINVAL);
  312. + }
  313. +
  314. + return clks[idx] ? : ERR_PTR(-ENODEV);
  315. +}
  316. +
  317. +static const struct of_device_id krait_cc_match_table[] = {
  318. + { .compatible = "qcom,krait-cc-v1", (void *)1UL },
  319. + { .compatible = "qcom,krait-cc-v2" },
  320. + {}
  321. +};
  322. +MODULE_DEVICE_TABLE(of, krait_cc_match_table);
  323. +
  324. +static int krait_cc_probe(struct platform_device *pdev)
  325. +{
  326. + struct device *dev = &pdev->dev;
  327. + const struct of_device_id *id;
  328. + unsigned long cur_rate, aux_rate;
  329. + int cpu;
  330. + struct clk *clk;
  331. + struct clk **clks;
  332. + struct clk *l2_pri_mux_clk;
  333. +
  334. + id = of_match_device(krait_cc_match_table, dev);
  335. + if (!id)
  336. + return -ENODEV;
  337. +
  338. + /* Rate is 1 because 0 causes problems for __clk_mux_determine_rate */
  339. + clk = clk_register_fixed_rate(dev, "qsb", NULL, CLK_IS_ROOT, 1);
  340. + if (IS_ERR(clk))
  341. + return PTR_ERR(clk);
  342. +
  343. + if (!id->data) {
  344. + clk = clk_register_fixed_factor(dev, "acpu_aux",
  345. + "gpll0_vote", 0, 1, 2);
  346. + if (IS_ERR(clk))
  347. + return PTR_ERR(clk);
  348. + }
  349. +
  350. + /* Krait configurations have at most 4 CPUs and one L2 */
  351. + clks = devm_kcalloc(dev, 5, sizeof(*clks), GFP_KERNEL);
  352. + if (!clks)
  353. + return -ENOMEM;
  354. +
  355. + for_each_possible_cpu(cpu) {
  356. + clk = krait_add_clks(dev, cpu, id->data);
  357. + if (IS_ERR(clk))
  358. + return PTR_ERR(clk);
  359. + clks[cpu] = clk;
  360. + }
  361. +
  362. + l2_pri_mux_clk = krait_add_clks(dev, -1, id->data);
  363. + if (IS_ERR(l2_pri_mux_clk))
  364. + return PTR_ERR(l2_pri_mux_clk);
  365. + clks[4] = l2_pri_mux_clk;
  366. +
  367. + /*
  368. + * We don't want the CPU or L2 clocks to be turned off at late init
  369. + * if CPUFREQ or HOTPLUG configs are disabled. So, bump up the
  370. + * refcount of these clocks. Any cpufreq/hotplug manager can assume
  371. + * that the clocks have already been prepared and enabled by the time
  372. + * they take over.
  373. + */
  374. + for_each_online_cpu(cpu) {
  375. + clk_prepare_enable(l2_pri_mux_clk);
  376. + WARN(clk_prepare_enable(clks[cpu]),
  377. + "Unable to turn on CPU%d clock", cpu);
  378. + }
  379. +
  380. + /*
  381. + * Force reinit of HFPLLs and muxes to overwrite any potential
  382. + * incorrect configuration of HFPLLs and muxes by the bootloader.
  383. + * While at it, also make sure the cores are running at known rates
  384. + * and print the current rate.
  385. + *
  386. + * The clocks are set to aux clock rate first to make sure the
  387. + * secondary mux is not sourcing off of QSB. The rate is then set to
  388. + * two different rates to force a HFPLL reinit under all
  389. + * circumstances.
  390. + */
  391. + cur_rate = clk_get_rate(l2_pri_mux_clk);
  392. + aux_rate = 384000000;
  393. + if (cur_rate == 1) {
  394. + pr_info("L2 @ QSB rate. Forcing new rate.\n");
  395. + cur_rate = aux_rate;
  396. + }
  397. + clk_set_rate(l2_pri_mux_clk, aux_rate);
  398. + clk_set_rate(l2_pri_mux_clk, 2);
  399. + clk_set_rate(l2_pri_mux_clk, cur_rate);
  400. + pr_info("L2 @ %lu KHz\n", clk_get_rate(l2_pri_mux_clk) / 1000);
  401. + for_each_possible_cpu(cpu) {
  402. + clk = clks[cpu];
  403. + cur_rate = clk_get_rate(clk);
  404. + if (cur_rate == 1) {
  405. + pr_info("CPU%d @ QSB rate. Forcing new rate.\n", cpu);
  406. + cur_rate = aux_rate;
  407. + }
  408. + clk_set_rate(clk, aux_rate);
  409. + clk_set_rate(clk, 2);
  410. + clk_set_rate(clk, cur_rate);
  411. + pr_info("CPU%d @ %lu KHz\n", cpu, clk_get_rate(clk) / 1000);
  412. + }
  413. +
  414. + of_clk_add_provider(dev->of_node, krait_of_get, clks);
  415. +
  416. + return 0;
  417. +}
  418. +
  419. +static struct platform_driver krait_cc_driver = {
  420. + .probe = krait_cc_probe,
  421. + .driver = {
  422. + .name = "krait-cc",
  423. + .of_match_table = krait_cc_match_table,
  424. + },
  425. +};
  426. +module_platform_driver(krait_cc_driver);
  427. +
  428. +MODULE_DESCRIPTION("Krait CPU Clock Driver");
  429. +MODULE_LICENSE("GPL v2");
  430. +MODULE_ALIAS("platform:krait-cc");