clock_5410x.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. /*
  2. * @brief LPC5410X clock driver
  3. *
  4. * @note
  5. * Copyright(C) NXP Semiconductors, 2014
  6. * All rights reserved.
  7. *
  8. * @par
  9. * Software that is described herein is for illustrative purposes only
  10. * which provides customers with programming information regarding the
  11. * LPC products. This software is supplied "AS IS" without any warranties of
  12. * any kind, and NXP Semiconductors and its licenser disclaim any and
  13. * all warranties, express or implied, including all implied warranties of
  14. * merchantability, fitness for a particular purpose and non-infringement of
  15. * intellectual property rights. NXP Semiconductors assumes no responsibility
  16. * or liability for the use of the software, conveys no license or rights under any
  17. * patent, copyright, mask work right, or any other intellectual property rights in
  18. * or to any products. NXP Semiconductors reserves the right to make changes
  19. * in the software without notification. NXP Semiconductors also makes no
  20. * representation or warranty that such application will be suitable for the
  21. * specified use without further testing or modification.
  22. *
  23. * @par
  24. * Permission to use, copy, modify, and distribute this software and its
  25. * documentation is hereby granted, under NXP Semiconductors' and its
  26. * licensor's relevant copyrights in the software, without fee, provided that it
  27. * is used in conjunction with NXP Semiconductors microcontrollers. This
  28. * copyright, permission, and disclaimer notice must appear in all copies of
  29. * this code.
  30. */
  31. #include "chip.h"
  32. /*****************************************************************************
  33. * Private types/enumerations/variables
  34. ****************************************************************************/
  35. /*****************************************************************************
  36. * Public types/enumerations/variables
  37. ****************************************************************************/
  38. /*****************************************************************************
  39. * Private functions
  40. ****************************************************************************/
  41. /* Return asynchronous APB clock rate (no regard for divider) */
  42. static uint32_t Chip_Clock_GetAsyncSyscon_ClockRate_NoDiv(void)
  43. {
  44. CHIP_ASYNC_SYSCON_SRC_T src;
  45. uint32_t clkRate;
  46. src = Chip_Clock_GetAsyncSysconClockSource();
  47. switch (src) {
  48. case SYSCON_ASYNC_IRC:
  49. clkRate = Chip_Clock_GetIntOscRate();
  50. break;
  51. case SYSCON_ASYNC_WDTOSC:
  52. clkRate = Chip_Clock_GetWDTOSCRate();
  53. break;
  54. case SYSCON_ASYNC_MAINCLK:
  55. clkRate = Chip_Clock_GetMainClockRate();
  56. break;
  57. case SYSCON_ASYNC_CLKIN:
  58. clkRate = Chip_Clock_GetSystemPLLInClockRate();
  59. break;
  60. case SYSCON_ASYNC_SYSPLLOUT:
  61. clkRate = Chip_Clock_GetSystemPLLOutClockRate(false);
  62. break;
  63. default:
  64. clkRate = 0;
  65. break;
  66. }
  67. return clkRate;
  68. }
  69. /*****************************************************************************
  70. * Public functions
  71. ****************************************************************************/
  72. /* Return main A clock rate */
  73. uint32_t Chip_Clock_GetMain_A_ClockRate(void)
  74. {
  75. uint32_t clkRate = 0;
  76. switch (Chip_Clock_GetMain_A_ClockSource()) {
  77. case SYSCON_MAIN_A_CLKSRC_IRC:
  78. clkRate = Chip_Clock_GetIntOscRate();
  79. break;
  80. case SYSCON_MAIN_A_CLKSRCA_CLKIN:
  81. clkRate = Chip_Clock_GetExtClockInRate();
  82. break;
  83. case SYSCON_MAIN_A_CLKSRCA_WDTOSC:
  84. clkRate = Chip_Clock_GetWDTOSCRate();
  85. break;
  86. default:
  87. clkRate = 0;
  88. break;
  89. }
  90. return clkRate;
  91. }
  92. /* Return main B clock rate */
  93. uint32_t Chip_Clock_GetMain_B_ClockRate(void)
  94. {
  95. uint32_t clkRate = 0;
  96. switch (Chip_Clock_GetMain_B_ClockSource()) {
  97. case SYSCON_MAIN_B_CLKSRC_MAINCLKSELA:
  98. clkRate = Chip_Clock_GetMain_A_ClockRate();
  99. break;
  100. case SYSCON_MAIN_B_CLKSRC_SYSPLLIN:
  101. clkRate = Chip_Clock_GetSystemPLLInClockRate();
  102. break;
  103. case SYSCON_MAIN_B_CLKSRC_SYSPLLOUT:
  104. clkRate = Chip_Clock_GetSystemPLLOutClockRate(false);
  105. break;
  106. case SYSCON_MAIN_B_CLKSRC_RTC:
  107. clkRate = Chip_Clock_GetRTCOscRate();
  108. break;
  109. }
  110. return clkRate;
  111. }
  112. /* Set CLKOUT clock source and divider */
  113. void Chip_Clock_SetCLKOUTSource(CHIP_SYSCON_CLKOUTSRC_T src, uint32_t div)
  114. {
  115. uint32_t srcClk = (uint32_t) src;
  116. /* Use a clock A source? */
  117. if (src >= SYSCON_CLKOUTSRCA_OUTPUT) {
  118. /* Not using a CLKOUT A source */
  119. LPC_SYSCON->CLKOUTSELB = srcClk - SYSCON_CLKOUTSRCA_OUTPUT;
  120. }
  121. else {
  122. /* Using a clock A source, select A and then switch B to A */
  123. LPC_SYSCON->CLKOUTSELA = srcClk;
  124. LPC_SYSCON->CLKOUTSELB = 0;
  125. }
  126. LPC_SYSCON->CLKOUTDIV = div;
  127. }
  128. /* Enable a system or peripheral clock */
  129. void Chip_Clock_EnablePeriphClock(CHIP_SYSCON_CLOCK_T clk)
  130. {
  131. uint32_t clkEnab = (uint32_t) clk;
  132. if (clkEnab >= 128) {
  133. clkEnab = clkEnab - 128;
  134. LPC_ASYNC_SYSCON->ASYNCAPBCLKCTRLSET = (1 << clkEnab);
  135. }
  136. else if (clkEnab >= 32) {
  137. LPC_SYSCON->AHBCLKCTRLSET[1] = (1 << (clkEnab - 32));
  138. }
  139. else {
  140. LPC_SYSCON->AHBCLKCTRLSET[0] = (1 << clkEnab);
  141. }
  142. }
  143. /* Disable a system or peripheral clock */
  144. void Chip_Clock_DisablePeriphClock(CHIP_SYSCON_CLOCK_T clk)
  145. {
  146. uint32_t clkEnab = (uint32_t) clk;
  147. if (clkEnab >= 128) {
  148. clkEnab = clkEnab - 128;
  149. LPC_ASYNC_SYSCON->ASYNCAPBCLKCTRLCLR = (1 << clkEnab);
  150. }
  151. else if (clkEnab >= 32) {
  152. LPC_SYSCON->AHBCLKCTRLCLR[1] = (1 << (clkEnab - 32));
  153. }
  154. else {
  155. LPC_SYSCON->AHBCLKCTRLCLR[0] = (1 << clkEnab);
  156. }
  157. }
  158. /* Returns the system tick rate as used with the system tick divider */
  159. uint32_t Chip_Clock_GetSysTickClockRate(void)
  160. {
  161. uint32_t sysRate, div;
  162. div = LPC_SYSCON->SYSTICKCLKDIV;
  163. /* If divider is 0, the system tick clock is disabled */
  164. if (div == 0) {
  165. sysRate = 0;
  166. }
  167. else {
  168. sysRate = Chip_Clock_GetSystemClockRate() / LPC_SYSCON->SYSTICKCLKDIV;
  169. }
  170. return sysRate;
  171. }
  172. /* Return ADC clock rate */
  173. uint32_t Chip_Clock_GetADCClockRate(void)
  174. {
  175. uint32_t div, clkRate = 0;
  176. div = Chip_Clock_GetADCClockDiv();
  177. /* ADC clock only enabled if div>0 */
  178. if (div > 0) {
  179. switch (Chip_Clock_GetADCClockSource()) {
  180. case SYSCON_ADCCLKSELSRC_MAINCLK:
  181. clkRate = Chip_Clock_GetMainClockRate();
  182. break;
  183. case SYSCON_ADCCLKSELSRC_SYSPLLOUT:
  184. clkRate = Chip_Clock_GetSystemPLLOutClockRate(false);
  185. break;
  186. case SYSCON_ADCCLKSELSRC_IRC:
  187. clkRate = Chip_Clock_GetIntOscRate();
  188. break;
  189. }
  190. clkRate = clkRate / div;
  191. }
  192. return clkRate;
  193. }
  194. /* Set asynchronous APB clock source */
  195. void Chip_Clock_SetAsyncSysconClockSource(CHIP_ASYNC_SYSCON_SRC_T src)
  196. {
  197. uint32_t clkSrc = (uint32_t) src;
  198. if (src >= SYSCON_ASYNC_MAINCLK) {
  199. LPC_ASYNC_SYSCON->ASYNCAPBCLKSELB = (clkSrc - 4);
  200. }
  201. else {
  202. LPC_ASYNC_SYSCON->ASYNCAPBCLKSELA = clkSrc;
  203. LPC_ASYNC_SYSCON->ASYNCAPBCLKSELB = 3;
  204. }
  205. }
  206. /* Get asynchronous APB clock source */
  207. CHIP_ASYNC_SYSCON_SRC_T Chip_Clock_GetAsyncSysconClockSource(void)
  208. {
  209. uint32_t clkSrc;
  210. if (LPC_ASYNC_SYSCON->ASYNCAPBCLKSELB == 3) {
  211. clkSrc = LPC_ASYNC_SYSCON->ASYNCAPBCLKSELA;
  212. }
  213. else {
  214. clkSrc = 4 + LPC_ASYNC_SYSCON->ASYNCAPBCLKSELB;
  215. }
  216. return (CHIP_ASYNC_SYSCON_SRC_T) clkSrc;
  217. }
  218. /* Return asynchronous APB clock rate */
  219. uint32_t Chip_Clock_GetAsyncSyscon_ClockRate(void)
  220. {
  221. uint32_t clkRate, div;
  222. clkRate = Chip_Clock_GetAsyncSyscon_ClockRate_NoDiv();
  223. div = LPC_ASYNC_SYSCON->ASYNCCLKDIV;
  224. if (div == 0) {
  225. /* Clock is disabled */
  226. return 0;
  227. }
  228. return clkRate / div;
  229. }
  230. /* Set main system clock source */
  231. void Chip_Clock_SetMainClockSource(CHIP_SYSCON_MAINCLKSRC_T src)
  232. {
  233. uint32_t clkSrc = (uint32_t) src;
  234. if (clkSrc >= 4) {
  235. /* Main B source only, not using main A */
  236. Chip_Clock_SetMain_B_ClockSource((CHIP_SYSCON_MAIN_B_CLKSRC_T) (clkSrc - 4));
  237. }
  238. else {
  239. /* Select main A clock source and set main B source to use main A */
  240. Chip_Clock_SetMain_A_ClockSource((CHIP_SYSCON_MAIN_A_CLKSRC_T) clkSrc);
  241. Chip_Clock_SetMain_B_ClockSource(SYSCON_MAIN_B_CLKSRC_MAINCLKSELA);
  242. }
  243. }
  244. /* Returns the main clock source */
  245. CHIP_SYSCON_MAINCLKSRC_T Chip_Clock_GetMainClockSource(void)
  246. {
  247. CHIP_SYSCON_MAIN_B_CLKSRC_T srcB;
  248. uint32_t clkSrc;
  249. /* Get main B clock source */
  250. srcB = Chip_Clock_GetMain_B_ClockSource();
  251. if (srcB == SYSCON_MAIN_B_CLKSRC_MAINCLKSELA) {
  252. /* Using source A, so return source A */
  253. clkSrc = (uint32_t) Chip_Clock_GetMain_A_ClockSource();
  254. }
  255. else {
  256. /* Using source B */
  257. clkSrc = 4 + (uint32_t) srcB;
  258. }
  259. return (CHIP_SYSCON_MAINCLKSRC_T) clkSrc;
  260. }
  261. /* Return main clock rate */
  262. uint32_t Chip_Clock_GetMainClockRate(void)
  263. {
  264. uint32_t clkRate;
  265. if (Chip_Clock_GetMain_B_ClockSource() == SYSCON_MAIN_B_CLKSRC_MAINCLKSELA) {
  266. /* Return main A clock rate */
  267. clkRate = Chip_Clock_GetMain_A_ClockRate();
  268. }
  269. else {
  270. /* Return main B clock rate */
  271. clkRate = Chip_Clock_GetMain_B_ClockRate();
  272. }
  273. return clkRate;
  274. }
  275. /* Return system clock rate */
  276. uint32_t Chip_Clock_GetSystemClockRate(void)
  277. {
  278. /* No point in checking for divide by 0 */
  279. return Chip_Clock_GetMainClockRate() / LPC_SYSCON->AHBCLKDIV;
  280. }
  281. /* Get UART base rate */
  282. uint32_t Chip_Clock_GetUARTBaseClockRate(void)
  283. {
  284. uint64_t inclk;
  285. /* Get clock rate into FRG */
  286. inclk = (uint64_t) Chip_Clock_GetAsyncSyscon_ClockRate();
  287. if (inclk != 0) {
  288. uint32_t mult, divmult;
  289. divmult = LPC_ASYNC_SYSCON->FRGCTRL & 0xFF;
  290. if ((divmult & 0xFF) == 0xFF) {
  291. /* Fractional part is enabled, get multiplier */
  292. mult = (divmult >> 8) & 0xFF;
  293. /* Get fractional error */
  294. inclk = (inclk * 256) / (uint64_t) (256 + mult);
  295. }
  296. }
  297. return (uint32_t) inclk;
  298. }
  299. /* Set UART base rate */
  300. uint32_t Chip_Clock_SetUARTBaseClockRate(uint32_t rate)
  301. {
  302. uint32_t div, inclk, err;
  303. uint64_t uart_fra_multiplier;
  304. /* Input clock into FRG block is the main system cloock */
  305. inclk = Chip_Clock_GetAsyncSyscon_ClockRate();
  306. /* Get integer divider for coarse rate */
  307. div = inclk / rate;
  308. if (div == 0) {
  309. div = 1;
  310. }
  311. /* Enable FRG clock */
  312. Chip_Clock_EnablePeriphClock(SYSCON_CLOCK_FRG);
  313. err = inclk - (rate * div);
  314. uart_fra_multiplier = (((uint64_t) err + (uint64_t) rate) * 256) / (uint64_t) (rate * div);
  315. /* Enable fractional divider and set multiplier */
  316. LPC_ASYNC_SYSCON->FRGCTRL = 0xFF | (uart_fra_multiplier << 8);
  317. return Chip_Clock_GetUARTBaseClockRate();
  318. }