fsl_clock.c 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249
  1. /*
  2. * Copyright 2018 - 2021 NXP
  3. * All rights reserved.
  4. *
  5. * SPDX-License-Identifier: BSD-3-Clause
  6. */
  7. #include "fsl_clock.h"
  8. /* Component ID definition, used by tools. */
  9. #ifndef FSL_COMPONENT_ID
  10. #define FSL_COMPONENT_ID "platform.drivers.clock"
  11. #endif
  12. /*******************************************************************************
  13. * Definitions
  14. ******************************************************************************/
  15. /* To make full use of CM7 hardware FPU, use double instead of uint64_t in clock driver to
  16. achieve better performance, it is depend on the IDE Floating point settings, if double precision is selected
  17. in IDE, clock_64b_t will switch to double type automatically. only support IAR and MDK here */
  18. #if __FPU_USED
  19. #if (defined(__ICCARM__))
  20. #if (__ARMVFP__ >= __ARMFPV5__) && \
  21. (__ARM_FP == 0xE) /*0xe implies support for half, single and double precision operations*/
  22. typedef double clock_64b_t;
  23. #else
  24. typedef uint64_t clock_64b_t;
  25. #endif
  26. #elif (defined(__GNUC__))
  27. #if (__ARM_FP == 0xE) /*0xe implies support for half, single and double precision operations*/
  28. typedef double clock_64b_t;
  29. #else
  30. typedef uint64_t clock_64b_t;
  31. #endif
  32. #elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
  33. #if defined __TARGET_FPU_FPV5_D16
  34. typedef double clock_64b_t;
  35. #else
  36. typedef uint64_t clock_64b_t;
  37. #endif
  38. #else
  39. typedef uint64_t clock_64b_t;
  40. #endif
  41. #else
  42. typedef uint64_t clock_64b_t;
  43. #endif
  44. /*******************************************************************************
  45. * Variables
  46. ******************************************************************************/
  47. /* External XTAL (OSC) clock frequency. */
  48. volatile uint32_t g_xtalFreq;
  49. /* External RTC XTAL clock frequency. */
  50. volatile uint32_t g_rtcXtalFreq;
  51. /*******************************************************************************
  52. * Prototypes
  53. ******************************************************************************/
  54. /*!
  55. * @brief Get the periph clock frequency.
  56. *
  57. * @return Periph clock frequency in Hz.
  58. */
  59. static uint32_t CLOCK_GetPeriphClkFreq(void);
  60. /*!
  61. * @brief Get the frequency of PLL USB1 software clock.
  62. *
  63. * @return The frequency of PLL USB1 software clock.
  64. */
  65. static uint32_t CLOCK_GetPllUsb1SWFreq(void);
  66. /*******************************************************************************
  67. * Code
  68. ******************************************************************************/
  69. static uint32_t CLOCK_GetPeriphClkFreq(void)
  70. {
  71. uint32_t freq;
  72. /* Periph_clk2_clk ---> Periph_clk */
  73. if ((CCM->CBCDR & CCM_CBCDR_PERIPH_CLK_SEL_MASK) != 0UL)
  74. {
  75. switch (CCM->CBCMR & CCM_CBCMR_PERIPH_CLK2_SEL_MASK)
  76. {
  77. /* Pll3_sw_clk ---> Periph_clk2_clk ---> Periph_clk */
  78. case CCM_CBCMR_PERIPH_CLK2_SEL(0U):
  79. freq = CLOCK_GetPllFreq(kCLOCK_PllUsb1);
  80. break;
  81. /* Osc_clk ---> Periph_clk2_clk ---> Periph_clk */
  82. case CCM_CBCMR_PERIPH_CLK2_SEL(1U):
  83. freq = CLOCK_GetOscFreq();
  84. break;
  85. case CCM_CBCMR_PERIPH_CLK2_SEL(2U):
  86. freq = CLOCK_GetPllFreq(kCLOCK_PllSys);
  87. break;
  88. case CCM_CBCMR_PERIPH_CLK2_SEL(3U):
  89. default:
  90. freq = 0U;
  91. break;
  92. }
  93. freq /= (((CCM->CBCDR & CCM_CBCDR_PERIPH_CLK2_PODF_MASK) >> CCM_CBCDR_PERIPH_CLK2_PODF_SHIFT) + 1U);
  94. }
  95. /* Pre_Periph_clk ---> Periph_clk */
  96. else
  97. {
  98. switch (CCM->CBCMR & CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK)
  99. {
  100. /* PLL2 */
  101. case CCM_CBCMR_PRE_PERIPH_CLK_SEL(0U):
  102. freq = CLOCK_GetPllFreq(kCLOCK_PllSys);
  103. break;
  104. /* PLL3 PFD3 */
  105. case CCM_CBCMR_PRE_PERIPH_CLK_SEL(1U):
  106. freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd3);
  107. break;
  108. /* PLL2 PFD3 */
  109. case CCM_CBCMR_PRE_PERIPH_CLK_SEL(2U):
  110. freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd3);
  111. break;
  112. /* PLL6 divided(/1) */
  113. case CCM_CBCMR_PRE_PERIPH_CLK_SEL(3U):
  114. freq = 500000000U;
  115. break;
  116. default:
  117. freq = 0U;
  118. break;
  119. }
  120. }
  121. return freq;
  122. }
  123. static uint32_t CLOCK_GetPllUsb1SWFreq(void)
  124. {
  125. uint32_t freq;
  126. switch ((CCM->CCSR & CCM_CCSR_PLL3_SW_CLK_SEL_MASK) >> CCM_CCSR_PLL3_SW_CLK_SEL_SHIFT)
  127. {
  128. case 0:
  129. {
  130. freq = CLOCK_GetPllFreq(kCLOCK_PllUsb1);
  131. break;
  132. }
  133. case 1:
  134. {
  135. freq = 24000000UL;
  136. break;
  137. }
  138. default:
  139. freq = 0UL;
  140. break;
  141. }
  142. return freq;
  143. }
  144. /*!
  145. * brief Initialize the external 24MHz clock.
  146. *
  147. * This function supports two modes:
  148. * 1. Use external crystal oscillator.
  149. * 2. Bypass the external crystal oscillator, using input source clock directly.
  150. *
  151. * After this function, please call ref CLOCK_SetXtal0Freq to inform clock driver
  152. * the external clock frequency.
  153. *
  154. * param bypassXtalOsc Pass in true to bypass the external crystal oscillator.
  155. * note This device does not support bypass external crystal oscillator, so
  156. * the input parameter should always be false.
  157. */
  158. void CLOCK_InitExternalClk(bool bypassXtalOsc)
  159. {
  160. /* This device does not support bypass XTAL OSC. */
  161. assert(!bypassXtalOsc);
  162. CCM_ANALOG->MISC0_CLR = CCM_ANALOG_MISC0_XTAL_24M_PWD_MASK; /* Power up */
  163. while ((XTALOSC24M->LOWPWR_CTRL & XTALOSC24M_LOWPWR_CTRL_XTALOSC_PWRUP_STAT_MASK) == 0UL)
  164. {
  165. }
  166. CCM_ANALOG->MISC0_SET = (uint32_t)CCM_ANALOG_MISC0_OSC_XTALOK_EN_MASK; /* detect freq */
  167. while ((CCM_ANALOG->MISC0 & CCM_ANALOG_MISC0_OSC_XTALOK_MASK) == 0UL)
  168. {
  169. }
  170. CCM_ANALOG->MISC0_CLR = (uint32_t)CCM_ANALOG_MISC0_OSC_XTALOK_EN_MASK;
  171. }
  172. /*!
  173. * brief Deinitialize the external 24MHz clock.
  174. *
  175. * This function disables the external 24MHz clock.
  176. *
  177. * After this function, please call ref CLOCK_SetXtal0Freq to set external clock
  178. * frequency to 0.
  179. */
  180. void CLOCK_DeinitExternalClk(void)
  181. {
  182. CCM_ANALOG->MISC0_SET = CCM_ANALOG_MISC0_XTAL_24M_PWD_MASK; /* Power down */
  183. }
  184. /*!
  185. * brief Switch the OSC.
  186. *
  187. * This function switches the OSC source for SoC.
  188. *
  189. * param osc OSC source to switch to.
  190. */
  191. void CLOCK_SwitchOsc(clock_osc_t osc)
  192. {
  193. if (osc == kCLOCK_RcOsc)
  194. {
  195. XTALOSC24M->LOWPWR_CTRL_SET = XTALOSC24M_LOWPWR_CTRL_SET_OSC_SEL_MASK;
  196. }
  197. else
  198. {
  199. XTALOSC24M->LOWPWR_CTRL_CLR = XTALOSC24M_LOWPWR_CTRL_CLR_OSC_SEL_MASK;
  200. }
  201. }
  202. /*!
  203. * brief Initialize the RC oscillator 24MHz clock.
  204. */
  205. void CLOCK_InitRcOsc24M(void)
  206. {
  207. XTALOSC24M->LOWPWR_CTRL |= XTALOSC24M_LOWPWR_CTRL_RC_OSC_EN_MASK;
  208. }
  209. /*!
  210. * brief Power down the RCOSC 24M clock.
  211. */
  212. void CLOCK_DeinitRcOsc24M(void)
  213. {
  214. XTALOSC24M->LOWPWR_CTRL &= ~XTALOSC24M_LOWPWR_CTRL_RC_OSC_EN_MASK;
  215. }
  216. /*!
  217. * brief Gets the AHB clock frequency.
  218. *
  219. * return The AHB clock frequency value in hertz.
  220. */
  221. uint32_t CLOCK_GetAhbFreq(void)
  222. {
  223. return CLOCK_GetPeriphClkFreq() / (((CCM->CBCDR & CCM_CBCDR_AHB_PODF_MASK) >> CCM_CBCDR_AHB_PODF_SHIFT) + 1U);
  224. }
  225. /*!
  226. * brief Gets the SEMC clock frequency.
  227. *
  228. * return The SEMC clock frequency value in hertz.
  229. */
  230. uint32_t CLOCK_GetSemcFreq(void)
  231. {
  232. uint32_t freq;
  233. /* SEMC alternative clock ---> SEMC Clock */
  234. if ((CCM->CBCDR & CCM_CBCDR_SEMC_CLK_SEL_MASK) != 0UL)
  235. {
  236. /* PLL3 PFD1 ---> SEMC alternative clock ---> SEMC Clock */
  237. if ((CCM->CBCDR & CCM_CBCDR_SEMC_ALT_CLK_SEL_MASK) != 0UL)
  238. {
  239. freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd1);
  240. }
  241. /* PLL2 PFD2 ---> SEMC alternative clock ---> SEMC Clock */
  242. else
  243. {
  244. freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd2);
  245. }
  246. }
  247. /* Periph_clk ---> SEMC Clock */
  248. else
  249. {
  250. freq = CLOCK_GetPeriphClkFreq();
  251. }
  252. freq /= (((CCM->CBCDR & CCM_CBCDR_SEMC_PODF_MASK) >> CCM_CBCDR_SEMC_PODF_SHIFT) + 1U);
  253. return freq;
  254. }
  255. /*!
  256. * brief Gets the IPG clock frequency.
  257. *
  258. * return The IPG clock frequency value in hertz.
  259. */
  260. uint32_t CLOCK_GetIpgFreq(void)
  261. {
  262. return CLOCK_GetAhbFreq() / (((CCM->CBCDR & CCM_CBCDR_IPG_PODF_MASK) >> CCM_CBCDR_IPG_PODF_SHIFT) + 1U);
  263. }
  264. /*!
  265. * brief Gets the PER clock frequency.
  266. *
  267. * return The PER clock frequency value in hertz.
  268. */
  269. uint32_t CLOCK_GetPerClkFreq(void)
  270. {
  271. uint32_t freq;
  272. /* Osc_clk ---> PER Clock*/
  273. if ((CCM->CSCMR1 & CCM_CSCMR1_PERCLK_CLK_SEL_MASK) != 0UL)
  274. {
  275. freq = CLOCK_GetOscFreq();
  276. }
  277. /* Periph_clk ---> AHB Clock ---> IPG Clock ---> PER Clock */
  278. else
  279. {
  280. freq = CLOCK_GetIpgFreq();
  281. }
  282. freq /= (((CCM->CSCMR1 & CCM_CSCMR1_PERCLK_PODF_MASK) >> CCM_CSCMR1_PERCLK_PODF_SHIFT) + 1U);
  283. return freq;
  284. }
  285. /*!
  286. * brief Gets the clock frequency for a specific clock name.
  287. *
  288. * This function checks the current clock configurations and then calculates
  289. * the clock frequency for a specific clock name defined in clock_name_t.
  290. *
  291. * param clockName Clock names defined in clock_name_t
  292. * return Clock frequency value in hertz
  293. */
  294. uint32_t CLOCK_GetFreq(clock_name_t name)
  295. {
  296. uint32_t freq;
  297. switch (name)
  298. {
  299. case kCLOCK_CpuClk:
  300. case kCLOCK_AhbClk:
  301. freq = CLOCK_GetAhbFreq();
  302. break;
  303. case kCLOCK_SemcClk:
  304. freq = CLOCK_GetSemcFreq();
  305. break;
  306. case kCLOCK_IpgClk:
  307. freq = CLOCK_GetIpgFreq();
  308. break;
  309. case kCLOCK_PerClk:
  310. freq = CLOCK_GetPerClkFreq();
  311. break;
  312. case kCLOCK_OscClk:
  313. freq = CLOCK_GetOscFreq();
  314. break;
  315. case kCLOCK_RtcClk:
  316. freq = CLOCK_GetRtcFreq();
  317. break;
  318. case kCLOCK_Usb1PllClk:
  319. freq = CLOCK_GetPllFreq(kCLOCK_PllUsb1);
  320. break;
  321. case kCLOCK_Usb1PllPfd0Clk:
  322. freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd0);
  323. break;
  324. case kCLOCK_Usb1PllPfd1Clk:
  325. freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd1);
  326. break;
  327. case kCLOCK_Usb1PllPfd2Clk:
  328. freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd2);
  329. break;
  330. case kCLOCK_Usb1PllPfd3Clk:
  331. freq = CLOCK_GetUsb1PfdFreq(kCLOCK_Pfd3);
  332. break;
  333. case kCLOCK_Usb1SwClk:
  334. freq = CLOCK_GetPllUsb1SWFreq();
  335. break;
  336. case kCLOCK_Usb1Sw60MClk:
  337. freq = CLOCK_GetPllUsb1SWFreq() / 8UL;
  338. break;
  339. case kCLOCK_Usb1Sw80MClk:
  340. freq = CLOCK_GetPllUsb1SWFreq() / 6UL;
  341. break;
  342. case kCLOCK_SysPllClk:
  343. freq = CLOCK_GetPllFreq(kCLOCK_PllSys);
  344. break;
  345. case kCLOCK_SysPllPfd0Clk:
  346. freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd0);
  347. break;
  348. case kCLOCK_SysPllPfd1Clk:
  349. freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd1);
  350. break;
  351. case kCLOCK_SysPllPfd2Clk:
  352. freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd2);
  353. break;
  354. case kCLOCK_SysPllPfd3Clk:
  355. freq = CLOCK_GetSysPfdFreq(kCLOCK_Pfd3);
  356. break;
  357. case kCLOCK_EnetPllClk:
  358. freq = CLOCK_GetPllFreq(kCLOCK_PllEnet);
  359. break;
  360. case kCLOCK_EnetPll25MClk:
  361. freq = CLOCK_GetPllFreq(kCLOCK_PllEnet25M);
  362. break;
  363. case kCLOCK_EnetPll500MClk:
  364. freq = CLOCK_GetPllFreq(kCLOCK_PllEnet500M);
  365. break;
  366. case kCLOCK_AudioPllClk:
  367. freq = CLOCK_GetPllFreq(kCLOCK_PllAudio);
  368. break;
  369. default:
  370. freq = 0U;
  371. break;
  372. }
  373. return freq;
  374. }
  375. /*!
  376. * brief Gets the frequency of selected clock root.
  377. *
  378. * param clockRoot The clock root used to get the frequency, please refer to @ref clock_root_t.
  379. * return The frequency of selected clock root.
  380. */
  381. uint32_t CLOCK_GetClockRootFreq(clock_root_t clockRoot)
  382. {
  383. static const clock_name_t clockRootSourceArray[][4] = CLOCK_ROOT_SOUCE;
  384. static const clock_mux_t clockRootMuxTupleArray[] = CLOCK_ROOT_MUX_TUPLE;
  385. static const clock_div_t clockRootDivTupleArray[][2] = CLOCK_ROOT_DIV_TUPLE;
  386. uint32_t freq = 0UL;
  387. clock_mux_t clockRootMuxTuple = clockRootMuxTupleArray[(uint8_t)clockRoot];
  388. clock_div_t clockRootPreDivTuple = clockRootDivTupleArray[(uint8_t)clockRoot][0];
  389. clock_div_t clockRootPostDivTuple = clockRootDivTupleArray[(uint8_t)clockRoot][1];
  390. uint32_t clockRootMuxValue = (CCM_TUPLE_REG(CCM, clockRootMuxTuple) & CCM_TUPLE_MASK(clockRootMuxTuple)) >>
  391. CCM_TUPLE_SHIFT(clockRootMuxTuple);
  392. clock_name_t clockSourceName;
  393. clockSourceName = clockRootSourceArray[(uint8_t)clockRoot][clockRootMuxValue];
  394. assert(clockSourceName != kCLOCK_NoneName);
  395. freq = CLOCK_GetFreq(clockSourceName);
  396. if (clockRootPreDivTuple != kCLOCK_NonePreDiv)
  397. {
  398. freq /= ((CCM_TUPLE_REG(CCM, clockRootPreDivTuple) & CCM_TUPLE_MASK(clockRootPreDivTuple)) >>
  399. CCM_TUPLE_SHIFT(clockRootPreDivTuple)) +
  400. 1UL;
  401. }
  402. freq /= ((CCM_TUPLE_REG(CCM, clockRootPostDivTuple) & CCM_TUPLE_MASK(clockRootPostDivTuple)) >>
  403. CCM_TUPLE_SHIFT(clockRootPostDivTuple)) +
  404. 1UL;
  405. return freq;
  406. }
  407. /*! brief Enable USB HS clock.
  408. *
  409. * This function only enables the access to USB HS prepheral, upper layer
  410. * should first call the ref CLOCK_EnableUsbhs0PhyPllClock to enable the PHY
  411. * clock to use USB HS.
  412. *
  413. * param src USB HS does not care about the clock source, here must be ref kCLOCK_UsbSrcUnused.
  414. * param freq USB HS does not care about the clock source, so this parameter is ignored.
  415. * retval true The clock is set successfully.
  416. * retval false The clock source is invalid to get proper USB HS clock.
  417. */
  418. bool CLOCK_EnableUsbhs0Clock(clock_usb_src_t src, uint32_t freq)
  419. {
  420. uint32_t i;
  421. CCM->CCGR6 |= CCM_CCGR6_CG0_MASK;
  422. USB->USBCMD |= USBHS_USBCMD_RST_MASK;
  423. /* Add a delay between RST and RS so make sure there is a DP pullup sequence*/
  424. for (i = 0; i < 400000UL; i++)
  425. {
  426. __ASM("nop");
  427. }
  428. PMU->REG_3P0 = (PMU->REG_3P0 & (~PMU_REG_3P0_OUTPUT_TRG_MASK)) |
  429. (PMU_REG_3P0_OUTPUT_TRG(0x17) | PMU_REG_3P0_ENABLE_LINREG_MASK);
  430. return true;
  431. }
  432. /*! brief Enable USB HS PHY PLL clock.
  433. *
  434. * This function enables the internal 480MHz USB PHY PLL clock.
  435. *
  436. * param src USB HS PHY PLL clock source.
  437. * param freq The frequency specified by src.
  438. * retval true The clock is set successfully.
  439. * retval false The clock source is invalid to get proper USB HS clock.
  440. */
  441. bool CLOCK_EnableUsbhs0PhyPllClock(clock_usb_phy_src_t src, uint32_t freq)
  442. {
  443. static const clock_usb_pll_config_t g_ccmConfigUsbPll = {.loopDivider = 0U};
  444. if ((CCM_ANALOG->PLL_USB1 & CCM_ANALOG_PLL_USB1_ENABLE_MASK) != 0UL)
  445. {
  446. CCM_ANALOG->PLL_USB1 |= CCM_ANALOG_PLL_USB1_EN_USB_CLKS_MASK;
  447. }
  448. else
  449. {
  450. CLOCK_InitUsb1Pll(&g_ccmConfigUsbPll);
  451. }
  452. USBPHY->CTRL &= ~USBPHY_CTRL_SFTRST_MASK; /* release PHY from reset */
  453. USBPHY->CTRL &= ~USBPHY_CTRL_CLKGATE_MASK;
  454. USBPHY->PWD = 0;
  455. USBPHY->CTRL |= USBPHY_CTRL_ENAUTOCLR_PHY_PWD_MASK | USBPHY_CTRL_ENAUTOCLR_CLKGATE_MASK |
  456. USBPHY_CTRL_ENUTMILEVEL2_MASK | USBPHY_CTRL_ENUTMILEVEL3_MASK;
  457. return true;
  458. }
  459. /*! brief Disable USB HS PHY PLL clock.
  460. *
  461. * This function disables USB HS PHY PLL clock.
  462. */
  463. void CLOCK_DisableUsbhs0PhyPllClock(void)
  464. {
  465. CCM_ANALOG->PLL_USB1 &= ~CCM_ANALOG_PLL_USB1_EN_USB_CLKS_MASK;
  466. USBPHY->CTRL |= USBPHY_CTRL_CLKGATE_MASK; /* Set to 1U to gate clocks */
  467. }
  468. /*!
  469. * brief Initialize the System PLL.
  470. *
  471. * This function initializes the System PLL with specific settings
  472. *
  473. * param config Configuration to set to PLL.
  474. */
  475. void CLOCK_InitSysPll(const clock_sys_pll_config_t *config)
  476. {
  477. /* Bypass PLL first */
  478. CCM_ANALOG->PLL_SYS = (CCM_ANALOG->PLL_SYS & (~CCM_ANALOG_PLL_SYS_BYPASS_CLK_SRC_MASK)) |
  479. CCM_ANALOG_PLL_SYS_BYPASS_MASK | CCM_ANALOG_PLL_SYS_BYPASS_CLK_SRC(config->src);
  480. CCM_ANALOG->PLL_SYS =
  481. (CCM_ANALOG->PLL_SYS & (~(CCM_ANALOG_PLL_SYS_DIV_SELECT_MASK | CCM_ANALOG_PLL_SYS_POWERDOWN_MASK))) |
  482. CCM_ANALOG_PLL_SYS_ENABLE_MASK | CCM_ANALOG_PLL_SYS_DIV_SELECT(config->loopDivider);
  483. /* Initialize the fractional mode */
  484. CCM_ANALOG->PLL_SYS_NUM = CCM_ANALOG_PLL_SYS_NUM_A(config->numerator);
  485. CCM_ANALOG->PLL_SYS_DENOM = CCM_ANALOG_PLL_SYS_DENOM_B(config->denominator);
  486. /* Initialize the spread spectrum mode */
  487. CCM_ANALOG->PLL_SYS_SS = CCM_ANALOG_PLL_SYS_SS_STEP(config->ss_step) |
  488. CCM_ANALOG_PLL_SYS_SS_ENABLE(config->ss_enable) |
  489. CCM_ANALOG_PLL_SYS_SS_STOP(config->ss_stop);
  490. while ((CCM_ANALOG->PLL_SYS & CCM_ANALOG_PLL_SYS_LOCK_MASK) == 0UL)
  491. {
  492. }
  493. /* Disable Bypass */
  494. CCM_ANALOG->PLL_SYS &= ~CCM_ANALOG_PLL_SYS_BYPASS_MASK;
  495. }
  496. /*!
  497. * brief De-initialize the System PLL.
  498. */
  499. void CLOCK_DeinitSysPll(void)
  500. {
  501. CCM_ANALOG->PLL_SYS = CCM_ANALOG_PLL_SYS_POWERDOWN_MASK;
  502. }
  503. /*!
  504. * brief Initialize the USB1 PLL.
  505. *
  506. * This function initializes the USB1 PLL with specific settings
  507. *
  508. * param config Configuration to set to PLL.
  509. */
  510. void CLOCK_InitUsb1Pll(const clock_usb_pll_config_t *config)
  511. {
  512. /* Bypass PLL first */
  513. CCM_ANALOG->PLL_USB1 = (CCM_ANALOG->PLL_USB1 & (~CCM_ANALOG_PLL_USB1_BYPASS_CLK_SRC_MASK)) |
  514. CCM_ANALOG_PLL_USB1_BYPASS_MASK | CCM_ANALOG_PLL_USB1_BYPASS_CLK_SRC(config->src);
  515. CCM_ANALOG->PLL_USB1 = (CCM_ANALOG->PLL_USB1 & (~CCM_ANALOG_PLL_USB1_DIV_SELECT_MASK)) |
  516. CCM_ANALOG_PLL_USB1_ENABLE_MASK | CCM_ANALOG_PLL_USB1_POWER_MASK |
  517. CCM_ANALOG_PLL_USB1_EN_USB_CLKS_MASK | CCM_ANALOG_PLL_USB1_DIV_SELECT(config->loopDivider);
  518. while ((CCM_ANALOG->PLL_USB1 & CCM_ANALOG_PLL_USB1_LOCK_MASK) == 0UL)
  519. {
  520. }
  521. /* Disable Bypass */
  522. CCM_ANALOG->PLL_USB1 &= ~CCM_ANALOG_PLL_USB1_BYPASS_MASK;
  523. }
  524. /*!
  525. * brief Deinitialize the USB1 PLL.
  526. */
  527. void CLOCK_DeinitUsb1Pll(void)
  528. {
  529. CCM_ANALOG->PLL_USB1 = 0U;
  530. }
  531. /*!
  532. * brief Initializes the Audio PLL.
  533. *
  534. * This function initializes the Audio PLL with specific settings
  535. *
  536. * param config Configuration to set to PLL.
  537. */
  538. void CLOCK_InitAudioPll(const clock_audio_pll_config_t *config)
  539. {
  540. uint32_t pllAudio;
  541. uint32_t misc2 = 0;
  542. /* Bypass PLL first */
  543. CCM_ANALOG->PLL_AUDIO = (CCM_ANALOG->PLL_AUDIO & (~CCM_ANALOG_PLL_AUDIO_BYPASS_CLK_SRC_MASK)) |
  544. CCM_ANALOG_PLL_AUDIO_BYPASS_MASK | CCM_ANALOG_PLL_AUDIO_BYPASS_CLK_SRC(config->src);
  545. CCM_ANALOG->PLL_AUDIO_NUM = CCM_ANALOG_PLL_AUDIO_NUM_A(config->numerator);
  546. CCM_ANALOG->PLL_AUDIO_DENOM = CCM_ANALOG_PLL_AUDIO_DENOM_B(config->denominator);
  547. /*
  548. * Set post divider:
  549. *
  550. * ------------------------------------------------------------------------
  551. * | config->postDivider | PLL_AUDIO[POST_DIV_SELECT] | MISC2[AUDIO_DIV] |
  552. * ------------------------------------------------------------------------
  553. * | 1 | 2 | 0 |
  554. * ------------------------------------------------------------------------
  555. * | 2 | 1 | 0 |
  556. * ------------------------------------------------------------------------
  557. * | 4 | 2 | 3 |
  558. * ------------------------------------------------------------------------
  559. * | 8 | 1 | 3 |
  560. * ------------------------------------------------------------------------
  561. * | 16 | 0 | 3 |
  562. * ------------------------------------------------------------------------
  563. */
  564. pllAudio =
  565. (CCM_ANALOG->PLL_AUDIO & (~(CCM_ANALOG_PLL_AUDIO_DIV_SELECT_MASK | CCM_ANALOG_PLL_AUDIO_POWERDOWN_MASK))) |
  566. CCM_ANALOG_PLL_AUDIO_ENABLE_MASK | CCM_ANALOG_PLL_AUDIO_DIV_SELECT(config->loopDivider);
  567. switch (config->postDivider)
  568. {
  569. case 16:
  570. pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(0);
  571. misc2 = CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK | CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK;
  572. break;
  573. case 8:
  574. pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(1);
  575. misc2 = CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK | CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK;
  576. break;
  577. case 4:
  578. pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(2);
  579. misc2 = CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK | CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK;
  580. break;
  581. case 2:
  582. pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(1);
  583. break;
  584. default:
  585. pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(2);
  586. break;
  587. }
  588. CCM_ANALOG->MISC2 =
  589. (CCM_ANALOG->MISC2 & ~(CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK | CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK)) | misc2;
  590. CCM_ANALOG->PLL_AUDIO = pllAudio;
  591. while ((CCM_ANALOG->PLL_AUDIO & CCM_ANALOG_PLL_AUDIO_LOCK_MASK) == 0UL)
  592. {
  593. }
  594. /* Disable Bypass */
  595. CCM_ANALOG->PLL_AUDIO &= ~CCM_ANALOG_PLL_AUDIO_BYPASS_MASK;
  596. }
  597. /*!
  598. * brief De-initialize the Audio PLL.
  599. */
  600. void CLOCK_DeinitAudioPll(void)
  601. {
  602. CCM_ANALOG->PLL_AUDIO = CCM_ANALOG_PLL_AUDIO_POWERDOWN_MASK;
  603. }
  604. /*!
  605. * brief Initialize the ENET PLL.
  606. *
  607. * This function initializes the ENET PLL with specific settings.
  608. *
  609. * param config Configuration to set to PLL.
  610. */
  611. void CLOCK_InitEnetPll(const clock_enet_pll_config_t *config)
  612. {
  613. uint32_t enet_pll = CCM_ANALOG_PLL_ENET_DIV_SELECT(config->loopDivider);
  614. CCM_ANALOG->PLL_ENET = (CCM_ANALOG->PLL_ENET & (~CCM_ANALOG_PLL_ENET_BYPASS_CLK_SRC_MASK)) |
  615. CCM_ANALOG_PLL_ENET_BYPASS_MASK | CCM_ANALOG_PLL_ENET_BYPASS_CLK_SRC(config->src);
  616. if (config->enableClkOutput)
  617. {
  618. enet_pll |= CCM_ANALOG_PLL_ENET_ENABLE_MASK;
  619. }
  620. if (config->enableClkOutput25M)
  621. {
  622. enet_pll |= CCM_ANALOG_PLL_ENET_ENET_25M_REF_EN_MASK;
  623. }
  624. if (config->enableClkOutput500M)
  625. {
  626. enet_pll |= CCM_ANALOG_PLL_ENET_ENET_500M_REF_EN_MASK;
  627. }
  628. CCM_ANALOG->PLL_ENET =
  629. (CCM_ANALOG->PLL_ENET & (~(CCM_ANALOG_PLL_ENET_DIV_SELECT_MASK | CCM_ANALOG_PLL_ENET_POWERDOWN_MASK))) |
  630. enet_pll;
  631. /* Wait for stable */
  632. while ((CCM_ANALOG->PLL_ENET & CCM_ANALOG_PLL_ENET_LOCK_MASK) == 0UL)
  633. {
  634. }
  635. /* Disable Bypass */
  636. CCM_ANALOG->PLL_ENET &= ~CCM_ANALOG_PLL_ENET_BYPASS_MASK;
  637. }
  638. /*!
  639. * brief Deinitialize the ENET PLL.
  640. *
  641. * This function disables the ENET PLL.
  642. */
  643. void CLOCK_DeinitEnetPll(void)
  644. {
  645. CCM_ANALOG->PLL_ENET = CCM_ANALOG_PLL_ENET_POWERDOWN_MASK;
  646. }
  647. /*!
  648. * brief Get current PLL output frequency.
  649. *
  650. * This function get current output frequency of specific PLL
  651. *
  652. * param pll pll name to get frequency.
  653. * return The PLL output frequency in hertz.
  654. */
  655. uint32_t CLOCK_GetPllFreq(clock_pll_t pll)
  656. {
  657. uint32_t freq;
  658. uint32_t divSelect;
  659. clock_64b_t freqTmp;
  660. static const uint32_t enetRefClkFreq[] = {
  661. 25000000U, /* 25M */
  662. 50000000U, /* 50M */
  663. 100000000U, /* 100M */
  664. 125000000U /* 125M */
  665. };
  666. /* check if PLL is enabled */
  667. if (!CLOCK_IsPllEnabled(CCM_ANALOG, pll))
  668. {
  669. return 0U;
  670. }
  671. /* get pll reference clock */
  672. freq = CLOCK_GetPllBypassRefClk(CCM_ANALOG, pll);
  673. /* check if pll is bypassed */
  674. if (CLOCK_IsPllBypassed(CCM_ANALOG, pll))
  675. {
  676. return freq;
  677. }
  678. switch (pll)
  679. {
  680. case kCLOCK_PllSys:
  681. /* PLL output frequency = Fref * (DIV_SELECT + NUM/DENOM). */
  682. freqTmp = ((clock_64b_t)freq * ((clock_64b_t)(CCM_ANALOG->PLL_SYS_NUM)));
  683. freqTmp /= ((clock_64b_t)(CCM_ANALOG->PLL_SYS_DENOM));
  684. if ((CCM_ANALOG->PLL_SYS & CCM_ANALOG_PLL_SYS_DIV_SELECT_MASK) != 0UL)
  685. {
  686. freq *= 22U;
  687. }
  688. else
  689. {
  690. freq *= 20U;
  691. }
  692. freq += (uint32_t)freqTmp;
  693. break;
  694. case kCLOCK_PllUsb1:
  695. freq = (freq * (((CCM_ANALOG->PLL_USB1 & CCM_ANALOG_PLL_USB1_DIV_SELECT_MASK) != 0UL) ? 22U : 20U));
  696. break;
  697. case kCLOCK_PllAudio:
  698. /* PLL output frequency = Fref * (DIV_SELECT + NUM/DENOM). */
  699. divSelect =
  700. (CCM_ANALOG->PLL_AUDIO & CCM_ANALOG_PLL_AUDIO_DIV_SELECT_MASK) >> CCM_ANALOG_PLL_AUDIO_DIV_SELECT_SHIFT;
  701. freqTmp = ((clock_64b_t)freq * ((clock_64b_t)(CCM_ANALOG->PLL_AUDIO_NUM)));
  702. freqTmp /= ((clock_64b_t)(CCM_ANALOG->PLL_AUDIO_DENOM));
  703. freq = freq * divSelect + (uint32_t)freqTmp;
  704. /* AUDIO PLL output = PLL output frequency / POSTDIV. */
  705. /*
  706. * Post divider:
  707. *
  708. * PLL_AUDIO[POST_DIV_SELECT]:
  709. * 0x00: 4
  710. * 0x01: 2
  711. * 0x02: 1
  712. *
  713. * MISC2[AUDO_DIV]:
  714. * 0x00: 1
  715. * 0x01: 2
  716. * 0x02: 1
  717. * 0x03: 4
  718. */
  719. switch (CCM_ANALOG->PLL_AUDIO & CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT_MASK)
  720. {
  721. case CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(0U):
  722. freq = freq >> 2U;
  723. break;
  724. case CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(1U):
  725. freq = freq >> 1U;
  726. break;
  727. case CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(2U):
  728. freq = freq >> 0U;
  729. break;
  730. default:
  731. assert(false);
  732. break;
  733. }
  734. switch (CCM_ANALOG->MISC2 & (CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK | CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK))
  735. {
  736. case CCM_ANALOG_MISC2_AUDIO_DIV_MSB(1) | CCM_ANALOG_MISC2_AUDIO_DIV_LSB(1):
  737. freq >>= 2U;
  738. break;
  739. case CCM_ANALOG_MISC2_AUDIO_DIV_MSB(0) | CCM_ANALOG_MISC2_AUDIO_DIV_LSB(1):
  740. freq >>= 1U;
  741. break;
  742. case CCM_ANALOG_MISC2_AUDIO_DIV_MSB(0) | CCM_ANALOG_MISC2_AUDIO_DIV_LSB(0):
  743. case CCM_ANALOG_MISC2_AUDIO_DIV_MSB(1) | CCM_ANALOG_MISC2_AUDIO_DIV_LSB(0):
  744. freq >>= 0U;
  745. break;
  746. default:
  747. assert(false);
  748. break;
  749. }
  750. break;
  751. case kCLOCK_PllEnet:
  752. divSelect =
  753. (CCM_ANALOG->PLL_ENET & CCM_ANALOG_PLL_ENET_DIV_SELECT_MASK) >> CCM_ANALOG_PLL_ENET_DIV_SELECT_SHIFT;
  754. freq = enetRefClkFreq[divSelect];
  755. break;
  756. case kCLOCK_PllEnet25M:
  757. /* ref_enetpll1 if fixed at 25MHz. */
  758. freq = 25000000UL;
  759. break;
  760. case kCLOCK_PllEnet500M:
  761. /* PLL6 is fixed at 25MHz. */
  762. freq = 500000000UL;
  763. break;
  764. default:
  765. freq = 0U;
  766. break;
  767. }
  768. return freq;
  769. }
  770. /*!
  771. * brief Initialize the System PLL PFD.
  772. *
  773. * This function initializes the System PLL PFD. During new value setting,
  774. * the clock output is disabled to prevent glitch.
  775. *
  776. * param pfd Which PFD clock to enable.
  777. * param pfdFrac The PFD FRAC value.
  778. * note It is recommended that PFD settings are kept between 12-35.
  779. */
  780. void CLOCK_InitSysPfd(clock_pfd_t pfd, uint8_t pfdFrac)
  781. {
  782. uint32_t pfdIndex = (uint32_t)pfd;
  783. uint32_t pfd528;
  784. pfd528 = CCM_ANALOG->PFD_528 &
  785. ~(((uint32_t)((uint32_t)CCM_ANALOG_PFD_528_PFD0_CLKGATE_MASK | (uint32_t)CCM_ANALOG_PFD_528_PFD0_FRAC_MASK)
  786. << (8UL * pfdIndex)));
  787. /* Disable the clock output first. */
  788. CCM_ANALOG->PFD_528 = pfd528 | ((uint32_t)CCM_ANALOG_PFD_528_PFD0_CLKGATE_MASK << (8UL * pfdIndex));
  789. /* Set the new value and enable output. */
  790. CCM_ANALOG->PFD_528 = pfd528 | (CCM_ANALOG_PFD_528_PFD0_FRAC(pfdFrac) << (8UL * pfdIndex));
  791. }
  792. /*!
  793. * brief De-initialize the System PLL PFD.
  794. *
  795. * This function disables the System PLL PFD.
  796. *
  797. * param pfd Which PFD clock to disable.
  798. */
  799. void CLOCK_DeinitSysPfd(clock_pfd_t pfd)
  800. {
  801. CCM_ANALOG->PFD_528 |= (uint32_t)CCM_ANALOG_PFD_528_PFD0_CLKGATE_MASK << (8UL * (uint32_t)pfd);
  802. }
  803. /*!
  804. * brief Check if Sys PFD is enabled
  805. *
  806. * param pfd PFD control name
  807. * return PFD bypass status.
  808. * - true: power on.
  809. * - false: power off.
  810. */
  811. bool CLOCK_IsSysPfdEnabled(clock_pfd_t pfd)
  812. {
  813. return ((CCM_ANALOG->PFD_528 & (uint32_t)CCM_ANALOG_PFD_528_PFD0_CLKGATE_MASK << (8UL * (uint32_t)pfd)) == 0U);
  814. }
  815. /*!
  816. * brief Initialize the USB1 PLL PFD.
  817. *
  818. * This function initializes the USB1 PLL PFD. During new value setting,
  819. * the clock output is disabled to prevent glitch.
  820. *
  821. * param pfd Which PFD clock to enable.
  822. * param pfdFrac The PFD FRAC value.
  823. * note It is recommended that PFD settings are kept between 12-35.
  824. */
  825. void CLOCK_InitUsb1Pfd(clock_pfd_t pfd, uint8_t pfdFrac)
  826. {
  827. uint32_t pfdIndex = (uint32_t)pfd;
  828. uint32_t pfd480;
  829. pfd480 = CCM_ANALOG->PFD_480 &
  830. ~((uint32_t)((uint32_t)CCM_ANALOG_PFD_480_PFD0_CLKGATE_MASK | (uint32_t)CCM_ANALOG_PFD_480_PFD0_FRAC_MASK)
  831. << (8UL * pfdIndex));
  832. /* Disable the clock output first. */
  833. CCM_ANALOG->PFD_480 = pfd480 | ((uint32_t)CCM_ANALOG_PFD_480_PFD0_CLKGATE_MASK << (8UL * pfdIndex));
  834. /* Set the new value and enable output. */
  835. CCM_ANALOG->PFD_480 = pfd480 | (CCM_ANALOG_PFD_480_PFD0_FRAC(pfdFrac) << (8UL * pfdIndex));
  836. }
  837. /*!
  838. * brief De-initialize the USB1 PLL PFD.
  839. *
  840. * This function disables the USB1 PLL PFD.
  841. *
  842. * param pfd Which PFD clock to disable.
  843. */
  844. void CLOCK_DeinitUsb1Pfd(clock_pfd_t pfd)
  845. {
  846. CCM_ANALOG->PFD_480 |= (uint32_t)CCM_ANALOG_PFD_480_PFD0_CLKGATE_MASK << (8UL * (uint32_t)pfd);
  847. }
  848. /*!
  849. * brief Check if Usb1 PFD is enabled
  850. *
  851. * param pfd PFD control name.
  852. * return PFD bypass status.
  853. * - true: power on.
  854. * - false: power off.
  855. */
  856. bool CLOCK_IsUsb1PfdEnabled(clock_pfd_t pfd)
  857. {
  858. return ((CCM_ANALOG->PFD_480 & (uint32_t)CCM_ANALOG_PFD_480_PFD0_CLKGATE_MASK << (8UL * (uint32_t)pfd)) == 0U);
  859. }
  860. /*!
  861. * brief Get current System PLL PFD output frequency.
  862. *
  863. * This function get current output frequency of specific System PLL PFD
  864. *
  865. * param pfd pfd name to get frequency.
  866. * return The PFD output frequency in hertz.
  867. */
  868. uint32_t CLOCK_GetSysPfdFreq(clock_pfd_t pfd)
  869. {
  870. uint32_t freq = CLOCK_GetPllFreq(kCLOCK_PllSys);
  871. switch (pfd)
  872. {
  873. case kCLOCK_Pfd0:
  874. freq /= ((CCM_ANALOG->PFD_528 & CCM_ANALOG_PFD_528_PFD0_FRAC_MASK) >> CCM_ANALOG_PFD_528_PFD0_FRAC_SHIFT);
  875. break;
  876. case kCLOCK_Pfd1:
  877. freq /= ((CCM_ANALOG->PFD_528 & CCM_ANALOG_PFD_528_PFD1_FRAC_MASK) >> CCM_ANALOG_PFD_528_PFD1_FRAC_SHIFT);
  878. break;
  879. case kCLOCK_Pfd2:
  880. freq /= ((CCM_ANALOG->PFD_528 & CCM_ANALOG_PFD_528_PFD2_FRAC_MASK) >> CCM_ANALOG_PFD_528_PFD2_FRAC_SHIFT);
  881. break;
  882. case kCLOCK_Pfd3:
  883. freq /= ((CCM_ANALOG->PFD_528 & CCM_ANALOG_PFD_528_PFD3_FRAC_MASK) >> CCM_ANALOG_PFD_528_PFD3_FRAC_SHIFT);
  884. break;
  885. default:
  886. freq = 0U;
  887. break;
  888. }
  889. freq *= 18U;
  890. return freq;
  891. }
  892. /*!
  893. * brief Get current USB1 PLL PFD output frequency.
  894. *
  895. * This function get current output frequency of specific USB1 PLL PFD
  896. *
  897. * param pfd pfd name to get frequency.
  898. * return The PFD output frequency in hertz.
  899. */
  900. uint32_t CLOCK_GetUsb1PfdFreq(clock_pfd_t pfd)
  901. {
  902. uint32_t freq = CLOCK_GetPllFreq(kCLOCK_PllUsb1);
  903. switch (pfd)
  904. {
  905. case kCLOCK_Pfd0:
  906. freq /= ((CCM_ANALOG->PFD_480 & CCM_ANALOG_PFD_480_PFD0_FRAC_MASK) >> CCM_ANALOG_PFD_480_PFD0_FRAC_SHIFT);
  907. break;
  908. case kCLOCK_Pfd1:
  909. freq /= ((CCM_ANALOG->PFD_480 & CCM_ANALOG_PFD_480_PFD1_FRAC_MASK) >> CCM_ANALOG_PFD_480_PFD1_FRAC_SHIFT);
  910. break;
  911. case kCLOCK_Pfd2:
  912. freq /= ((CCM_ANALOG->PFD_480 & CCM_ANALOG_PFD_480_PFD2_FRAC_MASK) >> CCM_ANALOG_PFD_480_PFD2_FRAC_SHIFT);
  913. break;
  914. case kCLOCK_Pfd3:
  915. freq /= ((CCM_ANALOG->PFD_480 & CCM_ANALOG_PFD_480_PFD3_FRAC_MASK) >> CCM_ANALOG_PFD_480_PFD3_FRAC_SHIFT);
  916. break;
  917. default:
  918. freq = 0U;
  919. break;
  920. }
  921. freq *= 18U;
  922. return freq;
  923. }
  924. /*!
  925. * brief Set the clock source and the divider of the clock output1.
  926. *
  927. * param selection The clock source to be output, please refer to clock_output1_selection_t.
  928. * param divider The divider of the output clock signal, please refer to clock_output_divider_t.
  929. */
  930. void CLOCK_SetClockOutput1(clock_output1_selection_t selection, clock_output_divider_t divider)
  931. {
  932. uint32_t tmp32;
  933. tmp32 = CCM->CCOSR;
  934. if (selection == kCLOCK_DisableClockOutput1)
  935. {
  936. tmp32 &= ~CCM_CCOSR_CLKO1_EN_MASK;
  937. }
  938. else
  939. {
  940. tmp32 |= CCM_CCOSR_CLKO1_EN_MASK;
  941. tmp32 &= ~(CCM_CCOSR_CLKO1_SEL_MASK | CCM_CCOSR_CLKO1_DIV_MASK);
  942. tmp32 |= CCM_CCOSR_CLKO1_SEL(selection) | CCM_CCOSR_CLKO1_DIV(divider);
  943. }
  944. CCM->CCOSR = tmp32;
  945. }
  946. /*!
  947. * brief Set the clock source and the divider of the clock output2.
  948. *
  949. * param selection The clock source to be output, please refer to clock_output2_selection_t.
  950. * param divider The divider of the output clock signal, please refer to clock_output_divider_t.
  951. */
  952. void CLOCK_SetClockOutput2(clock_output2_selection_t selection, clock_output_divider_t divider)
  953. {
  954. uint32_t tmp32;
  955. tmp32 = CCM->CCOSR;
  956. if (selection == kCLOCK_DisableClockOutput2)
  957. {
  958. tmp32 &= CCM_CCOSR_CLKO2_EN_MASK;
  959. }
  960. else
  961. {
  962. tmp32 |= CCM_CCOSR_CLKO2_EN_MASK;
  963. tmp32 &= ~(CCM_CCOSR_CLKO2_SEL_MASK | CCM_CCOSR_CLKO2_DIV_MASK);
  964. tmp32 |= CCM_CCOSR_CLKO2_SEL(selection) | CCM_CCOSR_CLKO2_DIV(divider);
  965. }
  966. CCM->CCOSR = tmp32;
  967. }
  968. /*!
  969. * brief Get the frequency of clock output1 clock signal.
  970. *
  971. * return The frequency of clock output1 clock signal.
  972. */
  973. uint32_t CLOCK_GetClockOutCLKO1Freq(void)
  974. {
  975. uint32_t freq = 0U;
  976. uint32_t tmp32;
  977. tmp32 = CCM->CCOSR;
  978. if ((tmp32 & CCM_CCOSR_CLKO1_EN_MASK) != 0UL)
  979. {
  980. switch ((tmp32 & CCM_CCOSR_CLKO1_SEL_MASK) >> CCM_CCOSR_CLKO1_SEL_SHIFT)
  981. {
  982. case (uint32_t)kCLOCK_OutputPllUsb1Sw:
  983. freq = CLOCK_GetPllUsb1SWFreq() / 2UL;
  984. break;
  985. case (uint32_t)kCLOCK_OutputPllSys:
  986. freq = CLOCK_GetPllFreq(kCLOCK_PllSys) / 2UL;
  987. break;
  988. case (uint32_t)kCLOCK_OutputPllENET500M:
  989. freq = CLOCK_GetPllFreq(kCLOCK_PllEnet500M) / 2UL;
  990. break;
  991. case (uint32_t)kCLOCK_OutputSemcClk:
  992. freq = CLOCK_GetSemcFreq();
  993. break;
  994. case (uint32_t)kCLOCK_OutputAhbClk:
  995. freq = CLOCK_GetAhbFreq();
  996. break;
  997. case (uint32_t)kCLOCK_OutputIpgClk:
  998. freq = CLOCK_GetIpgFreq();
  999. break;
  1000. case (uint32_t)kCLOCK_OutputPerClk:
  1001. freq = CLOCK_GetPerClkFreq();
  1002. break;
  1003. case (uint32_t)kCLOCK_OutputPll4MainClk:
  1004. freq = CLOCK_GetPllFreq(kCLOCK_PllAudio);
  1005. break;
  1006. default:
  1007. /* This branch should never be hit. */
  1008. break;
  1009. }
  1010. freq /= (((tmp32 & CCM_CCOSR_CLKO1_DIV_MASK) >> CCM_CCOSR_CLKO1_DIV_SHIFT) + 1U);
  1011. }
  1012. else
  1013. {
  1014. freq = 0UL;
  1015. }
  1016. return freq;
  1017. }
  1018. /*!
  1019. * brief Get the frequency of clock output2 clock signal.
  1020. *
  1021. * return The frequency of clock output2 clock signal.
  1022. */
  1023. uint32_t CLOCK_GetClockOutClkO2Freq(void)
  1024. {
  1025. uint32_t freq = 0U;
  1026. uint32_t tmp32;
  1027. tmp32 = CCM->CCOSR;
  1028. if ((tmp32 & CCM_CCOSR_CLKO2_EN_MASK) != 0UL)
  1029. {
  1030. switch ((tmp32 & CCM_CCOSR_CLKO2_SEL_MASK) >> CCM_CCOSR_CLKO2_SEL_SHIFT)
  1031. {
  1032. case (uint32_t)kCLOCK_OutputUsdhc1Clk:
  1033. freq = CLOCK_GetClockRootFreq(kCLOCK_Usdhc1ClkRoot);
  1034. break;
  1035. case (uint32_t)kCLOCK_OutputLpi2cClk:
  1036. freq = CLOCK_GetClockRootFreq(kCLOCK_Lpi2cClkRoot);
  1037. break;
  1038. case (uint32_t)kCLOCK_OutputOscClk:
  1039. freq = CLOCK_GetOscFreq();
  1040. break;
  1041. case (uint32_t)kCLOCK_OutputLpspiClk:
  1042. freq = CLOCK_GetClockRootFreq(kCLOCK_LpspiClkRoot);
  1043. break;
  1044. case (uint32_t)kCLOCK_OutputUsdhc2Clk:
  1045. freq = CLOCK_GetClockRootFreq(kCLOCK_Usdhc2ClkRoot);
  1046. break;
  1047. case (uint32_t)kCLOCK_OutputSai1Clk:
  1048. freq = CLOCK_GetClockRootFreq(kCLOCK_Sai1ClkRoot);
  1049. break;
  1050. case (uint32_t)kCLOCK_OutputSai2Clk:
  1051. freq = CLOCK_GetClockRootFreq(kCLOCK_Sai2ClkRoot);
  1052. break;
  1053. case (uint32_t)kCLOCK_OutputSai3Clk:
  1054. freq = CLOCK_GetClockRootFreq(kCLOCK_Sai3ClkRoot);
  1055. break;
  1056. case (uint32_t)kCLOCK_OutputTraceClk:
  1057. freq = CLOCK_GetClockRootFreq(kCLOCK_TraceClkRoot);
  1058. break;
  1059. case (uint32_t)kCLOCK_OutputCanClk:
  1060. freq = CLOCK_GetClockRootFreq(kCLOCK_CanClkRoot);
  1061. break;
  1062. case (uint32_t)kCLOCK_OutputFlexspiClk:
  1063. freq = CLOCK_GetClockRootFreq(kCLOCK_FlexspiClkRoot);
  1064. break;
  1065. case (uint32_t)kCLOCK_OutputUartClk:
  1066. freq = CLOCK_GetClockRootFreq(kCLOCK_UartClkRoot);
  1067. break;
  1068. case (uint32_t)kCLOCK_OutputSpdif0Clk:
  1069. freq = CLOCK_GetClockRootFreq(kCLOCK_SpdifClkRoot);
  1070. break;
  1071. default:
  1072. /* This branch should never be hit. */
  1073. break;
  1074. }
  1075. freq /= (((tmp32 & CCM_CCOSR_CLKO2_DIV_MASK) >> CCM_CCOSR_CLKO2_DIV_SHIFT) + 1U);
  1076. }
  1077. else
  1078. {
  1079. freq = 0UL;
  1080. }
  1081. return freq;
  1082. }