Newer
Older
mbed-os / targets / TARGET_TOSHIBA / TARGET_TMPM4G9 / device / system_TMPM4G9.c
@Deepak V. Shreshti Deepak V. Shreshti on 6 Dec 2019 16 KB Added SPDX identifier License
/**
 *******************************************************************************
 * @file    system_TMPM4G9.c
 * @brief   CMSIS Cortex-M4 Device Peripheral Access Layer Source File for the
 *          TOSHIBA 'TMPM4Gx' Device Series 
 * @version 1.0.0.0
 * $Date:: 2018-04-02 #$
 *
 * SPDX-License-Identifier: BSD-3-Clause
 *
 * Copyright(C) 2019, Toshiba Electronic Device Solutions Corporation
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *   1. Redistributions of source code must retain the above copyright notice,
 *      this list of conditions and the following disclaimer.
 *   2. 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.
 *   3. Neither the name of Nuvoton Technology Corp. 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 "TMPM4G9.h"

/*-------- <<< Start of configuration section >>> ----------------------------*/

/* Semi-Independent Watchdog Timer (SIWDT) Configuration */
#define SIWD_SETUP              (1U)                      /* 1:Disable SIWD, 0:Enable SIWD */
#define SIWDEN_Val              (0x00000000UL)            /* SIWD Disable */
#define SIWDCR_Val              (0x000000B1UL)            /* SIWD Disable code */

/* Clock Generator (CG) Configuration */
#define CLOCK_SETUP             (1U)                      /* 1:External HOSC, 0: Internal HOSC */
#define SYSCR_GEAR_Val          (0x00000000UL)            /* GEAR = fc */
#define SYSCR_MCKSEL_Val        (0x00000001UL)            /* fsysm(phiT0m) = fsysh(phiT0h) / 2 */

#define STBYCR_Val              (0x00000000UL)

#define CG_8M_MUL_20_FPLL       (0x00245028UL<<8U)        /* fPLL = 8MHz  * 20       */
#define CG_10M_MUL_16_FPLL      (0x002E5020UL<<8U)        /* fPLL = 10MHz * 16       */
#define CG_12M_MUL_13_3125_FPLL (0x0036DA1AUL<<8U)        /* fPLL = 12MHz * 13.3125  */
#define CG_16M_MUL_10_FPLL      (0x0048D014UL<<8U)        /* fPLL = 16MHz * 10       */
#define CG_20M_MUL_8_FPLL       (0x005AD010UL<<8U)        /* fPLL = 20MHz * 8        */

#define CG_PLL0SEL_PLL0ON_SET                (0x00000001UL)
#define CG_PLL0SEL_PLL0ON_CLEAR              (0xFFFFFFFEUL)
#define CG_PLL0SEL_PLL0SEL_SET               (0x00000002UL)
#define CG_PLL0SEL_PLL0SEL_CLEAR             (0xFFFFFFFDUL)

#define CG_SYSCR_MCKSEL_SET                  (SYSCR_MCKSEL_Val << 6U)
#define CG_SYSCR_MCKSELGST_Val               (SYSCR_MCKSEL_Val << 22U)
#define CG_SYSCR_MCKSELPST_Val               (SYSCR_MCKSEL_Val << 30U)

#define CG_OSCCR_IHOSC1EN_CLEAR              (0xFFFFFFFEUL)
#define CG_OSCCR_EOSCEN_SET                  (0x00000002UL)
#define CG_OSCCR_OSCSEL_SET                  (0x00000100UL)

#define CG_WUPHCR_WUON_START_SET             (0x00000001UL)

#define EXT_CG_WUPHCR_WUCLK_SET              (0x00000000UL)  /* WUCLK for External HOSC select the IHOSC1 */
#if (CLOCK_SETUP)
  #define CG_WUPHCR_WUCLK_SET                (0x00000100UL)  /* WUCLK for Inital/Lockup time */
  #define PLL0SEL_Ready          CG_10M_MUL_16_FPLL
