/*!
    \file    LISOC_RCC.c
    \brief   the LISOC_RCC configuration file

*/

#include "lisoc_test.h"
#include "rcc.h"
#include "datapath.h"

/*!
    \brief      LISOC_RCC per enable
    \param[in]  none
    \param[out] none
    \retval     none
*/
void rcc_PerEnable(RCC_PERn_Type RCC_PERn)
{
  LISOC_RCC->RCC_PERENR_W |= 0x1 << RCC_PERn;
}

/*!
    \brief      LISOC_RCC per disable
    \param[in]  none
    \param[out] none
    \retval     none
*/
void rcc_PerDisable(RCC_PERn_Type RCC_PERn)
{
  LISOC_RCC->RCC_PERENR_W &= ~(0x1 << RCC_PERn);
}

void rcc_RST(RCC_RSTn_Type RCC_RSTn)
{
  LISOC_RCC->RCC_SYSBLKRSTR_W |= 0x1 << RCC_RSTn;
  LISOC_RCC->RCC_SYSBLKRSTR_W &= ~(0x1 << RCC_RSTn);
}

void rcc_MCOSEL(RCC_MCOSELn_Type RCC_MCOSELn)
{
  LISOC_RCC->RCC_CR.MCOSEL = RCC_MCOSELn;
}

void rcc_switch(void)
{

  // 6. Set LISOC_RCC_SYSCFGR with 0x3F to switch clock
  LISOC_RCC->RCC_SYSCFGR.SYSSW = 1; // [0]
  LISOC_RCC->RCC_SYSCFGR.AXISW = 1; // [1]
  LISOC_RCC->RCC_SYSCFGR.BYTSW = 1; // [2]
  LISOC_RCC->RCC_SYSCFGR.PIXSW = 1; // [3]
  LISOC_RCC->RCC_SYSCFGR.VI1SW = 1; // [4]
  LISOC_RCC->RCC_SYSCFGR.VI2SW = 1; // [5]
}

