clock_manager_s10.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2016-2018 Intel Corporation <www.intel.com>
  4. *
  5. */
  6. #include <common.h>
  7. #include <asm/io.h>
  8. #include <asm/arch/clock_manager.h>
  9. #include <asm/arch/handoff_s10.h>
  10. #include <asm/arch/system_manager.h>
  11. DECLARE_GLOBAL_DATA_PTR;
  12. static const struct socfpga_clock_manager *clock_manager_base =
  13. (struct socfpga_clock_manager *)SOCFPGA_CLKMGR_ADDRESS;
  14. static const struct socfpga_system_manager *sysmgr_regs =
  15. (struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS;
  16. /*
  17. * function to write the bypass register which requires a poll of the
  18. * busy bit
  19. */
  20. static void cm_write_bypass_mainpll(u32 val)
  21. {
  22. writel(val, &clock_manager_base->main_pll.bypass);
  23. cm_wait_for_fsm();
  24. }
  25. static void cm_write_bypass_perpll(u32 val)
  26. {
  27. writel(val, &clock_manager_base->per_pll.bypass);
  28. cm_wait_for_fsm();
  29. }
  30. /* function to write the ctrl register which requires a poll of the busy bit */
  31. static void cm_write_ctrl(u32 val)
  32. {
  33. writel(val, &clock_manager_base->ctrl);
  34. cm_wait_for_fsm();
  35. }
  36. /*
  37. * Setup clocks while making no assumptions about previous state of the clocks.
  38. */
  39. void cm_basic_init(const struct cm_config * const cfg)
  40. {
  41. u32 mdiv, refclkdiv, mscnt, hscnt, vcocalib;
  42. if (cfg == 0)
  43. return;
  44. /* Put all plls in bypass */
  45. cm_write_bypass_mainpll(CLKMGR_BYPASS_MAINPLL_ALL);
  46. cm_write_bypass_perpll(CLKMGR_BYPASS_PERPLL_ALL);
  47. /* setup main PLL dividers where calculate the vcocalib value */
  48. mdiv = (cfg->main_pll_fdbck >> CLKMGR_FDBCK_MDIV_OFFSET) &
  49. CLKMGR_FDBCK_MDIV_MASK;
  50. refclkdiv = (cfg->main_pll_pllglob >> CLKMGR_PLLGLOB_REFCLKDIV_OFFSET) &
  51. CLKMGR_PLLGLOB_REFCLKDIV_MASK;
  52. mscnt = CLKMGR_MSCNT_CONST / (CLKMGR_MDIV_CONST + mdiv) / refclkdiv;
  53. hscnt = (mdiv + CLKMGR_MDIV_CONST) * mscnt / refclkdiv -
  54. CLKMGR_HSCNT_CONST;
  55. vcocalib = (hscnt & CLKMGR_VCOCALIB_HSCNT_MASK) |
  56. ((mscnt & CLKMGR_VCOCALIB_MSCNT_MASK) <<
  57. CLKMGR_VCOCALIB_MSCNT_OFFSET);
  58. writel((cfg->main_pll_pllglob & ~CLKMGR_PLLGLOB_PD_MASK &
  59. ~CLKMGR_PLLGLOB_RST_MASK),
  60. &clock_manager_base->main_pll.pllglob);
  61. writel(cfg->main_pll_fdbck, &clock_manager_base->main_pll.fdbck);
  62. writel(vcocalib, &clock_manager_base->main_pll.vcocalib);
  63. writel(cfg->main_pll_pllc0, &clock_manager_base->main_pll.pllc0);
  64. writel(cfg->main_pll_pllc1, &clock_manager_base->main_pll.pllc1);
  65. writel(cfg->main_pll_nocdiv, &clock_manager_base->main_pll.nocdiv);
  66. /* setup peripheral PLL dividers */
  67. /* calculate the vcocalib value */
  68. mdiv = (cfg->per_pll_fdbck >> CLKMGR_FDBCK_MDIV_OFFSET) &
  69. CLKMGR_FDBCK_MDIV_MASK;
  70. refclkdiv = (cfg->per_pll_pllglob >> CLKMGR_PLLGLOB_REFCLKDIV_OFFSET) &
  71. CLKMGR_PLLGLOB_REFCLKDIV_MASK;
  72. mscnt = CLKMGR_MSCNT_CONST / (CLKMGR_MDIV_CONST + mdiv) / refclkdiv;
  73. hscnt = (mdiv + CLKMGR_MDIV_CONST) * mscnt / refclkdiv -
  74. CLKMGR_HSCNT_CONST;
  75. vcocalib = (hscnt & CLKMGR_VCOCALIB_HSCNT_MASK) |
  76. ((mscnt & CLKMGR_VCOCALIB_MSCNT_MASK) <<
  77. CLKMGR_VCOCALIB_MSCNT_OFFSET);
  78. writel((cfg->per_pll_pllglob & ~CLKMGR_PLLGLOB_PD_MASK &
  79. ~CLKMGR_PLLGLOB_RST_MASK),
  80. &clock_manager_base->per_pll.pllglob);
  81. writel(cfg->per_pll_fdbck, &clock_manager_base->per_pll.fdbck);
  82. writel(vcocalib, &clock_manager_base->per_pll.vcocalib);
  83. writel(cfg->per_pll_pllc0, &clock_manager_base->per_pll.pllc0);
  84. writel(cfg->per_pll_pllc1, &clock_manager_base->per_pll.pllc1);
  85. writel(cfg->per_pll_emacctl, &clock_manager_base->per_pll.emacctl);
  86. writel(cfg->per_pll_gpiodiv, &clock_manager_base->per_pll.gpiodiv);
  87. /* Take both PLL out of reset and power up */
  88. setbits_le32(&clock_manager_base->main_pll.pllglob,
  89. CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK);
  90. setbits_le32(&clock_manager_base->per_pll.pllglob,
  91. CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK);
  92. #define LOCKED_MASK \
  93. (CLKMGR_STAT_MAINPLL_LOCKED | \
  94. CLKMGR_STAT_PERPLL_LOCKED)
  95. cm_wait_for_lock(LOCKED_MASK);
  96. /*
  97. * Dividers for C2 to C9 only init after PLLs are lock. As dividers
  98. * only take effect upon value change, we shall set a maximum value as
  99. * default value.
  100. */
  101. writel(0xff, &clock_manager_base->main_pll.mpuclk);
  102. writel(0xff, &clock_manager_base->main_pll.nocclk);
  103. writel(0xff, &clock_manager_base->main_pll.cntr2clk);
  104. writel(0xff, &clock_manager_base->main_pll.cntr3clk);
  105. writel(0xff, &clock_manager_base->main_pll.cntr4clk);
  106. writel(0xff, &clock_manager_base->main_pll.cntr5clk);
  107. writel(0xff, &clock_manager_base->main_pll.cntr6clk);
  108. writel(0xff, &clock_manager_base->main_pll.cntr7clk);
  109. writel(0xff, &clock_manager_base->main_pll.cntr8clk);
  110. writel(0xff, &clock_manager_base->main_pll.cntr9clk);
  111. writel(0xff, &clock_manager_base->per_pll.cntr2clk);
  112. writel(0xff, &clock_manager_base->per_pll.cntr3clk);
  113. writel(0xff, &clock_manager_base->per_pll.cntr4clk);
  114. writel(0xff, &clock_manager_base->per_pll.cntr5clk);
  115. writel(0xff, &clock_manager_base->per_pll.cntr6clk);
  116. writel(0xff, &clock_manager_base->per_pll.cntr7clk);
  117. writel(0xff, &clock_manager_base->per_pll.cntr8clk);
  118. writel(0xff, &clock_manager_base->per_pll.cntr9clk);
  119. writel(cfg->main_pll_mpuclk, &clock_manager_base->main_pll.mpuclk);
  120. writel(cfg->main_pll_nocclk, &clock_manager_base->main_pll.nocclk);
  121. writel(cfg->main_pll_cntr2clk, &clock_manager_base->main_pll.cntr2clk);
  122. writel(cfg->main_pll_cntr3clk, &clock_manager_base->main_pll.cntr3clk);
  123. writel(cfg->main_pll_cntr4clk, &clock_manager_base->main_pll.cntr4clk);
  124. writel(cfg->main_pll_cntr5clk, &clock_manager_base->main_pll.cntr5clk);
  125. writel(cfg->main_pll_cntr6clk, &clock_manager_base->main_pll.cntr6clk);
  126. writel(cfg->main_pll_cntr7clk, &clock_manager_base->main_pll.cntr7clk);
  127. writel(cfg->main_pll_cntr8clk, &clock_manager_base->main_pll.cntr8clk);
  128. writel(cfg->main_pll_cntr9clk, &clock_manager_base->main_pll.cntr9clk);
  129. writel(cfg->per_pll_cntr2clk, &clock_manager_base->per_pll.cntr2clk);
  130. writel(cfg->per_pll_cntr3clk, &clock_manager_base->per_pll.cntr3clk);
  131. writel(cfg->per_pll_cntr4clk, &clock_manager_base->per_pll.cntr4clk);
  132. writel(cfg->per_pll_cntr5clk, &clock_manager_base->per_pll.cntr5clk);
  133. writel(cfg->per_pll_cntr6clk, &clock_manager_base->per_pll.cntr6clk);
  134. writel(cfg->per_pll_cntr7clk, &clock_manager_base->per_pll.cntr7clk);
  135. writel(cfg->per_pll_cntr8clk, &clock_manager_base->per_pll.cntr8clk);
  136. writel(cfg->per_pll_cntr9clk, &clock_manager_base->per_pll.cntr9clk);
  137. /* Take all PLLs out of bypass */
  138. cm_write_bypass_mainpll(0);
  139. cm_write_bypass_perpll(0);
  140. /* clear safe mode / out of boot mode */
  141. cm_write_ctrl(readl(&clock_manager_base->ctrl)
  142. & ~(CLKMGR_CTRL_SAFEMODE));
  143. /* Now ungate non-hw-managed clocks */
  144. writel(~0, &clock_manager_base->main_pll.en);
  145. writel(~0, &clock_manager_base->per_pll.en);
  146. /* Clear the loss of lock bits (write 1 to clear) */
  147. writel(CLKMGR_INTER_PERPLLLOST_MASK | CLKMGR_INTER_MAINPLLLOST_MASK,
  148. &clock_manager_base->intrclr);
  149. }
  150. static unsigned long cm_get_main_vco_clk_hz(void)
  151. {
  152. unsigned long fref, refdiv, mdiv, reg, vco;
  153. reg = readl(&clock_manager_base->main_pll.pllglob);
  154. fref = (reg >> CLKMGR_PLLGLOB_VCO_PSRC_OFFSET) &
  155. CLKMGR_PLLGLOB_VCO_PSRC_MASK;
  156. switch (fref) {
  157. case CLKMGR_VCO_PSRC_EOSC1:
  158. fref = cm_get_osc_clk_hz();
  159. break;
  160. case CLKMGR_VCO_PSRC_INTOSC:
  161. fref = cm_get_intosc_clk_hz();
  162. break;
  163. case CLKMGR_VCO_PSRC_F2S:
  164. fref = cm_get_fpga_clk_hz();
  165. break;
  166. }
  167. refdiv = (reg >> CLKMGR_PLLGLOB_REFCLKDIV_OFFSET) &
  168. CLKMGR_PLLGLOB_REFCLKDIV_MASK;
  169. reg = readl(&clock_manager_base->main_pll.fdbck);
  170. mdiv = (reg >> CLKMGR_FDBCK_MDIV_OFFSET) & CLKMGR_FDBCK_MDIV_MASK;
  171. vco = fref / refdiv;
  172. vco = vco * (CLKMGR_MDIV_CONST + mdiv);
  173. return vco;
  174. }
  175. static unsigned long cm_get_per_vco_clk_hz(void)
  176. {
  177. unsigned long fref, refdiv, mdiv, reg, vco;
  178. reg = readl(&clock_manager_base->per_pll.pllglob);
  179. fref = (reg >> CLKMGR_PLLGLOB_VCO_PSRC_OFFSET) &
  180. CLKMGR_PLLGLOB_VCO_PSRC_MASK;
  181. switch (fref) {
  182. case CLKMGR_VCO_PSRC_EOSC1:
  183. fref = cm_get_osc_clk_hz();
  184. break;
  185. case CLKMGR_VCO_PSRC_INTOSC:
  186. fref = cm_get_intosc_clk_hz();
  187. break;
  188. case CLKMGR_VCO_PSRC_F2S:
  189. fref = cm_get_fpga_clk_hz();
  190. break;
  191. }
  192. refdiv = (reg >> CLKMGR_PLLGLOB_REFCLKDIV_OFFSET) &
  193. CLKMGR_PLLGLOB_REFCLKDIV_MASK;
  194. reg = readl(&clock_manager_base->per_pll.fdbck);
  195. mdiv = (reg >> CLKMGR_FDBCK_MDIV_OFFSET) & CLKMGR_FDBCK_MDIV_MASK;
  196. vco = fref / refdiv;
  197. vco = vco * (CLKMGR_MDIV_CONST + mdiv);
  198. return vco;
  199. }
  200. unsigned long cm_get_mpu_clk_hz(void)
  201. {
  202. unsigned long clock = readl(&clock_manager_base->main_pll.mpuclk);
  203. clock = (clock >> CLKMGR_CLKSRC_OFFSET) & CLKMGR_CLKSRC_MASK;
  204. switch (clock) {
  205. case CLKMGR_CLKSRC_MAIN:
  206. clock = cm_get_main_vco_clk_hz();
  207. clock /= (readl(&clock_manager_base->main_pll.pllc0) &
  208. CLKMGR_PLLC0_DIV_MASK);
  209. break;
  210. case CLKMGR_CLKSRC_PER:
  211. clock = cm_get_per_vco_clk_hz();
  212. clock /= (readl(&clock_manager_base->per_pll.pllc0) &
  213. CLKMGR_CLKCNT_MSK);
  214. break;
  215. case CLKMGR_CLKSRC_OSC1:
  216. clock = cm_get_osc_clk_hz();
  217. break;
  218. case CLKMGR_CLKSRC_INTOSC:
  219. clock = cm_get_intosc_clk_hz();
  220. break;
  221. case CLKMGR_CLKSRC_FPGA:
  222. clock = cm_get_fpga_clk_hz();
  223. break;
  224. }
  225. clock /= 1 + (readl(&clock_manager_base->main_pll.mpuclk) &
  226. CLKMGR_CLKCNT_MSK);
  227. return clock;
  228. }
  229. unsigned int cm_get_l3_main_clk_hz(void)
  230. {
  231. u32 clock = readl(&clock_manager_base->main_pll.nocclk);
  232. clock = (clock >> CLKMGR_CLKSRC_OFFSET) & CLKMGR_CLKSRC_MASK;
  233. switch (clock) {
  234. case CLKMGR_CLKSRC_MAIN:
  235. clock = cm_get_main_vco_clk_hz();
  236. clock /= (readl(&clock_manager_base->main_pll.pllc1) &
  237. CLKMGR_PLLC0_DIV_MASK);
  238. break;
  239. case CLKMGR_CLKSRC_PER:
  240. clock = cm_get_per_vco_clk_hz();
  241. clock /= (readl(&clock_manager_base->per_pll.pllc1) &
  242. CLKMGR_CLKCNT_MSK);
  243. break;
  244. case CLKMGR_CLKSRC_OSC1:
  245. clock = cm_get_osc_clk_hz();
  246. break;
  247. case CLKMGR_CLKSRC_INTOSC:
  248. clock = cm_get_intosc_clk_hz();
  249. break;
  250. case CLKMGR_CLKSRC_FPGA:
  251. clock = cm_get_fpga_clk_hz();
  252. break;
  253. }
  254. clock /= 1 + (readl(&clock_manager_base->main_pll.nocclk) &
  255. CLKMGR_CLKCNT_MSK);
  256. return clock;
  257. }
  258. unsigned int cm_get_mmc_controller_clk_hz(void)
  259. {
  260. u32 clock = readl(&clock_manager_base->per_pll.cntr6clk);
  261. clock = (clock >> CLKMGR_CLKSRC_OFFSET) & CLKMGR_CLKSRC_MASK;
  262. switch (clock) {
  263. case CLKMGR_CLKSRC_MAIN:
  264. clock = cm_get_l3_main_clk_hz();
  265. clock /= 1 + (readl(&clock_manager_base->main_pll.cntr6clk) &
  266. CLKMGR_CLKCNT_MSK);
  267. break;
  268. case CLKMGR_CLKSRC_PER:
  269. clock = cm_get_l3_main_clk_hz();
  270. clock /= 1 + (readl(&clock_manager_base->per_pll.cntr6clk) &
  271. CLKMGR_CLKCNT_MSK);
  272. break;
  273. case CLKMGR_CLKSRC_OSC1:
  274. clock = cm_get_osc_clk_hz();
  275. break;
  276. case CLKMGR_CLKSRC_INTOSC:
  277. clock = cm_get_intosc_clk_hz();
  278. break;
  279. case CLKMGR_CLKSRC_FPGA:
  280. clock = cm_get_fpga_clk_hz();
  281. break;
  282. }
  283. return clock / 4;
  284. }
  285. unsigned int cm_get_l4_sp_clk_hz(void)
  286. {
  287. u32 clock = cm_get_l3_main_clk_hz();
  288. clock /= (1 << ((readl(&clock_manager_base->main_pll.nocdiv) >>
  289. CLKMGR_NOCDIV_L4SPCLK_OFFSET) & CLKMGR_CLKCNT_MSK));
  290. return clock;
  291. }
  292. unsigned int cm_get_qspi_controller_clk_hz(void)
  293. {
  294. return readl(&sysmgr_regs->boot_scratch_cold0);
  295. }
  296. unsigned int cm_get_spi_controller_clk_hz(void)
  297. {
  298. u32 clock = cm_get_l3_main_clk_hz();
  299. clock /= (1 << ((readl(&clock_manager_base->main_pll.nocdiv) >>
  300. CLKMGR_NOCDIV_L4MAIN_OFFSET) & CLKMGR_CLKCNT_MSK));
  301. return clock;
  302. }
  303. unsigned int cm_get_l4_sys_free_clk_hz(void)
  304. {
  305. return cm_get_l3_main_clk_hz() / 4;
  306. }
  307. void cm_print_clock_quick_summary(void)
  308. {
  309. printf("MPU %d kHz\n", (u32)(cm_get_mpu_clk_hz() / 1000));
  310. printf("L3 main %d kHz\n", cm_get_l3_main_clk_hz() / 1000);
  311. printf("Main VCO %d kHz\n", (u32)(cm_get_main_vco_clk_hz() / 1000));
  312. printf("Per VCO %d kHz\n", (u32)(cm_get_per_vco_clk_hz() / 1000));
  313. printf("EOSC1 %d kHz\n", cm_get_osc_clk_hz() / 1000);
  314. printf("HPS MMC %d kHz\n", cm_get_mmc_controller_clk_hz() / 1000);
  315. printf("UART %d kHz\n", cm_get_l4_sp_clk_hz() / 1000);
  316. }