#else
  #define CG_WUPHCR_WUCLK_SET                (0x00000000UL)  /* WUCLK for Inital/Lockup time */
  #define PLL0SEL_Ready          CG_10M_MUL_16_FPLL
#endif
#define PLL0SEL_Val              (PLL0SEL_Ready|0x00000003UL)
#define PLL0SEL_MASK             (0xFFFFFF00UL)

/*-------- <<< End of configuration section >>> ------------------------------*/

/*-------- DEFINES -----------------------------------------------------------*/
/* Define clocks */
#define EOSC_8M                 (8000000UL)
#define EOSC_10M                (10000000UL)
#define EOSC_12M                (12000000UL)
#define EOSC_16M                (16000000UL)
#define EOSC_20M                (20000000UL)
#define IOSC_10M                (10000000UL)
#define EXTALH                  EOSC_10M        /* External high-speed oscillator freq */
#define IXTALH                  IOSC_10M        /* Internal high-speed oscillator freq */
#define EOSC_8M_DIV2_PLLON      (160000000UL)   /* 8.00MHz  * 40.0000 / 2 */
#define EOSC_10M_DIV2_PLLON     (160000000UL)   /* 10.00MHz * 32.0000 / 2 */
#define EOSC_12M_DIV2_PLLON     (159750000UL)   /* 12.00MHz * 26.6250 / 2 */
#define EOSC_16M_DIV2_PLLON     (160000000UL)   /* 16.00MHz * 20.0000 / 2 */
#define EOSC_20M_DIV2_PLLON     (160000000UL)   /* 20.00MHz * 16.0000 / 2 */
#define IOSC_10M_DIV2_PLLON     (160000000UL)   /* 10.00MHz * 32.0000 / 2 */

/* Configure Warm-up time */
#define HZ_1M                  (1000000UL)
#define WU_TIME_EXT            (5000UL)          /* warm-up time for EXT is 5ms   */
#define INIT_TIME_PLL          (100UL)           /* Initial time for PLL is 100us */
#define LOCKUP_TIME_PLL        (400UL)           /* Lockup time for PLL is 400us  */
#define WUPHCR_WUPT_EXT        ((uint32_t)(((((uint64_t)WU_TIME_EXT * IXTALH / HZ_1M) - 16UL) /16UL) << 20U)) /* OSCCR<WUPT11:0> = (warm-up time(us) * IXTALH - 16) / 16 */
#if (CLOCK_SETUP)
  #define WUPHCR_INIT_PLL      ((uint32_t)(((((uint64_t)INIT_TIME_PLL * EXTALH / HZ_1M) - 16UL) /16UL) << 20U))
  #define WUPHCR_LUPT_PLL      ((uint32_t)(((((uint64_t)LOCKUP_TIME_PLL * EXTALH / HZ_1M) - 16UL) /16UL) << 20U))
#else
  #define WUPHCR_INIT_PLL      ((uint32_t)(((((uint64_t)INIT_TIME_PLL * IXTALH / HZ_1M) - 16UL) /16UL) << 20U))
  #define WUPHCR_LUPT_PLL      ((uint32_t)(((((uint64_t)LOCKUP_TIME_PLL * IXTALH / HZ_1M) - 16UL) /16UL) << 20U))
#endif

/* Determine core clock frequency according to settings */
/* System clock is high-speed clock*/
#if (CLOCK_SETUP)
  #define CORE_TALH (EXTALH)
#else
  #define CORE_TALH (IXTALH)
#endif

