fsl_clock.c 37 KB

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