clk.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830
  1. /* Copyright (c) 2019-2025 Allwinner Technology Co., Ltd. ALL rights reserved.
  2. *
  3. * Allwinner is a trademark of Allwinner Technology Co.,Ltd., registered in
  4. *the the People's Republic of China and other countries.
  5. * All Allwinner Technology Co.,Ltd. trademarks are used with permission.
  6. *
  7. * DISCLAIMER
  8. * THIRD PARTY LICENCES MAY BE REQUIRED TO IMPLEMENT THE SOLUTION/PRODUCT.
  9. * IF YOU NEED TO INTEGRATE THIRD PARTY’S TECHNOLOGY (SONY, DTS, DOLBY, AVS OR MPEGLA, ETC.)
  10. * IN ALLWINNERS’SDK OR PRODUCTS, YOU SHALL BE SOLELY RESPONSIBLE TO OBTAIN
  11. * ALL APPROPRIATELY REQUIRED THIRD PARTY LICENCES.
  12. * ALLWINNER SHALL HAVE NO WARRANTY, INDEMNITY OR OTHER OBLIGATIONS WITH RESPECT TO MATTERS
  13. * COVERED UNDER ANY REQUIRED THIRD PARTY LICENSE.
  14. * YOU ARE SOLELY RESPONSIBLE FOR YOUR USAGE OF THIRD PARTY’S TECHNOLOGY.
  15. *
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY ALLWINNER"AS IS" AND TO THE MAXIMUM EXTENT
  18. * PERMITTED BY LAW, ALLWINNER EXPRESSLY DISCLAIMS ALL WARRANTIES OF ANY KIND,
  19. * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION REGARDING
  20. * THE TITLE, NON-INFRINGEMENT, ACCURACY, CONDITION, COMPLETENESS, PERFORMANCE
  21. * OR MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  22. * IN NO EVENT SHALL ALLWINNER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  24. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25. * LOSS OF USE, DATA, OR PROFITS, OR BUSINESS INTERRUPTION)
  26. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  27. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  28. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  29. * OF THE POSSIBILITY OF SUCH DAMAGE.
  30. */
  31. #include "sunxi_hal_common.h"
  32. #include "clk.h"
  33. #include "clk_periph.h"
  34. #include "clk_factors.h"
  35. #include <stdio.h>
  36. #include <string.h>
  37. extern clk_core_pt sunxi_clk_fixed_src_arry[];
  38. extern clk_fixed_factor_pt sunxi_clk_fixed_factor_arry[];
  39. extern clk_factor_pt sunxi_clk_factor_arry[];
  40. extern clk_periph_pt sunxi_clk_periph_arry[];
  41. extern clk_base_pt sunxi_periph_clk_init_arry[];
  42. extern hal_clk_status_t (*sunxi_clk_factor_init[])(void);
  43. static hal_clk_status_t sunxi_clk_set_parent(hal_clk_id_t clk, hal_clk_id_t parent_clk);
  44. static hal_clk_status_t sunxi_clk_get_parent(hal_clk_id_t clk, hal_clk_id_t *parent_clk);
  45. static hal_clk_status_t sunxi_clk_disable(hal_clk_id_t clk);
  46. static hal_clk_status_t sunxi_clk_enabled(hal_clk_id_t clk);
  47. static hal_clk_status_t sunxi_clk_is_enabled(hal_clk_id_t clk);
  48. static hal_clk_status_t sunxi_clk_round_rate(hal_clk_id_t clk, u32 rate, u32 *prate);
  49. static hal_clk_status_t sunxi_clk_recalc_rate(hal_clk_id_t clk, u32 *rate);
  50. static hal_clk_status_t sunxi_clk_get_rate(hal_clk_id_t clk, u32 *rate);
  51. static hal_clk_status_t sunxi_clk_set_rate(hal_clk_id_t clk, u32 rate);
  52. static inline uint64_t read_cntpct(void)
  53. {
  54. u64 val;
  55. asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r"(val));
  56. return val;
  57. }
  58. static inline uint32_t read_cntfrq(void)
  59. {
  60. u32 frq;
  61. asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r"(frq));
  62. return frq;
  63. }
  64. void clk_udelay(u32 us)
  65. {
  66. u64 start, target;
  67. start = read_cntpct();
  68. target = read_cntfrq() / 1000000ULL * us;
  69. while (read_cntpct() - start <= target) ;
  70. }
  71. clk_core_pt clk_get_core(hal_clk_id_t clk)
  72. {
  73. clk_core_pt pclk = NULL;
  74. u32 i;
  75. switch (HAL_CLK_GET_TYPE(clk))
  76. {
  77. /* */
  78. case HAL_CLK_PERIPH:
  79. for (i = 0; sunxi_clk_periph_arry[i] != NULL; i++)
  80. {
  81. pclk = (clk_core_pt)sunxi_clk_periph_arry[i];
  82. if (pclk->clk == clk)
  83. {
  84. break;
  85. }
  86. }
  87. break;
  88. /* */
  89. case HAL_CLK_FACTOR:
  90. for (i = 0; sunxi_clk_factor_arry[i] != NULL; i++)
  91. {
  92. pclk = (clk_core_pt)sunxi_clk_factor_arry[i];
  93. if (pclk->clk == clk)
  94. {
  95. break;
  96. }
  97. }
  98. break;
  99. /* */
  100. case HAL_CLK_FIXED_SRC:
  101. for (i = 0; sunxi_clk_fixed_src_arry[i] != NULL; i++)
  102. {
  103. pclk = (clk_core_pt)sunxi_clk_fixed_src_arry[i];
  104. if (pclk->clk == clk)
  105. {
  106. break;
  107. }
  108. }
  109. break;
  110. /* */
  111. case HAL_CLK_FIXED_FACTOR:
  112. for (i = 0; sunxi_clk_fixed_factor_arry[i] != NULL; i++)
  113. {
  114. pclk = (clk_core_pt)sunxi_clk_fixed_factor_arry[i];
  115. if (pclk->clk == clk)
  116. {
  117. break;
  118. }
  119. }
  120. break;
  121. /* */
  122. default:
  123. break;
  124. }
  125. return pclk;
  126. }
  127. hal_clk_status_t sunxi_clk_set_parent(hal_clk_id_t clk, hal_clk_id_t parent_clk)
  128. {
  129. u32 i = 0, cnt = 0, parent_rate = 0;
  130. u8 index = 0;
  131. hal_clk_status_t ret = HAL_CLK_STATUS_ERROR_CLK_NOT_FOUND;
  132. clk_core_pt pclk = NULL;
  133. clk_periph_pt periph_clk = NULL;
  134. CCMU_TRACE();
  135. pclk = clk_get_core(clk);
  136. if (pclk == NULL)
  137. {
  138. return ret;
  139. }
  140. switch (pclk->clk_type)
  141. {
  142. case HAL_CLK_PERIPH:
  143. periph_clk = (clk_periph_pt)pclk;
  144. if (periph_clk->clk_core.current_parent == parent_clk)
  145. {
  146. return HAL_CLK_STATUS_OK;
  147. }
  148. for (i = 0; i < periph_clk->parent_arry_size; i++)
  149. {
  150. if (periph_clk->parent_arry[i] != parent_clk)
  151. {
  152. continue;
  153. }
  154. ret = sunxi_clk_periph_set_parent(periph_clk, i);
  155. break;
  156. }
  157. if (ret == HAL_CLK_STATUS_OK)
  158. {
  159. periph_clk->clk_core.current_parent = parent_clk;
  160. periph_clk->clk_core.current_parent_type = HAL_CLK_GET_TYPE(parent_clk);
  161. ret = sunxi_clk_recalc_rate(parent_clk, &parent_rate);
  162. if (ret == HAL_CLK_STATUS_OK)
  163. {
  164. periph_clk->clk_core.parent_rate = parent_rate;
  165. }
  166. else
  167. {
  168. periph_clk->clk_core.parent_rate = 0;
  169. }
  170. }
  171. break;
  172. /* */
  173. case HAL_CLK_FIXED_SRC:
  174. case HAL_CLK_FIXED_FACTOR:
  175. case HAL_CLK_FACTOR:
  176. ret = HAL_CLK_STATUS_OK;
  177. break;
  178. /* */
  179. default:
  180. ret = HAL_CLK_STATUS_ERROR_CLK_SET_RATE_REFUSED;
  181. break;
  182. }
  183. CCMU_TRACE();
  184. return ret;
  185. }
  186. hal_clk_status_t sunxi_clk_get_parent(hal_clk_id_t clk, hal_clk_id_t *parent_clk)
  187. {
  188. u32 i;
  189. u8 index = 0;
  190. hal_clk_status_t ret = HAL_CLK_STATUS_ERROR_CLK_NOT_FOUND;
  191. hal_clk_id_t parent;
  192. clk_core_pt pclk = NULL;
  193. clk_periph_pt periph_clk = NULL;
  194. CCMU_TRACE();
  195. pclk = clk_get_core(clk);
  196. if (pclk == NULL)
  197. {
  198. return ret;
  199. }
  200. switch (pclk->clk_type)
  201. {
  202. case HAL_CLK_PERIPH:
  203. periph_clk = (clk_periph_pt)pclk;
  204. ret = sunxi_clk_periph_get_parent(periph_clk, &index);
  205. if (ret != HAL_CLK_STATUS_OK)
  206. {
  207. break;
  208. }
  209. if (index >= periph_clk->parent_arry_size)
  210. {
  211. ret = HAL_CLK_STATUS_ERROT_CLK_UNDEFINED;
  212. break;
  213. }
  214. parent = periph_clk->parent_arry[index];
  215. if (periph_clk->clk_core.current_parent == parent)
  216. {
  217. break;
  218. }
  219. periph_clk->clk_core.current_parent = parent;
  220. periph_clk->clk_core.current_parent_type = HAL_CLK_GET_TYPE(parent);
  221. (*parent_clk) = parent;
  222. break;
  223. /* */
  224. case HAL_CLK_FIXED_SRC:
  225. case HAL_CLK_FIXED_FACTOR:
  226. case HAL_CLK_FACTOR:
  227. pclk = clk_get_core(clk);
  228. (*parent_clk) = pclk->current_parent;
  229. ret = HAL_CLK_STATUS_OK;
  230. break;
  231. /* */
  232. default:
  233. ret = HAL_CLK_STATUS_ERROT_CLK_UNDEFINED;
  234. break;
  235. }
  236. CCMU_TRACE();
  237. return ret;
  238. }
  239. hal_clk_status_t sunxi_clk_disable(hal_clk_id_t clk)
  240. {
  241. u32 i;
  242. hal_clk_status_t ret = HAL_CLK_STATUS_ERROR_CLK_NOT_FOUND;
  243. clk_core_pt pclk = NULL;
  244. clk_periph_pt periph_clk = NULL;
  245. clk_factor_pt factor_clk = NULL;
  246. CCMU_TRACE();
  247. pclk = clk_get_core(clk);
  248. if (pclk == NULL)
  249. {
  250. return ret;
  251. }
  252. switch (pclk->clk_type)
  253. {
  254. case HAL_CLK_PERIPH:
  255. periph_clk = (clk_periph_pt)pclk;
  256. ret = sunxi_clk_periph_disable(periph_clk);
  257. if (ret == HAL_CLK_STATUS_DISABLED)
  258. {
  259. periph_clk->clk_core.clk_enbale = HAL_CLK_STATUS_DISABLED;
  260. }
  261. return HAL_CLK_STATUS_OK;
  262. break;
  263. /* */
  264. case HAL_CLK_FACTOR:
  265. factor_clk = (clk_factor_pt)pclk;
  266. ret = sunxi_clk_fators_disable(factor_clk);
  267. if (ret == HAL_CLK_STATUS_DISABLED)
  268. {
  269. factor_clk->clk_core.clk_enbale = HAL_CLK_STATUS_DISABLED;
  270. }
  271. return HAL_CLK_STATUS_OK;
  272. break;
  273. /* */
  274. case HAL_CLK_FIXED_FACTOR:
  275. ret = HAL_CLK_STATUS_ERROR_CLK_FACTOR_REFUSED;
  276. break;
  277. /* */
  278. case HAL_CLK_FIXED_SRC:
  279. ret = HAL_CLK_STATUS_ERROR_CLK_FACTOR_REFUSED;
  280. break;
  281. /* */
  282. default:
  283. ret = HAL_CLK_STATUS_ERROT_CLK_UNDEFINED;
  284. break;
  285. }
  286. CCMU_TRACE();
  287. return ret;
  288. }
  289. hal_clk_status_t sunxi_clk_enabled(hal_clk_id_t clk)
  290. {
  291. u32 i;
  292. hal_clk_status_t ret = HAL_CLK_STATUS_ERROR_CLK_NOT_FOUND;
  293. clk_core_pt pclk = NULL;
  294. clk_periph_pt periph_clk = NULL;
  295. clk_factor_pt factor_clk = NULL;
  296. CCMU_TRACE();
  297. pclk = clk_get_core(clk);
  298. if (pclk == NULL)
  299. {
  300. return ret;
  301. }
  302. switch (pclk->clk_type)
  303. {
  304. case HAL_CLK_PERIPH:
  305. periph_clk = (clk_periph_pt)pclk;
  306. ret = sunxi_clk_periph_enable(periph_clk);
  307. if (ret == HAL_CLK_STATUS_ENABLED)
  308. {
  309. periph_clk->clk_core.clk_enbale = HAL_CLK_STATUS_ENABLED;
  310. }
  311. break;
  312. /* */
  313. case HAL_CLK_FACTOR:
  314. factor_clk = (clk_factor_pt)pclk;
  315. ret = sunxi_clk_fators_enable(factor_clk);
  316. if (ret == HAL_CLK_STATUS_ENABLED)
  317. {
  318. factor_clk->clk_core.clk_enbale = HAL_CLK_STATUS_ENABLED;
  319. }
  320. break;
  321. /* */
  322. case HAL_CLK_FIXED_SRC:
  323. case HAL_CLK_FIXED_FACTOR:
  324. return pclk->clk_enbale;
  325. break;
  326. /* */
  327. default:
  328. ret = HAL_CLK_STATUS_ERROT_CLK_UNDEFINED;
  329. break;
  330. }
  331. CCMU_TRACE();
  332. return ret;
  333. }
  334. hal_clk_status_t sunxi_clk_is_enabled(hal_clk_id_t clk)
  335. {
  336. u32 i;
  337. hal_clk_status_t ret = HAL_CLK_STATUS_ERROR_CLK_NOT_FOUND;
  338. clk_core_pt pclk = NULL;
  339. clk_periph_pt periph_clk = NULL;
  340. clk_factor_pt factor_clk = NULL;
  341. CCMU_TRACE();
  342. pclk = clk_get_core(clk);
  343. if (pclk == NULL)
  344. {
  345. return ret;
  346. }
  347. switch (pclk->clk_type)
  348. {
  349. case HAL_CLK_FIXED_SRC:
  350. case HAL_CLK_FIXED_FACTOR:
  351. return HAL_CLK_STATUS_ENABLED;
  352. break;
  353. /* */
  354. case HAL_CLK_FACTOR:
  355. factor_clk = (clk_factor_pt)pclk;
  356. return sunxi_clk_fators_is_enabled(factor_clk);
  357. break;
  358. /* */
  359. case HAL_CLK_PERIPH:
  360. periph_clk = (clk_periph_pt)pclk;
  361. return sunxi_clk_periph_is_enabled(periph_clk);
  362. break;
  363. /* */
  364. default:
  365. ret = HAL_CLK_STATUS_ERROT_CLK_UNDEFINED;
  366. break;
  367. }
  368. CCMU_TRACE();
  369. return ret;
  370. }
  371. hal_clk_status_t sunxi_clk_round_rate(hal_clk_id_t clk, u32 rate, u32 *prate)
  372. {
  373. u32 i, parent_rate = 0, round_rate = 0;
  374. hal_clk_status_t ret = HAL_CLK_STATUS_ERROR_CLK_NOT_FOUND;
  375. clk_core_pt pclk = NULL;
  376. clk_periph_pt periph_clk = NULL;
  377. clk_factor_pt factor_clk = NULL;
  378. CCMU_TRACE();
  379. pclk = clk_get_core(clk);
  380. if (pclk == NULL)
  381. {
  382. return ret;
  383. }
  384. switch (pclk->clk_type)
  385. {
  386. /* */
  387. case HAL_CLK_FIXED_SRC:
  388. case HAL_CLK_FIXED_FACTOR:
  389. (*prate) = pclk->clk_rate;
  390. ret = HAL_CLK_STATUS_OK;
  391. break;
  392. /* */
  393. case HAL_CLK_FACTOR:
  394. factor_clk = (clk_factor_pt)pclk;
  395. round_rate = sunxi_clk_factors_round_rate(factor_clk, rate);
  396. if (round_rate == 0)
  397. {
  398. ret = HAL_CLK_STATUS_ERROR_CLK_ROUND_FAILED;
  399. break;
  400. }
  401. *prate = round_rate;
  402. ret = HAL_CLK_STATUS_OK;
  403. break;
  404. /* */
  405. case HAL_CLK_PERIPH:
  406. periph_clk = (clk_periph_pt)pclk;
  407. parent_rate = periph_clk->clk_core.parent_rate;
  408. round_rate = sunxi_clk_periph_round_rate(periph_clk, rate, parent_rate);
  409. if (round_rate == 0)
  410. {
  411. ret = HAL_CLK_STATUS_ERROR_CLK_ROUND_FAILED;
  412. break;
  413. }
  414. *prate = round_rate;
  415. ret = HAL_CLK_STATUS_OK;
  416. break;
  417. /* */
  418. default:
  419. ret = HAL_CLK_STATUS_ERROT_CLK_UNDEFINED;
  420. return ret;
  421. break;
  422. }
  423. CCMU_TRACE();
  424. return ret;
  425. }
  426. hal_clk_status_t sunxi_clk_recalc_rate(hal_clk_id_t clk, u32 *rate)
  427. {
  428. u32 i, current_rate = 0;
  429. u8 index = 0;
  430. hal_clk_status_t ret = HAL_CLK_STATUS_OK;
  431. hal_clk_id_t parent;
  432. clk_core_pt pclk = NULL;
  433. clk_periph_pt periph_clk = NULL;
  434. clk_factor_pt factor_clk = NULL;
  435. CCMU_TRACE();
  436. pclk = clk_get_core(clk);
  437. if (pclk == NULL)
  438. {
  439. return HAL_CLK_STATUS_ERROT_CLK_UNDEFINED;
  440. }
  441. switch (pclk->clk_type)
  442. {
  443. case HAL_CLK_PERIPH:
  444. periph_clk = (clk_periph_pt)pclk;
  445. ret = sunxi_clk_periph_recalc_rate(periph_clk, &current_rate);
  446. if (ret != HAL_CLK_STATUS_OK)
  447. {
  448. ret = HAL_CLK_STATUS_DISABLED;
  449. break;
  450. }
  451. (*rate) = current_rate;
  452. break;
  453. case HAL_CLK_FACTOR:
  454. factor_clk = (clk_factor_pt)pclk;
  455. ret = sunxi_clk_factors_recalc_rate(factor_clk, &current_rate);
  456. if (ret != HAL_CLK_STATUS_OK)
  457. {
  458. ret = HAL_CLK_STATUS_DISABLED;
  459. break;
  460. }
  461. (*rate) = current_rate;
  462. break;
  463. /* */
  464. case HAL_CLK_FIXED_SRC:
  465. case HAL_CLK_FIXED_FACTOR:
  466. (*rate) = pclk->clk_rate;
  467. break;
  468. /* */
  469. default:
  470. ret = HAL_CLK_STATUS_ERROT_CLK_UNDEFINED;
  471. break;
  472. }
  473. return ret;
  474. }
  475. hal_clk_status_t sunxi_clk_get_rate(hal_clk_id_t clk, u32 *rate)
  476. {
  477. u32 i;
  478. clk_core_pt pclk = NULL;
  479. hal_clk_status_t ret = HAL_CLK_STATUS_OK;
  480. CCMU_TRACE();
  481. pclk = clk_get_core(clk);
  482. if (pclk == NULL)
  483. {
  484. return HAL_CLK_STATUS_ERROR_CLK_NOT_FOUND;
  485. }
  486. (*rate) = pclk->clk_rate;
  487. return HAL_CLK_STATUS_OK;
  488. }
  489. hal_clk_status_t sunxi_clk_set_rate(hal_clk_id_t clk, u32 rate)
  490. {
  491. u32 i, parent_rate;
  492. clk_core_pt pclk = NULL;
  493. clk_periph_pt periph_clk = NULL;
  494. clk_factor_pt factor_clk = NULL;
  495. hal_clk_status_t ret = HAL_CLK_STATUS_ERROR_CLK_NOT_FOUND;
  496. CCMU_TRACE();
  497. pclk = clk_get_core(clk);
  498. if (pclk == NULL)
  499. {
  500. return ret;
  501. }
  502. switch (HAL_CLK_GET_TYPE(clk))
  503. {
  504. /* */
  505. case HAL_CLK_PERIPH:
  506. periph_clk = (clk_periph_pt)pclk;
  507. if (periph_clk->clk_core.clk_enbale == HAL_CLK_STATUS_ENABLED)
  508. {
  509. return HAL_CLK_STATUS_ERROR_CLK_NEED_DISABLED;
  510. }
  511. if (periph_clk->clk_core.clk_rate == rate)
  512. {
  513. return HAL_CLK_STATUS_OK;
  514. }
  515. parent_rate = periph_clk->clk_core.parent_rate;
  516. ret = sunxi_clk_periph_set_rate(periph_clk, rate);
  517. if (ret == HAL_CLK_STATUS_OK)
  518. {
  519. periph_clk->clk_core.clk_rate = rate;
  520. }
  521. break;
  522. /* */
  523. case HAL_CLK_FACTOR:
  524. factor_clk = (clk_factor_pt)pclk;
  525. ret = sunxi_clk_factors_set_rate(factor_clk, rate);
  526. if (ret == HAL_CLK_STATUS_OK)
  527. {
  528. factor_clk->clk_core.clk_rate = rate;
  529. }
  530. break;
  531. /* */
  532. case HAL_CLK_FIXED_SRC:
  533. case HAL_CLK_FIXED_FACTOR:
  534. ret = HAL_CLK_STATUS_ERROR_CLK_SET_RATE_REFUSED;
  535. break;
  536. /* */
  537. default:
  538. ret = HAL_CLK_STATUS_ERROT_CLK_UNDEFINED;
  539. break;
  540. }
  541. CCMU_TRACE();
  542. return ret;
  543. }
  544. hal_clk_status_t sunxi_fixed_factor_clk_init(void)
  545. {
  546. u32 i = 0, parent_rate = 0;
  547. clk_core_pt pclk = NULL;
  548. clk_core_pt parent_clk_core = NULL;
  549. clk_fixed_factor_pt fixed_factor = NULL;
  550. hal_clk_status_t ret = HAL_CLK_STATUS_ERROR_CLK_NOT_FOUND;
  551. CCMU_TRACE();
  552. for (i = 0; sunxi_clk_fixed_factor_arry[i] != NULL; i++)
  553. {
  554. fixed_factor = sunxi_clk_fixed_factor_arry[i];
  555. parent_clk_core = clk_get_core(fixed_factor->clk_core.current_parent);
  556. if (parent_clk_core == NULL)
  557. {
  558. return ret;
  559. }
  560. if (parent_clk_core->clk_enbale == HAL_CLK_STATUS_DISABLED)
  561. {
  562. return HAL_CLK_STATUS_ERROR_CLK_PARENT_DISABLED;
  563. }
  564. parent_rate = parent_clk_core->clk_rate;
  565. fixed_factor->clk_core.clk_enbale = HAL_CLK_STATUS_ENABLED;
  566. fixed_factor->clk_core.parent_rate = parent_rate;
  567. fixed_factor->clk_core.clk_rate = (parent_rate * fixed_factor->clk_mult) / fixed_factor->clk_div;
  568. }
  569. ret = HAL_CLK_STATUS_OK;
  570. CCMU_TRACE();
  571. return ret;
  572. }
  573. hal_clk_status_t sunxi_periph_bus_clk_init(void)
  574. {
  575. hal_clk_status_t ret;
  576. clk_base_pt clk_init;
  577. clk_periph_pt pclk;
  578. hal_clk_id_t parent_clk;
  579. u32 i = 0, parent_rate = 0, round_rate = 0, check_rate = 0;
  580. CCMU_TRACE();
  581. for (i = 0; sunxi_periph_clk_init_arry[i] != NULL; i++)
  582. {
  583. parent_clk = HAL_CLK_UNINITIALIZED ;
  584. clk_init = sunxi_periph_clk_init_arry[i];
  585. pclk = (clk_periph_pt)clk_get_core(clk_init->clk);
  586. if (pclk == NULL)
  587. {
  588. return HAL_CLK_STATUS_ERROR_CLK_NOT_FOUND;
  589. }
  590. CCMU_DBG("Clk-id %d init start.................\n", clk_init->clk);
  591. /* check and set clk parent select regs*/
  592. ret = sunxi_clk_get_parent(clk_init->clk, &parent_clk);
  593. if (ret != HAL_CLK_STATUS_OK)
  594. {
  595. break;
  596. }
  597. if (clk_init->parent != parent_clk)
  598. {
  599. CCMU_DBG("set Parent-id %d \n", parent_clk);
  600. ret = sunxi_clk_set_parent(clk_init->clk, clk_init->parent);
  601. if (ret != HAL_CLK_STATUS_OK)
  602. {
  603. break;
  604. }
  605. }
  606. /* check and get round clk*/
  607. ret = sunxi_clk_get_rate(clk_init->parent, &parent_rate);
  608. if (ret != HAL_CLK_STATUS_OK)
  609. {
  610. break;
  611. }
  612. pclk->clk_core.current_parent = clk_init->parent;
  613. pclk->clk_core.parent_rate = parent_rate;
  614. ret = sunxi_clk_round_rate(clk_init->clk, clk_init->clk_rate, &round_rate);
  615. if (ret != HAL_CLK_STATUS_OK)
  616. {
  617. break;
  618. }
  619. CCMU_DBG("get round rate %dHZ\n", round_rate);
  620. /* check and disbale clk status*/
  621. ret = sunxi_clk_is_enabled(clk_init->clk);
  622. if (ret == HAL_CLK_STATUS_ENABLED)
  623. {
  624. ret = sunxi_clk_disable(clk_init->clk);
  625. if (ret != HAL_CLK_STATUS_OK)
  626. {
  627. break;
  628. }
  629. }
  630. CCMU_DBG("set new rate %dHZ\n", round_rate);
  631. /* set clk rate*/
  632. ret = sunxi_clk_set_rate(clk_init->clk, round_rate);
  633. if (ret != HAL_CLK_STATUS_OK)
  634. {
  635. break;
  636. }
  637. /* enable clk status*/
  638. ret = sunxi_clk_enabled(clk_init->clk);
  639. if (ret != HAL_CLK_STATUS_ENABLED)
  640. {
  641. break;
  642. }
  643. ret = sunxi_clk_recalc_rate(clk_init->clk, &check_rate);
  644. if (ret != HAL_CLK_STATUS_OK)
  645. {
  646. break;
  647. }
  648. CCMU_DBG("Clk-id %d cached rate %dHZ recalc new rate %dHZ, parent-id %d parent rate %dHZ \n", clk_init->clk, pclk->clk_core.clk_rate, check_rate,
  649. pclk->clk_core.current_parent, pclk->clk_core.parent_rate);
  650. CCMU_DBG("Clk-id %d init final .................\n", clk_init->clk);
  651. }
  652. CCMU_DBG("ret %d \n", ret);
  653. return ret;
  654. }
  655. hal_clk_status_t sunxi_factor_clk_init(void)
  656. {
  657. u32 i;
  658. hal_clk_status_t ret = HAL_CLK_STATUS_OK;
  659. hal_clk_status_t (*func)(void) = NULL;
  660. for (i = 0; sunxi_clk_factor_init[i] != NULL; i++)
  661. {
  662. func = sunxi_clk_factor_init[i];
  663. ret = func();
  664. if (ret != HAL_CLK_STATUS_OK)
  665. {
  666. break;
  667. }
  668. }
  669. return ret;
  670. }
  671. hal_clk_status_t clk_set_parent(hal_clk_id_t clk, hal_clk_id_t parent_clk)
  672. {
  673. return sunxi_clk_set_parent(clk, parent_clk);
  674. }
  675. hal_clk_id_t clk_get_parent(hal_clk_id_t clk)
  676. {
  677. hal_clk_id_t parent_clk = HAL_CLK_UNINITIALIZED ;
  678. hal_clk_status_t ret;
  679. ret = sunxi_clk_get_parent(clk, &parent_clk);
  680. if (ret == HAL_CLK_STATUS_OK)
  681. {
  682. return parent_clk;
  683. }
  684. else
  685. {
  686. return HAL_CLK_UNINITIALIZED;
  687. }
  688. }
  689. hal_clk_status_t clk_disable_unprepare(hal_clk_id_t clk)
  690. {
  691. return sunxi_clk_disable(clk);
  692. }
  693. hal_clk_status_t clk_prepare_enable(hal_clk_id_t clk)
  694. {
  695. return sunxi_clk_enabled(clk);
  696. }
  697. hal_clk_status_t clk_is_enabled(hal_clk_id_t clk)
  698. {
  699. return sunxi_clk_is_enabled(clk);
  700. }
  701. hal_clk_status_t clk_round_rate(hal_clk_id_t clk, u32 rate, u32 *prate)
  702. {
  703. return sunxi_clk_round_rate(clk, rate, prate);
  704. }
  705. hal_clk_status_t clk_recalc_rate(hal_clk_id_t clk, u32 *p_rate)
  706. {
  707. return sunxi_clk_recalc_rate(clk, p_rate);
  708. }
  709. hal_clk_status_t clk_set_rate(hal_clk_id_t clk, u32 rate)
  710. {
  711. return sunxi_clk_set_rate(clk, rate);
  712. }
  713. hal_clk_status_t clk_get_rate(hal_clk_id_t clk, u32 *rate)
  714. {
  715. return sunxi_clk_get_rate(clk, rate);
  716. }
  717. hal_clk_id_t clk_get(hal_clk_type_t type, hal_clk_id_t id)
  718. {
  719. return id;
  720. }
  721. hal_clk_status_t clk_put(hal_clk_id_t id)
  722. {
  723. return HAL_CLK_STATUS_OK;
  724. }
  725. hal_clk_status_t clk_init(void)
  726. {
  727. hal_clk_status_t ret;
  728. ret = sunxi_factor_clk_init();
  729. /*the parent clk of some fixed-factor clk maybe factor-pll clk,
  730. so factor-pll clk init before fixed-factor clk*/
  731. ret = sunxi_fixed_factor_clk_init();
  732. ret = sunxi_periph_bus_clk_init();
  733. return ret;
  734. }