clocks-common.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. /*
  2. *
  3. * Clock initialization for OMAP4
  4. *
  5. * (C) Copyright 2010
  6. * Texas Instruments, <www.ti.com>
  7. *
  8. * Aneesh V <aneesh@ti.com>
  9. *
  10. * Based on previous work by:
  11. * Santosh Shilimkar <santosh.shilimkar@ti.com>
  12. * Rajendra Nayak <rnayak@ti.com>
  13. *
  14. * See file CREDITS for list of people who contributed to this
  15. * project.
  16. *
  17. * This program is free software; you can redistribute it and/or
  18. * modify it under the terms of the GNU General Public License as
  19. * published by the Free Software Foundation; either version 2 of
  20. * the License, or (at your option) any later version.
  21. *
  22. * This program is distributed in the hope that it will be useful,
  23. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  24. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  25. * GNU General Public License for more details.
  26. *
  27. * You should have received a copy of the GNU General Public License
  28. * along with this program; if not, write to the Free Software
  29. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  30. * MA 02111-1307 USA
  31. */
  32. #include <common.h>
  33. #include <asm/omap_common.h>
  34. #include <asm/gpio.h>
  35. #include <asm/arch/clocks.h>
  36. #include <asm/arch/sys_proto.h>
  37. #include <asm/utils.h>
  38. #include <asm/omap_gpio.h>
  39. #include <asm/emif.h>
  40. #ifndef CONFIG_SPL_BUILD
  41. /*
  42. * printing to console doesn't work unless
  43. * this code is executed from SPL
  44. */
  45. #define printf(fmt, args...)
  46. #define puts(s)
  47. #endif
  48. static inline u32 __get_sys_clk_index(void)
  49. {
  50. u32 ind;
  51. /*
  52. * For ES1 the ROM code calibration of sys clock is not reliable
  53. * due to hw issue. So, use hard-coded value. If this value is not
  54. * correct for any board over-ride this function in board file
  55. * From ES2.0 onwards you will get this information from
  56. * CM_SYS_CLKSEL
  57. */
  58. if (omap_revision() == OMAP4430_ES1_0)
  59. ind = OMAP_SYS_CLK_IND_38_4_MHZ;
  60. else {
  61. /* SYS_CLKSEL - 1 to match the dpll param array indices */
  62. ind = (readl((*prcm)->cm_sys_clksel) &
  63. CM_SYS_CLKSEL_SYS_CLKSEL_MASK) - 1;
  64. }
  65. return ind;
  66. }
  67. u32 get_sys_clk_index(void)
  68. __attribute__ ((weak, alias("__get_sys_clk_index")));
  69. u32 get_sys_clk_freq(void)
  70. {
  71. u8 index = get_sys_clk_index();
  72. return sys_clk_array[index];
  73. }
  74. static inline void do_bypass_dpll(u32 const base)
  75. {
  76. struct dpll_regs *dpll_regs = (struct dpll_regs *)base;
  77. clrsetbits_le32(&dpll_regs->cm_clkmode_dpll,
  78. CM_CLKMODE_DPLL_DPLL_EN_MASK,
  79. DPLL_EN_FAST_RELOCK_BYPASS <<
  80. CM_CLKMODE_DPLL_EN_SHIFT);
  81. }
  82. static inline void wait_for_bypass(u32 const base)
  83. {
  84. struct dpll_regs *const dpll_regs = (struct dpll_regs *)base;
  85. if (!wait_on_value(ST_DPLL_CLK_MASK, 0, &dpll_regs->cm_idlest_dpll,
  86. LDELAY)) {
  87. printf("Bypassing DPLL failed %x\n", base);
  88. }
  89. }
  90. static inline void do_lock_dpll(u32 const base)
  91. {
  92. struct dpll_regs *const dpll_regs = (struct dpll_regs *)base;
  93. clrsetbits_le32(&dpll_regs->cm_clkmode_dpll,
  94. CM_CLKMODE_DPLL_DPLL_EN_MASK,
  95. DPLL_EN_LOCK << CM_CLKMODE_DPLL_EN_SHIFT);
  96. }
  97. static inline void wait_for_lock(u32 const base)
  98. {
  99. struct dpll_regs *const dpll_regs = (struct dpll_regs *)base;
  100. if (!wait_on_value(ST_DPLL_CLK_MASK, ST_DPLL_CLK_MASK,
  101. &dpll_regs->cm_idlest_dpll, LDELAY)) {
  102. printf("DPLL locking failed for %x\n", base);
  103. hang();
  104. }
  105. }
  106. inline u32 check_for_lock(u32 const base)
  107. {
  108. struct dpll_regs *const dpll_regs = (struct dpll_regs *)base;
  109. u32 lock = readl(&dpll_regs->cm_idlest_dpll) & ST_DPLL_CLK_MASK;
  110. return lock;
  111. }
  112. static void do_setup_dpll(u32 const base, const struct dpll_params *params,
  113. u8 lock, char *dpll)
  114. {
  115. u32 temp, M, N;
  116. struct dpll_regs *const dpll_regs = (struct dpll_regs *)base;
  117. temp = readl(&dpll_regs->cm_clksel_dpll);
  118. if (check_for_lock(base)) {
  119. /*
  120. * The Dpll has already been locked by rom code using CH.
  121. * Check if M,N are matching with Ideal nominal opp values.
  122. * If matches, skip the rest otherwise relock.
  123. */
  124. M = (temp & CM_CLKSEL_DPLL_M_MASK) >> CM_CLKSEL_DPLL_M_SHIFT;
  125. N = (temp & CM_CLKSEL_DPLL_N_MASK) >> CM_CLKSEL_DPLL_N_SHIFT;
  126. if ((M != (params->m)) || (N != (params->n))) {
  127. debug("\n %s Dpll locked, but not for ideal M = %d,"
  128. "N = %d values, current values are M = %d,"
  129. "N= %d" , dpll, params->m, params->n,
  130. M, N);
  131. } else {
  132. /* Dpll locked with ideal values for nominal opps. */
  133. debug("\n %s Dpll already locked with ideal"
  134. "nominal opp values", dpll);
  135. goto setup_post_dividers;
  136. }
  137. }
  138. bypass_dpll(base);
  139. /* Set M & N */
  140. temp &= ~CM_CLKSEL_DPLL_M_MASK;
  141. temp |= (params->m << CM_CLKSEL_DPLL_M_SHIFT) & CM_CLKSEL_DPLL_M_MASK;
  142. temp &= ~CM_CLKSEL_DPLL_N_MASK;
  143. temp |= (params->n << CM_CLKSEL_DPLL_N_SHIFT) & CM_CLKSEL_DPLL_N_MASK;
  144. writel(temp, &dpll_regs->cm_clksel_dpll);
  145. /* Lock */
  146. if (lock)
  147. do_lock_dpll(base);
  148. setup_post_dividers:
  149. setup_post_dividers(base, params);
  150. /* Wait till the DPLL locks */
  151. if (lock)
  152. wait_for_lock(base);
  153. }
  154. u32 omap_ddr_clk(void)
  155. {
  156. u32 ddr_clk, sys_clk_khz, omap_rev, divider;
  157. const struct dpll_params *core_dpll_params;
  158. omap_rev = omap_revision();
  159. sys_clk_khz = get_sys_clk_freq() / 1000;
  160. core_dpll_params = get_core_dpll_params();
  161. debug("sys_clk %d\n ", sys_clk_khz * 1000);
  162. /* Find Core DPLL locked frequency first */
  163. ddr_clk = sys_clk_khz * 2 * core_dpll_params->m /
  164. (core_dpll_params->n + 1);
  165. if (omap_rev < OMAP5430_ES1_0) {
  166. /*
  167. * DDR frequency is PHY_ROOT_CLK/2
  168. * PHY_ROOT_CLK = Fdpll/2/M2
  169. */
  170. divider = 4;
  171. } else {
  172. /*
  173. * DDR frequency is PHY_ROOT_CLK
  174. * PHY_ROOT_CLK = Fdpll/2/M2
  175. */
  176. divider = 2;
  177. }
  178. ddr_clk = ddr_clk / divider / core_dpll_params->m2;
  179. ddr_clk *= 1000; /* convert to Hz */
  180. debug("ddr_clk %d\n ", ddr_clk);
  181. return ddr_clk;
  182. }
  183. /*
  184. * Lock MPU dpll
  185. *
  186. * Resulting MPU frequencies:
  187. * 4430 ES1.0 : 600 MHz
  188. * 4430 ES2.x : 792 MHz (OPP Turbo)
  189. * 4460 : 920 MHz (OPP Turbo) - DCC disabled
  190. */
  191. void configure_mpu_dpll(void)
  192. {
  193. const struct dpll_params *params;
  194. struct dpll_regs *mpu_dpll_regs;
  195. u32 omap_rev;
  196. omap_rev = omap_revision();
  197. /*
  198. * DCC and clock divider settings for 4460.
  199. * DCC is required, if more than a certain frequency is required.
  200. * For, 4460 > 1GHZ.
  201. * 5430 > 1.4GHZ.
  202. */
  203. if ((omap_rev >= OMAP4460_ES1_0) && (omap_rev < OMAP5430_ES1_0)) {
  204. mpu_dpll_regs =
  205. (struct dpll_regs *)((*prcm)->cm_clkmode_dpll_mpu);
  206. bypass_dpll((*prcm)->cm_clkmode_dpll_mpu);
  207. clrbits_le32((*prcm)->cm_mpu_mpu_clkctrl,
  208. MPU_CLKCTRL_CLKSEL_EMIF_DIV_MODE_MASK);
  209. setbits_le32((*prcm)->cm_mpu_mpu_clkctrl,
  210. MPU_CLKCTRL_CLKSEL_ABE_DIV_MODE_MASK);
  211. clrbits_le32(&mpu_dpll_regs->cm_clksel_dpll,
  212. CM_CLKSEL_DCC_EN_MASK);
  213. }
  214. setbits_le32((*prcm)->cm_mpu_mpu_clkctrl,
  215. MPU_CLKCTRL_CLKSEL_EMIF_DIV_MODE_MASK);
  216. setbits_le32((*prcm)->cm_mpu_mpu_clkctrl,
  217. MPU_CLKCTRL_CLKSEL_ABE_DIV_MODE_MASK);
  218. params = get_mpu_dpll_params();
  219. do_setup_dpll((*prcm)->cm_clkmode_dpll_mpu, params, DPLL_LOCK, "mpu");
  220. debug("MPU DPLL locked\n");
  221. }
  222. #ifdef CONFIG_USB_EHCI_OMAP
  223. static void setup_usb_dpll(void)
  224. {
  225. const struct dpll_params *params;
  226. u32 sys_clk_khz, sd_div, num, den;
  227. sys_clk_khz = get_sys_clk_freq() / 1000;
  228. /*
  229. * USB:
  230. * USB dpll is J-type. Need to set DPLL_SD_DIV for jitter correction
  231. * DPLL_SD_DIV = CEILING ([DPLL_MULT/(DPLL_DIV+1)]* CLKINP / 250)
  232. * - where CLKINP is sys_clk in MHz
  233. * Use CLKINP in KHz and adjust the denominator accordingly so
  234. * that we have enough accuracy and at the same time no overflow
  235. */
  236. params = get_usb_dpll_params();
  237. num = params->m * sys_clk_khz;
  238. den = (params->n + 1) * 250 * 1000;
  239. num += den - 1;
  240. sd_div = num / den;
  241. clrsetbits_le32((*prcm)->cm_clksel_dpll_usb,
  242. CM_CLKSEL_DPLL_DPLL_SD_DIV_MASK,
  243. sd_div << CM_CLKSEL_DPLL_DPLL_SD_DIV_SHIFT);
  244. /* Now setup the dpll with the regular function */
  245. do_setup_dpll((*prcm)->cm_clkmode_dpll_usb, params, DPLL_LOCK, "usb");
  246. }
  247. #endif
  248. static void setup_dplls(void)
  249. {
  250. u32 temp;
  251. const struct dpll_params *params;
  252. debug("setup_dplls\n");
  253. /* CORE dpll */
  254. params = get_core_dpll_params(); /* default - safest */
  255. /*
  256. * Do not lock the core DPLL now. Just set it up.
  257. * Core DPLL will be locked after setting up EMIF
  258. * using the FREQ_UPDATE method(freq_update_core())
  259. */
  260. if (emif_sdram_type() == EMIF_SDRAM_TYPE_LPDDR2)
  261. do_setup_dpll((*prcm)->cm_clkmode_dpll_core, params,
  262. DPLL_NO_LOCK, "core");
  263. else
  264. do_setup_dpll((*prcm)->cm_clkmode_dpll_core, params,
  265. DPLL_LOCK, "core");
  266. /* Set the ratios for CORE_CLK, L3_CLK, L4_CLK */
  267. temp = (CLKSEL_CORE_X2_DIV_1 << CLKSEL_CORE_SHIFT) |
  268. (CLKSEL_L3_CORE_DIV_2 << CLKSEL_L3_SHIFT) |
  269. (CLKSEL_L4_L3_DIV_2 << CLKSEL_L4_SHIFT);
  270. writel(temp, (*prcm)->cm_clksel_core);
  271. debug("Core DPLL configured\n");
  272. /* lock PER dpll */
  273. params = get_per_dpll_params();
  274. do_setup_dpll((*prcm)->cm_clkmode_dpll_per,
  275. params, DPLL_LOCK, "per");
  276. debug("PER DPLL locked\n");
  277. /* MPU dpll */
  278. configure_mpu_dpll();
  279. #ifdef CONFIG_USB_EHCI_OMAP
  280. setup_usb_dpll();
  281. #endif
  282. }
  283. #ifdef CONFIG_SYS_CLOCKS_ENABLE_ALL
  284. static void setup_non_essential_dplls(void)
  285. {
  286. u32 abe_ref_clk;
  287. const struct dpll_params *params;
  288. /* IVA */
  289. clrsetbits_le32((*prcm)->cm_bypclk_dpll_iva,
  290. CM_BYPCLK_DPLL_IVA_CLKSEL_MASK, DPLL_IVA_CLKSEL_CORE_X2_DIV_2);
  291. params = get_iva_dpll_params();
  292. do_setup_dpll((*prcm)->cm_clkmode_dpll_iva, params, DPLL_LOCK, "iva");
  293. /* Configure ABE dpll */
  294. params = get_abe_dpll_params();
  295. #ifdef CONFIG_SYS_OMAP_ABE_SYSCK
  296. abe_ref_clk = CM_ABE_PLL_REF_CLKSEL_CLKSEL_SYSCLK;
  297. #else
  298. abe_ref_clk = CM_ABE_PLL_REF_CLKSEL_CLKSEL_32KCLK;
  299. /*
  300. * We need to enable some additional options to achieve
  301. * 196.608MHz from 32768 Hz
  302. */
  303. setbits_le32((*prcm)->cm_clkmode_dpll_abe,
  304. CM_CLKMODE_DPLL_DRIFTGUARD_EN_MASK|
  305. CM_CLKMODE_DPLL_RELOCK_RAMP_EN_MASK|
  306. CM_CLKMODE_DPLL_LPMODE_EN_MASK|
  307. CM_CLKMODE_DPLL_REGM4XEN_MASK);
  308. /* Spend 4 REFCLK cycles at each stage */
  309. clrsetbits_le32((*prcm)->cm_clkmode_dpll_abe,
  310. CM_CLKMODE_DPLL_RAMP_RATE_MASK,
  311. 1 << CM_CLKMODE_DPLL_RAMP_RATE_SHIFT);
  312. #endif
  313. /* Select the right reference clk */
  314. clrsetbits_le32((*prcm)->cm_abe_pll_ref_clksel,
  315. CM_ABE_PLL_REF_CLKSEL_CLKSEL_MASK,
  316. abe_ref_clk << CM_ABE_PLL_REF_CLKSEL_CLKSEL_SHIFT);
  317. /* Lock the dpll */
  318. do_setup_dpll((*prcm)->cm_clkmode_dpll_abe, params, DPLL_LOCK, "abe");
  319. }
  320. #endif
  321. void do_scale_tps62361(int gpio, u32 reg, u32 volt_mv)
  322. {
  323. u32 step;
  324. int ret = 0;
  325. /* See if we can first get the GPIO if needed */
  326. if (gpio >= 0)
  327. ret = gpio_request(gpio, "TPS62361_VSEL0_GPIO");
  328. if (ret < 0) {
  329. printf("%s: gpio %d request failed %d\n", __func__, gpio, ret);
  330. gpio = -1;
  331. }
  332. /* Pull the GPIO low to select SET0 register, while we program SET1 */
  333. if (gpio >= 0)
  334. gpio_direction_output(gpio, 0);
  335. step = volt_mv - TPS62361_BASE_VOLT_MV;
  336. step /= 10;
  337. debug("do_scale_tps62361: volt - %d step - 0x%x\n", volt_mv, step);
  338. if (omap_vc_bypass_send_value(TPS62361_I2C_SLAVE_ADDR, reg, step))
  339. puts("Scaling voltage failed for vdd_mpu from TPS\n");
  340. /* Pull the GPIO high to select SET1 register */
  341. if (gpio >= 0)
  342. gpio_direction_output(gpio, 1);
  343. }
  344. void do_scale_vcore(u32 vcore_reg, u32 volt_mv)
  345. {
  346. u32 offset_code;
  347. u32 offset = volt_mv;
  348. /* convert to uV for better accuracy in the calculations */
  349. offset *= 1000;
  350. offset_code = get_offset_code(offset);
  351. debug("do_scale_vcore: volt - %d offset_code - 0x%x\n", volt_mv,
  352. offset_code);
  353. if (omap_vc_bypass_send_value(SMPS_I2C_SLAVE_ADDR,
  354. vcore_reg, offset_code))
  355. printf("Scaling voltage failed for 0x%x\n", vcore_reg);
  356. }
  357. static inline void enable_clock_domain(u32 const clkctrl_reg, u32 enable_mode)
  358. {
  359. clrsetbits_le32(clkctrl_reg, CD_CLKCTRL_CLKTRCTRL_MASK,
  360. enable_mode << CD_CLKCTRL_CLKTRCTRL_SHIFT);
  361. debug("Enable clock domain - %x\n", clkctrl_reg);
  362. }
  363. static inline void wait_for_clk_enable(u32 clkctrl_addr)
  364. {
  365. u32 clkctrl, idlest = MODULE_CLKCTRL_IDLEST_DISABLED;
  366. u32 bound = LDELAY;
  367. while ((idlest == MODULE_CLKCTRL_IDLEST_DISABLED) ||
  368. (idlest == MODULE_CLKCTRL_IDLEST_TRANSITIONING)) {
  369. clkctrl = readl(clkctrl_addr);
  370. idlest = (clkctrl & MODULE_CLKCTRL_IDLEST_MASK) >>
  371. MODULE_CLKCTRL_IDLEST_SHIFT;
  372. if (--bound == 0) {
  373. printf("Clock enable failed for 0x%x idlest 0x%x\n",
  374. clkctrl_addr, clkctrl);
  375. return;
  376. }
  377. }
  378. }
  379. static inline void enable_clock_module(u32 const clkctrl_addr, u32 enable_mode,
  380. u32 wait_for_enable)
  381. {
  382. clrsetbits_le32(clkctrl_addr, MODULE_CLKCTRL_MODULEMODE_MASK,
  383. enable_mode << MODULE_CLKCTRL_MODULEMODE_SHIFT);
  384. debug("Enable clock module - %x\n", clkctrl_addr);
  385. if (wait_for_enable)
  386. wait_for_clk_enable(clkctrl_addr);
  387. }
  388. void freq_update_core(void)
  389. {
  390. u32 freq_config1 = 0;
  391. const struct dpll_params *core_dpll_params;
  392. u32 omap_rev = omap_revision();
  393. core_dpll_params = get_core_dpll_params();
  394. /* Put EMIF clock domain in sw wakeup mode */
  395. enable_clock_domain((*prcm)->cm_memif_clkstctrl,
  396. CD_CLKCTRL_CLKTRCTRL_SW_WKUP);
  397. wait_for_clk_enable((*prcm)->cm_memif_emif_1_clkctrl);
  398. wait_for_clk_enable((*prcm)->cm_memif_emif_2_clkctrl);
  399. freq_config1 = SHADOW_FREQ_CONFIG1_FREQ_UPDATE_MASK |
  400. SHADOW_FREQ_CONFIG1_DLL_RESET_MASK;
  401. freq_config1 |= (DPLL_EN_LOCK << SHADOW_FREQ_CONFIG1_DPLL_EN_SHIFT) &
  402. SHADOW_FREQ_CONFIG1_DPLL_EN_MASK;
  403. freq_config1 |= (core_dpll_params->m2 <<
  404. SHADOW_FREQ_CONFIG1_M2_DIV_SHIFT) &
  405. SHADOW_FREQ_CONFIG1_M2_DIV_MASK;
  406. writel(freq_config1, (*prcm)->cm_shadow_freq_config1);
  407. if (!wait_on_value(SHADOW_FREQ_CONFIG1_FREQ_UPDATE_MASK, 0,
  408. (u32 *) (*prcm)->cm_shadow_freq_config1, LDELAY)) {
  409. puts("FREQ UPDATE procedure failed!!");
  410. hang();
  411. }
  412. /*
  413. * Putting EMIF in HW_AUTO is seen to be causing issues with
  414. * EMIF clocks and the master DLL. Put EMIF in SW_WKUP
  415. * in OMAP5430 ES1.0 silicon
  416. */
  417. if (omap_rev != OMAP5430_ES1_0) {
  418. /* Put EMIF clock domain back in hw auto mode */
  419. enable_clock_domain((*prcm)->cm_memif_clkstctrl,
  420. CD_CLKCTRL_CLKTRCTRL_HW_AUTO);
  421. wait_for_clk_enable((*prcm)->cm_memif_emif_1_clkctrl);
  422. wait_for_clk_enable((*prcm)->cm_memif_emif_2_clkctrl);
  423. }
  424. }
  425. void bypass_dpll(u32 const base)
  426. {
  427. do_bypass_dpll(base);
  428. wait_for_bypass(base);
  429. }
  430. void lock_dpll(u32 const base)
  431. {
  432. do_lock_dpll(base);
  433. wait_for_lock(base);
  434. }
  435. void setup_clocks_for_console(void)
  436. {
  437. /* Do not add any spl_debug prints in this function */
  438. clrsetbits_le32((*prcm)->cm_l4per_clkstctrl, CD_CLKCTRL_CLKTRCTRL_MASK,
  439. CD_CLKCTRL_CLKTRCTRL_SW_WKUP <<
  440. CD_CLKCTRL_CLKTRCTRL_SHIFT);
  441. /* Enable all UARTs - console will be on one of them */
  442. clrsetbits_le32((*prcm)->cm_l4per_uart1_clkctrl,
  443. MODULE_CLKCTRL_MODULEMODE_MASK,
  444. MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN <<
  445. MODULE_CLKCTRL_MODULEMODE_SHIFT);
  446. clrsetbits_le32((*prcm)->cm_l4per_uart2_clkctrl,
  447. MODULE_CLKCTRL_MODULEMODE_MASK,
  448. MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN <<
  449. MODULE_CLKCTRL_MODULEMODE_SHIFT);
  450. clrsetbits_le32((*prcm)->cm_l4per_uart3_clkctrl,
  451. MODULE_CLKCTRL_MODULEMODE_MASK,
  452. MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN <<
  453. MODULE_CLKCTRL_MODULEMODE_SHIFT);
  454. clrsetbits_le32((*prcm)->cm_l4per_uart3_clkctrl,
  455. MODULE_CLKCTRL_MODULEMODE_MASK,
  456. MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN <<
  457. MODULE_CLKCTRL_MODULEMODE_SHIFT);
  458. clrsetbits_le32((*prcm)->cm_l4per_clkstctrl, CD_CLKCTRL_CLKTRCTRL_MASK,
  459. CD_CLKCTRL_CLKTRCTRL_HW_AUTO <<
  460. CD_CLKCTRL_CLKTRCTRL_SHIFT);
  461. }
  462. void do_enable_clocks(u32 const *clk_domains,
  463. u32 const *clk_modules_hw_auto,
  464. u32 const *clk_modules_explicit_en,
  465. u8 wait_for_enable)
  466. {
  467. u32 i, max = 100;
  468. /* Put the clock domains in SW_WKUP mode */
  469. for (i = 0; (i < max) && clk_domains[i]; i++) {
  470. enable_clock_domain(clk_domains[i],
  471. CD_CLKCTRL_CLKTRCTRL_SW_WKUP);
  472. }
  473. /* Clock modules that need to be put in HW_AUTO */
  474. for (i = 0; (i < max) && clk_modules_hw_auto[i]; i++) {
  475. enable_clock_module(clk_modules_hw_auto[i],
  476. MODULE_CLKCTRL_MODULEMODE_HW_AUTO,
  477. wait_for_enable);
  478. };
  479. /* Clock modules that need to be put in SW_EXPLICIT_EN mode */
  480. for (i = 0; (i < max) && clk_modules_explicit_en[i]; i++) {
  481. enable_clock_module(clk_modules_explicit_en[i],
  482. MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN,
  483. wait_for_enable);
  484. };
  485. /* Put the clock domains in HW_AUTO mode now */
  486. for (i = 0; (i < max) && clk_domains[i]; i++) {
  487. enable_clock_domain(clk_domains[i],
  488. CD_CLKCTRL_CLKTRCTRL_HW_AUTO);
  489. }
  490. }
  491. void prcm_init(void)
  492. {
  493. switch (omap_hw_init_context()) {
  494. case OMAP_INIT_CONTEXT_SPL:
  495. case OMAP_INIT_CONTEXT_UBOOT_FROM_NOR:
  496. case OMAP_INIT_CONTEXT_UBOOT_AFTER_CH:
  497. enable_basic_clocks();
  498. scale_vcores();
  499. setup_dplls();
  500. #ifdef CONFIG_SYS_CLOCKS_ENABLE_ALL
  501. setup_non_essential_dplls();
  502. enable_non_essential_clocks();
  503. #endif
  504. break;
  505. default:
  506. break;
  507. }
  508. if (OMAP_INIT_CONTEXT_SPL != omap_hw_init_context())
  509. enable_basic_uboot_clocks();
  510. }