blob: 172e260a55d926483587e772800f11dea8ac83a9 [file] [log] [blame]
Ye Li56499f62021-08-07 16:01:11 +08001// SPDX-License-Identifier: GPL-2.0+ OR MIT
2/*
3 * Copyright 2021 NXP
4 */
Ye Li56499f62021-08-07 16:01:11 +08005#include <asm/io.h>
6#include <asm/arch/clock.h>
7#include <asm/arch/ddr.h>
8#include <asm/arch/imx-regs.h>
9
10#define DENALI_CTL_00 (DDR_CTL_BASE_ADDR + 4 * 0)
11#define CTL_START 0x1
12
13#define DENALI_CTL_03 (DDR_CTL_BASE_ADDR + 4 * 3)
14#define DENALI_CTL_197 (DDR_CTL_BASE_ADDR + 4 * 197)
15#define DENALI_CTL_250 (DDR_CTL_BASE_ADDR + 4 * 250)
16#define DENALI_CTL_251 (DDR_CTL_BASE_ADDR + 4 * 251)
17#define DENALI_CTL_266 (DDR_CTL_BASE_ADDR + 4 * 266)
18#define DFI_INIT_COMPLETE 0x2
19
20#define DENALI_CTL_614 (DDR_CTL_BASE_ADDR + 4 * 614)
21#define DENALI_CTL_615 (DDR_CTL_BASE_ADDR + 4 * 615)
22
23#define DENALI_PI_00 (DDR_PI_BASE_ADDR + 4 * 0)
24#define PI_START 0x1
25
26#define DENALI_PI_04 (DDR_PI_BASE_ADDR + 4 * 4)
27#define DENALI_PI_11 (DDR_PI_BASE_ADDR + 4 * 11)
28#define DENALI_PI_12 (DDR_PI_BASE_ADDR + 4 * 12)
29#define DENALI_CTL_23 (DDR_CTL_BASE_ADDR + 4 * 23)
30#define DENALI_CTL_25 (DDR_CTL_BASE_ADDR + 4 * 25)
31
32#define DENALI_PHY_1624 (DDR_PHY_BASE_ADDR + 4 * 1624)
Jacky Bai09e3e132023-01-31 16:42:29 +080033#define DENALI_PHY_1625 (DDR_PHY_BASE_ADDR + 4 * 1625)
Ye Li56499f62021-08-07 16:01:11 +080034#define DENALI_PHY_1537 (DDR_PHY_BASE_ADDR + 4 * 1537)
35#define PHY_FREQ_SEL_MULTICAST_EN(X) ((X) << 8)
36#define PHY_FREQ_SEL_INDEX(X) ((X) << 16)
37
38#define DENALI_PHY_1547 (DDR_PHY_BASE_ADDR + 4 * 1547)
39#define DENALI_PHY_1555 (DDR_PHY_BASE_ADDR + 4 * 1555)
40#define DENALI_PHY_1564 (DDR_PHY_BASE_ADDR + 4 * 1564)
41#define DENALI_PHY_1565 (DDR_PHY_BASE_ADDR + 4 * 1565)
42
43static void ddr_enable_pll_bypass(void)
44{
45 u32 reg_val;
46
47 /* PI_INIT_LVL_EN=0x0 (DENALI_PI_04) */
48 reg_val = readl(DENALI_PI_04) & ~0x1;
49 writel(reg_val, DENALI_PI_04);
50
51 /* PI_FREQ_MAP=0x1 (DENALI_PI_12) */
52 writel(0x1, DENALI_PI_12);
53
54 /* PI_INIT_WORK_FREQ=0x0 (DENALI_PI_11) */
55 reg_val = readl(DENALI_PI_11) & ~(0x1f << 8);
56 writel(reg_val, DENALI_PI_11);
57
58 /* DFIBUS_FREQ_INIT=0x0 (DENALI_CTL_23) */
59 reg_val = readl(DENALI_CTL_23) & ~(0x3 << 24);
60 writel(reg_val, DENALI_CTL_23);
61
62 /* PHY_LP4_BOOT_DISABLE=0x0 (DENALI_PHY_1547) */
63 reg_val = readl(DENALI_PHY_1547) & ~(0x1 << 8);
64 writel(reg_val, DENALI_PHY_1547);
65
66 /* PHY_PLL_BYPASS=0x1 (DENALI_PHY_1624) */
67 reg_val = readl(DENALI_PHY_1624) | 0x1;
68 writel(reg_val, DENALI_PHY_1624);
69
70 /* PHY_LP4_BOOT_PLL_BYPASS to 0x1 (DENALI_PHY_1555) */
71 reg_val = readl(DENALI_PHY_1555) | 0x1;
72 writel(reg_val, DENALI_PHY_1555);
73
74 /* FREQ_CHANGE_TYPE_F0 = 0x0/FREQ_CHANGE_TYPE_F1 = 0x1/FREQ_CHANGE_TYPE_F2 = 0x2 */
75 reg_val = 0x020100;
76 writel(reg_val, DENALI_CTL_25);
77}
78
79int ddr_calibration(unsigned int fsp_table[3])
80{
81 u32 reg_val;
82 u32 int_status_init, phy_freq_req, phy_freq_type;
83 u32 lock_0, lock_1, lock_2;
84 u32 freq_chg_pt, freq_chg_cnt;
Jacky Bai09e3e132023-01-31 16:42:29 +080085 u32 is_lpddr4 = 0;
Ye Li56499f62021-08-07 16:01:11 +080086
87 if (IS_ENABLED(CONFIG_IMX8ULP_DRAM_PHY_PLL_BYPASS)) {
88 ddr_enable_pll_bypass();
89 freq_chg_cnt = 0;
90 freq_chg_pt = 0;
91 } else {
Jacky Bai09e3e132023-01-31 16:42:29 +080092 reg_val = (readl(DENALI_CTL_00)>>8)&0xf;
93 if(reg_val == 0x7) {
94 /* LPDDR3 type */
95 set_ddr_clk(fsp_table[1] >> 1);
96 freq_chg_cnt = 0;
97 freq_chg_pt = 0;
98 } else if(reg_val == 0xb) {
99 /* LPDDR4/4x type */
100 is_lpddr4 = 1;
101 reg_val = readl(DENALI_CTL_250);
102 if (((reg_val >> 16) & 0x3) == 1)
103 freq_chg_cnt = 2;
104 else
105 freq_chg_cnt = 3;
Ye Li56499f62021-08-07 16:01:11 +0800106
Jacky Bai09e3e132023-01-31 16:42:29 +0800107 reg_val = readl(DENALI_PI_12);
108 if(reg_val == 0x3)
109 freq_chg_pt = 1;
110 else if(reg_val == 0x7)
111 freq_chg_pt = 2;
112 else {
113 printf("frequency map(0x%x) is wrong, please check!\r\n", reg_val);
114 return -1;
115 }
Ye Li56499f62021-08-07 16:01:11 +0800116 } else {
Jacky Bai09e3e132023-01-31 16:42:29 +0800117 printf("Incorrect DDR type configured!\r\n");
Ye Li56499f62021-08-07 16:01:11 +0800118 return -1;
119 }
120 }
121
122 /* Assert PI_START parameter and then assert START parameter in Controller. */
123 reg_val = readl(DENALI_PI_00) | PI_START;
124 writel(reg_val, DENALI_PI_00);
125
126 reg_val = readl(DENALI_CTL_00) | CTL_START;
127 writel(reg_val, DENALI_CTL_00);
128
129 /* Poll for init_done_bit in Controller interrupt status register (INT_STATUS_INIT) */
130 do {
131 if (!freq_chg_cnt) {
132 int_status_init = (readl(DENALI_CTL_266) >> 8) & 0xff;
133 /* DDR subsystem is ready for traffic. */
134 if (int_status_init & DFI_INIT_COMPLETE) {
135 debug("complete\n");
136 break;
137 }
138 }
139
140 /*
141 * During leveling, PHY will request for freq change and SoC clock logic
142 * should provide requested frequency
143 * Polling SIM LPDDR_CTRL2 Bit phy_freq_chg_req until be 1'b1
144 */
145 reg_val = readl(AVD_SIM_LPDDR_CTRL2);
Ye Li7f5dd942021-10-29 09:46:34 +0800146 /* DFS interrupt is set */
147 phy_freq_req = ((reg_val >> 7) & 0x1) && ((reg_val >> 15) & 0x1);
Ye Li56499f62021-08-07 16:01:11 +0800148 if (phy_freq_req) {
149 phy_freq_type = reg_val & 0x1F;
150 if (phy_freq_type == 0x00) {
151 debug("Poll for freq_chg_req on SIM register and change to F0 frequency.\n");
152 set_ddr_clk(fsp_table[phy_freq_type] >> 1);
153
154 /* Write 1'b1 at LPDDR_CTRL2 bit phy_freq_cfg_ack */
155 reg_val = readl(AVD_SIM_LPDDR_CTRL2);
156 writel(reg_val | (0x1 << 6), AVD_SIM_LPDDR_CTRL2);
157 } else if (phy_freq_type == 0x01) {
158 debug("Poll for freq_chg_req on SIM register and change to F1 frequency.\n");
159 set_ddr_clk(fsp_table[phy_freq_type] >> 1);
160
161 /* Write 1'b1 at LPDDR_CTRL2 bit phy_freq_cfg_ack */
162 reg_val = readl(AVD_SIM_LPDDR_CTRL2);
163 writel(reg_val | (0x1 << 6), AVD_SIM_LPDDR_CTRL2);
164 if (freq_chg_pt == 1)
165 freq_chg_cnt--;
166 } else if (phy_freq_type == 0x02) {
167 debug("Poll for freq_chg_req on SIM register and change to F2 frequency.\n");
168 set_ddr_clk(fsp_table[phy_freq_type] >> 1);
169
170 /* Write 1'b1 at LPDDR_CTRL2 bit phy_freq_cfg_ack */
171 reg_val = readl(AVD_SIM_LPDDR_CTRL2);
172 writel(reg_val | (0x1 << 6), AVD_SIM_LPDDR_CTRL2);
173 if (freq_chg_pt == 2)
174 freq_chg_cnt--;
175 }
Ye Li7f5dd942021-10-29 09:46:34 +0800176
177 /* Hardware clear the ack on falling edge of LPDDR_CTRL2:phy_freq_chg_reg */
178 /* Ensure the ack is clear before starting to poll request again */
179 while ((readl(AVD_SIM_LPDDR_CTRL2) & BIT(6)))
180 ;
Ye Li56499f62021-08-07 16:01:11 +0800181 }
182 } while (1);
183
184 /* Check PLL lock status */
185 lock_0 = readl(DENALI_PHY_1564) & 0xffff;
186 lock_1 = (readl(DENALI_PHY_1564) >> 16) & 0xffff;
187 lock_2 = readl(DENALI_PHY_1565) & 0xffff;
188
189 if ((lock_0 & 0x3) != 0x3 || (lock_1 & 0x3) != 0x3 || (lock_2 & 0x3) != 0x3) {
190 debug("De-Skew PLL failed to lock\n");
191 debug("lock_0=0x%x, lock_1=0x%x, lock_2=0x%x\n", lock_0, lock_1, lock_2);
192 return -1;
193 }
194
195 debug("De-Skew PLL is locked and ready\n");
Jacky Bai09e3e132023-01-31 16:42:29 +0800196
197 /* Change LPDDR4 FREQ1 to bypass mode if it is lower than 200MHz */
198 if(is_lpddr4 && fsp_table[1] < 400) {
199 /* Set FREQ1 to bypass mode */
200 reg_val = PHY_FREQ_SEL_MULTICAST_EN(0) | PHY_FREQ_SEL_INDEX(0);
201 writel(reg_val, DENALI_PHY_1537);
202
203 /* PHY_PLL_BYPASS=0x1 (DENALI_PHY_1624) */
204 reg_val =readl(DENALI_PHY_1624) | 0x1;
205 writel(reg_val, DENALI_PHY_1624);
206
207 /* DENALI_PHY_1625: bypass mode in PHY PLL */
208 reg_val =readl(DENALI_PHY_1625) & ~0xf;
209 writel(reg_val, DENALI_PHY_1625);
210 }
211
Ye Li56499f62021-08-07 16:01:11 +0800212 return 0;
213}
214
Jacky Bai9cac6e22021-10-29 09:46:33 +0800215static void save_dram_config(struct dram_timing_info2 *timing_info, unsigned long saved_timing_base)
216{
217 int i = 0;
218 struct dram_timing_info2 *saved_timing = (struct dram_timing_info2 *)saved_timing_base;
219 struct dram_cfg_param *cfg;
220
221 saved_timing->ctl_cfg_num = timing_info->ctl_cfg_num;
222 saved_timing->phy_f1_cfg_num = timing_info->phy_f1_cfg_num;
223 saved_timing->phy_f2_cfg_num = timing_info->phy_f2_cfg_num;
224
225 /* save the fsp table */
226 for (i = 0; i < 3; i++)
227 saved_timing->fsp_table[i] = timing_info->fsp_table[i];
228
229 cfg = (struct dram_cfg_param *)(saved_timing_base +
230 sizeof(*timing_info));
231
232 /* save ctl config */
233 saved_timing->ctl_cfg = cfg;
234 for (i = 0; i < timing_info->ctl_cfg_num; i++) {
235 cfg->reg = timing_info->ctl_cfg[i].reg;
236 cfg->val = timing_info->ctl_cfg[i].val;
237 cfg++;
238 }
239
240 /* save phy f1 config */
241 saved_timing->phy_f1_cfg = cfg;
242 for (i = 0; i < timing_info->phy_f1_cfg_num; i++) {
243 cfg->reg = timing_info->phy_f1_cfg[i].reg;
244 cfg->val = timing_info->phy_f1_cfg[i].val;
245 cfg++;
246 }
247
248 /* save phy f2 config */
249 saved_timing->phy_f2_cfg = cfg;
250 for (i = 0; i < timing_info->phy_f2_cfg_num; i++) {
251 cfg->reg = timing_info->phy_f2_cfg[i].reg;
252 cfg->val = timing_info->phy_f2_cfg[i].val;
253 cfg++;
254 }
255}
256
Ye Li56499f62021-08-07 16:01:11 +0800257int ddr_init(struct dram_timing_info2 *dram_timing)
258{
259 int i;
260
261 if (IS_ENABLED(CONFIG_IMX8ULP_DRAM_PHY_PLL_BYPASS)) {
262 /* Use PLL bypass for boot freq */
263 /* Since PLL can't generate the double freq, Need ddr clock to generate it. */
264 set_ddr_clk(dram_timing->fsp_table[0]); /* Set to boot freq */
265 setbits_le32(AVD_SIM_BASE_ADDR, 0x1); /* SIM_DDR_CTRL_DIV2_EN */
266 } else {
267 set_ddr_clk(dram_timing->fsp_table[0] >> 1); /* Set to boot freq */
268 clrbits_le32(AVD_SIM_BASE_ADDR, 0x1); /* SIM_DDR_CTRL_DIV2_EN */
269 }
270
Jacky Bai9cac6e22021-10-29 09:46:33 +0800271 /* save the dram config into sram for low power mode */
272 save_dram_config(dram_timing, CONFIG_SAVED_DRAM_TIMING_BASE);
273
Ye Li56499f62021-08-07 16:01:11 +0800274 /* Initialize CTL registers */
275 for (i = 0; i < dram_timing->ctl_cfg_num; i++)
276 writel(dram_timing->ctl_cfg[i].val, (ulong)dram_timing->ctl_cfg[i].reg);
277
278 /* Initialize PI registers */
279 for (i = 0; i < dram_timing->pi_cfg_num; i++)
280 writel(dram_timing->pi_cfg[i].val, (ulong)dram_timing->pi_cfg[i].reg);
281
282 /* Write PHY regiters for all 3 frequency points (48Mhz/384Mhz/528Mhz): f1_index=0 */
283 writel(PHY_FREQ_SEL_MULTICAST_EN(1) | PHY_FREQ_SEL_INDEX(0), DENALI_PHY_1537);
284 for (i = 0; i < dram_timing->phy_f1_cfg_num; i++)
285 writel(dram_timing->phy_f1_cfg[i].val, (ulong)dram_timing->phy_f1_cfg[i].reg);
286
287 /* Write PHY regiters for freqency point 2 (528Mhz): f2_index=1 */
288 writel(PHY_FREQ_SEL_MULTICAST_EN(0) | PHY_FREQ_SEL_INDEX(1), DENALI_PHY_1537);
289 for (i = 0; i < dram_timing->phy_f2_cfg_num; i++)
290 writel(dram_timing->phy_f2_cfg[i].val, (ulong)dram_timing->phy_f2_cfg[i].reg);
291
292 /* Re-enable MULTICAST mode */
293 writel(PHY_FREQ_SEL_MULTICAST_EN(1) | PHY_FREQ_SEL_INDEX(0), DENALI_PHY_1537);
294
295 return ddr_calibration(dram_timing->fsp_table);
296}