clock.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997
  1. /*++
  2. Copyright (c) 2014 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. clock.c
  5. Abstract:
  6. This module implements clock management for the TI AM335x first stage
  7. loader.
  8. Author:
  9. Evan Green 18-Dec-2014
  10. Environment:
  11. Firmware
  12. --*/
  13. //
  14. // ------------------------------------------------------------------- Includes
  15. //
  16. #include <uefifw.h>
  17. #include "init.h"
  18. //
  19. // ---------------------------------------------------------------- Definitions
  20. //
  21. //
  22. // ------------------------------------------------------ Data Type Definitions
  23. //
  24. //
  25. // ----------------------------------------------- Internal Function Prototypes
  26. //
  27. VOID
  28. EfipAm335InitializeMpuPll (
  29. UINTN Multiplier
  30. );
  31. VOID
  32. EfipAm335InitializeCorePll (
  33. VOID
  34. );
  35. VOID
  36. EfipAm335InitializePerPll (
  37. VOID
  38. );
  39. VOID
  40. EfipAm335InitializeDdrPll (
  41. UINTN Multiplier
  42. );
  43. VOID
  44. EfipAm335InitializeDisplayPll (
  45. VOID
  46. );
  47. VOID
  48. EfipAm335InitializeInterfaceClocks (
  49. VOID
  50. );
  51. VOID
  52. EfipAm335InitializePowerDomainTransition (
  53. VOID
  54. );
  55. //
  56. // -------------------------------------------------------------------- Globals
  57. //
  58. //
  59. // ------------------------------------------------------------------ Functions
  60. //
  61. VOID
  62. EfipAm335InitializeClocks (
  63. VOID
  64. )
  65. /*++
  66. Routine Description:
  67. This routine initializes functional clocks for needed modules and domains.
  68. Arguments:
  69. None.
  70. Return Value:
  71. None.
  72. --*/
  73. {
  74. UINT32 Value;
  75. //
  76. // Enable the L3 clock.
  77. //
  78. Value = AM3_CM_PER_READ(AM335_CM_PER_L3_CLOCK_CONTROL);
  79. Value |= AM335_CM_PER_L3_CLOCK_ENABLE;
  80. AM3_CM_PER_WRITE(AM335_CM_PER_L3_CLOCK_CONTROL, Value);
  81. do {
  82. Value = AM3_CM_PER_READ(AM335_CM_PER_L3_CLOCK_CONTROL);
  83. } while ((Value & AM335_CM_PER_L3_CLOCK_MODE_MASK) !=
  84. AM335_CM_PER_L3_CLOCK_ENABLE);
  85. //
  86. // Enable the L3 instr clock.
  87. //
  88. Value = AM3_CM_PER_READ(AM335_CM_PER_L3_INSTR_CLOCK_CONTROL);
  89. Value |= AM335_CM_PER_L3_INSTR_CLOCK_ENABLE;
  90. AM3_CM_PER_WRITE(AM335_CM_PER_L3_INSTR_CLOCK_CONTROL, Value);
  91. do {
  92. Value = AM3_CM_PER_READ(AM335_CM_PER_L3_INSTR_CLOCK_CONTROL);
  93. } while ((Value & AM335_CM_PER_L3_INSTR_CLOCK_MODE_MASK) !=
  94. AM335_CM_PER_L3_INSTR_CLOCK_ENABLE);
  95. //
  96. // Force a software wakeup of the L3 clock.
  97. //
  98. Value = AM3_CM_PER_READ(AM335_CM_PER_L3_CLOCK_STATE_CONTROL);
  99. Value |= AM335_CM_PER_L3_CLOCK_STATE_SOFTWARE_WAKEUP;
  100. AM3_CM_PER_WRITE(AM335_CM_PER_L3_CLOCK_STATE_CONTROL, Value);
  101. do {
  102. Value = AM3_CM_PER_READ(AM335_CM_PER_L3_CLOCK_STATE_CONTROL);
  103. } while ((Value & AM335_CM_PER_L3_CLOCK_STATE_TRANSITION_MASK) !=
  104. AM335_CM_PER_L3_CLOCK_STATE_SOFTWARE_WAKEUP);
  105. //
  106. // Force a software wakeup of the OCPWP L3 clock.
  107. //
  108. Value = AM3_CM_PER_READ(AM335_CM_PER_OCPWP_L3_CLOCK_STATE_CONTROL);
  109. Value |= AM335_CM_PER_OCPWP_L3_CLOCK_STATE_SOFTWARE_WAKEUP;
  110. AM3_CM_PER_WRITE(AM335_CM_PER_OCPWP_L3_CLOCK_STATE_CONTROL, Value);
  111. do {
  112. Value = AM3_CM_PER_READ(AM335_CM_PER_OCPWP_L3_CLOCK_STATE_CONTROL);
  113. } while ((Value & AM335_CM_PER_OCPWP_L3_CLOCK_STATE_TRANSITION_MASK) !=
  114. AM335_CM_PER_OCPWP_L3_CLOCK_STATE_SOFTWARE_WAKEUP);
  115. //
  116. // Force a software wakeup of the L3S clock.
  117. //
  118. Value = AM3_CM_PER_READ(AM335_CM_PER_L3S_CLOCK_STATE_CONTROL);
  119. Value |= AM335_CM_PER_L3S_CLOCK_STATE_SOFTWARE_WAKEUP;
  120. AM3_CM_PER_WRITE(AM335_CM_PER_L3S_CLOCK_STATE_CONTROL, Value);
  121. do {
  122. Value = AM3_CM_PER_READ(AM335_CM_PER_L3S_CLOCK_STATE_CONTROL);
  123. } while ((Value & AM335_CM_PER_L3S_CLOCK_STATE_TRANSITION_MASK) !=
  124. AM335_CM_PER_L3S_CLOCK_STATE_SOFTWARE_WAKEUP);
  125. //
  126. // Wait for the idle state in the L3 clock control.
  127. //
  128. do {
  129. Value = AM3_CM_PER_READ(AM335_CM_PER_L3_CLOCK_CONTROL);
  130. } while ((Value & AM335_CM_PER_L3_CLOCK_IDLE_STATE_MASK) !=
  131. AM335_CM_PER_L3_CLOCK_IDLE_STATE_FUNCTIONAL);
  132. //
  133. // Wait for the idle state in the L3 instr clock control.
  134. //
  135. do {
  136. Value = AM3_CM_PER_READ(AM335_CM_PER_L3_INSTR_CLOCK_CONTROL);
  137. } while ((Value & AM335_CM_PER_L3_INSTR_CLOCK_IDLE_STATE_MASK) !=
  138. AM335_CM_PER_L3_INSTR_CLOCK_IDLE_STATE_FUNCTIONAL);
  139. //
  140. // Wait for the L3 clock to become active.
  141. //
  142. do {
  143. Value = AM3_CM_PER_READ(AM335_CM_PER_L3_CLOCK_STATE_CONTROL);
  144. } while ((Value & AM335_CM_PER_L3_CLOCK_STATE_ACTIVE) == 0);
  145. //
  146. // Wait for the OCPWP L3 clock to become active.
  147. //
  148. do {
  149. Value = AM3_CM_PER_READ(AM335_CM_PER_OCPWP_L3_CLOCK_STATE_CONTROL);
  150. } while ((Value & AM335_CM_PER_OCPWP_L3_CLOCK_STATE_ACTIVE) == 0);
  151. //
  152. // Wait for the L3S clock to become active.
  153. //
  154. do {
  155. Value = AM3_CM_PER_READ(AM335_CM_PER_L3S_CLOCK_STATE_CONTROL);
  156. } while ((Value & AM335_CM_PER_L3S_CLOCK_STATE_ACTIVE) == 0);
  157. //
  158. // Enable the wakeup region.
  159. //
  160. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_CONTROL_CLOCK_CONTROL);
  161. Value |= AM335_CM_WAKEUP_CONTROL_CLOCK_ENABLE;
  162. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_CONTROL_CLOCK_CONTROL, Value);
  163. do {
  164. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_CONTROL_CLOCK_CONTROL);
  165. } while ((Value & AM335_CM_WAKEUP_CONTROL_CLOCK_MODE_MASK) !=
  166. AM335_CM_WAKEUP_CONTROL_CLOCK_ENABLE);
  167. //
  168. // Force a software wakeup of the CM wakeup clock.
  169. //
  170. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_CLOCK_STATE_CONTROL);
  171. Value |= AM335_CM_WAKEUP_CLOCK_STATE_SOFTWARE_WAKEUP;
  172. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_CLOCK_STATE_CONTROL, Value);
  173. do {
  174. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_CLOCK_STATE_CONTROL);
  175. } while ((Value & AM335_CM_WAKEUP_CLOCK_STATE_TRANSITION_MASK) !=
  176. AM335_CM_WAKEUP_CLOCK_STATE_SOFTWARE_WAKEUP);
  177. //
  178. // Force a software wakeup of the CM L3 Always On clock.
  179. //
  180. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_L3_AON_CLOCK_STATE_CONTROL);
  181. Value |= AM335_CM_WAKEUP_L3_AON_CLOCK_STATE_SOFTWARE_WAKEUP;
  182. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_L3_AON_CLOCK_STATE_CONTROL, Value);
  183. do {
  184. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_L3_AON_CLOCK_STATE_CONTROL);
  185. } while ((Value & AM335_CM_WAKEUP_L3_AON_CLOCK_STATE_TRANSITION_MASK) !=
  186. AM335_CM_WAKEUP_L3_AON_CLOCK_STATE_SOFTWARE_WAKEUP);
  187. //
  188. // Enable UART0.
  189. //
  190. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_UART0_CLOCK_CONTROL);
  191. Value |= AM335_CM_WAKEUP_UART0_CONTROL_CLOCK_ENABLE;
  192. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_UART0_CLOCK_CONTROL, Value);
  193. do {
  194. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_UART0_CLOCK_CONTROL);
  195. } while ((Value & AM335_CM_WAKEUP_UART0_CLOCK_MODE_MASK) !=
  196. AM335_CM_WAKEUP_UART0_CONTROL_CLOCK_ENABLE);
  197. //
  198. // Enable I2C0.
  199. //
  200. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_I2C0_CLOCK_CONTROL);
  201. Value |= AM335_CM_WAKEUP_I2C0_CONTROL_CLOCK_ENABLE;
  202. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_I2C0_CLOCK_CONTROL, Value);
  203. do {
  204. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_I2C0_CLOCK_CONTROL);
  205. } while ((Value & AM335_CM_WAKEUP_I2C0_CLOCK_MODE_MASK) !=
  206. AM335_CM_WAKEUP_I2C0_CONTROL_CLOCK_ENABLE);
  207. //
  208. // Wait for the idle state in the CM wakeup control clock.
  209. //
  210. do {
  211. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_CONTROL_CLOCK_CONTROL);
  212. } while ((Value & AM335_CM_WAKEUP_CONTROL_CLOCK_IDLE_STATE_MASK) !=
  213. AM335_CM_WAKEUP_CONTROL_CLOCK_IDLE_STATE_FUNCTIONAL);
  214. //
  215. // Wait for the L3 Always On clock to become active.
  216. //
  217. do {
  218. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_L3_AON_CLOCK_STATE_CONTROL);
  219. } while ((Value & AM335_CM_WAKEUP_L3_AON_CLOCK_STATE_ACTIVE) == 0);
  220. //
  221. // Wait for the L4 wakeup clock transition to become idle.
  222. //
  223. do {
  224. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_L4WKUP_CLOCK_CONTROL);
  225. } while ((Value & AM335_CM_WAKEUP_L4WKUP_CLOCK_IDLE_STATE_MASK) !=
  226. AM335_CM_WAKEUP_L4WKUP_CLOCK_IDLE_STATE_FUNCTIONAL);
  227. //
  228. // Wait for the L4 wakeup clock to become active.
  229. //
  230. do {
  231. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_CLOCK_STATE_CONTROL);
  232. } while ((Value & AM335_CM_WAKEUP_CLOCK_STATE_L4WAKEUP_ACTIVE) == 0);
  233. //
  234. // Wait for the L4 wakeup always on clock to become active.
  235. //
  236. do {
  237. Value = AM3_CM_WAKEUP_READ(
  238. AM335_CM_WAKEUP_L4WKUP_AON_CLOCK_STATE_CONTROL);
  239. } while ((Value & AM335_CM_WAKEUP_L4WKUP_AON_CLOCK_STATE_ACTIVE) == 0);
  240. //
  241. // Wait for the UART0 clock to become enabled.
  242. //
  243. do {
  244. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_CLOCK_STATE_CONTROL);
  245. } while ((Value & AM335_CM_WAKEUP_CLOCK_STATE_UART0_ACTIVE) == 0);
  246. //
  247. // Wait for the I2C0 clock to become enabled.
  248. //
  249. do {
  250. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_CLOCK_STATE_CONTROL);
  251. } while ((Value & AM335_CM_WAKEUP_CLOCK_STATE_I2C0_ACTIVE) == 0);
  252. //
  253. // Wait for the UART clock to become idle.
  254. //
  255. do {
  256. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_UART0_CLOCK_CONTROL);
  257. } while ((Value & AM335_CM_WAKEUP_UART0_CLOCK_IDLE_STATE_MASK) !=
  258. AM335_CM_WAKEUP_UART0_CLOCK_IDLE_STATE_FUNCTIONAL);
  259. //
  260. // Wait for the I2C clock to become idle.
  261. //
  262. do {
  263. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_I2C0_CLOCK_CONTROL);
  264. } while ((Value & AM335_CM_WAKEUP_I2C0_CLOCK_IDLE_STATE_MASK) !=
  265. AM335_CM_WAKEUP_I2C0_CLOCK_IDLE_STATE_FUNCTIONAL);
  266. return;
  267. }
  268. VOID
  269. EfipAm335InitializePlls (
  270. UINT32 OppIndex,
  271. UINT32 DdrFrequencyMultiplier
  272. )
  273. /*++
  274. Routine Description:
  275. This routine initializes the PLLs for the AM335x.
  276. Arguments:
  277. OppIndex - Supplies the index into the operating conditions table that the
  278. PLLs should be configured for.
  279. DdrFrequencyMultiplier - Supplies the multiplier value to initialize the
  280. DDR PLL with (depends on whether DDR2 or DDR3 is in use).
  281. Return Value:
  282. None.
  283. --*/
  284. {
  285. EfipAm335InitializeMpuPll(EfiAm335OppTable[OppIndex].PllMultiplier);
  286. EfipAm335InitializeCorePll();
  287. EfipAm335InitializePerPll();
  288. EfipAm335InitializeDdrPll(DdrFrequencyMultiplier);
  289. EfipAm335InitializeInterfaceClocks();
  290. EfipAm335InitializeDisplayPll();
  291. return;
  292. }
  293. //
  294. // --------------------------------------------------------- Internal Functions
  295. //
  296. VOID
  297. EfipAm335InitializeMpuPll (
  298. UINTN Multiplier
  299. )
  300. /*++
  301. Routine Description:
  302. This routine initializes the MPU PLL.
  303. Arguments:
  304. Multiplier - Supplies the multiplier value for the PLL.
  305. Return Value:
  306. None.
  307. --*/
  308. {
  309. UINT32 Value;
  310. //
  311. // Put the PLL in bypass mode.
  312. //
  313. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_CLOCK_MODE_DPLL_MPU) &
  314. ~AM335_CM_WAKEUP_CLOCK_MODE_DPLL_MPU_ENABLE;
  315. Value |= AM335_CM_WAKEUP_CLOCK_MODE_DPLL_MPU_ENABLE_MN_BYPASS;
  316. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_CLOCK_MODE_DPLL_MPU, Value);
  317. //
  318. // Wait for the PLL to go into bypass mode.
  319. //
  320. do {
  321. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_IDLE_STATUS_DPLL_MPU);
  322. } while ((Value & AM335_CM_WAKEUP_IDLE_STATUS_DPLL_MPU_MN_BYPASS) == 0);
  323. //
  324. // Clear the multiplier and divisor fields.
  325. //
  326. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_CLOCK_SELECT_DPLL_MPU);
  327. Value &= ~(AM335_CM_WAKEUP_CLOCK_SELECT_DPLL_MPU_MULT_MASK |
  328. AM335_CM_WAKEUP_CLOCK_SELECT_DPLL_MPU_DIV_MASK);
  329. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_CLOCK_SELECT_DPLL_MPU, Value);
  330. //
  331. // Set the new multiplier and divisor.
  332. //
  333. Value |= (Multiplier << AM335_CM_WAKEUP_CLOCK_SELECT_DPLL_MPU_MULT_SHIFT) |
  334. (AM335_MPU_PLL_N <<
  335. AM335_CM_WAKEUP_CLOCK_SELECT_DPLL_MPU_DIV_SHIFT);
  336. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_CLOCK_SELECT_DPLL_MPU, Value);
  337. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_DIV_M2_DPLL_MPU);
  338. Value &= ~(AM335_CM_WAKEUP_DIV_M2_DPLL_MPU_CLOCK_OUT_MASK);
  339. Value |= AM335_MPU_PLL_M2;
  340. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_DIV_M2_DPLL_MPU, Value);
  341. //
  342. // Enable and lock the PLL.
  343. //
  344. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_CLOCK_MODE_DPLL_MPU);
  345. Value |= AM335_CM_WAKEUP_CLOCK_MODE_DPLL_MPU_ENABLE;
  346. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_CLOCK_MODE_DPLL_MPU, Value);
  347. do {
  348. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_IDLE_STATUS_DPLL_MPU);
  349. } while ((Value & AM335_CM_WAKEUP_IDLE_STATUS_DPLL_MPU_CLOCK) == 0);
  350. return;
  351. }
  352. VOID
  353. EfipAm335InitializeCorePll (
  354. VOID
  355. )
  356. /*++
  357. Routine Description:
  358. This routine initializes the Core PLL.
  359. Arguments:
  360. None.
  361. Return Value:
  362. None.
  363. --*/
  364. {
  365. UINT32 Value;
  366. //
  367. // Put the PLL in bypass mode.
  368. //
  369. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_CLOCK_MODE_DPLL_CORE) &
  370. ~AM335_CM_WAKEUP_CLOCK_MODE_DPLL_CORE_ENABLE;
  371. Value |= AM335_CM_WAKEUP_CLOCK_MODE_DPLL_CORE_ENABLE_MN_BYPASS;
  372. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_CLOCK_MODE_DPLL_CORE, Value);
  373. //
  374. // Wait for the PLL to go into bypass mode.
  375. //
  376. do {
  377. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_IDLE_STATUS_DPLL_CORE);
  378. } while ((Value & AM335_CM_WAKEUP_IDLE_STATUS_DPLL_CORE_MN_BYPASS) == 0);
  379. //
  380. // Set the multiplier and divisor.
  381. //
  382. Value = (AM335_CORE_PLL_M <<
  383. AM335_CM_WAKEUP_CLOCK_SELECT_DPLL_CORE_MULT_SHIFT) |
  384. (AM335_CORE_PLL_N <<
  385. AM335_CM_WAKEUP_CLOCK_SELECT_DPLL_CORE_DIV_SHIFT);
  386. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_CLOCK_SELECT_DPLL_CORE, Value);
  387. //
  388. // Configure the high speed divisors. Start with the M4 divisor.
  389. //
  390. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_DIV_M4_DPLL_CORE);
  391. Value &= ~AM335_CM_WAKEUP_DIV_M4_DPLL_CORE_HSDIVIDER_CLOCK_OUT1_DIV_MASK;
  392. Value |= (AM335_CORE_PLL_HSDIVIDER_M4 <<
  393. AM335_CM_WAKEUP_DIV_M4_DPLL_CORE_HSDIVIDER_CLOCK_OUT1_DIV_SHIFT);
  394. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_DIV_M4_DPLL_CORE, Value);
  395. //
  396. // Set the M5 divisor.
  397. //
  398. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_DIV_M5_DPLL_CORE);
  399. Value &= ~AM335_CM_WAKEUP_DIV_M5_DPLL_CORE_HSDIVIDER_CLOCK_OUT2_DIV_MASK;
  400. Value |= (AM335_CORE_PLL_HSDIVIDER_M5 <<
  401. AM335_CM_WAKEUP_DIV_M5_DPLL_CORE_HSDIVIDER_CLOCK_OUT2_DIV_SHIFT);
  402. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_DIV_M5_DPLL_CORE, Value);
  403. //
  404. // Set the M6 divisor.
  405. //
  406. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_DIV_M6_DPLL_CORE);
  407. Value &= ~AM335_CM_WAKEUP_DIV_M6_DPLL_CORE_HSDIVIDER_CLOCK_OUT3_DIV_MASK;
  408. Value |= (AM335_CORE_PLL_HSDIVIDER_M6 <<
  409. AM335_CM_WAKEUP_DIV_M6_DPLL_CORE_HSDIVIDER_CLOCK_OUT3_DIV_SHIFT);
  410. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_DIV_M6_DPLL_CORE, Value);
  411. //
  412. // Enable and lock the PLL.
  413. //
  414. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_CLOCK_MODE_DPLL_CORE);
  415. Value |= AM335_CM_WAKEUP_CLOCK_MODE_DPLL_CORE_ENABLE;
  416. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_CLOCK_MODE_DPLL_CORE, Value);
  417. do {
  418. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_IDLE_STATUS_DPLL_CORE);
  419. } while ((Value & AM335_CM_WAKEUP_IDLE_STATUS_DPLL_CORE_CLOCK) == 0);
  420. return;
  421. }
  422. VOID
  423. EfipAm335InitializePerPll (
  424. VOID
  425. )
  426. /*++
  427. Routine Description:
  428. This routine initializes the Peripheral PLL.
  429. Arguments:
  430. None.
  431. Return Value:
  432. None.
  433. --*/
  434. {
  435. UINT32 Value;
  436. //
  437. // Put the PLL in bypass mode.
  438. //
  439. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_CLOCK_MODE_DPLL_PER) &
  440. ~AM335_CM_WAKEUP_CLOCK_MODE_DPLL_PER_ENABLE;
  441. Value |= AM335_CM_WAKEUP_CLOCK_MODE_DPLL_PER_ENABLE_MN_BYPASS;
  442. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_CLOCK_MODE_DPLL_PER, Value);
  443. //
  444. // Wait for the PLL to go into bypass mode.
  445. //
  446. do {
  447. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_IDLE_STATUS_DPLL_PER);
  448. } while ((Value & AM335_CM_WAKEUP_IDLE_STATUS_DPLL_PER_MN_BYPASS) == 0);
  449. //
  450. // Set the multiplier and divisor.
  451. //
  452. Value = (AM335_PER_PLL_M <<
  453. AM335_CM_WAKEUP_CLOCK_SELECT_DPLL_PER_MULT_SHIFT) |
  454. (AM335_PER_PLL_N <<
  455. AM335_CM_WAKEUP_CLOCK_SELECT_DPLL_PER_DIV_SHIFT);
  456. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_CLOCK_SELECT_DPLL_PER, Value);
  457. //
  458. // Set the M2 divisor.
  459. //
  460. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_DIV_M2_DPLL_PER);
  461. Value &= ~AM335_CM_WAKEUP_DIV_M2_DPLL_PER_CLOCK_OUT_DIV_MASK;
  462. Value |= (AM335_PER_PLL_M2 <<
  463. AM335_CM_WAKEUP_DIV_M2_DPLL_PER_CLOCK_OUT_DIV_SHIFT);
  464. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_DIV_M2_DPLL_PER, Value);
  465. //
  466. // Enable and lock the PLL.
  467. //
  468. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_CLOCK_MODE_DPLL_PER);
  469. Value |= AM335_CM_WAKEUP_CLOCK_MODE_DPLL_PER_ENABLE;
  470. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_CLOCK_MODE_DPLL_PER, Value);
  471. do {
  472. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_IDLE_STATUS_DPLL_PER);
  473. } while ((Value & AM335_CM_WAKEUP_IDLE_STATUS_DPLL_PER_CLOCK) == 0);
  474. return;
  475. }
  476. VOID
  477. EfipAm335InitializeDdrPll (
  478. UINTN Multiplier
  479. )
  480. /*++
  481. Routine Description:
  482. This routine initializes the DDR PLL.
  483. Arguments:
  484. Multiplier - Supplies the multiplier value for the PLL.
  485. Return Value:
  486. None.
  487. --*/
  488. {
  489. UINT32 Value;
  490. //
  491. // Put the PLL in bypass mode.
  492. //
  493. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_CLOCK_MODE_DPLL_DDR) &
  494. ~AM335_CM_WAKEUP_CLOCK_MODE_DPLL_DDR_ENABLE;
  495. Value |= AM335_CM_WAKEUP_CLOCK_MODE_DPLL_DDR_ENABLE_MN_BYPASS;
  496. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_CLOCK_MODE_DPLL_DDR, Value);
  497. //
  498. // Wait for the PLL to go into bypass mode.
  499. //
  500. do {
  501. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_IDLE_STATUS_DPLL_DDR);
  502. } while ((Value & AM335_CM_WAKEUP_IDLE_STATUS_DPLL_DDR_MN_BYPASS) == 0);
  503. //
  504. // Clear the multiplier and divisor fields.
  505. //
  506. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_CLOCK_SELECT_DPLL_DDR);
  507. Value &= ~(AM335_CM_WAKEUP_CLOCK_SELECT_DPLL_DDR_MULT_MASK |
  508. AM335_CM_WAKEUP_CLOCK_SELECT_DPLL_DDR_DIV_MASK);
  509. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_CLOCK_SELECT_DPLL_DDR, Value);
  510. //
  511. // Set the new multiplier and divisor.
  512. //
  513. Value |= (Multiplier << AM335_CM_WAKEUP_CLOCK_SELECT_DPLL_DDR_MULT_SHIFT) |
  514. (AM335_DDR_PLL_N <<
  515. AM335_CM_WAKEUP_CLOCK_SELECT_DPLL_DDR_DIV_SHIFT);
  516. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_CLOCK_SELECT_DPLL_DDR, Value);
  517. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_DIV_M2_DPLL_DDR);
  518. Value &= ~(AM335_CM_WAKEUP_DIV_M2_DPLL_DDR_CLOCK_OUT_MASK);
  519. Value |= AM335_DDR_PLL_M2;
  520. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_DIV_M2_DPLL_DDR, Value);
  521. //
  522. // Enable and lock the PLL.
  523. //
  524. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_CLOCK_MODE_DPLL_DDR);
  525. Value |= AM335_CM_WAKEUP_CLOCK_MODE_DPLL_DDR_ENABLE;
  526. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_CLOCK_MODE_DPLL_DDR, Value);
  527. do {
  528. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_IDLE_STATUS_DPLL_DDR);
  529. } while ((Value & AM335_CM_WAKEUP_IDLE_STATUS_DPLL_DDR_CLOCK) == 0);
  530. return;
  531. }
  532. VOID
  533. EfipAm335InitializeDisplayPll (
  534. VOID
  535. )
  536. /*++
  537. Routine Description:
  538. This routine initializes the Display PLL.
  539. Arguments:
  540. None.
  541. Return Value:
  542. None.
  543. --*/
  544. {
  545. UINT32 Value;
  546. //
  547. // Put the PLL in bypass mode.
  548. //
  549. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_CLOCK_MODE_DPLL_DISP) &
  550. ~AM335_CM_WAKEUP_CLOCK_MODE_DPLL_DISP_ENABLE;
  551. Value |= AM335_CM_WAKEUP_CLOCK_MODE_DPLL_DISP_ENABLE_MN_BYPASS;
  552. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_CLOCK_MODE_DPLL_DISP, Value);
  553. //
  554. // Wait for the PLL to go into bypass mode.
  555. //
  556. do {
  557. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_IDLE_STATUS_DPLL_DISP);
  558. } while ((Value & AM335_CM_WAKEUP_IDLE_STATUS_DPLL_DISP_MN_BYPASS) == 0);
  559. //
  560. // Clear the multiplier and divisor fields.
  561. //
  562. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_CLOCK_SELECT_DPLL_DISP);
  563. Value &= ~(AM335_CM_WAKEUP_CLOCK_SELECT_DPLL_DISP_MULT_MASK |
  564. AM335_CM_WAKEUP_CLOCK_SELECT_DPLL_DISP_DIV_MASK);
  565. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_CLOCK_SELECT_DPLL_DISP, Value);
  566. //
  567. // Set the new multiplier and divisor.
  568. //
  569. Value |= (AM335_DISP_PLL_M <<
  570. AM335_CM_WAKEUP_CLOCK_SELECT_DPLL_DISP_MULT_SHIFT) |
  571. (AM335_DISP_PLL_N <<
  572. AM335_CM_WAKEUP_CLOCK_SELECT_DPLL_DISP_DIV_SHIFT);
  573. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_CLOCK_SELECT_DPLL_DISP, Value);
  574. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_DIV_M2_DPLL_DISP);
  575. Value &= ~(AM335_CM_WAKEUP_DIV_M2_DPLL_DISP_CLOCK_OUT_MASK);
  576. Value |= AM335_DISP_PLL_M2;
  577. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_DIV_M2_DPLL_DISP, Value);
  578. //
  579. // Enable and lock the PLL.
  580. //
  581. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_CLOCK_MODE_DPLL_DISP);
  582. Value |= AM335_CM_WAKEUP_CLOCK_MODE_DPLL_DISP_ENABLE;
  583. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_CLOCK_MODE_DPLL_DISP, Value);
  584. do {
  585. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_IDLE_STATUS_DPLL_DISP);
  586. } while ((Value & AM335_CM_WAKEUP_IDLE_STATUS_DPLL_DISP_CLOCK) == 0);
  587. return;
  588. }
  589. VOID
  590. EfipAm335InitializeInterfaceClocks (
  591. VOID
  592. )
  593. /*++
  594. Routine Description:
  595. This routine fires up the needed interface clocks around the SoC.
  596. Arguments:
  597. None.
  598. Return Value:
  599. None.
  600. --*/
  601. {
  602. UINT32 Value;
  603. //
  604. // Some of these interfaces have already been initialized getting the UART
  605. // and LEDs running, but it's nice to have these all in once place.
  606. //
  607. Value = AM3_CM_PER_READ(AM335_CM_PER_L3_CLOCK_CONTROL);
  608. Value |= AM335_CM_PER_L3_CLOCK_ENABLE;
  609. AM3_CM_PER_WRITE(AM335_CM_PER_L3_CLOCK_CONTROL, Value);
  610. do {
  611. Value = AM3_CM_PER_READ(AM335_CM_PER_L3_CLOCK_CONTROL);
  612. } while ((Value & AM335_CM_PER_L3_CLOCK_MODE_MASK) !=
  613. AM335_CM_PER_L3_CLOCK_ENABLE);
  614. Value = AM3_CM_PER_READ(AM335_CM_PER_L4LS_CLOCK_CONTROL);
  615. Value |= AM335_CM_PER_L4LS_CLOCK_ENABLE;
  616. AM3_CM_PER_WRITE(AM335_CM_PER_L4LS_CLOCK_CONTROL, Value);
  617. do {
  618. Value = AM3_CM_PER_READ(AM335_CM_PER_L4LS_CLOCK_CONTROL);
  619. } while ((Value & AM335_CM_PER_L4LS_CLOCK_MODE_MASK) !=
  620. AM335_CM_PER_L4LS_CLOCK_ENABLE);
  621. Value = AM3_CM_PER_READ(AM335_CM_PER_L4FW_CLOCK_CONTROL);
  622. Value |= AM335_CM_PER_L4FW_CLOCK_ENABLE;
  623. AM3_CM_PER_WRITE(AM335_CM_PER_L4FW_CLOCK_CONTROL, Value);
  624. do {
  625. Value = AM3_CM_PER_READ(AM335_CM_PER_L4FW_CLOCK_CONTROL);
  626. } while ((Value & AM335_CM_PER_L4FW_CLOCK_MODE_MASK) !=
  627. AM335_CM_PER_L4FW_CLOCK_ENABLE);
  628. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_L4WKUP_CLOCK_CONTROL);
  629. Value |= AM335_CM_WAKEUP_L4FW_CLOCK_ENABLE;
  630. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_L4WKUP_CLOCK_CONTROL, Value);
  631. do {
  632. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_L4WKUP_CLOCK_CONTROL);
  633. } while ((Value & AM335_CM_WAKEUP_L4FW_CLOCK_MODE_MASK) !=
  634. AM335_CM_WAKEUP_L4FW_CLOCK_ENABLE);
  635. Value = AM3_CM_PER_READ(AM335_CM_PER_L3_INSTR_CLOCK_CONTROL);
  636. Value |= AM335_CM_PER_L3_INSTR_CLOCK_ENABLE;
  637. AM3_CM_PER_WRITE(AM335_CM_PER_L3_INSTR_CLOCK_CONTROL, Value);
  638. do {
  639. Value = AM3_CM_PER_READ(AM335_CM_PER_L3_INSTR_CLOCK_CONTROL);
  640. } while ((Value & AM335_CM_PER_L3_INSTR_CLOCK_MODE_MASK) !=
  641. AM335_CM_PER_L3_INSTR_CLOCK_ENABLE);
  642. Value = AM3_CM_PER_READ(AM335_CM_PER_L4HS_CLOCK_CONTROL);
  643. Value |= AM335_CM_PER_L4HS_CLOCK_ENABLE;
  644. AM3_CM_PER_WRITE(AM335_CM_PER_L4HS_CLOCK_CONTROL, Value);
  645. do {
  646. Value = AM3_CM_PER_READ(AM335_CM_PER_L4HS_CLOCK_CONTROL);
  647. } while ((Value & AM335_CM_PER_L4HS_CLOCK_MODE_MASK) !=
  648. AM335_CM_PER_L4FW_CLOCK_ENABLE);
  649. //
  650. // Enable USB clocks.
  651. //
  652. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_CLOCK_DCO_LDO_DPLL_PER);
  653. Value |= AM335_CM_WAKEUP_DCO_LDO_PER_DPLL_GATE_CONTROL;
  654. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_CLOCK_DCO_LDO_DPLL_PER, Value);
  655. Value = AM3_CM_PER_READ(AM335_CM_PER_USB0_CLOCK_CONTROL);
  656. Value |= AM335_CM_PER_USB0_CLOCK_ENABLE;
  657. AM3_CM_PER_WRITE(AM335_CM_PER_USB0_CLOCK_CONTROL, Value);
  658. do {
  659. Value = AM3_CM_PER_READ(AM335_CM_PER_USB0_CLOCK_CONTROL);
  660. } while ((Value & AM335_CM_PER_USB0_CLOCK_MODE_MASK) !=
  661. AM335_CM_PER_USB0_CLOCK_ENABLE);
  662. return;
  663. }
  664. VOID
  665. EfipAm335InitializePowerDomainTransition (
  666. VOID
  667. )
  668. /*++
  669. Routine Description:
  670. This routine performs clock wakeups for needed modules.
  671. Arguments:
  672. None.
  673. Return Value:
  674. None.
  675. --*/
  676. {
  677. UINT32 Value;
  678. Value = AM3_CM_PER_READ(AM335_CM_PER_L3_CLOCK_STATE_CONTROL);
  679. Value |= AM335_CM_PER_L3_CLOCK_STATE_SOFTWARE_WAKEUP;
  680. AM3_CM_PER_WRITE(AM335_CM_PER_L3_CLOCK_STATE_CONTROL, Value);
  681. Value = AM3_CM_PER_READ(AM335_CM_PER_L4LS_CLOCK_STATE_CONTROL);
  682. Value |= AM335_CM_PER_L4LS_CLOCK_STATE_SOFTWARE_WAKEUP;
  683. AM3_CM_PER_WRITE(AM335_CM_PER_L4LS_CLOCK_STATE_CONTROL, Value);
  684. Value = AM3_CM_WAKEUP_READ(AM335_CM_WAKEUP_CLOCK_STATE_CONTROL);
  685. Value |= AM335_CM_WAKEUP_CLOCK_STATE_SOFTWARE_WAKEUP;
  686. AM3_CM_WAKEUP_WRITE(AM335_CM_WAKEUP_CLOCK_STATE_CONTROL, Value);
  687. Value = AM3_CM_PER_READ(AM335_CM_PER_L4FW_CLOCK_STATE_CONTROL);
  688. Value |= AM335_CM_PER_L4FW_CLOCK_STATE_SOFTWARE_WAKEUP;
  689. AM3_CM_PER_WRITE(AM335_CM_PER_L4FW_CLOCK_STATE_CONTROL, Value);
  690. Value = AM3_CM_PER_READ(AM335_CM_PER_L3S_CLOCK_STATE_CONTROL);
  691. Value |= AM335_CM_PER_L3S_CLOCK_STATE_SOFTWARE_WAKEUP;
  692. AM3_CM_PER_WRITE(AM335_CM_PER_L3S_CLOCK_STATE_CONTROL, Value);
  693. return;
  694. }