/*!
    \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;

  uint32_t nmp            = D_NMP;
  uint32_t nvc1           = D_NVC1;
  uint32_t nvc2_s1        = D_NVC2_S1;
  uint32_t nvc2_s2        = D_NVC2_S2;
  uint32_t frac_en        = 1;
  uint32_t apbdiv         = 1;

  // Here, LISOC_RCC_RTC32KCTRL setting just to verify the interface of BWLISOCANATN40.
  uint32_t cnt_sel        = 0;
  uint32_t ext_code       = 55;
  uint32_t ext_code_en    = 1;
  uint32_t cal_div        = 0;
  uint32_t cal_allow      = 1;
  uint32_t cal_en         = 1;

  //nvc2_s1        = 0x3f;
  //nvc2_s2 |= 1 << 3;
  //nvc1 = 2;
  //nmp = 3;

  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.APBDIV      = apbdiv;  // [19]
  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]
  
  // 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]

  //LISOC_RCC->RCC_DATPLLCTRL.DPLL_LOCK_DLYTUNE = 1;
  //LISOC_RCC->RCC_SYSPLLCTRL.SPLL_LOCK_DLYTUNE = 1;

  LISOC_RCC->RCC_RTC32KCTRL.ANA_RES     = 1; //ES2 backup frequency divider
  //LISOC_RCC->RCC_DCXO_CTRL0.DCXO_MODE = 1;

  // 5. Wait for pll lock
  delay_us(100);


  #if 0
  //LISOC_RCC->RCC_DATPLLCTRL.DPLL_LOCK_RST = 1;
  //delay_us(100);

  //LISOC_RCC->RCC_DATPLLCTRL.DPLL_LOCK_RST = 0;
  //LISOC_RCC->RCC_ANATEST.SPLL_CLK_TEST_SEL = 1;
  //LISOC_RCC->RCC_ANATEST.DPLL_CLK_TEST_SEL = 1;
  //LISOC_RCC->RCC_ANATEST.DPLL_CLK_TEST_DIVSEL = 1;

  //LISOC_RCC->RCC_ANATEST.DCXO_TEST_DC_SEL = 3;
  #if 0
  LISOC_RCC->RCC_ANATEST.SPLL_DC_TEST_SEL = 0;
  LISOC_RCC->RCC_ANATEST.DPLL_DC_TEST_SEL = 3;
  LISOC_RCC->RCC_ANATEST.DCXO_TEST_DC_SEL = 3;

  LISOC_RCC->RCC_ANATEST.TEST_DC_CH = 4;
  LISOC_RCC->RCC_ANATEST.TEST_DC_EN = 1;
  #endif
  //LISOC_RCC->RCC_ANATEST.RC32K_TEST_CLK_SEL = 3;
  //LISOC_RCC->RCC_ANATEST.DCXO_TEST_CLK_SEL = 3;
  //LISOC_RCC->RCC_ANATEST.SPLL_CLK_TEST_SEL = 0;
  //LISOC_RCC->RCC_ANATEST.DPLL_CLK_TEST_SEL = 0;

  LISOC_RCC->RCC_ANATEST.TEST_CLK_CH = 5;
  LISOC_RCC->RCC_ANATEST.TEST_CLK_EN = 1;
  #endif



#if 0
  LISOC_RCC->RCC_ANATEST.TEST_CLK_CH = 1;
  LISOC_RCC->RCC_ANATEST.TEST_CLK_EN = 1;


  rcc_MCOSEL(VIDEO_CLK2);



  LISOC_RCC->RCC_ANATEST.TEST_CLK_CH = 5;
  LISOC_RCC->RCC_ANATEST.TEST_CLK_EN = 1;
  LISOC_RCC->RCC_ANATEST.RC32K_TEST_CLK_SEL = 6;
  LISOC_RCC->RCC_ANATEST.TEST_CLK_CH = 1;
  LISOC_RCC->RCC_ANATEST.TEST_CLK_EN = 1;
#endif
  //LISOC_RCC->RCC_ANATEST.TEST_CLK_CH = 5;
  //LISOC_RCC->RCC_ANATEST.TEST_CLK_EN = 1;

  rcc_MCOSEL(MRX_PIX_CLK);

  //printf("rcc init complete\n");
}

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

