1 /*
2 * Copyright (c) 2021 Bestechnic (Shanghai) Co., Ltd. All rights reserved.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #if defined(CHIP_HAS_PSRAM) && (CHIP_PSRAM_CTRL_VER == 2 || CHIP_PSRAM_CTRL_VER == 3)
16
17 #include "plat_types.h"
18 #include "plat_addr_map.h"
19 #include "cmsis.h"
20 #include "hal_location.h"
21 #include "hal_psram.h"
22 #include "hal_timer.h"
23 #include "hal_trace.h"
24 #include "hal_cache.h"
25 #include "pmu.h"
26 #include "reg_psram_mc_v2.h"
27 #include "reg_psram_phy_v2.h"
28 #include "string.h"
29
30 #define PSRAM_RESET
31 //#define PSRAM_DUAL_8BIT
32 #ifdef CHIP_BEST2003
33 #ifndef PSRAM_APS3208K
34 #define PSRAM_WRAP_ENABLE
35 #endif
36 #endif
37
38 #ifndef PSRAM_PAGE_SIZE
39 #ifdef PSRAM_XCCELA_MODE
40 // APS128xxN APS256xxN APS512xxN
41 #define PSRAM_PAGE_SIZE 2048
42 #else /* PSRAM_XCCELA_MODE */
43 // APS3208K APS6408L
44 #define PSRAM_PAGE_SIZE 1024
45 #endif /* PSRAM_XCCELA_MODE */
46 #endif
47
48 #ifdef PSRAM_DEBUG
49 #define PSRAM_TRACE TRACE_IMM
50 #else
51 #define PSRAM_TRACE(...)
52 #endif
53
54 #ifdef PSRAM_DEBUG
55 #define PSRAM_TRACENOCRLF_NOTS REL_TRACE_NOCRLF_NOTS
56 #else
57 #define PSRAM_TRACENOCRLF_NOTS(...)
58 #endif
59
60 #define TX_FIFO_DEPTH 8
61 #define RX_FIFO_DEPTH 8
62
63 // MR0
64 #define MR0_DRIVE_STR_SHIFT 0
65 #define MR0_DRIVE_STR_MASK (0x3 << MR0_DRIVE_STR_SHIFT)
66 #define MR0_DRIVE_STR(n) BITFIELD_VAL(MR0_DRIVE_STR, n)
67 #define MR0_READ_LATENCY_SHIFT 2
68 #define MR0_READ_LATENCY_MASK (0x7 << MR0_READ_LATENCY_SHIFT)
69 #define MR0_READ_LATENCY(n) BITFIELD_VAL(MR0_READ_LATENCY, n)
70 #define MR0_LT (1 << 5)
71 #define MR0_FIXED_00_SHIFT 6
72 #define MR0_FIXED_00_MASK (0x3 << MR0_FIXED_00_SHIFT)
73 #define MR0_FIXED_00(n) BITFIELD_VAL(MR0_FIXED_00, n)
74
75 // MR1
76 #define MR1_VENDOR_ID_SHIFT 0
77 #define MR1_VENDOR_ID_MASK (0x1F << MR1_VENDOR_ID_SHIFT)
78 #define MR1_VENDOR_ID(n) BITFIELD_VAL(MR1_VENDOR_ID, n)
79 #define MR1_DENSITY_SHIFT 5
80 #define MR1_DENSITY_MASK (0x3 << MR1_DENSITY_SHIFT)
81 #define MR1_DENSITY(n) BITFIELD_VAL(MR1_DENSITY, n)
82 #define MR1_ULP (1 << 7)
83
84 // MR2
85 #define MR2_VENDOR_ID_SHIFT 0
86 #define MR2_VENDOR_ID_MASK (0x7 << MR2_VENDOR_ID_SHIFT)
87 #define MR2_VENDOR_ID(n) BITFIELD_VAL(MR2_VENDOR_ID, n)
88 #define MR2_DEV_ID_SHIFT 3
89 #define MR2_DEV_ID_MASK (0x3 << MR2_DEV_ID_SHIFT)
90 #define MR2_DEV_ID(n) BITFIELD_VAL(MR2_DEV_ID, n)
91 #define MR2_RSVD (1 << 5)
92 #define MR2_FIXED_1 (1 << 6)
93 #define MR2_GB (1 << 7)
94
95 // MR4
96 #define MR4_PASR_SHIFT 0
97 #define MR4_PASR_MASK (0x7 << MR4_PASR_SHIFT)
98 #define MR4_PASR(n) BITFIELD_VAL(MR4_PASR, n)
99 #define MR4_RF (1 << 3)
100 #define MR4_FIXED_0 (1 << 4)
101 #define MR4_WRITE_LATENCY_SHIFT 5
102 #define MR4_WRITE_LATENCY_MASK (0x7 << MR4_WRITE_LATENCY_SHIFT)
103 #define MR4_WRITE_LATENCY(n) BITFIELD_VAL(MR4_WRITE_LATENCY, n)
104
105 // MR6
106 #define MR6_RSVD_SHIFT 0
107 #define MR6_RSVD_MASK (0xF << MR6_RSVD_SHIFT)
108 #define MR6_RSVD(n) BITFIELD_VAL(MR6_RSVD, n)
109 #define MR6_HALF_SLEEP_SHIFT 4
110 #define MR6_HALF_SLEEP_MASK (0xF << MR6_HALF_SLEEP_SHIFT)
111 #define MR6_HALF_SLEEP(n) BITFIELD_VAL(MR6_HALF_SLEEP, n)
112
113 // MR8
114 #define MR8_BL_SHIFT 0
115 #define MR8_BL_MASK (0x3 << MR8_BL_SHIFT)
116 #define MR8_BL(n) BITFIELD_VAL(MR8_BL, n)
117 #define MR8_BT (1 << 2)
118 #define MR8_FIXED_0 (1 << 3)
119 #define MR8_RSVD_SHIFT 4
120 #define MR8_RSVD_MASK (0x7 << MR8_RSVD_SHIFT)
121 #define MR8_RSVD(n) BITFIELD_VAL(MR8_RSVD, n)
122 #define MR8_FIXED_00 (1 << 7)
123
124 enum PSRAM_CMD_T {
125 PSRAM_CMD_SYNC_READ = 0x00,
126 PSRAM_CMD_SYNC_WRITE = 0x80,
127 PSRAM_CMD_4BYTE_READ = 0x3F,
128 PSRAM_CMD_4BYTE_WRITE = 0xBF,
129 PSRAM_CMD_REG_READ = 0x40,
130 PSRAM_CMD_REG_WRITE = 0xC0,
131 PSRAM_CMD_GLOBAL_RESET = 0xFF,
132 };
133
134 enum CP_FSM_STATE_T {
135 CP_FSM_STATE_SELF_REFRESH = 1,
136 CP_FSM_STATE_PD = 2,
137 CP_FSM_STATE_READY = 4,
138 };
139
140 enum MEMIF_CMD_T {
141 MEMIF_NO_CMD = 0x00,
142 MEMIF_WRITE = 0x01,
143 MEMIF_READ = 0x02,
144 MEMIF_MRS = 0x05,
145 MEMIF_MRR = 0x06,
146 MEMIF_REF = 0x08,
147 MEMIF_SREF = 0x09,
148 MEMIF_PD = 0x10,
149 MEMIF_NOP = 0x20,
150 MEMIF_RST = 0xFF,
151 MEMIF_ZQCL = 0x85,
152 MEMIF_ZQCS = 0x45,
153 MEMIF_ZQCRST = 0x25,
154 MEMIF_START_CLOCK = 0x40,
155 MEMIF_STOP_CLOCK = 0x80,
156 MEMIF_NEW_CMD = 0x7F,
157 };
158
159 static struct PSRAM_MC_T *const psram_mc = (struct PSRAM_MC_T *)PSRAM_CTRL_BASE;
160 static struct PSRAM_PHY_T *const psram_phy = (struct PSRAM_PHY_T *)(PSRAM_CTRL_BASE + 0x8000);
161
162 #ifdef FPGA
163 static const uint32_t psram_cfg_clk = 20 * 1000 * 1000;
164 static const uint32_t psram_run_clk = 20 * 1000 * 1000;
165 #else /*FPGA*/
166 #if (PSRAM_SPEED != 0)
167 static const uint32_t psram_cfg_clk = 48 * 1000 * 1000;
168 static const uint32_t psram_run_clk = PSRAM_SPEED * 1000 * 1000;
169 #else
170 #error "invalid PSRAM_SPEED"
171 #endif
172 #endif /*FPGA*/
173
174 static void psram_chip_timing_config(uint32_t clk, bool psram_first);
175
hal_psramip_mc_busy(void)176 int hal_psramip_mc_busy(void)
177 {
178 return !!(psram_mc->REG_404 & PSRAM_ULP_MC_BUSY);
179 }
180
hal_psramip_wb_busy(void)181 static int hal_psramip_wb_busy(void)
182 {
183 return !!(psram_mc->REG_404 & PSRAM_ULP_MC_WB_FILL_LEVEL_MASK);
184 }
185
hal_psramip_mc_in_sleep(void)186 int hal_psramip_mc_in_sleep(void)
187 {
188 return GET_BITFIELD(psram_mc->REG_404, PSRAM_ULP_MC_CP_FSM_STATE) == CP_FSM_STATE_PD;
189 }
190
hal_psramip_rx_fifo_empty(void)191 int hal_psramip_rx_fifo_empty(void)
192 {
193 return !!(psram_mc->REG_404 & PSRAM_ULP_MC_MGR_RXFIFO_R_EMPTY);
194 }
195
hal_psramip_tx_fifo_full(void)196 int hal_psramip_tx_fifo_full(void)
197 {
198 return !!(psram_mc->REG_404 & PSRAM_ULP_MC_MGR_TXFIFO_W_FULL);
199 }
200
hal_psramip_get_rx_fifo_len(void)201 uint32_t hal_psramip_get_rx_fifo_len(void)
202 {
203 return GET_BITFIELD(psram_mc->REG_404, PSRAM_ULP_MC_MGR_RXFIFO_FULL_CNT);
204 }
205
hal_psramip_get_tx_fifo_free_len(void)206 uint32_t hal_psramip_get_tx_fifo_free_len(void)
207 {
208 return GET_BITFIELD(psram_mc->REG_404, PSRAM_ULP_MC_MGR_TXFIFO_EMPTY_CNT);
209 }
210
hal_psramip_mc_busy_wait(void)211 void hal_psramip_mc_busy_wait(void)
212 {
213 while (hal_psramip_mc_busy());
214 }
215
hal_psramip_wb_busy_wait(void)216 void hal_psramip_wb_busy_wait(void)
217 {
218 while (hal_psramip_wb_busy());
219 }
220
hal_psramip_flush_tx_fifo(void)221 void hal_psramip_flush_tx_fifo(void)
222 {
223 hal_psramip_mc_busy_wait();
224 psram_mc->REG_01C = PSRAM_ULP_MC_MGR_TX_FIFO_CLR;
225 hal_psramip_mc_busy_wait();
226 }
227
hal_psramip_flush_rx_fifo(void)228 void hal_psramip_flush_rx_fifo(void)
229 {
230 hal_psramip_mc_busy_wait();
231 psram_mc->REG_01C = PSRAM_ULP_MC_MGR_RX_FIFO_CLR;
232 hal_psramip_mc_busy_wait();
233 }
234
hal_psramip_flush_all_fifo(void)235 void hal_psramip_flush_all_fifo(void)
236 {
237 hal_psramip_mc_busy_wait();
238 psram_mc->REG_01C = PSRAM_ULP_MC_MGR_TX_FIFO_CLR | PSRAM_ULP_MC_MGR_RX_FIFO_CLR;
239 hal_psramip_mc_busy_wait();
240 }
241
hal_psramip_xfer_addr_len(uint32_t addr,uint32_t len)242 void hal_psramip_xfer_addr_len(uint32_t addr, uint32_t len)
243 {
244 psram_mc->REG_008 = addr;
245 psram_mc->REG_00C = len;
246 }
247
hal_psramip_write_fifo(uint32_t * data,uint32_t len)248 void hal_psramip_write_fifo(uint32_t *data, uint32_t len)
249 {
250 for (uint32_t i = 0; i < len; i++) {
251 psram_mc->REG_014 = *data++;
252 }
253 }
254
hal_psramip_read_fifo(uint32_t * data,uint32_t len)255 void hal_psramip_read_fifo(uint32_t *data, uint32_t len)
256 {
257 for (uint32_t i = 0; i < len; i++) {
258 *data++ = psram_mc->REG_018;
259 }
260 }
261
hal_psramip_set_reg_data_mask(void)262 void hal_psramip_set_reg_data_mask(void)
263 {
264 #ifdef PSRAM_DUAL_8BIT
265 psram_mc->REG_010 = 0xFC;
266 #else
267 psram_mc->REG_010 = 0xFE;
268 #endif
269 }
270
hal_psramip_set_mem_data_mask(void)271 void hal_psramip_set_mem_data_mask(void)
272 {
273 psram_mc->REG_010 = 0;
274 }
275
hal_psramip_set_cmd(enum MEMIF_CMD_T cmd)276 void hal_psramip_set_cmd(enum MEMIF_CMD_T cmd)
277 {
278 psram_mc->REG_004 = cmd;
279 }
280
psram_read_reg(uint32_t reg,uint32_t * val)281 POSSIBLY_UNUSED void psram_read_reg(uint32_t reg, uint32_t *val)
282 {
283 hal_psramip_flush_all_fifo();
284 hal_psramip_xfer_addr_len(reg, 1);
285 hal_psramip_set_cmd(MEMIF_MRR);
286 while (hal_psramip_rx_fifo_empty());
287 hal_psramip_read_fifo(val, 1);
288 }
289
psram_send_cmd_reg(enum MEMIF_CMD_T cmd,uint32_t reg,uint32_t val)290 static void psram_send_cmd_reg(enum MEMIF_CMD_T cmd, uint32_t reg, uint32_t val)
291 {
292 #ifdef PSRAM_DUAL_8BIT
293 val &= 0xFF;
294 val |= (val << 8);
295 #endif
296 hal_psramip_flush_all_fifo();
297 //hal_psramip_set_reg_data_mask();
298 hal_psramip_write_fifo(&val, 1);
299 hal_psramip_xfer_addr_len(reg, 1);
300 hal_psramip_set_cmd(cmd);
301 while (hal_psramip_get_tx_fifo_free_len() != TX_FIFO_DEPTH);
302 hal_psramip_mc_busy_wait();
303 //hal_psramip_set_mem_data_mask();
304 }
305
psram_write_reg(uint32_t reg,uint32_t val)306 static void psram_write_reg(uint32_t reg, uint32_t val)
307 {
308 psram_send_cmd_reg(MEMIF_MRS, reg, val);
309 }
310
psram_single_cmd(enum MEMIF_CMD_T cmd)311 static void psram_single_cmd(enum MEMIF_CMD_T cmd)
312 {
313 hal_psramip_flush_all_fifo();
314 hal_psramip_set_cmd(cmd);
315 hal_psramip_mc_busy_wait();
316 }
317
psram_reset(void)318 static POSSIBLY_UNUSED void psram_reset(void)
319 {
320 psram_single_cmd(MEMIF_RST);
321 #ifdef PSRAM_APS3208K
322 hal_sys_timer_delay_us(1);
323 psram_single_cmd(MEMIF_RST);
324 #endif
325 }
326
psram_set_timing(uint32_t clk)327 static void psram_set_timing(uint32_t clk)
328 {
329 uint32_t reg;
330 uint32_t val;
331 #ifdef PSRAM_XCCELA_MODE
332 reg = 8;
333 #ifdef PSRAM_WRAP_ENABLE
334 // Wrap 32
335 val = MR8_BL(1);
336 #else
337 // Wrap 1k
338 val = MR8_BL(0x3);
339 #endif
340 psram_write_reg(reg, val);
341
342 reg = 0;
343 if (clk <= 66000000) {
344 val = 0;
345 } else if (clk <= 109000000) {
346 val = 1;
347 } else if (clk <= 133000000) {
348 val = 2;
349 } else if (clk <= 166000000) {
350 val = 3;
351 } else {
352 val = 4;
353 }
354 // Latency type: Variable
355 val = MR0_DRIVE_STR(3) | MR0_READ_LATENCY(val);
356 psram_write_reg(reg, val);
357
358 reg = 4;
359 if (clk <= 66000000) {
360 val = 0;
361 } else if (clk <= 109000000) {
362 val = 4;
363 } else if (clk <= 133000000) {
364 val = 2;
365 } else if (clk <= 166000000) {
366 val = 6;
367 } else {
368 val = 1;
369 }
370 //Always 4x Refresh
371 val = MR4_PASR(0) | MR4_WRITE_LATENCY(val);
372 psram_write_reg(reg, val);
373 #else /*PSRAM_XCCELA_MODE*/
374 #ifndef PSRAM_APS3208K
375 reg = 8;
376 #ifdef PSRAM_WRAP_ENABLE
377 // Wrap 32
378 val = MR8_BL(1);
379 #else
380 // Wrap 1k
381 val = MR8_BL(0x3);
382 #endif
383 psram_write_reg(reg, val);
384 #endif /* PSRAM_APS3208K */
385 reg = 0;
386 if (clk <= 66000000) {
387 val = 2;
388 } else if (clk <= 109000000) {
389 val = 3;
390 } else if (clk <= 133000000) {
391 val = 4;
392 } else if (clk <= 166000000) {
393 val = 5;
394 } else {
395 val = 6;
396 }
397 // Latency type: Variable
398 val = MR0_DRIVE_STR(3) | MR0_READ_LATENCY(val);
399 psram_write_reg(reg, val);
400
401 reg = 4;
402 if (clk <= 166000000) {
403 val = 0;
404 } else {
405 val = 4;
406 }
407 //Fast Refresh,
408 val = MR4_PASR(0) | MR4_WRITE_LATENCY(val);
409 psram_write_reg(reg, val);
410 #endif /*PSRAM_XCCELA_MODE*/
411 }
412
hal_psram_phy_read_reg(__I uint32_t * addr)413 static uint32_t hal_psram_phy_read_reg(__I uint32_t *addr)
414 {
415 #if defined(CHIP_BEST2003) || defined(CHIP_BEST2006)
416 *addr;
417 #endif
418 return *addr;
419 }
420
hal_psram_phy_dll_config(uint32_t clk)421 static void hal_psram_phy_dll_config(uint32_t clk)
422 {
423 uint32_t phy_clk;
424 uint32_t range;
425 uint32_t val;
426
427 val = hal_psram_phy_read_reg(&psram_phy->REG_050);
428 val &= ~PSRAM_ULP_PHY_REG_DLL_RESETB | PSRAM_ULP_PHY_REG_DLL_CK_RDY;
429 psram_phy->REG_050 = val;
430 phy_clk = clk;
431 if (phy_clk <= 100000000 / 2) {
432 range = 3;
433 } else if (phy_clk <= 150000000 / 2) {
434 range = 2;
435 } else if (phy_clk <= 300000000 / 2) {
436 range = 1;
437 } else {
438 range = 1;
439 }
440 val = SET_BITFIELD(val, PSRAM_ULP_PHY_REG_DLL_RANGE, range);
441 psram_phy->REG_050 = val;
442 hal_sys_timer_delay_us(100);
443 val |= PSRAM_ULP_PHY_REG_DLL_RESETB | PSRAM_ULP_PHY_REG_DLL_CK_RDY;
444 psram_phy->REG_050 = val;
445 hal_sys_timer_delay_us(100);
446 }
447
hal_psram_phy_init(uint32_t clk)448 static void hal_psram_phy_init(uint32_t clk)
449 {
450 uint32_t val;
451 val = hal_psram_phy_read_reg(&psram_phy->REG_048);
452 val |= PSRAM_ULP_PHY_REG_LDO_PU | PSRAM_ULP_PHY_REG_LDO_PRECHARGE;
453 psram_phy->REG_048 = val;
454 hal_sys_timer_delay_us(100);
455
456 val &= ~PSRAM_ULP_PHY_REG_LDO_PRECHARGE;
457 val = SET_BITFIELD(val, PSRAM_ULP_PHY_REG_LDO_IEN1, 0xd);
458 val = SET_BITFIELD(val, PSRAM_ULP_PHY_REG_LDO_IEN2, 0x7);
459 val = SET_BITFIELD(val, PSRAM_ULP_PHY_REG_LDO_VTUNE, 0x2);
460 psram_phy->REG_048 = val;
461 hal_sys_timer_delay_us(100);
462
463 val = hal_psram_phy_read_reg(&psram_phy->REG_04C);
464 val |= PSRAM_ULP_PHY_REG_PSRAM_PU;
465 //val = SET_BITFIELD(val, PSRAM_ULP_PHY_REG_PSRAM_SWRC, 0x3);
466 val = SET_BITFIELD(val, PSRAM_ULP_PHY_REG_PSRAM_TXDRV, 0x3);
467 psram_phy->REG_04C = val;
468 hal_sys_timer_delay_us(100);
469
470 val = hal_psram_phy_read_reg(&psram_phy->REG_050);
471 val |= PSRAM_ULP_PHY_REG_DLL_PU;
472 val = SET_BITFIELD(val, PSRAM_ULP_PHY_REG_DLL_SWRC, 0x0);
473 val &= ~PSRAM_ULP_PHY_REG_BYPASS_DECIMATION;
474 psram_phy->REG_050 = val;
475 hal_sys_timer_delay_us(100);
476
477 val |= PSRAM_ULP_PHY_REG_DLL_RESETB;
478 psram_phy->REG_050 = val;
479 hal_sys_timer_delay_us(100);
480
481 hal_psram_phy_dll_config(clk);
482 hal_sys_timer_delay_us(500);
483 }
hal_psram_phy_sleep()484 POSSIBLY_UNUSED void hal_psram_phy_sleep()
485 {
486 uint32_t val;
487
488 val = hal_psram_phy_read_reg(&psram_phy->REG_04C);
489 val &= ~PSRAM_ULP_PHY_REG_PSRAM_PU;
490 psram_phy->REG_04C = val;
491
492 val = hal_psram_phy_read_reg(&psram_phy->REG_050);
493 val &= ~PSRAM_ULP_PHY_REG_DLL_PU;
494 psram_phy->REG_050 = val;
495
496 val = hal_psram_phy_read_reg(&psram_phy->REG_048);
497 val &= ~PSRAM_ULP_PHY_REG_LDO_PU;
498 psram_phy->REG_048 = val;
499 }
500
hal_psram_digphy_init()501 static void hal_psram_digphy_init()
502 {
503 #if CHIP_PSRAM_CTRL_VER >= 3
504 uint32_t val;
505 val = hal_psram_phy_read_reg(&psram_phy->REG_004);
506 #ifdef PSRAM_XCCELA_MODE
507 val |= PSRAM_ULP_PHY_ADDR_4BYTES_EN | PSRAM_ULP_PHY_DQS_DM_MERGE_EN;
508 val &= ~PSRAM_ULP_PHY_PHY_DUMMY_CYC_EN;
509 #endif
510 val |= PSRAM_ULP_PHY_CTRL_DELAY(1);
511 val &= ~PSRAM_ULP_PHY_PHY_DLY_AUTO_EN;
512 psram_phy->REG_004 = val;
513 #endif
514 }
hal_psram_phy_wakeup()515 POSSIBLY_UNUSED static void hal_psram_phy_wakeup()
516 {
517 uint32_t val;
518 val = hal_psram_phy_read_reg(&psram_phy->REG_048);
519 val |= PSRAM_ULP_PHY_REG_LDO_PU | PSRAM_ULP_PHY_REG_LDO_PRECHARGE;
520 psram_phy->REG_048 = val;
521 hal_sys_timer_delay_us(10);
522
523 val &= ~PSRAM_ULP_PHY_REG_LDO_PRECHARGE;
524 val = SET_BITFIELD(val, PSRAM_ULP_PHY_REG_LDO_IEN1, 0xd);
525 val = SET_BITFIELD(val, PSRAM_ULP_PHY_REG_LDO_IEN2, 0x7);
526 val = SET_BITFIELD(val, PSRAM_ULP_PHY_REG_LDO_VTUNE, 0x2);
527 psram_phy->REG_048 = val;
528
529 val = hal_psram_phy_read_reg(&psram_phy->REG_04C);
530 val |= PSRAM_ULP_PHY_REG_PSRAM_PU;
531 //val = SET_BITFIELD(val, PSRAM_ULP_PHY_REG_PSRAM_SWRC, 0x3);
532 val = SET_BITFIELD(val, PSRAM_ULP_PHY_REG_PSRAM_TXDRV, 0x3);
533 psram_phy->REG_04C = val;
534
535 val = hal_psram_phy_read_reg(&psram_phy->REG_050);
536 val |= PSRAM_ULP_PHY_REG_DLL_PU;
537 //val = SET_BITFIELD(val, PSRAM_ULP_PHY_REG_DLL_SWRC, 0x3);
538 psram_phy->REG_050 = val;
539 hal_sys_timer_delay_us(2);
540
541 val |= PSRAM_ULP_PHY_REG_DLL_RESETB;
542 psram_phy->REG_050 = val;
543 hal_sys_timer_delay_us(20);
544
545 do {
546 val = hal_psram_phy_read_reg(&psram_phy->REG_058);
547 } while ((val & PSRAM_ULP_PHY_DLL_LOCK) == 0);
548 }
hal_psram_mc_set_timing(uint32_t clk,bool init)549 static void hal_psram_mc_set_timing(uint32_t clk, bool init)
550 {
551 uint32_t val;
552 #ifdef PSRAM_XCCELA_MODE
553 if (init) {
554 val = PSRAM_ULP_MC_WRITE_LATENCY(1);
555 } else {
556 if (clk <= 66000000) {
557 val = PSRAM_ULP_MC_WRITE_LATENCY(3);
558 } else if (clk <= 109000000) {
559 val = PSRAM_ULP_MC_WRITE_LATENCY(4);
560 } else if (clk <= 133000000) {
561 val = PSRAM_ULP_MC_WRITE_LATENCY(5);
562 } else if (clk <= 166000000) {
563 val = PSRAM_ULP_MC_WRITE_LATENCY(6);
564 } else {
565 val = PSRAM_ULP_MC_WRITE_LATENCY(7);
566 }
567 }
568 psram_mc->REG_028 = val;
569 if (clk <= 66000000) {
570 val = PSRAM_ULP_MC_READ_LATENCY(3);
571 } else if (clk <= 109000000) {
572 val = PSRAM_ULP_MC_READ_LATENCY(4);
573 } else if (clk <= 133000000) {
574 val = PSRAM_ULP_MC_READ_LATENCY(5);
575 } else if (clk <= 166000000) {
576 val = PSRAM_ULP_MC_READ_LATENCY(6);
577 } else {
578 val = PSRAM_ULP_MC_READ_LATENCY(7);
579 }
580 psram_mc->REG_02C = val;
581 // tCPH >= 24 ns
582 val = (clk / 1000000 * 24 + (1000 - 1)) / 1000;
583 psram_mc->REG_058 = PSRAM_ULP_MC_T_CPHR(val);
584 psram_mc->REG_060 = PSRAM_ULP_MC_T_CPHW(val);
585 psram_mc->REG_068 = PSRAM_ULP_MC_T_MRR(val);
586 psram_mc->REG_06C = PSRAM_ULP_MC_T_MRS(val);
587 #else /*PSRAM_XCCELA_MODE*/
588 if (clk <= 166000000) {
589 val = PSRAM_ULP_MC_WRITE_LATENCY(0);
590 } else {
591 val = PSRAM_ULP_MC_WRITE_LATENCY(2);
592 }
593 psram_mc->REG_028 = val;
594 if (clk <= 66000000) {
595 val = PSRAM_ULP_MC_READ_LATENCY(2);
596 } else if (clk <= 109000000) {
597 val = PSRAM_ULP_MC_READ_LATENCY(3);
598 } else if (clk <= 133000000) {
599 val = PSRAM_ULP_MC_READ_LATENCY(4);
600 } else if (clk <= 166000000) {
601 val = PSRAM_ULP_MC_READ_LATENCY(5);
602 } else {
603 val = PSRAM_ULP_MC_READ_LATENCY(6);
604 }
605 psram_mc->REG_02C = val;
606 // tCPH
607 val = 2;
608 psram_mc->REG_058 = PSRAM_ULP_MC_T_CPHR(val);
609 psram_mc->REG_068 = PSRAM_ULP_MC_T_MRR(val);
610 val = 6;
611 psram_mc->REG_060 = PSRAM_ULP_MC_T_CPHW(val);
612 #if CHIP_PSRAM_CTRL_VER == 2
613 val += 1;
614 #endif
615 psram_mc->REG_06C = PSRAM_ULP_MC_T_MRS(val);
616 #endif /*PSRAM_XCCELA_MODE*/
617 // tRC >= 55 ns
618 val = (clk / 1000000 * 55 + (1000 - 1)) / 1000;
619 psram_mc->REG_050 = PSRAM_ULP_MC_T_RC(val);
620 // tCEM <= 2.5 us
621 val = clk / 1000000 * 25 / 10;
622 psram_mc->REG_070 = PSRAM_ULP_MC_T_CEM(val);
623 // tRST >= 2 us
624 val = clk / 1000000 * 2 + 1;
625 psram_mc->REG_074 = PSRAM_ULP_MC_T_RST(val);
626 // tHS >= 2 us
627 val = clk / 1000000 * 2 + 1;
628 psram_mc->REG_080 = PSRAM_ULP_MC_T_HS(val);
629 // tXPHS in [60 ns, 2 us]
630 val = (clk / 1000000 * 60 + (1000 - 1)) / 1000;
631 psram_mc->REG_084 = PSRAM_ULP_MC_T_XPHS(val);
632 // tXHS >= 100 us
633 val = clk / 1000000 * 100 + 1;
634 psram_mc->REG_088 = PSRAM_ULP_MC_T_XHS(val);
635 psram_mc->REG_09C = PSRAM_ULP_MC_WR_DMY_CYC(1);
636 // NOP dummy cycles, same as tXPHS in [60 ns, 2 us]
637 val = (clk / 1000000 * 60 + (1000 - 1)) / 1000;
638 psram_mc->REG_0A0 = PSRAM_ULP_MC_STOP_CLK_IN_NOP |
639 #ifdef PSRAM_XCCELA_MODE
640 PSRAM_ULP_MC_STOP_CLK_IN_TCPH |
641 #endif
642 PSRAM_ULP_MC_NOP_DMY_CYC(val);
643 psram_mc->REG_0A4 = PSRAM_ULP_MC_QUEUE_IDLE_CYCLE(5000);
644 }
645
hal_psram_phy_wait_lock()646 static void hal_psram_phy_wait_lock()
647 {
648 #ifndef PROGRAMMER
649 uint32_t val;
650 uint32_t val_50;
651 uint32_t count = 0;
652 val = hal_psram_phy_read_reg(&psram_phy->REG_048);
653 val_50 = hal_psram_phy_read_reg(&psram_phy->REG_050);
654 #endif
655 while (1) {
656 uint32_t val_58;
657 val_58 = hal_psram_phy_read_reg(&psram_phy->REG_058);
658 if ((val_58 & PSRAM_ULP_PHY_DLL_LOCK))
659 break;
660 #ifndef PROGRAMMER
661 if (count++ > 20) {
662 if (GET_BITFIELD(val, PSRAM_ULP_PHY_REG_LDO_VTUNE) == 0x2) {
663 val = SET_BITFIELD(val, PSRAM_ULP_PHY_REG_LDO_VTUNE, 0x1);
664 psram_phy->REG_048 = val;
665 } else if (GET_BITFIELD(val, PSRAM_ULP_PHY_REG_LDO_VTUNE) == 0x1) {
666 val = SET_BITFIELD(val, PSRAM_ULP_PHY_REG_LDO_VTUNE, 0x2);
667 psram_phy->REG_048 = val;
668 if (GET_BITFIELD(val_50, PSRAM_ULP_PHY_REG_DLL_RANGE) == 0x1) {
669 val_50 = SET_BITFIELD(val_50, PSRAM_ULP_PHY_REG_DLL_RANGE, 0x2);
670 psram_phy->REG_050 = val_50;
671 }
672 }
673 count = 0;
674 }
675 #endif
676 hal_sys_timer_delay_us(100);
677 }
678 }
679
680 POSSIBLY_UNUSED
hal_psram_init_calib(void)681 static void hal_psram_init_calib(void)
682 {
683 uint32_t val;
684 uint32_t delay;
685
686 hal_psram_phy_wait_lock();
687 val = hal_psram_phy_read_reg(&psram_phy->REG_058);
688 delay = GET_BITFIELD(val, PSRAM_ULP_PHY_DLL_DLY_IN);
689 //ASSERT(delay < (PSRAM_ULP_PHY_DLL_DLY_IN_MASK >> PSRAM_ULP_PHY_DLL_DLY_IN_SHIFT),
690 // "%s: Bad DLL_DLY_IN=0x%X reg=0x%08X", __func__, delay, psram_phy->REG_058);
691
692 delay /= 2;
693 psram_phy->REG_054 = PSRAM_ULP_PHY_REG_PSRAM_TX_CEB_DLY(delay) | PSRAM_ULP_PHY_REG_PSRAM_TX_CLK_DLY(delay) |
694 PSRAM_ULP_PHY_REG_PSRAM_TX_DQS_DLY(delay) | PSRAM_ULP_PHY_REG_PSRAM_RX_DQS_DLY(delay);
695 hal_sys_timer_delay_us(100);
696 }
697
hal_psram_mc_init(uint32_t clk)698 static void hal_psram_mc_init(uint32_t clk)
699 {
700 uint32_t val = 0;
701 #if CHIP_PSRAM_CTRL_VER >= 3
702 #if defined(PSRAM_DUAL_8BIT)
703 val |= PSRAM_ULP_MC_CHIP_BIT;
704 #elif defined(PSRAM_X16_MODE)
705 val |= PSRAM_ULP_MC_CHIP_X16;
706 #endif
707 #ifdef PSRAM_SQPI_MODE
708 val |= PSRAM_ULP_MC_SQPI_MODE;
709 val |= (PSRAM_ULP_PHY_IDLE_DQ_OEN | PSRAM_ULP_PHY_IDLE_DQS_OEN);
710 #else /* PSRAM_SQPI_MODE */
711 val |= PSRAM_ULP_MC_OPI_MODE;
712 val = SET_BITFIELD(val, PSRAM_ULP_MC_CHIP_CA_PATTERN, 0x1);
713 #endif /* PSRAM_SQPI_MODE */
714 #else /* CHIP_PSRAM_CTRL_VER == 2 */
715 #if defined(PSRAM_DUAL_8BIT)
716 val |= PSRAM_ULP_MC_CHIP_BIT;
717 #endif
718 #endif /* CHIP_PSRAM_CTRL_VER >= 3 */
719 psram_mc->REG_000 = val;
720 psram_mc->REG_020 = 0;
721 psram_mc->REG_024 =
722 #if CHIP_PSRAM_CTRL_VER >= 3
723 //PSRAM_ULP_MC_ENTRY_SLEEP_IDLE |
724 #endif
725 PSRAM_ULP_MC_AUTOWAKEUP_EN |
726 PSRAM_ULP_MC_PD_MR(6) | PSRAM_ULP_MC_PD_CMD(0xF0);
727 #ifdef PSRAM_WRAP_ENABLE
728 // Burst len: 32 bytes, page: 1K
729 val = PSRAM_ULP_MC_BURST_LENGTH(1);
730 #else
731 if (PSRAM_PAGE_SIZE == 512) {
732 val = PSRAM_ULP_MC_BURST_LENGTH(7);
733 } else if (PSRAM_PAGE_SIZE == 1024) {
734 val = PSRAM_ULP_MC_BURST_LENGTH(4);
735 } else if (PSRAM_PAGE_SIZE == 2048) {
736 val = PSRAM_ULP_MC_BURST_LENGTH(5);
737 } else {
738 // 4K
739 val = PSRAM_ULP_MC_BURST_LENGTH(6);
740 }
741 #endif /* PSRAM_WRAP_ENABLE */
742 if (PSRAM_PAGE_SIZE == 512) {
743 val |= PSRAM_ULP_MC_PAGE_BOUNDARY(3);
744 } else if (PSRAM_PAGE_SIZE == 1024) {
745 val |= PSRAM_ULP_MC_PAGE_BOUNDARY(0);
746 } else if (PSRAM_PAGE_SIZE == 2048) {
747 val |= PSRAM_ULP_MC_PAGE_BOUNDARY(1);
748 } else {
749 // 4K
750 val |= PSRAM_ULP_MC_PAGE_BOUNDARY(2);
751 }
752 psram_mc->REG_034 = val;
753 // AHB bus width: 32 bits
754 psram_mc->REG_038 = 0;
755 // Write buffer level with high priority: 0~7
756 #if CHIP_PSRAM_CTRL_VER == 2
757 psram_mc->REG_03C = PSRAM_ULP_MC_HIGH_PRI_LEVEL(1);
758 #else
759 psram_mc->REG_03C = PSRAM_ULP_MC_HIGH_PRI_LEVEL(4);
760 #endif
761 #ifdef PSRAM_WRAP_ENABLE
762 psram_mc->REG_040 = PSRAM_ULP_MC_CP_WRAP_EN;
763 #else
764 psram_mc->REG_040 = PSRAM_ULP_MC_WRAP_CRT_RET_EN;
765 #endif
766 psram_mc->REG_044 = 0;
767 psram_mc->REG_048 = 0;
768
769 hal_psramip_set_reg_data_mask();
770 hal_sys_timer_delay_us(100);
771
772 hal_psram_mc_set_timing(clk, true);
773 hal_sys_timer_delay_us(100);
774
775 psram_mc->REG_400 = PSRAM_ULP_MC_INIT_COMPLETE;
776 hal_sys_timer_delay_us(100);
777 }
778
hal_psram_sleep(void)779 void hal_psram_sleep(void)
780 {
781 hal_psramip_mc_busy_wait();
782 if (!hal_psramip_mc_in_sleep()) {
783 #if CHIP_PSRAM_CTRL_VER >= 3
784 //psram_mc->REG_024 &= ~PSRAM_ULP_MC_ENTRY_SLEEP_IDLE;
785 #endif
786 hal_psramip_mc_busy_wait();
787 #if CHIP_PSRAM_CTRL_VER >= 3
788 #ifdef PSRAM_XCCELA_MODE
789 int val = psram_mc->REG_028;
790 psram_mc->REG_028 = PSRAM_ULP_MC_WRITE_LATENCY(1);
791 __DSB();
792 hal_psramip_mc_busy_wait();
793 #endif /* PSRAM_XCCELA_MODE */
794 psram_write_reg(0x6, 0xF0);
795 hal_psramip_mc_busy_wait();
796 #ifdef PSRAM_XCCELA_MODE
797 psram_mc->REG_028 = val;
798 hal_psramip_mc_busy_wait();
799 #endif /* PSRAM_XCCELA_MODE */
800 #else
801 hal_psramip_set_cmd(MEMIF_PD);
802 hal_psramip_mc_busy_wait();
803 #endif
804 }
805 hal_psram_phy_sleep();
806 }
807
hal_psram_wakeup(void)808 void hal_psram_wakeup(void)
809 {
810 hal_psram_phy_wakeup();
811 hal_psramip_set_cmd(MEMIF_NOP);
812 hal_psramip_mc_busy_wait();
813 #if CHIP_PSRAM_CTRL_VER >= 3
814 //psram_mc->REG_024 |= PSRAM_ULP_MC_ENTRY_SLEEP_IDLE;
815 #endif
816 }
817
psram_chip_timing_config(uint32_t clk,bool update_psram_first)818 static void psram_chip_timing_config(uint32_t clk, bool update_psram_first)
819 {
820 enum HAL_CMU_FREQ_T freq;
821
822 if (clk <= 52000000) {
823 freq = HAL_CMU_FREQ_104M;
824 } else if (clk <= 104000000) {
825 freq = HAL_CMU_FREQ_208M;
826 } else {
827 #ifdef HAL_CMU_FREQ_390M
828 freq = HAL_CMU_FREQ_390M;
829 #else
830 freq = HAL_CMU_FREQ_208M;
831 #endif
832 }
833
834 if (update_psram_first) {
835 psram_set_timing(clk);
836 }
837
838 hal_cmu_mem_set_freq(freq);
839 hal_sys_timer_delay_us(500);
840 hal_psram_phy_dll_config(clk);
841
842 #if !defined(FPGA) && !defined(SIMU)
843 hal_psram_init_calib();
844 #endif
845 hal_psram_mc_set_timing(clk, false);
846 if (!update_psram_first) {
847 psram_set_timing(clk);
848 }
849 hal_sys_timer_delay_us(100);
850 }
hal_psram_snoop_enable()851 void hal_psram_snoop_enable()
852 {
853 #if CHIP_PSRAM_CTRL_VER >= 3
854 psram_mc->REG_044 &= ~PSRAM_ULP_MC_SNP_DISABLE;
855 #endif
856 }
hal_psram_snoop_disable()857 void hal_psram_snoop_disable()
858 {
859 psram_mc->REG_044 |= PSRAM_ULP_MC_SNP_DISABLE;
860 }
861
hal_psram_write_buffer_invalidate(void)862 void hal_psram_write_buffer_invalidate(void)
863 {
864 uint32_t level;
865 uint32_t start = hal_sys_timer_get();
866
867 __DSB();
868 do {
869 level = GET_BITFIELD(psram_mc->REG_404, PSRAM_ULP_MC_WB_FILL_LEVEL);
870 if (level == 0) {
871 break;
872 }
873 } while (hal_sys_timer_get() - start < MS_TO_TICKS(1));
874
875 ASSERT(level == 0, "%s: Drain timeout: level=%u status=0x%08X", __func__, level, psram_mc->REG_404);
876
877 psram_mc->REG_044 |= PSRAM_ULP_MC_WB_INVALID;
878 __DSB();
879 }
880
hal_psram_phy_restore_range(uint32_t range)881 static void hal_psram_phy_restore_range(uint32_t range)
882 {
883 uint32_t val;
884
885 val = hal_psram_phy_read_reg(&psram_phy->REG_050);
886 val &= ~PSRAM_ULP_PHY_REG_DLL_RESETB | PSRAM_ULP_PHY_REG_DLL_CK_RDY;
887 psram_phy->REG_050 = val;
888 val = SET_BITFIELD(val, PSRAM_ULP_PHY_REG_DLL_RANGE, range);
889 psram_phy->REG_050 = val;
890 val |= PSRAM_ULP_PHY_REG_DLL_RESETB | PSRAM_ULP_PHY_REG_DLL_CK_RDY;
891 psram_phy->REG_050 = val;
892 }
893
psram_mc_reset(uint32_t range)894 static void psram_mc_reset(uint32_t range)
895 {
896 hal_cmu_reset_set(HAL_CMU_MOD_H_PSRAM);
897 hal_cmu_reset_set(HAL_CMU_MOD_O_PSRAM);
898 hal_cmu_reset_clear(HAL_CMU_MOD_H_PSRAM);
899 hal_cmu_reset_clear(HAL_CMU_MOD_O_PSRAM);
900
901 hal_cmu_mem_set_freq(HAL_CMU_FREQ_104M);
902 hal_psram_phy_init(psram_cfg_clk);
903 hal_sys_timer_delay_us(30);
904 hal_psram_mc_init(psram_cfg_clk);
905 #if !defined(FPGA) && !defined(SIMU)
906 hal_psram_init_calib();
907 #endif
908 psram_reset();
909 psram_chip_timing_config(psram_run_clk, true);
910 hal_psram_phy_restore_range(range);
911 #if !defined(FPGA) && !defined(SIMU)
912 hal_psram_init_calib();
913 #endif
914
915 hal_psram_snoop_disable();
916 }
psramphy_check_tx_ceb_valid(uint32_t range)917 POSSIBLY_UNUSED static bool psramphy_check_tx_ceb_valid(uint32_t range)
918 {
919 int retry = 2;
920 while (retry--) {
921 int count = 0;
922 hal_psramip_flush_all_fifo();
923 hal_psramip_xfer_addr_len(0x100000, 8);
924 hal_psramip_set_cmd(MEMIF_READ);
925 while (hal_psramip_rx_fifo_empty()) {
926 if (count++ > 10) {
927 //PSRAM_TRACE(1, "%s, rx fifo empty, return false", __FUNCTION__);
928 psram_mc_reset(range);
929 hal_psram_snoop_disable();
930 return false;
931 }
932 }
933 }
934 return true;
935 }
psramphy_check_tx_clk_valid(uint32_t range)936 POSSIBLY_UNUSED static bool psramphy_check_tx_clk_valid(uint32_t range)
937 {
938 uint32_t time;
939 uint32_t val;
940
941 time = hal_fast_sys_timer_get();
942 psram_mc->REG_01C = PSRAM_ULP_MC_MGR_TX_FIFO_CLR | PSRAM_ULP_MC_MGR_RX_FIFO_CLR;
943 hal_psramip_xfer_addr_len(0xAA55AA55, 1);
944 hal_psramip_set_cmd(MEMIF_READ);
945 while (hal_psramip_rx_fifo_empty()) {
946 if (FAST_TICKS_TO_US(hal_fast_sys_timer_get() - time) > 5) {
947 val = hal_psram_phy_read_reg(&psram_phy->REG_004);
948 val |= PSRAM_ULP_PHY_PHY_LOOPBACK_EN;
949 psram_phy->REG_004 = val;
950 while (hal_psramip_mc_busy());
951 val &= ~PSRAM_ULP_PHY_PHY_LOOPBACK_EN;
952 psram_phy->REG_004 = val;
953 return false;
954 }
955 }
956 return true;
957 }
psramphy_check_write_valid()958 static bool psramphy_check_write_valid()
959 {
960 uint32_t i;
961 uint32_t val, val0, val1;
962 uint32_t val2, val3;
963 volatile uint32_t *psram_base = (volatile uint32_t *)PSRAM_NC_BASE;
964 volatile uint32_t *psram_base1 = (volatile uint32_t *)(PSRAM_NC_BASE + 0x100000);
965
966 for (i = 0; i < 0x100; ++i) {
967 *(psram_base + i) = 0xffffffff;
968 *(psram_base1 + i) = 0xffffffff;
969 }
970 for (i = 0; i < 0x100; ++i) {
971 val = i & 0xFF;
972 val = val | (val << 8) | (val << 16) | (val << 24);
973 val0 = (val & 0x00FF00FF) | ((~val) & 0xFF00FF00);
974 val1 = (val & 0xFF0000FF) | ((~val) & 0x00FFFF00);
975 *(psram_base + i) = val0;
976 *(psram_base1 + i) = val1;
977 }
978
979 hal_psramip_wb_busy_wait();
980 hal_psramip_mc_busy_wait();
981 for (i = 0; i < 0x100; ++i) {
982 val = i & 0xFF;
983 val = val | (val << 8) | (val << 16) | (val << 24);
984 val0 = (val & 0x00FF00FF) | ((~val) & 0xFF00FF00);
985 val1 = (val & 0xFF0000FF) | ((~val) & 0x00FFFF00);
986 val2 = *(psram_base + i);
987 val3 = *(psram_base1 + i);
988 if (val2 != val0) {
989 //PSRAM_TRACE(3, "%s, i:%d, 0x%x, 0x%x", __FUNCTION__, i, val2, val0);
990 return false;
991 }
992 if (val3 != val1) {
993 //PSRAM_TRACE(3, "%s, i:%d, 0x%x, 0x%x", __FUNCTION__, i, val3, val1);
994 return false;
995 }
996 }
997 return true;
998 }
999
hal_psram_calib_range(uint32_t range)1000 static void hal_psram_calib_range(uint32_t range)
1001 {
1002 #define BUFFER_SIZE 0x20
1003 uint32_t val;
1004 uint32_t delay;
1005 POSSIBLY_UNUSED uint8_t tx_dqs, rx_dqs, tx_ceb, tx_clk;
1006 uint8_t inc_delay, volume;
1007 POSSIBLY_UNUSED int8_t left_bound;
1008 POSSIBLY_UNUSED int8_t right_bound;
1009 bool cali_valid[BUFFER_SIZE][BUFFER_SIZE];
1010 uint8_t cali_value[BUFFER_SIZE][BUFFER_SIZE];
1011 POSSIBLY_UNUSED bool valid_array[BUFFER_SIZE];
1012
1013 #ifdef PSRAM_WINDOW_TEST
1014 static int8_t last_left_bound = 0;
1015 static int8_t last_right_bound = 0;
1016 uint8_t dqs_point = 0;
1017 uint8_t dqs_len = 0;
1018 static uint8_t last_dqs_point = 0;
1019 static uint8_t last_dqs_len = 0;
1020 POSSIBLY_UNUSED static uint8_t cali_data[BUFFER_SIZE][BUFFER_SIZE];
1021 #endif
1022
1023 ASSERT(range <= (PSRAM_ULP_PHY_REG_DLL_RANGE_MASK >> PSRAM_ULP_PHY_REG_DLL_RANGE_SHIFT), "ERROR, bad ana phy range:%d", range);
1024
1025 val = hal_psram_phy_read_reg(&psram_phy->REG_050);
1026 val &= ~(PSRAM_ULP_PHY_REG_DLL_RESETB | PSRAM_ULP_PHY_REG_DLL_CK_RDY);
1027 psram_phy->REG_050 = val;
1028 val = SET_BITFIELD(val, PSRAM_ULP_PHY_REG_DLL_RANGE, range);
1029 psram_phy->REG_050 = val;
1030 hal_sys_timer_delay_us(100);
1031 val |= (PSRAM_ULP_PHY_REG_DLL_RESETB | PSRAM_ULP_PHY_REG_DLL_CK_RDY);
1032 psram_phy->REG_050 = val;
1033
1034 hal_sys_timer_delay_us(100);
1035 hal_sys_timer_delay_us(100);
1036
1037 hal_psram_phy_wait_lock();
1038
1039 val = hal_psram_phy_read_reg(&psram_phy->REG_058);
1040 if ((val & PSRAM_ULP_PHY_DLL_ALL_ONE)) {
1041 PSRAM_TRACE(2, "%s: all one, increase range=%d", __func__, range + 1);
1042 return hal_psram_calib_range(range + 1);
1043 }
1044
1045 delay = GET_BITFIELD(val, PSRAM_ULP_PHY_DLL_DLY_IN);
1046 PSRAM_TRACE(4, "%s, range:%d, T/4 = 0x%x(psram_phy->REG_058:0x%x)", __func__, range, delay / 2, val);
1047 #ifdef PSRAM_WINDOW_TEST
1048 TRACE_IMM(TR_ATTR_NO_LF | TR_ATTR_NO_TS | TR_ATTR_NO_ID, ", T/4=0x%02x", delay / 2);
1049 #endif
1050 if (delay > (PSRAM_ULP_PHY_REG_PSRAM_TX_DQS_DLY_MASK >> PSRAM_ULP_PHY_REG_PSRAM_TX_DQS_DLY_SHIFT) && range < 3) {
1051 PSRAM_TRACE(2, "%s: bad delay (T/2 > 0x1f). increase range=%d", __func__, range + 1);
1052 return hal_psram_calib_range(range + 1);
1053 }
1054
1055 inc_delay = delay / 8;
1056 if (inc_delay == 0)
1057 inc_delay = 1;
1058
1059 #if CHIP_PSRAM_CTRL_VER >= 3
1060 tx_ceb = delay / 2;
1061 tx_clk = delay / 2 + 2;
1062 #else /*CHIP_PSRAM_CTRL_VER == 2*/
1063 tx_ceb = delay * 5 / 6; // t/4 + t/6
1064 tx_clk = (delay * 11 + 8) / 16;// t/4 + t/8 - t/32
1065 #endif
1066
1067 volume = (PSRAM_ULP_PHY_REG_PSRAM_TX_DQS_DLY_MASK >> PSRAM_ULP_PHY_REG_PSRAM_TX_DQS_DLY_SHIFT) / inc_delay;
1068 //PSRAM_TRACE(2, "volume:%d, inc_delay:%d", volume, inc_delay);
1069
1070 #if 0
1071 //calibrate tx_ceb
1072 PSRAM_TRACE(0, "cali tx_ceb");
1073 left_bound = -1;
1074 right_bound = -1;
1075 memset(valid_array, 0, sizeof(valid_array));
1076 for (tx_ceb = 0; tx_ceb <= volume; tx_ceb++) {
1077 bool valid;
1078
1079 psram_phy->REG_054 = PSRAM_ULP_PHY_REG_PSRAM_TX_CEB_DLY(tx_ceb * inc_delay) | PSRAM_ULP_PHY_REG_PSRAM_TX_CLK_DLY(delay / 2) |
1080 PSRAM_ULP_PHY_REG_PSRAM_TX_DQS_DLY(delay / 2) | PSRAM_ULP_PHY_REG_PSRAM_RX_DQS_DLY(delay / 2);
1081
1082 valid = psramphy_check_tx_ceb_valid(range);
1083 PSRAM_TRACE(3, "%s, tx_ceb:0x%x, valid:%d", __FUNCTION__, (tx_ceb * inc_delay), valid);
1084 valid_array[tx_ceb] = valid;
1085 if (tx_ceb == 0) {
1086 if (valid) {
1087 left_bound = tx_ceb;
1088 PSRAM_TRACE(1, "left_bound:0x%x", left_bound * inc_delay);
1089 }
1090 } else if (tx_ceb == volume) {
1091 if (valid) {
1092 right_bound = tx_ceb;//find right bound
1093 PSRAM_TRACE(1, "right_bound:0x%x", right_bound * inc_delay);
1094 } else {
1095 if (valid_array[tx_ceb - 1]) {
1096 right_bound = tx_ceb - 1; //find right bound
1097 PSRAM_TRACE(1, "right_bound:0x%x", right_bound * inc_delay);
1098 }
1099 }
1100 } else {
1101 if (valid && !valid_array[tx_ceb - 1]) {
1102 left_bound = tx_ceb;//find left bound
1103 PSRAM_TRACE(1, "left_bound:0x%x", left_bound * inc_delay);
1104 } else if (!valid && valid_array[tx_ceb - 1]) {
1105 right_bound = tx_ceb - 1; //find right bound
1106 PSRAM_TRACE(1, "right_bound:0x%x", right_bound * inc_delay);
1107 break;
1108 }
1109 }
1110 }
1111 if (left_bound != -1 && right_bound != -1) { // && (right_bound-left_bound>1)) {
1112 tx_ceb = (left_bound + right_bound) / 2;
1113 PSRAM_TRACE(3, "cali tx_ceb done, tx_ceb:0x%x(0x%x-0x%x)", tx_ceb * inc_delay, left_bound * inc_delay, right_bound * inc_delay);
1114 } else {
1115 ASSERT(false, "ERROR, tx_ceb need do more cali");
1116 }
1117 tx_ceb *= inc_delay;
1118 #endif
1119 #if 0
1120 //calibrate tx_clk
1121 PSRAM_TRACE(0, "cali tx_clk");
1122 left_bound = -1;
1123 right_bound = -1;
1124 memset(valid_array, 0, sizeof(valid_array));
1125 for (tx_clk = 0; tx_clk <= volume; tx_clk++) {
1126 bool valid;
1127
1128 psram_phy->REG_054 = PSRAM_ULP_PHY_REG_PSRAM_TX_CEB_DLY(tx_ceb) | PSRAM_ULP_PHY_REG_PSRAM_TX_CLK_DLY(tx_clk * inc_delay) |
1129 PSRAM_ULP_PHY_REG_PSRAM_TX_DQS_DLY(delay / 2) | PSRAM_ULP_PHY_REG_PSRAM_RX_DQS_DLY(delay / 2);
1130 valid = psramphy_check_tx_ceb_valid(range);
1131 //PSRAM_TRACE(3, "%s, tx_clk:0x%x, valid:%d", __FUNCTION__, (tx_clk*inc_delay), valid);
1132 valid_array[tx_clk] = valid;
1133 if (tx_clk == 0) {
1134 if (valid) {
1135 left_bound = tx_clk;
1136 PSRAM_TRACE(1, "left_bound:0x%x", left_bound * inc_delay);
1137 }
1138 } else if (tx_clk == volume) {
1139 if (valid) {
1140 right_bound = tx_clk;//find right bound
1141 PSRAM_TRACE(1, "right_bound:0x%x", right_bound * inc_delay);
1142 } else {
1143 if (valid_array[tx_clk - 1]) {
1144 right_bound = tx_clk - 1; //find right bound
1145 PSRAM_TRACE(1, "right_bound:0x%x", right_bound * inc_delay);
1146 }
1147 }
1148 } else {
1149 if (valid && !valid_array[tx_clk - 1]) {
1150 left_bound = tx_clk;//find left bound
1151 PSRAM_TRACE(1, "left_bound:0x%x", left_bound * inc_delay);
1152 } else if (!valid && valid_array[tx_clk - 1]) {
1153 right_bound = tx_clk - 1; //find right bound
1154 PSRAM_TRACE(1, "right_bound:0x%x", right_bound * inc_delay);
1155 break;
1156 }
1157 }
1158 }
1159 if (left_bound != -1 && right_bound != -1) { // && (right_bound-left_bound>1)) {
1160 tx_clk = (left_bound + right_bound) / 2;
1161 PSRAM_TRACE(3, "cali tx_clk done, tx_clk:0x%x(0x%x-0x%x)", tx_clk * inc_delay, left_bound * inc_delay, right_bound * inc_delay);
1162 } else {
1163 ASSERT(false, "ERROR, tx_clk need do more cali");
1164 }
1165 tx_clk *= inc_delay;
1166 #endif
1167
1168 #ifdef PSRAM_WINDOW_TEST //new added,Use when testing window,2021-08-28
1169 volume = (PSRAM_ULP_PHY_REG_PSRAM_TX_DQS_DLY_MASK >> PSRAM_ULP_PHY_REG_PSRAM_TX_DQS_DLY_SHIFT) / inc_delay;
1170 PSRAM_TRACE(2, "volume:%d, inc_delay:%d", volume, inc_delay);
1171
1172 //calibrate tx_clk
1173 PSRAM_TRACE(0, "cali tx_clk");
1174 left_bound = -1;
1175 right_bound = -1;
1176 memset(valid_array, 0, sizeof(valid_array));
1177 for (tx_clk = 1; tx_clk <= volume; tx_clk++) {
1178 bool valid;
1179 tx_ceb = tx_clk - 1;
1180 psram_phy->REG_054 = PSRAM_ULP_PHY_REG_PSRAM_TX_CEB_DLY(tx_ceb * inc_delay) | PSRAM_ULP_PHY_REG_PSRAM_TX_CLK_DLY(tx_clk * inc_delay) |
1181 PSRAM_ULP_PHY_REG_PSRAM_TX_DQS_DLY(delay / 2) | PSRAM_ULP_PHY_REG_PSRAM_RX_DQS_DLY(delay / 2);
1182 valid = psramphy_check_tx_clk_valid(range);
1183 //PSRAM_TRACE(3, "tx_clk:0x%x, valid:%d", (tx_clk*inc_delay), valid);
1184 valid_array[tx_clk] = valid;
1185 if (tx_clk == 1) {
1186 if (valid) {
1187 left_bound = tx_clk;
1188 PSRAM_TRACE(1, "left_bound:0x%x", left_bound * inc_delay);
1189 }
1190 } else if (tx_clk == volume) {
1191 if (valid) {
1192 right_bound = tx_clk;//find right bound
1193 PSRAM_TRACE(1, "right_bound:0x%x", right_bound * inc_delay);
1194 } else {
1195 if (valid_array[tx_clk - 1]) {
1196 right_bound = tx_clk - 1; //find right bound
1197 PSRAM_TRACE(1, "right_bound:0x%x", right_bound * inc_delay);
1198 }
1199 }
1200 } else {
1201 if (valid && !valid_array[tx_clk - 1]) {
1202 left_bound = tx_clk;//find left bound
1203 PSRAM_TRACE(1, "left_bound:0x%x", left_bound * inc_delay);
1204 } else if (!valid && valid_array[tx_clk - 1]) {
1205 right_bound = tx_clk - 1; //find right bound
1206 PSRAM_TRACE(1, "right_bound:0x%x", right_bound * inc_delay);
1207 break;
1208 }
1209 }
1210 }
1211 if (left_bound != -1 && right_bound != -1) {// && (right_bound-left_bound>1)) {
1212 tx_clk = (left_bound + right_bound) / 2;
1213 PSRAM_TRACE(3, "cali tx_clk done, tx_clk:0x%x(0x%x-0x%x)", tx_clk * inc_delay, left_bound * inc_delay, right_bound * inc_delay);
1214
1215 #ifdef PSRAM_WINDOW_TEST
1216 if ((last_left_bound != left_bound) || (last_right_bound != right_bound)) {
1217 last_left_bound = left_bound;
1218 last_right_bound = right_bound;
1219 TRACE_IMM(TR_ATTR_NO_LF | TR_ATTR_NO_TS | TR_ATTR_NO_ID, ", tx_clk:0x%02x(0x%02x-0x%02x)", tx_clk * inc_delay, left_bound * inc_delay, right_bound * inc_delay);
1220 } else {
1221 TRACE_IMM(TR_ATTR_NO_LF | TR_ATTR_NO_TS | TR_ATTR_NO_ID, ", **********************");
1222 }
1223 #endif
1224 } else {
1225 ASSERT(false, "ERROR, tx_clk need do more cali");
1226 }
1227 tx_ceb = (tx_clk - 1) * inc_delay;
1228 tx_clk = tx_clk * inc_delay;
1229 #endif
1230
1231 PSRAM_TRACE(2, "tx_ceb:0x%x, tx_clk:0x%x", tx_ceb, tx_clk);
1232
1233 volume = MIN(delay, (PSRAM_ULP_PHY_REG_PSRAM_TX_DQS_DLY_MASK >> PSRAM_ULP_PHY_REG_PSRAM_TX_DQS_DLY_SHIFT)) / inc_delay;
1234 PSRAM_TRACE(2, "volume:%d, inc_delay:%d", volume, inc_delay);
1235
1236 //calibrate tx_dqs and rx_dqs
1237 uint8_t all_valid = 1;
1238 memset(cali_valid, 0, sizeof(cali_valid));
1239 for (tx_dqs = 0; tx_dqs <= volume; tx_dqs++) {
1240 for (rx_dqs = 0; rx_dqs <= volume; rx_dqs++) {
1241 #ifdef PSRAM_XCCELA_MODE
1242 psram_phy->REG_054 = PSRAM_ULP_PHY_REG_PSRAM_TX_CEB_DLY(tx_ceb) | PSRAM_ULP_PHY_REG_PSRAM_TX_CLK_DLY(tx_dqs * inc_delay) |
1243 PSRAM_ULP_PHY_REG_PSRAM_TX_DQS_DLY(0) | PSRAM_ULP_PHY_REG_PSRAM_RX_DQS_DLY(rx_dqs * inc_delay);
1244 #else
1245 psram_phy->REG_054 = PSRAM_ULP_PHY_REG_PSRAM_TX_CEB_DLY(tx_ceb) | PSRAM_ULP_PHY_REG_PSRAM_TX_CLK_DLY(tx_clk) |
1246 PSRAM_ULP_PHY_REG_PSRAM_TX_DQS_DLY(tx_dqs * inc_delay) | PSRAM_ULP_PHY_REG_PSRAM_RX_DQS_DLY(rx_dqs * inc_delay);
1247 #endif
1248 cali_valid[tx_dqs][rx_dqs] = psramphy_check_write_valid();
1249 //PSRAM_TRACE(3, "tx_dqs:0x%x, rx_dqs:0x%x, valid:%d", tx_dqs*inc_delay, rx_dqs*inc_delay, cali_valid[tx_dqs][rx_dqs]);
1250 if (cali_valid[tx_dqs][rx_dqs] == false)
1251 all_valid = 0;
1252 }
1253 }
1254
1255 if (all_valid && range < (PSRAM_ULP_PHY_DLL_DLY_IN_MASK >> PSRAM_ULP_PHY_DLL_DLY_IN_SHIFT)) {
1256 //PSRAM_TRACE(2, "%s: all valid increase range=%d", __func__, range+1);
1257 //return hal_psram_calib_range(range+1);
1258 }
1259
1260 memset(cali_value, 0, sizeof(cali_value));
1261 PSRAM_TRACENOCRLF_NOTS(0, "\r\n\r\n ---------------------------------------------------------------------- \r\n");
1262 PSRAM_TRACENOCRLF_NOTS(0, " rx_dqs");
1263 for (tx_dqs = 0; tx_dqs <= volume; tx_dqs++) {
1264 PSRAM_TRACENOCRLF_NOTS(1, " %2d ", tx_dqs * inc_delay);
1265 }
1266 PSRAM_TRACENOCRLF_NOTS(0, "\r\n");
1267 for (tx_dqs = 0; tx_dqs <= volume; tx_dqs++) {
1268 PSRAM_TRACENOCRLF_NOTS(1, "tx_dqs:%2d ", tx_dqs * inc_delay);
1269 for (rx_dqs = 0; rx_dqs <= volume; rx_dqs++) {
1270 PSRAM_TRACENOCRLF_NOTS(1, " %d ", cali_valid[tx_dqs][rx_dqs]);
1271 if (cali_valid[tx_dqs][rx_dqs]) {
1272 uint8_t len_from_zero;
1273 int8_t p;
1274 p = tx_dqs;
1275 while (p >= 0) {
1276 if (cali_valid[p][rx_dqs] == false)
1277 break;
1278 p--;
1279 }
1280 len_from_zero = tx_dqs - p;
1281 cali_value[tx_dqs][rx_dqs] = len_from_zero;
1282
1283 p = tx_dqs;
1284 while (p <= volume) {
1285 if (cali_valid[p][rx_dqs] == false)
1286 break;
1287 p++;
1288 }
1289 len_from_zero = p - tx_dqs;
1290 cali_value[tx_dqs][rx_dqs] = MIN(cali_value[tx_dqs][rx_dqs], len_from_zero);
1291
1292 p = rx_dqs;
1293 while (p >= 0) {
1294 if (cali_valid[tx_dqs][p] == false)
1295 break;
1296 p--;
1297 }
1298 len_from_zero = rx_dqs - p;
1299 cali_value[tx_dqs][rx_dqs] = MIN(cali_value[tx_dqs][rx_dqs], len_from_zero);
1300
1301 p = rx_dqs;
1302 while (p <= volume) {
1303 if (cali_valid[tx_dqs][p] == false)
1304 break;
1305 p++;
1306 }
1307 len_from_zero = p - rx_dqs;
1308 cali_value[tx_dqs][rx_dqs] = MIN(cali_value[tx_dqs][rx_dqs], len_from_zero);
1309 }
1310 }
1311 PSRAM_TRACENOCRLF_NOTS(0, "\r\n");
1312 }
1313 PSRAM_TRACENOCRLF_NOTS(0, " -------------------------------------------------------------------------- \r\n");
1314
1315 #ifdef PSRAM_WINDOW_TEST
1316 //Processing window data
1317 uint8_t cp_volume = volume + 1;
1318 uint8_t enable_clear_circle = 0;
1319 uint8_t enable_print_window = 0;
1320 uint8_t rows;
1321
1322 #if 1 //Window inner bag 0 test,2021-08-30
1323 #define HW_READ_REG(_Reg) (*((volatile uint32_t*)(_Reg)))
1324 #define HW_WRITE_REG(_Reg,_Value) (*((volatile uint32_t*)(_Reg)) = (uint32_t)(_Value))
1325 if (HW_READ_REG(0x400000F4) == 0xCAFE) {
1326 HW_WRITE_REG(0x400000F4, 0x9A55);
1327 cali_valid[4][4] = 0;//Central point clear
1328 }
1329 #endif
1330
1331 for (tx_dqs = 0; tx_dqs < cp_volume; tx_dqs++) {
1332 for (rx_dqs = 0; rx_dqs < cp_volume; rx_dqs++) {
1333 cali_data[tx_dqs][rx_dqs] = cali_valid[tx_dqs][rx_dqs] + '0';
1334 }
1335 }
1336
1337 if (cp_volume % 2) {
1338 rows = cp_volume / 2;
1339 } else {
1340 rows = cp_volume / 2 - 1;
1341 }
1342 for (tx_dqs = 0; tx_dqs < rows; tx_dqs++) {
1343 //Check the starting line
1344 for (rx_dqs = tx_dqs; rx_dqs < cp_volume - tx_dqs; rx_dqs++) {
1345 if (cali_data[tx_dqs][rx_dqs] == '0') {
1346 break;
1347 }
1348 }
1349
1350 if (rx_dqs >= cp_volume - tx_dqs) {
1351 //Check the end of the line
1352 for (rx_dqs = tx_dqs; rx_dqs < cp_volume - tx_dqs; rx_dqs++) {
1353 if (cali_data[volume - tx_dqs][rx_dqs] == '0') {
1354 break;
1355 }
1356 }
1357 if (rx_dqs >= cp_volume - tx_dqs) {
1358 //Check the starting column
1359 for (rx_dqs = tx_dqs; rx_dqs < cp_volume - tx_dqs; rx_dqs++) {
1360 if (cali_data[rx_dqs][tx_dqs] == '0') {
1361 break;
1362 }
1363 }
1364 if (rx_dqs >= cp_volume - tx_dqs) {
1365 //Check the end of the column
1366 for (rx_dqs = tx_dqs; rx_dqs < cp_volume - tx_dqs; rx_dqs++) {
1367 if (cali_data[rx_dqs][volume - tx_dqs] == '0') {
1368 break;
1369 }
1370 }
1371 if (rx_dqs >= cp_volume - tx_dqs) {
1372 enable_clear_circle = 0;
1373 } else {
1374 enable_clear_circle = 1;
1375 }
1376 } else {
1377 enable_clear_circle = 1;
1378 }
1379 } else {
1380 enable_clear_circle = 1;
1381 }
1382 } else {
1383 enable_clear_circle = 1;
1384 }
1385
1386 //The current line has 0, directly clear the current circle
1387 if (enable_clear_circle) {
1388 enable_clear_circle = 0;
1389
1390 //clear the starting line
1391 for (rx_dqs = tx_dqs; rx_dqs < cp_volume - tx_dqs; rx_dqs++) {
1392 cali_data[tx_dqs][rx_dqs] = ' ';
1393 }
1394
1395 //clear the end of the line
1396 for (rx_dqs = tx_dqs; rx_dqs < cp_volume - tx_dqs; rx_dqs++) {
1397 cali_data[volume - tx_dqs][rx_dqs] = ' ';
1398 }
1399
1400 //clear the starting column
1401 for (rx_dqs = tx_dqs + 1; rx_dqs < cp_volume - tx_dqs - 1; rx_dqs++) {
1402 cali_data[rx_dqs][tx_dqs] = ' ';
1403 }
1404
1405 //clear the end of the column
1406 for (rx_dqs = tx_dqs + 1; rx_dqs < cp_volume - tx_dqs - 1; rx_dqs++) {
1407 cali_data[rx_dqs][volume - tx_dqs] = ' ';
1408 }
1409 } else {
1410 //Check if there is 0 in the middle of the ring
1411 uint8_t i;
1412
1413 enable_print_window = 0;
1414 for (i = tx_dqs; i < cp_volume - tx_dqs * 2 + tx_dqs; i++) {
1415 //Check the remaining rows
1416 for (rx_dqs = tx_dqs; rx_dqs < cp_volume - tx_dqs * 2 + tx_dqs; rx_dqs++) {
1417 if (cali_data[i][rx_dqs] == '0') {
1418 break;
1419 }
1420 }
1421 if (rx_dqs < cp_volume - tx_dqs * 2 + tx_dqs) {
1422 enable_print_window = 1;
1423 break;
1424 }
1425 }
1426 break;
1427 }
1428 }
1429
1430 //Only the middle window is left, print it out forcibly
1431 if (tx_dqs >= rows) {
1432 enable_print_window = 1;
1433 }
1434
1435 dqs_point = tx_dqs;
1436 dqs_len = cp_volume - tx_dqs * 2;
1437
1438 if (last_dqs_point != dqs_point) {
1439 last_dqs_point = dqs_point;
1440
1441 TRACE_IMM(TR_ATTR_NO_LF | TR_ATTR_NO_TS | TR_ATTR_NO_ID, ", rx_dqs:(%02d,%02d)~(%02d,%02d)",
1442 dqs_point * inc_delay, dqs_point * inc_delay,
1443 (dqs_point + dqs_len - 1)*inc_delay, dqs_point * inc_delay);
1444 } else {
1445 TRACE_IMM(TR_ATTR_NO_LF | TR_ATTR_NO_TS | TR_ATTR_NO_ID, ", ++++++++++++++++++++++");
1446 }
1447
1448 if (last_dqs_len != dqs_len) {
1449 last_dqs_len = dqs_len;
1450
1451 if (enable_print_window) {
1452 TRACE_IMM(TR_ATTR_NO_LF | TR_ATTR_NO_TS | TR_ATTR_NO_ID, ", tx_dqs:(%02d,%02d)~(%02d,%02d), abnormal",
1453 dqs_point * inc_delay, dqs_point * inc_delay,
1454 dqs_point * inc_delay, (dqs_point + dqs_len - 1)*inc_delay);
1455 } else {
1456 TRACE_IMM(TR_ATTR_NO_LF | TR_ATTR_NO_TS | TR_ATTR_NO_ID, ", tx_dqs:(%02d,%02d)~(%02d,%02d), normal",
1457 dqs_point * inc_delay, dqs_point * inc_delay,
1458 dqs_point * inc_delay, (dqs_point + dqs_len - 1)*inc_delay);
1459 }
1460 } else {
1461 if (enable_print_window) {
1462 TRACE_IMM(TR_ATTR_NO_LF | TR_ATTR_NO_TS | TR_ATTR_NO_ID, ", ----------------------, abnormal");
1463 } else {
1464 TRACE_IMM(TR_ATTR_NO_LF | TR_ATTR_NO_TS | TR_ATTR_NO_ID, ", ----------------------, ######");
1465 }
1466 }
1467 TRACE_IMM(TR_ATTR_NO_TS | TR_ATTR_NO_ID, ", vol:%02d, delay:%02d", volume, inc_delay);
1468
1469 if (enable_print_window) {
1470 enable_print_window = 0;
1471
1472 //Print original window data
1473 REL_TRACE_NOTS(0, " ");
1474 REL_TRACE_NOCRLF_NOTS(0, " rx_dqs ");
1475 for (tx_dqs = 0; tx_dqs <= volume; tx_dqs++) {
1476 REL_TRACE_NOCRLF_NOTS(1, " %2d ", tx_dqs * inc_delay);
1477 }
1478 REL_TRACE_NOCRLF_NOTS(0, "\r\n");
1479 for (tx_dqs = 0; tx_dqs <= volume; tx_dqs++) {
1480 REL_TRACE_NOCRLF_NOTS(1, "tx_dqs:%2d ", tx_dqs * inc_delay);
1481 for (rx_dqs = 0; rx_dqs <= volume; rx_dqs++) {
1482 REL_TRACE_NOCRLF_NOTS(1, " %d ", cali_valid[tx_dqs][rx_dqs]);
1483 }
1484 REL_TRACE_NOCRLF_NOTS(0, "\r\n");
1485 }
1486 REL_TRACE_NOTS(0, " ");
1487
1488 //Print new window data
1489 REL_TRACE_NOCRLF_NOTS(0, " rx_dqs ");
1490 for (tx_dqs = 0; tx_dqs <= volume; tx_dqs++) {
1491 REL_TRACE_NOCRLF_NOTS(1, " %2d ", tx_dqs * inc_delay);
1492 }
1493 REL_TRACE_NOCRLF_NOTS(0, "\r\n");
1494 for (tx_dqs = 0; tx_dqs <= volume; tx_dqs++) {
1495 REL_TRACE_NOCRLF_NOTS(1, "tx_dqs:%2d ", tx_dqs * inc_delay);
1496 for (rx_dqs = 0; rx_dqs <= volume; rx_dqs++) {
1497 REL_TRACE_NOCRLF_NOTS(1, " %c ", cali_data[tx_dqs][rx_dqs]);
1498 }
1499 REL_TRACE_NOCRLF_NOTS(0, "\r\n");
1500 }
1501 REL_TRACE_NOTS(0, " ");
1502 }
1503 #endif
1504
1505 #if 0
1506 //Print cali_value window data
1507 PSRAM_TRACENOCRLF_NOTS(0, "\r\n\r\n ---------------------------------------------------------------------- \r\n");
1508 PSRAM_TRACENOCRLF_NOTS(0, " rx_dqs");
1509 for (tx_dqs = 0; tx_dqs <= volume; tx_dqs++) {
1510 PSRAM_TRACENOCRLF_NOTS(1, " %2d ", tx_dqs * inc_delay);
1511 }
1512 PSRAM_TRACENOCRLF_NOTS(0, "\r\n");
1513 for (tx_dqs = 0; tx_dqs <= volume; tx_dqs++) {
1514 PSRAM_TRACENOCRLF_NOTS(1, "tx_dqs:%2d ", tx_dqs * inc_delay);
1515 for (rx_dqs = 0; rx_dqs <= volume; rx_dqs++) {
1516 PSRAM_TRACENOCRLF_NOTS(1, " %d ", cali_value[tx_dqs][rx_dqs]);
1517 }
1518 PSRAM_TRACENOCRLF_NOTS(0, "\r\n");
1519 }
1520 PSRAM_TRACENOCRLF_NOTS(0, " -------------------------------------------------------------------------- \r\n");
1521 #endif
1522
1523 uint32_t position = 0;
1524 uint8_t max_value = 0;
1525 for (tx_dqs = 0; tx_dqs <= volume; tx_dqs++) {
1526 for (rx_dqs = 0; rx_dqs <= volume; rx_dqs++) {
1527 if (cali_value[tx_dqs][rx_dqs] > max_value) {
1528 max_value = cali_value[tx_dqs][rx_dqs];
1529 position = tx_dqs * (volume + 1) + rx_dqs;
1530 }
1531 }
1532 }
1533 PSRAM_TRACENOCRLF_NOTS(1, "position:%d\r\n", position);
1534 tx_dqs = position / (volume + 1) * inc_delay;
1535 rx_dqs = (position % (volume + 1)) * inc_delay;
1536 PSRAM_TRACENOCRLF_NOTS(2, "most optimal position. tx_dqs:%d, rx_dqs:%d\r\n", tx_dqs, rx_dqs);
1537 #ifdef PSRAM_XCCELA_MODE
1538 psram_phy->REG_054 = PSRAM_ULP_PHY_REG_PSRAM_TX_CEB_DLY(tx_ceb) | PSRAM_ULP_PHY_REG_PSRAM_TX_CLK_DLY(tx_dqs) |
1539 PSRAM_ULP_PHY_REG_PSRAM_TX_DQS_DLY(0) | PSRAM_ULP_PHY_REG_PSRAM_RX_DQS_DLY(rx_dqs);
1540 #else
1541 psram_phy->REG_054 = PSRAM_ULP_PHY_REG_PSRAM_TX_CEB_DLY(tx_ceb) | PSRAM_ULP_PHY_REG_PSRAM_TX_CLK_DLY(tx_clk) |
1542 PSRAM_ULP_PHY_REG_PSRAM_TX_DQS_DLY(tx_dqs) | PSRAM_ULP_PHY_REG_PSRAM_RX_DQS_DLY(rx_dqs);
1543 #endif
1544
1545 #if 0
1546 volume = (PSRAM_ULP_PHY_REG_PSRAM_TX_DQS_DLY_MASK >> PSRAM_ULP_PHY_REG_PSRAM_TX_DQS_DLY_SHIFT) / inc_delay;
1547 PSRAM_TRACE(2, "volume:%d, inc_delay:%d", volume, inc_delay);
1548
1549 //calibrate tx_clk
1550 PSRAM_TRACE(0, "cali tx_clk");
1551 left_bound = -1;
1552 right_bound = -1;
1553 memset(valid_array, 0, sizeof(valid_array));
1554 for (tx_clk = 1; tx_clk <= volume; tx_clk++) {
1555 bool valid;
1556 //tx_ceb = tx_clk;
1557 psram_phy->REG_054 = PSRAM_ULP_PHY_REG_PSRAM_TX_CEB_DLY(tx_ceb * inc_delay) | PSRAM_ULP_PHY_REG_PSRAM_TX_CLK_DLY(tx_clk * inc_delay) |
1558 PSRAM_ULP_PHY_REG_PSRAM_TX_DQS_DLY(delay / 2) | PSRAM_ULP_PHY_REG_PSRAM_RX_DQS_DLY(delay / 2);
1559 valid = psramphy_check_write_valid(range);
1560 PSRAM_TRACE(3, "tx_clk:0x%x, valid:%d", (tx_clk * inc_delay), valid);
1561 valid_array[tx_clk] = valid;
1562 if (tx_clk == 1) {
1563 if (valid) {
1564 left_bound = tx_clk;
1565 PSRAM_TRACE(1, "left_bound:0x%x", left_bound * inc_delay);
1566 }
1567 } else if (tx_clk == volume) {
1568 if (valid) {
1569 right_bound = tx_clk;//find right bound
1570 PSRAM_TRACE(1, "right_bound:0x%x", right_bound * inc_delay);
1571 } else {
1572 if (valid_array[tx_clk - 1]) {
1573 right_bound = tx_clk - 1; //find right bound
1574 PSRAM_TRACE(1, "right_bound:0x%x", right_bound * inc_delay);
1575 }
1576 }
1577 } else {
1578 if (valid && !valid_array[tx_clk - 1]) {
1579 left_bound = tx_clk;//find left bound
1580 PSRAM_TRACE(1, "left_bound:0x%x", left_bound * inc_delay);
1581 } else if (!valid && valid_array[tx_clk - 1]) {
1582 right_bound = tx_clk - 1; //find right bound
1583 PSRAM_TRACE(1, "right_bound:0x%x", right_bound * inc_delay);
1584 break;
1585 }
1586 }
1587 }
1588 if (left_bound != -1 && right_bound != -1) {// && (right_bound-left_bound>1)) {
1589 tx_clk = (left_bound + right_bound) / 2;
1590 PSRAM_TRACE(3, "cali tx_clk done, tx_clk:0x%x(0x%x-0x%x)", tx_clk * inc_delay, left_bound * inc_delay, right_bound * inc_delay);
1591 } else {
1592 ASSERT(false, "ERROR, tx_clk need do more cali");
1593 }
1594 //tx_ceb = tx_clk * inc_delay;
1595 tx_clk = tx_clk * inc_delay;
1596 #endif
1597 }
hal_psram_calib(uint32_t clk)1598 void hal_psram_calib(uint32_t clk)
1599 {
1600 uint32_t phy_clk;
1601 uint32_t range;
1602 PSRAM_TRACE(2, "%s, speed:%d", __func__, clk);
1603 phy_clk = clk;
1604 if (phy_clk <= 100000000 / 2) {
1605 range = 3;
1606 } else if (phy_clk <= 150000000 / 2) {
1607 range = 2;
1608 } else if (phy_clk <= 300000000 / 2) {
1609 range = 1;
1610 } else {
1611 range = 1;
1612 }
1613 #ifdef PSRAM_WINDOW_TEST
1614 TRACE_IMM(TR_ATTR_NO_LF, "clk:%d, range:%d", clk, range);
1615 #endif
1616 hal_psram_calib_range(range);
1617 }
1618
hal_psram_init(void)1619 void hal_psram_init(void)
1620 {
1621 hal_cache_wrap_enable(HAL_CACHE_ID_I_CACHE);
1622 hal_cache_wrap_enable(HAL_CACHE_ID_D_CACHE);
1623
1624 hal_cmu_mem_set_freq(HAL_CMU_FREQ_104M);
1625 hal_cmu_clock_enable(HAL_CMU_MOD_O_PSRAM);
1626 hal_cmu_clock_enable(HAL_CMU_MOD_H_PSRAM);
1627 hal_cmu_reset_clear(HAL_CMU_MOD_O_PSRAM);
1628 hal_cmu_reset_clear(HAL_CMU_MOD_H_PSRAM);
1629
1630 #ifndef FPGA
1631 hal_psram_phy_init(psram_cfg_clk);
1632 hal_sys_timer_delay_us(100);
1633 #endif
1634 hal_psram_digphy_init();
1635 hal_psram_mc_init(psram_cfg_clk);
1636 #if !defined(FPGA) && !defined(SIMU)
1637 hal_psram_init_calib();
1638 #endif
1639
1640 #ifdef PSRAM_RESET
1641 psram_reset();
1642 psram_chip_timing_config(psram_run_clk, true);
1643 #else
1644 uint32_t reg;
1645 uint32_t val;
1646
1647 reg = 4;
1648 psram_read_reg(reg, &val);
1649 if (val & MR4_WL) {
1650 psram_chip_timing_config(psram_run_clk, false);
1651 } else {
1652 psram_chip_timing_config(psram_run_clk, true);
1653 }
1654 #endif
1655
1656 hal_psram_snoop_disable();
1657 #if !defined(FPGA) && !defined(SIMU)
1658 hal_psram_calib(psram_run_clk);
1659 #endif
1660 hal_psram_snoop_enable();
1661 }
1662
1663 #endif
1664
1665