1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright 2018 NXP 4 */ 5 6 #include <common.h> 7 #include <errno.h> 8 #include <asm/io.h> 9 #include <asm/arch/ddr.h> 10 #include <asm/arch/clock.h> 11 #include <asm/arch/imx8m_ddr.h> 12 #include <asm/arch/sys_proto.h> 13 14 void ddr4_cfg_umctl2(struct dram_cfg_param *ddrc_cfg, int num) 15 { 16 int i = 0; 17 18 for (i = 0; i < num; i++) { 19 reg32_write(ddrc_cfg->reg, ddrc_cfg->val); 20 ddrc_cfg++; 21 } 22 } 23 24 void ddr_init(struct dram_timing_info *dram_timing) 25 { 26 volatile unsigned int tmp_t; 27 /* 28 * assert [0]ddr1_preset_n, [1]ddr1_core_reset_n, 29 * [2]ddr1_phy_reset, [3]ddr1_phy_pwrokin_n, 30 * [4]src_system_rst_b! 31 */ 32 reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00003F); 33 /* deassert [4]src_system_rst_b! */ 34 reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00000F); 35 36 /* 37 * change the clock source of dram_apb_clk_root 38 * to source 4 --800MHz/4 39 */ 40 clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON | 41 CLK_ROOT_SOURCE_SEL(4) | 42 CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV4)); 43 44 dram_pll_init(DRAM_PLL_OUT_600M); 45 46 reg32_write(0x303A00EC, 0x0000ffff); /* PGC_CPU_MAPPING */ 47 reg32setbit(0x303A00F8, 5); /* PU_PGC_SW_PUP_REQ */ 48 49 /* release [0]ddr1_preset_n, [3]ddr1_phy_pwrokin_n */ 50 reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000006); 51 52 reg32_write(DDRC_DBG1(0), 0x00000001); 53 reg32_write(DDRC_PWRCTL(0), 0x00000001); 54 55 while (0 != (0x7 & reg32_read(DDRC_STAT(0)))) 56 ; 57 58 /* config the uMCTL2's registers */ 59 ddr4_cfg_umctl2(dram_timing->ddrc_cfg, dram_timing->ddrc_cfg_num); 60 61 reg32_write(DDRC_RFSHCTL3(0), 0x00000001); 62 /* RESET: <ctn> DEASSERTED */ 63 /* RESET: <a Port 0 DEASSERTED(0) */ 64 reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000004); 65 reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000000); 66 67 reg32_write(DDRC_DBG1(0), 0x00000000); 68 reg32_write(DDRC_PWRCTL(0), 0x00000aa); 69 reg32_write(DDRC_SWCTL(0), 0x00000000); 70 71 reg32_write(DDRC_DFIMISC(0), 0x00000000); 72 73 /* config the DDR PHY's registers */ 74 ddr_cfg_phy(dram_timing); 75 76 do { 77 tmp_t = reg32_read(IP2APB_DDRPHY_IPS_BASE_ADDR(0) + 78 4 * 0x00020097); 79 } while (tmp_t != 0); 80 81 reg32_write(DDRC_DFIMISC(0), 0x00000020); 82 83 /* wait DFISTAT.dfi_init_complete to 1 */ 84 while (0 == (0x1 & reg32_read(DDRC_DFISTAT(0)))) 85 ; 86 87 /* clear DFIMISC.dfi_init_complete_en */ 88 reg32_write(DDRC_DFIMISC(0), 0x00000000); 89 /* set DFIMISC.dfi_init_complete_en again */ 90 reg32_write(DDRC_DFIMISC(0), 0x00000001); 91 reg32_write(DDRC_PWRCTL(0), 0x0000088); 92 93 /* 94 * set SWCTL.sw_done to enable quasi-dynamic register 95 * programming outside reset. 96 */ 97 reg32_write(DDRC_SWCTL(0), 0x00000001); 98 /* wait SWSTAT.sw_done_ack to 1 */ 99 while (0 == (0x1 & reg32_read(DDRC_SWSTAT(0)))) 100 ; 101 102 /* wait STAT to normal state */ 103 while (0x1 != (0x7 & reg32_read(DDRC_STAT(0)))) 104 ; 105 106 reg32_write(DDRC_PWRCTL(0), 0x0000088); 107 reg32_write(DDRC_PCTRL_0(0), 0x00000001); 108 /* dis_auto-refresh is set to 0 */ 109 reg32_write(DDRC_RFSHCTL3(0), 0x00000000); 110 111 /* save the dram timing config into memory */ 112 dram_config_save(dram_timing, CONFIG_SAVED_DRAM_TIMING_BASE); 113 } 114