speed.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /*
  2. *
  3. * (C) Copyright 2000-2003
  4. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  5. *
  6. * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
  7. * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
  8. *
  9. * See file CREDITS for list of people who contributed to this
  10. * project.
  11. *
  12. * This program is free software; you can redistribute it and/or
  13. * modify it under the terms of the GNU General Public License as
  14. * published by the Free Software Foundation; either version 2 of
  15. * the License, or (at your option) any later version.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with this program; if not, write to the Free Software
  24. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  25. * MA 02111-1307 USA
  26. */
  27. #include <common.h>
  28. #include <asm/processor.h>
  29. #include <asm/m5329.h>
  30. #include <asm/immap_5329.h>
  31. /* PLL min/max specifications */
  32. #define MAX_FVCO 500000 /* KHz */
  33. #define MAX_FSYS 80000 /* KHz */
  34. #define MIN_FSYS 58333 /* KHz */
  35. #define FREF 16000 /* KHz */
  36. #define MAX_MFD 135 /* Multiplier */
  37. #define MIN_MFD 88 /* Multiplier */
  38. #define BUSDIV 6 /* Divider */
  39. /*
  40. * Low Power Divider specifications
  41. */
  42. #define MIN_LPD (1 << 0) /* Divider (not encoded) */
  43. #define MAX_LPD (1 << 15) /* Divider (not encoded) */
  44. #define DEFAULT_LPD (1 << 1) /* Divider (not encoded) */
  45. /*
  46. * Get the value of the current system clock
  47. *
  48. * Parameters:
  49. * none
  50. *
  51. * Return Value:
  52. * The current output system frequency
  53. */
  54. int get_sys_clock(void)
  55. {
  56. volatile ccm_t *ccm = (volatile ccm_t *)(MMAP_CCM);
  57. volatile pll_t *pll = (volatile pll_t *)(MMAP_PLL);
  58. int divider;
  59. /* Test to see if device is in LIMP mode */
  60. if (ccm->misccr & CCM_MISCCR_LIMP) {
  61. divider = ccm->cdr & CCM_CDR_LPDIV(0xF);
  62. return (FREF / (2 << divider));
  63. } else {
  64. return ((FREF * pll->pfdr) / (BUSDIV * 4));
  65. }
  66. }
  67. /*
  68. * Initialize the Low Power Divider circuit
  69. *
  70. * Parameters:
  71. * div Desired system frequency divider
  72. *
  73. * Return Value:
  74. * The resulting output system frequency
  75. */
  76. int clock_limp(int div)
  77. {
  78. volatile ccm_t *ccm = (volatile ccm_t *)(MMAP_CCM);
  79. u32 temp;
  80. /* Check bounds of divider */
  81. if (div < MIN_LPD)
  82. div = MIN_LPD;
  83. if (div > MAX_LPD)
  84. div = MAX_LPD;
  85. /* Save of the current value of the SSIDIV so we don't overwrite the value */
  86. temp = (ccm->cdr & CCM_CDR_SSIDIV(0xF));
  87. /* Apply the divider to the system clock */
  88. ccm->cdr = (CCM_CDR_LPDIV(div) | CCM_CDR_SSIDIV(temp));
  89. ccm->misccr |= CCM_MISCCR_LIMP;
  90. return (FREF / (3 * (1 << div)));
  91. }
  92. /*
  93. * Exit low power LIMP mode
  94. *
  95. * Parameters:
  96. * div Desired system frequency divider
  97. *
  98. * Return Value:
  99. * The resulting output system frequency
  100. */
  101. int clock_exit_limp(void)
  102. {
  103. volatile ccm_t *ccm = (volatile ccm_t *)(MMAP_CCM);
  104. int fout;
  105. /* Exit LIMP mode */
  106. ccm->misccr &= (~CCM_MISCCR_LIMP);
  107. /* Wait for PLL to lock */
  108. while (!(ccm->misccr & CCM_MISCCR_PLL_LOCK)) ;
  109. fout = get_sys_clock();
  110. return fout;
  111. }
  112. /* Initialize the PLL
  113. *
  114. * Parameters:
  115. * fref PLL reference clock frequency in KHz
  116. * fsys Desired PLL output frequency in KHz
  117. * flags Operating parameters
  118. *
  119. * Return Value:
  120. * The resulting output system frequency
  121. */
  122. int clock_pll(int fsys, int flags)
  123. {
  124. volatile u32 *sdram_workaround = (volatile u32 *)(MMAP_SDRAM + 0x80);
  125. volatile pll_t *pll = (volatile pll_t *)(MMAP_PLL);
  126. int fref, temp, fout, mfd;
  127. u32 i;
  128. fref = FREF;
  129. if (fsys == 0) {
  130. /* Return current PLL output */
  131. mfd = pll->pfdr;
  132. return (fref * mfd / (BUSDIV * 4));
  133. }
  134. /* Check bounds of requested system clock */
  135. if (fsys > MAX_FSYS)
  136. fsys = MAX_FSYS;
  137. if (fsys < MIN_FSYS)
  138. fsys = MIN_FSYS;
  139. /* Multiplying by 100 when calculating the temp value,
  140. and then dividing by 100 to calculate the mfd allows
  141. for exact values without needing to include floating
  142. point libraries. */
  143. temp = (100 * fsys) / fref;
  144. mfd = (4 * BUSDIV * temp) / 100;
  145. /* Determine the output frequency for selected values */
  146. fout = ((fref * mfd) / (BUSDIV * 4));
  147. /*
  148. * Check to see if the SDRAM has already been initialized.
  149. * If it has then the SDRAM needs to be put into self refresh
  150. * mode before reprogramming the PLL.
  151. */
  152. /* Put SDRAM into self refresh mode */
  153. /* if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
  154. MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_CKE;*/
  155. /*
  156. * Initialize the PLL to generate the new system clock frequency.
  157. * The device must be put into LIMP mode to reprogram the PLL.
  158. */
  159. /* Enter LIMP mode */
  160. clock_limp(DEFAULT_LPD);
  161. /* Reprogram PLL for desired fsys */
  162. pll->podr = (PLL_PODR_CPUDIV(BUSDIV / 3) | PLL_PODR_BUSDIV(BUSDIV));
  163. pll->pfdr = mfd;
  164. /* Exit LIMP mode */
  165. clock_exit_limp();
  166. /*
  167. * Return the SDRAM to normal operation if it is in use.
  168. */
  169. /* Exit self refresh mode */
  170. /* if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
  171. MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_CKE;*/
  172. /* software workaround for SDRAM opeartion after exiting LIMP mode errata */
  173. *sdram_workaround = CFG_SDRAM_BASE;
  174. /* wait for DQS logic to relock */
  175. for (i = 0; i < 0x200; i++) ;
  176. return fout;
  177. }
  178. /*
  179. * get_clocks() fills in gd->cpu_clock and gd->bus_clk
  180. */
  181. int get_clocks(void)
  182. {
  183. DECLARE_GLOBAL_DATA_PTR;
  184. gd->bus_clk = clock_pll(CFG_CLK / 1000, 0) * 1000;
  185. gd->cpu_clk = (gd->bus_clk * 3);
  186. return (0);
  187. }