blob: 8a8ef44ecc15a8e6b4754f30643c2d5d7e3d9fd3 [file] [log] [blame]
Jacky Baiba997cc2021-06-25 09:47:46 +08001/*
2 * Copyright 2021-2024 NXP
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
8#include <stdbool.h>
9
Jacky Bai9f6e5d92022-01-25 16:34:58 +080010#include <arch_helpers.h>
11#include <bl31/interrupt_mgmt.h>
12#include <common/runtime_svc.h>
Jacky Baiba997cc2021-06-25 09:47:46 +080013#include <lib/mmio.h>
Jacky Bai9f6e5d92022-01-25 16:34:58 +080014#include <lib/spinlock.h>
15#include <plat/common/platform.h>
16
Jacky Baiba997cc2021-06-25 09:47:46 +080017#include <platform_def.h>
18
Jacky Bai9f6e5d92022-01-25 16:34:58 +080019#include <dram.h>
Jacky Baiba997cc2021-06-25 09:47:46 +080020#include <upower_api.h>
21
22#define PHY_FREQ_SEL_INDEX(x) ((x) << 16)
23#define PHY_FREQ_MULTICAST_EN(x) ((x) << 8)
24#define DENALI_PHY_1537 U(0x5804)
25
26#define IMX_DDRC_BASE U(0x2E060000)
27#define SAVED_DRAM_DATA_BASE U(0x20055000)
28#define DENALI_CTL_144 0x240
29#define LPI_WAKEUP_EN_SHIFT U(8)
30#define IMX_LPAV_SIM_BASE 0x2DA50000
31#define LPDDR_CTRL 0x14
32#define LPDDR_AUTO_LP_MODE_DISABLE BIT(24)
33#define SOC_LP_CMD_SHIFT U(15)
34#define LPDDR_CTRL2 0x18
35
36#define DENALI_CTL_00 U(0x0)
37#define DENALI_CTL_23 U(0x5c)
38#define DFIBUS_FREQ_INIT_SHIFT U(24)
39#define TSREF2PHYMSTR_SHIFT U(8)
40#define TSREF2PHYMSTR_MASK GENMASK(13, 8)
41
42#define DENALI_CTL_24 U(0x60)
43#define DENALI_CTL_25 U(0x64)
44
45#define DENALI_CTL_93 U(0x174)
46#define PWRUP_SREFRESH_EXIT BIT(0)
47
48#define DENALI_CTL_127 U(0x1fc)
49#define PHYMSTR_TRAIN_AFTER_INIT_COMPLETE BIT(16)
50
51#define DENALI_CTL_147 U(0x24c)
52#define DENALI_CTL_153 U(0x264)
53#define PCPCS_PD_EN BIT(8)
54
55#define DENALI_CTL_249 U(0x3E4)
56#define DENALI_CTL_266 U(0x428)
57
58#define DENALI_PHY_1547 U(0x582c)
59#define PHY_LP4_BOOT_DISABLE BIT(8)
60
61#define DENALI_PHY_1559 U(0x585c)
62#define DENALI_PHY_1590 U(0x58D8)
63
64#define DENALI_PI_00 U(0x2000)
65#define DENALI_PI_04 U(0x2010)
66#define DENALI_PI_52 U(0x20D0)
67#define DENALI_PI_26 U(0x2068)
68#define DENALI_PI_33 U(0x2084)
69#define DENALI_PI_65 U(0x2104)
70#define DENALI_PI_77 U(0x2134)
71#define DENALI_PI_134 U(0x2218)
72#define DENALI_PI_131 U(0x220C)
73#define DENALI_PI_132 U(0x2210)
74#define DENALI_PI_134 U(0x2218)
75#define DENALI_PI_137 U(0x2224)
76#define DENALI_PI_174 U(0x22B8)
77#define DENALI_PI_175 U(0x22BC)
78#define DENALI_PI_181 U(0x22D4)
79#define DENALI_PI_182 U(0x22D8)
80#define DENALI_PI_191 U(0x22FC)
81#define DENALI_PI_192 U(0x2300)
82#define DENALI_PI_212 U(0x2350)
83#define DENALI_PI_214 U(0x2358)
84#define DENALI_PI_217 U(0x2364)
85
86#define LPDDR3_TYPE U(0x7)
87#define LPDDR4_TYPE U(0xB)
88
89extern void upower_wait_resp(void);
90
91struct dram_cfg_param {
92 uint32_t reg;
93 uint32_t val;
94};
95
96struct dram_timing_info {
97 /* ddr controller config */
98 struct dram_cfg_param *ctl_cfg;
99 unsigned int ctl_cfg_num;
100 /* pi config */
101 struct dram_cfg_param *pi_cfg;
102 unsigned int pi_cfg_num;
103 /* phy freq1 config */
104 struct dram_cfg_param *phy_f1_cfg;
105 unsigned int phy_f1_cfg_num;
106 /* phy freq2 config */
107 struct dram_cfg_param *phy_f2_cfg;
108 unsigned int phy_f2_cfg_num;
109 /* initialized drate table */
110 unsigned int fsp_table[3];
111};
112
113#define CTL_NUM U(680)
114#define PI_NUM U(298)
115#define PHY_NUM U(1654)
116#define PHY_DIFF_NUM U(49)
117struct dram_cfg {
118 uint32_t ctl_cfg[CTL_NUM];
119 uint32_t pi_cfg[PI_NUM];
120 uint32_t phy_full[PHY_NUM];
121 uint32_t phy_diff[PHY_DIFF_NUM];
122};
123
124struct dram_timing_info *info;
125struct dram_cfg *dram_timing_cfg;
126
127/* mark if dram cfg is already saved */
128static bool dram_cfg_saved;
129static uint32_t dram_class;
130
131/* PHY register index for frequency diff */
132uint32_t freq_specific_reg_array[PHY_DIFF_NUM] = {
13390, 92, 93, 96, 97, 100, 101, 102, 103, 104, 114,
134346, 348, 349, 352, 353, 356, 357, 358, 359, 360,
135370, 602, 604, 605, 608, 609, 612, 613, 614, 615,
136616, 626, 858, 860, 861, 864, 865, 868, 869, 870,
137871, 872, 882, 1063, 1319, 1566, 1624, 1625
138};
139
Jacky Bai9f6e5d92022-01-25 16:34:58 +0800140/* lock used for DDR DVFS */
141spinlock_t dfs_lock;
142static volatile uint32_t core_count;
143static volatile bool in_progress;
Jacky Bai8d07de32022-05-27 15:33:40 +0800144static volatile bool sys_dvfs;
Jacky Bai9f6e5d92022-01-25 16:34:58 +0800145static int num_fsp;
146
Jacky Baiba997cc2021-06-25 09:47:46 +0800147static void ddr_init(void)
148{
149 unsigned int i;
150
151 /* restore the ddr ctl config */
152 for (i = 0U; i < CTL_NUM; i++) {
153 mmio_write_32(IMX_DDRC_BASE + i * 4, dram_timing_cfg->ctl_cfg[i]);
154 }
155
156 /* load the PI registers */
157 for (i = 0U; i < PI_NUM; i++) {
158 mmio_write_32(IMX_DDRC_BASE + 0x2000 + i * 4, dram_timing_cfg->pi_cfg[i]);
159 }
160
161
162 /* restore all PHY registers for all the fsp. */
163 mmio_write_32(IMX_DDRC_BASE + DENALI_PHY_1537, 0x100);
164 /* restore all the phy configs */
165 for (i = 0U; i < PHY_NUM; i++) {
166 /* skip the reserved registers space */
167 if (i >= 121U && i <= 255U) {
168 continue;
169 }
170 if (i >= 377U && i <= 511U) {
171 continue;
172 }
173 if (i >= 633U && i <= 767U) {
174 continue;
175 }
176 if (i >= 889U && i <= 1023U) {
177 continue;
178 }
179 if (i >= 1065U && i <= 1279U) {
180 continue;
181 }
182 if (i >= 1321U && i <= 1535U) {
183 continue;
184 }
185 mmio_write_32(IMX_DDRC_BASE + 0x4000 + i * 4, dram_timing_cfg->phy_full[i]);
186 }
187
188 if (dram_class == LPDDR4_TYPE) {
189 /* restore only the diff. */
190 mmio_write_32(IMX_DDRC_BASE + DENALI_PHY_1537, 0x0);
191 for (i = 0U; i < PHY_DIFF_NUM; i++) {
192 mmio_write_32(IMX_DDRC_BASE + 0x4000 + freq_specific_reg_array[i] * 4,
193 dram_timing_cfg->phy_diff[i]);
194 }
195 }
196
197 /* Re-enable MULTICAST mode */
198 mmio_write_32(IMX_DDRC_BASE + DENALI_PHY_1537, PHY_FREQ_MULTICAST_EN(1));
199}
200
201void dram_enter_retention(void)
202{
203 unsigned int i;
204
205 /* 1. config the PCC_LPDDR4[SSADO] to 2b'11 for ACK domain 0/1's STOP */
206 mmio_setbits_32(IMX_PCC5_BASE + 0x108, 0x2 << 22);
207
208 /*
209 * 2. Make sure the DENALI_CTL_144[LPI_WAKEUP_EN[5:0]] has the bit
210 * LPI_WAKEUP_EN[3] = 1b'1. This enables the option 'self-refresh
211 * long with mem and ctlr clk gating or self-refresh power-down
212 * long with mem and ctlr clk gating'
213 */
214 mmio_setbits_32(IMX_DDRC_BASE + DENALI_CTL_144, BIT(3) << LPI_WAKEUP_EN_SHIFT);
215
216 /*
217 * 3a. Config SIM_LPAV LPDDR_CTRL[LPDDR_AUTO_LP_MODE_DISABLE] to 1b'0(enable
218 * the logic to automatic handles low power entry/exit. This is the recommended
219 * option over handling through software.
220 * 3b. Config the SIM_LPAV LPDDR_CTRL[SOC_LP_CMD] to 6b'101001(encoding for
221 * self_refresh with both DDR controller and DRAM clock gate. THis is mandatory
222 * since LPPDR logic will be power gated).
223 */
224 mmio_clrbits_32(IMX_LPAV_SIM_BASE + LPDDR_CTRL, LPDDR_AUTO_LP_MODE_DISABLE);
225 mmio_clrsetbits_32(IMX_LPAV_SIM_BASE + LPDDR_CTRL,
226 0x3f << SOC_LP_CMD_SHIFT, 0x29 << SOC_LP_CMD_SHIFT);
227
228 /* Save DDR Controller & PHY config.
229 * Set PHY_FREQ_SEL_MULTICAST_EN=0 & PHY_FREQ_SEL_INDEX=1. Read and store all
230 * the PHY registers for F2 into phy_f1_cfg, then read/store the diff between
231 * F1 & F2 into phy_f2_cfg.
232 */
233 if (!dram_cfg_saved) {
234 info = (struct dram_timing_info *)SAVED_DRAM_DATA_BASE;
235 dram_timing_cfg = (struct dram_cfg *)(SAVED_DRAM_DATA_BASE +
236 sizeof(struct dram_timing_info));
237
238 /* get the dram type */
239 dram_class = mmio_read_32(IMX_DDRC_BASE + DENALI_CTL_00);
240 dram_class = (dram_class >> 8) & 0xf;
241
242 /* save the ctl registers */
243 for (i = 0U; i < CTL_NUM; i++) {
244 dram_timing_cfg->ctl_cfg[i] = mmio_read_32(IMX_DDRC_BASE + i * 4);
245 }
246 dram_timing_cfg->ctl_cfg[0] = dram_timing_cfg->ctl_cfg[0] & 0xFFFFFFFE;
247
248 /* save the PI registers */
249 for (i = 0U; i < PI_NUM; i++) {
250 dram_timing_cfg->pi_cfg[i] = mmio_read_32(IMX_DDRC_BASE + 0x2000 + i * 4);
251 }
252 dram_timing_cfg->pi_cfg[0] = dram_timing_cfg->pi_cfg[0] & 0xFFFFFFFE;
253
254 /*
255 * Read and store all PHY registers. full array is a full
256 * copy for all the setpoint
257 */
258 if (dram_class == LPDDR4_TYPE) {
259 mmio_write_32(IMX_DDRC_BASE + DENALI_PHY_1537, 0x10000);
260 for (i = 0U; i < PHY_NUM; i++) {
261 /* Make sure MULTICASE is enabled */
262 if (i == 1537U) {
263 dram_timing_cfg->phy_full[i] = 0x100;
264 } else {
265 dram_timing_cfg->phy_full[i] = mmio_read_32(IMX_DDRC_BASE + 0x4000 + i * 4);
266 }
267 }
268
269 /*
270 * set PHY_FREQ_SEL_MULTICAST_EN=0 & PHY_FREQ_SEL_INDEX=0.
271 * Read and store only the diff.
272 */
273 mmio_write_32(IMX_DDRC_BASE + DENALI_PHY_1537, 0x0);
274 /* save only the frequency based diff config to save memory */
275 for (i = 0U; i < PHY_DIFF_NUM; i++) {
276 dram_timing_cfg->phy_diff[i] = mmio_read_32(IMX_DDRC_BASE + 0x4000 +
277 freq_specific_reg_array[i] * 4);
278 }
279 } else {
280 /* LPDDR3, only f1 need to save */
281 for (i = 0U; i < info->phy_f1_cfg_num; i++) {
282 info->phy_f1_cfg[i].val = mmio_read_32(info->phy_f1_cfg[i].reg);
283 }
284 }
285
286 dram_cfg_saved = true;
287 }
288}
289
290void dram_exit_retention(void)
291{
292 uint32_t val;
293
294 /* 1. Config the LPAV PLL4 and DDR clock for the desired LPDDR operating frequency. */
295 mmio_setbits_32(IMX_PCC5_BASE + 0x108, BIT(30));
296
297 /* 2. Write PCC5.PCC_LPDDR4[SWRST] to 1b'1 to release LPDDR from reset. */
298 mmio_setbits_32(IMX_PCC5_BASE + 0x108, BIT(28));
299
300 /* 3. Reload the LPDDR CTL/PI/PHY register */
301 ddr_init();
302
303 if (dram_class == LPDDR4_TYPE) {
304 /* 4a. FIXME Set PHY_SET_DFI_INPUT_N parameters to 4'h1. LPDDR4 only */
305 mmio_write_32(IMX_DDRC_BASE + DENALI_PHY_1559, 0x01010101);
306
307 /*
308 * 4b. CTL PWRUP_SREFRESH_EXIT=1'b0 for disabling self refresh exit
309 * from controller.
310 */
311 /*
312 * 4c. PI_PWRUP_SELF_REF_EXIT=1, PI_MC_PWRUP_SELF_REF_EXIT=0 for enabling
313 * self refresh exit from PI
314 */
315 /* 4c. PI_INT_LVL_EN=0 to skip Initialization trainings. */
316 /*
317 * 4d. PI_WRLVL_EN_F0/1/2= PI_CALVL_EN_F0/1/2= PI_RDLVL_EN_F0/1/2=
318 * PI_RDLVL_GATE_EN_F0/1/2= PI_WDQLVL_EN_F0/1/2=0x2.
319 * Enable non initialization trainings.
320 */
321 /* 4e. PI_PWRUP_SREFRESH_EXIT_CS=0xF */
322 /* 4f. PI_DLL_RESET=0x1 */
323 mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_137, 0x1);
324 /* PI_PWRUP_SELF_REF_EXIT = 1 */
325 mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_132, 0x01000000);
326 /* PI_MC_PWRUP_SELF_REF_EXIT = 0 */
327 mmio_clrbits_32(IMX_DDRC_BASE + DENALI_PI_132, BIT(16));
328 /* PI_INT_LVL_EN = 0 */
329 mmio_clrbits_32(IMX_DDRC_BASE + DENALI_PI_04, BIT(0));
330 /* PI_WRLVL_EN_F0 = 3, PI_WRLVL_EN_F1 = 3 */
331 mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_174, 0x03030000);
332 /* PI_WRLVL_EN_F2 = 3 */
333 mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_175, 0x03);
334 /* PI_CALVL_EN_F0 = 3, PI_CALVL_EN_F1 = 3 */
335 mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_191, 0x03030000);
336 /* PI_CALVL_EN_F2 = 3 */
337 mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_192, 0x03);
338 /* PI_WDQLVL_EN_F0 = 3 */
339 mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_212, 0x300);
340 /* PI_WDQLVL_EN_F1 = 3 */
341 mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_214, 0x03000000);
342 /* PI_WDQLVL_EN_F2 = 3 */
343 mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_217, 0x300);
344 /* PI_EDLVL_EN_F0 = 3, PI_EDLVL_GATE_EN_F0 = 3 */
345 mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_181, 0x03030000);
346 /*
347 * PI_RDLVL_EN_F1 = 3, PI_RDLVL_GATE_EN_F1 = 3,
348 * PI_RDLVL_EN_F2 = 3, PI_RDLVL_GATE_EN_F2 = 3
349 */
350 mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_182, 0x03030303);
351 /* PI_PWRUP_SREFRESH_EXIT_CS = 0xF */
352 mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_134, 0x000F0000);
353 } else {
354 /* PI_DLL_RESET=1 */
355 mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_137, 0x1);
356 /* PI_PWRUP_SELF_REF_EXIT=1 */
357 mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_132, 0x01000000);
358 /* PI_MC_PWRUP_SELF_REF_EXIT=0 */
359 mmio_clrbits_32(IMX_DDRC_BASE + DENALI_PI_132, BIT(16));
360 /* PI_INT_LVL_EN=0 */
361 mmio_clrbits_32(IMX_DDRC_BASE + DENALI_PI_04, BIT(0));
362 /* PI_WRLVL_EN_F0=3 */
363 mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_174, 0x00030000);
364 /* PI_CALVL_EN_F0=3 */
365 mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_191, 0x00030000);
366 /* PI_RDLVL_EN_F0=3,PI_RDLVL_GATE_EN_F0=3 */
367 mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_181, 0x03030000);
368 /* PI_PWRUP_SREFRESH_EXIT_CS=0xF */
369 mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_134, 0x000F0000);
370 }
371
372 mmio_write_32(IMX_DDRC_BASE + DENALI_CTL_144, 0x00002D00);
373
374 /* Force in-order AXI read data */
375 mmio_write_32(IMX_DDRC_BASE + DENALI_CTL_144, 0x1);
376
377 /*
378 * Disable special R/W group switches so that R/W group placement
379 * is always at END of R/W group.
380 */
381 mmio_write_32(IMX_DDRC_BASE + DENALI_CTL_249, 0x0);
382
383 /* Reduce time for IO pad calibration */
384 mmio_write_32(IMX_DDRC_BASE + DENALI_PHY_1590, 0x01000000);
385
386 mmio_write_32(IMX_DDRC_BASE + DENALI_CTL_25, 0x00020100);
387
388 /* PD disable */
389 mmio_write_32(IMX_DDRC_BASE + DENALI_CTL_153, 0x04040000);
390 /*
391 * 5. Disable automatic LP entry and PCPCS modes LP_AUTO_ENTRY_EN
392 * to 1b'0, PCPCS_PD_EN to 1b'0
393 */
394
395 upwr_xcp_set_ddr_retention(APD_DOMAIN, 0, NULL);
396 upower_wait_resp();
397
398 if (dram_class == LPDDR4_TYPE) {
399 /* 7. Write PI START parameter to 1'b1 */
400 mmio_write_32(IMX_DDRC_BASE + DENALI_PI_00, 0x00000b01);
401
402 /* 8. Write CTL START parameter to 1'b1 */
403 mmio_write_32(IMX_DDRC_BASE + DENALI_CTL_00, 0x00000b01);
404 } else {
405 /* 7. Write PI START parameter to 1'b1 */
406 mmio_write_32(IMX_DDRC_BASE + DENALI_PI_00, 0x00000701);
407
408 /* 8. Write CTL START parameter to 1'b1 */
409 mmio_write_32(IMX_DDRC_BASE + DENALI_CTL_00, 0x00000701);
410 }
411
412 /* 9. DENALI_CTL_266: Wait for INT_STATUS_INIT=0x2 */
413 do {
414 val = (mmio_read_32(IMX_DDRC_BASE + DENALI_CTL_266) >> 8) & 0xFF;
415 } while (val != 0x2);
416
417 /*
418 * 10. Run SW trainings by setting PI_CALVL_REQ,PI_WRLVL_REQ,PI_RDLVL_GATE_REQ,
419 * PI_RDLVL_REQ,PI_WDQLVL_REQ(NA for LPDDR3) in same order.
420 */
421 if (dram_class == LPDDR4_TYPE) {
422 mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_52, 0x10000); /* CALVL */
423 mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_26, 0x100); /* WRLVL */
424 mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_33, 0x10000); /* RDGATE */
425 mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_33, 0x100); /* RDQLVL */
426 mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_65, 0x10000); /* WDQLVL */
427
428 /* 11. Wait for trainings to get complete by polling PI_INT_STATUS */
429 while ((mmio_read_32(IMX_DDRC_BASE + DENALI_PI_77) & 0x07E00000) != 0x07E00000) {
430 ;
431 }
432 } else {
433 mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_52, 0x10000); /* CALVL */
434 mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_26, 0x100); /* WRLVL */
435 mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_33, 0x10000); /* RDGATE */
436 mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_33, 0x100); /* RDQLVL */
437 while ((mmio_read_32(IMX_DDRC_BASE + DENALI_PI_77) & 0x05E00000) != 0x05E00000) {
438 ;
439 }
Jacky Bai9f6e5d92022-01-25 16:34:58 +0800440 }
441}
442
443#define LPDDR_DONE (0x1<<4)
444#define SOC_FREQ_CHG_ACK (0x1<<6)
445#define SOC_FREQ_CHG_REQ (0x1<<7)
446#define LPI_WAKEUP_EN (0x4<<8)
447#define SOC_FREQ_REQ (0x1<<11)
448
449#define LPDDR_EN_CLKGATE (0x1<<17)
450
451static void set_cgc2_ddrclk(uint8_t src, uint8_t div)
452{
453
454 /* Wait until the reg is unlocked for writing */
455 while (mmio_read_32(IMX_CGC2_BASE + 0x40) & BIT(31))
456 ;
457
458 mmio_write_32(IMX_CGC2_BASE + 0x40, (src << 28) | (div << 21));
459 /* Wait for the clock switching done */
460 while (!(mmio_read_32(IMX_CGC2_BASE + 0x40) & BIT(27)))
461 ;
462}
463static void set_ddr_clk(uint32_t ddr_freq)
464{
465 /* Disable DDR clock */
466 mmio_clrbits_32(IMX_PCC5_BASE + 0x108, BIT(30));
467 switch (ddr_freq) {
468 /* boot frequency ? */
469 case 48:
470 set_cgc2_ddrclk(2, 0);
471 break;
472 /* default bypass frequency for fsp 1 */
473 case 192:
474 set_cgc2_ddrclk(0, 1);
475 break;
476 case 384:
477 set_cgc2_ddrclk(0, 0);
478 break;
479 case 264:
480 set_cgc2_ddrclk(4, 3);
481 break;
482 case 528:
483 set_cgc2_ddrclk(4, 1);
484 break;
485 default:
486 break;
487 }
488 /* Enable DDR clock */
489 mmio_setbits_32(IMX_PCC5_BASE + 0x108, BIT(30));
490
491 /* Wait until the reg is unlocked for writing */
492 while (mmio_read_32(IMX_CGC2_BASE + 0x40) & BIT(31)) {
493 ;
494 }
495}
496
497#define AVD_SIM_LPDDR_CTRL (IMX_LPAV_SIM_BASE + 0x14)
498#define AVD_SIM_LPDDR_CTRL2 (IMX_LPAV_SIM_BASE + 0x18)
499#define MAX_FSP_NUM U(3)
500#define DDR_DFS_GET_FSP_COUNT 0x10
501#define DDR_BYPASS_DRATE U(400)
502
Jacky Bai8d07de32022-05-27 15:33:40 +0800503extern int upower_pmic_i2c_write(uint32_t reg_addr, uint32_t reg_val);
504
Jacky Bai9f6e5d92022-01-25 16:34:58 +0800505/* Normally, we only switch frequency between 1(bypass) and 2(highest) */
506int lpddr4_dfs(uint32_t freq_index)
507{
508 uint32_t lpddr_ctrl, lpddr_ctrl2;
509 uint32_t ddr_ctl_144;
510
511 /*
512 * Valid index: 0 to 2
513 * index 0: boot frequency
514 * index 1: bypass frequency
515 * index 2: highest frequency
516 */
517 if (freq_index > 2U) {
518 return -1;
519 }
520
Jacky Bai8d07de32022-05-27 15:33:40 +0800521 /*
522 * increase the voltage to 1.1V firstly before increase frequency
523 * and APD enter OD mode
524 */
525 if (freq_index == 2U && sys_dvfs) {
526 upower_pmic_i2c_write(0x22, 0x28);
527 }
528
Jacky Bai9f6e5d92022-01-25 16:34:58 +0800529 /* Enable LPI_WAKEUP_EN */
530 ddr_ctl_144 = mmio_read_32(IMX_DDRC_BASE + DENALI_CTL_144);
531 mmio_setbits_32(IMX_DDRC_BASE + DENALI_CTL_144, LPI_WAKEUP_EN);
532
533 /* put DRAM into long self-refresh & clock gating */
534 lpddr_ctrl = mmio_read_32(AVD_SIM_LPDDR_CTRL);
535 lpddr_ctrl = (lpddr_ctrl & ~((0x3f << 15) | (0x3 << 9))) | (0x28 << 15) | (freq_index << 9);
536 mmio_write_32(AVD_SIM_LPDDR_CTRL, lpddr_ctrl);
537
538 /* Gating the clock */
539 lpddr_ctrl2 = mmio_read_32(AVD_SIM_LPDDR_CTRL2);
540 mmio_setbits_32(AVD_SIM_LPDDR_CTRL2, LPDDR_EN_CLKGATE);
541
542 /* Request frequency change */
543 mmio_setbits_32(AVD_SIM_LPDDR_CTRL, SOC_FREQ_REQ);
544
545 do {
546 lpddr_ctrl = mmio_read_32(AVD_SIM_LPDDR_CTRL);
547 if (lpddr_ctrl & SOC_FREQ_CHG_REQ) {
548 /* Bypass mode */
549 if (info->fsp_table[freq_index] < DDR_BYPASS_DRATE) {
550 /* Change to PLL bypass mode */
551 mmio_write_32(IMX_LPAV_SIM_BASE, 0x1);
552 /* change the ddr clock source & frequency */
553 set_ddr_clk(info->fsp_table[freq_index]);
554 } else {
555 /* Change to PLL unbypass mode */
556 mmio_write_32(IMX_LPAV_SIM_BASE, 0x0);
557 /* change the ddr clock source & frequency */
558 set_ddr_clk(info->fsp_table[freq_index] >> 1);
559 }
560
561 mmio_clrsetbits_32(AVD_SIM_LPDDR_CTRL, SOC_FREQ_CHG_REQ, SOC_FREQ_CHG_ACK);
562 continue;
563 }
564 } while ((lpddr_ctrl & LPDDR_DONE) != 0); /* several try? */
565
566 /* restore the original setting */
567 mmio_write_32(IMX_DDRC_BASE + DENALI_CTL_144, ddr_ctl_144);
568 mmio_write_32(AVD_SIM_LPDDR_CTRL2, lpddr_ctrl2);
569
570 /* Check the DFS result */
571 lpddr_ctrl = mmio_read_32(AVD_SIM_LPDDR_CTRL) & 0xF;
572 if (lpddr_ctrl != 0U) {
573 /* Must be something wrong, return failure */
574 return -1;
Jacky Baiba997cc2021-06-25 09:47:46 +0800575 }
Jacky Bai9f6e5d92022-01-25 16:34:58 +0800576
Jacky Bai8d07de32022-05-27 15:33:40 +0800577 /* decrease the BUCK3 voltage after frequency changed to lower
578 * and APD in ND_MODE
579 */
580 if (freq_index == 1U && sys_dvfs) {
581 upower_pmic_i2c_write(0x22, 0x20);
582 }
583
Jacky Bai9f6e5d92022-01-25 16:34:58 +0800584 /* DFS done successfully */
585 return 0;
586}
587
588/* for the non-primary core, waiting for DFS done */
589static uint64_t waiting_dvfs(uint32_t id, uint32_t flags,
590 void *handle, void *cookie)
591{
592 uint32_t irq;
593
594 irq = plat_ic_acknowledge_interrupt();
595 if (irq < 1022U) {
596 plat_ic_end_of_interrupt(irq);
597 }
598
599 /* set the WFE done status */
600 spin_lock(&dfs_lock);
601 core_count++;
602 dsb();
603 spin_unlock(&dfs_lock);
604
605 while (in_progress) {
606 wfe();
607 }
608
609 return 0;
610}
611
612int dram_dvfs_handler(uint32_t smc_fid, void *handle,
613 u_register_t x1, u_register_t x2, u_register_t x3)
614{
615 unsigned int fsp_index = x1;
616 uint32_t online_cpus = x2 - 1;
617 uint64_t mpidr = read_mpidr_el1();
618 unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
619
620 /* Get the number of FSPs */
621 if (x1 == DDR_DFS_GET_FSP_COUNT) {
622 SMC_RET2(handle, num_fsp, info->fsp_table[1]);
623 }
624
625 /* start lpddr frequency scaling */
626 in_progress = true;
Jacky Bai8d07de32022-05-27 15:33:40 +0800627 sys_dvfs = x3 ? true : false;
Jacky Bai9f6e5d92022-01-25 16:34:58 +0800628 dsb();
629
630 /* notify other core wait for scaling done */
631 for (unsigned int i = 0; i < PLATFORM_CORE_COUNT; i++)
632 /* Skip raise SGI for current CPU */
633 if (i != cpu_id) {
634 plat_ic_raise_el3_sgi(0x8, i);
635 }
636
637 /* Make sure all the cpu in WFE */
638 while (online_cpus != core_count) {
639 ;
640 }
641
642 /* Flush the L1/L2 cache */
643 dcsw_op_all(DCCSW);
644
645 lpddr4_dfs(fsp_index);
646
647 in_progress = false;
648 core_count = 0;
649 dsb();
650 sev();
651 isb();
652
653 SMC_RET1(handle, 0);
654}
655
656void dram_init(void)
657{
658 uint32_t flags = 0;
659 uint32_t rc;
660 unsigned int i;
661
662 /* Register the EL3 handler for DDR DVFS */
663 set_interrupt_rm_flag(flags, NON_SECURE);
664 rc = register_interrupt_type_handler(INTR_TYPE_EL3, waiting_dvfs, flags);
665 if (rc) {
666 panic();
667 }
668
669 info = (struct dram_timing_info *)SAVED_DRAM_DATA_BASE;
670
671 /* Get the num of the supported Fsp */
672 for (i = 0; i < MAX_FSP_NUM; i++) {
673 if (!info->fsp_table[i]) {
674 break;
675 }
676 }
677
678 num_fsp = (i > MAX_FSP_NUM) ? MAX_FSP_NUM : i;
Jacky Baiba997cc2021-06-25 09:47:46 +0800679}