diff --git a/include/libopencm3/vf6xx/anadig.h b/include/libopencm3/vf6xx/anadig.h
new file mode 100644
index 00000000..594da960
--- /dev/null
+++ b/include/libopencm3/vf6xx/anadig.h
@@ -0,0 +1,224 @@
+/** @defgroup anadig_defines ANADIG Defines
+ *
+ * @brief Defined Constants and Types for the VF6xx Analog components
+ * control digital interface
+ *
+ * @ingroup VF6xx_defines
+ *
+ * @version 1.0.0
+ *
+ * @author @htmlonly © @endhtmlonly 2014
+ * Stefan Agner
+ *
+ * @date 01 July 2014
+ *
+ * LGPL License Terms @ref lgpl_license
+ * */
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2014 Stefan Agner
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see .
+ */
+
+#ifndef LIBOPENCM3_ANADIG_H
+#define LIBOPENCM3_ANADIG_H
+
+#include
+#include
+
+/* --- ANADIG registers ---------------------------------------------------- */
+
+#define ANADIG_PLL3_CTRL MMIO32(ANADIG_BASE + 0x010)
+#define ANADIG_PLL7_CTRL MMIO32(ANADIG_BASE + 0x020)
+#define ANADIG_PLL2_CTRL MMIO32(ANADIG_BASE + 0x030)
+#define ANADIG_PLL2_SS MMIO32(ANADIG_BASE + 0x040)
+#define ANADIG_PLL2_NUM MMIO32(ANADIG_BASE + 0x050)
+#define ANADIG_PLL2_DENOM MMIO32(ANADIG_BASE + 0x060)
+#define ANADIG_PLL4_CTRL MMIO32(ANADIG_BASE + 0x070)
+#define ANADIG_PLL4_NUM MMIO32(ANADIG_BASE + 0x080)
+#define ANADIG_PLL4_DENOM MMIO32(ANADIG_BASE + 0x090)
+#define ANADIG_PLL6_CTRL MMIO32(ANADIG_BASE + 0x0A0)
+#define ANADIG_PLL6_NUM MMIO32(ANADIG_BASE + 0x0B0)
+#define ANADIG_PLL6_DENOM MMIO32(ANADIG_BASE + 0x0C0)
+#define ANADIG_PLL5_CTRL MMIO32(ANADIG_BASE + 0x0E0)
+#define ANADIG_PLL3_PFD MMIO32(ANADIG_BASE + 0x0F0)
+#define ANADIG_PLL2_PFD MMIO32(ANADIG_BASE + 0x100)
+#define ANADIG_REG_1P1 MMIO32(ANADIG_BASE + 0x110)
+#define ANADIG_REG_3P0 MMIO32(ANADIG_BASE + 0x120)
+#define ANADIG_REG_2P5 MMIO32(ANADIG_BASE + 0x130)
+#define ANADIG_ANA_MISC0 MMIO32(ANADIG_BASE + 0x150)
+#define ANADIG_ANA_MISC1 MMIO32(ANADIG_BASE + 0x160)
+#define ANADIG_ANADIG_DIGPROG MMIO32(ANADIG_BASE + 0x260)
+#define ANADIG_PLL1_CTRL MMIO32(ANADIG_BASE + 0x270)
+#define ANADIG_PLL1_SS MMIO32(ANADIG_BASE + 0x280)
+#define ANADIG_PLL1_NUM MMIO32(ANADIG_BASE + 0x290)
+#define ANADIG_PLL1_DENOM MMIO32(ANADIG_BASE + 0x2A0)
+#define ANADIG_PLL1_PFD MMIO32(ANADIG_BASE + 0x2B0)
+#define ANADIG_PLL_LOCK MMIO32(ANADIG_BASE + 0x2C0)
+
+/* --- ANADIG values -....-------------------------------------------------- */
+
+/* ANADIG_PLL3_CTRL: PLL3 Control Register (480MHz PLL of USB0) */
+#define ANADIG_PLL3_CTRL_LOCK (1 << 31)
+#define ANADIG_PLL3_CTRL_BYPASS (1 << 16)
+#define ANADIG_PLL3_CTRL_BYPASS_CLK_SRC (1 << 14)
+#define ANADIG_PLL3_CTRL_ENABLE (1 << 13)
+#define ANADIG_PLL3_CTRL_POWER (1 << 12)
+#define ANADIG_PLL3_CTRL_EN_USB_CLKS (1 << 6)
+#define ANADIG_PLL3_CTRL_DIV_SELECT (1 << 1)
+
+/* ANADIG_PLL7_CTRL: PLL7 Control Register (480MHz PLL of USB1) */
+#define ANADIG_PLL7_CTRL_LOCK (1 << 31)
+#define ANADIG_PLL7_CTRL_BYPASS (1 << 16)
+#define ANADIG_PLL7_CTRL_BYPASS_CLK_SRC (1 << 14)
+#define ANADIG_PLL7_CTRL_ENABLE (1 << 13)
+#define ANADIG_PLL7_CTRL_POWER (1 << 12)
+#define ANADIG_PLL7_CTRL_EN_USB_CLKS (1 << 6)
+#define ANADIG_PLL7_CTRL_DIV_SELECT (1 << 1)
+
+/* ANADIG_PLL2_CTRL: PLL2 Control Register (528MHz PLL) */
+#define ANADIG_PLL2_CTRL_LOCK (1 << 31)
+#define ANADIG_PLL2_CTRL_PFD_OFFSET_EN (1 << 18)
+#define ANADIG_PLL2_CTRL_DITHER_ENABLE (1 << 17)
+#define ANADIG_PLL2_CTRL_BYPASS (1 << 16)
+#define ANADIG_PLL2_CTRL_BYPASS_CLK_SRC (1 << 14)
+#define ANADIG_PLL2_CTRL_ENABLE (1 << 13)
+#define ANADIG_PLL2_CTRL_POWERDOWN (1 << 12)
+#define ANADIG_PLL2_CTRL_DIV_SELECT (1 << 1)
+
+/* ANADIG_PLL2_SS: PLL2 Spread Spectrum definition register */
+#define ANADIG_PLL2_SS_STOP_MASK (0xffff << 16)
+#define ANADIG_PLL2_SS_ENABLE (1 << 15)
+#define ANADIG_PLL2_SS_STEP_MASK 0x8fff
+
+/* ANADIG_PLL2_NUM: PLL2 Numerator definition register */
+#define ANADIG_PLL2_NUM_MFN_MASK 0x3fffffff
+
+/* ANADIG_PLL2_DENOM: PLL2 Denominator definition register */
+#define ANADIG_PLL2_DENOM_MFN_MASK 0x3fffffff
+
+/* ANADIG_PLL4_CTRL: PLL4 Control Register (audio PLL) */
+#define ANADIG_PLL4_CTRL_LOCK (1 << 31)
+#define ANADIG_PLL4_CTRL_PFD_OFFSET_EN (1 << 18)
+#define ANADIG_PLL4_CTRL_DITHER_ENABLE (1 << 17)
+#define ANADIG_PLL4_CTRL_BYPASS (1 << 16)
+#define ANADIG_PLL4_CTRL_BYPASS_CLK_SRC (1 << 14)
+#define ANADIG_PLL4_CTRL_ENABLE (1 << 13)
+#define ANADIG_PLL4_CTRL_POWERDOWN (1 << 12)
+#define ANADIG_PLL4_CTRL_DIV_SELECT_MASK (0x7f)
+
+/* ANADIG_PLL4_NUM: PLL4 Numerator definition register */
+#define ANADIG_PLL4_NUM_MFN_MASK 0x3fffffff
+
+/* ANADIG_PLL4_DENOM: PLL4 Denominator definition register */
+#define ANADIG_PLL4_DENOM_MFN_MASK 0x3fffffff
+
+/* ANADIG_PLL6_CTRL: PLL6 Control Register (video PLL) */
+#define ANADIG_PLL6_CTRL_LOCK (1 << 31)
+#define ANADIG_PLL6_CTRL_PFD_OFFSET_EN (1 << 18)
+#define ANADIG_PLL6_CTRL_DITHER_ENABLE (1 << 17)
+#define ANADIG_PLL6_CTRL_BYPASS (1 << 16)
+#define ANADIG_PLL6_CTRL_BYPASS_CLK_SRC (1 << 14)
+#define ANADIG_PLL6_CTRL_ENABLE (1 << 13)
+#define ANADIG_PLL6_CTRL_POWERDOWN (1 << 12)
+#define ANADIG_PLL6_CTRL_DIV_SELECT_MASK (0x7f)
+
+/* ANADIG_PLL6_NUM: PLL6 Numerator definition register */
+#define ANADIG_PLL6_NUM_MFN_MASK 0x3fffffff
+
+/* ANADIG_PLL6_DENOM: PLL6 Denominator definition register */
+#define ANADIG_PLL6_DENOM_MFN_MASK 0x3fffffff
+
+/* ANADIG_PLL5_CTRL: PLL5 Control Register (video PLL) */
+#define ANADIG_PLL5_CTRL_LOCK (1 << 31)
+#define ANADIG_PLL5_CTRL_PFD_OFFSET_EN (1 << 18)
+#define ANADIG_PLL5_CTRL_DITHER_ENABLE (1 << 17)
+#define ANADIG_PLL5_CTRL_BYPASS (1 << 16)
+#define ANADIG_PLL5_CTRL_BYPASS_CLK_SRC (1 << 14)
+#define ANADIG_PLL5_CTRL_ENABLE (1 << 13)
+#define ANADIG_PLL5_CTRL_POWERDOWN (1 << 12)
+#define ANADIG_PLL5_CTRL_DIV_SELECT_MASK (0x3)
+
+/* ANADIG_PLL_PFD: PLL1/PLL2/PLL3 PFD Clocks */
+#define ANADIG_PLL_PFD4_CLKGATE (1 << 31)
+#define ANADIG_PLL_PFD4_STABLE (1 << 30)
+#define ANADIG_PLL_PFD4_FRAC_SHIFT 24
+#define ANADIG_PLL_PFD4_FRAC_MASK (0x3f << 24)
+#define ANADIG_PLL_PFD3_CLKGATE (1 << 23)
+#define ANADIG_PLL_PFD3_STABLE (1 << 22)
+#define ANADIG_PLL_PFD3_FRAC_SHIFT 16
+#define ANADIG_PLL_PFD3_FRAC_MASK (0x3f << 16)
+#define ANADIG_PLL_PFD2_CLKGATE (1 << 15)
+#define ANADIG_PLL_PFD2_STABLE (1 << 14)
+#define ANADIG_PLL_PFD2_FRAC_SHIFT 8
+#define ANADIG_PLL_PFD2_FRAC_MASK (0x3f << 8)
+#define ANADIG_PLL_PFD1_CLKGATE (1 << 7)
+#define ANADIG_PLL_PFD1_STABLE (1 << 6)
+#define ANADIG_PLL_PFD1_FRAC_SHIFT 0
+#define ANADIG_PLL_PFD1_FRAC_MASK (0x3f << 0)
+
+/* AANADIG_ANA_MISC0: miscellaneous analog blocks */
+#define ANADIG_ANA_MISC0_OSC_XTALOK_EN (1 << 17)
+#define ANADIG_ANA_MISC0_OSC_XTALOK (1 << 16)
+#define ANADIG_ANA_MISC0_CLK_24M_IRC_XTAL_SEL (1 << 13)
+#define ANADIG_ANA_MISC0_STOP_MODE_CONFIG (1 << 12)
+#define ANADIG_ANA_MISC0_REFTOP_VBGUP (1 << 7)
+#define ANADIG_ANA_MISC0_REFTOP_SELBIASOFF (1 << 3)
+#define ANADIG_ANA_MISC0_REFTOP_LOWPOWER (1 << 2)
+#define ANADIG_ANA_MISC0_REFTOP_PWDVBGUP (1 << 1)
+#define ANADIG_ANA_MISC0_REFTOP_PWD (1 << 0)
+
+/* AANADIG_ANA_MISC0: miscellaneous analog blocks */
+#define ANADIG_ANA_MISC1_IRQ_ANA_BO (1 << 30)
+#define ANADIG_ANA_MISC1_IRQ_TEMPSENSE (1 << 29)
+#define ANADIG_ANA_MISC1_LVDSCLK1_IBEN (1 << 12)
+#define ANADIG_ANA_MISC1_LVDSCLK1_OBEN (1 << 10)
+
+/* AANADIG_ANA_DIGPROG: Digital Program register */
+#define ANADIG_ANADIG_DIGPROG_MAJOR_MASK (0xffff << 8)
+#define ANADIG_ANADIG_DIGPROG_MINOR_MASK (0xff << 0)
+
+/* ANADIG_PLL1_CTRL: PLL1 Control Register (video PLL) */
+#define ANADIG_PLL1_CTRL_LOCK (1 << 31)
+#define ANADIG_PLL1_CTRL_PFD_OFFSET_EN (1 << 18)
+#define ANADIG_PLL1_CTRL_DITHER_ENABLE (1 << 17)
+#define ANADIG_PLL1_CTRL_BYPASS (1 << 16)
+#define ANADIG_PLL1_CTRL_BYPASS_CLK_SRC (1 << 14)
+#define ANADIG_PLL1_CTRL_ENABLE (1 << 13)
+#define ANADIG_PLL1_CTRL_POWERDOWN (1 << 12)
+#define ANADIG_PLL1_CTRL_DIV_SELECT (1 << 1)
+
+/* ANADIG_PLL1_SS: PLL1 Spread Spectrum definition register */
+#define ANADIG_PLL1_SS_STOP_MASK (0xffff << 16)
+#define ANADIG_PLL1_SS_ENABLE (1 << 15)
+#define ANADIG_PLL1_SS_STEP_MASK 0x8fff
+
+/* ANADIG_PLL1_NUM: PLL1 Numerator definition register */
+#define ANADIG_PLL1_NUM_MFN_MASK 0x3fffffff
+
+/* ANADIG_PLL1_DENOM: PLL1 Denominator definition register */
+#define ANADIG_PLL1_DENOM_MFN_MASK 0x3fffffff
+
+/* ANADIG_PLL_LOCK: PLL Lock Register */
+#define ANADIG_PLL_LOCK_PLL1 (1 << 6)
+#define ANADIG_PLL_LOCK_PLL2 (1 << 5)
+#define ANADIG_PLL_LOCK_PLL4 (1 << 4)
+#define ANADIG_PLL_LOCK_PLL6 (1 << 3)
+#define ANADIG_PLL_LOCK_PLL5 (1 << 2)
+#define ANADIG_PLL_LOCK_PLL3 (1 << 1)
+#define ANADIG_PLL_LOCK_PLL7 (1 << 0)
+
+#endif
diff --git a/include/libopencm3/vf6xx/ccm.h b/include/libopencm3/vf6xx/ccm.h
index 9451deea..5793beeb 100644
--- a/include/libopencm3/vf6xx/ccm.h
+++ b/include/libopencm3/vf6xx/ccm.h
@@ -81,19 +81,17 @@
#define CCM_CCSR_DAP_EN (1 << 24)
+/* PLL1/PLL2 PFD SEL definition */
#define CCM_CCSR_PLL2_PFD_CLK_SEL_SHIFT 19
-#define CCM_CCSR_PLL2_PFD_CLK_SEL_MAIN 0x0
-#define CCM_CCSR_PLL2_PFD_CLK_SEL_PFD1 0x1
-#define CCM_CCSR_PLL2_PFD_CLK_SEL_PFD2 0x2
-#define CCM_CCSR_PLL2_PFD_CLK_SEL_PFD3 0x3
-#define CCM_CCSR_PLL2_PFD_CLK_SEL_PFD4 0x4
-
+#define CCM_CCSR_PLL2_PFD_CLK_SEL_MASK (0x7 << 19)
#define CCM_CCSR_PLL1_PFD_CLK_SEL_SHIFT 16
-#define CCM_CCSR_PLL1_PFD_CLK_SEL_MAIN 0x0
-#define CCM_CCSR_PLL1_PFD_CLK_SEL_PFD1 0x1
-#define CCM_CCSR_PLL1_PFD_CLK_SEL_PFD2 0x2
-#define CCM_CCSR_PLL1_PFD_CLK_SEL_PFD3 0x3
-#define CCM_CCSR_PLL1_PFD_CLK_SEL_PFD4 0x4
+#define CCM_CCSR_PLL1_PFD_CLK_SEL_MASK (0x7 << 16)
+
+#define CCM_CCSR_PLL_PFD_CLK_SEL_MAIN 0x0
+#define CCM_CCSR_PLL_PFD_CLK_SEL_PFD1 0x1
+#define CCM_CCSR_PLL_PFD_CLK_SEL_PFD2 0x2
+#define CCM_CCSR_PLL_PFD_CLK_SEL_PFD3 0x3
+#define CCM_CCSR_PLL_PFD_CLK_SEL_PFD4 0x4
#define CCM_CCSR_PLL2_PFDN4_EN (1 << 15)
#define CCM_CCSR_PLL2_PFDN3_EN (1 << 14)
@@ -110,6 +108,7 @@
#define CCM_CCSR_SLOW_CLK_SEL (1 << 5)
#define CCM_CCSR_SYS_CLK_SEL_SHIFT 0
+#define CCM_CCSR_SYS_CLK_SEL_MASK 0x7
#define CCM_CCSR_SYS_CLK_SEL_FAST 0x0
#define CCM_CCSR_SYS_CLK_SEL_SLOW 0x1
#define CCM_CCSR_SYS_CLK_SEL_PLL2_PFD 0x2
@@ -117,7 +116,28 @@
#define CCM_CCSR_SYS_CLK_SEL_PLL1_PFD 0x4
#define CCM_CCSR_SYS_CLK_SEL_PLL3 0x5
+/* CACRR: ARM Clock Root Register */
+#define CCM_CACRR_FLEX_CLK_DIV_SHIFT 22
+#define CCM_CACRR_FLEX_CLK_DIV_MASK (0x7 << 22)
+#define CCM_CACRR_PLL6_CLK_DIV (1 << 21)
+#define CCM_CACRR_PLL3_CLK_DIV (1 << 20)
+#define CCM_CACRR_PLL1_PFD_CLK_DIV_SHIFT 16
+#define CCM_CACRR_PLL1_PFD_CLK_DIV_MASK (0x3 << 16)
+#define CCM_CACRR_IPG_CLK_DIV_SHIFT 11
+#define CCM_CACRR_IPG_CLK_DIV_MASK (0x3 << 11)
+#define CCM_CACRR_PLL4_CLK_DIV_SHIFT 6
+#define CCM_CACRR_PLL4_CLK_DIV_MASK (0x7 << 6)
+#define CCM_CACRR_BUS_CLK_DIV_SHIFT 3
+#define CCM_CACRR_BUS_CLK_DIV_MASK (0x7 << 3)
+#define CCM_CACRR_ARM_CLK_DIV_SHIFT 0
+#define CCM_CACRR_ARM_CLK_DIV_MASK (0x7 << 0)
+
/* --- Variable definitions ------------------------------------------------ */
+
+extern uint32_t ccm_core_clk;
+extern uint32_t ccm_platform_bus_clk;
+extern uint32_t ccm_ipg_bus_clk;
+
enum ccm_clock_gate {
/* AIPS0 */
CG0_FLEXCAN0 = 0,
@@ -323,6 +343,8 @@ enum ccm_clock_gate {
BEGIN_DECLS
void ccm_clock_gate_enable(enum ccm_clock_gate gr);
+void ccm_clock_gate_disable(enum ccm_clock_gate gr);
+void ccm_calculate_clocks(void);
END_DECLS
diff --git a/include/libopencm3/vf6xx/memorymap.h b/include/libopencm3/vf6xx/memorymap.h
index 830346a0..eeed63ff 100644
--- a/include/libopencm3/vf6xx/memorymap.h
+++ b/include/libopencm3/vf6xx/memorymap.h
@@ -44,6 +44,8 @@
#define SPI0_BASE (PERIPH_BASE_AIPS0 + 0x2C000)
#define SPI1_BASE (PERIPH_BASE_AIPS0 + 0x2D000)
+#define ANADIG_BASE (PERIPH_BASE_AIPS0 + 0x50000)
+
#define CCM_BASE (PERIPH_BASE_AIPS0 + 0x6B000)
/* AIPS1 */
diff --git a/lib/vf6xx/ccm.c b/lib/vf6xx/ccm.c
index cced3137..8468d6d8 100644
--- a/lib/vf6xx/ccm.c
+++ b/lib/vf6xx/ccm.c
@@ -37,8 +37,25 @@
#include
#include
+#include
/**@{*/
+static const uint32_t pll1_main_clk = 528000000;
+static const uint32_t pll2_main_clk = 528000000;
+static const uint32_t pll3_main_clk = 480000000;
+
+/* ARM Cortex-A5 clock, core clock */
+uint32_t ccm_core_clk = 0;
+
+/* Platform bus clock and Cortex-M4 core clock */
+uint32_t ccm_platform_bus_clk = 0;
+
+/* IPS bus clock */
+uint32_t ccm_ipg_bus_clk = 0;
+
+
+uint32_t ccm_get_pll_pfd(uint32_t pfd_sel, uint32_t pll_pfd, uint32_t pll_clk);
+
/*---------------------------------------------------------------------------*/
/** @brief Enable clock of given device
@@ -66,4 +83,122 @@ void ccm_clock_gate_disable(enum ccm_clock_gate gr)
uint32_t gr_mask = 0x3 << ((gr % 16) * 2);
CCM_CCGR(offset * 4) &= ~gr_mask;
}
+
+/*---------------------------------------------------------------------------*/
+/** @brief Calculate PFD clock
+
+This function calculates the PFD clock for PLL1/2 or 3. All those PLLs
+have the same PFD clock muxing/calculating logic, hence we can use one
+function for all of them
+
+@param[in] pfd_sel uint32_t. The PFD selection (muxing) value
+@param[in] pll_pfd uint32_t. The ANADIG PFD register containing the fractions
+for all possible PFDs
+@param[in] pll_clk uint32_t. PLLs main clock (which the PFDs are derived from)
+*/
+
+uint32_t ccm_get_pll_pfd(uint32_t pfd_sel, uint32_t pll_pfd, uint32_t pll_clk)
+{
+ uint64_t pll_pfd_clk;
+ uint32_t pll_pfd_frac = pll_pfd;
+
+ switch(pfd_sel)
+ {
+ case CCM_CCSR_PLL_PFD_CLK_SEL_MAIN:
+ return pll_clk;
+ case CCM_CCSR_PLL_PFD_CLK_SEL_PFD1:
+ pll_pfd_frac &= ANADIG_PLL_PFD1_FRAC_MASK;
+ pll_pfd_frac >>= ANADIG_PLL_PFD1_FRAC_SHIFT;
+ break;
+ case CCM_CCSR_PLL_PFD_CLK_SEL_PFD2:
+ pll_pfd_frac &= ANADIG_PLL_PFD2_FRAC_MASK;
+ pll_pfd_frac >>= ANADIG_PLL_PFD2_FRAC_SHIFT;
+ break;
+ case CCM_CCSR_PLL_PFD_CLK_SEL_PFD3:
+ pll_pfd_frac &= ANADIG_PLL_PFD3_FRAC_MASK;
+ pll_pfd_frac >>= ANADIG_PLL_PFD3_FRAC_SHIFT;
+ break;
+ case CCM_CCSR_PLL_PFD_CLK_SEL_PFD4:
+ pll_pfd_frac &= ANADIG_PLL_PFD4_FRAC_MASK;
+ pll_pfd_frac >>= ANADIG_PLL_PFD4_FRAC_SHIFT;
+ break;
+ }
+
+ /* Calculate using to PLL PFD fraction */
+ pll_pfd_clk = pll_clk;
+ pll_pfd_clk *= 18;
+ pll_pfd_clk /= pll_pfd_frac;
+
+ return (uint32_t)pll_pfd_clk;
+}
+
+/*---------------------------------------------------------------------------*/
+/** @brief Calculate clocks
+
+This function calculates the root clocks from the registers. On Vybrid, we
+assume that the clocks/device is setup by the main operating system running
+on the Cortex-A5 (for instance Linux). However, in order to calculate clocks
+for peripherals its important to know the current value of those clocks.
+
+This are mainly the @ref ccm_core_clk which the Cortex-A5 is running with
+and lots of other clocks derive from.
+The @ref ccm_platform_bus_clk is the clock which the Cortex-M4 is running
+with.
+And the @ref ccm_ipg_bus_clk is the clock most peripherals run with.
+
+*/
+
+void ccm_calculate_clocks()
+{
+ uint32_t ccsr = CCM_CCSR;
+ uint32_t cacrr = CCM_CACRR;
+ uint32_t arm_clk_div = (cacrr & CCM_CACRR_ARM_CLK_DIV_MASK) + 1;
+ uint32_t bus_clk_div = cacrr & CCM_CACRR_BUS_CLK_DIV_MASK;
+ uint32_t ipg_clk_div = cacrr & CCM_CACRR_IPG_CLK_DIV_MASK;
+ uint32_t pll_pfd_sel;
+
+ bus_clk_div >>= CCM_CACRR_BUS_CLK_DIV_SHIFT;
+ bus_clk_div += 1;
+
+ ipg_clk_div >>= CCM_CACRR_IPG_CLK_DIV_SHIFT;
+ ipg_clk_div += 1;
+
+ /* Get Cortex-A5 core clock from system clock selection */
+ switch(ccsr & CCM_CCSR_SYS_CLK_SEL_MASK)
+ {
+ case CCM_CCSR_SYS_CLK_SEL_FAST:
+ ccm_core_clk = 24000000;
+ break;
+ case CCM_CCSR_SYS_CLK_SEL_SLOW:
+ ccm_core_clk = 32000;
+ break;
+ case CCM_CCSR_SYS_CLK_SEL_PLL2_PFD:
+ pll_pfd_sel = ccsr & CCM_CCSR_PLL2_PFD_CLK_SEL_MASK;
+ pll_pfd_sel >>= CCM_CCSR_PLL2_PFD_CLK_SEL_SHIFT;
+
+ ccm_core_clk = ccm_get_pll_pfd(pll_pfd_sel, ANADIG_PLL2_PFD,
+ pll2_main_clk);
+ break;
+ case CCM_CCSR_SYS_CLK_SEL_PLL2:
+ ccm_core_clk = pll2_main_clk;
+ break;
+ case CCM_CCSR_SYS_CLK_SEL_PLL1_PFD:
+ pll_pfd_sel = ccsr & CCM_CCSR_PLL1_PFD_CLK_SEL_MASK;
+ pll_pfd_sel >>= CCM_CCSR_PLL1_PFD_CLK_SEL_SHIFT;
+
+ ccm_core_clk = ccm_get_pll_pfd(pll_pfd_sel, ANADIG_PLL1_PFD,
+ pll1_main_clk);
+ break;
+ case CCM_CCSR_SYS_CLK_SEL_PLL3:
+ ccm_core_clk = pll3_main_clk;
+ break;
+ }
+
+ ccm_core_clk /= arm_clk_div;
+ ccm_platform_bus_clk = ccm_core_clk / bus_clk_div;
+ ccm_ipg_bus_clk = ccm_platform_bus_clk / ipg_clk_div;
+
+ return;
+}
+
/**@}*/