/* SPDX-License-Identifier: BSD-3-Clause */

#include "dramc_dv_init.h"

void CKE_FIX_ON(DRAMC_CTX_T *p, U8 EN, U8 rank)
{
  switch(rank)
  {
    case 0 : vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CKECTRL), P_Fld(EN, CKECTRL_CKEFIXON));  break;
    case 1 : vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CKECTRL), P_Fld(EN, CKECTRL_CKE1FIXON)); break;
    default: mcSHOW_ERR_MSG(("ERROR: CKE FIX ON error. Unexpected Rank  \n"));
  }
}

static void LP4_MRS(DRAMC_CTX_T *p, U16 reg_addr, U8 reg_op, U8 rank)
{
    U8 temp_MRS_RESPONSE  ;

    mcSHOW_DBG_MSG6(("[LP4_DRAM_INIT_MRS] RK:%1d-MA:%2d-OP:0x%2x @Channle:%1d\n",rank,reg_addr,reg_op,vGetPHY2ChannelMapping(p)));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL0), P_Fld(rank , SWCMD_CTRL0_MRSRK       ) \
                                                            | P_Fld(reg_addr, SWCMD_CTRL0_MRSMA    ) \
                                                            | P_Fld(reg_op  , SWCMD_CTRL0_MRSOP    ));

    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN), 0);
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN), P_Fld(1, SWCMD_EN_MRWEN));

    temp_MRS_RESPONSE = 0 ;
    do
    {
        temp_MRS_RESPONSE = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP), SPCMDRESP_MRW_RESPONSE) ;
    } while ( temp_MRS_RESPONSE != 1 );
    
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN), P_Fld(0, SWCMD_EN_MRWEN));
}


static void LP4_FSP_WR_or_OP (DRAMC_CTX_T *p, U8 FSP_WR, U8 FSP_OP, U8 rank)
{
	U8 MR13 = 0;
    MR13 = ((FSP_OP & 1) << 7) | ((FSP_WR & 1) << 6) /*| ((LP4_DMI & 1) << 5)*/ | (1 << 4);
    LP4_MRS(p, 13, MR13, rank);
}


static void lp4_dram_init_single_rank(DRAMC_CTX_T *p,LP4_DRAM_CONFIG_T *tr,U8 rank)
{
    U8 MR1;
    U8 MR2;
    U8 MR3;
    U8 MR51;
    U8 MR11;
    U8 MR12;
    U8 MR14;


    U8 nWR    =5; 
    U8 WR_LEV =0; 
    U8 PDDS   =5; 
    U8 PPRP   =0; 
    U8 PU_CAL =0; 
    U8 WLS    =0; 
    



    MR1 = ((tr->RPST    & 1)<<7) | ((nWR         & 7)<<4) | ((tr->RD_PRE  & 1)<<3) | ((tr->WR_PRE & 1)<<2) | ((tr->BL & 3)<<0);
    MR2 = ((WR_LEV      & 1)<<7) | ((WLS         & 1)<<6) | ((tr->MR_WL   & 7)<<3) | ((tr->MR_RL  & 7)<<0); 
    MR3 = ((tr->DBI_WR  & 1)<<7) | ((tr->DBI_RD  & 1)<<6) | ((   PDDS     & 7)<<3) | ((PPRP       & 1)<<2) | ((tr->WR_PST & 1)<<1) | ((PU_CAL & 1)<<0);
    MR51= ((tr->LP4Y_EN & 1)<<3) | ((tr->LP4Y_EN & 1)<<2) | ((tr->LP4Y_EN & 1)<<1);
    if(tr->WORK_FSP == 0)
    {
        MR11 = 0x0;
        MR14 = 0x5d;
    }
    else
    {
        MR11 = 0x04;
        MR14 = 0x18;
    }
    MR12= 0x5d;
    #if FSP1_CLKCA_TERM
    if(p->dram_fsp == FSP_1)
        MR12 = 0x20;
    #endif

    u1MR02Value[tr->WORK_FSP] = MR2;
    u1MR03Value[tr->WORK_FSP] = MR3;
    #if ENABLE_LP4_ZQ_CAL
    DramcZQCalibration(p, rank);
    #endif

    mcSHOW_DBG_MSG6(("[LP4_DRAM_INIT] Channle:%1d-Rank:%1d >>>>>>\n",vGetPHY2ChannelMapping(p),rank));


    if(tr->WORK_FSP == 0) {LP4_FSP_WR_or_OP(p, 0, 1, rank);}
    else                  {LP4_FSP_WR_or_OP(p, 1, 0, rank);}

    mcDELAY_XNS(15);

    LP4_MRS(p,  1, MR1 , rank);
    LP4_MRS(p,  2, MR2 , rank);
    LP4_MRS(p,  3, MR3 , rank);
    LP4_MRS(p,  11, MR11 , rank);
    LP4_MRS(p,  12, MR12 , rank);
    LP4_MRS(p,  14, MR14 , rank);
    if(tr->LP4Y_EN == 1)  { LP4_MRS(p, 51, MR51, rank); }
    
    mcDELAY_XNS(15);


    if(tr->WORK_FSP == 0) {LP4_FSP_WR_or_OP(p, 1, 0, rank);}
    else                  {LP4_FSP_WR_or_OP(p, 0, 1, rank);}

    mcDELAY_XNS(15);

    LP4_MRS(p,  1, MR1 , rank);
    LP4_MRS(p,  2, MR2 , rank);

    MR3 = (((!tr->DBI_WR)  & 1)<<7) | (((!tr->DBI_RD)  & 1)<<6) | ((   PDDS     & 7)<<3) | ((PPRP       & 1)<<2) | ((tr->WR_PST & 1)<<1) | ((PU_CAL & 1)<<0);
    LP4_MRS(p,  3, MR3 , rank);
    LP4_MRS(p,  11, MR11 , rank);
    LP4_MRS(p,  12, MR12 , rank);
    LP4_MRS(p,  14, MR14 , rank);

    LP4_FSP_WR_or_OP(p, tr->WORK_FSP, tr->WORK_FSP, rank);

    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_CA_CMD7)     , P_Fld( 1       , CA_CMD7_RG_TX_ARCLKB_PULL_DN_LP4Y       ));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ7)      , P_Fld( 1       , B0_DQ7_RG_TX_ARDQS0B_PULL_DN_B0_LP4Y    ));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ7)      , P_Fld( 1       , B1_DQ7_RG_TX_ARDQS0B_PULL_DN_B1_LP4Y    ));

    mcSHOW_DBG_MSG6(("[LP4_DRAM_INIT] Channle:%1d-Rank:%1d <<<<<<\n",vGetPHY2ChannelMapping(p),rank));
}

