/*
 * Copyright (c) 2022, Shenzhen CVA Innovation CO.,LTD
 * All rights reserved.
 *
 * Shenzhen CVA Innovation CO.,LTD (CVA chip) is supplying this file for use
 * exclusively with CVA's microcontroller products. This file can be freely
 * distributed within development tools that are supporting such microcontroller
 * products.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
 * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
 * CVA SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
 * OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 */

/*******************************************************************************
 * the includes
 ******************************************************************************/

#include "drivers/cpu/startup/system_M011x.h"
#include "drivers/cpu/cpu_drv.h"

/*******************************************************************************
 * the defines
 ******************************************************************************/

/*******************************************************************************
 * the typedefs
 ******************************************************************************/

/*******************************************************************************
 * the globals
 ******************************************************************************/

/*******************************************************************************
 * the functions
 ******************************************************************************/

void SystemInit(void)
{
#if 0
    /* PFLASH prefetch */
    SimReg_SetFlashPFlsFlushEn(SIM, 1); /* Flush PFLASH prefetch */
    SimReg_SetFlashPFlsPfbEn(SIM, 1);   /* Enable PFLASH prefetch*/

    /* Unlock SCG */
    Scg0Reg_SetKey(SCG0, 0x19962020);

#ifdef _USE_EXT_OSC_
    /* Use External oscillator */
    Scg0Reg_SetOscCtrlRange(SCG0, 1);  /* set SOSC frequency range(use max value when SOSC as the clock source of the PLL) */
    Scg0Reg_SetOscCtrlEnSosc(SCG0, 1); /* enable SOSC */
    while(Scg0Reg_GetStatusSoscRdy(SCG0) == 0)
    {
        ; /* wait until SOSC is ready */
    }

    /* Disable PLL */
    Scg0Reg_SetPllCtrl0PllEn(SCG0, 0);
    /* PLL configuration:
     * - PLL input clock source : SOSC
     * - PLL pre-divider : 1
     * - feedback divider : 40
     * - PLL Feedback clock divider pre-scaler : 1
     * - PLL post-divider setting : 4
     * Final PLL output frequency is 8M(SOSC) * 40 / 4 / 2 = 80M
     */
    Scg0Reg_SetPllCtrl1PllClkinSel(SCG0, 0);
    Scg0Reg_SetPllCtrl0PllPreDiv(SCG0, 0);
    Scg0Reg_SetPllCtrl0PllM(SCG0, 80);
    Scg0Reg_SetPllCtrl0PllFdkSel(SCG0, 0);
    Scg0Reg_SetPllCtrl0PllPosDiv(SCG0, 4);
    /* Enable PLL */
    Scg0Reg_SetPllCtrl0PllEn(SCG0, 1);

    /* Use systick for delay */
    SysTick->LOAD = 8000U;
    SysTick->VAL  = 0U;
    SysTick->CTRL = 5U;     /* SysTick uses the processor clock and enable sysTick */
    while(SysTick->CTRL < 0x10000){
        ;/* wait for COUNTFLAG setting*/
    }
    /*recover sysTick register*/
    SysTick->CTRL = 4U;
    SysTick->LOAD = 0U;
    SysTick->VAL  = 0U;

    while(Scg0Reg_GetStatusPllLock(SCG0) == 0)
    {
        ;
    }

    /* Flash AHB bus read access time configure */
    FtfcReg_SetFcnfgBusReadTm(FTFC, 1); /* 2T required for 80M AHB */

    /* Set clk_pll as system clock */
    Scg2Reg_SetCsrSrcSys(SCG2, 2);
    while(Scg2Reg_GetCsrSysSt(SCG2) != 2)
    {
        ;
    }
#else
    /* Disable PLL */
    Scg0Reg_SetPllCtrl0PllEn(SCG0, 0);
    /* PLL configuration:
     * - PLL input clock source : SIRC
     * - PLL pre-divider : 1
     * - feedback divider : 80
     * - PLL Feedback clock divider pre-scaler : 1
     * - PLL post-divider setting : 4
     * Final PLL output frequency is 8M(SIRC) * 80 / 4 / 2 = 80M
     */
    Scg0Reg_SetPllCtrl1PllClkinSel(SCG0, 1);
    Scg0Reg_SetPllCtrl0PllPreDiv(SCG0, 0);
    Scg0Reg_SetPllCtrl0PllM(SCG0, 80);
    Scg0Reg_SetPllCtrl0PllFdkSel(SCG0, 0);
    Scg0Reg_SetPllCtrl0PllPosDiv(SCG0, 4);
    /* Enable PLL */
    Scg0Reg_SetPllCtrl0PllEn(SCG0, 1);
    while(Scg0Reg_GetStatusPllLock(SCG0) == 0)
    {
        ;
    }

    /* Flash AHB bus read access time configure */
    FtfcReg_SetFcnfgBusReadTm(FTFC, 1); /* 2T required for 80M AHB */

    /* Set clk_pll as system clock */
    Scg2Reg_SetCsrSrcSys(SCG2, 2);
    while(Scg2Reg_GetCsrSysSt(SCG2) != 2)
    {
        ;
    }
#endif

    /* Set Core and APB clock source divider */
    Scg1Reg_SetCkSrcSysDiv(SCG1, 0); /* Divide-by-1 */
    Scg2Reg_SetCsrDivAips(SCG2, 0);  /* Divide-by-1 */

    /* Finish setting up the clock */
    Scg0Reg_SetKey(SCG0, 0); /* lock SCG again */
    
#endif
}