/*!
    \brief      LISOC_RCC init
    \param[in]  none
    \param[out] none
    \retval     none
*/
void rcc_init(void)
{
  // 0. Parameters setting
  uint32_t datpll_ndiv    = 0x30;
  uint32_t datpll_npost   = 0;
  uint32_t datpll_da_en   = 1;
  uint32_t datpll_da_out_en   = 1;
  uint32_t syspll_ndiv    = 0x1d;
  uint32_t syspll_npost   = 0;
  uint32_t syspll_da_en   = 1;
  uint32_t syspll_da_out_en   = 1;

#if 1
  uint32_t nmp            = datapath_def_cfg.NMP;
  uint32_t nvc1           = datapath_def_cfg.NVC1;
  uint32_t nvc2_s1        = datapath_def_cfg.NVC2_S1;
  uint32_t nvc2_s2        = datapath_def_cfg.NVC2_S2;
#else
  uint32_t nmp            = D_NMP;
  uint32_t nvc1           = D_NVC1;
  uint32_t nvc2_s1        = D_NVC2_S1;
  uint32_t nvc2_s2        = D_NVC2_S2;
#endif

  uint32_t frac_en        = 1;
  uint32_t apbdiv         = 1;

  // Here, LISOC_RCC_RTC32KCTRL setting just to verify the interface of BWLISOCANATN40.
  #if 1
  uint32_t cnt_sel        = 0;
  uint32_t ext_code       = 62;
  uint32_t ext_code_en    = 1;
  uint32_t cal_div        = 0;
  uint32_t cal_allow      = 1;
  uint32_t cal_en         = 1;
  #else 
  uint32_t cnt_sel        = 1;
  uint32_t ext_code       = 0xf;
  uint32_t ext_code_en    = 1;
  uint32_t cal_div        = 1;
  uint32_t cal_allow      = 1;
  uint32_t cal_en         = 1;
  #endif
  LISOC_RCC->RCC_SDMCFGR_W = 0x15A5A5; // for dp normal mode



  // 1. Set LISOC_RCC_CR with 0x0008fd09
  //LISOC_RCC->RCC_CR_W = 0;
  LISOC_RCC->RCC_CR.NVC2_S1     = nvc2_s1; // [15:10]
  LISOC_RCC->RCC_CR.NVC1        = nvc1;    // [9:8]
  LISOC_RCC->RCC_CR.NMP         = nmp;     // [7:6]
  LISOC_RCC->RCC_CR.NVC2_S2     = nvc2_s2; // [5:1]
  LISOC_RCC->RCC_CR.FRAC_EN     = frac_en; // [0]
  LISOC_RCC->RCC_CR.APBDIV      = apbdiv;  // [19]

  // 2. Set LISOC_RCC_DATPLLCFGR with 0x00000830  ([31:12]: reserved)
  LISOC_RCC->RCC_DATPLLCFGR.RG_NPOST    = datpll_npost; // [6]
  LISOC_RCC->RCC_DATPLLCFGR.RG_NDIV     = datpll_ndiv;  // [5:0]
  LISOC_RCC->RCC_DATPLLCFGR.DA_EN       = datpll_da_en; // [11]
  LISOC_RCC->RCC_DATPLLCFGR.DA_OUT_EN   = datpll_da_out_en; // [10]

  // 3. Set LISOC_RCC_SYSPLLCFGR with 0x0000081d  ([31:12]: reserved)
  LISOC_RCC->RCC_SYSPLLCFGR.RG_NPOST    = syspll_npost; // [6]
  LISOC_RCC->RCC_SYSPLLCFGR.RG_NDIV     = syspll_ndiv;  // [5:0]
  LISOC_RCC->RCC_SYSPLLCFGR.DA_EN       = syspll_da_en; // [11]
  LISOC_RCC->RCC_SYSPLLCFGR.DA_OUT_EN   = syspll_da_out_en; // [10]
  
  // 4. Set LISOC_RCC_RTC32KCTRL with 0x000011f7 ([31:13]: reserved)
  LISOC_RCC->RCC_RTC32KCTRL.CNT_SEL     = cnt_sel;     // [12]
  LISOC_RCC->RCC_RTC32KCTRL.EXT_CODE    = ext_code;    // [11:5]
  LISOC_RCC->RCC_RTC32KCTRL.EXT_CODE_EN = ext_code_en; // [4]
  LISOC_RCC->RCC_RTC32KCTRL.CAL_DIV     = cal_div;     // [3:2]
  LISOC_RCC->RCC_RTC32KCTRL.CAL_ALLOW   = cal_allow;   // [1]
  LISOC_RCC->RCC_RTC32KCTRL.CAL_EN      = cal_en;      // [0]

  #if 0
  #if(video_format == UHD60_RAW10_YUV422_8 || video_format == UHD60_TPGEN_TEST)
  //#if(video_format == UHD60_RAW10_YUV422_8)
  LISOC_RCC->RCC_RTC32KCTRL.ANA_RES     = 1; //ES2 original frequency divider 297M->324M
  #else
  LISOC_RCC->RCC_RTC32KCTRL.ANA_RES     = 1; //ES2 backup frequency divider
  #endif
  #endif
  #ifndef ES1
  LISOC_RCC->RCC_RTC32KCTRL.ANA_RES     = 1; //ES2 backup frequency divider
  #endif
  // 5. Wait for pll lock
  while(LISOC_RCC->RCC_CR.SYSPLLLOCK ==0 || LISOC_RCC->RCC_CR.DATAPLLLOCK == 0);
  
}

void rcc_SYS_RESET(void)
{
  LISOC_RCC->RCC_SYSENR.SYSRST = 0x01u;
}

void rcc_cfg(void)
{
  LISOC_RCC->RCC_PERENR_W       = 0x0;
  LISOC_RCC->RCC_SYSENR_W       = 0x3E;
  LISOC_RCC->RCC_DPENR_W        = 0x0;
  LISOC_RCC->RCC_DPBLKRSTR_W    = 0x1FFF;
  rcc_init();
  rcc_switch();
  LISOC_RCC->RCC_PERENR_W       = 0x1FFF;
  LISOC_RCC->RCC_SYSENR_W       = 0x3F;
  LISOC_RCC->RCC_DPENR_W        = 0x1FF;
  LISOC_RCC->RCC_DPBLKRSTR_W    = 0;

  delay_ms(30);//Waiting for RCC to stabilizes

  rcc_MCOSEL(VIDEO_CLK2);

  #if 0

  LISOC_RCC->RCC_ANATEST.TEST_CLK_CH = 2;
  LISOC_RCC->RCC_ANATEST.TEST_CLK_EN = 1;

  LISOC_RCC->RCC_ANATEST.RC32K_TEST_CLK_SEL = 6;
  LISOC_RCC->RCC_ANATEST.DIV_TEST_EN = 1;
  LISOC_RCC->RCC_ANATEST.DIV_TEST_SEL = 6;
  #endif
}
