cpufreq.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. /*
  2. * cpu.c: clock scaling for the iMX
  3. *
  4. * Copyright (C) 2000 2001, The Delft University of Technology
  5. * Copyright (c) 2004 Sascha Hauer <sascha@saschahauer.de>
  6. * Copyright (C) 2006 Inky Lung <ilung@cwlinux.com>
  7. * Copyright (C) 2006 Pavel Pisa, PiKRON <ppisa@pikron.com>
  8. *
  9. * Based on SA1100 version written by:
  10. * - Johan Pouwelse (J.A.Pouwelse@its.tudelft.nl): initial version
  11. * - Erik Mouw (J.A.K.Mouw@its.tudelft.nl):
  12. *
  13. * This program is free software; you can redistribute it and/or modify
  14. * it under the terms of the GNU General Public License as published by
  15. * the Free Software Foundation; either version 2 of the License, or
  16. * (at your option) any later version.
  17. *
  18. * This program is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU General Public License
  24. * along with this program; if not, write to the Free Software
  25. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  26. *
  27. */
  28. /*#define DEBUG*/
  29. #include <linux/kernel.h>
  30. #include <linux/types.h>
  31. #include <linux/init.h>
  32. #include <linux/cpufreq.h>
  33. #include <linux/clk.h>
  34. #include <linux/err.h>
  35. #include <asm/system.h>
  36. #include <mach/hardware.h>
  37. #include "generic.h"
  38. #ifndef __val2mfld
  39. #define __val2mfld(mask,val) (((mask)&~((mask)<<1))*(val)&(mask))
  40. #endif
  41. #ifndef __mfld2val
  42. #define __mfld2val(mask,val) (((val)&(mask))/((mask)&~((mask)<<1)))
  43. #endif
  44. #define CR_920T_CLOCK_MODE 0xC0000000
  45. #define CR_920T_FASTBUS_MODE 0x00000000
  46. #define CR_920T_ASYNC_MODE 0xC0000000
  47. static u32 mpctl0_at_boot;
  48. static u32 bclk_div_at_boot;
  49. static struct clk *system_clk, *mcu_clk;
  50. static void imx_set_async_mode(void)
  51. {
  52. adjust_cr(CR_920T_CLOCK_MODE, CR_920T_ASYNC_MODE);
  53. }
  54. static void imx_set_fastbus_mode(void)
  55. {
  56. adjust_cr(CR_920T_CLOCK_MODE, CR_920T_FASTBUS_MODE);
  57. }
  58. static void imx_set_mpctl0(u32 mpctl0)
  59. {
  60. unsigned long flags;
  61. if (mpctl0 == 0) {
  62. local_irq_save(flags);
  63. CSCR &= ~CSCR_MPEN;
  64. local_irq_restore(flags);
  65. return;
  66. }
  67. local_irq_save(flags);
  68. MPCTL0 = mpctl0;
  69. CSCR |= CSCR_MPEN;
  70. local_irq_restore(flags);
  71. }
  72. /**
  73. * imx_compute_mpctl - compute new PLL parameters
  74. * @new_mpctl: pointer to location assigned by new PLL control register value
  75. * @cur_mpctl: current PLL control register parameters
  76. * @f_ref: reference source frequency Hz
  77. * @freq: required frequency in Hz
  78. * @relation: is one of %CPUFREQ_RELATION_L (supremum)
  79. * and %CPUFREQ_RELATION_H (infimum)
  80. */
  81. long imx_compute_mpctl(u32 *new_mpctl, u32 cur_mpctl, u32 f_ref, unsigned long freq, int relation)
  82. {
  83. u32 mfi;
  84. u32 mfn;
  85. u32 mfd;
  86. u32 pd;
  87. unsigned long long ll;
  88. long l;
  89. long quot;
  90. /* Fdppl=2*Fref*(MFI+MFN/(MFD+1))/(PD+1) */
  91. /* PD=<0,15>, MFD=<1,1023>, MFI=<5,15> MFN=<0,1022> */
  92. if (cur_mpctl) {
  93. mfd = ((cur_mpctl >> 16) & 0x3ff) + 1;
  94. pd = ((cur_mpctl >> 26) & 0xf) + 1;
  95. } else {
  96. pd=2; mfd=313;
  97. }
  98. /* pd=2; mfd=313; mfi=8; mfn=183; */
  99. /* (MFI+MFN/(MFD)) = Fdppl / (2*Fref) * (PD); */
  100. quot = (f_ref + (1 << 9)) >> 10;
  101. l = (freq * pd + quot) / (2 * quot);
  102. mfi = l >> 10;
  103. mfn = ((l & ((1 << 10) - 1)) * mfd + (1 << 9)) >> 10;
  104. mfd -= 1;
  105. pd -= 1;
  106. *new_mpctl = ((mfi & 0xf) << 10) | (mfn & 0x3ff) | ((mfd & 0x3ff) << 16)
  107. | ((pd & 0xf) << 26);
  108. ll = 2 * (unsigned long long)f_ref * ( (mfi<<16) + (mfn<<16) / (mfd+1) );
  109. quot = (pd+1) * (1<<16);
  110. ll += quot / 2;
  111. do_div(ll, quot);
  112. freq = ll;
  113. pr_debug(KERN_DEBUG "imx: new PLL parameters pd=%d mfd=%d mfi=%d mfn=%d, freq=%ld\n",
  114. pd, mfd, mfi, mfn, freq);
  115. return freq;
  116. }
  117. static int imx_verify_speed(struct cpufreq_policy *policy)
  118. {
  119. if (policy->cpu != 0)
  120. return -EINVAL;
  121. cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq);
  122. return 0;
  123. }
  124. static unsigned int imx_get_speed(unsigned int cpu)
  125. {
  126. unsigned int freq;
  127. unsigned int cr;
  128. unsigned int cscr;
  129. unsigned int bclk_div;
  130. if (cpu)
  131. return 0;
  132. cscr = CSCR;
  133. bclk_div = __mfld2val(CSCR_BCLK_DIV, cscr) + 1;
  134. cr = get_cr();
  135. if((cr & CR_920T_CLOCK_MODE) == CR_920T_FASTBUS_MODE) {
  136. freq = clk_get_rate(system_clk);
  137. freq = (freq + bclk_div/2) / bclk_div;
  138. } else {
  139. freq = clk_get_rate(mcu_clk);
  140. if (cscr & CSCR_MPU_PRESC)
  141. freq /= 2;
  142. }
  143. freq = (freq + 500) / 1000;
  144. return freq;
  145. }
  146. static int imx_set_target(struct cpufreq_policy *policy,
  147. unsigned int target_freq,
  148. unsigned int relation)
  149. {
  150. struct cpufreq_freqs freqs;
  151. u32 mpctl0 = 0;
  152. u32 cscr;
  153. unsigned long flags;
  154. long freq;
  155. long sysclk;
  156. unsigned int bclk_div = bclk_div_at_boot;
  157. /*
  158. * Some governors do not respects CPU and policy lower limits
  159. * which leads to bad things (division by zero etc), ensure
  160. * that such things do not happen.
  161. */
  162. if(target_freq < policy->cpuinfo.min_freq)
  163. target_freq = policy->cpuinfo.min_freq;
  164. if(target_freq < policy->min)
  165. target_freq = policy->min;
  166. freq = target_freq * 1000;
  167. pr_debug(KERN_DEBUG "imx: requested frequency %ld Hz, mpctl0 at boot 0x%08x\n",
  168. freq, mpctl0_at_boot);
  169. sysclk = clk_get_rate(system_clk);
  170. if (freq > sysclk / bclk_div_at_boot + 1000000) {
  171. freq = imx_compute_mpctl(&mpctl0, mpctl0_at_boot, CLK32 * 512, freq, relation);
  172. if (freq < 0) {
  173. printk(KERN_WARNING "imx: target frequency %ld Hz cannot be set\n", freq);
  174. return -EINVAL;
  175. }
  176. } else {
  177. if(freq + 1000 < sysclk) {
  178. if (relation == CPUFREQ_RELATION_L)
  179. bclk_div = (sysclk - 1000) / freq;
  180. else
  181. bclk_div = (sysclk + freq + 1000) / freq;
  182. if(bclk_div > 16)
  183. bclk_div = 16;
  184. if(bclk_div < bclk_div_at_boot)
  185. bclk_div = bclk_div_at_boot;
  186. }
  187. freq = (sysclk + bclk_div / 2) / bclk_div;
  188. }
  189. freqs.old = imx_get_speed(0);
  190. freqs.new = (freq + 500) / 1000;
  191. freqs.cpu = 0;
  192. freqs.flags = 0;
  193. cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
  194. local_irq_save(flags);
  195. imx_set_fastbus_mode();
  196. imx_set_mpctl0(mpctl0);
  197. cscr = CSCR;
  198. cscr &= ~CSCR_BCLK_DIV;
  199. cscr |= __val2mfld(CSCR_BCLK_DIV, bclk_div - 1);
  200. CSCR = cscr;
  201. if(mpctl0) {
  202. CSCR |= CSCR_MPLL_RESTART;
  203. /* Wait until MPLL is stabilized */
  204. while( CSCR & CSCR_MPLL_RESTART );
  205. imx_set_async_mode();
  206. }
  207. local_irq_restore(flags);
  208. cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
  209. pr_debug(KERN_INFO "imx: set frequency %ld Hz, running from %s\n",
  210. freq, mpctl0? "MPLL": "SPLL");
  211. return 0;
  212. }
  213. static int __init imx_cpufreq_driver_init(struct cpufreq_policy *policy)
  214. {
  215. printk(KERN_INFO "i.MX cpu freq change driver v1.0\n");
  216. if (policy->cpu != 0)
  217. return -EINVAL;
  218. policy->cur = policy->min = policy->max = imx_get_speed(0);
  219. policy->cpuinfo.min_freq = 8000;
  220. policy->cpuinfo.max_freq = 200000;
  221. /* Manual states, that PLL stabilizes in two CLK32 periods */
  222. policy->cpuinfo.transition_latency = 4 * 1000000000LL / CLK32;
  223. return 0;
  224. }
  225. static struct cpufreq_driver imx_driver = {
  226. .flags = CPUFREQ_STICKY,
  227. .verify = imx_verify_speed,
  228. .target = imx_set_target,
  229. .get = imx_get_speed,
  230. .init = imx_cpufreq_driver_init,
  231. .name = "imx",
  232. };
  233. static int __init imx_cpufreq_init(void)
  234. {
  235. bclk_div_at_boot = __mfld2val(CSCR_BCLK_DIV, CSCR) + 1;
  236. mpctl0_at_boot = 0;
  237. system_clk = clk_get(NULL, "system_clk");
  238. if (IS_ERR(system_clk))
  239. return PTR_ERR(system_clk);
  240. mcu_clk = clk_get(NULL, "mcu_clk");
  241. if (IS_ERR(mcu_clk)) {
  242. clk_put(system_clk);
  243. return PTR_ERR(mcu_clk);
  244. }
  245. if((CSCR & CSCR_MPEN) &&
  246. ((get_cr() & CR_920T_CLOCK_MODE) != CR_920T_FASTBUS_MODE))
  247. mpctl0_at_boot = MPCTL0;
  248. return cpufreq_register_driver(&imx_driver);
  249. }
  250. arch_initcall(imx_cpufreq_init);