1*e3963c09SPeng Fan // SPDX-License-Identifier: GPL-2.0+ 2*e3963c09SPeng Fan /* 3*e3963c09SPeng Fan * Copyright 2018 NXP 4*e3963c09SPeng Fan * 5*e3963c09SPeng Fan */ 6*e3963c09SPeng Fan 7*e3963c09SPeng Fan #include <common.h> 8*e3963c09SPeng Fan #include <errno.h> 9*e3963c09SPeng Fan #include <asm/io.h> 10*e3963c09SPeng Fan #include <asm/arch/ddr.h> 11*e3963c09SPeng Fan #include <asm/arch/clock.h> 12*e3963c09SPeng Fan #include <asm/arch/ddr.h> 13*e3963c09SPeng Fan #include <asm/arch/lpddr4_define.h> 14*e3963c09SPeng Fan #include <asm/arch/sys_proto.h> 15*e3963c09SPeng Fan 16*e3963c09SPeng Fan void lpddr4_cfg_umctl2(struct dram_cfg_param *ddrc_cfg, int num) 17*e3963c09SPeng Fan { 18*e3963c09SPeng Fan int i = 0; 19*e3963c09SPeng Fan 20*e3963c09SPeng Fan for (i = 0; i < num; i++) { 21*e3963c09SPeng Fan reg32_write(ddrc_cfg->reg, ddrc_cfg->val); 22*e3963c09SPeng Fan ddrc_cfg++; 23*e3963c09SPeng Fan } 24*e3963c09SPeng Fan } 25*e3963c09SPeng Fan 26*e3963c09SPeng Fan void ddr_init(struct dram_timing_info *dram_timing) 27*e3963c09SPeng Fan { 28*e3963c09SPeng Fan unsigned int tmp; 29*e3963c09SPeng Fan 30*e3963c09SPeng Fan debug("DDRINFO: start lpddr4 ddr init\n"); 31*e3963c09SPeng Fan /* step 1: reset */ 32*e3963c09SPeng Fan if (is_imx8mq()) { 33*e3963c09SPeng Fan reg32_write(SRC_DDRC_RCR_ADDR + 0x04, 0x8F00000F); 34*e3963c09SPeng Fan reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00000F); 35*e3963c09SPeng Fan reg32_write(SRC_DDRC_RCR_ADDR + 0x04, 0x8F000000); 36*e3963c09SPeng Fan } else { 37*e3963c09SPeng Fan reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00001F); 38*e3963c09SPeng Fan reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00000F); 39*e3963c09SPeng Fan } 40*e3963c09SPeng Fan 41*e3963c09SPeng Fan mdelay(100); 42*e3963c09SPeng Fan 43*e3963c09SPeng Fan debug("DDRINFO: reset done\n"); 44*e3963c09SPeng Fan /* 45*e3963c09SPeng Fan * change the clock source of dram_apb_clk_root: 46*e3963c09SPeng Fan * source 4 800MHz /4 = 200MHz 47*e3963c09SPeng Fan */ 48*e3963c09SPeng Fan clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON | 49*e3963c09SPeng Fan CLK_ROOT_SOURCE_SEL(4) | 50*e3963c09SPeng Fan CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV4)); 51*e3963c09SPeng Fan 52*e3963c09SPeng Fan /* disable iso */ 53*e3963c09SPeng Fan reg32_write(0x303A00EC, 0x0000ffff); /* PGC_CPU_MAPPING */ 54*e3963c09SPeng Fan reg32setbit(0x303A00F8, 5); /* PU_PGC_SW_PUP_REQ */ 55*e3963c09SPeng Fan 56*e3963c09SPeng Fan debug("DDRINFO: cfg clk\n"); 57*e3963c09SPeng Fan dram_pll_init(MHZ(750)); 58*e3963c09SPeng Fan 59*e3963c09SPeng Fan /* 60*e3963c09SPeng Fan * release [0]ddr1_preset_n, [1]ddr1_core_reset_n, 61*e3963c09SPeng Fan * [2]ddr1_phy_reset, [3]ddr1_phy_pwrokin_n 62*e3963c09SPeng Fan */ 63*e3963c09SPeng Fan reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000006); 64*e3963c09SPeng Fan 65*e3963c09SPeng Fan /*step2 Configure uMCTL2's registers */ 66*e3963c09SPeng Fan debug("DDRINFO: ddrc config start\n"); 67*e3963c09SPeng Fan lpddr4_cfg_umctl2(dram_timing->ddrc_cfg, dram_timing->ddrc_cfg_num); 68*e3963c09SPeng Fan debug("DDRINFO: ddrc config done\n"); 69*e3963c09SPeng Fan 70*e3963c09SPeng Fan /* 71*e3963c09SPeng Fan * step3 de-assert all reset 72*e3963c09SPeng Fan * RESET: <core_ddrc_rstn> DEASSERTED 73*e3963c09SPeng Fan * RESET: <aresetn> for Port 0 DEASSERT(0)ED 74*e3963c09SPeng Fan */ 75*e3963c09SPeng Fan reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000004); 76*e3963c09SPeng Fan reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000000); 77*e3963c09SPeng Fan 78*e3963c09SPeng Fan reg32_write(DDRC_DBG1(0), 0x00000000); 79*e3963c09SPeng Fan /* step4 */ 80*e3963c09SPeng Fan /* [0]dis_auto_refresh=1 */ 81*e3963c09SPeng Fan reg32_write(DDRC_RFSHCTL3(0), 0x00000011); 82*e3963c09SPeng Fan 83*e3963c09SPeng Fan /* [8]--1: lpddr4_sr allowed; [5]--1: software entry to SR */ 84*e3963c09SPeng Fan reg32_write(DDRC_PWRCTL(0), 0x000000a8); 85*e3963c09SPeng Fan 86*e3963c09SPeng Fan do { 87*e3963c09SPeng Fan tmp = reg32_read(DDRC_STAT(0)); 88*e3963c09SPeng Fan } while ((tmp & 0x33f) != 0x223); 89*e3963c09SPeng Fan 90*e3963c09SPeng Fan reg32_write(DDRC_DDR_SS_GPR0, 0x01); /* LPDDR4 mode */ 91*e3963c09SPeng Fan 92*e3963c09SPeng Fan /* step5 */ 93*e3963c09SPeng Fan reg32_write(DDRC_SWCTL(0), 0x00000000); 94*e3963c09SPeng Fan 95*e3963c09SPeng Fan /* step6 */ 96*e3963c09SPeng Fan tmp = reg32_read(DDRC_MSTR2(0)); 97*e3963c09SPeng Fan if (tmp == 0x2) 98*e3963c09SPeng Fan reg32_write(DDRC_DFIMISC(0), 0x00000210); 99*e3963c09SPeng Fan else if (tmp == 0x1) 100*e3963c09SPeng Fan reg32_write(DDRC_DFIMISC(0), 0x00000110); 101*e3963c09SPeng Fan else 102*e3963c09SPeng Fan reg32_write(DDRC_DFIMISC(0), 0x00000010); 103*e3963c09SPeng Fan 104*e3963c09SPeng Fan /* step7 [0]--1: disable quasi-dynamic programming */ 105*e3963c09SPeng Fan reg32_write(DDRC_SWCTL(0), 0x00000001); 106*e3963c09SPeng Fan 107*e3963c09SPeng Fan /* step8 Configure LPDDR4 PHY's registers */ 108*e3963c09SPeng Fan debug("DDRINFO:ddrphy config start\n"); 109*e3963c09SPeng Fan ddr_cfg_phy(dram_timing); 110*e3963c09SPeng Fan debug("DDRINFO: ddrphy config done\n"); 111*e3963c09SPeng Fan 112*e3963c09SPeng Fan /* 113*e3963c09SPeng Fan * step14 CalBusy.0 =1, indicates the calibrator is actively 114*e3963c09SPeng Fan * calibrating. Wait Calibrating done. 115*e3963c09SPeng Fan */ 116*e3963c09SPeng Fan do { 117*e3963c09SPeng Fan tmp = reg32_read(DDRPHY_CalBusy(0)); 118*e3963c09SPeng Fan } while ((tmp & 0x1)); 119*e3963c09SPeng Fan 120*e3963c09SPeng Fan debug("DDRINFO:ddrphy calibration done\n"); 121*e3963c09SPeng Fan 122*e3963c09SPeng Fan /* step15 [0]--0: to enable quasi-dynamic programming */ 123*e3963c09SPeng Fan reg32_write(DDRC_SWCTL(0), 0x00000000); 124*e3963c09SPeng Fan 125*e3963c09SPeng Fan /* step16 */ 126*e3963c09SPeng Fan tmp = reg32_read(DDRC_MSTR2(0)); 127*e3963c09SPeng Fan if (tmp == 0x2) 128*e3963c09SPeng Fan reg32_write(DDRC_DFIMISC(0), 0x00000230); 129*e3963c09SPeng Fan else if (tmp == 0x1) 130*e3963c09SPeng Fan reg32_write(DDRC_DFIMISC(0), 0x00000130); 131*e3963c09SPeng Fan else 132*e3963c09SPeng Fan reg32_write(DDRC_DFIMISC(0), 0x00000030); 133*e3963c09SPeng Fan 134*e3963c09SPeng Fan /* step17 [0]--1: disable quasi-dynamic programming */ 135*e3963c09SPeng Fan reg32_write(DDRC_SWCTL(0), 0x00000001); 136*e3963c09SPeng Fan /* step18 wait DFISTAT.dfi_init_complete to 1 */ 137*e3963c09SPeng Fan do { 138*e3963c09SPeng Fan tmp = reg32_read(DDRC_DFISTAT(0)); 139*e3963c09SPeng Fan } while ((tmp & 0x1) == 0x0); 140*e3963c09SPeng Fan 141*e3963c09SPeng Fan /* step19 */ 142*e3963c09SPeng Fan reg32_write(DDRC_SWCTL(0), 0x00000000); 143*e3963c09SPeng Fan 144*e3963c09SPeng Fan /* step20~22 */ 145*e3963c09SPeng Fan tmp = reg32_read(DDRC_MSTR2(0)); 146*e3963c09SPeng Fan if (tmp == 0x2) { 147*e3963c09SPeng Fan reg32_write(DDRC_DFIMISC(0), 0x00000210); 148*e3963c09SPeng Fan /* set DFIMISC.dfi_init_complete_en again */ 149*e3963c09SPeng Fan reg32_write(DDRC_DFIMISC(0), 0x00000211); 150*e3963c09SPeng Fan } else if (tmp == 0x1) { 151*e3963c09SPeng Fan reg32_write(DDRC_DFIMISC(0), 0x00000110); 152*e3963c09SPeng Fan /* set DFIMISC.dfi_init_complete_en again */ 153*e3963c09SPeng Fan reg32_write(DDRC_DFIMISC(0), 0x00000111); 154*e3963c09SPeng Fan } else { 155*e3963c09SPeng Fan /* clear DFIMISC.dfi_init_complete_en */ 156*e3963c09SPeng Fan reg32_write(DDRC_DFIMISC(0), 0x00000010); 157*e3963c09SPeng Fan /* set DFIMISC.dfi_init_complete_en again */ 158*e3963c09SPeng Fan reg32_write(DDRC_DFIMISC(0), 0x00000011); 159*e3963c09SPeng Fan } 160*e3963c09SPeng Fan 161*e3963c09SPeng Fan /* step23 [5]selfref_sw=0; */ 162*e3963c09SPeng Fan reg32_write(DDRC_PWRCTL(0), 0x00000008); 163*e3963c09SPeng Fan /* step24 sw_done=1 */ 164*e3963c09SPeng Fan reg32_write(DDRC_SWCTL(0), 0x00000001); 165*e3963c09SPeng Fan 166*e3963c09SPeng Fan /* step25 wait SWSTAT.sw_done_ack to 1 */ 167*e3963c09SPeng Fan do { 168*e3963c09SPeng Fan tmp = reg32_read(DDRC_SWSTAT(0)); 169*e3963c09SPeng Fan } while ((tmp & 0x1) == 0x0); 170*e3963c09SPeng Fan 171*e3963c09SPeng Fan #ifdef DFI_BUG_WR 172*e3963c09SPeng Fan reg32_write(DDRC_DFIPHYMSTR(0), 0x00000001); 173*e3963c09SPeng Fan #endif 174*e3963c09SPeng Fan /* wait STAT.operating_mode([1:0] for ddr3) to normal state */ 175*e3963c09SPeng Fan do { 176*e3963c09SPeng Fan tmp = reg32_read(DDRC_STAT(0)); 177*e3963c09SPeng Fan } while ((tmp & 0x3) != 0x1); 178*e3963c09SPeng Fan 179*e3963c09SPeng Fan /* step26 */ 180*e3963c09SPeng Fan reg32_write(DDRC_RFSHCTL3(0), 0x00000010); 181*e3963c09SPeng Fan 182*e3963c09SPeng Fan /* enable port 0 */ 183*e3963c09SPeng Fan reg32_write(DDRC_PCTRL_0(0), 0x00000001); 184*e3963c09SPeng Fan debug("DDRINFO: ddrmix config done\n"); 185*e3963c09SPeng Fan 186*e3963c09SPeng Fan /* save the dram timing config into memory */ 187*e3963c09SPeng Fan dram_config_save(dram_timing, CONFIG_SAVED_DRAM_TIMING_BASE); 188*e3963c09SPeng Fan } 189