#include #include #include "../include/common_lib.h" #include "../include/ddr_common_func.h" DDR_SYSREG_REG_SW_REG_S ddr_sysreg; #ifndef CONFIG_DDR_RANK_SIZE #define CONFIG_DDR_RANK_SIZE SZ_4G #endif unsigned long get_ddr_density() { int div =1, mul=1; #ifdef CONFIG_DDR_DUAL_RANK mul = 2; #endif #ifdef CONFIG_DDR_ROW16 mul *= 2; #endif #ifdef CONFIG_DDR_H32_MODE div = 2; #endif return CONFIG_DDR_RANK_SIZE*mul/div; } enum DDR_TYPE get_ddr_type() { #ifdef CONFIG_LPDDR4X return DDR_TYPE_LPDDR4X; #elif defined CONFIG_LPDDR4 return DDR_TYPE_LPDDR4; #else printf("unsupport lpddr4 type!!!\n"); return NULL; #endif // #ifdef CONFIG_LPDDR4X } void ddr_sysreg_wr(unsigned long int addr,unsigned int wr_data) { wr(addr+DDR_SYSREG_BADDR,wr_data); } unsigned int ddr_sysreg_rd(unsigned long int addr) { int rdata; rdata = rd(addr+DDR_SYSREG_BADDR); return rdata; } void ddr_phy_reg_wr(unsigned long int addr,unsigned int wr_data) { //unsigned long int ddr_phy_sel,addr_low; addr<<=1; //ddr_phy_sel=(addr)&0x00ffffff; //ddr_phy_sel>>=21; //addr_low=(addr)&0x001fffff; //wr(_SYS_REG_DDR_PHY_PS_SEL,ddr_phy_sel); //ddr_sysreg_rd(DDR_CFG0); wr16(_DDR_PHY_BADDR+addr, wr_data); #ifndef CONFIG_DDR_H32_MODE wr16(_DDR_PHY1_BADDR+addr, wr_data); #endif } void ddr_phy0_reg_wr(unsigned long int addr,unsigned int wr_data) { addr<<=1; wr16(_DDR_PHY_BADDR+addr, wr_data); } void ddr_phy1_reg_wr(unsigned long int addr,unsigned int wr_data) { addr<<=1; wr16(_DDR_PHY1_BADDR+addr, wr_data); } void ddr_phy_broadcast_en(int enable) { //ddr_sysreg.ddr_sysreg_registers_struct_ddr_cfg0.u32 = ddr_sysreg_rd(DDR_CFG0); //ddr_sysreg.ddr_sysreg_registers_struct_ddr_cfg0.rg_broadcast_mode = enable; //ddr_sysreg_wr(DDR_CFG0,ddr_sysreg.ddr_sysreg_registers_struct_ddr_cfg0.u32); ddr_sysreg_rd(DDR_CFG0); ddr_sysreg_rd(DDR_CFG0); } unsigned int ddr_phy1_reg_rd(unsigned long int addr) { //unsigned long int ddr_phy_sel,addr_low,rd_data; unsigned int rd_data; addr<<=1; rd_data=rd16(_DDR_PHY1_BADDR+addr); return rd_data; } unsigned int ddr_phy0_reg_rd(unsigned long int addr) { //unsigned long int ddr_phy_sel,addr_low,rd_data; unsigned int rd_data; addr<<=1; rd_data=rd16(_DDR_PHY_BADDR+addr); return rd_data; } unsigned int ddr_phy_reg_rd(unsigned long int addr) { //unsigned long int ddr_phy_sel,addr_low,rd_data; unsigned int rd_data; addr<<=1; rd_data=rd16(_DDR_PHY_BADDR+addr); return rd_data; } void lp4_mrw(int addr, int wdata,int dch,int rank) { DWC_DDR_UMCTL2_C_STRUCT_REG_S umctl2_reg; if(dch==0) { umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.u32 = rd(MRCTRL0); //umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.mr_addr = addr; //do not care for lp4 umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.mr_rank = rank;//rank0 only umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.mr_type = 0;//write wr(MRCTRL0,umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.u32); umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl1.u32 = rd(MRCTRL1); umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl1.mr_data = (addr<<8) | (wdata&0xFF); wr(MRCTRL1,umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl1.u32); umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.u32 = rd(MRCTRL0); umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.mr_wr = 1;//trigger wr/rd wr(MRCTRL0,umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.u32); } else { umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.u32 = rd(MRCTRL0_DCH1); //umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.mr_addr = addr; //do not care for lp4 umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.mr_rank = rank;//rank0 only umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.mr_type = 0;//write wr(MRCTRL0_DCH1,umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.u32); umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl1.u32 = rd(MRCTRL1_DCH1); umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl1.mr_data = (addr<<8) | (wdata&0xFF); wr(MRCTRL1_DCH1,umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl1.u32); umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.u32 = rd(MRCTRL0_DCH1); umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.mr_wr = 1;//trigger wr/rd wr(MRCTRL0_DCH1,umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.u32); } } int lp4_mrr(int addr,int dch,int rank) { DWC_DDR_UMCTL2_C_STRUCT_REG_S umctl2_reg; if(dch==0) { umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.u32 = rd(MRCTRL0); //umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.mr_addr = addr; //do not care for lp4 umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.mr_rank = rank;//rank0 only umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.mr_type = 1;//read wr(MRCTRL0,umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.u32); umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl1.u32 = rd(MRCTRL1); umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl1.mr_data = addr<<8; wr(MRCTRL1,umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl1.u32); umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.u32 = rd(MRCTRL0); umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.mr_wr = 1;//trigger wr/rd wr(MRCTRL0,umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.u32); umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl1.u32 = rd(MRCTRL1); return (umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl1.mr_data & 0xFF); } else { umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.u32 = rd(MRCTRL0_DCH1); //umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.mr_addr = addr; //do not care for lp4 umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.mr_rank = rank;//rank0 only umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.mr_type = 1;//read wr(MRCTRL0_DCH1,umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.u32); umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl1.u32 = rd(MRCTRL1_DCH1); umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl1.mr_data = addr<<8; wr(MRCTRL1_DCH1,umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl1.u32); umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.u32 = rd(MRCTRL0_DCH1); umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.mr_wr = 1;//trigger wr/rd wr(MRCTRL0_DCH1,umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl0.u32); umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl1.u32 = rd(MRCTRL1_DCH1); return (umctl2_reg.dwc_ddr_umctl2_c_struct_mrctrl1.mr_data & 0xFF); } } int lp4_set_ron(int ron) { enum DDR_TYPE type; int cfg; type = get_ddr_type(); if (type == DDR_TYPE_LPDDR4X) { switch ((int)ron) { case 40: cfg = 0xe00; break; case 60: cfg = 0x604; break; case 120: cfg = 0x206; break; default: printf("unsupported ron config<%d>\n", (int)ron); return -1; } } else if (type == DDR_TYPE_LPDDR4) { switch ((int)ron) { case 40: cfg = 0xe3f; break; case 60: cfg = 0x61f; break; case 120: cfg = 0x20f; break; default: printf("unsupported ron config<%d>\n", (int)ron); return -1; } } else { printf("unsupported ddr type<%d>\n", (int)type); return -1; } ddr_phy_reg_wr(0xd0000,0x0); ddr_phy_reg_wr(0x10049,cfg); ddr_phy_reg_wr(0x10149,cfg); ddr_phy_reg_wr(0x11049,cfg); ddr_phy_reg_wr(0x11149,cfg); ddr_phy_reg_wr(0x12049,cfg); ddr_phy_reg_wr(0x12149,cfg); ddr_phy_reg_wr(0x13049,cfg); ddr_phy_reg_wr(0x13149,cfg); ddr_phy_reg_wr(0xd0000,0x1); return 0; } void disable_axi_port(int port) { if(port & 0x1) wr(PCTRL_0,0); if(port & 0x2) wr(PCTRL_1,0); if(port & 0x4) wr(PCTRL_2,0); if(port & 0x8) wr(PCTRL_3,0); if(port & 0x10) wr(PCTRL_4,0); if(port & 0x1F) { //at least one port is not disabled wr(DBG1,0); wr(DBG1_DCH1,0); } else { //all ports are disabled wr(DBG1,3); wr(DBG1_DCH1,3); } } void enable_axi_port(int port) { //wr(0xffff004008,0xff400000);//Full bypass scramble //wr(0xffff004008,0xff400000);//Full bypass scramble //axi rst->release ddr_sysreg_wr(DDR_CFG0,0x00f0); ddr_sysreg_wr(DDR_CFG0,0x1ff0); wr(DBG1,0); wr(DBG1_DCH1,0); if(port & 0x1) wr(PCTRL_0,1); if(port & 0x2) wr(PCTRL_1,1); if(port & 0x4) wr(PCTRL_2,1); if(port & 0x8) wr(PCTRL_3,1); if(port & 0x10) wr(PCTRL_4,1); } void enable_auto_refresh() { wr(RFSHCTL3,0);//enable auto_refresh } void pll_config (int speed) { if(speed==4266) { //4266 ddr_sysreg_wr(DDR_CFG0+0xc,0x4b000000); ddr_sysreg_wr(DDR_CFG0+0x8,0x01205801); udelay(2); ddr_sysreg_wr(DDR_CFG0+0xc,0x0b000000); } else if(speed==3733) { //3733 ddr_sysreg_wr(DDR_CFG0+0xc,0x4b000000); ddr_sysreg_wr(DDR_CFG0+0x8,0x01204d01); udelay(2); ddr_sysreg_wr(DDR_CFG0+0xc,0x0b000000); } else if(speed==3200) { //3200 } else if(speed==2133) { //2133 ddr_sysreg_wr(DDR_CFG0+0xc,0x4b000000); ddr_sysreg_wr(DDR_CFG0+0x8,0x01608501); udelay(2); ddr_sysreg_wr(DDR_CFG0+0xc,0x0b000000); } else { #ifdef CONFIG_DDR_MSG printf("Reserved Pll setting\n"); #endif ddr_sysreg_wr(DDR_CFG0+0xc,0x4b000000); ddr_sysreg_wr(DDR_CFG0+0x8,0x01606601); ddr_sysreg_wr(DDR_CFG0+0xc,0x0b000000); } #ifdef CONFIG_DDR_MSG printf("Freq is %0x \n",ddr_sysreg_rd(DDR_CFG0+0x8)); #endif while((ddr_sysreg_rd(DDR_CFG0+0x18)&1)!=0x1); //pll lock ddr_sysreg_wr(DDR_CFG0+0x18,0x10000);// core clock cg off } void ctrl_en(enum DDR_BITWIDTH bits) { // wr(SWCTL,0x00000000); wr(DFIMISC,0x00000030);// [5]dfi_init_start // wr(SWCTL,0x00000001); // while(rd(SWSTAT)!=0x00000001); while(rd(DFISTAT)!=0x00000001); //polling dfi_init_complete if(bits==64) { while(rd(DCH1_DFISTAT)!=0x00000001); } // wr(SWCTL,0x00000000); wr(DFIMISC,0x00000010); wr(DFIMISC,0x00000011); wr(PWRCTL,0x0000000a); //[3] dfi_dram_clk_disable [1] powerdown_en wr(DCH1_PWRCTL,0x0000000a); wr(SWCTL,0x00000001); while(rd(SWSTAT)!=0x00000001); while(rd(STAT)!=0x00000001); if(bits==64) { while(rd(DCH1_STAT)!=0x00000001); } wr(DFIPHYMSTR,0x14000001); wr(SWCTL,0x00000000); wr(INIT0,0x00020002); wr(SWCTL,0x00000001); while(rd(SWSTAT)!=0x00000001); //wr(PWRCTL,0x0000000b); //wr(DCH1_PWRCTL,0x0000000b); #ifdef CONFIG_DDR_MSG printf("DFIPHYMSTR is %0x \n",rd(DFIPHYMSTR)); printf("DFIUPD0 is %0x \n",rd(DFIUPD0)); printf("DFIUPD1 is %0x \n",rd(DFIUPD1)); printf("ZQCTL0 is %0x \n",rd(ZQCTL0)); printf("ADDRMAP0 is %0x \n",rd(ADDRMAP0)); printf("ADDRMAP1 is %0x \n",rd(ADDRMAP1)); #endif } void deassert_pwrok_apb (enum DDR_BITWIDTH bits) { ddr_sysreg_wr(DDR_CFG0,0x40); // release PwrOkIn ddr_sysreg_wr(DDR_CFG0,0x40); ddr_sysreg_wr(DDR_CFG0,0x40); ddr_sysreg_wr(DDR_CFG0,0x40); ddr_sysreg_wr(DDR_CFG0,0x40); ddr_sysreg_wr(DDR_CFG0,0x40); ddr_sysreg_wr(DDR_CFG0,0xc0); // release Phyrst ddr_sysreg_wr(DDR_CFG0,0xc0); // release Phyrst ddr_sysreg_wr(DDR_CFG0,0xc0); // release Phyrst ddr_sysreg_wr(DDR_CFG0,0xc0); // release Phyrst ddr_sysreg_wr(DDR_CFG0,0xd0); // release apb presetn ddr_sysreg_wr(DDR_CFG0,0xd0); ddr_sysreg_wr(DDR_CFG0,0xd0); ddr_sysreg_wr(DDR_CFG0,0xd0); ddr_sysreg_wr(DDR_CFG0,0xd0); ddr_sysreg_wr(DDR_CFG0,0xd0); if(bits==32) { ddr_sysreg_wr(DDR_CFG0,0xd2); } } //void ctrl_init(int speed,int rank_num) { void ctrl_init(int rank_num, int speed) { wr(DBG1,0x00000001); wr(PWRCTL,0x00000001); while(rd(STAT)!=0x00000000); if(rank_num==2) { #ifdef CONFIG_DDR_MSG printf("Ctrl in dual rank mode \n"); #endif wr(MSTR,0x03080020); } else { wr(MSTR,0x01080020); } wr(MRCTRL0,0x00003030); wr(MRCTRL1,0x0002d90f); if(speed==4266) { #ifdef CONFIG_DDR_MSG printf("Enter LP4 4266 init\n"); #endif wr(DERATEEN,0x000014f5); //[0] dereate enable [7:4] derate byte input wr(DERATEINT,0x40000000); wr(DERATECTL,0x00000001); wr(PWRCTL,0x00000020); wr(PWRTMG,0x0040ae04); wr(HWLPCTL,0x00430002); #ifdef ALL_BANK_REF wr(RFSHCTL0,0x00210000); wr(RFSHCTL1,0x000f0026); wr(RFSHCTL3,0x00000001); wr(RFSHTMG,0x00828196);//[9:0] trfcb 380/0.937=406;//0x196 --> if 512MB on channel -> trfcb 280ns wr(RFSHTMG1,0x00610000); #else wr(RFSHCTL0,0x00210004); wr(RFSHCTL1,0x000f0026); wr(RFSHCTL3,0x00000001); wr(RFSHTMG,0x82000098); //[31] t_rfc_nom_x1_sel ,1 //[27:16] -tREFI 488ns/0.94=520=0x208 //[9:0] -t_rfc_min 140ns/0.94=149=0x95 //wr(RFSHTMG,0x81c00088); //for 3733 test wr(RFSHTMG1,0x00610000); #endif wr(CRCPARCTL0,0x00000000); wr(INIT0,0xc0020002); wr(INIT1,0x00010002); wr(INIT2,0x00002300); wr(INIT3,0x0074003f);//OP[2:0] RL wr(INIT4,0x00330008); wr(INIT5,0x0005000c); wr(INIT6,0x0000004d); wr(INIT7,0x0000004d); wr(DIMMCTL,0x00000000); wr(RANKCTL,0x0000ab9f);//RANKCTL wr(RANKCTL1,0x0000001a); wr(DRAMTMG0,0x2221482d); wr(DRAMTMG1,0x00090941); #ifdef CONFIG_DDR_DBI_OFF wr(DRAMTMG2,0x09121219);//[29:24] -write latency [21:16] read latency [13:8] rd2wr [5:0] wr2rd #ifdef CONFIG_DDR_MSG printf("Enter LP4 DBI OFF mode\n"); #endif #else //wr(DRAMTMG2,0x09141619);//[29:24] -write latency [21:16] read latency [13:8] rd2wr [5:0] wr2rd wr(DRAMTMG2,0x09141f1a);//[29:24] -write latency [21:16] read latency [13:8] rd2wr [5:0] wr2rd #endif wr(DRAMTMG3,0x00f0f000); wr(DRAMTMG4,0x14040914);//[19:16] tCCD //wr(DRAMTMG4,0x14050914);//[19:16] tCCD wr(DRAMTMG5,0x02061111); wr(DRAMTMG6,0x0101000a); wr(DRAMTMG7,0x00000602); wr(DRAMTMG8,0x00000101); wr(DRAMTMG12,0x00020000); wr(DRAMTMG13,0x0e100002); wr(DRAMTMG14,0x00000133); //if(rank_num==2) { //wr(ZQCTL0,0x242d0021); //printf("zq_share_mode! \n"); //} else { wr(ZQCTL0,0x042d0026); //} //wr(ZQCTL1,0x0360ccda);// ccda-> zq cal interval wr(ZQCTL1,0x03600800);// wr(ZQCTL2,0x00000000); #ifdef CONFIG_DDR_DBI_OFF wr(DFITMG0,0x059f820e);//[22:16] dfi_t_rddate_en=RL-5 #else wr(DFITMG0,0x05a3820e);//[28:24] dft_t_ctrl_delay [22:16] dfi_t_rddate_en=RL-5 #endif wr(DFITMG1,0x000c0303); wr(DFILPCFG0,0x0351a001); //wr(DFIUPD0,0x00400018); //[31:30]=0 use ctrlupd enable //wr(DFIUPD1,0x00b700c4); //wr(DFIUPD2,0x00000000);//[31]=0 disable phy ctrlupdate wr(DFIMISC,0x00000011); #ifdef CONFIG_DDR_DBI_OFF wr(DFITMG2,0x00001f0e);//[14:9] dfi_tphy_rdcslat wr(DBICTL,0x00000001); //dbi-off #else wr(DFITMG2,0x0000230e);//[14:9] dfi_tphy_rdcslat wr(DBICTL,0x00000007); //dbi-on #endif wr(DFIPHYMSTR,0x14000001); wr(ADDRMAP0,0x0004001f); // +2 wr(ADDRMAP1,0x00090909); //bank +2 wr(ADDRMAP2,0x00000000); //col b5+5 ~ col b2 +2 wr(ADDRMAP3,0x01010101); //col b9 ~ col b6 wr(ADDRMAP4,0x00001f1f); //col b11~ col b10 wr(ADDRMAP5,0x080f0808); //row_b11 row b2_10 row b1 row b0 +6 wr(ADDRMAP6,0x08080808); wr(ADDRMAP7,0x00000f0f); wr(ADDRMAP9,0x08080808); wr(ADDRMAP10,0x08080808); wr(ADDRMAP11,0x00000008); wr(ODTCFG,0x060a0c44); } else if(speed==3733) { #ifdef CONFIG_DDR_MSG printf("Enter LP4 3733 init\n"); #endif //wr(DERATEEN,0x00001302);// 3733 disable derate wr(DERATEEN,0x000013f3);// derate enable wr(DERATEINT,0x40000000); wr(DERATECTL,0x00000001); wr(PWRCTL,0x00000020); wr(PWRTMG,0x0040ae04); wr(HWLPCTL,0x00430000); #ifdef ALL_BANK_REF wr(RFSHCTL0,0x00210000); wr(RFSHCTL1,0x000d0021); wr(RFSHCTL3,0x00000001); wr(RFSHTMG,0x006f8164);//tREFI=0x6F*32*1.083=3.846us trfcpb 280ns :0x106 trfcpb 380ns/1.083ns= 0x164 wr(RFSHTMG1,0x00540000); #else wr(RFSHCTL0,0x00210004); wr(RFSHCTL1,0x000d0021); wr(RFSHCTL3,0x00000001); wr(RFSHTMG,0x81c00084); //[31] t_rfc_nom_x1_sel ,1 //[27:16] -tREFI 488ns/1.083=450=0x1c2 //[9:0] -t_rfc_min 140ns/1.083=130=0x82 wr(RFSHTMG1,0x00540000); #endif wr(CRCPARCTL0,0x00000000); wr(INIT0,0xc0020002); wr(INIT1,0x00010002); wr(INIT2,0x00001f00); wr(INIT3,0x00640036); wr(INIT4,0x00f20008); wr(INIT5,0x0004000b); wr(INIT6,0x00440012); wr(INIT7,0x0004001a); wr(DIMMCTL,0x00000000); wr(RANKCTL,0x0000ab9f); wr(RANKCTL1,0x00000017); wr(DRAMTMG0,0x1f263f28);//[30:24]-wr2pre 0x1e->0x1f wr(DRAMTMG1,0x00080839);//[20:16]-txp [13:8]-rd2pre 0x7->0x8 [6:0] 0x38->0x39 #ifdef CONFIG_DDR_DBI_OFF wr(DRAMTMG2,0x08101116); #else //wr(DRAMTMG2,0x08121516);//[29:24] -write latency [21:16] read latency [13:8] rd2wr [5:0] wr2rd // if(rank_num==2) { // wr(DRAMTMG2,0x08121b1a);//[29:24] -write latency [21:16] read latency [13:8] rd2wr [5:0] wr2rd //} else { wr(DRAMTMG2,0x08121d17);//[29:24] -write latency [21:16] read latency [13:8] rd2wr [5:0] wr2rd //} #endif wr(DRAMTMG3,0x00d0e000); wr(DRAMTMG4,0x11040a12);//[4:0] t_rp wr(DRAMTMG5,0x02050e0e); wr(DRAMTMG6,0x01010008); wr(DRAMTMG7,0x00000502); wr(DRAMTMG8,0x00000101); wr(DRAMTMG12,0x00020000); wr(DRAMTMG13,0x0d100002); wr(DRAMTMG14,0x0000010c); // if(rank_num==2) { // wr(ZQCTL0,0x23a5001c); //[29] - zq share // printf("zq_share_mode! \n"); //} else { wr(ZQCTL0,0x03a50021); //} //wr(ZQCTL1,0x02f0ccda);//ccda->zq cal interval wr(ZQCTL1,0x02f00800); wr(ZQCTL2,0x00000000); #ifdef CONFIG_DDR_DBI_OFF wr(DFITMG0,0x059b820c);//[28:24] dfi_t_ctrl_delay [22:16] dfi_t_rdata_en=RL-5 #else wr(DFITMG0,0x059f820c);//[28:24] dfi_t_ctrl_delay #endif wr(DFITMG1,0x000c0303);//dfi_t_wrdata_delay=tctrl+6+BL/2+trainedTdqsdly=24, may need take care cmd pipe wr(DFILPCFG0,0x0351a001); //wr(DFIUPD0,0xc0400018); //wr(DFIUPD1,0x00b700c4); //wr(DFIUPD2,0x80000000); wr(DFIMISC,0x00000011); #ifdef CONFIG_DDR_DBI_OFF wr(DFITMG2,0x00001b0c);//[14:9] dfi_tphy_rdcslat wr(DBICTL,0x00000001);//[2:0] dbi-off #else wr(DFITMG2,0x00001f0c);// wr(DBICTL,0x00000007);//[2:0] dbi-on #endif wr(DFIPHYMSTR,0x14000001); wr(ADDRMAP0,0x0002001f); wr(ADDRMAP1,0x00090909); wr(ADDRMAP2,0x01010000); wr(ADDRMAP3,0x01010101); wr(ADDRMAP4,0x00001f1f); wr(ADDRMAP5,0x080f0808); wr(ADDRMAP6,0x08080808); wr(ADDRMAP7,0x00000f0f); wr(ADDRMAP9,0x08080808); wr(ADDRMAP10,0x08080808); wr(ADDRMAP11,0x00000008); wr(ODTCFG,0x06090b40); } else if(speed==3200) { #ifdef CONFIG_DDR_MSG printf("Enter LP4 3200 init\n"); #endif wr(DERATEEN,0x000012f3); wr(DERATEINT,0x726d4ada); wr(DERATECTL,0x00000001); wr(PWRCTL,0x00000020); wr(PWRTMG,0x0040ae04); wr(HWLPCTL,0x00430002); #ifdef ALL_BANK_REF wr(RFSHCTL0,0x00210000);//[2] per-bank ref enable wr(RFSHCTL1,0x000b001c); wr(RFSHCTL3,0x00000001); wr(RFSHTMG,0x00618130);//[9:0] trfcab 380ns/1.25=304=0x130 [27:16]=3904/32/1.25=97 = 0x61 wr(RFSHTMG1,0x00480000); #else wr(RFSHCTL0,0x00210004);//[2] per-bank ref enable wr(RFSHCTL1,0x000b001c); wr(RFSHCTL3,0x00000001); wr(RFSHTMG,0x81860070);//tREFI=3.9us lower(tREFI/(1/790MHz)/32)=96 //[9:0] t_rfc_min must be set to RoundUp(RoundUp(tRFCmin/tCK)/2) trfcpb or trfcab //[27:16]-tREFI, per-ref 488ns/1.25=390=0x186 wr(RFSHTMG1,0x00480000); #endif wr(CRCPARCTL0,0x00000000); wr(INIT0,0xc0020002); wr(INIT1,0x00010002); wr(INIT2,0x00001a00); wr(INIT3,0x0054002e); //OP[2:0] RL wr(INIT4,0x0c310008);//[31:16] LP4 MR3 wr(INIT5,0x00040009); wr(INIT6,0x00000012); wr(INIT7,0x0000001a); wr(DIMMCTL,0x00000000); wr(RANKCTL,0x0000ab9f); wr(RANKCTL1,0x00000017); wr(DRAMTMG0,0x1b203622); wr(DRAMTMG1,0x00060630); #ifdef CONFIG_DDR_DBI_OFF wr(DRAMTMG2,0x070e0f14);//[29:24] -write latency [21:16] read latency [13:8] rd2wr [5:0] wr2rd #else wr(DRAMTMG2,0x07101b15);//[29:24] -write latency [21:16] read latency [13:8] rd2wr [5:0] wr2rd #endif wr(DRAMTMG3,0x00b0c000); wr(DRAMTMG4,0x0f04080f); wr(DRAMTMG5,0x02040c0c); wr(DRAMTMG6,0x01010007); wr(DRAMTMG7,0x00000402); wr(DRAMTMG8,0x00000101); wr(DRAMTMG12,0x00020000); wr(DRAMTMG13,0x0c100002); wr(DRAMTMG14,0x000000e6); wr(ZQCTL0,0x03200018); wr(ZQCTL1,0x0280ccda); wr(ZQCTL2,0x00000000); #ifdef CONFIG_DDR_DBI_OFF wr(DFITMG0,0x0597820a); #else wr(DFITMG0,0x059b820a); //[22:16] dfi_t_rddate_en=RL-5 #endif wr(DFITMG1,0x000b0303); wr(DFILPCFG0,0x0351a001); //wr(DFIUPD0,0xc0400018); //wr(DFIUPD1,0x00b700c4); //wr(DFIUPD2,0x80000000); wr(DFIMISC,0x00000011); #ifdef CONFIG_DDR_DBI_OFF wr(DFITMG2,0x0000170a); //[14:8] dfi_tphy_rdcslat wr(DBICTL,0x00000001); //dbi-off #else wr(DFITMG2,0x00001b0a); //[14:8] dfi_tphy_rdcslat wr(DBICTL,0x00000007); //dbi-on #endif wr(DFIPHYMSTR,0x14000001); wr(ADDRMAP0,0x0004001f); // +2 wr(ADDRMAP1,0x00090909); //bank +2 wr(ADDRMAP2,0x00000000); //col b5+5 ~ col b2 +2 wr(ADDRMAP3,0x01010101); //col b9 ~ col b6 wr(ADDRMAP4,0x00001f1f); //col b11~ col b10 wr(ADDRMAP5,0x080f0808); //row_b11 row b2_10 row b1 row b0 +6 wr(ADDRMAP6,0x08080808); wr(ADDRMAP7,0x00000f0f); wr(ADDRMAP9,0x08080808); wr(ADDRMAP10,0x08080808); wr(ADDRMAP11,0x00000008); wr(ODTCFG,0x06080a38); } else if(speed==2133){ #ifdef CONFIG_DDR_MSG printf("Enter LP4 2133 init\n"); #endif wr(DERATEEN,0x000011f1); wr(DERATEINT,0x726d4ada); wr(DERATECTL,0x00000001); wr(PWRCTL,0x00000020); wr(PWRTMG,0x0040ae04); wr(HWLPCTL,0x00430002); #ifdef ALL_BANK_REF wr(RFSHCTL0,0x00210000); wr(RFSHCTL1,0x00070013); wr(RFSHCTL3,0x00000001); wr(RFSHTMG,0x004180cc);// 380ns =0xcc wr(RFSHTMG1,0x00300000); #else wr(RFSHCTL0,0x00210004); wr(RFSHCTL1,0x00070013); wr(RFSHCTL3,0x00000001); wr(RFSHTMG,0x81050048);// //[9:0] t_rfc_min must be set to RoundUp(RoundUp(tRFCmin/tCK)/2) trfcpb or trfcab //[27:16]-tREFI, per-ref 488ns/1.87=261=0x105 //[9:0] -t_rfc_min 140ns/1.87=75=0x48 wr(RFSHTMG1,0x00300000); #endif wr(CRCPARCTL0,0x00000000); wr(INIT0,0xc0020002); wr(INIT1,0x00010002); wr(INIT2,0x00001200); wr(INIT3,0x0034001b); wr(INIT4,0x00310008); wr(INIT5,0x00030007); wr(INIT6,0x0000004d); wr(INIT7,0x0000004d); wr(DIMMCTL,0x00000000); wr(RANKCTL,0x0000ab9f); wr(RANKCTL1,0x00000012); wr(DRAMTMG0,0x14162417); wr(DRAMTMG1,0x00040420); //wr(DRAMTMG2,0x050a0c0f);//[29:24] -write latency [21:16] read latency [13:8] rd2wr [5:0] wr2rd wr(DRAMTMG2,0x050a1212);//[29:24] -write latency [21:16] read latency [13:8] rd2wr [5:0] wr2rd wr(DRAMTMG3,0x00708000); wr(DRAMTMG4,0x0a04060a); wr(DRAMTMG5,0x02030808); wr(DRAMTMG6,0x01010005); wr(DRAMTMG7,0x00000302); wr(DRAMTMG8,0x00000101); wr(DRAMTMG12,0x00020000); wr(DRAMTMG13,0x0a100002); wr(DRAMTMG14,0x00000099); // if(rank_num==2) { // wr(ZQCTL0,0x22160010); // } else { wr(ZQCTL0,0x02160010); // } wr(ZQCTL1,0x01b0ccda); wr(ZQCTL2,0x00000000); wr(DFITMG0,0x048f8206); wr(DFITMG1,0x000b0303); wr(DFILPCFG0,0x0351a001); //wr(DFIUPD0,0xc0400018); //wr(DFIUPD1,0x00b700c4); //wr(DFIUPD2,0x80000000); wr(DFIMISC,0x00000011); wr(DFITMG2,0x00000f06); wr(DBICTL,0x00000001); wr(DFIPHYMSTR,0x14000001); wr(ADDRMAP0,0x0004001f); // +2 wr(ADDRMAP1,0x00090909); //bank +2 wr(ADDRMAP2,0x00000000); //col b5+5 ~ col b2 +2 wr(ADDRMAP3,0x01010101); //col b9 ~ col b6 wr(ADDRMAP4,0x00001f1f); //col b11~ col b10 wr(ADDRMAP5,0x080f0808); //row_b11 row b2_10 row b1 row b0 +6 wr(ADDRMAP6,0x08080808); wr(ADDRMAP7,0x00000f0f); wr(ADDRMAP9,0x08080808); wr(ADDRMAP10,0x08080808); wr(ADDRMAP11,0x00000008); wr(ODTCFG,0x06060828); } else { printf("Wrong Speed setting!!!\n"); } wr(DFIUPD0,0x00400018); //[31:30]=0 use ctrlupd enable //wr(DFIUPD1,0x005b0062); // less ctrl interval wr(DFIUPD1,0x00280032); // less ctrl interval wr(DFIUPD2,0x00000000);//[31]=0 disable phy ctrlupdate //wr(DFIUPD0,0xc0400018); //wr(DFIUPD1,0x00b700c4); //wr(DFIUPD2,0x80000000); wr(ODTMAP,0x00000000); wr(SCHED,0x1f829b1c); //[2] page-close enable [14:8] 0x1b: lpr entry num=28, hpr entry num=4 wr(SCHED1,0x4400b00f); //[7:0] page-close timer wr(PERFHPR1,0x0f000001); wr(PERFLPR1,0x0f00007f); wr(PERFWR1,0x0f00007f); wr(SCHED3,0x00000208); wr(SCHED4,0x08400810); wr(DBG0,0x00000000); wr(DBG1,0x00000000); wr(DBGCMD,0x00000000); wr(SWCTL,0x00000001); wr(SWCTLSTATIC,0x00000000); wr(POISONCFG,0x00000001); wr(PCTRL_0,0x00000001); wr(PCTRL_1,0x00000001); wr(PCTRL_2,0x00000001); wr(PCTRL_3,0x00000001); wr(PCTRL_4,0x00000001); wr(DCH1_MRCTRL0,0x00003030); wr(DCH1_MRCTRL1,0x0002d90f); wr(DCH1_DERATECTL,0x00000001); wr(DCH1_PWRCTL,0x00000020); wr(DCH1_HWLPCTL,0x00430002); wr(DCH1_CRCPARCTL0,0x00000000); wr(DCH1_ZQCTL2,0x00000000); wr(DCH1_ODTMAP,0x00000000); wr(DCH1_DBG1,0x00000000); wr(DCH1_DBGCMD,0x00000000); while(rd(RFSHCTL3)!=0x00000001); //update by perf sim wr(PCCFG,0x00000010); //[4] page match limit,limits the number of consecutive same page DDRC transactions that can be granted by the Port Arbiter to four wr(PCFGR_0,0x0000500f); //CPU read wr(PCFGW_0,0x0000500f); //CPU write wr(PCFGR_1,0x00005020); //VI Read max 32 wr(PCFGW_1,0x0000501f); //VI Write, sensor/isp/dw/dsp wr(PCFGR_2,0x0000501f); //VO Read, DPU/GPU wr(PCFGW_2,0x0000503f); //VO Write, GPU wr(PCFGR_3,0x000051ff); wr(PCFGW_3,0x000051ff); wr(PCFGR_4,0x0000503f); wr(PCFGW_4,0x0000503f); while(rd(PWRCTL)!=0x00000020); wr(PWRCTL,0x00000020); while(rd(DCH1_PWRCTL)!=0x00000020); wr(DCH1_PWRCTL,0x00000020); wr(DBG1,0x00000000); while(rd(PWRCTL)!=0x00000020); wr(PWRCTL,0x00000020); while(rd(PWRCTL)!=0x00000020); wr(PWRCTL,0x00000020); wr(DCH1_DBG1,0x00000000); while(rd(DCH1_PWRCTL)!=0x00000020); wr(DCH1_PWRCTL,0x00000020); while(rd(DCH1_PWRCTL)!=0x00000020); wr(DCH1_PWRCTL,0x00000020); //while(rd(DFIPHYMSTR)!=0x14000000); wr(DFIPHYMSTR,0x14000001); wr(SWCTL,0x00000000); wr(DFIMISC,0x00000010); wr(DFIMISC,0x00000010); // wr(SWCTL,0x00000001); // while(rd(SWSTAT)!=0x00000001); wr(DBG1,0x00000002); wr(DCH1_DBG1,0x00000002); //while(rd(MSTR)!=0x01080020); #ifdef CONFIG_DDR_MSG printf("RankCTL is %0x \n",rd(RANKCTL)); printf("DRAMTMG2 is %0x \n",rd(DRAMTMG2)); printf("DFITMG0 is %0x \n",rd(DFITMG0)); printf("DFITMG1 is %0x \n",rd(DFITMG1)); printf("DRAMTMG4 is %0x \n",rd(DRAMTMG4));//[19:16] tCCD #endif } void addrmap (int rank_num, enum DDR_BITWIDTH bits) { if(bits==DDR_BITWIDTH_16) { #ifdef CONFIG_DDR_MSG printf("DDR 16bit mode\n"); #endif wr(MSTR,0x01080020|0x1000); wr(ADDRMAP0,0x001f1f16); // wr(ADDRMAP1,0x00070707); //bank +2 wr(ADDRMAP2,0x00000000); //col b5+5 ~ col b2 +2 wr(ADDRMAP3,0x1f000000); //col b9 ~ col b6 wr(ADDRMAP4,0x00001f1f); //col b11~ col b10 wr(ADDRMAP5,0x060f0606); //row_b11 row b2_10 row b1 row b0 +6 wr(ADDRMAP6,0x06060606); //max row 15 wr(ADDRMAP7,0x00000f0f); wr(ADDRMAP9,0x06060606); wr(ADDRMAP10,0x06060606); wr(ADDRMAP11,0x00000006); } else if(bits==DDR_BITWIDTH_32){ #ifdef CONFIG_DDR_MSG printf("DDR 32bit mode\n"); #endif wr(ADDRMAP0,0x001f001f); // if(rank_num==2) { wr(ADDRMAP0,0x001f0017);//4GB } wr(ADDRMAP1,0x00080808); //bank +2 wr(ADDRMAP2,0x00000000); //col b5+5 ~ col b2 +2 wr(ADDRMAP3,0x00000000); //col b9 ~ col b6 wr(ADDRMAP4,0x00001f1f); //col b11~ col b10 wr(ADDRMAP5,0x070f0707); //row_b11 row b2_10 row b1 row b0 +6 wr(ADDRMAP6,0x07070707); //max row 15 wr(ADDRMAP7,0x00000f0f); wr(ADDRMAP9,0x07070707); wr(ADDRMAP10,0x07070707); wr(ADDRMAP11,0x00000007); } else if(bits==DDR_BITWIDTH_64){ #ifdef CONFIG_DDR_MSG printf("DDR 64bit mode, 256B interleaving\n"); #endif wr(ADDRMAP0,0x0004001f); // +2 if(rank_num==2) { #ifdef CONFIG_DDR_ROW16 wr(ADDRMAP0,0x00040019);//16GB #else wr(ADDRMAP0,0x00040018);//8GB #endif } wr(ADDRMAP1,0x00090909); //bank +2 wr(ADDRMAP2,0x00000000); //col b5+5 ~ col b2 +2 wr(ADDRMAP3,0x01010101); //col b9 ~ col b6 wr(ADDRMAP4,0x00001f1f); //col b11~ col b10 wr(ADDRMAP5,0x080f0808); //row_b11 row b2_10 row b1 row b0 +6 wr(ADDRMAP6,0x08080808); #ifdef CONFIG_DDR_ROW16 wr(ADDRMAP7,0x00000f08); #else wr(ADDRMAP7,0x00000f0f); #endif wr(ADDRMAP9,0x08080808); wr(ADDRMAP10,0x08080808); wr(ADDRMAP11,0x00000008); } else { printf("Wrong address map setting!!!\n"); } } void quasi_reg_write(unsigned long int reg,int wdata) { DWC_DDR_UMCTL2_C_STRUCT_REG_S umctl2_reg; umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.u32 = rd(SWCTL); umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.sw_done = 0; wr(SWCTL,umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.u32); wr(reg,wdata); umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.u32 = rd(SWCTL); umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.sw_done = 1; wr(SWCTL,umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.u32); umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.u32 = rd(SWSTAT); while( umctl2_reg.dwc_ddr_umctl2_c_struct_swstat.sw_done_ack == 0) umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.u32 = rd(SWSTAT); } void lpddr4_selfrefresh_exit(int mode) { int rdata=0; wr(PWRCTL,0x0); // put sdram into idle state wr(PWRCTL_DCH1,0x0); // put sdram into idle state while((rdata & 0x307) != 1) //wait sdram exit selfrefresh sate,wait umctl2 back to normal rdata = rd(STAT); rdata = 0; if(mode==0) { while((rdata & 0x307) != 1) //wait sdram exit selfrefresh sate,wait umctl2 back to normal rdata = rd(STAT_DCH1); } #ifdef CONFIG_DDR_MSG printf("[sdram_selfrefresh_exit] STAT is :%x after selfrefresh exit\n",rdata); #endif } void dfi_init(int dfi_init_complete_en) { DWC_DDR_UMCTL2_C_STRUCT_REG_S umctl2_reg; int rdata; #ifdef CONFIG_DDR_MSG printf("[dfi_init]: start dfi_init \n"); #endif wr(SWCTL, 0x00000000); //sw_done if(dfi_init_complete_en) wr(DFIMISC, 0x71); // x0~3: Goto PHY P0~3, // bit[6]: dis_dyn_adr_tri // bit[5]: dfi_init_start // bit[4]: ctl_idle_en // bit[0]: dfi_init_complete_en else wr(DFIMISC, 0x70); wr(SWCTL, 0x00000001); //sw_done //read SWSTAT, wait sw_done_ack = 1 rdata = rd(SWSTAT); while(rdata == 0) { rdata = rd(SWSTAT); } //Poll DFISTAT, wait dfi_init_complete umctl2_reg.dwc_ddr_umctl2_c_struct_dfistat.u32 = rd(DFISTAT); while(umctl2_reg.dwc_ddr_umctl2_c_struct_dfistat.dfi_init_complete == 0) //wait dfi_init_complete = 1 umctl2_reg.dwc_ddr_umctl2_c_struct_dfistat.u32 = rd(DFISTAT); //pull down dfi_init_start umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.u32 = rd(SWCTL); umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.sw_done = 0; wr(SWCTL,umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.u32); umctl2_reg.dwc_ddr_umctl2_c_struct_dfimisc.u32 = rd(DFIMISC); umctl2_reg.dwc_ddr_umctl2_c_struct_dfimisc.dfi_init_start = 0; wr(DFIMISC,umctl2_reg.dwc_ddr_umctl2_c_struct_dfimisc.u32); umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.u32 = rd(SWCTL); umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.sw_done = 1; wr(SWCTL,umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.u32); umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.u32 = rd(SWSTAT); while( umctl2_reg.dwc_ddr_umctl2_c_struct_swstat.sw_done_ack == 0) { umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.u32 = rd(SWSTAT); } #ifdef CONFIG_DDR_MSG printf("[dfi_init]: dfi_init end\n"); #endif } //put sdram into selfrefresh state, pwden_en=1 enable selfrefresh power-down, otherwise stay in selfrefresh void lpddr4_enter_selfrefresh(int pwdn_en,int dis_dram_clk,int mode) { DWC_DDR_UMCTL2_C_STRUCT_REG_S umctl2_reg; umctl2_reg.dwc_ddr_umctl2_c_struct_pwrctl.u32 = rd(PWRCTL); umctl2_reg.dwc_ddr_umctl2_c_struct_pwrctl.selfref_sw = 1; if(pwdn_en) umctl2_reg.dwc_ddr_umctl2_c_struct_pwrctl.stay_in_selfref = 0;//goto selfrefresh-powerdown after enter selfrefresh else umctl2_reg.dwc_ddr_umctl2_c_struct_pwrctl.stay_in_selfref = 1;//do not goto selfrefresh-powerdown, stay in selfrefresh umctl2_reg.dwc_ddr_umctl2_c_struct_pwrctl.lpddr4_sr_allowed = 1; if(dis_dram_clk) umctl2_reg.dwc_ddr_umctl2_c_struct_pwrctl.en_dfi_dram_clk_disable = 1; //turn off sdram clk when in self-refresh power-down state wr(PWRCTL,umctl2_reg.dwc_ddr_umctl2_c_struct_pwrctl.u32);//put sdram into selfrefresh state wr(PWRCTL_DCH1,umctl2_reg.dwc_ddr_umctl2_c_struct_pwrctl.u32);//put sdram into selfrefresh state //STAT:0x4 bit8,9:selfref_state umctl2_reg.dwc_ddr_umctl2_c_struct_stat.u32 = rd(STAT); if(pwdn_en) { while( umctl2_reg.dwc_ddr_umctl2_c_struct_stat.selfref_state != 2) //wait sdram enter selfrefresh-powerdown state umctl2_reg.dwc_ddr_umctl2_c_struct_stat.u32 = rd(STAT); } else { while( umctl2_reg.dwc_ddr_umctl2_c_struct_stat.selfref_state != 1) //wait sdram enter selfrefresh state umctl2_reg.dwc_ddr_umctl2_c_struct_stat.u32 = rd(STAT); } #ifdef CONFIG_DDR_MSG printf("[lpddr4_enter_selfrefresh]: CH0 STAT is :%x after enter selfrefresh state\n",umctl2_reg.dwc_ddr_umctl2_c_struct_stat.u32); #endif if(mode==0) { umctl2_reg.dwc_ddr_umctl2_c_struct_stat.u32 = rd(STAT_DCH1); if(pwdn_en) { while( umctl2_reg.dwc_ddr_umctl2_c_struct_stat.selfref_state != 2) //wait sdram enter selfrefresh-powerdown state umctl2_reg.dwc_ddr_umctl2_c_struct_stat.u32 = rd(STAT); } else { while( umctl2_reg.dwc_ddr_umctl2_c_struct_stat.selfref_state != 1) //wait sdram enter selfrefresh state umctl2_reg.dwc_ddr_umctl2_c_struct_stat.u32 = rd(STAT); } #ifdef CONFIG_DDR_MSG printf("[lpddr4_enter_selfrefresh]: CH1 STAT is :%x after enter selfrefresh state\n",umctl2_reg.dwc_ddr_umctl2_c_struct_stat.u32); #endif } } void lpddr4_auto_ps_en(int pwdn_en,int selfref_en,int clock_auto_disable ) { DWC_DDR_UMCTL2_C_STRUCT_REG_S umctl2_reg; umctl2_reg.dwc_ddr_umctl2_c_struct_pwrctl.u32 = rd(PWRCTL); umctl2_reg.dwc_ddr_umctl2_c_struct_pwrctl.stay_in_selfref = 0; umctl2_reg.dwc_ddr_umctl2_c_struct_pwrctl.lpddr4_sr_allowed = pwdn_en; umctl2_reg.dwc_ddr_umctl2_c_struct_pwrctl.deeppowerdown_en = 0; umctl2_reg.dwc_ddr_umctl2_c_struct_pwrctl.selfref_sw = 0; umctl2_reg.dwc_ddr_umctl2_c_struct_pwrctl.selfref_en = selfref_en; umctl2_reg.dwc_ddr_umctl2_c_struct_pwrctl.powerdown_en = pwdn_en; umctl2_reg.dwc_ddr_umctl2_c_struct_pwrctl.en_dfi_dram_clk_disable = clock_auto_disable; wr(PWRCTL,umctl2_reg.dwc_ddr_umctl2_c_struct_pwrctl.u32); wr(PWRCTL_DCH1,umctl2_reg.dwc_ddr_umctl2_c_struct_pwrctl.u32); #ifdef CONFIG_DDR_MSG printf("[lpddr4_selfrefresh_en] wait lpddr4 enter selfrefresh by slefref_en \n"); #endif } //de_assert umctl2_reset, phy_crst, and all areset void de_assert_other_reset_ddr() { #ifdef CONFIG_DDR_MSG printf("de-assert areset and ctrl_crst_n,ddr_phy_crst_n by sysreg or tb \n"); #endif //wr(0xf0000000,0xf); //ddr_sysreg_wr(DDR_CFG0,0x1ff0); //ddr_sysreg_wr(DDR_CFG0,0x1ff0); //ddr_sysreg_wr(DDR_CFG0,0x1ff0); ddr_sysreg.ddr_sysreg_registers_struct_ddr_cfg0.u32 = ddr_sysreg_rd(DDR_CFG0); ddr_sysreg.ddr_sysreg_registers_struct_ddr_cfg0.rg_ctl_ddr_usw_rst_reg |= 0x1F2; ddr_sysreg_wr(DDR_CFG0,ddr_sysreg.ddr_sysreg_registers_struct_ddr_cfg0.u32); } //assert umctl2_reset, and all areset void assert_ddrc_and_areset_sysreg() { #ifdef CONFIG_DDR_MSG printf("assert areset and ctrl_rst by sysreg \n"); #endif ddr_sysreg.ddr_sysreg_registers_struct_ddr_cfg0.u32 = ddr_sysreg_rd(DDR_CFG0); ddr_sysreg.ddr_sysreg_registers_struct_ddr_cfg0.rg_ctl_ddr_usw_rst_reg &= 0xd; ddr_sysreg_wr(DDR_CFG0,ddr_sysreg.ddr_sysreg_registers_struct_ddr_cfg0.u32); } void dfi_freq_change(int dfi_freq,int skip_dram_init) { DWC_DDR_UMCTL2_C_STRUCT_REG_S umctl2_reg; int rdata; #ifdef CONFIG_DDR_MSG printf("[dfi_freq_change]: start dfi_freq_change, target dfi_freq is %x \n",dfi_freq); #endif wr(DBG1,3); umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.u32 = rd(SWCTL); umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.sw_done = 0; wr(SWCTL,umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.u32); umctl2_reg.dwc_ddr_umctl2_c_struct_init0.u32 = rd(INIT0); umctl2_reg.dwc_ddr_umctl2_c_struct_init0.skip_dram_init = skip_dram_init; wr(INIT0,umctl2_reg.dwc_ddr_umctl2_c_struct_init0.u32); umctl2_reg.dwc_ddr_umctl2_c_struct_dfimisc.u32 = rd(DFIMISC); umctl2_reg.dwc_ddr_umctl2_c_struct_dfimisc.dfi_frequency = dfi_freq; umctl2_reg.dwc_ddr_umctl2_c_struct_dfimisc.dfi_init_start = 0x1; umctl2_reg.dwc_ddr_umctl2_c_struct_dfimisc.dfi_init_complete_en = 0; wr(DFIMISC,umctl2_reg.dwc_ddr_umctl2_c_struct_dfimisc.u32); umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.u32 = rd(SWCTL); umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.sw_done = 1; wr(SWCTL,umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.u32); umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.u32 = rd(SWSTAT); while( umctl2_reg.dwc_ddr_umctl2_c_struct_swstat.sw_done_ack == 0) umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.u32 = rd(SWSTAT); rdata = rd(DFISTAT); while((rdata & 0x1) != 0) //wait dfi_init_complete = 0 rdata = rd(DFISTAT); //change dfi clk freq here //pull down dfi_init_start umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.u32 = rd(SWCTL); umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.sw_done = 0; wr(SWCTL,umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.u32); umctl2_reg.dwc_ddr_umctl2_c_struct_dfimisc.u32 = rd(DFIMISC); umctl2_reg.dwc_ddr_umctl2_c_struct_dfimisc.dfi_init_start = 0; wr(DFIMISC,umctl2_reg.dwc_ddr_umctl2_c_struct_dfimisc.u32); umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.u32 = rd(SWCTL); umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.sw_done = 1; wr(SWCTL,umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.u32); umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.u32 = rd(SWSTAT); while( umctl2_reg.dwc_ddr_umctl2_c_struct_swstat.sw_done_ack == 0) umctl2_reg.dwc_ddr_umctl2_c_struct_swctl.u32 = rd(SWSTAT); umctl2_reg.dwc_ddr_umctl2_c_struct_dfistat.u32 = rd(DFISTAT); while(umctl2_reg.dwc_ddr_umctl2_c_struct_dfistat.dfi_init_complete == 0) umctl2_reg.dwc_ddr_umctl2_c_struct_dfistat.u32 = rd(DFISTAT); wr(DBG1,0); #ifdef CONFIG_DDR_MSG printf("[dfi_freq_change]: dfi_freq_change, end \n",dfi_freq); #endif } void ddr_soc_pll_disable () { ddr_sysreg_wr(DDR_CFG0+0x18,0x00000); //core clock gating enable ddr_sysreg_wr(DDR_CFG0+0xc,0x4b000000); //Reset SOC PLL #ifdef CONFIG_DDR_MSG printf("DDR SOC PLL PowerDown \n"); #endif } void lpddr4_auto_selref() { ddr_sysreg_wr(DDR_CFG1,0xa0000); //remove core clock after xx wr(SWCTL,0); wr(SWCTLSTATIC,1); wr(PWRTMG,0x40ae04); wr(HWLPCTL,0x430003); wr(DCH1_HWLPCTL,0x430003); wr(SWCTL,1); wr(SWCTLSTATIC,0); wr(PWRCTL,0x0000000b); //[3] dfi_dram_clk_disable [1] powerdown_en [0]serref_en wr(DCH1_PWRCTL,0x0000000b); }