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