• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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