clock_imx8mm.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright 2018-2019 NXP
  4. *
  5. * Peng Fan <peng.fan@nxp.com>
  6. */
  7. #include <common.h>
  8. #include <asm/arch/clock.h>
  9. #include <asm/arch/imx-regs.h>
  10. #include <asm/arch/sys_proto.h>
  11. #include <asm/io.h>
  12. #include <div64.h>
  13. #include <errno.h>
  14. #include <linux/bitops.h>
  15. #include <linux/delay.h>
  16. DECLARE_GLOBAL_DATA_PTR;
  17. static struct anamix_pll *ana_pll = (struct anamix_pll *)ANATOP_BASE_ADDR;
  18. void enable_ocotp_clk(unsigned char enable)
  19. {
  20. clock_enable(CCGR_OCOTP, !!enable);
  21. }
  22. int enable_i2c_clk(unsigned char enable, unsigned i2c_num)
  23. {
  24. /* 0 - 3 is valid i2c num */
  25. if (i2c_num > 3)
  26. return -EINVAL;
  27. clock_enable(CCGR_I2C1 + i2c_num, !!enable);
  28. return 0;
  29. }
  30. #ifdef CONFIG_SPL_BUILD
  31. static struct imx_int_pll_rate_table imx8mm_fracpll_tbl[] = {
  32. PLL_1443X_RATE(1000000000U, 250, 3, 1, 0),
  33. PLL_1443X_RATE(800000000U, 300, 9, 0, 0),
  34. PLL_1443X_RATE(750000000U, 250, 8, 0, 0),
  35. PLL_1443X_RATE(650000000U, 325, 3, 2, 0),
  36. PLL_1443X_RATE(600000000U, 300, 3, 2, 0),
  37. PLL_1443X_RATE(594000000U, 99, 1, 2, 0),
  38. PLL_1443X_RATE(400000000U, 300, 9, 1, 0),
  39. PLL_1443X_RATE(266666667U, 400, 9, 2, 0),
  40. PLL_1443X_RATE(167000000U, 334, 3, 4, 0),
  41. PLL_1443X_RATE(100000000U, 300, 9, 3, 0),
  42. };
  43. static int fracpll_configure(enum pll_clocks pll, u32 freq)
  44. {
  45. int i;
  46. u32 tmp, div_val;
  47. void *pll_base;
  48. struct imx_int_pll_rate_table *rate;
  49. for (i = 0; i < ARRAY_SIZE(imx8mm_fracpll_tbl); i++) {
  50. if (freq == imx8mm_fracpll_tbl[i].rate)
  51. break;
  52. }
  53. if (i == ARRAY_SIZE(imx8mm_fracpll_tbl)) {
  54. printf("No matched freq table %u\n", freq);
  55. return -EINVAL;
  56. }
  57. rate = &imx8mm_fracpll_tbl[i];
  58. switch (pll) {
  59. case ANATOP_DRAM_PLL:
  60. setbits_le32(GPC_BASE_ADDR + 0xEC, 1 << 7);
  61. setbits_le32(GPC_BASE_ADDR + 0xF8, 1 << 5);
  62. writel(SRC_DDR1_ENABLE_MASK, SRC_BASE_ADDR + 0x1004);
  63. pll_base = &ana_pll->dram_pll_gnrl_ctl;
  64. break;
  65. case ANATOP_VIDEO_PLL:
  66. pll_base = &ana_pll->video_pll1_gnrl_ctl;
  67. break;
  68. default:
  69. return 0;
  70. }
  71. /* Bypass clock and set lock to pll output lock */
  72. tmp = readl(pll_base);
  73. tmp |= BYPASS_MASK;
  74. writel(tmp, pll_base);
  75. /* Enable RST */
  76. tmp &= ~RST_MASK;
  77. writel(tmp, pll_base);
  78. div_val = (rate->mdiv << MDIV_SHIFT) | (rate->pdiv << PDIV_SHIFT) |
  79. (rate->sdiv << SDIV_SHIFT);
  80. writel(div_val, pll_base + 4);
  81. writel(rate->kdiv << KDIV_SHIFT, pll_base + 8);
  82. __udelay(100);
  83. /* Disable RST */
  84. tmp |= RST_MASK;
  85. writel(tmp, pll_base);
  86. /* Wait Lock*/
  87. while (!(readl(pll_base) & LOCK_STATUS))
  88. ;
  89. /* Bypass */
  90. tmp &= ~BYPASS_MASK;
  91. writel(tmp, pll_base);
  92. return 0;
  93. }
  94. void dram_pll_init(ulong pll_val)
  95. {
  96. fracpll_configure(ANATOP_DRAM_PLL, pll_val);
  97. }
  98. static struct dram_bypass_clk_setting imx8mm_dram_bypass_tbl[] = {
  99. DRAM_BYPASS_ROOT_CONFIG(MHZ(100), 2, CLK_ROOT_PRE_DIV1, 2,
  100. CLK_ROOT_PRE_DIV2),
  101. DRAM_BYPASS_ROOT_CONFIG(MHZ(250), 3, CLK_ROOT_PRE_DIV2, 2,
  102. CLK_ROOT_PRE_DIV2),
  103. DRAM_BYPASS_ROOT_CONFIG(MHZ(400), 1, CLK_ROOT_PRE_DIV2, 3,
  104. CLK_ROOT_PRE_DIV2),
  105. };
  106. void dram_enable_bypass(ulong clk_val)
  107. {
  108. int i;
  109. struct dram_bypass_clk_setting *config;
  110. for (i = 0; i < ARRAY_SIZE(imx8mm_dram_bypass_tbl); i++) {
  111. if (clk_val == imx8mm_dram_bypass_tbl[i].clk)
  112. break;
  113. }
  114. if (i == ARRAY_SIZE(imx8mm_dram_bypass_tbl)) {
  115. printf("No matched freq table %lu\n", clk_val);
  116. return;
  117. }
  118. config = &imx8mm_dram_bypass_tbl[i];
  119. clock_set_target_val(DRAM_ALT_CLK_ROOT, CLK_ROOT_ON |
  120. CLK_ROOT_SOURCE_SEL(config->alt_root_sel) |
  121. CLK_ROOT_PRE_DIV(config->alt_pre_div));
  122. clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON |
  123. CLK_ROOT_SOURCE_SEL(config->apb_root_sel) |
  124. CLK_ROOT_PRE_DIV(config->apb_pre_div));
  125. clock_set_target_val(DRAM_SEL_CFG, CLK_ROOT_ON |
  126. CLK_ROOT_SOURCE_SEL(1));
  127. }
  128. void dram_disable_bypass(void)
  129. {
  130. clock_set_target_val(DRAM_SEL_CFG, CLK_ROOT_ON |
  131. CLK_ROOT_SOURCE_SEL(0));
  132. clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON |
  133. CLK_ROOT_SOURCE_SEL(4) |
  134. CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV5));
  135. }
  136. #endif
  137. void init_uart_clk(u32 index)
  138. {
  139. /*
  140. * set uart clock root
  141. * 24M OSC
  142. */
  143. switch (index) {
  144. case 0:
  145. clock_enable(CCGR_UART1, 0);
  146. clock_set_target_val(UART1_CLK_ROOT, CLK_ROOT_ON |
  147. CLK_ROOT_SOURCE_SEL(0));
  148. clock_enable(CCGR_UART1, 1);
  149. return;
  150. case 1:
  151. clock_enable(CCGR_UART2, 0);
  152. clock_set_target_val(UART2_CLK_ROOT, CLK_ROOT_ON |
  153. CLK_ROOT_SOURCE_SEL(0));
  154. clock_enable(CCGR_UART2, 1);
  155. return;
  156. case 2:
  157. clock_enable(CCGR_UART3, 0);
  158. clock_set_target_val(UART3_CLK_ROOT, CLK_ROOT_ON |
  159. CLK_ROOT_SOURCE_SEL(0));
  160. clock_enable(CCGR_UART3, 1);
  161. return;
  162. case 3:
  163. clock_enable(CCGR_UART4, 0);
  164. clock_set_target_val(UART4_CLK_ROOT, CLK_ROOT_ON |
  165. CLK_ROOT_SOURCE_SEL(0));
  166. clock_enable(CCGR_UART4, 1);
  167. return;
  168. default:
  169. printf("Invalid uart index\n");
  170. return;
  171. }
  172. }
  173. void init_wdog_clk(void)
  174. {
  175. clock_enable(CCGR_WDOG1, 0);
  176. clock_enable(CCGR_WDOG2, 0);
  177. clock_enable(CCGR_WDOG3, 0);
  178. clock_set_target_val(WDOG_CLK_ROOT, CLK_ROOT_ON |
  179. CLK_ROOT_SOURCE_SEL(0));
  180. clock_enable(CCGR_WDOG1, 1);
  181. clock_enable(CCGR_WDOG2, 1);
  182. clock_enable(CCGR_WDOG3, 1);
  183. }
  184. int clock_init(void)
  185. {
  186. u32 val_cfg0;
  187. /*
  188. * The gate is not exported to clk tree, so configure them here.
  189. * According to ANAMIX SPEC
  190. * sys pll1 fixed at 800MHz
  191. * sys pll2 fixed at 1GHz
  192. * Here we only enable the outputs.
  193. */
  194. val_cfg0 = readl(&ana_pll->sys_pll1_gnrl_ctl);
  195. val_cfg0 |= INTPLL_CLKE_MASK | INTPLL_DIV2_CLKE_MASK |
  196. INTPLL_DIV3_CLKE_MASK | INTPLL_DIV4_CLKE_MASK |
  197. INTPLL_DIV5_CLKE_MASK | INTPLL_DIV6_CLKE_MASK |
  198. INTPLL_DIV8_CLKE_MASK | INTPLL_DIV10_CLKE_MASK |
  199. INTPLL_DIV20_CLKE_MASK;
  200. writel(val_cfg0, &ana_pll->sys_pll1_gnrl_ctl);
  201. val_cfg0 = readl(&ana_pll->sys_pll2_gnrl_ctl);
  202. val_cfg0 |= INTPLL_CLKE_MASK | INTPLL_DIV2_CLKE_MASK |
  203. INTPLL_DIV3_CLKE_MASK | INTPLL_DIV4_CLKE_MASK |
  204. INTPLL_DIV5_CLKE_MASK | INTPLL_DIV6_CLKE_MASK |
  205. INTPLL_DIV8_CLKE_MASK | INTPLL_DIV10_CLKE_MASK |
  206. INTPLL_DIV20_CLKE_MASK;
  207. writel(val_cfg0, &ana_pll->sys_pll2_gnrl_ctl);
  208. /* config GIC to sys_pll2_100m */
  209. clock_enable(CCGR_GIC, 0);
  210. clock_set_target_val(GIC_CLK_ROOT, CLK_ROOT_ON |
  211. CLK_ROOT_SOURCE_SEL(3));
  212. clock_enable(CCGR_GIC, 1);
  213. clock_set_target_val(NAND_USDHC_BUS_CLK_ROOT, CLK_ROOT_ON |
  214. CLK_ROOT_SOURCE_SEL(1));
  215. clock_enable(CCGR_DDR1, 0);
  216. clock_set_target_val(DRAM_ALT_CLK_ROOT, CLK_ROOT_ON |
  217. CLK_ROOT_SOURCE_SEL(1));
  218. clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON |
  219. CLK_ROOT_SOURCE_SEL(1));
  220. clock_enable(CCGR_DDR1, 1);
  221. init_wdog_clk();
  222. clock_enable(CCGR_TEMP_SENSOR, 1);
  223. clock_enable(CCGR_SEC_DEBUG, 1);
  224. return 0;
  225. };
  226. u32 imx_get_uartclk(void)
  227. {
  228. return 24000000U;
  229. }
  230. static u32 decode_intpll(enum clk_root_src intpll)
  231. {
  232. u32 pll_gnrl_ctl, pll_div_ctl, pll_clke_mask;
  233. u32 main_div, pre_div, post_div, div;
  234. u64 freq;
  235. switch (intpll) {
  236. case ARM_PLL_CLK:
  237. pll_gnrl_ctl = readl(&ana_pll->arm_pll_gnrl_ctl);
  238. pll_div_ctl = readl(&ana_pll->arm_pll_div_ctl);
  239. break;
  240. case GPU_PLL_CLK:
  241. pll_gnrl_ctl = readl(&ana_pll->gpu_pll_gnrl_ctl);
  242. pll_div_ctl = readl(&ana_pll->gpu_pll_div_ctl);
  243. break;
  244. case VPU_PLL_CLK:
  245. pll_gnrl_ctl = readl(&ana_pll->vpu_pll_gnrl_ctl);
  246. pll_div_ctl = readl(&ana_pll->vpu_pll_div_ctl);
  247. break;
  248. case SYSTEM_PLL1_800M_CLK:
  249. case SYSTEM_PLL1_400M_CLK:
  250. case SYSTEM_PLL1_266M_CLK:
  251. case SYSTEM_PLL1_200M_CLK:
  252. case SYSTEM_PLL1_160M_CLK:
  253. case SYSTEM_PLL1_133M_CLK:
  254. case SYSTEM_PLL1_100M_CLK:
  255. case SYSTEM_PLL1_80M_CLK:
  256. case SYSTEM_PLL1_40M_CLK:
  257. pll_gnrl_ctl = readl(&ana_pll->sys_pll1_gnrl_ctl);
  258. pll_div_ctl = readl(&ana_pll->sys_pll1_div_ctl);
  259. break;
  260. case SYSTEM_PLL2_1000M_CLK:
  261. case SYSTEM_PLL2_500M_CLK:
  262. case SYSTEM_PLL2_333M_CLK:
  263. case SYSTEM_PLL2_250M_CLK:
  264. case SYSTEM_PLL2_200M_CLK:
  265. case SYSTEM_PLL2_166M_CLK:
  266. case SYSTEM_PLL2_125M_CLK:
  267. case SYSTEM_PLL2_100M_CLK:
  268. case SYSTEM_PLL2_50M_CLK:
  269. pll_gnrl_ctl = readl(&ana_pll->sys_pll2_gnrl_ctl);
  270. pll_div_ctl = readl(&ana_pll->sys_pll2_div_ctl);
  271. break;
  272. case SYSTEM_PLL3_CLK:
  273. pll_gnrl_ctl = readl(&ana_pll->sys_pll3_gnrl_ctl);
  274. pll_div_ctl = readl(&ana_pll->sys_pll3_div_ctl);
  275. break;
  276. default:
  277. return -EINVAL;
  278. }
  279. /* Only support SYS_XTAL 24M, PAD_CLK not take into consideration */
  280. if ((pll_gnrl_ctl & INTPLL_REF_CLK_SEL_MASK) != 0)
  281. return 0;
  282. if ((pll_gnrl_ctl & INTPLL_RST_MASK) == 0)
  283. return 0;
  284. /*
  285. * When BYPASS is equal to 1, PLL enters the bypass mode
  286. * regardless of the values of RESETB
  287. */
  288. if (pll_gnrl_ctl & INTPLL_BYPASS_MASK)
  289. return 24000000u;
  290. if (!(pll_gnrl_ctl & INTPLL_LOCK_MASK)) {
  291. puts("pll not locked\n");
  292. return 0;
  293. }
  294. switch (intpll) {
  295. case ARM_PLL_CLK:
  296. case GPU_PLL_CLK:
  297. case VPU_PLL_CLK:
  298. case SYSTEM_PLL3_CLK:
  299. case SYSTEM_PLL1_800M_CLK:
  300. case SYSTEM_PLL2_1000M_CLK:
  301. pll_clke_mask = INTPLL_CLKE_MASK;
  302. div = 1;
  303. break;
  304. case SYSTEM_PLL1_400M_CLK:
  305. case SYSTEM_PLL2_500M_CLK:
  306. pll_clke_mask = INTPLL_DIV2_CLKE_MASK;
  307. div = 2;
  308. break;
  309. case SYSTEM_PLL1_266M_CLK:
  310. case SYSTEM_PLL2_333M_CLK:
  311. pll_clke_mask = INTPLL_DIV3_CLKE_MASK;
  312. div = 3;
  313. break;
  314. case SYSTEM_PLL1_200M_CLK:
  315. case SYSTEM_PLL2_250M_CLK:
  316. pll_clke_mask = INTPLL_DIV4_CLKE_MASK;
  317. div = 4;
  318. break;
  319. case SYSTEM_PLL1_160M_CLK:
  320. case SYSTEM_PLL2_200M_CLK:
  321. pll_clke_mask = INTPLL_DIV5_CLKE_MASK;
  322. div = 5;
  323. break;
  324. case SYSTEM_PLL1_133M_CLK:
  325. case SYSTEM_PLL2_166M_CLK:
  326. pll_clke_mask = INTPLL_DIV6_CLKE_MASK;
  327. div = 6;
  328. break;
  329. case SYSTEM_PLL1_100M_CLK:
  330. case SYSTEM_PLL2_125M_CLK:
  331. pll_clke_mask = INTPLL_DIV8_CLKE_MASK;
  332. div = 8;
  333. break;
  334. case SYSTEM_PLL1_80M_CLK:
  335. case SYSTEM_PLL2_100M_CLK:
  336. pll_clke_mask = INTPLL_DIV10_CLKE_MASK;
  337. div = 10;
  338. break;
  339. case SYSTEM_PLL1_40M_CLK:
  340. case SYSTEM_PLL2_50M_CLK:
  341. pll_clke_mask = INTPLL_DIV20_CLKE_MASK;
  342. div = 20;
  343. break;
  344. default:
  345. return -EINVAL;
  346. }
  347. if ((pll_gnrl_ctl & pll_clke_mask) == 0)
  348. return 0;
  349. main_div = (pll_div_ctl & INTPLL_MAIN_DIV_MASK) >>
  350. INTPLL_MAIN_DIV_SHIFT;
  351. pre_div = (pll_div_ctl & INTPLL_PRE_DIV_MASK) >>
  352. INTPLL_PRE_DIV_SHIFT;
  353. post_div = (pll_div_ctl & INTPLL_POST_DIV_MASK) >>
  354. INTPLL_POST_DIV_SHIFT;
  355. /* FFVCO = (m * FFIN) / p, FFOUT = (m * FFIN) / (p * 2^s) */
  356. freq = 24000000ULL * main_div;
  357. return lldiv(freq, pre_div * (1 << post_div) * div);
  358. }
  359. static u32 decode_fracpll(enum clk_root_src frac_pll)
  360. {
  361. u32 pll_gnrl_ctl, pll_fdiv_ctl0, pll_fdiv_ctl1;
  362. u32 main_div, pre_div, post_div, k;
  363. switch (frac_pll) {
  364. case DRAM_PLL1_CLK:
  365. pll_gnrl_ctl = readl(&ana_pll->dram_pll_gnrl_ctl);
  366. pll_fdiv_ctl0 = readl(&ana_pll->dram_pll_fdiv_ctl0);
  367. pll_fdiv_ctl1 = readl(&ana_pll->dram_pll_fdiv_ctl1);
  368. break;
  369. case AUDIO_PLL1_CLK:
  370. pll_gnrl_ctl = readl(&ana_pll->audio_pll1_gnrl_ctl);
  371. pll_fdiv_ctl0 = readl(&ana_pll->audio_pll1_fdiv_ctl0);
  372. pll_fdiv_ctl1 = readl(&ana_pll->audio_pll1_fdiv_ctl1);
  373. break;
  374. case AUDIO_PLL2_CLK:
  375. pll_gnrl_ctl = readl(&ana_pll->audio_pll2_gnrl_ctl);
  376. pll_fdiv_ctl0 = readl(&ana_pll->audio_pll2_fdiv_ctl0);
  377. pll_fdiv_ctl1 = readl(&ana_pll->audio_pll2_fdiv_ctl1);
  378. break;
  379. case VIDEO_PLL_CLK:
  380. pll_gnrl_ctl = readl(&ana_pll->video_pll1_gnrl_ctl);
  381. pll_fdiv_ctl0 = readl(&ana_pll->video_pll1_fdiv_ctl0);
  382. pll_fdiv_ctl1 = readl(&ana_pll->video_pll1_fdiv_ctl1);
  383. break;
  384. default:
  385. printf("Not supported\n");
  386. return 0;
  387. }
  388. /* Only support SYS_XTAL 24M, PAD_CLK not take into consideration */
  389. if ((pll_gnrl_ctl & GENMASK(1, 0)) != 0)
  390. return 0;
  391. if ((pll_gnrl_ctl & RST_MASK) == 0)
  392. return 0;
  393. /*
  394. * When BYPASS is equal to 1, PLL enters the bypass mode
  395. * regardless of the values of RESETB
  396. */
  397. if (pll_gnrl_ctl & BYPASS_MASK)
  398. return 24000000u;
  399. if (!(pll_gnrl_ctl & LOCK_STATUS)) {
  400. puts("pll not locked\n");
  401. return 0;
  402. }
  403. if (!(pll_gnrl_ctl & CLKE_MASK))
  404. return 0;
  405. main_div = (pll_fdiv_ctl0 & MDIV_MASK) >>
  406. MDIV_SHIFT;
  407. pre_div = (pll_fdiv_ctl0 & PDIV_MASK) >>
  408. PDIV_SHIFT;
  409. post_div = (pll_fdiv_ctl0 & SDIV_MASK) >>
  410. SDIV_SHIFT;
  411. k = pll_fdiv_ctl1 & KDIV_MASK;
  412. return lldiv((main_div * 65536 + k) * 24000000ULL,
  413. 65536 * pre_div * (1 << post_div));
  414. }
  415. static u32 get_root_src_clk(enum clk_root_src root_src)
  416. {
  417. switch (root_src) {
  418. case OSC_24M_CLK:
  419. return 24000000u;
  420. case OSC_HDMI_CLK:
  421. return 26000000u;
  422. case OSC_32K_CLK:
  423. return 32000u;
  424. case ARM_PLL_CLK:
  425. case GPU_PLL_CLK:
  426. case VPU_PLL_CLK:
  427. case SYSTEM_PLL1_800M_CLK:
  428. case SYSTEM_PLL1_400M_CLK:
  429. case SYSTEM_PLL1_266M_CLK:
  430. case SYSTEM_PLL1_200M_CLK:
  431. case SYSTEM_PLL1_160M_CLK:
  432. case SYSTEM_PLL1_133M_CLK:
  433. case SYSTEM_PLL1_100M_CLK:
  434. case SYSTEM_PLL1_80M_CLK:
  435. case SYSTEM_PLL1_40M_CLK:
  436. case SYSTEM_PLL2_1000M_CLK:
  437. case SYSTEM_PLL2_500M_CLK:
  438. case SYSTEM_PLL2_333M_CLK:
  439. case SYSTEM_PLL2_250M_CLK:
  440. case SYSTEM_PLL2_200M_CLK:
  441. case SYSTEM_PLL2_166M_CLK:
  442. case SYSTEM_PLL2_125M_CLK:
  443. case SYSTEM_PLL2_100M_CLK:
  444. case SYSTEM_PLL2_50M_CLK:
  445. case SYSTEM_PLL3_CLK:
  446. return decode_intpll(root_src);
  447. case DRAM_PLL1_CLK:
  448. case AUDIO_PLL1_CLK:
  449. case AUDIO_PLL2_CLK:
  450. case VIDEO_PLL_CLK:
  451. return decode_fracpll(root_src);
  452. default:
  453. return 0;
  454. }
  455. return 0;
  456. }
  457. static u32 get_root_clk(enum clk_root_index clock_id)
  458. {
  459. enum clk_root_src root_src;
  460. u32 post_podf, pre_podf, root_src_clk;
  461. if (clock_root_enabled(clock_id) <= 0)
  462. return 0;
  463. if (clock_get_prediv(clock_id, &pre_podf) < 0)
  464. return 0;
  465. if (clock_get_postdiv(clock_id, &post_podf) < 0)
  466. return 0;
  467. if (clock_get_src(clock_id, &root_src) < 0)
  468. return 0;
  469. root_src_clk = get_root_src_clk(root_src);
  470. return root_src_clk / (post_podf + 1) / (pre_podf + 1);
  471. }
  472. u32 mxc_get_clock(enum mxc_clock clk)
  473. {
  474. u32 val;
  475. switch (clk) {
  476. case MXC_ARM_CLK:
  477. return get_root_clk(ARM_A53_CLK_ROOT);
  478. case MXC_IPG_CLK:
  479. clock_get_target_val(IPG_CLK_ROOT, &val);
  480. val = val & 0x3;
  481. return get_root_clk(AHB_CLK_ROOT) / 2 / (val + 1);
  482. case MXC_CSPI_CLK:
  483. return get_root_clk(ECSPI1_CLK_ROOT);
  484. case MXC_ESDHC_CLK:
  485. return get_root_clk(USDHC1_CLK_ROOT);
  486. case MXC_ESDHC2_CLK:
  487. return get_root_clk(USDHC2_CLK_ROOT);
  488. case MXC_ESDHC3_CLK:
  489. return get_root_clk(USDHC3_CLK_ROOT);
  490. case MXC_I2C_CLK:
  491. return get_root_clk(I2C1_CLK_ROOT);
  492. case MXC_UART_CLK:
  493. return get_root_clk(UART1_CLK_ROOT);
  494. case MXC_QSPI_CLK:
  495. return get_root_clk(QSPI_CLK_ROOT);
  496. default:
  497. printf("Unsupported mxc_clock %d\n", clk);
  498. break;
  499. }
  500. return 0;
  501. }
  502. #ifdef CONFIG_FEC_MXC
  503. int set_clk_enet(enum enet_freq type)
  504. {
  505. u32 target;
  506. u32 enet1_ref;
  507. switch (type) {
  508. case ENET_125MHZ:
  509. enet1_ref = ENET1_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_125M_CLK;
  510. break;
  511. case ENET_50MHZ:
  512. enet1_ref = ENET1_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_50M_CLK;
  513. break;
  514. case ENET_25MHZ:
  515. enet1_ref = ENET1_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_25M_CLK;
  516. break;
  517. default:
  518. return -EINVAL;
  519. }
  520. /* disable the clock first */
  521. clock_enable(CCGR_ENET1, 0);
  522. clock_enable(CCGR_SIM_ENET, 0);
  523. /* set enet axi clock 266Mhz */
  524. target = CLK_ROOT_ON | ENET_AXI_CLK_ROOT_FROM_SYS1_PLL_266M |
  525. CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV1) |
  526. CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV1);
  527. clock_set_target_val(ENET_AXI_CLK_ROOT, target);
  528. target = CLK_ROOT_ON | enet1_ref |
  529. CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV1) |
  530. CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV1);
  531. clock_set_target_val(ENET_REF_CLK_ROOT, target);
  532. target = CLK_ROOT_ON |
  533. ENET1_TIME_CLK_ROOT_FROM_PLL_ENET_MAIN_100M_CLK |
  534. CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV1) |
  535. CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV4);
  536. clock_set_target_val(ENET_TIMER_CLK_ROOT, target);
  537. /* enable clock */
  538. clock_enable(CCGR_SIM_ENET, 1);
  539. clock_enable(CCGR_ENET1, 1);
  540. return 0;
  541. }
  542. #endif