chipcHw_init.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /*****************************************************************************
  2. * Copyright 2003 - 2008 Broadcom Corporation. All rights reserved.
  3. *
  4. * Unless you and Broadcom execute a separate written software license
  5. * agreement governing use of this software, this software is licensed to you
  6. * under the terms of the GNU General Public License version 2, available at
  7. * http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
  8. *
  9. * Notwithstanding the above, under no circumstances may you combine this
  10. * software in any way with any other Broadcom software provided under a
  11. * license other than the GPL, without Broadcom's express prior written
  12. * consent.
  13. *****************************************************************************/
  14. /****************************************************************************/
  15. /**
  16. * @file chipcHw_init.c
  17. *
  18. * @brief Low level CHIPC PLL configuration functions
  19. *
  20. * @note
  21. *
  22. * These routines provide basic PLL controlling functionality only.
  23. */
  24. /****************************************************************************/
  25. /* ---- Include Files ---------------------------------------------------- */
  26. #include <csp/errno.h>
  27. #include <csp/stdint.h>
  28. #include <csp/module.h>
  29. #include <mach/csp/chipcHw_def.h>
  30. #include <mach/csp/chipcHw_inline.h>
  31. #include <csp/reg.h>
  32. #include <csp/delay.h>
  33. /* ---- Private Constants and Types --------------------------------------- */
  34. /*
  35. Calculation for NDIV_i to obtain VCO frequency
  36. -----------------------------------------------
  37. Freq_vco = Freq_ref * (P2 / P1) * (PLL_NDIV_i + PLL_NDIV_f)
  38. for Freq_vco = VCO_FREQ_MHz
  39. Freq_ref = chipcHw_XTAL_FREQ_Hz
  40. PLL_P1 = PLL_P2 = 1
  41. and
  42. PLL_NDIV_f = 0
  43. We get:
  44. PLL_NDIV_i = Freq_vco / Freq_ref = VCO_FREQ_MHz / chipcHw_XTAL_FREQ_Hz
  45. Calculation for PLL MDIV to obtain frequency Freq_x for channel x
  46. -----------------------------------------------------------------
  47. Freq_x = chipcHw_XTAL_FREQ_Hz * PLL_NDIV_i / PLL_MDIV_x = VCO_FREQ_MHz / PLL_MDIV_x
  48. PLL_MDIV_x = VCO_FREQ_MHz / Freq_x
  49. */
  50. /* ---- Private Variables ------------------------------------------------- */
  51. /****************************************************************************/
  52. /**
  53. * @brief Initializes the PLL2
  54. *
  55. * This function initializes the PLL2
  56. *
  57. */
  58. /****************************************************************************/
  59. void chipcHw_pll2Enable(uint32_t vcoFreqHz)
  60. {
  61. uint32_t pllPreDivider2 = 0;
  62. {
  63. REG_LOCAL_IRQ_SAVE;
  64. pChipcHw->PLLConfig2 =
  65. chipcHw_REG_PLL_CONFIG_D_RESET |
  66. chipcHw_REG_PLL_CONFIG_A_RESET;
  67. pllPreDivider2 = chipcHw_REG_PLL_PREDIVIDER_POWER_DOWN |
  68. chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_INTEGER |
  69. (chipcHw_REG_PLL_PREDIVIDER_NDIV_i(vcoFreqHz) <<
  70. chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT) |
  71. (chipcHw_REG_PLL_PREDIVIDER_P1 <<
  72. chipcHw_REG_PLL_PREDIVIDER_P1_SHIFT) |
  73. (chipcHw_REG_PLL_PREDIVIDER_P2 <<
  74. chipcHw_REG_PLL_PREDIVIDER_P2_SHIFT);
  75. /* Enable CHIPC registers to control the PLL */
  76. pChipcHw->PLLStatus |= chipcHw_REG_PLL_STATUS_CONTROL_ENABLE;
  77. /* Set pre divider to get desired VCO frequency */
  78. pChipcHw->PLLPreDivider2 = pllPreDivider2;
  79. /* Set NDIV Frac */
  80. pChipcHw->PLLDivider2 = chipcHw_REG_PLL_DIVIDER_NDIV_f;
  81. /* This has to be removed once the default values are fixed for PLL2. */
  82. pChipcHw->PLLControl12 = 0x38000700;
  83. pChipcHw->PLLControl22 = 0x00000015;
  84. /* Reset PLL2 */
  85. if (vcoFreqHz > chipcHw_REG_PLL_CONFIG_VCO_SPLIT_FREQ) {
  86. pChipcHw->PLLConfig2 = chipcHw_REG_PLL_CONFIG_D_RESET |
  87. chipcHw_REG_PLL_CONFIG_A_RESET |
  88. chipcHw_REG_PLL_CONFIG_VCO_1601_3200 |
  89. chipcHw_REG_PLL_CONFIG_POWER_DOWN;
  90. } else {
  91. pChipcHw->PLLConfig2 = chipcHw_REG_PLL_CONFIG_D_RESET |
  92. chipcHw_REG_PLL_CONFIG_A_RESET |
  93. chipcHw_REG_PLL_CONFIG_VCO_800_1600 |
  94. chipcHw_REG_PLL_CONFIG_POWER_DOWN;
  95. }
  96. REG_LOCAL_IRQ_RESTORE;
  97. }
  98. /* Insert certain amount of delay before deasserting ARESET. */
  99. udelay(1);
  100. {
  101. REG_LOCAL_IRQ_SAVE;
  102. /* Remove analog reset and Power on the PLL */
  103. pChipcHw->PLLConfig2 &=
  104. ~(chipcHw_REG_PLL_CONFIG_A_RESET |
  105. chipcHw_REG_PLL_CONFIG_POWER_DOWN);
  106. REG_LOCAL_IRQ_RESTORE;
  107. }
  108. /* Wait until PLL is locked */
  109. while (!(pChipcHw->PLLStatus2 & chipcHw_REG_PLL_STATUS_LOCKED))
  110. ;
  111. {
  112. REG_LOCAL_IRQ_SAVE;
  113. /* Remove digital reset */
  114. pChipcHw->PLLConfig2 &= ~chipcHw_REG_PLL_CONFIG_D_RESET;
  115. REG_LOCAL_IRQ_RESTORE;
  116. }
  117. }
  118. EXPORT_SYMBOL(chipcHw_pll2Enable);
  119. /****************************************************************************/
  120. /**
  121. * @brief Initializes the PLL1
  122. *
  123. * This function initializes the PLL1
  124. *
  125. */
  126. /****************************************************************************/
  127. void chipcHw_pll1Enable(uint32_t vcoFreqHz, chipcHw_SPREAD_SPECTRUM_e ssSupport)
  128. {
  129. uint32_t pllPreDivider = 0;
  130. {
  131. REG_LOCAL_IRQ_SAVE;
  132. pChipcHw->PLLConfig =
  133. chipcHw_REG_PLL_CONFIG_D_RESET |
  134. chipcHw_REG_PLL_CONFIG_A_RESET;
  135. /* Setting VCO frequency */
  136. if (ssSupport == chipcHw_SPREAD_SPECTRUM_ALLOW) {
  137. pllPreDivider =
  138. chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_MASH_1_8 |
  139. ((chipcHw_REG_PLL_PREDIVIDER_NDIV_i(vcoFreqHz) -
  140. 1) << chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT) |
  141. (chipcHw_REG_PLL_PREDIVIDER_P1 <<
  142. chipcHw_REG_PLL_PREDIVIDER_P1_SHIFT) |
  143. (chipcHw_REG_PLL_PREDIVIDER_P2 <<
  144. chipcHw_REG_PLL_PREDIVIDER_P2_SHIFT);
  145. } else {
  146. pllPreDivider = chipcHw_REG_PLL_PREDIVIDER_POWER_DOWN |
  147. chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_INTEGER |
  148. (chipcHw_REG_PLL_PREDIVIDER_NDIV_i(vcoFreqHz) <<
  149. chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT) |
  150. (chipcHw_REG_PLL_PREDIVIDER_P1 <<
  151. chipcHw_REG_PLL_PREDIVIDER_P1_SHIFT) |
  152. (chipcHw_REG_PLL_PREDIVIDER_P2 <<
  153. chipcHw_REG_PLL_PREDIVIDER_P2_SHIFT);
  154. }
  155. /* Enable CHIPC registers to control the PLL */
  156. pChipcHw->PLLStatus |= chipcHw_REG_PLL_STATUS_CONTROL_ENABLE;
  157. /* Set pre divider to get desired VCO frequency */
  158. pChipcHw->PLLPreDivider = pllPreDivider;
  159. /* Set NDIV Frac */
  160. if (ssSupport == chipcHw_SPREAD_SPECTRUM_ALLOW) {
  161. pChipcHw->PLLDivider = chipcHw_REG_PLL_DIVIDER_M1DIV |
  162. chipcHw_REG_PLL_DIVIDER_NDIV_f_SS;
  163. } else {
  164. pChipcHw->PLLDivider = chipcHw_REG_PLL_DIVIDER_M1DIV |
  165. chipcHw_REG_PLL_DIVIDER_NDIV_f;
  166. }
  167. /* Reset PLL1 */
  168. if (vcoFreqHz > chipcHw_REG_PLL_CONFIG_VCO_SPLIT_FREQ) {
  169. pChipcHw->PLLConfig = chipcHw_REG_PLL_CONFIG_D_RESET |
  170. chipcHw_REG_PLL_CONFIG_A_RESET |
  171. chipcHw_REG_PLL_CONFIG_VCO_1601_3200 |
  172. chipcHw_REG_PLL_CONFIG_POWER_DOWN;
  173. } else {
  174. pChipcHw->PLLConfig = chipcHw_REG_PLL_CONFIG_D_RESET |
  175. chipcHw_REG_PLL_CONFIG_A_RESET |
  176. chipcHw_REG_PLL_CONFIG_VCO_800_1600 |
  177. chipcHw_REG_PLL_CONFIG_POWER_DOWN;
  178. }
  179. REG_LOCAL_IRQ_RESTORE;
  180. /* Insert certain amount of delay before deasserting ARESET. */
  181. udelay(1);
  182. {
  183. REG_LOCAL_IRQ_SAVE;
  184. /* Remove analog reset and Power on the PLL */
  185. pChipcHw->PLLConfig &=
  186. ~(chipcHw_REG_PLL_CONFIG_A_RESET |
  187. chipcHw_REG_PLL_CONFIG_POWER_DOWN);
  188. REG_LOCAL_IRQ_RESTORE;
  189. }
  190. /* Wait until PLL is locked */
  191. while (!(pChipcHw->PLLStatus & chipcHw_REG_PLL_STATUS_LOCKED)
  192. || !(pChipcHw->
  193. PLLStatus2 & chipcHw_REG_PLL_STATUS_LOCKED))
  194. ;
  195. /* Remove digital reset */
  196. {
  197. REG_LOCAL_IRQ_SAVE;
  198. pChipcHw->PLLConfig &= ~chipcHw_REG_PLL_CONFIG_D_RESET;
  199. REG_LOCAL_IRQ_RESTORE;
  200. }
  201. }
  202. }
  203. EXPORT_SYMBOL(chipcHw_pll1Enable);
  204. /****************************************************************************/
  205. /**
  206. * @brief Initializes the chipc module
  207. *
  208. * This function initializes the PLLs and core system clocks
  209. *
  210. */
  211. /****************************************************************************/
  212. void chipcHw_Init(chipcHw_INIT_PARAM_t *initParam /* [ IN ] Misc chip initialization parameter */
  213. ) {
  214. #if !(defined(__KERNEL__) && !defined(STANDALONE))
  215. delay_init();
  216. #endif
  217. /* Do not program PLL, when warm reset */
  218. if (!(chipcHw_getStickyBits() & chipcHw_REG_STICKY_CHIP_WARM_RESET)) {
  219. chipcHw_pll1Enable(initParam->pllVcoFreqHz,
  220. initParam->ssSupport);
  221. chipcHw_pll2Enable(initParam->pll2VcoFreqHz);
  222. } else {
  223. /* Clear sticky bits */
  224. chipcHw_clearStickyBits(chipcHw_REG_STICKY_CHIP_WARM_RESET);
  225. }
  226. /* Clear sticky bits */
  227. chipcHw_clearStickyBits(chipcHw_REG_STICKY_CHIP_SOFT_RESET);
  228. /* Before configuring the ARM clock, atleast we need to make sure BUS clock maintains the proper ratio with ARM clock */
  229. pChipcHw->ACLKClock =
  230. (pChipcHw->
  231. ACLKClock & ~chipcHw_REG_ACLKClock_CLK_DIV_MASK) | (initParam->
  232. armBusRatio &
  233. chipcHw_REG_ACLKClock_CLK_DIV_MASK);
  234. /* Set various core component frequencies. The order in which this is done is important for some. */
  235. /* The RTBUS (DDR PHY) is derived from the BUS, and the BUS from the ARM, and VPM needs to know BUS */
  236. /* frequency to find its ratio with the BUS. Hence we must set the ARM first, followed by the BUS, */
  237. /* then VPM and RTBUS. */
  238. chipcHw_setClockFrequency(chipcHw_CLOCK_ARM,
  239. initParam->busClockFreqHz *
  240. initParam->armBusRatio);
  241. chipcHw_setClockFrequency(chipcHw_CLOCK_BUS, initParam->busClockFreqHz);
  242. chipcHw_setClockFrequency(chipcHw_CLOCK_VPM,
  243. initParam->busClockFreqHz *
  244. initParam->vpmBusRatio);
  245. chipcHw_setClockFrequency(chipcHw_CLOCK_DDR,
  246. initParam->busClockFreqHz *
  247. initParam->ddrBusRatio);
  248. chipcHw_setClockFrequency(chipcHw_CLOCK_RTBUS,
  249. initParam->busClockFreqHz / 2);
  250. }