summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/arm/lpc24xx/misc/system-clocks.c
diff options
context:
space:
mode:
authorThomas Doerfler <Thomas.Doerfler@embedded-brains.de>2008-09-22 11:30:09 +0000
committerThomas Doerfler <Thomas.Doerfler@embedded-brains.de>2008-09-22 11:30:09 +0000
commit5aeed173cf2cbdd7c003ce6f67658e274efc9b05 (patch)
tree4b6663898770eb47d745e61f421b43a2d725dc6f /c/src/lib/libbsp/arm/lpc24xx/misc/system-clocks.c
parentlpc24xx: New BSP (diff)
downloadrtems-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.c152
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);
+}