clock.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. /*
  2. * (C) Copyright 2007
  3. * Sascha Hauer, Pengutronix
  4. *
  5. * (C) Copyright 2009 Freescale Semiconductor, Inc.
  6. *
  7. * See file CREDITS for list of people who contributed to this
  8. * project.
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License as
  12. * published by the Free Software Foundation; either version 2 of
  13. * the License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  23. * MA 02111-1307 USA
  24. */
  25. #include <common.h>
  26. #include <asm/io.h>
  27. #include <asm/errno.h>
  28. #include <asm/arch/imx-regs.h>
  29. #include <asm/arch/crm_regs.h>
  30. #include <asm/arch/clock.h>
  31. #include <div64.h>
  32. #include <asm/arch/sys_proto.h>
  33. enum pll_clocks {
  34. PLL1_CLOCK = 0,
  35. PLL2_CLOCK,
  36. PLL3_CLOCK,
  37. PLL4_CLOCK,
  38. PLL_CLOCKS,
  39. };
  40. struct mxc_pll_reg *mxc_plls[PLL_CLOCKS] = {
  41. [PLL1_CLOCK] = (struct mxc_pll_reg *)PLL1_BASE_ADDR,
  42. [PLL2_CLOCK] = (struct mxc_pll_reg *)PLL2_BASE_ADDR,
  43. [PLL3_CLOCK] = (struct mxc_pll_reg *)PLL3_BASE_ADDR,
  44. #ifdef CONFIG_MX53
  45. [PLL4_CLOCK] = (struct mxc_pll_reg *)PLL4_BASE_ADDR,
  46. #endif
  47. };
  48. struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)MXC_CCM_BASE;
  49. void set_usboh3_clk(void)
  50. {
  51. unsigned int reg;
  52. reg = readl(&mxc_ccm->cscmr1) &
  53. ~MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK;
  54. reg |= 1 << MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET;
  55. writel(reg, &mxc_ccm->cscmr1);
  56. reg = readl(&mxc_ccm->cscdr1);
  57. reg &= ~MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK;
  58. reg &= ~MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK;
  59. reg |= 4 << MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET;
  60. reg |= 1 << MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET;
  61. writel(reg, &mxc_ccm->cscdr1);
  62. }
  63. void enable_usboh3_clk(unsigned char enable)
  64. {
  65. unsigned int reg;
  66. reg = readl(&mxc_ccm->CCGR2);
  67. if (enable)
  68. reg |= 1 << MXC_CCM_CCGR2_CG14_OFFSET;
  69. else
  70. reg &= ~(1 << MXC_CCM_CCGR2_CG14_OFFSET);
  71. writel(reg, &mxc_ccm->CCGR2);
  72. }
  73. void set_usb_phy1_clk(void)
  74. {
  75. unsigned int reg;
  76. reg = readl(&mxc_ccm->cscmr1);
  77. reg &= ~MXC_CCM_CSCMR1_USB_PHY_CLK_SEL;
  78. writel(reg, &mxc_ccm->cscmr1);
  79. }
  80. void enable_usb_phy1_clk(unsigned char enable)
  81. {
  82. unsigned int reg;
  83. reg = readl(&mxc_ccm->CCGR4);
  84. if (enable)
  85. reg |= 1 << MXC_CCM_CCGR4_CG5_OFFSET;
  86. else
  87. reg &= ~(1 << MXC_CCM_CCGR4_CG5_OFFSET);
  88. writel(reg, &mxc_ccm->CCGR4);
  89. }
  90. void set_usb_phy2_clk(void)
  91. {
  92. unsigned int reg;
  93. reg = readl(&mxc_ccm->cscmr1);
  94. reg &= ~MXC_CCM_CSCMR1_USB_PHY_CLK_SEL;
  95. writel(reg, &mxc_ccm->cscmr1);
  96. }
  97. void enable_usb_phy2_clk(unsigned char enable)
  98. {
  99. unsigned int reg;
  100. reg = readl(&mxc_ccm->CCGR4);
  101. if (enable)
  102. reg |= 1 << MXC_CCM_CCGR4_CG6_OFFSET;
  103. else
  104. reg &= ~(1 << MXC_CCM_CCGR4_CG6_OFFSET);
  105. writel(reg, &mxc_ccm->CCGR4);
  106. }
  107. /*
  108. * Calculate the frequency of PLLn.
  109. */
  110. static uint32_t decode_pll(struct mxc_pll_reg *pll, uint32_t infreq)
  111. {
  112. uint32_t ctrl, op, mfd, mfn, mfi, pdf, ret;
  113. uint64_t refclk, temp;
  114. int32_t mfn_abs;
  115. ctrl = readl(&pll->ctrl);
  116. if (ctrl & MXC_DPLLC_CTL_HFSM) {
  117. mfn = __raw_readl(&pll->hfs_mfn);
  118. mfd = __raw_readl(&pll->hfs_mfd);
  119. op = __raw_readl(&pll->hfs_op);
  120. } else {
  121. mfn = __raw_readl(&pll->mfn);
  122. mfd = __raw_readl(&pll->mfd);
  123. op = __raw_readl(&pll->op);
  124. }
  125. mfd &= MXC_DPLLC_MFD_MFD_MASK;
  126. mfn &= MXC_DPLLC_MFN_MFN_MASK;
  127. pdf = op & MXC_DPLLC_OP_PDF_MASK;
  128. mfi = (op & MXC_DPLLC_OP_MFI_MASK) >> MXC_DPLLC_OP_MFI_OFFSET;
  129. /* 21.2.3 */
  130. if (mfi < 5)
  131. mfi = 5;
  132. /* Sign extend */
  133. if (mfn >= 0x04000000) {
  134. mfn |= 0xfc000000;
  135. mfn_abs = -mfn;
  136. } else
  137. mfn_abs = mfn;
  138. refclk = infreq * 2;
  139. if (ctrl & MXC_DPLLC_CTL_DPDCK0_2_EN)
  140. refclk *= 2;
  141. do_div(refclk, pdf + 1);
  142. temp = refclk * mfn_abs;
  143. do_div(temp, mfd + 1);
  144. ret = refclk * mfi;
  145. if ((int)mfn < 0)
  146. ret -= temp;
  147. else
  148. ret += temp;
  149. return ret;
  150. }
  151. /*
  152. * Get mcu main rate
  153. */
  154. u32 get_mcu_main_clk(void)
  155. {
  156. u32 reg, freq;
  157. reg = (__raw_readl(&mxc_ccm->cacrr) & MXC_CCM_CACRR_ARM_PODF_MASK) >>
  158. MXC_CCM_CACRR_ARM_PODF_OFFSET;
  159. freq = decode_pll(mxc_plls[PLL1_CLOCK], CONFIG_SYS_MX5_HCLK);
  160. return freq / (reg + 1);
  161. }
  162. /*
  163. * Get the rate of peripheral's root clock.
  164. */
  165. u32 get_periph_clk(void)
  166. {
  167. u32 reg;
  168. reg = __raw_readl(&mxc_ccm->cbcdr);
  169. if (!(reg & MXC_CCM_CBCDR_PERIPH_CLK_SEL))
  170. return decode_pll(mxc_plls[PLL2_CLOCK], CONFIG_SYS_MX5_HCLK);
  171. reg = __raw_readl(&mxc_ccm->cbcmr);
  172. switch ((reg & MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK) >>
  173. MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET) {
  174. case 0:
  175. return decode_pll(mxc_plls[PLL1_CLOCK], CONFIG_SYS_MX5_HCLK);
  176. case 1:
  177. return decode_pll(mxc_plls[PLL3_CLOCK], CONFIG_SYS_MX5_HCLK);
  178. default:
  179. return 0;
  180. }
  181. /* NOTREACHED */
  182. }
  183. /*
  184. * Get the rate of ipg clock.
  185. */
  186. static u32 get_ipg_clk(void)
  187. {
  188. uint32_t freq, reg, div;
  189. freq = get_ahb_clk();
  190. reg = __raw_readl(&mxc_ccm->cbcdr);
  191. div = ((reg & MXC_CCM_CBCDR_IPG_PODF_MASK) >>
  192. MXC_CCM_CBCDR_IPG_PODF_OFFSET) + 1;
  193. return freq / div;
  194. }
  195. /*
  196. * Get the rate of ipg_per clock.
  197. */
  198. static u32 get_ipg_per_clk(void)
  199. {
  200. u32 pred1, pred2, podf;
  201. if (__raw_readl(&mxc_ccm->cbcmr) & MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL)
  202. return get_ipg_clk();
  203. /* Fixme: not handle what about lpm*/
  204. podf = __raw_readl(&mxc_ccm->cbcdr);
  205. pred1 = (podf & MXC_CCM_CBCDR_PERCLK_PRED1_MASK) >>
  206. MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET;
  207. pred2 = (podf & MXC_CCM_CBCDR_PERCLK_PRED2_MASK) >>
  208. MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET;
  209. podf = (podf & MXC_CCM_CBCDR_PERCLK_PODF_MASK) >>
  210. MXC_CCM_CBCDR_PERCLK_PODF_OFFSET;
  211. return get_periph_clk() / ((pred1 + 1) * (pred2 + 1) * (podf + 1));
  212. }
  213. /*
  214. * Get the rate of uart clk.
  215. */
  216. static u32 get_uart_clk(void)
  217. {
  218. unsigned int freq, reg, pred, podf;
  219. reg = __raw_readl(&mxc_ccm->cscmr1);
  220. switch ((reg & MXC_CCM_CSCMR1_UART_CLK_SEL_MASK) >>
  221. MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET) {
  222. case 0x0:
  223. freq = decode_pll(mxc_plls[PLL1_CLOCK],
  224. CONFIG_SYS_MX5_HCLK);
  225. break;
  226. case 0x1:
  227. freq = decode_pll(mxc_plls[PLL2_CLOCK],
  228. CONFIG_SYS_MX5_HCLK);
  229. break;
  230. case 0x2:
  231. freq = decode_pll(mxc_plls[PLL3_CLOCK],
  232. CONFIG_SYS_MX5_HCLK);
  233. break;
  234. default:
  235. return 66500000;
  236. }
  237. reg = __raw_readl(&mxc_ccm->cscdr1);
  238. pred = (reg & MXC_CCM_CSCDR1_UART_CLK_PRED_MASK) >>
  239. MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET;
  240. podf = (reg & MXC_CCM_CSCDR1_UART_CLK_PODF_MASK) >>
  241. MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET;
  242. freq /= (pred + 1) * (podf + 1);
  243. return freq;
  244. }
  245. /*
  246. * This function returns the low power audio clock.
  247. */
  248. u32 get_lp_apm(void)
  249. {
  250. u32 ret_val = 0;
  251. u32 ccsr = __raw_readl(&mxc_ccm->ccsr);
  252. if (((ccsr >> 9) & 1) == 0)
  253. ret_val = CONFIG_SYS_MX5_HCLK;
  254. else
  255. ret_val = ((32768 * 1024));
  256. return ret_val;
  257. }
  258. /*
  259. * get cspi clock rate.
  260. */
  261. u32 imx_get_cspiclk(void)
  262. {
  263. u32 ret_val = 0, pdf, pre_pdf, clk_sel;
  264. u32 cscmr1 = __raw_readl(&mxc_ccm->cscmr1);
  265. u32 cscdr2 = __raw_readl(&mxc_ccm->cscdr2);
  266. pre_pdf = (cscdr2 & MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK) \
  267. >> MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET;
  268. pdf = (cscdr2 & MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK) \
  269. >> MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET;
  270. clk_sel = (cscmr1 & MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK) \
  271. >> MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET;
  272. switch (clk_sel) {
  273. case 0:
  274. ret_val = decode_pll(mxc_plls[PLL1_CLOCK],
  275. CONFIG_SYS_MX5_HCLK) /
  276. ((pre_pdf + 1) * (pdf + 1));
  277. break;
  278. case 1:
  279. ret_val = decode_pll(mxc_plls[PLL2_CLOCK],
  280. CONFIG_SYS_MX5_HCLK) /
  281. ((pre_pdf + 1) * (pdf + 1));
  282. break;
  283. case 2:
  284. ret_val = decode_pll(mxc_plls[PLL3_CLOCK],
  285. CONFIG_SYS_MX5_HCLK) /
  286. ((pre_pdf + 1) * (pdf + 1));
  287. break;
  288. default:
  289. ret_val = get_lp_apm() / ((pre_pdf + 1) * (pdf + 1));
  290. break;
  291. }
  292. return ret_val;
  293. }
  294. /*
  295. * The API of get mxc clockes.
  296. */
  297. unsigned int mxc_get_clock(enum mxc_clock clk)
  298. {
  299. switch (clk) {
  300. case MXC_ARM_CLK:
  301. return get_mcu_main_clk();
  302. case MXC_AHB_CLK:
  303. return get_ahb_clk();
  304. case MXC_IPG_CLK:
  305. return get_ipg_clk();
  306. case MXC_IPG_PERCLK:
  307. return get_ipg_per_clk();
  308. case MXC_UART_CLK:
  309. return get_uart_clk();
  310. case MXC_CSPI_CLK:
  311. return imx_get_cspiclk();
  312. case MXC_FEC_CLK:
  313. return decode_pll(mxc_plls[PLL1_CLOCK],
  314. CONFIG_SYS_MX5_HCLK);
  315. case MXC_SATA_CLK:
  316. return get_ahb_clk();
  317. default:
  318. break;
  319. }
  320. return -1;
  321. }
  322. u32 imx_get_uartclk(void)
  323. {
  324. return get_uart_clk();
  325. }
  326. u32 imx_get_fecclk(void)
  327. {
  328. return mxc_get_clock(MXC_IPG_CLK);
  329. }
  330. #ifdef CONFIG_MX53
  331. /*
  332. * The clock for the external interface can be set to use internal clock
  333. * if fuse bank 4, row 3, bit 2 is set.
  334. * This is an undocumented feature and it was confirmed by Freescale's support:
  335. * Fuses (but not pins) may be used to configure SATA clocks.
  336. * Particularly the i.MX53 Fuse_Map contains the next information
  337. * about configuring SATA clocks : SATA_ALT_REF_CLK[1:0] (offset 0x180C)
  338. * '00' - 100MHz (External)
  339. * '01' - 50MHz (External)
  340. * '10' - 120MHz, internal (USB PHY)
  341. * '11' - Reserved
  342. */
  343. void mxc_set_sata_internal_clock(void)
  344. {
  345. u32 *tmp_base =
  346. (u32 *)(IIM_BASE_ADDR + 0x180c);
  347. set_usb_phy1_clk();
  348. writel((readl(tmp_base) & (~0x7)) | 0x4, tmp_base);
  349. }
  350. #endif
  351. /*
  352. * Dump some core clockes.
  353. */
  354. int do_mx5_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  355. {
  356. u32 freq;
  357. freq = decode_pll(mxc_plls[PLL1_CLOCK], CONFIG_SYS_MX5_HCLK);
  358. printf("PLL1 %8d MHz\n", freq / 1000000);
  359. freq = decode_pll(mxc_plls[PLL2_CLOCK], CONFIG_SYS_MX5_HCLK);
  360. printf("PLL2 %8d MHz\n", freq / 1000000);
  361. freq = decode_pll(mxc_plls[PLL3_CLOCK], CONFIG_SYS_MX5_HCLK);
  362. printf("PLL3 %8d MHz\n", freq / 1000000);
  363. #ifdef CONFIG_MX53
  364. freq = decode_pll(mxc_plls[PLL4_CLOCK], CONFIG_SYS_MX5_HCLK);
  365. printf("PLL4 %8d MHz\n", freq / 1000000);
  366. #endif
  367. printf("\n");
  368. printf("AHB %8d kHz\n", mxc_get_clock(MXC_AHB_CLK) / 1000);
  369. printf("IPG %8d kHz\n", mxc_get_clock(MXC_IPG_CLK) / 1000);
  370. printf("IPG PERCLK %8d kHz\n", mxc_get_clock(MXC_IPG_PERCLK) / 1000);
  371. return 0;
  372. }
  373. /***************************************************/
  374. U_BOOT_CMD(
  375. clocks, CONFIG_SYS_MAXARGS, 1, do_mx5_showclocks,
  376. "display clocks",
  377. ""
  378. );