#if ((PLL0SEL_Val & (1U<<1U)) && (PLL0SEL_Val & (1U<<0U)))   /* If PLL selected and enabled */
  #if (CORE_TALH == EOSC_8M)         /* If input is 8MHz */
    #if ((PLL0SEL_Val & PLL0SEL_MASK) == (CG_8M_MUL_20_FPLL))
      #define __CORE_CLK   EOSC_8M_DIV2_PLLON                          /* output clock is 160MHz */
    #else                                     /* fc -> reserved */
      #define __CORE_CLK   (0U)
    #endif                           /* End input is 8MHz */
  #elif (CORE_TALH == EOSC_10M)      /* If input is 10MHz */
    #if ((PLL0SEL_Val & PLL0SEL_MASK) == CG_10M_MUL_16_FPLL)
      #define __CORE_CLK   EOSC_10M_DIV2_PLLON                         /* output clock is 160MHz */
    #else                                     /* fc -> reserved */
      #define __CORE_CLK   (0U)
    #endif                           /* End input is 10MHz */
  #elif (CORE_TALH == EOSC_12M)      /* If input is 12MHz */
    #if ((PLL0SEL_Val & PLL0SEL_MASK) == CG_12M_MUL_13_3125_FPLL)
      #define __CORE_CLK   EOSC_12M_DIV2_PLLON                         /* output clock is 159.75MHz */
    #else                                    /* fc -> reserved */
      #define __CORE_CLK   (0U)
    #endif                           /* End input is 12MHz    */
  #elif (CORE_TALH == EOSC_16M)      /* If input is 16MHz */
    #if ((PLL0SEL_Val & PLL0SEL_MASK) == CG_16M_MUL_10_FPLL)
      #define __CORE_CLK   EOSC_16M_DIV2_PLLON                         /* output clock is 160MHz */
    #else                                    /* fc -> reserved */
      #define __CORE_CLK   (0U)
    #endif                           /* End input is 16MHz    */
  #elif (CORE_TALH == EOSC_20M)      /* If input is 20MHz */
    #if ((PLL0SEL_Val & PLL0SEL_MASK) == CG_20M_MUL_8_FPLL)
      #define __CORE_CLK   EOSC_20M_DIV2_PLLON                         /* output clock is 160MHz */
    #else                                    /* fc -> reserved */
      #define __CORE_CLK   (0U)
    #endif                           /* End input is 20MHz    */
  #elif (CORE_TALH == IOSC_10M)      /* If input is 10MHz */
    #if ((PLL0SEL_Val & PLL0SEL_MASK) == CG_10M_MUL_16_FPLL)
      #define __CORE_CLK   IOSC_10M_DIV2_PLLON                         /* output clock is 160MHz */
    #else                                    /* fc -> reserved */
      #define __CORE_CLK   (0U)
    #endif                           /* End input is 10MHz    */
  #else                              /* input clock not known */
    #define __CORE_CLK   (0U)
    #error "Core Oscillator Frequency invalid!"
  #endif                             /* End switch input clock */
#else
  #define __CORE_CLK   (CORE_TALH)
#endif

#if   ((SYSCR_GEAR_Val & 7U) == 0U)      /* Gear -> fc                         */
  #define __CORE_SYS   (__CORE_CLK)
#elif ((SYSCR_GEAR_Val & 7U) == 1U)      /* Gear -> fc/2                       */
  #define __CORE_SYS   (__CORE_CLK / 2U)
#elif ((SYSCR_GEAR_Val & 7U) == 2U)      /* Gear -> fc/4                       */
  #define __CORE_SYS   (__CORE_CLK / 4U )
#elif ((SYSCR_GEAR_Val & 7U) == 3U)      /* Gear -> fc/8                       */
  #define __CORE_SYS   (__CORE_CLK / 8U)
#elif ((SYSCR_GEAR_Val & 7U) == 4U)      /* Gear -> fc/16                      */
  #define __CORE_SYS   (__CORE_CLK / 16U)
#else                               /* Gear -> reserved                   */
  #define __CORE_SYS   (0U)
#endif


/* Clock Variable definitions */
uint32_t SystemCoreClock = __CORE_SYS;  /*!< System Clock Frequency (Core Clock) */
uint32_t CoreClockInput = 0U;

/**
 * Initialize the system
 *
 * @param  none
 * @return none
 *
 * @brief  Update SystemCoreClock according register values.
 */
