diff options
author | Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> | 2008-09-22 11:30:09 +0000 |
---|---|---|
committer | Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> | 2008-09-22 11:30:09 +0000 |
commit | 5aeed173cf2cbdd7c003ce6f67658e274efc9b05 (patch) | |
tree | 4b6663898770eb47d745e61f421b43a2d725dc6f /c/src/lib/libbsp/arm/lpc24xx/misc/system-clocks.c | |
parent | lpc24xx: New BSP (diff) | |
download | rtems-5aeed173cf2cbdd7c003ce6f67658e274efc9b05.tar.bz2 |
lpc24xx: new BSP
Diffstat (limited to 'c/src/lib/libbsp/arm/lpc24xx/misc/system-clocks.c')
-rw-r--r-- | c/src/lib/libbsp/arm/lpc24xx/misc/system-clocks.c | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/arm/lpc24xx/misc/system-clocks.c b/c/src/lib/libbsp/arm/lpc24xx/misc/system-clocks.c new file mode 100644 index 0000000000..7f5df7dcdd --- /dev/null +++ b/c/src/lib/libbsp/arm/lpc24xx/misc/system-clocks.c @@ -0,0 +1,152 @@ +/** + * @file + * + * @ingroup lpc24xx + * + * @brief System clocks. + */ + +/* + * Copyright (c) 2008 + * Embedded Brains GmbH + * Obere Lagerstr. 30 + * D-82178 Puchheim + * Germany + * rtems@embedded-brains.de + * + * The license and distribution terms for this file may be found in the file + * LICENSE in this distribution or at http://www.rtems.com/license/LICENSE. + */ + +#include <libcpu/utility.h> + +#include <bsp.h> +#include <bsp/lpc24xx.h> +#include <bsp/system-clocks.h> + +/** + * @brief Internal RC oscillator frequency in [Hz]. + */ +#define LPC24XX_OSCILLATOR_INTERNAL 4000000U + +#ifdef LPC2478 + /** + * @brief Main oscillator frequency in [Hz]. + */ + #define LPC24XX_OSCILLATOR_MAIN 12000000U + + /** + * @brief RTC oscillator frequency in [Hz]. + */ + #define LPC24XX_OSCILLATOR_RTC 32768 +#else + #error Unknown oscillator frequencies +#endif + +/** + * @brief Returns the CPU clock frequency in [Hz]. + */ +unsigned lpc24xx_cclk( void) +{ + unsigned clksrc = GET_CLKSRCSEL_CLKSRC( CLKSRCSEL); + unsigned pllinclk = 0; + unsigned pllclk = 0; + unsigned cclk = 0; + + /* Get PLL input frequency */ + switch (clksrc) { + case 0: + pllinclk = LPC24XX_OSCILLATOR_INTERNAL; + break; + case 1: + pllinclk = LPC24XX_OSCILLATOR_MAIN; + break; + case 2: + pllinclk = LPC24XX_OSCILLATOR_RTC; + break; + default: + while (1) { + /* Spin forever */ + } + return 0; + } + + /* Get PLL output frequency */ + if (REG_FLAG_IS_SET( PLLSTAT, PLLSTAT_PLLC)) { + uint32_t pllcfg = PLLCFG; + unsigned n = GET_PLLCFG_NSEL( pllcfg) + 1; + unsigned m = GET_PLLCFG_MSEL( pllcfg) + 1; + + pllclk = (pllinclk / n) * 2 * m; + } else { + pllclk = pllinclk; + } + + /* Get CPU clock frequency */ + cclk = pllclk / (GET_CCLKCFG_CCLKSEL( CCLKCFG) + 1); + + return cclk; +} + +static void lpc24xx_pll_config( uint32_t val) +{ + PLLCON = val; + PLLFEED = 0xaa; + PLLFEED = 0x55; +} + +/** + * @brief Sets the Phase Locked Loop (PLL). + * + * @param clksrc Selects the clock source for the PLL. + * + * @param nsel Selects PLL pre-divider value (sometimes named psel). + * + * @param msel Selects PLL multiplier value. + * + * @param cclksel Selects the divide value for creating the CPU clock (CCLK) + * from the PLL output. + * + * @note All parameter values are the actual register field values. + */ +void lpc24xx_set_pll( unsigned clksrc, unsigned nsel, unsigned msel, unsigned cclksel) +{ + bool pll_enabled = REG_FLAG_IS_SET( PLLSTAT, PLLSTAT_PLLE); + + /* Disconnect PLL if necessary */ + if (REG_FLAG_IS_SET( PLLSTAT, PLLSTAT_PLLC)) { + if (pll_enabled) { + lpc24xx_pll_config( PLLCON_PLLE); + } else { + lpc24xx_pll_config( 0); + } + } + + /* Set CPU clock divider to a reasonable save value */ + CCLKCFG = SET_CCLKCFG_CCLKSEL( 0, 1); + + /* Disable PLL if necessary */ + if (pll_enabled) { + lpc24xx_pll_config( 0); + } + + /* Select clock source */ + CLKSRCSEL = SET_CLKSRCSEL_CLKSRC( 0, clksrc); + + /* Set PLL Configuration Register */ + PLLCFG = SET_PLLCFG_NSEL( 0, nsel) | SET_PLLCFG_MSEL( 0, msel); + + /* Enable PLL */ + lpc24xx_pll_config( PLLCON_PLLE); + + /* Wait for lock */ + while (REG_FLAG_IS_CLEARED( PLLSTAT, PLLSTAT_PLOCK)) { + /* Wait */ + } + + /* Set CPU clock divider and ensure that we have an odd value */ + CCLKCFG = SET_CCLKCFG_CCLKSEL( 0, cclksel | 1); + + /* Connect PLL */ + lpc24xx_pll_config( PLLCON_PLLE | PLLCON_PLLC); +} |