cpufreq.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  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 <asm/system.h>
  34. #include <asm/hardware.h>
  35. #include "generic.h"
  36. #ifndef __val2mfld
  37. #define __val2mfld(mask,val) (((mask)&~((mask)<<1))*(val)&(mask))
  38. #endif
  39. #ifndef __mfld2val
  40. #define __mfld2val(mask,val) (((val)&(mask))/((mask)&~((mask)<<1)))
  41. #endif
  42. #define CR_920T_CLOCK_MODE 0xC0000000
  43. #define CR_920T_FASTBUS_MODE 0x00000000
  44. #define CR_920T_ASYNC_MODE 0xC0000000
  45. static u32 mpctl0_at_boot;
  46. static void imx_set_async_mode(void)
  47. {
  48. adjust_cr(CR_920T_CLOCK_MODE, CR_920T_ASYNC_MODE);
  49. }
  50. static void imx_set_fastbus_mode(void)
  51. {
  52. adjust_cr(CR_920T_CLOCK_MODE, CR_920T_FASTBUS_MODE);
  53. }
  54. static void imx_set_mpctl0(u32 mpctl0)
  55. {
  56. unsigned long flags;
  57. if (mpctl0 == 0) {
  58. local_irq_save(flags);
  59. CSCR &= ~CSCR_MPEN;
  60. local_irq_restore(flags);
  61. return;
  62. }
  63. local_irq_save(flags);
  64. MPCTL0 = mpctl0;
  65. CSCR |= CSCR_MPEN;
  66. local_irq_restore(flags);
  67. }
  68. /**
  69. * imx_compute_mpctl - compute new PLL parameters
  70. * @new_mpctl: pointer to location assigned by new PLL control register value
  71. * @cur_mpctl: current PLL control register parameters
  72. * @freq: required frequency in Hz
  73. * @relation: is one of %CPUFREQ_RELATION_L (supremum)
  74. * and %CPUFREQ_RELATION_H (infimum)
  75. */
  76. long imx_compute_mpctl(u32 *new_mpctl, u32 cur_mpctl, unsigned long freq, int relation)
  77. {
  78. u32 f_ref = (CSCR & CSCR_SYSTEM_SEL) ? 16000000 : (CLK32 * 512);
  79. u32 mfi;
  80. u32 mfn;
  81. u32 mfd;
  82. u32 pd;
  83. unsigned long long ll;
  84. long l;
  85. long quot;
  86. /* Fdppl=2*Fref*(MFI+MFN/(MFD+1))/(PD+1) */
  87. /* PD=<0,15>, MFD=<1,1023>, MFI=<5,15> MFN=<0,1022> */
  88. if (cur_mpctl) {
  89. mfd = ((cur_mpctl >> 16) & 0x3ff) + 1;
  90. pd = ((cur_mpctl >> 26) & 0xf) + 1;
  91. } else {
  92. pd=2; mfd=313;
  93. }
  94. /* pd=2; mfd=313; mfi=8; mfn=183; */
  95. /* (MFI+MFN/(MFD)) = Fdppl / (2*Fref) * (PD); */
  96. quot = (f_ref + (1 << 9)) >> 10;
  97. l = (freq * pd + quot) / (2 * quot);
  98. mfi = l >> 10;
  99. mfn = ((l & ((1 << 10) - 1)) * mfd + (1 << 9)) >> 10;
  100. mfd -= 1;
  101. pd -= 1;
  102. *new_mpctl = ((mfi & 0xf) << 10) | (mfn & 0x3ff) | ((mfd & 0x3ff) << 16)
  103. | ((pd & 0xf) << 26);
  104. ll = 2 * (unsigned long long)f_ref * ( (mfi<<16) + (mfn<<16) / (mfd+1) );
  105. quot = (pd+1) * (1<<16);
  106. ll += quot / 2;
  107. do_div(ll, quot);
  108. freq = ll;
  109. pr_debug(KERN_DEBUG "imx: new PLL parameters pd=%d mfd=%d mfi=%d mfn=%d, freq=%ld\n",
  110. pd, mfd, mfi, mfn, freq);
  111. return freq;
  112. }
  113. static int imx_verify_speed(struct cpufreq_policy *policy)
  114. {
  115. if (policy->cpu != 0)
  116. return -EINVAL;
  117. cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq);
  118. return 0;
  119. }
  120. static unsigned int imx_get_speed(unsigned int cpu)
  121. {
  122. unsigned int freq;
  123. unsigned int cr;
  124. unsigned int cscr;
  125. unsigned int bclk_div;
  126. if (cpu)
  127. return 0;
  128. cscr = CSCR;
  129. bclk_div = __mfld2val(CSCR_BCLK_DIV, cscr) + 1;
  130. cr = get_cr();
  131. if((cr & CR_920T_CLOCK_MODE) == CR_920T_FASTBUS_MODE) {
  132. freq = imx_get_system_clk();
  133. freq = (freq + bclk_div/2) / bclk_div;
  134. } else {
  135. freq = imx_get_mcu_clk();
  136. if (cscr & CSCR_MPU_PRESC)
  137. freq /= 2;
  138. }
  139. freq = (freq + 500) / 1000;
  140. return freq;
  141. }
  142. static int imx_set_target(struct cpufreq_policy *policy,
  143. unsigned int target_freq,
  144. unsigned int relation)
  145. {
  146. struct cpufreq_freqs freqs;
  147. u32 mpctl0 = 0;
  148. u32 cscr;
  149. unsigned long flags;
  150. long freq;
  151. long sysclk;
  152. unsigned int bclk_div = 1;
  153. /*
  154. * Some governors do not respects CPU and policy lower limits
  155. * which leads to bad things (division by zero etc), ensure
  156. * that such things do not happen.
  157. */
  158. if(target_freq < policy->cpuinfo.min_freq)
  159. target_freq = policy->cpuinfo.min_freq;
  160. if(target_freq < policy->min)
  161. target_freq = policy->min;
  162. freq = target_freq * 1000;
  163. pr_debug(KERN_DEBUG "imx: requested frequency %ld Hz, mpctl0 at boot 0x%08x\n",
  164. freq, mpctl0_at_boot);
  165. sysclk = imx_get_system_clk();
  166. if (freq > sysclk + 1000000) {
  167. freq = imx_compute_mpctl(&mpctl0, mpctl0_at_boot, freq, relation);
  168. if (freq < 0) {
  169. printk(KERN_WARNING "imx: target frequency %ld Hz cannot be set\n", freq);
  170. return -EINVAL;
  171. }
  172. } else {
  173. if(freq + 1000 < sysclk) {
  174. if (relation == CPUFREQ_RELATION_L)
  175. bclk_div = (sysclk - 1000) / freq;
  176. else
  177. bclk_div = (sysclk + freq + 1000) / freq;
  178. if(bclk_div > 16)
  179. bclk_div = 16;
  180. }
  181. freq = (sysclk + bclk_div / 2) / bclk_div;
  182. }
  183. freqs.old = imx_get_speed(0);
  184. freqs.new = (freq + 500) / 1000;
  185. freqs.cpu = 0;
  186. freqs.flags = 0;
  187. cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
  188. local_irq_save(flags);
  189. imx_set_fastbus_mode();
  190. imx_set_mpctl0(mpctl0);
  191. cscr = CSCR;
  192. cscr &= ~CSCR_BCLK_DIV;
  193. cscr |= __val2mfld(CSCR_BCLK_DIV, bclk_div - 1);
  194. CSCR = cscr;
  195. if(mpctl0) {
  196. CSCR |= CSCR_MPLL_RESTART;
  197. /* Wait until MPLL is stablized */
  198. while( CSCR & CSCR_MPLL_RESTART );
  199. imx_set_async_mode();
  200. }
  201. local_irq_restore(flags);
  202. cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
  203. pr_debug(KERN_INFO "imx: set frequency %ld Hz, running from %s\n",
  204. freq, mpctl0? "MPLL": "SPLL");
  205. return 0;
  206. }
  207. static int __init imx_cpufreq_driver_init(struct cpufreq_policy *policy)
  208. {
  209. printk(KERN_INFO "i.MX cpu freq change driver v1.0\n");
  210. if (policy->cpu != 0)
  211. return -EINVAL;
  212. policy->cur = policy->min = policy->max = imx_get_speed(0);
  213. policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
  214. policy->cpuinfo.min_freq = 8000;
  215. policy->cpuinfo.max_freq = 200000;
  216. /* Manual states, that PLL stabilizes in two CLK32 periods */
  217. policy->cpuinfo.transition_latency = 4 * 1000000000LL / CLK32;
  218. return 0;
  219. }
  220. static struct cpufreq_driver imx_driver = {
  221. .flags = CPUFREQ_STICKY,
  222. .verify = imx_verify_speed,
  223. .target = imx_set_target,
  224. .get = imx_get_speed,
  225. .init = imx_cpufreq_driver_init,
  226. .name = "imx",
  227. };
  228. static int __init imx_cpufreq_init(void)
  229. {
  230. mpctl0_at_boot = 0;
  231. if((CSCR & CSCR_MPEN) &&
  232. ((get_cr() & CR_920T_CLOCK_MODE) != CR_920T_FASTBUS_MODE))
  233. mpctl0_at_boot = MPCTL0;
  234. return cpufreq_register_driver(&imx_driver);
  235. }
  236. arch_initcall(imx_cpufreq_init);