void SystemCoreClockUpdate(void)
{                               /* Get Core Clock Frequency */
    uint32_t CoreClock = 0U;
    uint32_t regval = 0U;
    uint32_t oscsel = 0U;
    uint32_t pll0sel = 0U;
    uint32_t pll0on = 0U;

	CoreClockInput = 0U;
    /* Determine clock frequency according to clock register values */
    /* System clock is high-speed clock */
    regval = TSB_CG->OSCCR;
    oscsel = regval & CG_OSCCR_OSCSEL_SET;
    if (oscsel) {  /* If system clock is External high-speed oscillator freq */
        CoreClock = EXTALH;
    } else {                    /* If system clock is Internal high-speed oscillator freq */
        CoreClock = IXTALH;
    }
    regval = TSB_CG->PLL0SEL;
    pll0sel = regval & CG_PLL0SEL_PLL0SEL_SET;
    pll0on = regval & CG_PLL0SEL_PLL0ON_SET;
    if (pll0sel && pll0on) {                      /* If PLL enabled  */
        if (CoreClock == EOSC_8M) {               /* If input is 8MHz */
            if ((TSB_CG->PLL0SEL & PLL0SEL_MASK) == CG_8M_MUL_20_FPLL) {
                CoreClockInput = EOSC_8M_DIV2_PLLON;           /* output clock is 160MHz */
            } else {
                CoreClockInput = 0U;    /* fc -> reserved */
            }
        } else if (CoreClock == EOSC_10M) {      /* If input is 10MHz */
            if ((TSB_CG->PLL0SEL & PLL0SEL_MASK) == CG_10M_MUL_16_FPLL) {
                CoreClockInput = EOSC_10M_DIV2_PLLON;          /* output clock is 160MHz */
            } else {
                CoreClockInput = 0U;    /* fc -> reserved */
            }
        } else if (CoreClock == EOSC_12M) {      /* If input is 12MHz */
            if ((TSB_CG->PLL0SEL & PLL0SEL_MASK) == CG_12M_MUL_13_3125_FPLL) {
                CoreClockInput = EOSC_12M_DIV2_PLLON;          /* output clock is 159.75MHz */
            } else {
                CoreClockInput = 0U;    /* fc -> reserved */
            }
        } else if (CoreClock == EOSC_16M) {      /* If input is 16MHz */
            if ((TSB_CG->PLL0SEL & PLL0SEL_MASK) == CG_16M_MUL_10_FPLL) {
                CoreClockInput = EOSC_16M_DIV2_PLLON;          /* output clock is 160MHz */
            } else {
                CoreClockInput = 0U;    /* fc -> reserved */
            }
        } else if (CoreClock == EOSC_20M) {      /* If input is 20MHz */
            if ((TSB_CG->PLL0SEL & PLL0SEL_MASK) == CG_20M_MUL_8_FPLL) {
                CoreClockInput = EOSC_20M_DIV2_PLLON;          /* output clock is 160MHz */
            } else {
                CoreClockInput = 0U;    /* fc -> reserved */
            }
        } else if (CoreClock == IOSC_10M) {      /* If input is 10MHz */
            if ((TSB_CG->PLL0SEL & PLL0SEL_MASK) == CG_10M_MUL_16_FPLL) {
                CoreClockInput = IOSC_10M_DIV2_PLLON;          /* output clock is 160MHz */
            } else {
                CoreClockInput = 0U;    /* fc -> reserved */
            }
        } else {
            CoreClockInput = 0U;
        }
    } else {                                       /* If PLL not used */
        CoreClockInput = CoreClock;
    }

    switch (TSB_CG->SYSCR & 7U) {
    case 0U:                                 /* Gear -> fc */
        SystemCoreClock = CoreClockInput;
        break;
    case 1U:                                 /* Gear -> fc/2 */
        SystemCoreClock = CoreClockInput / 2U;
        break;
    case 2U:                                 /* Gear -> fc/4 */
        SystemCoreClock = CoreClockInput / 4U;
        break;
    case 3U:                                 /* Gear -> fc/8 */
        SystemCoreClock = CoreClockInput / 8U;
        break;
    case 4U:                                 /* Gear -> fc/16 */
        SystemCoreClock = CoreClockInput / 16U;
        break;
    case 5U:
    case 6U:
    case 7U:
        SystemCoreClock = 0U;
        break;
    default:
        SystemCoreClock = 0U;
        break;
    }
}

