clk_rv1108.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * (C) Copyright 2016 Rockchip Electronics Co., Ltd
  4. * Author: Andy Yan <andy.yan@rock-chips.com>
  5. */
  6. #include <common.h>
  7. #include <bitfield.h>
  8. #include <clk-uclass.h>
  9. #include <dm.h>
  10. #include <errno.h>
  11. #include <log.h>
  12. #include <malloc.h>
  13. #include <syscon.h>
  14. #include <asm/io.h>
  15. #include <asm/arch-rockchip/clock.h>
  16. #include <asm/arch-rockchip/cru_rv1108.h>
  17. #include <asm/arch-rockchip/hardware.h>
  18. #include <dm/lists.h>
  19. #include <dt-bindings/clock/rv1108-cru.h>
  20. #include <linux/stringify.h>
  21. DECLARE_GLOBAL_DATA_PTR;
  22. enum {
  23. VCO_MAX_HZ = 2400U * 1000000,
  24. VCO_MIN_HZ = 600 * 1000000,
  25. OUTPUT_MAX_HZ = 2400U * 1000000,
  26. OUTPUT_MIN_HZ = 24 * 1000000,
  27. };
  28. #define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1))
  29. #define PLL_DIVISORS(hz, _refdiv, _postdiv1, _postdiv2) {\
  30. .refdiv = _refdiv,\
  31. .fbdiv = (u32)((u64)hz * _refdiv * _postdiv1 * _postdiv2 / OSC_HZ),\
  32. .postdiv1 = _postdiv1, .postdiv2 = _postdiv2};\
  33. _Static_assert(((u64)hz * _refdiv * _postdiv1 * _postdiv2 / OSC_HZ) *\
  34. OSC_HZ / (_refdiv * _postdiv1 * _postdiv2) == hz,\
  35. #hz "Hz cannot be hit with PLL "\
  36. "divisors on line " __stringify(__LINE__));
  37. static const struct pll_div apll_init_cfg = PLL_DIVISORS(APLL_HZ, 1, 3, 1);
  38. static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 2, 2, 1);
  39. /* use integer mode */
  40. static inline int rv1108_pll_id(enum rk_clk_id clk_id)
  41. {
  42. int id = 0;
  43. switch (clk_id) {
  44. case CLK_ARM:
  45. case CLK_DDR:
  46. id = clk_id - 1;
  47. break;
  48. case CLK_GENERAL:
  49. id = 2;
  50. break;
  51. default:
  52. printf("invalid pll id:%d\n", clk_id);
  53. id = -1;
  54. break;
  55. }
  56. return id;
  57. }
  58. static int rkclk_set_pll(struct rv1108_cru *cru, enum rk_clk_id clk_id,
  59. const struct pll_div *div)
  60. {
  61. int pll_id = rv1108_pll_id(clk_id);
  62. struct rv1108_pll *pll = &cru->pll[pll_id];
  63. /* All PLLs have same VCO and output frequency range restrictions. */
  64. uint vco_hz = OSC_HZ / 1000 * div->fbdiv / div->refdiv * 1000;
  65. uint output_hz = vco_hz / div->postdiv1 / div->postdiv2;
  66. debug("PLL at %p: fb=%d, ref=%d, pst1=%d, pst2=%d, vco=%u Hz, output=%u Hz\n",
  67. pll, div->fbdiv, div->refdiv, div->postdiv1,
  68. div->postdiv2, vco_hz, output_hz);
  69. assert(vco_hz >= VCO_MIN_HZ && vco_hz <= VCO_MAX_HZ &&
  70. output_hz >= OUTPUT_MIN_HZ && output_hz <= OUTPUT_MAX_HZ);
  71. /*
  72. * When power on or changing PLL setting,
  73. * we must force PLL into slow mode to ensure output stable clock.
  74. */
  75. rk_clrsetreg(&pll->con3, WORK_MODE_MASK,
  76. WORK_MODE_SLOW << WORK_MODE_SHIFT);
  77. /* use integer mode */
  78. rk_setreg(&pll->con3, 1 << DSMPD_SHIFT);
  79. /* Power down */
  80. rk_setreg(&pll->con3, 1 << GLOBAL_POWER_DOWN_SHIFT);
  81. rk_clrsetreg(&pll->con0, FBDIV_MASK, div->fbdiv << FBDIV_SHIFT);
  82. rk_clrsetreg(&pll->con1, POSTDIV1_MASK | POSTDIV2_MASK | REFDIV_MASK,
  83. (div->postdiv1 << POSTDIV1_SHIFT |
  84. div->postdiv2 << POSTDIV2_SHIFT |
  85. div->refdiv << REFDIV_SHIFT));
  86. rk_clrsetreg(&pll->con2, FRACDIV_MASK,
  87. (div->refdiv << REFDIV_SHIFT));
  88. /* Power Up */
  89. rk_clrreg(&pll->con3, 1 << GLOBAL_POWER_DOWN_SHIFT);
  90. /* waiting for pll lock */
  91. while (readl(&pll->con2) & (1 << LOCK_STA_SHIFT))
  92. udelay(1);
  93. /*
  94. * set PLL into normal mode.
  95. */
  96. rk_clrsetreg(&pll->con3, WORK_MODE_MASK,
  97. WORK_MODE_NORMAL << WORK_MODE_SHIFT);
  98. return 0;
  99. }
  100. static uint32_t rkclk_pll_get_rate(struct rv1108_cru *cru,
  101. enum rk_clk_id clk_id)
  102. {
  103. uint32_t refdiv, fbdiv, postdiv1, postdiv2;
  104. uint32_t con0, con1, con3;
  105. int pll_id = rv1108_pll_id(clk_id);
  106. struct rv1108_pll *pll = &cru->pll[pll_id];
  107. uint32_t freq;
  108. con3 = readl(&pll->con3);
  109. if (con3 & WORK_MODE_MASK) {
  110. con0 = readl(&pll->con0);
  111. con1 = readl(&pll->con1);
  112. fbdiv = (con0 >> FBDIV_SHIFT) & FBDIV_MASK;
  113. postdiv1 = (con1 & POSTDIV1_MASK) >> POSTDIV1_SHIFT;
  114. postdiv2 = (con1 & POSTDIV2_MASK) >> POSTDIV2_SHIFT;
  115. refdiv = (con1 >> REFDIV_SHIFT) & REFDIV_MASK;
  116. freq = (24 * fbdiv / (refdiv * postdiv1 * postdiv2)) * 1000000;
  117. } else {
  118. freq = OSC_HZ;
  119. }
  120. return freq;
  121. }
  122. static int rv1108_mac_set_clk(struct rv1108_cru *cru, ulong rate)
  123. {
  124. uint32_t con = readl(&cru->clksel_con[24]);
  125. ulong pll_rate;
  126. uint8_t div;
  127. if ((con >> MAC_PLL_SEL_SHIFT) & MAC_PLL_SEL_GPLL)
  128. pll_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
  129. else
  130. pll_rate = rkclk_pll_get_rate(cru, CLK_ARM);
  131. /*default set 50MHZ for gmac*/
  132. if (!rate)
  133. rate = 50000000;
  134. div = DIV_ROUND_UP(pll_rate, rate) - 1;
  135. if (div <= 0x1f)
  136. rk_clrsetreg(&cru->clksel_con[24], MAC_CLK_DIV_MASK,
  137. div << MAC_CLK_DIV_SHIFT);
  138. else
  139. debug("Unsupported div for gmac:%d\n", div);
  140. return DIV_TO_RATE(pll_rate, div);
  141. }
  142. static int rv1108_sfc_set_clk(struct rv1108_cru *cru, uint rate)
  143. {
  144. u32 con = readl(&cru->clksel_con[27]);
  145. u32 pll_rate;
  146. u32 div;
  147. if ((con >> SFC_PLL_SEL_SHIFT) && SFC_PLL_SEL_GPLL)
  148. pll_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
  149. else
  150. pll_rate = rkclk_pll_get_rate(cru, CLK_DDR);
  151. div = DIV_ROUND_UP(pll_rate, rate) - 1;
  152. if (div <= 0x3f)
  153. rk_clrsetreg(&cru->clksel_con[27], SFC_CLK_DIV_MASK,
  154. div << SFC_CLK_DIV_SHIFT);
  155. else
  156. debug("Unsupported sfc clk rate:%d\n", rate);
  157. return DIV_TO_RATE(pll_rate, div);
  158. }
  159. static ulong rv1108_saradc_get_clk(struct rv1108_cru *cru)
  160. {
  161. u32 div, val;
  162. val = readl(&cru->clksel_con[22]);
  163. div = bitfield_extract(val, CLK_SARADC_DIV_CON_SHIFT,
  164. CLK_SARADC_DIV_CON_WIDTH);
  165. return DIV_TO_RATE(OSC_HZ, div);
  166. }
  167. static ulong rv1108_saradc_set_clk(struct rv1108_cru *cru, uint hz)
  168. {
  169. int src_clk_div;
  170. src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1;
  171. assert(src_clk_div < 128);
  172. rk_clrsetreg(&cru->clksel_con[22],
  173. CLK_SARADC_DIV_CON_MASK,
  174. src_clk_div << CLK_SARADC_DIV_CON_SHIFT);
  175. return rv1108_saradc_get_clk(cru);
  176. }
  177. static ulong rv1108_aclk_vio1_get_clk(struct rv1108_cru *cru)
  178. {
  179. u32 div, val;
  180. val = readl(&cru->clksel_con[28]);
  181. div = bitfield_extract(val, ACLK_VIO1_CLK_DIV_SHIFT,
  182. CLK_VIO_DIV_CON_WIDTH);
  183. return DIV_TO_RATE(GPLL_HZ, div);
  184. }
  185. static ulong rv1108_aclk_vio1_set_clk(struct rv1108_cru *cru, uint hz)
  186. {
  187. int src_clk_div;
  188. src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz) - 1;
  189. assert(src_clk_div < 32);
  190. rk_clrsetreg(&cru->clksel_con[28],
  191. ACLK_VIO1_CLK_DIV_MASK | ACLK_VIO1_PLL_SEL_MASK,
  192. (src_clk_div << ACLK_VIO1_CLK_DIV_SHIFT) |
  193. (VIO_PLL_SEL_GPLL << ACLK_VIO1_PLL_SEL_SHIFT));
  194. return rv1108_aclk_vio1_get_clk(cru);
  195. }
  196. static ulong rv1108_aclk_vio0_get_clk(struct rv1108_cru *cru)
  197. {
  198. u32 div, val;
  199. val = readl(&cru->clksel_con[28]);
  200. div = bitfield_extract(val, ACLK_VIO0_CLK_DIV_SHIFT,
  201. CLK_VIO_DIV_CON_WIDTH);
  202. return DIV_TO_RATE(GPLL_HZ, div);
  203. }
  204. static ulong rv1108_aclk_vio0_set_clk(struct rv1108_cru *cru, uint hz)
  205. {
  206. int src_clk_div;
  207. src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz) - 1;
  208. assert(src_clk_div < 32);
  209. rk_clrsetreg(&cru->clksel_con[28],
  210. ACLK_VIO0_CLK_DIV_MASK | ACLK_VIO0_PLL_SEL_MASK,
  211. (src_clk_div << ACLK_VIO0_CLK_DIV_SHIFT) |
  212. (VIO_PLL_SEL_GPLL << ACLK_VIO0_PLL_SEL_SHIFT));
  213. /*HCLK_VIO default div = 4*/
  214. rk_clrsetreg(&cru->clksel_con[29],
  215. HCLK_VIO_CLK_DIV_MASK,
  216. 3 << HCLK_VIO_CLK_DIV_SHIFT);
  217. /*PCLK_VIO default div = 4*/
  218. rk_clrsetreg(&cru->clksel_con[29],
  219. PCLK_VIO_CLK_DIV_MASK,
  220. 3 << PCLK_VIO_CLK_DIV_SHIFT);
  221. return rv1108_aclk_vio0_get_clk(cru);
  222. }
  223. static ulong rv1108_dclk_vop_get_clk(struct rv1108_cru *cru)
  224. {
  225. u32 div, val;
  226. val = readl(&cru->clksel_con[32]);
  227. div = bitfield_extract(val, DCLK_VOP_CLK_DIV_SHIFT,
  228. DCLK_VOP_DIV_CON_WIDTH);
  229. return DIV_TO_RATE(GPLL_HZ, div);
  230. }
  231. static ulong rv1108_dclk_vop_set_clk(struct rv1108_cru *cru, uint hz)
  232. {
  233. int src_clk_div;
  234. src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz) - 1;
  235. assert(src_clk_div < 64);
  236. rk_clrsetreg(&cru->clksel_con[32],
  237. DCLK_VOP_CLK_DIV_MASK | DCLK_VOP_PLL_SEL_MASK |
  238. DCLK_VOP_SEL_SHIFT,
  239. (src_clk_div << DCLK_VOP_CLK_DIV_SHIFT) |
  240. (DCLK_VOP_PLL_SEL_GPLL << DCLK_VOP_PLL_SEL_SHIFT) |
  241. (DCLK_VOP_SEL_PLL << DCLK_VOP_SEL_SHIFT));
  242. return rv1108_dclk_vop_get_clk(cru);
  243. }
  244. static ulong rv1108_aclk_bus_get_clk(struct rv1108_cru *cru)
  245. {
  246. u32 div, val;
  247. ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
  248. val = readl(&cru->clksel_con[2]);
  249. div = bitfield_extract(val, ACLK_BUS_DIV_CON_SHIFT,
  250. ACLK_BUS_DIV_CON_WIDTH);
  251. return DIV_TO_RATE(parent_rate, div);
  252. }
  253. static ulong rv1108_aclk_bus_set_clk(struct rv1108_cru *cru, uint hz)
  254. {
  255. int src_clk_div;
  256. ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
  257. src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
  258. assert(src_clk_div < 32);
  259. rk_clrsetreg(&cru->clksel_con[2],
  260. ACLK_BUS_DIV_CON_MASK | ACLK_BUS_PLL_SEL_MASK,
  261. (src_clk_div << ACLK_BUS_DIV_CON_SHIFT) |
  262. (ACLK_BUS_PLL_SEL_GPLL << ACLK_BUS_PLL_SEL_SHIFT));
  263. return rv1108_aclk_bus_get_clk(cru);
  264. }
  265. static ulong rv1108_aclk_peri_get_clk(struct rv1108_cru *cru)
  266. {
  267. u32 div, val;
  268. ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
  269. val = readl(&cru->clksel_con[23]);
  270. div = bitfield_extract(val, ACLK_PERI_DIV_CON_SHIFT,
  271. PERI_DIV_CON_WIDTH);
  272. return DIV_TO_RATE(parent_rate, div);
  273. }
  274. static ulong rv1108_hclk_peri_get_clk(struct rv1108_cru *cru)
  275. {
  276. u32 div, val;
  277. ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
  278. val = readl(&cru->clksel_con[23]);
  279. div = bitfield_extract(val, HCLK_PERI_DIV_CON_SHIFT,
  280. PERI_DIV_CON_WIDTH);
  281. return DIV_TO_RATE(parent_rate, div);
  282. }
  283. static ulong rv1108_pclk_peri_get_clk(struct rv1108_cru *cru)
  284. {
  285. u32 div, val;
  286. ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
  287. val = readl(&cru->clksel_con[23]);
  288. div = bitfield_extract(val, PCLK_PERI_DIV_CON_SHIFT,
  289. PERI_DIV_CON_WIDTH);
  290. return DIV_TO_RATE(parent_rate, div);
  291. }
  292. static ulong rv1108_aclk_peri_set_clk(struct rv1108_cru *cru, uint hz)
  293. {
  294. int src_clk_div;
  295. ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
  296. src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
  297. assert(src_clk_div < 32);
  298. rk_clrsetreg(&cru->clksel_con[23],
  299. ACLK_PERI_DIV_CON_MASK | ACLK_PERI_PLL_SEL_MASK,
  300. (src_clk_div << ACLK_PERI_DIV_CON_SHIFT) |
  301. (ACLK_PERI_PLL_SEL_GPLL << ACLK_PERI_PLL_SEL_SHIFT));
  302. return rv1108_aclk_peri_get_clk(cru);
  303. }
  304. static ulong rv1108_hclk_peri_set_clk(struct rv1108_cru *cru, uint hz)
  305. {
  306. int src_clk_div;
  307. ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
  308. src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
  309. assert(src_clk_div < 32);
  310. rk_clrsetreg(&cru->clksel_con[23],
  311. HCLK_PERI_DIV_CON_MASK,
  312. (src_clk_div << HCLK_PERI_DIV_CON_SHIFT));
  313. return rv1108_hclk_peri_get_clk(cru);
  314. }
  315. static ulong rv1108_pclk_peri_set_clk(struct rv1108_cru *cru, uint hz)
  316. {
  317. int src_clk_div;
  318. ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
  319. src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
  320. assert(src_clk_div < 32);
  321. rk_clrsetreg(&cru->clksel_con[23],
  322. PCLK_PERI_DIV_CON_MASK,
  323. (src_clk_div << PCLK_PERI_DIV_CON_SHIFT));
  324. return rv1108_pclk_peri_get_clk(cru);
  325. }
  326. static ulong rv1108_i2c_get_clk(struct rv1108_cru *cru, ulong clk_id)
  327. {
  328. u32 div, con;
  329. switch (clk_id) {
  330. case SCLK_I2C0_PMU:
  331. con = readl(&cru->clksel_con[19]);
  332. div = bitfield_extract(con, CLK_I2C0_DIV_CON_SHIFT,
  333. I2C_DIV_CON_WIDTH);
  334. break;
  335. case SCLK_I2C1:
  336. con = readl(&cru->clksel_con[19]);
  337. div = bitfield_extract(con, CLK_I2C1_DIV_CON_SHIFT,
  338. I2C_DIV_CON_WIDTH);
  339. break;
  340. case SCLK_I2C2:
  341. con = readl(&cru->clksel_con[20]);
  342. div = bitfield_extract(con, CLK_I2C2_DIV_CON_SHIFT,
  343. I2C_DIV_CON_WIDTH);
  344. break;
  345. case SCLK_I2C3:
  346. con = readl(&cru->clksel_con[20]);
  347. div = bitfield_extract(con, CLK_I2C3_DIV_CON_SHIFT,
  348. I2C_DIV_CON_WIDTH);
  349. break;
  350. default:
  351. printf("do not support this i2c bus\n");
  352. return -EINVAL;
  353. }
  354. return DIV_TO_RATE(GPLL_HZ, div);
  355. }
  356. static ulong rv1108_i2c_set_clk(struct rv1108_cru *cru, ulong clk_id, uint hz)
  357. {
  358. int src_clk_div;
  359. /* i2c0,4,8 src clock from ppll, i2c1,2,3,5,6,7 src clock from gpll*/
  360. src_clk_div = GPLL_HZ / hz;
  361. assert(src_clk_div - 1 <= 127);
  362. switch (clk_id) {
  363. case SCLK_I2C0_PMU:
  364. rk_clrsetreg(&cru->clksel_con[19],
  365. CLK_I2C0_DIV_CON_MASK | CLK_I2C1_PLL_SEL_MASK,
  366. (src_clk_div << CLK_I2C0_DIV_CON_SHIFT) |
  367. (CLK_I2C1_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT));
  368. break;
  369. case SCLK_I2C1:
  370. rk_clrsetreg(&cru->clksel_con[19],
  371. CLK_I2C1_DIV_CON_MASK | CLK_I2C1_PLL_SEL_MASK,
  372. (src_clk_div << CLK_I2C1_DIV_CON_SHIFT) |
  373. (CLK_I2C1_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT));
  374. break;
  375. case SCLK_I2C2:
  376. rk_clrsetreg(&cru->clksel_con[20],
  377. CLK_I2C2_DIV_CON_MASK | CLK_I2C3_PLL_SEL_MASK,
  378. (src_clk_div << CLK_I2C2_DIV_CON_SHIFT) |
  379. (CLK_I2C3_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT));
  380. break;
  381. case SCLK_I2C3:
  382. rk_clrsetreg(&cru->clksel_con[20],
  383. CLK_I2C3_DIV_CON_MASK | CLK_I2C3_PLL_SEL_MASK,
  384. (src_clk_div << CLK_I2C3_DIV_CON_SHIFT) |
  385. (CLK_I2C3_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT));
  386. break;
  387. default:
  388. printf("do not support this i2c bus\n");
  389. return -EINVAL;
  390. }
  391. return rv1108_i2c_get_clk(cru, clk_id);
  392. }
  393. static ulong rv1108_mmc_get_clk(struct rv1108_cru *cru)
  394. {
  395. u32 div, con;
  396. ulong mmc_clk;
  397. con = readl(&cru->clksel_con[26]);
  398. div = bitfield_extract(con, EMMC_CLK_DIV_SHIFT, 8);
  399. con = readl(&cru->clksel_con[25]);
  400. if ((con & EMMC_PLL_SEL_MASK) >> EMMC_PLL_SEL_SHIFT == EMMC_PLL_SEL_OSC)
  401. mmc_clk = DIV_TO_RATE(OSC_HZ, div) / 2;
  402. else
  403. mmc_clk = DIV_TO_RATE(GPLL_HZ, div) / 2;
  404. debug("%s div %d get_clk %ld\n", __func__, div, mmc_clk);
  405. return mmc_clk;
  406. }
  407. static ulong rv1108_mmc_set_clk(struct rv1108_cru *cru, ulong rate)
  408. {
  409. int div;
  410. u32 pll_rate;
  411. div = DIV_ROUND_UP(rkclk_pll_get_rate(cru, CLK_GENERAL), rate);
  412. if (div < 127) {
  413. debug("%s source gpll\n", __func__);
  414. rk_clrsetreg(&cru->clksel_con[25], EMMC_PLL_SEL_MASK,
  415. (EMMC_PLL_SEL_GPLL << EMMC_PLL_SEL_SHIFT));
  416. pll_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
  417. } else {
  418. debug("%s source 24m\n", __func__);
  419. rk_clrsetreg(&cru->clksel_con[25], EMMC_PLL_SEL_MASK,
  420. (EMMC_PLL_SEL_OSC << EMMC_PLL_SEL_SHIFT));
  421. pll_rate = OSC_HZ;
  422. }
  423. div = DIV_ROUND_UP(pll_rate / 2, rate);
  424. rk_clrsetreg(&cru->clksel_con[26], EMMC_CLK_DIV_MASK,
  425. ((div - 1) << EMMC_CLK_DIV_SHIFT));
  426. debug("%s set_rate %ld div %d\n", __func__, rate, div);
  427. return DIV_TO_RATE(pll_rate, div);
  428. }
  429. static ulong rv1108_clk_get_rate(struct clk *clk)
  430. {
  431. struct rv1108_clk_priv *priv = dev_get_priv(clk->dev);
  432. switch (clk->id) {
  433. case 0 ... 63:
  434. return rkclk_pll_get_rate(priv->cru, clk->id);
  435. case SCLK_SARADC:
  436. return rv1108_saradc_get_clk(priv->cru);
  437. case ACLK_VIO0:
  438. return rv1108_aclk_vio0_get_clk(priv->cru);
  439. case ACLK_VIO1:
  440. return rv1108_aclk_vio1_get_clk(priv->cru);
  441. case DCLK_VOP:
  442. return rv1108_dclk_vop_get_clk(priv->cru);
  443. case ACLK_PRE:
  444. return rv1108_aclk_bus_get_clk(priv->cru);
  445. case ACLK_PERI:
  446. return rv1108_aclk_peri_get_clk(priv->cru);
  447. case HCLK_PERI:
  448. return rv1108_hclk_peri_get_clk(priv->cru);
  449. case PCLK_PERI:
  450. return rv1108_pclk_peri_get_clk(priv->cru);
  451. case SCLK_I2C0_PMU:
  452. case SCLK_I2C1:
  453. case SCLK_I2C2:
  454. case SCLK_I2C3:
  455. return rv1108_i2c_get_clk(priv->cru, clk->id);
  456. case HCLK_EMMC:
  457. case SCLK_EMMC:
  458. case SCLK_EMMC_SAMPLE:
  459. return rv1108_mmc_get_clk(priv->cru);
  460. default:
  461. return -ENOENT;
  462. }
  463. }
  464. static ulong rv1108_clk_set_rate(struct clk *clk, ulong rate)
  465. {
  466. struct rv1108_clk_priv *priv = dev_get_priv(clk->dev);
  467. ulong new_rate;
  468. switch (clk->id) {
  469. case SCLK_MAC:
  470. new_rate = rv1108_mac_set_clk(priv->cru, rate);
  471. break;
  472. case SCLK_SFC:
  473. new_rate = rv1108_sfc_set_clk(priv->cru, rate);
  474. break;
  475. case SCLK_SARADC:
  476. new_rate = rv1108_saradc_set_clk(priv->cru, rate);
  477. break;
  478. case ACLK_VIO0:
  479. new_rate = rv1108_aclk_vio0_set_clk(priv->cru, rate);
  480. break;
  481. case ACLK_VIO1:
  482. new_rate = rv1108_aclk_vio1_set_clk(priv->cru, rate);
  483. break;
  484. case DCLK_VOP:
  485. new_rate = rv1108_dclk_vop_set_clk(priv->cru, rate);
  486. break;
  487. case ACLK_PRE:
  488. new_rate = rv1108_aclk_bus_set_clk(priv->cru, rate);
  489. break;
  490. case ACLK_PERI:
  491. new_rate = rv1108_aclk_peri_set_clk(priv->cru, rate);
  492. break;
  493. case HCLK_PERI:
  494. new_rate = rv1108_hclk_peri_set_clk(priv->cru, rate);
  495. break;
  496. case PCLK_PERI:
  497. new_rate = rv1108_pclk_peri_set_clk(priv->cru, rate);
  498. break;
  499. case SCLK_I2C0_PMU:
  500. case SCLK_I2C1:
  501. case SCLK_I2C2:
  502. case SCLK_I2C3:
  503. new_rate = rv1108_i2c_set_clk(priv->cru, clk->id, rate);
  504. break;
  505. case HCLK_EMMC:
  506. case SCLK_EMMC:
  507. new_rate = rv1108_mmc_set_clk(priv->cru, rate);
  508. break;
  509. default:
  510. return -ENOENT;
  511. }
  512. return new_rate;
  513. }
  514. static const struct clk_ops rv1108_clk_ops = {
  515. .get_rate = rv1108_clk_get_rate,
  516. .set_rate = rv1108_clk_set_rate,
  517. };
  518. static void rkclk_init(struct rv1108_cru *cru)
  519. {
  520. unsigned int apll, dpll, gpll;
  521. unsigned int aclk_bus, aclk_peri, hclk_peri, pclk_peri;
  522. aclk_bus = rv1108_aclk_bus_set_clk(cru, ACLK_BUS_HZ / 2);
  523. aclk_peri = rv1108_aclk_peri_set_clk(cru, ACLK_PERI_HZ / 2);
  524. hclk_peri = rv1108_hclk_peri_set_clk(cru, HCLK_PERI_HZ / 2);
  525. pclk_peri = rv1108_pclk_peri_set_clk(cru, PCLK_PERI_HZ / 2);
  526. rv1108_aclk_vio0_set_clk(cru, 297000000);
  527. rv1108_aclk_vio1_set_clk(cru, 297000000);
  528. /* configure apll */
  529. rkclk_set_pll(cru, CLK_ARM, &apll_init_cfg);
  530. rkclk_set_pll(cru, CLK_GENERAL, &gpll_init_cfg);
  531. aclk_bus = rv1108_aclk_bus_set_clk(cru, ACLK_BUS_HZ);
  532. aclk_peri = rv1108_aclk_peri_set_clk(cru, ACLK_PERI_HZ);
  533. hclk_peri = rv1108_hclk_peri_set_clk(cru, HCLK_PERI_HZ);
  534. pclk_peri = rv1108_pclk_peri_set_clk(cru, PCLK_PERI_HZ);
  535. apll = rkclk_pll_get_rate(cru, CLK_ARM);
  536. dpll = rkclk_pll_get_rate(cru, CLK_DDR);
  537. gpll = rkclk_pll_get_rate(cru, CLK_GENERAL);
  538. rk_clrsetreg(&cru->clksel_con[0], CORE_CLK_DIV_MASK,
  539. 0 << MAC_CLK_DIV_SHIFT);
  540. printf("APLL: %d DPLL:%d GPLL:%d\n", apll, dpll, gpll);
  541. printf("ACLK_BUS: %d ACLK_PERI:%d HCLK_PERI:%d PCLK_PERI:%d\n",
  542. aclk_bus, aclk_peri, hclk_peri, pclk_peri);
  543. }
  544. static int rv1108_clk_ofdata_to_platdata(struct udevice *dev)
  545. {
  546. struct rv1108_clk_priv *priv = dev_get_priv(dev);
  547. priv->cru = dev_read_addr_ptr(dev);
  548. return 0;
  549. }
  550. static int rv1108_clk_probe(struct udevice *dev)
  551. {
  552. struct rv1108_clk_priv *priv = dev_get_priv(dev);
  553. rkclk_init(priv->cru);
  554. return 0;
  555. }
  556. static int rv1108_clk_bind(struct udevice *dev)
  557. {
  558. int ret;
  559. struct udevice *sys_child;
  560. struct sysreset_reg *priv;
  561. /* The reset driver does not have a device node, so bind it here */
  562. ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
  563. &sys_child);
  564. if (ret) {
  565. debug("Warning: No sysreset driver: ret=%d\n", ret);
  566. } else {
  567. priv = malloc(sizeof(struct sysreset_reg));
  568. priv->glb_srst_fst_value = offsetof(struct rv1108_cru,
  569. glb_srst_fst_val);
  570. priv->glb_srst_snd_value = offsetof(struct rv1108_cru,
  571. glb_srst_snd_val);
  572. sys_child->priv = priv;
  573. }
  574. #if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
  575. ret = offsetof(struct rv1108_cru, softrst_con[0]);
  576. ret = rockchip_reset_bind(dev, ret, 13);
  577. if (ret)
  578. debug("Warning: software reset driver bind faile\n");
  579. #endif
  580. return 0;
  581. }
  582. static const struct udevice_id rv1108_clk_ids[] = {
  583. { .compatible = "rockchip,rv1108-cru" },
  584. { }
  585. };
  586. U_BOOT_DRIVER(clk_rv1108) = {
  587. .name = "clk_rv1108",
  588. .id = UCLASS_CLK,
  589. .of_match = rv1108_clk_ids,
  590. .priv_auto_alloc_size = sizeof(struct rv1108_clk_priv),
  591. .ops = &rv1108_clk_ops,
  592. .bind = rv1108_clk_bind,
  593. .ofdata_to_platdata = rv1108_clk_ofdata_to_platdata,
  594. .probe = rv1108_clk_probe,
  595. };