void LP4_single_end_DRAMC_post_config(DRAMC_CTX_T *p, U8 LP4Y_EN)
{
    mcSHOW_DBG_MSG6(("============ LP4 DIFF to SE enter ============\n"));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_CMD13), P_Fld( LP4Y_EN , SHU_CA_CMD13_RG_TX_ARCLKB_OE_TIE_SEL_CA ) \
                                                              | P_Fld( LP4Y_EN       , SHU_CA_CMD13_RG_TX_ARCLKB_OE_TIE_EN_CA  ));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DQ13) , P_Fld( LP4Y_EN , SHU_B0_DQ13_RG_TX_ARDQSB_OE_TIE_SEL_B0  ) \
                                                              | P_Fld( LP4Y_EN       , SHU_B0_DQ13_RG_TX_ARDQSB_OE_TIE_EN_B0   ));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DQ13) , P_Fld( LP4Y_EN , SHU_B1_DQ13_RG_TX_ARDQSB_OE_TIE_SEL_B1  ) \
                                                              | P_Fld( LP4Y_EN       , SHU_B1_DQ13_RG_TX_ARDQSB_OE_TIE_EN_B1   ));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_CMD0) , P_Fld( 0 , SHU_CA_CMD0_R_LP4Y_WDN_MODE_CLK         ));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DQ0)  , P_Fld( 0 , SHU_B0_DQ0_R_LP4Y_WDN_MODE_DQS0         ));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DQ0)  , P_Fld( 0 , SHU_B1_DQ0_R_LP4Y_WDN_MODE_DQS1         ));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_CMD7) , P_Fld( 0 , SHU_CA_CMD7_R_LP4Y_SDN_MODE_CLK         ));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DQ7)  , P_Fld( LP4Y_EN , SHU_B0_DQ7_R_LP4Y_SDN_MODE_DQS0         ));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DQ7)  , P_Fld( LP4Y_EN , SHU_B1_DQ7_R_LP4Y_SDN_MODE_DQS1         ));

#if 1

    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_CA_CMD7)     , P_Fld( 0 , CA_CMD7_RG_TX_ARCLKB_PULL_DN_LP4Y       ));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ7)      , P_Fld( 0 , B0_DQ7_RG_TX_ARDQS0B_PULL_DN_B0_LP4Y    ));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ7)      , P_Fld( 0 , B1_DQ7_RG_TX_ARDQS0B_PULL_DN_B1_LP4Y    ));
#else

    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_CA_CMD7)     , P_Fld( 1 , CA_CMD7_RG_TX_ARCLKB_PULL_DN_LP4Y       ));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ7)      , P_Fld( 1 , B0_DQ7_RG_TX_ARDQS0B_PULL_DN_B0_LP4Y    ));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ7)      , P_Fld( 1 , B1_DQ7_RG_TX_ARDQS0B_PULL_DN_B1_LP4Y    ));
#endif
    mcSHOW_DBG_MSG6(("============ LP4 DIFF to SE exit  ============\n"));
}

void LP4_DRAM_INIT(DRAMC_CTX_T *p)
{
    U8 RANK;


#if SA_CONFIG_EN && DV_SIMULATION_DFS
    DramcPowerOnSequence(p);
#endif


    mcDELAY_XNS(200);

    for(RANK=0;RANK<2;RANK++)
    {
        CKE_FIX_ON(p,1,RANK);
        mcDELAY_XNS(400);


        lp4_dram_init_single_rank(p,DV_p.lp4_init,RANK);
        CKE_FIX_ON(p,0,RANK);
    }

    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0), P_Fld(0, REFCTRL0_REFDIS));
}

