ppc-corenet-cpufreq.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. /*
  2. * Copyright 2013 Freescale Semiconductor, Inc.
  3. *
  4. * CPU Frequency Scaling driver for Freescale PowerPC corenet SoCs.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. */
  10. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  11. #include <linux/clk.h>
  12. #include <linux/cpufreq.h>
  13. #include <linux/errno.h>
  14. #include <sysdev/fsl_soc.h>
  15. #include <linux/init.h>
  16. #include <linux/kernel.h>
  17. #include <linux/module.h>
  18. #include <linux/mutex.h>
  19. #include <linux/of.h>
  20. #include <linux/slab.h>
  21. #include <linux/smp.h>
  22. /**
  23. * struct cpu_data - per CPU data struct
  24. * @clk: the clk of CPU
  25. * @parent: the parent node of cpu clock
  26. * @table: frequency table
  27. */
  28. struct cpu_data {
  29. struct clk *clk;
  30. struct device_node *parent;
  31. struct cpufreq_frequency_table *table;
  32. };
  33. /**
  34. * struct soc_data - SoC specific data
  35. * @freq_mask: mask the disallowed frequencies
  36. * @flag: unique flags
  37. */
  38. struct soc_data {
  39. u32 freq_mask[4];
  40. u32 flag;
  41. };
  42. #define FREQ_MASK 1
  43. /* see hardware specification for the allowed frqeuencies */
  44. static const struct soc_data sdata[] = {
  45. { /* used by p2041 and p3041 */
  46. .freq_mask = {0x8, 0x8, 0x2, 0x2},
  47. .flag = FREQ_MASK,
  48. },
  49. { /* used by p5020 */
  50. .freq_mask = {0x8, 0x2},
  51. .flag = FREQ_MASK,
  52. },
  53. { /* used by p4080, p5040 */
  54. .freq_mask = {0},
  55. .flag = 0,
  56. },
  57. };
  58. /*
  59. * the minimum allowed core frequency, in Hz
  60. * for chassis v1.0, >= platform frequency
  61. * for chassis v2.0, >= platform frequency / 2
  62. */
  63. static u32 min_cpufreq;
  64. static const u32 *fmask;
  65. /* serialize frequency changes */
  66. static DEFINE_MUTEX(cpufreq_lock);
  67. static DEFINE_PER_CPU(struct cpu_data *, cpu_data);
  68. /* cpumask in a cluster */
  69. static DEFINE_PER_CPU(cpumask_var_t, cpu_mask);
  70. #ifndef CONFIG_SMP
  71. static inline const struct cpumask *cpu_core_mask(int cpu)
  72. {
  73. return cpumask_of(0);
  74. }
  75. #endif
  76. static unsigned int corenet_cpufreq_get_speed(unsigned int cpu)
  77. {
  78. struct cpu_data *data = per_cpu(cpu_data, cpu);
  79. return clk_get_rate(data->clk) / 1000;
  80. }
  81. /* reduce the duplicated frequencies in frequency table */
  82. static void freq_table_redup(struct cpufreq_frequency_table *freq_table,
  83. int count)
  84. {
  85. int i, j;
  86. for (i = 1; i < count; i++) {
  87. for (j = 0; j < i; j++) {
  88. if (freq_table[j].frequency == CPUFREQ_ENTRY_INVALID ||
  89. freq_table[j].frequency !=
  90. freq_table[i].frequency)
  91. continue;
  92. freq_table[i].frequency = CPUFREQ_ENTRY_INVALID;
  93. break;
  94. }
  95. }
  96. }
  97. /* sort the frequencies in frequency table in descenting order */
  98. static void freq_table_sort(struct cpufreq_frequency_table *freq_table,
  99. int count)
  100. {
  101. int i, j, ind;
  102. unsigned int freq, max_freq;
  103. struct cpufreq_frequency_table table;
  104. for (i = 0; i < count - 1; i++) {
  105. max_freq = freq_table[i].frequency;
  106. ind = i;
  107. for (j = i + 1; j < count; j++) {
  108. freq = freq_table[j].frequency;
  109. if (freq == CPUFREQ_ENTRY_INVALID ||
  110. freq <= max_freq)
  111. continue;
  112. ind = j;
  113. max_freq = freq;
  114. }
  115. if (ind != i) {
  116. /* exchange the frequencies */
  117. table.driver_data = freq_table[i].driver_data;
  118. table.frequency = freq_table[i].frequency;
  119. freq_table[i].driver_data = freq_table[ind].driver_data;
  120. freq_table[i].frequency = freq_table[ind].frequency;
  121. freq_table[ind].driver_data = table.driver_data;
  122. freq_table[ind].frequency = table.frequency;
  123. }
  124. }
  125. }
  126. static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy)
  127. {
  128. struct device_node *np;
  129. int i, count, ret;
  130. u32 freq, mask;
  131. struct clk *clk;
  132. struct cpufreq_frequency_table *table;
  133. struct cpu_data *data;
  134. unsigned int cpu = policy->cpu;
  135. np = of_get_cpu_node(cpu, NULL);
  136. if (!np)
  137. return -ENODEV;
  138. data = kzalloc(sizeof(*data), GFP_KERNEL);
  139. if (!data) {
  140. pr_err("%s: no memory\n", __func__);
  141. goto err_np;
  142. }
  143. data->clk = of_clk_get(np, 0);
  144. if (IS_ERR(data->clk)) {
  145. pr_err("%s: no clock information\n", __func__);
  146. goto err_nomem2;
  147. }
  148. data->parent = of_parse_phandle(np, "clocks", 0);
  149. if (!data->parent) {
  150. pr_err("%s: could not get clock information\n", __func__);
  151. goto err_nomem2;
  152. }
  153. count = of_property_count_strings(data->parent, "clock-names");
  154. table = kcalloc(count + 1, sizeof(*table), GFP_KERNEL);
  155. if (!table) {
  156. pr_err("%s: no memory\n", __func__);
  157. goto err_node;
  158. }
  159. if (fmask)
  160. mask = fmask[get_hard_smp_processor_id(cpu)];
  161. else
  162. mask = 0x0;
  163. for (i = 0; i < count; i++) {
  164. clk = of_clk_get(data->parent, i);
  165. freq = clk_get_rate(clk);
  166. /*
  167. * the clock is valid if its frequency is not masked
  168. * and large than minimum allowed frequency.
  169. */
  170. if (freq < min_cpufreq || (mask & (1 << i)))
  171. table[i].frequency = CPUFREQ_ENTRY_INVALID;
  172. else
  173. table[i].frequency = freq / 1000;
  174. table[i].driver_data = i;
  175. }
  176. freq_table_redup(table, count);
  177. freq_table_sort(table, count);
  178. table[i].frequency = CPUFREQ_TABLE_END;
  179. /* set the min and max frequency properly */
  180. ret = cpufreq_frequency_table_cpuinfo(policy, table);
  181. if (ret) {
  182. pr_err("invalid frequency table: %d\n", ret);
  183. goto err_nomem1;
  184. }
  185. data->table = table;
  186. per_cpu(cpu_data, cpu) = data;
  187. /* update ->cpus if we have cluster, no harm if not */
  188. cpumask_copy(policy->cpus, per_cpu(cpu_mask, cpu));
  189. for_each_cpu(i, per_cpu(cpu_mask, cpu))
  190. per_cpu(cpu_data, i) = data;
  191. policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
  192. policy->cur = corenet_cpufreq_get_speed(policy->cpu);
  193. cpufreq_frequency_table_get_attr(table, cpu);
  194. of_node_put(np);
  195. return 0;
  196. err_nomem1:
  197. kfree(table);
  198. err_node:
  199. of_node_put(data->parent);
  200. err_nomem2:
  201. per_cpu(cpu_data, cpu) = NULL;
  202. kfree(data);
  203. err_np:
  204. of_node_put(np);
  205. return -ENODEV;
  206. }
  207. static int __exit corenet_cpufreq_cpu_exit(struct cpufreq_policy *policy)
  208. {
  209. struct cpu_data *data = per_cpu(cpu_data, policy->cpu);
  210. unsigned int cpu;
  211. cpufreq_frequency_table_put_attr(policy->cpu);
  212. of_node_put(data->parent);
  213. kfree(data->table);
  214. kfree(data);
  215. for_each_cpu(cpu, per_cpu(cpu_mask, policy->cpu))
  216. per_cpu(cpu_data, cpu) = NULL;
  217. return 0;
  218. }
  219. static int corenet_cpufreq_verify(struct cpufreq_policy *policy)
  220. {
  221. struct cpufreq_frequency_table *table =
  222. per_cpu(cpu_data, policy->cpu)->table;
  223. return cpufreq_frequency_table_verify(policy, table);
  224. }
  225. static int corenet_cpufreq_target(struct cpufreq_policy *policy,
  226. unsigned int target_freq, unsigned int relation)
  227. {
  228. struct cpufreq_freqs freqs;
  229. unsigned int new;
  230. struct clk *parent;
  231. int ret;
  232. struct cpu_data *data = per_cpu(cpu_data, policy->cpu);
  233. cpufreq_frequency_table_target(policy, data->table,
  234. target_freq, relation, &new);
  235. if (policy->cur == data->table[new].frequency)
  236. return 0;
  237. freqs.old = policy->cur;
  238. freqs.new = data->table[new].frequency;
  239. mutex_lock(&cpufreq_lock);
  240. cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
  241. parent = of_clk_get(data->parent, data->table[new].driver_data);
  242. ret = clk_set_parent(data->clk, parent);
  243. if (ret)
  244. freqs.new = freqs.old;
  245. cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
  246. mutex_unlock(&cpufreq_lock);
  247. return ret;
  248. }
  249. static struct freq_attr *corenet_cpufreq_attr[] = {
  250. &cpufreq_freq_attr_scaling_available_freqs,
  251. NULL,
  252. };
  253. static struct cpufreq_driver ppc_corenet_cpufreq_driver = {
  254. .name = "ppc_cpufreq",
  255. .flags = CPUFREQ_CONST_LOOPS,
  256. .init = corenet_cpufreq_cpu_init,
  257. .exit = __exit_p(corenet_cpufreq_cpu_exit),
  258. .verify = corenet_cpufreq_verify,
  259. .target = corenet_cpufreq_target,
  260. .get = corenet_cpufreq_get_speed,
  261. .attr = corenet_cpufreq_attr,
  262. };
  263. static const struct of_device_id node_matches[] __initdata = {
  264. { .compatible = "fsl,p2041-clockgen", .data = &sdata[0], },
  265. { .compatible = "fsl,p3041-clockgen", .data = &sdata[0], },
  266. { .compatible = "fsl,p5020-clockgen", .data = &sdata[1], },
  267. { .compatible = "fsl,p4080-clockgen", .data = &sdata[2], },
  268. { .compatible = "fsl,p5040-clockgen", .data = &sdata[2], },
  269. { .compatible = "fsl,qoriq-clockgen-2.0", },
  270. {}
  271. };
  272. static int __init ppc_corenet_cpufreq_init(void)
  273. {
  274. int ret;
  275. struct device_node *np;
  276. const struct of_device_id *match;
  277. const struct soc_data *data;
  278. unsigned int cpu;
  279. np = of_find_matching_node(NULL, node_matches);
  280. if (!np)
  281. return -ENODEV;
  282. for_each_possible_cpu(cpu) {
  283. if (!alloc_cpumask_var(&per_cpu(cpu_mask, cpu), GFP_KERNEL))
  284. goto err_mask;
  285. cpumask_copy(per_cpu(cpu_mask, cpu), cpu_core_mask(cpu));
  286. }
  287. match = of_match_node(node_matches, np);
  288. data = match->data;
  289. if (data) {
  290. if (data->flag)
  291. fmask = data->freq_mask;
  292. min_cpufreq = fsl_get_sys_freq();
  293. } else {
  294. min_cpufreq = fsl_get_sys_freq() / 2;
  295. }
  296. of_node_put(np);
  297. ret = cpufreq_register_driver(&ppc_corenet_cpufreq_driver);
  298. if (!ret)
  299. pr_info("Freescale PowerPC corenet CPU frequency scaling driver\n");
  300. return ret;
  301. err_mask:
  302. for_each_possible_cpu(cpu)
  303. free_cpumask_var(per_cpu(cpu_mask, cpu));
  304. return -ENOMEM;
  305. }
  306. module_init(ppc_corenet_cpufreq_init);
  307. static void __exit ppc_corenet_cpufreq_exit(void)
  308. {
  309. unsigned int cpu;
  310. for_each_possible_cpu(cpu)
  311. free_cpumask_var(per_cpu(cpu_mask, cpu));
  312. cpufreq_unregister_driver(&ppc_corenet_cpufreq_driver);
  313. }
  314. module_exit(ppc_corenet_cpufreq_exit);
  315. MODULE_LICENSE("GPL");
  316. MODULE_AUTHOR("Tang Yuantian <Yuantian.Tang@freescale.com>");
  317. MODULE_DESCRIPTION("cpufreq driver for Freescale e500mc series SoCs");