clock_manager_arria10.c 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2016-2017 Intel Corporation
  4. */
  5. #include <common.h>
  6. #include <fdtdec.h>
  7. #include <malloc.h>
  8. #include <asm/io.h>
  9. #include <dm.h>
  10. #include <clk.h>
  11. #include <dm/device-internal.h>
  12. #include <asm/arch/clock_manager.h>
  13. #ifdef CONFIG_SPL_BUILD
  14. static u32 eosc1_hz;
  15. static u32 cb_intosc_hz;
  16. static u32 f2s_free_hz;
  17. struct mainpll_cfg {
  18. u32 vco0_psrc;
  19. u32 vco1_denom;
  20. u32 vco1_numer;
  21. u32 mpuclk;
  22. u32 mpuclk_cnt;
  23. u32 mpuclk_src;
  24. u32 nocclk;
  25. u32 nocclk_cnt;
  26. u32 nocclk_src;
  27. u32 cntr2clk_cnt;
  28. u32 cntr3clk_cnt;
  29. u32 cntr4clk_cnt;
  30. u32 cntr5clk_cnt;
  31. u32 cntr6clk_cnt;
  32. u32 cntr7clk_cnt;
  33. u32 cntr7clk_src;
  34. u32 cntr8clk_cnt;
  35. u32 cntr9clk_cnt;
  36. u32 cntr9clk_src;
  37. u32 cntr15clk_cnt;
  38. u32 nocdiv_l4mainclk;
  39. u32 nocdiv_l4mpclk;
  40. u32 nocdiv_l4spclk;
  41. u32 nocdiv_csatclk;
  42. u32 nocdiv_cstraceclk;
  43. u32 nocdiv_cspdbclk;
  44. };
  45. struct perpll_cfg {
  46. u32 vco0_psrc;
  47. u32 vco1_denom;
  48. u32 vco1_numer;
  49. u32 cntr2clk_cnt;
  50. u32 cntr2clk_src;
  51. u32 cntr3clk_cnt;
  52. u32 cntr3clk_src;
  53. u32 cntr4clk_cnt;
  54. u32 cntr4clk_src;
  55. u32 cntr5clk_cnt;
  56. u32 cntr5clk_src;
  57. u32 cntr6clk_cnt;
  58. u32 cntr6clk_src;
  59. u32 cntr7clk_cnt;
  60. u32 cntr8clk_cnt;
  61. u32 cntr8clk_src;
  62. u32 cntr9clk_cnt;
  63. u32 cntr9clk_src;
  64. u32 emacctl_emac0sel;
  65. u32 emacctl_emac1sel;
  66. u32 emacctl_emac2sel;
  67. u32 gpiodiv_gpiodbclk;
  68. };
  69. struct strtou32 {
  70. const char *str;
  71. const u32 val;
  72. };
  73. static const struct strtou32 mainpll_cfg_tab[] = {
  74. { "vco0-psrc", offsetof(struct mainpll_cfg, vco0_psrc) },
  75. { "vco1-denom", offsetof(struct mainpll_cfg, vco1_denom) },
  76. { "vco1-numer", offsetof(struct mainpll_cfg, vco1_numer) },
  77. { "mpuclk-cnt", offsetof(struct mainpll_cfg, mpuclk_cnt) },
  78. { "mpuclk-src", offsetof(struct mainpll_cfg, mpuclk_src) },
  79. { "nocclk-cnt", offsetof(struct mainpll_cfg, nocclk_cnt) },
  80. { "nocclk-src", offsetof(struct mainpll_cfg, nocclk_src) },
  81. { "cntr2clk-cnt", offsetof(struct mainpll_cfg, cntr2clk_cnt) },
  82. { "cntr3clk-cnt", offsetof(struct mainpll_cfg, cntr3clk_cnt) },
  83. { "cntr4clk-cnt", offsetof(struct mainpll_cfg, cntr4clk_cnt) },
  84. { "cntr5clk-cnt", offsetof(struct mainpll_cfg, cntr5clk_cnt) },
  85. { "cntr6clk-cnt", offsetof(struct mainpll_cfg, cntr6clk_cnt) },
  86. { "cntr7clk-cnt", offsetof(struct mainpll_cfg, cntr7clk_cnt) },
  87. { "cntr7clk-src", offsetof(struct mainpll_cfg, cntr7clk_src) },
  88. { "cntr8clk-cnt", offsetof(struct mainpll_cfg, cntr8clk_cnt) },
  89. { "cntr9clk-cnt", offsetof(struct mainpll_cfg, cntr9clk_cnt) },
  90. { "cntr9clk-src", offsetof(struct mainpll_cfg, cntr9clk_src) },
  91. { "cntr15clk-cnt", offsetof(struct mainpll_cfg, cntr15clk_cnt) },
  92. { "nocdiv-l4mainclk", offsetof(struct mainpll_cfg, nocdiv_l4mainclk) },
  93. { "nocdiv-l4mpclk", offsetof(struct mainpll_cfg, nocdiv_l4mpclk) },
  94. { "nocdiv-l4spclk", offsetof(struct mainpll_cfg, nocdiv_l4spclk) },
  95. { "nocdiv-csatclk", offsetof(struct mainpll_cfg, nocdiv_csatclk) },
  96. { "nocdiv-cstraceclk", offsetof(struct mainpll_cfg, nocdiv_cstraceclk) },
  97. { "nocdiv-cspdbgclk", offsetof(struct mainpll_cfg, nocdiv_cspdbclk) },
  98. };
  99. static const struct strtou32 perpll_cfg_tab[] = {
  100. { "vco0-psrc", offsetof(struct perpll_cfg, vco0_psrc) },
  101. { "vco1-denom", offsetof(struct perpll_cfg, vco1_denom) },
  102. { "vco1-numer", offsetof(struct perpll_cfg, vco1_numer) },
  103. { "cntr2clk-cnt", offsetof(struct perpll_cfg, cntr2clk_cnt) },
  104. { "cntr2clk-src", offsetof(struct perpll_cfg, cntr2clk_src) },
  105. { "cntr3clk-cnt", offsetof(struct perpll_cfg, cntr3clk_cnt) },
  106. { "cntr3clk-src", offsetof(struct perpll_cfg, cntr3clk_src) },
  107. { "cntr4clk-cnt", offsetof(struct perpll_cfg, cntr4clk_cnt) },
  108. { "cntr4clk-src", offsetof(struct perpll_cfg, cntr4clk_src) },
  109. { "cntr5clk-cnt", offsetof(struct perpll_cfg, cntr5clk_cnt) },
  110. { "cntr5clk-src", offsetof(struct perpll_cfg, cntr5clk_src) },
  111. { "cntr6clk-cnt", offsetof(struct perpll_cfg, cntr6clk_cnt) },
  112. { "cntr6clk-src", offsetof(struct perpll_cfg, cntr6clk_src) },
  113. { "cntr7clk-cnt", offsetof(struct perpll_cfg, cntr7clk_cnt) },
  114. { "cntr8clk-cnt", offsetof(struct perpll_cfg, cntr8clk_cnt) },
  115. { "cntr8clk-src", offsetof(struct perpll_cfg, cntr8clk_src) },
  116. { "cntr9clk-cnt", offsetof(struct perpll_cfg, cntr9clk_cnt) },
  117. { "emacctl-emac0sel", offsetof(struct perpll_cfg, emacctl_emac0sel) },
  118. { "emacctl-emac1sel", offsetof(struct perpll_cfg, emacctl_emac1sel) },
  119. { "emacctl-emac2sel", offsetof(struct perpll_cfg, emacctl_emac2sel) },
  120. { "gpiodiv-gpiodbclk", offsetof(struct perpll_cfg, gpiodiv_gpiodbclk) },
  121. };
  122. static const struct strtou32 alteragrp_cfg_tab[] = {
  123. { "nocclk", offsetof(struct mainpll_cfg, nocclk) },
  124. { "mpuclk", offsetof(struct mainpll_cfg, mpuclk) },
  125. };
  126. struct strtopu32 {
  127. const char *str;
  128. u32 *p;
  129. };
  130. const struct strtopu32 dt_to_val[] = {
  131. { "altera_arria10_hps_eosc1", &eosc1_hz },
  132. { "altera_arria10_hps_cb_intosc_ls", &cb_intosc_hz },
  133. { "altera_arria10_hps_f2h_free", &f2s_free_hz },
  134. };
  135. static int of_to_struct(const void *blob, int node, const struct strtou32 *cfg_tab,
  136. int cfg_tab_len, void *cfg)
  137. {
  138. int i;
  139. u32 val;
  140. for (i = 0; i < cfg_tab_len; i++) {
  141. if (fdtdec_get_int_array(blob, node, cfg_tab[i].str, &val, 1)) {
  142. /* could not find required property */
  143. return -EINVAL;
  144. }
  145. *(u32 *)(cfg + cfg_tab[i].val) = val;
  146. }
  147. return 0;
  148. }
  149. static int of_get_input_clks(const void *blob)
  150. {
  151. struct udevice *dev;
  152. struct clk clk;
  153. int i, ret;
  154. for (i = 0; i < ARRAY_SIZE(dt_to_val); i++) {
  155. memset(&clk, 0, sizeof(clk));
  156. ret = uclass_get_device_by_name(UCLASS_CLK, dt_to_val[i].str,
  157. &dev);
  158. if (ret)
  159. return ret;
  160. ret = clk_request(dev, &clk);
  161. if (ret)
  162. return ret;
  163. *dt_to_val[i].p = clk_get_rate(&clk);
  164. }
  165. return 0;
  166. }
  167. static int of_get_clk_cfg(const void *blob, struct mainpll_cfg *main_cfg,
  168. struct perpll_cfg *per_cfg)
  169. {
  170. int ret, node, child, len;
  171. const char *node_name;
  172. ret = of_get_input_clks(blob);
  173. if (ret)
  174. return ret;
  175. node = fdtdec_next_compatible(blob, 0, COMPAT_ALTERA_SOCFPGA_CLK_INIT);
  176. if (node < 0)
  177. return -EINVAL;
  178. child = fdt_first_subnode(blob, node);
  179. if (child < 0)
  180. return -EINVAL;
  181. node_name = fdt_get_name(blob, child, &len);
  182. while (node_name) {
  183. if (!strcmp(node_name, "mainpll")) {
  184. if (of_to_struct(blob, child, mainpll_cfg_tab,
  185. ARRAY_SIZE(mainpll_cfg_tab), main_cfg))
  186. return -EINVAL;
  187. } else if (!strcmp(node_name, "perpll")) {
  188. if (of_to_struct(blob, child, perpll_cfg_tab,
  189. ARRAY_SIZE(perpll_cfg_tab), per_cfg))
  190. return -EINVAL;
  191. } else if (!strcmp(node_name, "alteragrp")) {
  192. if (of_to_struct(blob, child, alteragrp_cfg_tab,
  193. ARRAY_SIZE(alteragrp_cfg_tab), main_cfg))
  194. return -EINVAL;
  195. }
  196. child = fdt_next_subnode(blob, child);
  197. if (child < 0)
  198. break;
  199. node_name = fdt_get_name(blob, child, &len);
  200. }
  201. return 0;
  202. }
  203. /* calculate the intended main VCO frequency based on handoff */
  204. static unsigned int cm_calc_handoff_main_vco_clk_hz
  205. (struct mainpll_cfg *main_cfg)
  206. {
  207. unsigned int clk_hz;
  208. /* Check main VCO clock source: eosc, intosc or f2s? */
  209. switch (main_cfg->vco0_psrc) {
  210. case CLKMGR_MAINPLL_VCO0_PSRC_EOSC:
  211. clk_hz = eosc1_hz;
  212. break;
  213. case CLKMGR_MAINPLL_VCO0_PSRC_E_INTOSC:
  214. clk_hz = cb_intosc_hz;
  215. break;
  216. case CLKMGR_MAINPLL_VCO0_PSRC_F2S:
  217. clk_hz = f2s_free_hz;
  218. break;
  219. default:
  220. return 0;
  221. }
  222. /* calculate the VCO frequency */
  223. clk_hz /= 1 + main_cfg->vco1_denom;
  224. clk_hz *= 1 + main_cfg->vco1_numer;
  225. return clk_hz;
  226. }
  227. /* calculate the intended periph VCO frequency based on handoff */
  228. static unsigned int cm_calc_handoff_periph_vco_clk_hz(
  229. struct mainpll_cfg *main_cfg, struct perpll_cfg *per_cfg)
  230. {
  231. unsigned int clk_hz;
  232. /* Check periph VCO clock source: eosc, intosc, f2s or mainpll? */
  233. switch (per_cfg->vco0_psrc) {
  234. case CLKMGR_PERPLL_VCO0_PSRC_EOSC:
  235. clk_hz = eosc1_hz;
  236. break;
  237. case CLKMGR_PERPLL_VCO0_PSRC_E_INTOSC:
  238. clk_hz = cb_intosc_hz;
  239. break;
  240. case CLKMGR_PERPLL_VCO0_PSRC_F2S:
  241. clk_hz = f2s_free_hz;
  242. break;
  243. case CLKMGR_PERPLL_VCO0_PSRC_MAIN:
  244. clk_hz = cm_calc_handoff_main_vco_clk_hz(main_cfg);
  245. clk_hz /= main_cfg->cntr15clk_cnt;
  246. break;
  247. default:
  248. return 0;
  249. }
  250. /* calculate the VCO frequency */
  251. clk_hz /= 1 + per_cfg->vco1_denom;
  252. clk_hz *= 1 + per_cfg->vco1_numer;
  253. return clk_hz;
  254. }
  255. /* calculate the intended MPU clock frequency based on handoff */
  256. static unsigned int cm_calc_handoff_mpu_clk_hz(struct mainpll_cfg *main_cfg,
  257. struct perpll_cfg *per_cfg)
  258. {
  259. unsigned int clk_hz;
  260. /* Check MPU clock source: main, periph, osc1, intosc or f2s? */
  261. switch (main_cfg->mpuclk_src) {
  262. case CLKMGR_MAINPLL_MPUCLK_SRC_MAIN:
  263. clk_hz = cm_calc_handoff_main_vco_clk_hz(main_cfg);
  264. clk_hz /= (main_cfg->mpuclk & CLKMGR_MAINPLL_MPUCLK_CNT_MSK)
  265. + 1;
  266. break;
  267. case CLKMGR_MAINPLL_MPUCLK_SRC_PERI:
  268. clk_hz = cm_calc_handoff_periph_vco_clk_hz(main_cfg, per_cfg);
  269. clk_hz /= ((main_cfg->mpuclk >>
  270. CLKMGR_MAINPLL_MPUCLK_PERICNT_LSB) &
  271. CLKMGR_MAINPLL_MPUCLK_CNT_MSK) + 1;
  272. break;
  273. case CLKMGR_MAINPLL_MPUCLK_SRC_OSC1:
  274. clk_hz = eosc1_hz;
  275. break;
  276. case CLKMGR_MAINPLL_MPUCLK_SRC_INTOSC:
  277. clk_hz = cb_intosc_hz;
  278. break;
  279. case CLKMGR_MAINPLL_MPUCLK_SRC_FPGA:
  280. clk_hz = f2s_free_hz;
  281. break;
  282. default:
  283. return 0;
  284. }
  285. clk_hz /= main_cfg->mpuclk_cnt + 1;
  286. return clk_hz;
  287. }
  288. /* calculate the intended NOC clock frequency based on handoff */
  289. static unsigned int cm_calc_handoff_noc_clk_hz(struct mainpll_cfg *main_cfg,
  290. struct perpll_cfg *per_cfg)
  291. {
  292. unsigned int clk_hz;
  293. /* Check MPU clock source: main, periph, osc1, intosc or f2s? */
  294. switch (main_cfg->nocclk_src) {
  295. case CLKMGR_MAINPLL_NOCCLK_SRC_MAIN:
  296. clk_hz = cm_calc_handoff_main_vco_clk_hz(main_cfg);
  297. clk_hz /= (main_cfg->nocclk & CLKMGR_MAINPLL_NOCCLK_CNT_MSK)
  298. + 1;
  299. break;
  300. case CLKMGR_MAINPLL_NOCCLK_SRC_PERI:
  301. clk_hz = cm_calc_handoff_periph_vco_clk_hz(main_cfg, per_cfg);
  302. clk_hz /= ((main_cfg->nocclk >>
  303. CLKMGR_MAINPLL_NOCCLK_PERICNT_LSB) &
  304. CLKMGR_MAINPLL_NOCCLK_CNT_MSK) + 1;
  305. break;
  306. case CLKMGR_MAINPLL_NOCCLK_SRC_OSC1:
  307. clk_hz = eosc1_hz;
  308. break;
  309. case CLKMGR_MAINPLL_NOCCLK_SRC_INTOSC:
  310. clk_hz = cb_intosc_hz;
  311. break;
  312. case CLKMGR_MAINPLL_NOCCLK_SRC_FPGA:
  313. clk_hz = f2s_free_hz;
  314. break;
  315. default:
  316. return 0;
  317. }
  318. clk_hz /= main_cfg->nocclk_cnt + 1;
  319. return clk_hz;
  320. }
  321. /* return 1 if PLL ramp is required */
  322. static int cm_is_pll_ramp_required(int main0periph1,
  323. struct mainpll_cfg *main_cfg,
  324. struct perpll_cfg *per_cfg)
  325. {
  326. /* Check for main PLL */
  327. if (main0periph1 == 0) {
  328. /*
  329. * PLL ramp is not required if both MPU clock and NOC clock are
  330. * not sourced from main PLL
  331. */
  332. if (main_cfg->mpuclk_src != CLKMGR_MAINPLL_MPUCLK_SRC_MAIN &&
  333. main_cfg->nocclk_src != CLKMGR_MAINPLL_NOCCLK_SRC_MAIN)
  334. return 0;
  335. /*
  336. * PLL ramp is required if MPU clock is sourced from main PLL
  337. * and MPU clock is over 900MHz (as advised by HW team)
  338. */
  339. if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_MAIN &&
  340. (cm_calc_handoff_mpu_clk_hz(main_cfg, per_cfg) >
  341. CLKMGR_PLL_RAMP_MPUCLK_THRESHOLD_HZ))
  342. return 1;
  343. /*
  344. * PLL ramp is required if NOC clock is sourced from main PLL
  345. * and NOC clock is over 300MHz (as advised by HW team)
  346. */
  347. if (main_cfg->nocclk_src == CLKMGR_MAINPLL_NOCCLK_SRC_MAIN &&
  348. (cm_calc_handoff_noc_clk_hz(main_cfg, per_cfg) >
  349. CLKMGR_PLL_RAMP_NOCCLK_THRESHOLD_HZ))
  350. return 2;
  351. } else if (main0periph1 == 1) {
  352. /*
  353. * PLL ramp is not required if both MPU clock and NOC clock are
  354. * not sourced from periph PLL
  355. */
  356. if (main_cfg->mpuclk_src != CLKMGR_MAINPLL_MPUCLK_SRC_PERI &&
  357. main_cfg->nocclk_src != CLKMGR_MAINPLL_NOCCLK_SRC_PERI)
  358. return 0;
  359. /*
  360. * PLL ramp is required if MPU clock are source from periph PLL
  361. * and MPU clock is over 900MHz (as advised by HW team)
  362. */
  363. if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_PERI &&
  364. (cm_calc_handoff_mpu_clk_hz(main_cfg, per_cfg) >
  365. CLKMGR_PLL_RAMP_MPUCLK_THRESHOLD_HZ))
  366. return 1;
  367. /*
  368. * PLL ramp is required if NOC clock are source from periph PLL
  369. * and NOC clock is over 300MHz (as advised by HW team)
  370. */
  371. if (main_cfg->nocclk_src == CLKMGR_MAINPLL_NOCCLK_SRC_PERI &&
  372. (cm_calc_handoff_noc_clk_hz(main_cfg, per_cfg) >
  373. CLKMGR_PLL_RAMP_NOCCLK_THRESHOLD_HZ))
  374. return 2;
  375. }
  376. return 0;
  377. }
  378. static u32 cm_calculate_numer(struct mainpll_cfg *main_cfg,
  379. struct perpll_cfg *per_cfg,
  380. u32 safe_hz, u32 clk_hz)
  381. {
  382. u32 cnt;
  383. u32 clk;
  384. u32 shift;
  385. u32 mask;
  386. u32 denom;
  387. if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_MAIN) {
  388. cnt = main_cfg->mpuclk_cnt;
  389. clk = main_cfg->mpuclk;
  390. shift = 0;
  391. mask = CLKMGR_MAINPLL_MPUCLK_CNT_MSK;
  392. denom = main_cfg->vco1_denom;
  393. } else if (main_cfg->nocclk_src == CLKMGR_MAINPLL_NOCCLK_SRC_MAIN) {
  394. cnt = main_cfg->nocclk_cnt;
  395. clk = main_cfg->nocclk;
  396. shift = 0;
  397. mask = CLKMGR_MAINPLL_NOCCLK_CNT_MSK;
  398. denom = main_cfg->vco1_denom;
  399. } else if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_PERI) {
  400. cnt = main_cfg->mpuclk_cnt;
  401. clk = main_cfg->mpuclk;
  402. shift = CLKMGR_MAINPLL_MPUCLK_PERICNT_LSB;
  403. mask = CLKMGR_MAINPLL_MPUCLK_CNT_MSK;
  404. denom = per_cfg->vco1_denom;
  405. } else if (main_cfg->nocclk_src == CLKMGR_MAINPLL_NOCCLK_SRC_PERI) {
  406. cnt = main_cfg->nocclk_cnt;
  407. clk = main_cfg->nocclk;
  408. shift = CLKMGR_MAINPLL_NOCCLK_PERICNT_LSB;
  409. mask = CLKMGR_MAINPLL_NOCCLK_CNT_MSK;
  410. denom = per_cfg->vco1_denom;
  411. } else {
  412. return 0;
  413. }
  414. return (safe_hz / clk_hz) * (cnt + 1) * (((clk >> shift) & mask) + 1) *
  415. (1 + denom) - 1;
  416. }
  417. /*
  418. * Calculate the new PLL numerator which is based on existing DTS hand off and
  419. * intended safe frequency (safe_hz). Note that PLL ramp is only modifying the
  420. * numerator while maintaining denominator as denominator will influence the
  421. * jitter condition. Please refer A10 HPS TRM for the jitter guide. Note final
  422. * value for numerator is minus with 1 to cater our register value
  423. * representation.
  424. */
  425. static unsigned int cm_calc_safe_pll_numer(int main0periph1,
  426. struct mainpll_cfg *main_cfg,
  427. struct perpll_cfg *per_cfg,
  428. unsigned int safe_hz)
  429. {
  430. unsigned int clk_hz = 0;
  431. /* Check for main PLL */
  432. if (main0periph1 == 0) {
  433. /* Check main VCO clock source: eosc, intosc or f2s? */
  434. switch (main_cfg->vco0_psrc) {
  435. case CLKMGR_MAINPLL_VCO0_PSRC_EOSC:
  436. clk_hz = eosc1_hz;
  437. break;
  438. case CLKMGR_MAINPLL_VCO0_PSRC_E_INTOSC:
  439. clk_hz = cb_intosc_hz;
  440. break;
  441. case CLKMGR_MAINPLL_VCO0_PSRC_F2S:
  442. clk_hz = f2s_free_hz;
  443. break;
  444. default:
  445. return 0;
  446. }
  447. } else if (main0periph1 == 1) {
  448. /* Check periph VCO clock source: eosc, intosc, f2s, mainpll */
  449. switch (per_cfg->vco0_psrc) {
  450. case CLKMGR_PERPLL_VCO0_PSRC_EOSC:
  451. clk_hz = eosc1_hz;
  452. break;
  453. case CLKMGR_PERPLL_VCO0_PSRC_E_INTOSC:
  454. clk_hz = cb_intosc_hz;
  455. break;
  456. case CLKMGR_PERPLL_VCO0_PSRC_F2S:
  457. clk_hz = f2s_free_hz;
  458. break;
  459. case CLKMGR_PERPLL_VCO0_PSRC_MAIN:
  460. clk_hz = cm_calc_handoff_main_vco_clk_hz(main_cfg);
  461. clk_hz /= main_cfg->cntr15clk_cnt;
  462. break;
  463. default:
  464. return 0;
  465. }
  466. } else {
  467. return 0;
  468. }
  469. return cm_calculate_numer(main_cfg, per_cfg, safe_hz, clk_hz);
  470. }
  471. /* ramping the main PLL to final value */
  472. static void cm_pll_ramp_main(struct mainpll_cfg *main_cfg,
  473. struct perpll_cfg *per_cfg,
  474. unsigned int pll_ramp_main_hz)
  475. {
  476. unsigned int clk_hz = 0, clk_incr_hz = 0, clk_final_hz = 0;
  477. /* find out the increment value */
  478. if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_MAIN) {
  479. clk_incr_hz = CLKMGR_PLL_RAMP_MPUCLK_INCREMENT_HZ;
  480. clk_final_hz = cm_calc_handoff_mpu_clk_hz(main_cfg, per_cfg);
  481. } else if (main_cfg->nocclk_src == CLKMGR_MAINPLL_NOCCLK_SRC_MAIN) {
  482. clk_incr_hz = CLKMGR_PLL_RAMP_NOCCLK_INCREMENT_HZ;
  483. clk_final_hz = cm_calc_handoff_noc_clk_hz(main_cfg, per_cfg);
  484. }
  485. /* execute the ramping here */
  486. for (clk_hz = pll_ramp_main_hz + clk_incr_hz;
  487. clk_hz < clk_final_hz; clk_hz += clk_incr_hz) {
  488. writel((main_cfg->vco1_denom <<
  489. CLKMGR_MAINPLL_VCO1_DENOM_LSB) |
  490. cm_calc_safe_pll_numer(0, main_cfg, per_cfg, clk_hz),
  491. socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO1);
  492. mdelay(1);
  493. cm_wait_for_lock(LOCKED_MASK);
  494. }
  495. writel((main_cfg->vco1_denom << CLKMGR_MAINPLL_VCO1_DENOM_LSB) |
  496. main_cfg->vco1_numer,
  497. socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO1);
  498. mdelay(1);
  499. cm_wait_for_lock(LOCKED_MASK);
  500. }
  501. /* ramping the periph PLL to final value */
  502. static void cm_pll_ramp_periph(struct mainpll_cfg *main_cfg,
  503. struct perpll_cfg *per_cfg,
  504. unsigned int pll_ramp_periph_hz)
  505. {
  506. unsigned int clk_hz = 0, clk_incr_hz = 0, clk_final_hz = 0;
  507. /* find out the increment value */
  508. if (main_cfg->mpuclk_src == CLKMGR_MAINPLL_MPUCLK_SRC_PERI) {
  509. clk_incr_hz = CLKMGR_PLL_RAMP_MPUCLK_INCREMENT_HZ;
  510. clk_final_hz = cm_calc_handoff_mpu_clk_hz(main_cfg, per_cfg);
  511. } else if (main_cfg->nocclk_src == CLKMGR_MAINPLL_NOCCLK_SRC_PERI) {
  512. clk_incr_hz = CLKMGR_PLL_RAMP_NOCCLK_INCREMENT_HZ;
  513. clk_final_hz = cm_calc_handoff_noc_clk_hz(main_cfg, per_cfg);
  514. }
  515. /* execute the ramping here */
  516. for (clk_hz = pll_ramp_periph_hz + clk_incr_hz;
  517. clk_hz < clk_final_hz; clk_hz += clk_incr_hz) {
  518. writel((per_cfg->vco1_denom <<
  519. CLKMGR_PERPLL_VCO1_DENOM_LSB) |
  520. cm_calc_safe_pll_numer(1, main_cfg, per_cfg,
  521. clk_hz),
  522. socfpga_get_clkmgr_addr() +
  523. CLKMGR_A10_PERPLL_VCO1);
  524. mdelay(1);
  525. cm_wait_for_lock(LOCKED_MASK);
  526. }
  527. writel((per_cfg->vco1_denom << CLKMGR_PERPLL_VCO1_DENOM_LSB) |
  528. per_cfg->vco1_numer,
  529. socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO1);
  530. mdelay(1);
  531. cm_wait_for_lock(LOCKED_MASK);
  532. }
  533. /*
  534. * Setup clocks while making no assumptions of the
  535. * previous state of the clocks.
  536. *
  537. * Start by being paranoid and gate all sw managed clocks
  538. *
  539. * Put all plls in bypass
  540. *
  541. * Put all plls VCO registers back to reset value (bgpwr dwn).
  542. *
  543. * Put peripheral and main pll src to reset value to avoid glitch.
  544. *
  545. * Delay 5 us.
  546. *
  547. * Deassert bg pwr dn and set numerator and denominator
  548. *
  549. * Start 7 us timer.
  550. *
  551. * set internal dividers
  552. *
  553. * Wait for 7 us timer.
  554. *
  555. * Enable plls
  556. *
  557. * Set external dividers while plls are locking
  558. *
  559. * Wait for pll lock
  560. *
  561. * Assert/deassert outreset all.
  562. *
  563. * Take all pll's out of bypass
  564. *
  565. * Clear safe mode
  566. *
  567. * set source main and peripheral clocks
  568. *
  569. * Ungate clocks
  570. */
  571. static int cm_full_cfg(struct mainpll_cfg *main_cfg, struct perpll_cfg *per_cfg)
  572. {
  573. unsigned int pll_ramp_main_hz = 0, pll_ramp_periph_hz = 0,
  574. ramp_required;
  575. /* gate off all mainpll clock excpet HW managed clock */
  576. writel(CLKMGR_MAINPLL_EN_S2FUSER0CLKEN_SET_MSK |
  577. CLKMGR_MAINPLL_EN_HMCPLLREFCLKEN_SET_MSK,
  578. socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_ENR);
  579. /* now we can gate off the rest of the peripheral clocks */
  580. writel(0, socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_EN);
  581. /* Put all plls in external bypass */
  582. writel(CLKMGR_MAINPLL_BYPASS_RESET,
  583. socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_BYPASSS);
  584. writel(CLKMGR_PERPLL_BYPASS_RESET,
  585. socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_BYPASSS);
  586. /*
  587. * Put all plls VCO registers back to reset value.
  588. * Some code might have messed with them. At same time set the
  589. * desired clock source
  590. */
  591. writel(CLKMGR_MAINPLL_VCO0_RESET |
  592. CLKMGR_MAINPLL_VCO0_REGEXTSEL_SET_MSK |
  593. (main_cfg->vco0_psrc << CLKMGR_MAINPLL_VCO0_PSRC_LSB),
  594. socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO0);
  595. writel(CLKMGR_PERPLL_VCO0_RESET |
  596. CLKMGR_PERPLL_VCO0_REGEXTSEL_SET_MSK |
  597. (per_cfg->vco0_psrc << CLKMGR_PERPLL_VCO0_PSRC_LSB),
  598. socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO0);
  599. writel(CLKMGR_MAINPLL_VCO1_RESET,
  600. socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO1);
  601. writel(CLKMGR_PERPLL_VCO1_RESET,
  602. socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO1);
  603. /* clear the interrupt register status register */
  604. writel(CLKMGR_CLKMGR_INTR_MAINPLLLOST_SET_MSK |
  605. CLKMGR_CLKMGR_INTR_PERPLLLOST_SET_MSK |
  606. CLKMGR_CLKMGR_INTR_MAINPLLRFSLIP_SET_MSK |
  607. CLKMGR_CLKMGR_INTR_PERPLLRFSLIP_SET_MSK |
  608. CLKMGR_CLKMGR_INTR_MAINPLLFBSLIP_SET_MSK |
  609. CLKMGR_CLKMGR_INTR_PERPLLFBSLIP_SET_MSK |
  610. CLKMGR_CLKMGR_INTR_MAINPLLACHIEVED_SET_MSK |
  611. CLKMGR_CLKMGR_INTR_PERPLLACHIEVED_SET_MSK,
  612. socfpga_get_clkmgr_addr() + CLKMGR_A10_INTR);
  613. /* Program VCO Numerator and Denominator for main PLL */
  614. ramp_required = cm_is_pll_ramp_required(0, main_cfg, per_cfg);
  615. if (ramp_required) {
  616. /* set main PLL to safe starting threshold frequency */
  617. if (ramp_required == 1)
  618. pll_ramp_main_hz = CLKMGR_PLL_RAMP_MPUCLK_THRESHOLD_HZ;
  619. else if (ramp_required == 2)
  620. pll_ramp_main_hz = CLKMGR_PLL_RAMP_NOCCLK_THRESHOLD_HZ;
  621. writel((main_cfg->vco1_denom <<
  622. CLKMGR_MAINPLL_VCO1_DENOM_LSB) |
  623. cm_calc_safe_pll_numer(0, main_cfg, per_cfg,
  624. pll_ramp_main_hz),
  625. socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO1);
  626. } else
  627. writel((main_cfg->vco1_denom <<
  628. CLKMGR_MAINPLL_VCO1_DENOM_LSB) |
  629. main_cfg->vco1_numer,
  630. socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO1);
  631. /* Program VCO Numerator and Denominator for periph PLL */
  632. ramp_required = cm_is_pll_ramp_required(1, main_cfg, per_cfg);
  633. if (ramp_required) {
  634. /* set periph PLL to safe starting threshold frequency */
  635. if (ramp_required == 1)
  636. pll_ramp_periph_hz =
  637. CLKMGR_PLL_RAMP_MPUCLK_THRESHOLD_HZ;
  638. else if (ramp_required == 2)
  639. pll_ramp_periph_hz =
  640. CLKMGR_PLL_RAMP_NOCCLK_THRESHOLD_HZ;
  641. writel((per_cfg->vco1_denom <<
  642. CLKMGR_PERPLL_VCO1_DENOM_LSB) |
  643. cm_calc_safe_pll_numer(1, main_cfg, per_cfg,
  644. pll_ramp_periph_hz),
  645. socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO1);
  646. } else
  647. writel((per_cfg->vco1_denom <<
  648. CLKMGR_PERPLL_VCO1_DENOM_LSB) |
  649. per_cfg->vco1_numer,
  650. socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO1);
  651. /* Wait for at least 5 us */
  652. udelay(5);
  653. /* Now deassert BGPWRDN and PWRDN */
  654. clrbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO0,
  655. CLKMGR_MAINPLL_VCO0_BGPWRDN_SET_MSK |
  656. CLKMGR_MAINPLL_VCO0_PWRDN_SET_MSK);
  657. clrbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO0,
  658. CLKMGR_PERPLL_VCO0_BGPWRDN_SET_MSK |
  659. CLKMGR_PERPLL_VCO0_PWRDN_SET_MSK);
  660. /* Wait for at least 7 us */
  661. udelay(7);
  662. /* enable the VCO and disable the external regulator to PLL */
  663. writel((readl(socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO0) &
  664. ~CLKMGR_MAINPLL_VCO0_REGEXTSEL_SET_MSK) |
  665. CLKMGR_MAINPLL_VCO0_EN_SET_MSK,
  666. socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO0);
  667. writel((readl(socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO0) &
  668. ~CLKMGR_PERPLL_VCO0_REGEXTSEL_SET_MSK) |
  669. CLKMGR_PERPLL_VCO0_EN_SET_MSK,
  670. socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO0);
  671. /* setup all the main PLL counter and clock source */
  672. writel(main_cfg->nocclk,
  673. socfpga_get_clkmgr_addr() + CLKMGR_A10_ALTR_NOCCLK);
  674. writel(main_cfg->mpuclk,
  675. socfpga_get_clkmgr_addr() + CLKMGR_A10_ALTR_MPUCLK);
  676. /* main_emaca_clk divider */
  677. writel(main_cfg->cntr2clk_cnt,
  678. socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_CNTR2CLK);
  679. /* main_emacb_clk divider */
  680. writel(main_cfg->cntr3clk_cnt,
  681. socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_CNTR3CLK);
  682. /* main_emac_ptp_clk divider */
  683. writel(main_cfg->cntr4clk_cnt,
  684. socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_CNTR4CLK);
  685. /* main_gpio_db_clk divider */
  686. writel(main_cfg->cntr5clk_cnt,
  687. socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_CNTR5CLK);
  688. /* main_sdmmc_clk divider */
  689. writel(main_cfg->cntr6clk_cnt,
  690. socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_CNTR6CLK);
  691. /* main_s2f_user0_clk divider */
  692. writel(main_cfg->cntr7clk_cnt |
  693. (main_cfg->cntr7clk_src << CLKMGR_MAINPLL_CNTR7CLK_SRC_LSB),
  694. socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_CNTR7CLK);
  695. /* main_s2f_user1_clk divider */
  696. writel(main_cfg->cntr8clk_cnt,
  697. socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_CNTR8CLK);
  698. /* main_hmc_pll_clk divider */
  699. writel(main_cfg->cntr9clk_cnt |
  700. (main_cfg->cntr9clk_src << CLKMGR_MAINPLL_CNTR9CLK_SRC_LSB),
  701. socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_CNTR9CLK);
  702. /* main_periph_ref_clk divider */
  703. writel(main_cfg->cntr15clk_cnt,
  704. socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_CNTR15CLK);
  705. /* setup all the peripheral PLL counter and clock source */
  706. /* peri_emaca_clk divider */
  707. writel(per_cfg->cntr2clk_cnt |
  708. (per_cfg->cntr2clk_src << CLKMGR_PERPLL_CNTR2CLK_SRC_LSB),
  709. socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_CNTR2CLK);
  710. /* peri_emacb_clk divider */
  711. writel(per_cfg->cntr3clk_cnt |
  712. (per_cfg->cntr3clk_src << CLKMGR_PERPLL_CNTR3CLK_SRC_LSB),
  713. socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_CNTR3CLK);
  714. /* peri_emac_ptp_clk divider */
  715. writel(per_cfg->cntr4clk_cnt |
  716. (per_cfg->cntr4clk_src << CLKMGR_PERPLL_CNTR4CLK_SRC_LSB),
  717. socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_CNTR4CLK);
  718. /* peri_gpio_db_clk divider */
  719. writel(per_cfg->cntr5clk_cnt |
  720. (per_cfg->cntr5clk_src << CLKMGR_PERPLL_CNTR5CLK_SRC_LSB),
  721. socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_CNTR5CLK);
  722. /* peri_sdmmc_clk divider */
  723. writel(per_cfg->cntr6clk_cnt |
  724. (per_cfg->cntr6clk_src << CLKMGR_PERPLL_CNTR6CLK_SRC_LSB),
  725. socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_CNTR6CLK);
  726. /* peri_s2f_user0_clk divider */
  727. writel(per_cfg->cntr7clk_cnt,
  728. socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_CNTR7CLK);
  729. /* peri_s2f_user1_clk divider */
  730. writel(per_cfg->cntr8clk_cnt |
  731. (per_cfg->cntr8clk_src << CLKMGR_PERPLL_CNTR8CLK_SRC_LSB),
  732. socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_CNTR8CLK);
  733. /* peri_hmc_pll_clk divider */
  734. writel(per_cfg->cntr9clk_cnt,
  735. socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_CNTR9CLK);
  736. /* setup all the external PLL counter */
  737. /* mpu wrapper / external divider */
  738. writel(main_cfg->mpuclk_cnt |
  739. (main_cfg->mpuclk_src << CLKMGR_MAINPLL_MPUCLK_SRC_LSB),
  740. socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_MPUCLK);
  741. /* NOC wrapper / external divider */
  742. writel(main_cfg->nocclk_cnt |
  743. (main_cfg->nocclk_src << CLKMGR_MAINPLL_NOCCLK_SRC_LSB),
  744. socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_NOCCLK);
  745. /* NOC subclock divider such as l4 */
  746. writel(main_cfg->nocdiv_l4mainclk |
  747. (main_cfg->nocdiv_l4mpclk <<
  748. CLKMGR_MAINPLL_NOCDIV_L4MPCLK_LSB) |
  749. (main_cfg->nocdiv_l4spclk <<
  750. CLKMGR_MAINPLL_NOCDIV_L4SPCLK_LSB) |
  751. (main_cfg->nocdiv_csatclk <<
  752. CLKMGR_MAINPLL_NOCDIV_CSATCLK_LSB) |
  753. (main_cfg->nocdiv_cstraceclk <<
  754. CLKMGR_MAINPLL_NOCDIV_CSTRACECLK_LSB) |
  755. (main_cfg->nocdiv_cspdbclk <<
  756. CLKMGR_MAINPLL_NOCDIV_CSPDBGCLK_LSB),
  757. socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_NOCDIV);
  758. /* gpio_db external divider */
  759. writel(per_cfg->gpiodiv_gpiodbclk,
  760. socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_GPIOFIV);
  761. /* setup the EMAC clock mux select */
  762. writel((per_cfg->emacctl_emac0sel <<
  763. CLKMGR_PERPLL_EMACCTL_EMAC0SEL_LSB) |
  764. (per_cfg->emacctl_emac1sel <<
  765. CLKMGR_PERPLL_EMACCTL_EMAC1SEL_LSB) |
  766. (per_cfg->emacctl_emac2sel <<
  767. CLKMGR_PERPLL_EMACCTL_EMAC2SEL_LSB),
  768. socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_EMACCTL);
  769. /* at this stage, check for PLL lock status */
  770. cm_wait_for_lock(LOCKED_MASK);
  771. /*
  772. * after locking, but before taking out of bypass,
  773. * assert/deassert outresetall
  774. */
  775. /* assert mainpll outresetall */
  776. setbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO0,
  777. CLKMGR_MAINPLL_VCO0_OUTRSTALL_SET_MSK);
  778. /* assert perpll outresetall */
  779. setbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO0,
  780. CLKMGR_PERPLL_VCO0_OUTRSTALL_SET_MSK);
  781. /* de-assert mainpll outresetall */
  782. clrbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_VCO0,
  783. CLKMGR_MAINPLL_VCO0_OUTRSTALL_SET_MSK);
  784. /* de-assert perpll outresetall */
  785. clrbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_VCO0,
  786. CLKMGR_PERPLL_VCO0_OUTRSTALL_SET_MSK);
  787. /* Take all PLLs out of bypass when boot mode is cleared. */
  788. /* release mainpll from bypass */
  789. writel(CLKMGR_MAINPLL_BYPASS_RESET,
  790. socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_BYPASSR);
  791. /* wait till Clock Manager is not busy */
  792. cm_wait_for_fsm();
  793. /* release perpll from bypass */
  794. writel(CLKMGR_PERPLL_BYPASS_RESET,
  795. socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_BYPASSR);
  796. /* wait till Clock Manager is not busy */
  797. cm_wait_for_fsm();
  798. /* clear boot mode */
  799. clrbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_A10_CTRL,
  800. CLKMGR_CLKMGR_CTL_BOOTMOD_SET_MSK);
  801. /* wait till Clock Manager is not busy */
  802. cm_wait_for_fsm();
  803. /* At here, we need to ramp to final value if needed */
  804. if (pll_ramp_main_hz != 0)
  805. cm_pll_ramp_main(main_cfg, per_cfg, pll_ramp_main_hz);
  806. if (pll_ramp_periph_hz != 0)
  807. cm_pll_ramp_periph(main_cfg, per_cfg, pll_ramp_periph_hz);
  808. /* Now ungate non-hw-managed clocks */
  809. writel(CLKMGR_MAINPLL_EN_S2FUSER0CLKEN_SET_MSK |
  810. CLKMGR_MAINPLL_EN_HMCPLLREFCLKEN_SET_MSK,
  811. socfpga_get_clkmgr_addr() + CLKMGR_A10_MAINPLL_ENS);
  812. writel(CLKMGR_PERPLL_EN_RESET,
  813. socfpga_get_clkmgr_addr() + CLKMGR_A10_PERPLL_ENS);
  814. /* Clear the loss lock and slip bits as they might set during
  815. clock reconfiguration */
  816. writel(CLKMGR_CLKMGR_INTR_MAINPLLLOST_SET_MSK |
  817. CLKMGR_CLKMGR_INTR_PERPLLLOST_SET_MSK |
  818. CLKMGR_CLKMGR_INTR_MAINPLLRFSLIP_SET_MSK |
  819. CLKMGR_CLKMGR_INTR_PERPLLRFSLIP_SET_MSK |
  820. CLKMGR_CLKMGR_INTR_MAINPLLFBSLIP_SET_MSK |
  821. CLKMGR_CLKMGR_INTR_PERPLLFBSLIP_SET_MSK,
  822. socfpga_get_clkmgr_addr() + CLKMGR_A10_INTR);
  823. return 0;
  824. }
  825. static void cm_use_intosc(void)
  826. {
  827. setbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_A10_CTRL,
  828. CLKMGR_CLKMGR_CTL_BOOTCLK_INTOSC_SET_MSK);
  829. }
  830. int cm_basic_init(const void *blob)
  831. {
  832. struct mainpll_cfg main_cfg;
  833. struct perpll_cfg per_cfg;
  834. int rval;
  835. /* initialize to zero for use case of optional node */
  836. memset(&main_cfg, 0, sizeof(main_cfg));
  837. memset(&per_cfg, 0, sizeof(per_cfg));
  838. rval = of_get_clk_cfg(blob, &main_cfg, &per_cfg);
  839. if (rval)
  840. return rval;
  841. cm_use_intosc();
  842. return cm_full_cfg(&main_cfg, &per_cfg);
  843. }
  844. #endif
  845. static u32 cm_get_rate_dm(char *name)
  846. {
  847. struct uclass *uc;
  848. struct udevice *dev = NULL;
  849. struct clk clk = { 0 };
  850. ulong rate;
  851. int ret;
  852. /* Device addresses start at 1 */
  853. ret = uclass_get(UCLASS_CLK, &uc);
  854. if (ret)
  855. return 0;
  856. ret = uclass_get_device_by_name(UCLASS_CLK, name, &dev);
  857. if (ret)
  858. return 0;
  859. ret = device_probe(dev);
  860. if (ret)
  861. return 0;
  862. ret = clk_request(dev, &clk);
  863. if (ret)
  864. return 0;
  865. rate = clk_get_rate(&clk);
  866. clk_free(&clk);
  867. return rate;
  868. }
  869. static u32 cm_get_rate_dm_khz(char *name)
  870. {
  871. return cm_get_rate_dm(name) / 1000;
  872. }
  873. unsigned long cm_get_mpu_clk_hz(void)
  874. {
  875. return cm_get_rate_dm("main_mpu_base_clk");
  876. }
  877. unsigned int cm_get_qspi_controller_clk_hz(void)
  878. {
  879. return cm_get_rate_dm("qspi_clk");
  880. }
  881. unsigned int cm_get_l4_sp_clk_hz(void)
  882. {
  883. return cm_get_rate_dm("l4_sp_clk");
  884. }
  885. void cm_print_clock_quick_summary(void)
  886. {
  887. printf("MPU %10d kHz\n", cm_get_rate_dm_khz("main_mpu_base_clk"));
  888. printf("MMC %8d kHz\n", cm_get_rate_dm_khz("sdmmc_clk"));
  889. printf("QSPI %8d kHz\n", cm_get_rate_dm_khz("qspi_clk"));
  890. printf("SPI %8d kHz\n", cm_get_rate_dm_khz("spi_m_clk"));
  891. printf("EOSC1 %8d kHz\n", cm_get_rate_dm_khz("osc1"));
  892. printf("cb_intosc %8d kHz\n", cm_get_rate_dm_khz("cb_intosc_ls_clk"));
  893. printf("f2s_free %8d kHz\n", cm_get_rate_dm_khz("f2s_free_clk"));
  894. printf("Main VCO %8d kHz\n", cm_get_rate_dm_khz("main_pll@40"));
  895. printf("NOC %8d kHz\n", cm_get_rate_dm_khz("main_noc_base_clk"));
  896. printf("L4 Main %8d kHz\n", cm_get_rate_dm_khz("l4_main_clk"));
  897. printf("L4 MP %8d kHz\n", cm_get_rate_dm_khz("l4_mp_clk"));
  898. printf("L4 SP %8d kHz\n", cm_get_rate_dm_khz("l4_sp_clk"));
  899. printf("L4 sys free %8d kHz\n", cm_get_rate_dm_khz("l4_sys_free_clk"));
  900. }