Commit 258db72309ec47b99cec89c06f6b4491f9951b27
1 parent
e2985a6e64
Exists in
smarc_8mm-imx_v2018.03_4.14.98_2.0.0_ga
and in
5 other branches
MLK-19777-01: imx8mm: rename the lpddr4_ddrphy_train file
For LPDDR4 or DDR4, the ddr phy train flow is the same. So rename the 'lpddr4_ddrphy_train.c' to 'ddrphy_train.c'. make it more common for reuse and move it to driver/ddr/imx8m/. Signed-off-by: Bai Ping <ping.bai@nxp.com>
Showing 7 changed files with 276 additions and 283 deletions Side-by-side Diff
arch/arm/include/asm/arch-imx8m/imx8m_ddr.h
... | ... | @@ -52,7 +52,7 @@ |
52 | 52 | |
53 | 53 | void ddr_load_train_firmware(enum fw_type type); |
54 | 54 | void ddr_init(struct dram_timing_info *timing_info); |
55 | -void lpddr4_cfg_phy(struct dram_timing_info *timing_info); | |
55 | +void ddr_cfg_phy(struct dram_timing_info *timing_info); | |
56 | 56 | void load_lpddr4_phy_pie(void); |
57 | 57 | void ddrphy_trained_csr_save(struct dram_cfg_param *, unsigned int); |
58 | 58 | void dram_config_save(struct dram_timing_info *, unsigned long); |
drivers/ddr/imx8m/Makefile
drivers/ddr/imx8m/ddrphy_train.c
1 | +/* | |
2 | + * Copyright 2018 NXP | |
3 | + * | |
4 | + * SPDX-License-Identifier: GPL-2.0+ | |
5 | + */ | |
6 | +#include <common.h> | |
7 | +#include <linux/kernel.h> | |
8 | +#include <asm/arch/imx8m_ddr.h> | |
9 | +#include <asm/arch/lpddr4_define.h> | |
10 | + | |
11 | +void ddr_cfg_phy(struct dram_timing_info *dram_timing) | |
12 | +{ | |
13 | + struct dram_cfg_param *dram_cfg; | |
14 | + struct dram_fsp_msg *fsp_msg; | |
15 | + unsigned int num; | |
16 | + int i = 0; | |
17 | + int j = 0; | |
18 | + | |
19 | + /* initialize PHY configuration */ | |
20 | + dram_cfg = dram_timing->ddrphy_cfg; | |
21 | + num = dram_timing->ddrphy_cfg_num; | |
22 | + for (i = 0; i < num; i++) { | |
23 | + /* config phy reg */ | |
24 | + dwc_ddrphy_apb_wr(dram_cfg->reg, dram_cfg->val); | |
25 | + dram_cfg++; | |
26 | + } | |
27 | + | |
28 | + /* load the frequency setpoint message block config */ | |
29 | + fsp_msg = dram_timing->fsp_msg; | |
30 | + for (i = 0; i < dram_timing->fsp_msg_num; i++) { | |
31 | + printf("DRAM PHY training for %dMTS\n", fsp_msg->drate); | |
32 | + /* set dram PHY input clocks to desired frequency */ | |
33 | + ddrphy_init_set_dfi_clk(fsp_msg->drate); | |
34 | + | |
35 | + /* load the dram training firmware image */ | |
36 | + dwc_ddrphy_apb_wr(0xd0000,0x0); | |
37 | + ddr_load_train_firmware(fsp_msg->fw_type); | |
38 | + | |
39 | + /* load the frequency set point message block parameter */ | |
40 | + dram_cfg = fsp_msg->fsp_cfg; | |
41 | + num = fsp_msg->fsp_cfg_num; | |
42 | + for (j = 0; j < num; j++) { | |
43 | + dwc_ddrphy_apb_wr(dram_cfg->reg, dram_cfg->val); | |
44 | + dram_cfg++; | |
45 | + } | |
46 | + | |
47 | + /* | |
48 | + * -------------------- excute the firmware -------------------- | |
49 | + * Running the firmware is a simply process to taking the | |
50 | + * PMU out of reset and stall, then the firwmare will be run | |
51 | + * 1. reset the PMU; | |
52 | + * 2. begin the excution; | |
53 | + * 3. wait for the training done; | |
54 | + * 4. read the message block result. | |
55 | + * ------------------------------------------------------------- | |
56 | + */ | |
57 | + dwc_ddrphy_apb_wr(0xd0000, 0x1); | |
58 | + dwc_ddrphy_apb_wr(0xd0099, 0x9); | |
59 | + dwc_ddrphy_apb_wr(0xd0099, 0x1); | |
60 | + dwc_ddrphy_apb_wr(0xd0099, 0x0); | |
61 | + | |
62 | + /* Wait for the training firmware to complete */ | |
63 | + wait_ddrphy_training_complete(); | |
64 | + | |
65 | + /* Halt the microcontroller. */ | |
66 | + dwc_ddrphy_apb_wr(0xd0099, 0x1); | |
67 | + | |
68 | + /* Read the Message Block results */ | |
69 | + dwc_ddrphy_apb_wr(0xd0000, 0x0); | |
70 | + ddrphy_init_read_msg_block(fsp_msg->fw_type); | |
71 | + dwc_ddrphy_apb_wr(0xd0000, 0x1); | |
72 | + | |
73 | + fsp_msg++; | |
74 | + } | |
75 | + | |
76 | + /* Load PHY Init Engine Image */ | |
77 | + dram_cfg = dram_timing->ddrphy_pie; | |
78 | + num = dram_timing->ddrphy_pie_num; | |
79 | + for (i = 0; i < num; i++) { | |
80 | + dwc_ddrphy_apb_wr(dram_cfg->reg, dram_cfg->val); | |
81 | + dram_cfg++; | |
82 | + } | |
83 | + | |
84 | + /* save the ddr PHY trained CSR in memory for low power use */ | |
85 | + ddrphy_trained_csr_save(dram_timing->ddrphy_trained_csr, | |
86 | + dram_timing->ddrphy_trained_csr_num); | |
87 | +} |
drivers/ddr/imx8m/lpddr4/Makefile
drivers/ddr/imx8m/lpddr4/lpddr4_ddrphy_train.c
1 | -/* | |
2 | - * Copyright 2018 NXP | |
3 | - * | |
4 | - * SPDX-License-Identifier: GPL-2.0+ | |
5 | - */ | |
6 | -#include <common.h> | |
7 | -#include <linux/kernel.h> | |
8 | -#include <asm/arch/imx8m_ddr.h> | |
9 | -#include <asm/arch/lpddr4_define.h> | |
10 | - | |
11 | -void lpddr4_cfg_phy(struct dram_timing_info *dram_timing) | |
12 | -{ | |
13 | - struct dram_cfg_param *dram_cfg; | |
14 | - struct dram_fsp_msg *fsp_msg; | |
15 | - unsigned int num; | |
16 | - int i = 0; | |
17 | - int j = 0; | |
18 | - | |
19 | - /* initialize PHY configuration */ | |
20 | - dram_cfg = dram_timing->ddrphy_cfg; | |
21 | - num = dram_timing->ddrphy_cfg_num; | |
22 | - for (i = 0; i < num; i++) { | |
23 | - /* config phy reg */ | |
24 | - dwc_ddrphy_apb_wr(dram_cfg->reg, dram_cfg->val); | |
25 | - dram_cfg++; | |
26 | - } | |
27 | - | |
28 | - /* load the frequency setpoint message block config */ | |
29 | - fsp_msg = dram_timing->fsp_msg; | |
30 | - for (i = 0; i < dram_timing->fsp_msg_num; i++) { | |
31 | - printf("DRAM PHY training for %dMTS\n", fsp_msg->drate); | |
32 | - /* set dram PHY input clocks to desired frequency */ | |
33 | - ddrphy_init_set_dfi_clk(fsp_msg->drate); | |
34 | - | |
35 | - /* load the dram training firmware image */ | |
36 | - dwc_ddrphy_apb_wr(0xd0000,0x0); | |
37 | - ddr_load_train_firmware(fsp_msg->fw_type); | |
38 | - | |
39 | - /* load the frequency set point message block parameter */ | |
40 | - dram_cfg = fsp_msg->fsp_cfg; | |
41 | - num = fsp_msg->fsp_cfg_num; | |
42 | - for (j = 0; j < num; j++) { | |
43 | - dwc_ddrphy_apb_wr(dram_cfg->reg, dram_cfg->val); | |
44 | - dram_cfg++; | |
45 | - } | |
46 | - | |
47 | - /* | |
48 | - * -------------------- excute the firmware -------------------- | |
49 | - * Running the firmware is a simply process to taking the | |
50 | - * PMU out of reset and stall, then the firwmare will be run | |
51 | - * 1. reset the PMU; | |
52 | - * 2. begin the excution; | |
53 | - * 3. wait for the training done; | |
54 | - * 4. read the message block result. | |
55 | - * ------------------------------------------------------------- | |
56 | - */ | |
57 | - dwc_ddrphy_apb_wr(0xd0000, 0x1); | |
58 | - dwc_ddrphy_apb_wr(0xd0099, 0x9); | |
59 | - dwc_ddrphy_apb_wr(0xd0099, 0x1); | |
60 | - dwc_ddrphy_apb_wr(0xd0099, 0x0); | |
61 | - | |
62 | - /* Wait for the training firmware to complete */ | |
63 | - wait_ddrphy_training_complete(); | |
64 | - | |
65 | - /* Halt the microcontroller. */ | |
66 | - dwc_ddrphy_apb_wr(0xd0099, 0x1); | |
67 | - | |
68 | - /* Read the Message Block results */ | |
69 | - dwc_ddrphy_apb_wr(0xd0000, 0x0); | |
70 | - ddrphy_init_read_msg_block(fsp_msg->fw_type); | |
71 | - dwc_ddrphy_apb_wr(0xd0000, 0x1); | |
72 | - | |
73 | - fsp_msg++; | |
74 | - } | |
75 | - | |
76 | - /* Load PHY Init Engine Image */ | |
77 | - dram_cfg = dram_timing->ddrphy_pie; | |
78 | - num = dram_timing->ddrphy_pie_num; | |
79 | - for (i = 0; i < num; i++) { | |
80 | - dwc_ddrphy_apb_wr(dram_cfg->reg, dram_cfg->val); | |
81 | - dram_cfg++; | |
82 | - } | |
83 | - | |
84 | - /* save the ddr PHY trained CSR in memory for low power use */ | |
85 | - ddrphy_trained_csr_save(dram_timing->ddrphy_trained_csr, | |
86 | - dram_timing->ddrphy_trained_csr_num); | |
87 | -} |
drivers/ddr/imx8m/lpddr4/lpddr4_init.c
1 | -/* | |
2 | -* Copyright 2018 NXP | |
3 | -* | |
4 | -* SPDX-License-Identifier: GPL-2.0+ | |
5 | -*/ | |
6 | - | |
7 | -#include <common.h> | |
8 | -#include <errno.h> | |
9 | -#include <asm/io.h> | |
10 | -#include <asm/arch/ddr.h> | |
11 | -#include <asm/arch/clock.h> | |
12 | -#include <asm/arch/imx8m_ddr.h> | |
13 | -#include <asm/arch/lpddr4_define.h> | |
14 | -#include <asm/arch/sys_proto.h> | |
15 | - | |
16 | -void lpddr4_cfg_umctl2(struct dram_cfg_param *ddrc_cfg, int num) | |
17 | -{ | |
18 | - int i = 0; | |
19 | - | |
20 | - for (i = 0; i < num; i++) { | |
21 | - reg32_write(ddrc_cfg->reg, ddrc_cfg->val); | |
22 | - ddrc_cfg++; | |
23 | - } | |
24 | -} | |
25 | - | |
26 | -void ddr_init(struct dram_timing_info *dram_timing) | |
27 | -{ | |
28 | - unsigned int tmp; | |
29 | - | |
30 | - printf("DDRINFO: start lpddr4 ddr init\n"); | |
31 | - /* step 1: reset */ | |
32 | - if (is_imx8mq()) { | |
33 | - reg32_write(SRC_DDRC_RCR_ADDR + 0x04, 0x8F00000F); | |
34 | - reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00000F); | |
35 | - reg32_write(SRC_DDRC_RCR_ADDR + 0x04, 0x8F000000); | |
36 | - } else { | |
37 | - reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00001F); | |
38 | - reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00000F); | |
39 | - } | |
40 | - | |
41 | - mdelay(100); | |
42 | - | |
43 | - debug("DDRINFO: reset done\n"); | |
44 | - /* change the clock source of dram_apb_clk_root: source 4 800MHz /4 = 200MHz */ | |
45 | - clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(4) | | |
46 | - CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV4)); | |
47 | - | |
48 | - /* disable iso */ | |
49 | - reg32_write(0x303A00EC, 0x0000ffff); /* PGC_CPU_MAPPING */ | |
50 | - reg32setbit(0x303A00F8, 5); /* PU_PGC_SW_PUP_REQ */ | |
51 | - | |
52 | - debug("DDRINFO: cfg clk\n"); | |
53 | - dram_pll_init(DRAM_PLL_OUT_750M); | |
54 | - | |
55 | - /* | |
56 | - * release [0]ddr1_preset_n, [1]ddr1_core_reset_n, | |
57 | - * [2]ddr1_phy_reset, [3]ddr1_phy_pwrokin_n | |
58 | - */ | |
59 | - reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000006); | |
60 | - | |
61 | - /*step2 Configure uMCTL2's registers */ | |
62 | - debug("DDRINFO: ddrc config start\n"); | |
63 | - lpddr4_cfg_umctl2(dram_timing->ddrc_cfg, dram_timing->ddrc_cfg_num); | |
64 | - debug("DDRINFO: ddrc config done\n"); | |
65 | - | |
66 | - /* | |
67 | - * step3 de-assert all reset | |
68 | - * RESET: <core_ddrc_rstn> DEASSERTED | |
69 | - * RESET: <aresetn> for Port 0 DEASSERT(0)ED | |
70 | - */ | |
71 | - reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000004); | |
72 | - reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000000); | |
73 | - | |
74 | - reg32_write(DDRC_DBG1(0), 0x00000000); | |
75 | - /* step4 */ | |
76 | - /* [0]dis_auto_refresh=1 */ | |
77 | - reg32_write(DDRC_RFSHCTL3(0), 0x00000011); | |
78 | - | |
79 | - /* [8]--1: lpddr4_sr allowed; [5]--1: software entry to SR */ | |
80 | - reg32_write(DDRC_PWRCTL(0), 0x000000a8); | |
81 | - | |
82 | - do { | |
83 | - tmp = reg32_read(DDRC_STAT(0)); | |
84 | - } while ((tmp & 0x33f) != 0x223); | |
85 | - | |
86 | - reg32_write(DDRC_DDR_SS_GPR0, 0x01); /* LPDDR4 mode */ | |
87 | - | |
88 | - /* step5 */ | |
89 | - reg32_write(DDRC_SWCTL(0), 0x00000000); | |
90 | - | |
91 | - /* step6 */ | |
92 | - tmp = reg32_read(DDRC_MSTR2(0)); | |
93 | - if (tmp == 0x2) { | |
94 | - reg32_write(DDRC_DFIMISC(0), 0x00000210); | |
95 | - } else if (tmp == 0x1) { | |
96 | - reg32_write(DDRC_DFIMISC(0), 0x00000110); | |
97 | - } else { | |
98 | - reg32_write(DDRC_DFIMISC(0), 0x00000010); | |
99 | - } | |
100 | - | |
101 | - /* step7 [0]--1: disable quasi-dynamic programming */ | |
102 | - reg32_write(DDRC_SWCTL(0), 0x00000001); | |
103 | - | |
104 | - /* step8 Configure LPDDR4 PHY's registers */ | |
105 | - debug("DDRINFO:ddrphy config start\n"); | |
106 | - lpddr4_cfg_phy(dram_timing); | |
107 | - debug("DDRINFO: ddrphy config done\n"); | |
108 | - | |
109 | - /* | |
110 | - * step14 CalBusy.0 =1, indicates the calibrator is actively | |
111 | - * calibrating. Wait Calibrating done. | |
112 | - */ | |
113 | - do { | |
114 | - tmp = reg32_read(DDRPHY_CalBusy(0)); | |
115 | - } while ((tmp & 0x1)); | |
116 | - | |
117 | - printf("DDRINFO:ddrphy calibration done\n"); | |
118 | - | |
119 | - /* step15 [0]--0: to enable quasi-dynamic programming */ | |
120 | - reg32_write(DDRC_SWCTL(0), 0x00000000); | |
121 | - | |
122 | - /* step16 */ | |
123 | - tmp = reg32_read(DDRC_MSTR2(0)); | |
124 | - if (tmp == 0x2) { | |
125 | - reg32_write(DDRC_DFIMISC(0), 0x00000230); | |
126 | - } else if (tmp == 0x1) { | |
127 | - reg32_write(DDRC_DFIMISC(0), 0x00000130); | |
128 | - } else { | |
129 | - reg32_write(DDRC_DFIMISC(0), 0x00000030); | |
130 | - } | |
131 | - | |
132 | - /* step17 [0]--1: disable quasi-dynamic programming */ | |
133 | - reg32_write(DDRC_SWCTL(0), 0x00000001); | |
134 | - /* step18 wait DFISTAT.dfi_init_complete to 1 */ | |
135 | - do { | |
136 | - tmp = reg32_read(DDRC_DFISTAT(0)); | |
137 | - } while ((tmp & 0x1) == 0x0); | |
138 | - | |
139 | - /* step19 */ | |
140 | - reg32_write(DDRC_SWCTL(0), 0x00000000); | |
141 | - | |
142 | - /* step20~22 */ | |
143 | - tmp = reg32_read(DDRC_MSTR2(0)); | |
144 | - if (tmp == 0x2) { | |
145 | - reg32_write(DDRC_DFIMISC(0), 0x00000210); | |
146 | - /* set DFIMISC.dfi_init_complete_en again */ | |
147 | - reg32_write(DDRC_DFIMISC(0), 0x00000211); | |
148 | - } else if (tmp == 0x1) { | |
149 | - reg32_write(DDRC_DFIMISC(0), 0x00000110); | |
150 | - /* set DFIMISC.dfi_init_complete_en again */ | |
151 | - reg32_write(DDRC_DFIMISC(0), 0x00000111); | |
152 | - } else { | |
153 | - /* clear DFIMISC.dfi_init_complete_en */ | |
154 | - reg32_write(DDRC_DFIMISC(0), 0x00000010); | |
155 | - /* set DFIMISC.dfi_init_complete_en again */ | |
156 | - reg32_write(DDRC_DFIMISC(0), 0x00000011); | |
157 | - } | |
158 | - | |
159 | - /* step23 [5]selfref_sw=0; */ | |
160 | - reg32_write(DDRC_PWRCTL(0), 0x00000008); | |
161 | - /* step24 sw_done=1 */ | |
162 | - reg32_write(DDRC_SWCTL(0), 0x00000001); | |
163 | - | |
164 | - /* step25 wait SWSTAT.sw_done_ack to 1 */ | |
165 | - do { | |
166 | - tmp = reg32_read(DDRC_SWSTAT(0)); | |
167 | - } while ((tmp & 0x1) == 0x0); | |
168 | - | |
169 | -#ifdef DFI_BUG_WR | |
170 | - reg32_write(DDRC_DFIPHYMSTR(0), 0x00000001); | |
171 | -#endif | |
172 | - /* wait STAT.operating_mode([1:0] for ddr3) to normal state */ | |
173 | - do { | |
174 | - tmp = reg32_read(DDRC_STAT(0)); | |
175 | - } while ((tmp & 0x3) != 0x1); | |
176 | - | |
177 | - /* step26 */ | |
178 | - reg32_write(DDRC_RFSHCTL3(0), 0x00000010); | |
179 | - | |
180 | - /* enable port 0 */ | |
181 | - reg32_write(DDRC_PCTRL_0(0), 0x00000001); | |
182 | - printf("DDRINFO: ddrmix config done\n"); | |
183 | - | |
184 | - /* save the dram timing config into memory */ | |
185 | - dram_config_save(dram_timing, CONFIG_SAVED_DRAM_TIMING_BASE); | |
186 | -} |
drivers/ddr/imx8m/lpddr4_init.c
1 | +/* | |
2 | +* Copyright 2018 NXP | |
3 | +* | |
4 | +* SPDX-License-Identifier: GPL-2.0+ | |
5 | +*/ | |
6 | + | |
7 | +#include <common.h> | |
8 | +#include <errno.h> | |
9 | +#include <asm/io.h> | |
10 | +#include <asm/arch/ddr.h> | |
11 | +#include <asm/arch/clock.h> | |
12 | +#include <asm/arch/imx8m_ddr.h> | |
13 | +#include <asm/arch/lpddr4_define.h> | |
14 | +#include <asm/arch/sys_proto.h> | |
15 | + | |
16 | +void lpddr4_cfg_umctl2(struct dram_cfg_param *ddrc_cfg, int num) | |
17 | +{ | |
18 | + int i = 0; | |
19 | + | |
20 | + for (i = 0; i < num; i++) { | |
21 | + reg32_write(ddrc_cfg->reg, ddrc_cfg->val); | |
22 | + ddrc_cfg++; | |
23 | + } | |
24 | +} | |
25 | + | |
26 | +void ddr_init(struct dram_timing_info *dram_timing) | |
27 | +{ | |
28 | + unsigned int tmp; | |
29 | + | |
30 | + printf("DDRINFO: start lpddr4 ddr init\n"); | |
31 | + /* step 1: reset */ | |
32 | + if (is_imx8mq()) { | |
33 | + reg32_write(SRC_DDRC_RCR_ADDR + 0x04, 0x8F00000F); | |
34 | + reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00000F); | |
35 | + reg32_write(SRC_DDRC_RCR_ADDR + 0x04, 0x8F000000); | |
36 | + } else { | |
37 | + reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00001F); | |
38 | + reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00000F); | |
39 | + } | |
40 | + | |
41 | + mdelay(100); | |
42 | + | |
43 | + debug("DDRINFO: reset done\n"); | |
44 | + /* change the clock source of dram_apb_clk_root: source 4 800MHz /4 = 200MHz */ | |
45 | + clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(4) | | |
46 | + CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV4)); | |
47 | + | |
48 | + /* disable iso */ | |
49 | + reg32_write(0x303A00EC, 0x0000ffff); /* PGC_CPU_MAPPING */ | |
50 | + reg32setbit(0x303A00F8, 5); /* PU_PGC_SW_PUP_REQ */ | |
51 | + | |
52 | + debug("DDRINFO: cfg clk\n"); | |
53 | + dram_pll_init(DRAM_PLL_OUT_750M); | |
54 | + | |
55 | + /* | |
56 | + * release [0]ddr1_preset_n, [1]ddr1_core_reset_n, | |
57 | + * [2]ddr1_phy_reset, [3]ddr1_phy_pwrokin_n | |
58 | + */ | |
59 | + reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000006); | |
60 | + | |
61 | + /*step2 Configure uMCTL2's registers */ | |
62 | + debug("DDRINFO: ddrc config start\n"); | |
63 | + lpddr4_cfg_umctl2(dram_timing->ddrc_cfg, dram_timing->ddrc_cfg_num); | |
64 | + debug("DDRINFO: ddrc config done\n"); | |
65 | + | |
66 | + /* | |
67 | + * step3 de-assert all reset | |
68 | + * RESET: <core_ddrc_rstn> DEASSERTED | |
69 | + * RESET: <aresetn> for Port 0 DEASSERT(0)ED | |
70 | + */ | |
71 | + reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000004); | |
72 | + reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000000); | |
73 | + | |
74 | + reg32_write(DDRC_DBG1(0), 0x00000000); | |
75 | + /* step4 */ | |
76 | + /* [0]dis_auto_refresh=1 */ | |
77 | + reg32_write(DDRC_RFSHCTL3(0), 0x00000011); | |
78 | + | |
79 | + /* [8]--1: lpddr4_sr allowed; [5]--1: software entry to SR */ | |
80 | + reg32_write(DDRC_PWRCTL(0), 0x000000a8); | |
81 | + | |
82 | + do { | |
83 | + tmp = reg32_read(DDRC_STAT(0)); | |
84 | + } while ((tmp & 0x33f) != 0x223); | |
85 | + | |
86 | + reg32_write(DDRC_DDR_SS_GPR0, 0x01); /* LPDDR4 mode */ | |
87 | + | |
88 | + /* step5 */ | |
89 | + reg32_write(DDRC_SWCTL(0), 0x00000000); | |
90 | + | |
91 | + /* step6 */ | |
92 | + tmp = reg32_read(DDRC_MSTR2(0)); | |
93 | + if (tmp == 0x2) { | |
94 | + reg32_write(DDRC_DFIMISC(0), 0x00000210); | |
95 | + } else if (tmp == 0x1) { | |
96 | + reg32_write(DDRC_DFIMISC(0), 0x00000110); | |
97 | + } else { | |
98 | + reg32_write(DDRC_DFIMISC(0), 0x00000010); | |
99 | + } | |
100 | + | |
101 | + /* step7 [0]--1: disable quasi-dynamic programming */ | |
102 | + reg32_write(DDRC_SWCTL(0), 0x00000001); | |
103 | + | |
104 | + /* step8 Configure LPDDR4 PHY's registers */ | |
105 | + debug("DDRINFO:ddrphy config start\n"); | |
106 | + ddr_cfg_phy(dram_timing); | |
107 | + debug("DDRINFO: ddrphy config done\n"); | |
108 | + | |
109 | + /* | |
110 | + * step14 CalBusy.0 =1, indicates the calibrator is actively | |
111 | + * calibrating. Wait Calibrating done. | |
112 | + */ | |
113 | + do { | |
114 | + tmp = reg32_read(DDRPHY_CalBusy(0)); | |
115 | + } while ((tmp & 0x1)); | |
116 | + | |
117 | + printf("DDRINFO:ddrphy calibration done\n"); | |
118 | + | |
119 | + /* step15 [0]--0: to enable quasi-dynamic programming */ | |
120 | + reg32_write(DDRC_SWCTL(0), 0x00000000); | |
121 | + | |
122 | + /* step16 */ | |
123 | + tmp = reg32_read(DDRC_MSTR2(0)); | |
124 | + if (tmp == 0x2) { | |
125 | + reg32_write(DDRC_DFIMISC(0), 0x00000230); | |
126 | + } else if (tmp == 0x1) { | |
127 | + reg32_write(DDRC_DFIMISC(0), 0x00000130); | |
128 | + } else { | |
129 | + reg32_write(DDRC_DFIMISC(0), 0x00000030); | |
130 | + } | |
131 | + | |
132 | + /* step17 [0]--1: disable quasi-dynamic programming */ | |
133 | + reg32_write(DDRC_SWCTL(0), 0x00000001); | |
134 | + /* step18 wait DFISTAT.dfi_init_complete to 1 */ | |
135 | + do { | |
136 | + tmp = reg32_read(DDRC_DFISTAT(0)); | |
137 | + } while ((tmp & 0x1) == 0x0); | |
138 | + | |
139 | + /* step19 */ | |
140 | + reg32_write(DDRC_SWCTL(0), 0x00000000); | |
141 | + | |
142 | + /* step20~22 */ | |
143 | + tmp = reg32_read(DDRC_MSTR2(0)); | |
144 | + if (tmp == 0x2) { | |
145 | + reg32_write(DDRC_DFIMISC(0), 0x00000210); | |
146 | + /* set DFIMISC.dfi_init_complete_en again */ | |
147 | + reg32_write(DDRC_DFIMISC(0), 0x00000211); | |
148 | + } else if (tmp == 0x1) { | |
149 | + reg32_write(DDRC_DFIMISC(0), 0x00000110); | |
150 | + /* set DFIMISC.dfi_init_complete_en again */ | |
151 | + reg32_write(DDRC_DFIMISC(0), 0x00000111); | |
152 | + } else { | |
153 | + /* clear DFIMISC.dfi_init_complete_en */ | |
154 | + reg32_write(DDRC_DFIMISC(0), 0x00000010); | |
155 | + /* set DFIMISC.dfi_init_complete_en again */ | |
156 | + reg32_write(DDRC_DFIMISC(0), 0x00000011); | |
157 | + } | |
158 | + | |
159 | + /* step23 [5]selfref_sw=0; */ | |
160 | + reg32_write(DDRC_PWRCTL(0), 0x00000008); | |
161 | + /* step24 sw_done=1 */ | |
162 | + reg32_write(DDRC_SWCTL(0), 0x00000001); | |
163 | + | |
164 | + /* step25 wait SWSTAT.sw_done_ack to 1 */ | |
165 | + do { | |
166 | + tmp = reg32_read(DDRC_SWSTAT(0)); | |
167 | + } while ((tmp & 0x1) == 0x0); | |
168 | + | |
169 | +#ifdef DFI_BUG_WR | |
170 | + reg32_write(DDRC_DFIPHYMSTR(0), 0x00000001); | |
171 | +#endif | |
172 | + /* wait STAT.operating_mode([1:0] for ddr3) to normal state */ | |
173 | + do { | |
174 | + tmp = reg32_read(DDRC_STAT(0)); | |
175 | + } while ((tmp & 0x3) != 0x1); | |
176 | + | |
177 | + /* step26 */ | |
178 | + reg32_write(DDRC_RFSHCTL3(0), 0x00000010); | |
179 | + | |
180 | + /* enable port 0 */ | |
181 | + reg32_write(DDRC_PCTRL_0(0), 0x00000001); | |
182 | + printf("DDRINFO: ddrmix config done\n"); | |
183 | + | |
184 | + /* save the dram timing config into memory */ | |
185 | + dram_config_save(dram_timing, CONFIG_SAVED_DRAM_TIMING_BASE); | |
186 | +} |