123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393 |
- /*
- * @brief LPC5410X clock driver
- *
- * @note
- * Copyright(C) NXP Semiconductors, 2014
- * All rights reserved.
- *
- * @par
- * Software that is described herein is for illustrative purposes only
- * which provides customers with programming information regarding the
- * LPC products. This software is supplied "AS IS" without any warranties of
- * any kind, and NXP Semiconductors and its licenser disclaim any and
- * all warranties, express or implied, including all implied warranties of
- * merchantability, fitness for a particular purpose and non-infringement of
- * intellectual property rights. NXP Semiconductors assumes no responsibility
- * or liability for the use of the software, conveys no license or rights under any
- * patent, copyright, mask work right, or any other intellectual property rights in
- * or to any products. NXP Semiconductors reserves the right to make changes
- * in the software without notification. NXP Semiconductors also makes no
- * representation or warranty that such application will be suitable for the
- * specified use without further testing or modification.
- *
- * @par
- * Permission to use, copy, modify, and distribute this software and its
- * documentation is hereby granted, under NXP Semiconductors' and its
- * licensor's relevant copyrights in the software, without fee, provided that it
- * is used in conjunction with NXP Semiconductors microcontrollers. This
- * copyright, permission, and disclaimer notice must appear in all copies of
- * this code.
- */
- #include "chip.h"
- /*****************************************************************************
- * Private types/enumerations/variables
- ****************************************************************************/
- /*****************************************************************************
- * Public types/enumerations/variables
- ****************************************************************************/
- /*****************************************************************************
- * Private functions
- ****************************************************************************/
- /* Return asynchronous APB clock rate (no regard for divider) */
- static uint32_t Chip_Clock_GetAsyncSyscon_ClockRate_NoDiv(void)
- {
- CHIP_ASYNC_SYSCON_SRC_T src;
- uint32_t clkRate;
- src = Chip_Clock_GetAsyncSysconClockSource();
- switch (src) {
- case SYSCON_ASYNC_IRC:
- clkRate = Chip_Clock_GetIntOscRate();
- break;
- case SYSCON_ASYNC_WDTOSC:
- clkRate = Chip_Clock_GetWDTOSCRate();
- break;
- case SYSCON_ASYNC_MAINCLK:
- clkRate = Chip_Clock_GetMainClockRate();
- break;
- case SYSCON_ASYNC_CLKIN:
- clkRate = Chip_Clock_GetSystemPLLInClockRate();
- break;
- case SYSCON_ASYNC_SYSPLLOUT:
- clkRate = Chip_Clock_GetSystemPLLOutClockRate(false);
- break;
- default:
- clkRate = 0;
- break;
- }
- return clkRate;
- }
- /*****************************************************************************
- * Public functions
- ****************************************************************************/
- /* Return main A clock rate */
- uint32_t Chip_Clock_GetMain_A_ClockRate(void)
- {
- uint32_t clkRate = 0;
- switch (Chip_Clock_GetMain_A_ClockSource()) {
- case SYSCON_MAIN_A_CLKSRC_IRC:
- clkRate = Chip_Clock_GetIntOscRate();
- break;
- case SYSCON_MAIN_A_CLKSRCA_CLKIN:
- clkRate = Chip_Clock_GetExtClockInRate();
- break;
- case SYSCON_MAIN_A_CLKSRCA_WDTOSC:
- clkRate = Chip_Clock_GetWDTOSCRate();
- break;
- default:
- clkRate = 0;
- break;
- }
- return clkRate;
- }
- /* Return main B clock rate */
- uint32_t Chip_Clock_GetMain_B_ClockRate(void)
- {
- uint32_t clkRate = 0;
- switch (Chip_Clock_GetMain_B_ClockSource()) {
- case SYSCON_MAIN_B_CLKSRC_MAINCLKSELA:
- clkRate = Chip_Clock_GetMain_A_ClockRate();
- break;
- case SYSCON_MAIN_B_CLKSRC_SYSPLLIN:
- clkRate = Chip_Clock_GetSystemPLLInClockRate();
- break;
- case SYSCON_MAIN_B_CLKSRC_SYSPLLOUT:
- clkRate = Chip_Clock_GetSystemPLLOutClockRate(false);
- break;
- case SYSCON_MAIN_B_CLKSRC_RTC:
- clkRate = Chip_Clock_GetRTCOscRate();
- break;
- }
- return clkRate;
- }
- /* Set CLKOUT clock source and divider */
- void Chip_Clock_SetCLKOUTSource(CHIP_SYSCON_CLKOUTSRC_T src, uint32_t div)
- {
- uint32_t srcClk = (uint32_t) src;
- /* Use a clock A source? */
- if (src >= SYSCON_CLKOUTSRCA_OUTPUT) {
- /* Not using a CLKOUT A source */
- LPC_SYSCON->CLKOUTSELB = srcClk - SYSCON_CLKOUTSRCA_OUTPUT;
- }
- else {
- /* Using a clock A source, select A and then switch B to A */
- LPC_SYSCON->CLKOUTSELA = srcClk;
- LPC_SYSCON->CLKOUTSELB = 0;
- }
- LPC_SYSCON->CLKOUTDIV = div;
- }
- /* Enable a system or peripheral clock */
- void Chip_Clock_EnablePeriphClock(CHIP_SYSCON_CLOCK_T clk)
- {
- uint32_t clkEnab = (uint32_t) clk;
- if (clkEnab >= 128) {
- clkEnab = clkEnab - 128;
- LPC_ASYNC_SYSCON->ASYNCAPBCLKCTRLSET = (1 << clkEnab);
- }
- else if (clkEnab >= 32) {
- LPC_SYSCON->AHBCLKCTRLSET[1] = (1 << (clkEnab - 32));
- }
- else {
- LPC_SYSCON->AHBCLKCTRLSET[0] = (1 << clkEnab);
- }
- }
- /* Disable a system or peripheral clock */
- void Chip_Clock_DisablePeriphClock(CHIP_SYSCON_CLOCK_T clk)
- {
- uint32_t clkEnab = (uint32_t) clk;
- if (clkEnab >= 128) {
- clkEnab = clkEnab - 128;
- LPC_ASYNC_SYSCON->ASYNCAPBCLKCTRLCLR = (1 << clkEnab);
- }
- else if (clkEnab >= 32) {
- LPC_SYSCON->AHBCLKCTRLCLR[1] = (1 << (clkEnab - 32));
- }
- else {
- LPC_SYSCON->AHBCLKCTRLCLR[0] = (1 << clkEnab);
- }
- }
- /* Returns the system tick rate as used with the system tick divider */
- uint32_t Chip_Clock_GetSysTickClockRate(void)
- {
- uint32_t sysRate, div;
- div = LPC_SYSCON->SYSTICKCLKDIV;
- /* If divider is 0, the system tick clock is disabled */
- if (div == 0) {
- sysRate = 0;
- }
- else {
- sysRate = Chip_Clock_GetSystemClockRate() / LPC_SYSCON->SYSTICKCLKDIV;
- }
- return sysRate;
- }
- /* Return ADC clock rate */
- uint32_t Chip_Clock_GetADCClockRate(void)
- {
- uint32_t div, clkRate = 0;
- div = Chip_Clock_GetADCClockDiv();
- /* ADC clock only enabled if div>0 */
- if (div > 0) {
- switch (Chip_Clock_GetADCClockSource()) {
- case SYSCON_ADCCLKSELSRC_MAINCLK:
- clkRate = Chip_Clock_GetMainClockRate();
- break;
- case SYSCON_ADCCLKSELSRC_SYSPLLOUT:
- clkRate = Chip_Clock_GetSystemPLLOutClockRate(false);
- break;
- case SYSCON_ADCCLKSELSRC_IRC:
- clkRate = Chip_Clock_GetIntOscRate();
- break;
- }
- clkRate = clkRate / div;
- }
- return clkRate;
- }
- /* Set asynchronous APB clock source */
- void Chip_Clock_SetAsyncSysconClockSource(CHIP_ASYNC_SYSCON_SRC_T src)
- {
- uint32_t clkSrc = (uint32_t) src;
- if (src >= SYSCON_ASYNC_MAINCLK) {
- LPC_ASYNC_SYSCON->ASYNCAPBCLKSELB = (clkSrc - 4);
- }
- else {
- LPC_ASYNC_SYSCON->ASYNCAPBCLKSELA = clkSrc;
- LPC_ASYNC_SYSCON->ASYNCAPBCLKSELB = 3;
- }
- }
- /* Get asynchronous APB clock source */
- CHIP_ASYNC_SYSCON_SRC_T Chip_Clock_GetAsyncSysconClockSource(void)
- {
- uint32_t clkSrc;
- if (LPC_ASYNC_SYSCON->ASYNCAPBCLKSELB == 3) {
- clkSrc = LPC_ASYNC_SYSCON->ASYNCAPBCLKSELA;
- }
- else {
- clkSrc = 4 + LPC_ASYNC_SYSCON->ASYNCAPBCLKSELB;
- }
- return (CHIP_ASYNC_SYSCON_SRC_T) clkSrc;
- }
- /* Return asynchronous APB clock rate */
- uint32_t Chip_Clock_GetAsyncSyscon_ClockRate(void)
- {
- uint32_t clkRate, div;
- clkRate = Chip_Clock_GetAsyncSyscon_ClockRate_NoDiv();
- div = LPC_ASYNC_SYSCON->ASYNCCLKDIV;
- if (div == 0) {
- /* Clock is disabled */
- return 0;
- }
- return clkRate / div;
- }
- /* Set main system clock source */
- void Chip_Clock_SetMainClockSource(CHIP_SYSCON_MAINCLKSRC_T src)
- {
- uint32_t clkSrc = (uint32_t) src;
- if (clkSrc >= 4) {
- /* Main B source only, not using main A */
- Chip_Clock_SetMain_B_ClockSource((CHIP_SYSCON_MAIN_B_CLKSRC_T) (clkSrc - 4));
- }
- else {
- /* Select main A clock source and set main B source to use main A */
- Chip_Clock_SetMain_A_ClockSource((CHIP_SYSCON_MAIN_A_CLKSRC_T) clkSrc);
- Chip_Clock_SetMain_B_ClockSource(SYSCON_MAIN_B_CLKSRC_MAINCLKSELA);
- }
- }
- /* Returns the main clock source */
- CHIP_SYSCON_MAINCLKSRC_T Chip_Clock_GetMainClockSource(void)
- {
- CHIP_SYSCON_MAIN_B_CLKSRC_T srcB;
- uint32_t clkSrc;
- /* Get main B clock source */
- srcB = Chip_Clock_GetMain_B_ClockSource();
- if (srcB == SYSCON_MAIN_B_CLKSRC_MAINCLKSELA) {
- /* Using source A, so return source A */
- clkSrc = (uint32_t) Chip_Clock_GetMain_A_ClockSource();
- }
- else {
- /* Using source B */
- clkSrc = 4 + (uint32_t) srcB;
- }
- return (CHIP_SYSCON_MAINCLKSRC_T) clkSrc;
- }
- /* Return main clock rate */
- uint32_t Chip_Clock_GetMainClockRate(void)
- {
- uint32_t clkRate;
- if (Chip_Clock_GetMain_B_ClockSource() == SYSCON_MAIN_B_CLKSRC_MAINCLKSELA) {
- /* Return main A clock rate */
- clkRate = Chip_Clock_GetMain_A_ClockRate();
- }
- else {
- /* Return main B clock rate */
- clkRate = Chip_Clock_GetMain_B_ClockRate();
- }
- return clkRate;
- }
- /* Return system clock rate */
- uint32_t Chip_Clock_GetSystemClockRate(void)
- {
- /* No point in checking for divide by 0 */
- return Chip_Clock_GetMainClockRate() / LPC_SYSCON->AHBCLKDIV;
- }
- /* Get UART base rate */
- uint32_t Chip_Clock_GetUARTBaseClockRate(void)
- {
- uint64_t inclk;
- /* Get clock rate into FRG */
- inclk = (uint64_t) Chip_Clock_GetAsyncSyscon_ClockRate();
- if (inclk != 0) {
- uint32_t mult, divmult;
- divmult = LPC_ASYNC_SYSCON->FRGCTRL & 0xFF;
- if ((divmult & 0xFF) == 0xFF) {
- /* Fractional part is enabled, get multiplier */
- mult = (divmult >> 8) & 0xFF;
- /* Get fractional error */
- inclk = (inclk * 256) / (uint64_t) (256 + mult);
- }
- }
- return (uint32_t) inclk;
- }
- /* Set UART base rate */
- uint32_t Chip_Clock_SetUARTBaseClockRate(uint32_t rate)
- {
- uint32_t div, inclk, err;
- uint64_t uart_fra_multiplier;
- /* Input clock into FRG block is the main system cloock */
- inclk = Chip_Clock_GetAsyncSyscon_ClockRate();
- /* Get integer divider for coarse rate */
- div = inclk / rate;
- if (div == 0) {
- div = 1;
- }
- /* Enable FRG clock */
- Chip_Clock_EnablePeriphClock(SYSCON_CLOCK_FRG);
- err = inclk - (rate * div);
- uart_fra_multiplier = (((uint64_t) err + (uint64_t) rate) * 256) / (uint64_t) (rate * div);
- /* Enable fractional divider and set multiplier */
- LPC_ASYNC_SYSCON->FRGCTRL = 0xFF | (uart_fra_multiplier << 8);
- return Chip_Clock_GetUARTBaseClockRate();
- }
|