/**
 * Initialize the system
 *
 * @param  none
 * @return none
 *
 * @brief  Setup the microcontroller system.
 *         Initialize the System.
 */
void SystemInit(void)
{
#if (SIWD_SETUP)                  /* Watchdog Setup */
    /* SIWD Disable */
    TSB_SIWD0->EN = SIWDEN_Val;
    TSB_SIWD0->CR = SIWDCR_Val;
#else
    /* SIWD Enable (Setting after a Reset) */
#endif

#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)   /* FPU setting */
  SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));  /* set CP10 and CP11 Full Access */
#endif

#if (CLOCK_SETUP)               /* Clock(external) Setup */
    TSB_CG->SYSCR = SYSCR_GEAR_Val;

    TSB_CG->WUPHCR = (WUPHCR_WUPT_EXT | EXT_CG_WUPHCR_WUCLK_SET);
    TSB_CG->OSCCR |= CG_OSCCR_EOSCEN_SET;
    TSB_CG->WUPHCR = (WUPHCR_WUPT_EXT | EXT_CG_WUPHCR_WUCLK_SET | CG_WUPHCR_WUON_START_SET);
    while (TSB_CG_WUPHCR_WUEF) {
		;
    }                           /* Warm-up */

    TSB_CG->OSCCR |= CG_OSCCR_OSCSEL_SET;
    while (!TSB_CG_OSCCR_OSCF) {
        ;
    }                         /* Confirm CGOSCCR<OSCF>="1" */
    TSB_CG->OSCCR &= CG_OSCCR_IHOSC1EN_CLEAR ;
#else
    /* Internal HOSC Enable (Setting after a Reset) */
#endif

    TSB_CG->SYSCR = (SYSCR_GEAR_Val | CG_SYSCR_MCKSEL_SET);   /* set <MCKSEL> */
    while((TSB_CG->SYSCR & (CG_SYSCR_MCKSELGST_Val | CG_SYSCR_MCKSELPST_Val))
           != ((CG_SYSCR_MCKSELGST_Val | CG_SYSCR_MCKSELPST_Val))){
        ;
    }

    TSB_CG->WUPHCR = (WUPHCR_INIT_PLL | CG_WUPHCR_WUCLK_SET);
    TSB_CG->PLL0SEL &= CG_PLL0SEL_PLL0SEL_CLEAR;    /* PLL-->fOsc */
    TSB_CG->PLL0SEL &= CG_PLL0SEL_PLL0ON_CLEAR;
    TSB_CG->PLL0SEL = PLL0SEL_Ready;
    TSB_CG->WUPHCR = (WUPHCR_INIT_PLL | CG_WUPHCR_WUCLK_SET | CG_WUPHCR_WUON_START_SET);
    while (TSB_CG_WUPHCR_WUEF) {
        ;
    }                           /* Warm-up */

    TSB_CG->WUPHCR = (WUPHCR_LUPT_PLL | CG_WUPHCR_WUCLK_SET);
    TSB_CG->PLL0SEL |= CG_PLL0SEL_PLL0ON_SET;    /* PLL enabled */
    TSB_CG->STBYCR = STBYCR_Val;
    TSB_CG->WUPHCR = (WUPHCR_LUPT_PLL | CG_WUPHCR_WUCLK_SET | CG_WUPHCR_WUON_START_SET);
    while (TSB_CG_WUPHCR_WUEF) {
        ;
    }                           /* Lockup */
    TSB_CG->PLL0SEL |= CG_PLL0SEL_PLL0SEL_SET;
    while (!TSB_CG_PLL0SEL_PLL0ST) {
        ;
    }                        /*Confirm CGPLL0SEL<PLL0ST> = "1" */
}