/* * dmc.c * * Created on: 2021Äê10ÔÂ30ÈÕ * Author: graydon */ #include #include #include #include #include #include "DMCInit.h" /* delay function */ #pragma inline static void dmcdelay(uint32_t delay) { uint32_t i; for(i=delay; i>0ul; i--){ NOP(); } } /* DMC phy ZQ calibration routine * The first step in DMC initialization */ void adi_dmc_phy_calibration(ADI_DMC_CONFIG *pConfig,uint32_t csel_dsel) { /* Program the ODT and drive strength values */ *pREG_DMC0_DDR_ZQ_CTL0 = pConfig->ulDDR_ZQCTL0; *pREG_DMC0_DDR_ZQ_CTL1 = pConfig->ulDDR_ZQCTL1; *pREG_DMC0_DDR_ZQ_CTL2 = pConfig->ulDDR_ZQCTL2; /* Generate the trigger */ *pREG_DMC0_DDR_CA_CTL = 0x00000000ul ; *pREG_DMC0_DDR_ROOT_CTL = 0x00000000ul; *pREG_DMC0_DDR_ROOT_CTL = 0x00010000ul; dmcdelay(csel_dsel*8000ul); /* The [31:26] bits may change if pad ring changes */ *pREG_DMC0_DDR_CA_CTL = 0x0C000001ul|TrigCalib; dmcdelay(csel_dsel*8000ul); *pREG_DMC0_DDR_CA_CTL = 0x00000000ul ; *pREG_DMC0_DDR_ROOT_CTL = 0x00000000ul ; /* DQS delay trim*/ if (DelayTrim) { *pREG_DMC0_DDR_LANE0_CTL1|= (((Bypasscode)<ulDDR_DLLCTLCFG) & 0xFFFFul; *pREG_DMC0_TR0 = pConfig->ulDDR_TR0; *pREG_DMC0_TR1 = pConfig->ulDDR_TR1; *pREG_DMC0_TR2 = pConfig->ulDDR_TR2; /* program shadow registers */ *pREG_DMC0_MR = ((pConfig->ulDDR_MREMR1) >> 16ul) & 0xFFFFul; *pREG_DMC0_MR1 = (pConfig->ulDDR_MREMR1) & 0xFFFFul; *pREG_DMC0_MR2 = (pConfig->ulDDR_EMR2EMR3)>>16ul & 0xFFFFul; *pREG_DMC0_EMR3 =(pConfig->ulDDR_EMR2EMR3) & 0xFFFFul; /* program Dll timing register */ *pREG_DMC0_DLLCTL = ((pConfig->ulDDR_DLLCTLCFG) >> 16ul) & 0xFFFFul; dmcdelay(csel_dsel*2000ul); *pREG_DMC0_DDR_CA_CTL |=BITM_DMC_DDR_CA_CTL_SW_REFRESH; dmcdelay(csel_dsel_r*5ul); *pREG_DMC0_DDR_ROOT_CTL |= BITM_DMC_DDR_ROOT_CTL_SW_REFRESH | (OfstdCycle << BITP_DMC_DDR_ROOT_CTL_PIPE_OFSTDCYCLE); /* Start DMC initialization */ *pREG_DMC0_CTL = pConfig->ulDDR_CTL; dmcdelay(csel_dsel*12500ul); /* Add necessary delay depending on the configuration */ t_EMR1=(pConfig->ulDDR_MREMR1 & BITM_DMC_MR1_WL)>>BITP_DMC_MR1_WL; if(t_EMR1) { dmcdelay(csel_dsel_r*600ul); while(((*pREG_DMC0_MR1 & BITM_DMC_MR1_WL)>>BITP_DMC_MR1_WL) != 0ul) { } } t_EMR3=(pConfig->ulDDR_EMR2EMR3 & BITM_DMC_EMR3_MPR)>>BITP_DMC_EMR3_MPR; if(t_EMR3) { dmcdelay(csel_dsel*2000ul); while(((*pREG_DMC0_EMR3 & BITM_DMC_EMR3_MPR)>>BITP_DMC_EMR3_MPR) != 0ul) { } } t_CTL=(pConfig->ulDDR_CTL & BITM_DMC_CTL_RL_DQS)>>BITP_DMC_CTL_RL_DQS; if(t_CTL) { dmcdelay(csel_dsel*600ul); while(((*pREG_DMC0_CTL & BITM_DMC_CTL_RL_DQS)>>BITP_DMC_CTL_RL_DQS) != 0ul) { } } /* check if DMC initialization finished, if not return error */ while((*pREG_DMC0_STAT & BITM_DMC_STAT_INITDONE) !=BITM_DMC_STAT_INITDONE); /* End of DMC controller configuration, Start of Phy control registers */ /* toggle DCYCLE */ *pREG_DMC0_DDR_LANE0_CTL1 |= BITM_DMC_DDR_LANE0_CTL1_COMP_DCYCLE; *pREG_DMC0_DDR_LANE1_CTL1 |= BITM_DMC_DDR_LANE1_CTL1_COMP_DCYCLE; dmcdelay(csel_dsel_r*10ul); *pREG_DMC0_DDR_LANE0_CTL1 &= (~BITM_DMC_DDR_LANE0_CTL1_COMP_DCYCLE); *pREG_DMC0_DDR_LANE1_CTL1 &= (~BITM_DMC_DDR_LANE1_CTL1_COMP_DCYCLE); /* toggle RSTDAT */ *pREG_DMC0_DDR_LANE0_CTL0 |= BITM_DMC_DDR_LANE0_CTL0_CB_RSTDAT; *pREG_DMC0_DDR_LANE0_CTL0 &= (~BITM_DMC_DDR_LANE0_CTL0_CB_RSTDAT); *pREG_DMC0_DDR_LANE1_CTL0 |= BITM_DMC_DDR_LANE1_CTL0_CB_RSTDAT; *pREG_DMC0_DDR_LANE1_CTL0 &= (~BITM_DMC_DDR_LANE1_CTL0_CB_RSTDAT); dmcdelay(csel_dsel*2500ul); /* Program phyphase*/ phyphase = (*pREG_DMC0_STAT & BITM_DMC_STAT_PHYRDPHASE)>>BITP_DMC_STAT_PHYRDPHASE; data_cyc= (phyphase << BITP_DMC_DLLCTL_DATACYC) & BITM_DMC_DLLCTL_DATACYC; rd_cnt = ((pConfig->ulDDR_DLLCTLCFG) >> 16); rd_cnt <<= BITP_DMC_DLLCTL_DLLCALRDCNT; rd_cnt &= BITM_DMC_DLLCTL_DLLCALRDCNT; *pREG_DMC0_DLLCTL =rd_cnt|data_cyc; *pREG_DMC0_CTL = (pConfig->ulDDR_CTL & (~BITM_DMC_CTL_INIT) & (~BITM_DMC_CTL_RL_DQS)); return ADI_DMC_SUCCESS; } /* In order to preserve ddr content while changing DMC clock, put memory in self refresh mode * * sequence: program DMC controller to enter self refresh mode. No further access should be issued to ddr memory * call cgu routines to change DMC clock * exit self-refresh mode * */ void adi_dmc_self_refresh(bool enter) { if (enter){ /*Set the SRREQ bit to enter self refresh mode*/ while((*pREG_DMC0_STAT & BITM_DMC_STAT_IDLE)==0ul) { } *pREG_DMC0_CTL|= BITM_DMC_CTL_SRREQ; /*Wait for self refresh acknowledge from the controller*/ while((*pREG_DMC0_STAT & BITM_DMC_STAT_SRACK)==0ul) { } }else{ /*clear the SRREQ bit to exit self refresh mode*/ *pREG_DMC0_CTL &= ~BITM_DMC_CTL_SRREQ; /*Wait for self refresh acknowledge from the controller*/ while((*pREG_DMC0_STAT & BITM_DMC_STAT_SRACK)==1ul) { } /*Wait for the DMC to be in IDLE state*/ while((*pREG_DMC0_STAT & BITM_DMC_STAT_IDLE)==0ul) { } *pREG_DMC0_CTL |=BITM_DMC_CTL_DLLCAL; /*Wait for DLL calib*/ while((*pREG_DMC0_STAT & BITM_DMC_STAT_DLLCALDONE)==0ul) { } } } /** * @brief Initializes DMC controller. * * @return Status * - 0: Successful in initializing DMC controller. * - 1: Error. */ int dmc_cfg0_init(void) { static ADI_DMC_CONFIG CONFIG533 = { CFG0_REG_DDR_DLLCTLCFG, CFG0_REG_DMC_MR2MR3, CFG0_REG_DMC_CTL_VALUE, CFG0_REG_DMC_MRMR1, CFG0_REG_DMC_TR0_VALUE, CFG0_REG_DMC_TR1_VALUE, CFG0_REG_DMC_TR2_VALUE, 0x00782828ul, 0ul, 0x70000000ul }; /* Initialize DMC PHY registers*/ adi_dmc_phy_calibration((&CONFIG533),csel_dsel_r); /* Initialize DMC Controller*/ if(adi_dmc_ctrl_init((&CONFIG533),csel_dsel_r) != ADI_DMC_SUCCESS) { /* Return non-zero */ return 1u; } return 0u; }