drv_clock.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2018-02-08 RT-Thread the first version
  9. */
  10. #include <rtthread.h>
  11. #include <rthw.h>
  12. #include "drv_clock.h"
  13. int cpu_get_pll_clk(void)
  14. {
  15. rt_uint32_t reg;
  16. int n, k, m, p;
  17. reg = CCU->pll_cpu_ctrl;
  18. if (!(reg & (0x01 << 31)))
  19. return 0;
  20. p = PLL_CPU_DIV_P(reg) + 1;
  21. n = PLL_CPU_FACTOR_N(reg) + 1;
  22. k = PLL_CPU_FACTOR_K(reg) + 1;
  23. m = PLL_CPU_FACTOR_M(reg) + 1;
  24. //(24MHz*n*k)/(m*p)
  25. return (_24MHZ_ * n * k) / (m * p);
  26. }
  27. int audio_get_pll_clk(void)
  28. {
  29. rt_uint32_t reg;
  30. unsigned char n, m;
  31. reg = CCU->pll_audio_ctrl;
  32. if (!(reg & (0x01 << 31)))
  33. return 0;
  34. n = PLL_AUDIO_FACTOR_N(reg) + 1;
  35. m = PLL_AUDIO_PREDIV_M(reg) + 1;
  36. //24MHz*n*2/m
  37. return _24MHZ_ * 2 * n / m;
  38. }
  39. int video_get_pll_clk(void)
  40. {
  41. rt_uint32_t reg;
  42. int n, m;
  43. reg = CCU->pll_video_ctrl;
  44. if (!(reg & (0x01 << 31)))
  45. return 0;
  46. if (reg & PLL_VIDEO_MODE_SEL)
  47. {
  48. //(24MHz*n)/m
  49. n = PLL_VIDEO_FACTOR_N(reg) + 1;
  50. m = PLL_VIDEO_PREDIV_M(reg) + 1;
  51. return (_24MHZ_ * n) / m;
  52. }
  53. if (reg & PLL_VIDEO_FRAC_CLK_OUT)
  54. return 270000000;
  55. else
  56. return 297000000;
  57. return 0;
  58. }
  59. int ve_get_pll_clk(void)
  60. {
  61. rt_uint32_t reg;
  62. int n, m;
  63. reg = CCU->pll_ve_ctrl;
  64. if (!(reg & (0x01 << 31)))
  65. return 0;
  66. if (reg & PLL_VE_MODE_SEL)
  67. {
  68. //(24MHz*n)/m
  69. n = PLL_VE_FACTOR_N(reg) + 1;
  70. m = PLL_VE_PREDIV_M(reg) + 1;
  71. return (_24MHZ_ * n) / m;
  72. }
  73. if (reg & PLL_VE_FRAC_CLK_OUT)
  74. return 297000000;
  75. else
  76. return 270000000;
  77. return 0;
  78. }
  79. int ddr_get_pll_clk(void)
  80. {
  81. rt_uint32_t reg;
  82. int n, k, m;
  83. reg = CCU->pll_ddr_ctrl;
  84. if (!(reg & (0x01 << 31)))
  85. return 0;
  86. n = PLL_DDR_FACTOR_N(reg) + 1;
  87. k = PLL_DDR_FACTOR_K(reg) + 1;
  88. m = PLL_DDR_FACTOR_M(reg) + 1;
  89. //(24MHz*n*k)/m
  90. return (_24MHZ_ * n * k) / m;
  91. }
  92. int periph_get_pll_clk(void)
  93. {
  94. rt_uint32_t reg;
  95. int n, k;
  96. reg = CCU->pll_periph_ctrl;
  97. if (!(reg & (0x01 << 31)))
  98. return 0;
  99. n = PLL_PERIPH_FACTOR_N(reg) + 1;
  100. k = PLL_PERIPH_FACTOR_K(reg) + 1;
  101. return _24MHZ_ * n * k;
  102. }
  103. static int cpu_get_clk_src(void)
  104. {
  105. return (CCU->cpu_clk_src >> 16) & 0x3;
  106. }
  107. int cpu_get_clk(void)
  108. {
  109. rt_uint32_t reg;
  110. int cpusrc;
  111. reg = CCU->ahb_apb_hclkc_cfg;
  112. cpusrc = cpu_get_clk_src();
  113. if (cpusrc == CLK_PLL_SRC)
  114. return (cpu_get_pll_clk() / (HCLKC_DIV(reg) + 1));
  115. else if (cpusrc == CLK_OSC24M_SRC)
  116. return _24MHZ_ / (HCLKC_DIV(reg) + 1);
  117. else
  118. return _32KHZ_ / (HCLKC_DIV(reg) + 1); //猜测 内部32KHz时钟
  119. return 0;
  120. }
  121. int ahb_get_clk(void)
  122. {
  123. rt_uint32_t reg;
  124. int sel, spd;
  125. reg = CCU->ahb_apb_hclkc_cfg;
  126. sel = AHB_SRC_SEL(reg);
  127. if (sel == CLK_PLL_SRC)
  128. {
  129. spd = cpu_get_clk();
  130. return spd / (1 << AHB_CLK_DIV(reg));
  131. }
  132. else if (sel == PRE_DIV_SRC)
  133. {
  134. spd = periph_get_pll_clk();
  135. return spd / (AHB_PRE_DIV(reg) + 1) / (1 << AHB_CLK_DIV(reg));
  136. }
  137. else if (sel == CLK_OSC24M_SRC)
  138. return _24MHZ_ / (1 << AHB_CLK_DIV(reg));
  139. else
  140. return _32KHZ_ / (1 << AHB_CLK_DIV(reg));
  141. }
  142. int apb_get_clk(void)
  143. {
  144. rt_uint32_t reg;
  145. int spd;
  146. reg = CCU->ahb_apb_hclkc_cfg;
  147. spd = ahb_get_clk();
  148. // 0x:/2 10:/4 11:/8
  149. if (!(APH_CLK_PATIO(reg) & 0x1))
  150. return spd / 2;
  151. else
  152. return spd / (1 << APH_CLK_PATIO(reg));
  153. }
  154. static rt_err_t wait_pll_stable(rt_uint32_t base)
  155. {
  156. rt_uint32_t rval = 0;
  157. volatile int time = 0xfff;
  158. do
  159. {
  160. rval = *((volatile rt_uint32_t *)base);
  161. time--;
  162. }
  163. while (time && !(rval & (1 << 28)));
  164. return !time;
  165. }
  166. rt_err_t cpu_set_pll_clk(int clk)
  167. {
  168. rt_uint32_t cpu_src;
  169. int p = 0, k = 1, m = 1, n = 0;
  170. if (clk == 0)
  171. return RT_EINVAL;
  172. if (clk > 1152000000)
  173. {
  174. k = 2;
  175. }
  176. else if (clk > 768000000)
  177. {
  178. k = 3;
  179. m = 2;
  180. }
  181. n = clk / (_24MHZ_ * k / m) - 1;
  182. cpu_src = (CCU->cpu_clk_src >> 16) & 0x3;
  183. CCU->cpu_clk_src = CLK_OSC24M_SRC << 16;
  184. CCU->pll_cpu_ctrl &= ~(0x1 << 31);
  185. //PLL1 rate = ((24000000 * n * k) >> 0) / m (p is ignored)
  186. CCU->pll_cpu_ctrl = (0x1 << 31) | (m << 0) | (k << 4) | (n << 8) | (p << 16);
  187. if (wait_pll_stable((rt_uint32_t)(&CCU->pll_cpu_ctrl)))
  188. return RT_ERROR;
  189. CCU->cpu_clk_src = cpu_src << 16;
  190. return RT_EOK;
  191. }
  192. rt_err_t audio_set_pll_clk(int clk)
  193. {
  194. int n = 0, m = 0;
  195. int n_temp = clk;
  196. int m_temp = _24MHZ_ * 2;
  197. if ((clk > 200000000) || (clk < 20000000))
  198. return RT_EINVAL;
  199. if (clk == 0)
  200. {
  201. CCU->pll_audio_ctrl &= ~(0x1 << 31);
  202. return RT_EOK;
  203. }
  204. while (n_temp != m_temp)
  205. {
  206. if (n_temp > m_temp)
  207. {
  208. n_temp = n_temp - m_temp;
  209. }
  210. else if (m_temp > n_temp)
  211. {
  212. m_temp = m_temp - n_temp;
  213. }
  214. }
  215. n = clk / n_temp;
  216. m = _24MHZ_ * 2 / m_temp;
  217. if ((n > 128) || (m > 32) || (clk != (_24MHZ_ * n * 2) / m))
  218. return RT_ERROR;
  219. CCU->pll_audio_ctrl &= ~(0x1 << 31);
  220. n = (n - 1) & 0x7f;
  221. m = (m - 1) & 0x1f;
  222. //clk = (24 * n * 2) / m
  223. CCU->pll_audio_ctrl = (0x1 << 31) | (0x0 << 24) | (n << 8) | m;
  224. if (wait_pll_stable((rt_uint32_t)(&CCU->pll_audio_ctrl)))
  225. return RT_ERROR;
  226. else
  227. return RT_EOK;
  228. }
  229. rt_err_t video_set_pll_clk(int clk)
  230. {
  231. int n = 0, m = 0;
  232. int n_temp = clk;
  233. int m_temp = _24MHZ_;
  234. if ((clk > 600000000) || (clk < 30000000))
  235. return RT_EINVAL;
  236. if (clk == 0)
  237. {
  238. CCU->pll_video_ctrl &= ~(0x1 << 31);
  239. return RT_EOK;
  240. }
  241. while (n_temp != m_temp)
  242. {
  243. if (n_temp > m_temp)
  244. {
  245. n_temp = n_temp - m_temp;
  246. }
  247. else if (m_temp > n_temp)
  248. {
  249. m_temp = m_temp - n_temp;
  250. }
  251. }
  252. n = clk / n_temp;
  253. m = _24MHZ_ / m_temp;
  254. if ((n > 128) || (m > 16) || (clk != (_24MHZ_ * n) / m))
  255. return RT_ERROR;
  256. CCU->pll_video_ctrl &= ~(0x1 << 31);
  257. n = (n - 1) & 0x7f;
  258. m = (m - 1) & 0xf;
  259. //speed = (24*n)/m
  260. CCU->pll_video_ctrl = (0x1 << 31) | (0x0 << 30) | (0x1 << 24) | (n << 8) | m;
  261. if (wait_pll_stable((rt_uint32_t)(&CCU->pll_video_ctrl)))
  262. return RT_ERROR;
  263. else
  264. return RT_EOK;
  265. }
  266. rt_err_t ve_set_pll_clk(int clk)
  267. {
  268. int n = 0, m = 0;
  269. int n_temp = clk;
  270. int m_temp = _24MHZ_;
  271. if ((clk > 600000000) || (clk < 30000000))
  272. return RT_EINVAL;
  273. if (clk == 0)
  274. {
  275. CCU->pll_ve_ctrl &= ~(0x1 << 31);
  276. return RT_EOK;
  277. }
  278. while (n_temp != m_temp)
  279. {
  280. if (n_temp > m_temp)
  281. {
  282. n_temp = n_temp - m_temp;
  283. }
  284. else if (m_temp > n_temp)
  285. {
  286. m_temp = m_temp - n_temp;
  287. }
  288. }
  289. n = clk / n_temp;
  290. m = _24MHZ_ / m_temp;
  291. if ((n > 128) || (m > 16) || (clk != (_24MHZ_ * n) / m))
  292. return RT_ERROR;
  293. CCU->pll_ve_ctrl &= ~(0x1 << 31);
  294. n = (n - 1) & 0x7f;
  295. m = (m - 1) & 0xf;
  296. //clk = (24 * n) / m
  297. CCU->pll_ve_ctrl = (0x1 << 31) | (0x1 << 24) | (n << 8) | m;
  298. if (wait_pll_stable((rt_uint32_t)(&CCU->pll_ve_ctrl)))
  299. return RT_ERROR;
  300. else
  301. return RT_EOK;
  302. }
  303. rt_err_t periph_set_pll_clk(int clk)
  304. {
  305. rt_uint32_t clk_src;
  306. rt_uint32_t temp_data;
  307. int n = 0, k = 0;
  308. if ((clk > 1800000000) || (clk < 200000000) || (clk == 0) || (clk % _24MHZ_ != 0))
  309. return RT_EINVAL;
  310. n = clk / _24MHZ_;
  311. for (k = 2; ((n > 32) || (k < 5)); k++)
  312. {
  313. if ((n % k) != 0)
  314. n /= k;
  315. }
  316. if ((n > 32) || (k > 4) || (clk != (_24MHZ_ * n * k)))
  317. return RT_ERROR;
  318. temp_data = CCU->ahb_apb_hclkc_cfg;
  319. clk_src = (temp_data >> 12) & 0x3;
  320. temp_data &= ~(0x3 << 12);
  321. temp_data |= (CLK_PLL_SRC << 12);
  322. CCU->ahb_apb_hclkc_cfg = temp_data;
  323. CCU->pll_periph_ctrl &= ~(0x1 << 31);
  324. n = (n - 1) & 0x1f;
  325. k = (k - 1) & 0x3;
  326. //clk = 24 * n *k
  327. CCU->pll_periph_ctrl = (0x1 << 31) | (0x1 << 18) | (n << 8) | (k << 4) || (0x1);
  328. if (wait_pll_stable((rt_uint32_t)(&CCU->pll_periph_ctrl)))
  329. return RT_ERROR;
  330. temp_data = CCU->ahb_apb_hclkc_cfg;
  331. temp_data &= ~(0x3 << 12);
  332. temp_data |= (clk_src << 12);
  333. CCU->ahb_apb_hclkc_cfg = temp_data;
  334. return RT_EOK;
  335. }
  336. rt_err_t cpu_set_clk(int clk)
  337. {
  338. if (clk < _24MHZ_)
  339. return RT_EINVAL;
  340. if (clk == cpu_get_clk())
  341. return RT_EOK;
  342. CCU->cpu_clk_src = CLK_OSC24M_SRC << 16;
  343. if (clk == _24MHZ_)
  344. return RT_EOK;
  345. if (cpu_set_pll_clk(clk))
  346. return RT_ERROR;
  347. CCU->ahb_apb_hclkc_cfg &= ~(0x3 << 16);
  348. CCU->cpu_clk_src = CLK_PLL_SRC << 16;
  349. return RT_EOK;
  350. }
  351. rt_err_t bus_gate_clk_enalbe(enum bus_gate bus)
  352. {
  353. rt_uint32_t offset;
  354. rt_uint32_t gate_reg;
  355. offset = bus & 0xfff;
  356. gate_reg = bus >> BUS_GATE_OFFSET_BIT;
  357. if (gate_reg == 0x00)
  358. CCU->bus_clk_gating0 |= (0x1 << offset);
  359. else if (gate_reg == 0x01)
  360. CCU->bus_clk_gating1 |= (0x1 << offset);
  361. else if (gate_reg == 0x02)
  362. CCU->bus_clk_gating2 |= (0x1 << offset);
  363. else
  364. return RT_EINVAL;
  365. return RT_EOK;
  366. }
  367. rt_err_t bus_gate_clk_disalbe(enum bus_gate bus)
  368. {
  369. rt_uint32_t offset;
  370. rt_uint32_t gate_reg;
  371. offset = bus & 0xfff;
  372. gate_reg = bus >> BUS_GATE_OFFSET_BIT;
  373. if (gate_reg == 0x00)
  374. CCU->bus_clk_gating0 &= ~(0x1 << offset);
  375. else if (gate_reg == 0x01)
  376. CCU->bus_clk_gating1 &= ~(0x1 << offset);
  377. else if (gate_reg == 0x02)
  378. CCU->bus_clk_gating2 &= ~(0x1 << offset);
  379. else
  380. return RT_EINVAL;
  381. return RT_EOK;
  382. }
  383. rt_err_t bus_software_reset_disalbe(enum bus_gate bus)
  384. {
  385. rt_uint32_t offset;
  386. rt_uint32_t gate_reg;
  387. offset = bus & 0xfff;
  388. gate_reg = bus >> BUS_GATE_OFFSET_BIT;
  389. if (gate_reg == 0x00)
  390. CCU->bus_soft_rst0 |= (0x1 << offset);
  391. else if (gate_reg == 0x01)
  392. CCU->bus_soft_rst1 |= (0x1 << offset);
  393. else if (gate_reg == 0x02)
  394. CCU->bus_soft_rst2 |= (0x1 << offset);
  395. else
  396. return RT_EINVAL;
  397. return RT_EOK;
  398. }
  399. rt_err_t bus_software_reset_enalbe(enum bus_gate bus)
  400. {
  401. rt_uint32_t offset;
  402. rt_uint32_t gate_reg;
  403. offset = bus & 0xfff;
  404. gate_reg = bus >> BUS_GATE_OFFSET_BIT;
  405. if (gate_reg == 0x00)
  406. CCU->bus_soft_rst0 &= ~(0x1 << offset);
  407. else if (gate_reg == 0x01)
  408. CCU->bus_soft_rst1 &= ~(0x1 << offset);
  409. else if (gate_reg == 0x02)
  410. CCU->bus_soft_rst2 &= ~(0x1 << offset);
  411. else
  412. return RT_EINVAL;
  413. return RT_EOK;
  414. }
  415. rt_err_t mmc_set_clk(enum mmc_clk_id clk_id, int hz)
  416. {
  417. unsigned int pll, pll_hz, div, n, oclk_dly, sclk_dly;
  418. volatile rt_uint32_t *mmc_clk = (clk_id == SDMMC0) ? \
  419. (&CCU->sdmmc0_clk) : (&CCU->sdmmc1_clk);
  420. if (hz < 0)
  421. {
  422. return RT_EINVAL;
  423. }
  424. if (hz == 0)
  425. {
  426. *mmc_clk &= ~(0x1 << 31);
  427. return RT_EOK;
  428. }
  429. if (hz <= 24000000)
  430. {
  431. pll = (0x0 << 24);
  432. pll_hz = 24000000;
  433. }
  434. else
  435. {
  436. pll = (0x1 << 24);
  437. pll_hz = periph_get_pll_clk();
  438. }
  439. div = pll_hz / hz;
  440. if (pll_hz % hz)
  441. {
  442. div++;
  443. }
  444. n = 0;
  445. while (div > 16)
  446. {
  447. n++;
  448. div = (div + 1) / 2;
  449. }
  450. if (n > 3)
  451. {
  452. return -1;
  453. }
  454. /* determine delays */
  455. if (hz <= 400000)
  456. {
  457. oclk_dly = 0;
  458. sclk_dly = 0;
  459. }
  460. else if (hz <= 25000000)
  461. {
  462. oclk_dly = 0;
  463. sclk_dly = 5;
  464. }
  465. else if (hz <= 50000000)
  466. {
  467. oclk_dly = 3;
  468. sclk_dly = 4;
  469. }
  470. else
  471. {
  472. /* hz > 50000000 */
  473. oclk_dly = 1;
  474. sclk_dly = 4;
  475. }
  476. *mmc_clk = (0x1 << 31) | pll | (sclk_dly << 20) | \
  477. (n << 16) | (oclk_dly << 8) | (div - 1);
  478. return RT_EOK;
  479. }
  480. rt_err_t dram_gate_clk_enable(enum dram_gate dram_gate)
  481. {
  482. CCU->dram_gating |= (0x01 << dram_gate);
  483. return RT_EOK;
  484. }
  485. rt_err_t dram_gate_clk_disable(enum dram_gate dram_gate)
  486. {
  487. CCU->dram_gating &= ~(0x01 << dram_gate);
  488. return RT_EOK;
  489. }