added prescaler for 16 bit pwm in LPC1347 target

Fork of mbed-dev by mbed official

Revision:
144:ef7eb2e8f9f7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_KL43Z/drivers/fsl_clock.c	Fri Sep 02 15:07:44 2016 +0100
@@ -0,0 +1,408 @@
+/*
+ * Copyright (c) 2015, Freescale Semiconductor, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ *   of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ *   list of conditions and the following disclaimer in the documentation and/or
+ *   other materials provided with the distribution.
+ *
+ * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "fsl_common.h"
+#include "fsl_clock.h"
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+#if (defined(OSC) && !(defined(OSC0)))
+#define OSC0 OSC
+#endif
+
+#define MCG_HIRC_FREQ (48000000U)
+#define MCG_LIRC_FREQ1 (2000000U)
+#define MCG_LIRC_FREQ2 (8000000U)
+
+#define MCG_S_CLKST_VAL ((MCG->S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT)
+#define MCG_SC_FCRDIV_VAL ((MCG->SC & MCG_SC_FCRDIV_MASK) >> MCG_SC_FCRDIV_SHIFT)
+#define MCG_MC_LIRC_DIV2_VAL ((MCG->MC & MCG_MC_LIRC_DIV2_MASK) >> MCG_MC_LIRC_DIV2_SHIFT)
+#define MCG_C2_IRCS_VAL ((MCG->C2 & MCG_C2_IRCS_MASK) >> MCG_C2_IRCS_SHIFT)
+
+#define SIM_CLKDIV1_OUTDIV1_VAL ((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV1_MASK) >> SIM_CLKDIV1_OUTDIV1_SHIFT)
+#define SIM_CLKDIV1_OUTDIV4_VAL ((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV4_MASK) >> SIM_CLKDIV1_OUTDIV4_SHIFT)
+#define SIM_SOPT1_OSC32KSEL_VAL ((SIM->SOPT1 & SIM_SOPT1_OSC32KSEL_MASK) >> SIM_SOPT1_OSC32KSEL_SHIFT)
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+
+/* External XTAL0 (OSC0) clock frequency. */
+uint32_t g_xtal0Freq;
+
+/* External XTAL32K clock frequency. */
+uint32_t g_xtal32Freq;
+
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+
+/*!
+ * @brief Get the current MCG_Lite LIRC_CLK frequency in Hz.
+ *
+ * This function will return the LIRC_CLK value in frequency(Hz) based
+ * on current MCG_Lite configurations and settings. It is an internal function.
+ *
+ * @return MCG_Lite LIRC_CLK frequency.
+ */
+static uint32_t CLOCK_GetLircClkFreq(void);
+
+/*!
+ * @brief Get RANGE value based on OSC frequency.
+ *
+ * To setup external crystal oscillator, must set the register bits RANGE base
+ * on the crystal frequency. This function returns the RANGE base on the input
+ * frequency. This is an internal function.
+ *
+ * @return RANGE value.
+ */
+static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq);
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+
+static uint32_t CLOCK_GetLircClkFreq(void)
+{
+    static const uint32_t lircFreqs[] = {MCG_LIRC_FREQ1, MCG_LIRC_FREQ2};
+
+    /* Check whether the LIRC is enabled. */
+    if ((MCG->C1 & MCG_C1_IRCLKEN_MASK) || (kMCGLITE_ClkSrcLirc == MCG_S_CLKST_VAL))
+    {
+        return lircFreqs[MCG_C2_IRCS_VAL];
+    }
+    else
+    {
+        return 0U;
+    }
+}
+
+static uint8_t CLOCK_GetOscRangeFromFreq(uint32_t freq)
+{
+    uint8_t range;
+
+    if (freq <= 39063U)
+    {
+        range = 0U;
+    }
+    else if (freq <= 8000000U)
+    {
+        range = 1U;
+    }
+    else
+    {
+        range = 2U;
+    }
+
+    return range;
+}
+
+uint32_t CLOCK_GetOsc0ErClkFreq(void)
+{
+    if (OSC0->CR & OSC_CR_ERCLKEN_MASK)
+    {
+        /* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */
+        assert(g_xtal0Freq);
+        return g_xtal0Freq;
+    }
+    else
+    {
+        return 0U;
+    }
+}
+
+uint32_t CLOCK_GetEr32kClkFreq(void)
+{
+    uint32_t freq;
+
+    switch (SIM_SOPT1_OSC32KSEL_VAL)
+    {
+        case 0U: /* OSC 32k clock  */
+            freq = (CLOCK_GetOsc0ErClkFreq() == 32768U) ? 32768U : 0U;
+            break;
+        case 2U: /* RTC 32k clock  */
+            /* Please call CLOCK_SetXtal32Freq base on board setting before using XTAL32K/RTC_CLKIN clock. */
+            assert(g_xtal32Freq);
+            freq = g_xtal32Freq;
+            break;
+        case 3U: /* LPO clock      */
+            freq = LPO_CLK_FREQ;
+            break;
+        default:
+            freq = 0U;
+            break;
+    }
+    return freq;
+}
+
+uint32_t CLOCK_GetPlatClkFreq(void)
+{
+    return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1);
+}
+
+uint32_t CLOCK_GetFlashClkFreq(void)
+{
+    uint32_t freq;
+
+    freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1);
+    freq /= (SIM_CLKDIV1_OUTDIV4_VAL + 1);
+
+    return freq;
+}
+
+uint32_t CLOCK_GetBusClkFreq(void)
+{
+    uint32_t freq;
+
+    freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1);
+    freq /= (SIM_CLKDIV1_OUTDIV4_VAL + 1);
+
+    return freq;
+}
+
+uint32_t CLOCK_GetCoreSysClkFreq(void)
+{
+    return CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1);
+}
+
+uint32_t CLOCK_GetFreq(clock_name_t clockName)
+{
+    uint32_t freq;
+
+    switch (clockName)
+    {
+        case kCLOCK_CoreSysClk:
+        case kCLOCK_PlatClk:
+            freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1);
+            break;
+        case kCLOCK_BusClk:
+        case kCLOCK_FlashClk:
+            freq = CLOCK_GetOutClkFreq() / (SIM_CLKDIV1_OUTDIV1_VAL + 1);
+            freq /= (SIM_CLKDIV1_OUTDIV4_VAL + 1);
+            break;
+        case kCLOCK_Er32kClk:
+            freq = CLOCK_GetEr32kClkFreq();
+            break;
+        case kCLOCK_Osc0ErClk:
+            freq = CLOCK_GetOsc0ErClkFreq();
+            break;
+        case kCLOCK_McgInternalRefClk:
+            freq = CLOCK_GetInternalRefClkFreq();
+            break;
+        case kCLOCK_McgPeriphClk:
+        case kCLOCK_McgIrc48MClk:
+            freq = CLOCK_GetPeriphClkFreq();
+            break;
+        case kCLOCK_LpoClk:
+            freq = LPO_CLK_FREQ;
+            break;
+        default:
+            freq = 0U;
+            break;
+    }
+
+    return freq;
+}
+
+void CLOCK_SetSimConfig(sim_clock_config_t const *config)
+{
+    SIM->CLKDIV1 = config->clkdiv1;
+    CLOCK_SetEr32kClock(config->er32kSrc);
+}
+
+bool CLOCK_EnableUsbfs0Clock(clock_usb_src_t src, uint32_t freq)
+{
+    bool ret = true;
+
+    CLOCK_DisableClock(kCLOCK_Usbfs0);
+
+    if (kCLOCK_UsbSrcExt == src)
+    {
+        SIM->SOPT2 &= ~SIM_SOPT2_USBSRC_MASK;
+    }
+    else
+    {
+        SIM->SOPT2 |= SIM_SOPT2_USBSRC_MASK;
+    }
+
+    CLOCK_EnableClock(kCLOCK_Usbfs0);
+
+    if (kCLOCK_UsbSrcIrc48M == src)
+    {
+        USB0->CLK_RECOVER_IRC_EN = 0x03U;
+        USB0->CLK_RECOVER_CTRL |= USB_CLK_RECOVER_CTRL_CLOCK_RECOVER_EN_MASK;
+    }
+
+    return ret;
+}
+
+uint32_t CLOCK_GetInternalRefClkFreq(void)
+{
+    uint8_t divider1 = MCG_SC_FCRDIV_VAL;
+    uint8_t divider2 = MCG_MC_LIRC_DIV2_VAL;
+    /* LIRC internal reference clock is selected*/
+    return CLOCK_GetLircClkFreq() >> (divider1 + divider2);
+}
+
+uint32_t CLOCK_GetPeriphClkFreq(void)
+{
+    /* Check whether the HIRC is enabled. */
+    if ((MCG->MC & MCG_MC_HIRCEN_MASK) || (kMCGLITE_ClkSrcHirc == MCG_S_CLKST_VAL))
+    {
+        return MCG_HIRC_FREQ;
+    }
+    else
+    {
+        return 0U;
+    }
+}
+
+uint32_t CLOCK_GetOutClkFreq(void)
+{
+    uint32_t freq;
+
+    switch (MCG_S_CLKST_VAL)
+    {
+        case kMCGLITE_ClkSrcHirc:
+            freq = MCG_HIRC_FREQ;
+            break;
+        case kMCGLITE_ClkSrcLirc:
+            freq = CLOCK_GetLircClkFreq() >> MCG_SC_FCRDIV_VAL;
+            break;
+        case kMCGLITE_ClkSrcExt:
+            /* Please call CLOCK_SetXtal0Freq base on board setting before using OSC0 clock. */
+            assert(g_xtal0Freq);
+            freq = g_xtal0Freq;
+            break;
+        default:
+            freq = 0U;
+            break;
+    }
+
+    return freq;
+}
+
+mcglite_mode_t CLOCK_GetMode(void)
+{
+    mcglite_mode_t mode;
+
+    switch (MCG_S_CLKST_VAL)
+    {
+        case kMCGLITE_ClkSrcHirc: /* HIRC */
+            mode = kMCGLITE_ModeHirc48M;
+            break;
+        case kMCGLITE_ClkSrcLirc: /* LIRC */
+            if (kMCGLITE_Lirc2M == MCG_C2_IRCS_VAL)
+            {
+                mode = kMCGLITE_ModeLirc2M;
+            }
+            else
+            {
+                mode = kMCGLITE_ModeLirc8M;
+            }
+            break;
+        case kMCGLITE_ClkSrcExt: /* EXT  */
+            mode = kMCGLITE_ModeExt;
+            break;
+        default:
+            mode = kMCGLITE_ModeError;
+            break;
+    }
+
+    return mode;
+}
+
+status_t CLOCK_SetMcgliteConfig(mcglite_config_t const *targetConfig)
+{
+    assert(targetConfig);
+
+    /*
+     * If switch between LIRC8M and LIRC2M, need to switch to HIRC mode first,
+     * because could not switch directly.
+     */
+    if ((kMCGLITE_ClkSrcLirc == MCG_S_CLKST_VAL) && (kMCGLITE_ClkSrcLirc == targetConfig->outSrc) &&
+        (MCG_C2_IRCS_VAL != targetConfig->ircs))
+    {
+        MCG->C1 = (MCG->C1 & ~MCG_C1_CLKS_MASK) | MCG_C1_CLKS(kMCGLITE_ClkSrcHirc);
+        while (kMCGLITE_ClkSrcHirc != MCG_S_CLKST_VAL)
+        {
+        }
+    }
+
+    /* Set configuration now. */
+    MCG->SC = MCG_SC_FCRDIV(targetConfig->fcrdiv);
+    MCG->MC = MCG_MC_HIRCEN(targetConfig->hircEnableInNotHircMode) | MCG_MC_LIRC_DIV2(targetConfig->lircDiv2);
+    MCG->C2 = (MCG->C2 & ~MCG_C2_IRCS_MASK) | MCG_C2_IRCS(targetConfig->ircs);
+    MCG->C1 = MCG_C1_CLKS(targetConfig->outSrc) | targetConfig->irclkEnableMode;
+
+    /*
+     * If external oscillator used and MCG_Lite is set to EXT mode, need to
+     * wait for the OSC stable.
+     */
+    if ((MCG->C2 & MCG_C2_EREFS0_MASK) && (kMCGLITE_ClkSrcExt == targetConfig->outSrc))
+    {
+        while (!(MCG->S & MCG_S_OSCINIT0_MASK))
+        {
+        }
+    }
+
+    /* Wait for clock source change completed. */
+    while (targetConfig->outSrc != MCG_S_CLKST_VAL)
+    {
+    }
+
+    return kStatus_Success;
+}
+
+void CLOCK_InitOsc0(osc_config_t const *config)
+{
+    uint8_t range = CLOCK_GetOscRangeFromFreq(config->freq);
+
+    OSC_SetCapLoad(OSC0, config->capLoad);
+    OSC_SetExtRefClkConfig(OSC0, &config->oscerConfig);
+
+    MCG->C2 = ((MCG->C2 & MCG_C2_IRCS_MASK) | MCG_C2_RANGE0(range) | (uint8_t)config->workMode);
+
+    if ((kOSC_ModeExt != config->workMode) && (OSC0->CR & OSC_CR_ERCLKEN_MASK))
+    {
+        /* Wait for stable. */
+        while (!(MCG->S & MCG_S_OSCINIT0_MASK))
+        {
+        }
+    }
+}
+
+void CLOCK_DeinitOsc0(void)
+{
+    OSC0->CR = 0U;
+    MCG->C2 &= MCG_C2_IRCS_MASK;
+}