1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2022-05-16     shelton      first version
9  */
10 
11 #include "drv_common.h"
12 
13 #ifdef BSP_USING_SDRAM
14 #include "drv_sdram.h"
15 
16 #define DRV_DEBUG
17 #define LOG_TAG                         "drv.sdram"
18 #include <drv_log.h>
19 
20 #ifdef RT_USING_MEMHEAP_AS_HEAP
21 static struct rt_memheap system_heap;
22 #endif
23 
sdram_init_sequence(xmc_cmd_bank1_2_type cmd_bank)24 static void sdram_init_sequence(xmc_cmd_bank1_2_type cmd_bank)
25 {
26     xmc_sdram_cmd_type sdram_cmd_struct;
27     uint32_t timeout = 0xffff, delay = 0;
28 
29     sdram_cmd_struct.cmd = XMC_CMD_CLK;
30     sdram_cmd_struct.auto_refresh = 1;
31     sdram_cmd_struct.cmd_banks = cmd_bank;
32     sdram_cmd_struct.data = 0;
33     xmc_sdram_cmd(&sdram_cmd_struct);
34 
35     while((xmc_flag_status_get(XMC_BANK5_6_SDRAM, XMC_BUSY_FLAG) != RESET) && (timeout > 0))
36     {
37         timeout --;
38     }
39 
40     /* insert 100 ms delay */
41     for (delay = 0; delay < 0xffff; delay ++)
42         ;
43 
44     sdram_cmd_struct.cmd = XMC_CMD_PRECHARG_ALL;
45     sdram_cmd_struct.auto_refresh = 1;
46     sdram_cmd_struct.cmd_banks = cmd_bank;
47     sdram_cmd_struct.data = 0;
48     xmc_sdram_cmd(&sdram_cmd_struct);
49 
50     timeout = 0xffff;
51     while((xmc_flag_status_get(XMC_BANK5_6_SDRAM, XMC_BUSY_FLAG) != RESET) && (timeout > 0))
52     {
53         timeout --;
54     }
55 
56     /* set refresh rate */
57     xmc_sdram_refresh_counter_set(SDRAM_REFRESH_COUNT);
58 
59     sdram_cmd_struct.cmd = XMC_CMD_AUTO_REFRESH;
60     sdram_cmd_struct.auto_refresh = 8;
61     sdram_cmd_struct.cmd_banks = cmd_bank;
62     sdram_cmd_struct.data = 0;
63     xmc_sdram_cmd(&sdram_cmd_struct);
64 
65     timeout = 0xffff;
66     while((xmc_flag_status_get(XMC_BANK5_6_SDRAM, XMC_BUSY_FLAG) != RESET) && (timeout > 0))
67     {
68         timeout --;
69     }
70 
71     sdram_cmd_struct.cmd = XMC_CMD_LOAD_MODE;
72     sdram_cmd_struct.auto_refresh = 1;
73     sdram_cmd_struct.cmd_banks = cmd_bank;
74 
75 #if SDRAM_DATA_WIDTH == 8
76     sdram_cmd_struct.data = (uint32_t)SDRAM_BURST_LEN_1   |
77 #elif SDRAM_DATA_WIDTH == 16
78     sdram_cmd_struct.data = (uint32_t)SDRAM_BURST_LEN_2   |
79 #endif
80                             SDRAM_BURST_SEQUENTIAL        |
81 #if SDRAM_CAS_LATENCY == 3
82                             SDRAM_CAS_LATENCY_3           |
83 #else
84                             SDRAM_CAS_LATENCY_2           |
85 #endif
86                             SDRAM_OPERATING_MODE_STANDARD |
87                             SDRAM_WR_BURST_SINGLE;
88 
89     xmc_sdram_cmd(&sdram_cmd_struct);
90 
91     timeout = 0xffff;
92     while((xmc_flag_status_get(XMC_BANK5_6_SDRAM, XMC_BUSY_FLAG) != RESET) && (timeout > 0))
93     {
94         timeout --;
95     }
96 }
97 
sdram_init(void)98 static int sdram_init(void)
99 {
100     int result = RT_EOK;
101     xmc_cmd_bank1_2_type target_bank = XMC_CMD_BANK1;
102 
103     xmc_sdram_init_type sdram_init_struct;
104     xmc_sdram_timing_type sdram_timing_struct;
105 
106     at32_msp_sdram_init(NULL);
107 
108     /* xmc configuration */
109     xmc_sdram_default_para_init(&sdram_init_struct, &sdram_timing_struct);
110 
111 #if SDRAM_TARGET_BANK == 1
112     sdram_init_struct.sdram_bank = XMC_SDRAM_BANK1;
113 #else
114     sdram_init_struct.sdram_bank = XMC_SDRAM_BANK2;
115 #endif
116 #if SDRAM_COLUMN_BITS == 8
117     sdram_init_struct.column_address = XMC_COLUMN_8;
118 #elif SDRAM_COLUMN_BITS == 9
119     sdram_init_struct.column_address = XMC_COLUMN_9;
120 #elif SDRAM_COLUMN_BITS == 10
121     sdram_init_struct.column_address = XMC_COLUMN_10;
122 #else
123     sdram_init_struct.column_address = XMC_COLUMN_11;
124 #endif
125 #if SDRAM_ROW_BITS == 11
126     sdram_init_struct.row_address = XMC_ROW_11;
127 #elif SDRAM_ROW_BITS == 12
128     sdram_init_struct.row_address = XMC_ROW_12;
129 #else
130     sdram_init_struct.row_address = XMC_ROW_13;
131 #endif
132 #if SDRAM_DATA_WIDTH == 8
133     sdram_init_struct.width = XMC_MEM_WIDTH_8;
134 #elif SDRAM_DATA_WIDTH == 16
135     sdram_init_struct.width = XMC_MEM_WIDTH_16;
136 #endif
137 
138     sdram_init_struct.internel_banks = XMC_INBK_4;
139 
140 #if SDRAM_CAS_LATENCY == 1
141     sdram_init_struct.cas = XMC_CAS_1;
142 #elif SDRAM_CAS_LATENCY == 2
143     sdram_init_struct.cas = XMC_CAS_2;
144 #else
145     sdram_init_struct.cas = XMC_CAS_3;
146 #endif
147 #if SDRAM_RPIPE_DELAY == 0
148     sdram_init_struct.read_delay = XMC_READ_DELAY_0;
149 #elif SDRAM_RPIPE_DELAY == 1
150     sdram_init_struct.read_delay = XMC_READ_DELAY_1;
151 #else
152     sdram_init_struct.read_delay = XMC_READ_DELAY_2;
153 #endif
154 #if SDCLOCK_PERIOD == 2
155     sdram_init_struct.clkdiv = XMC_CLKDIV_2;
156 #else
157     sdram_init_struct.clkdiv = XMC_CLKDIV_3;
158 #endif
159 
160     sdram_init_struct.write_protection = FALSE;
161     sdram_init_struct.burst_read = TRUE;
162 
163     sdram_timing_struct.tmrd = LOADTOACTIVEDELAY;
164     sdram_timing_struct.txsr = EXITSELFREFRESHDELAY;
165     sdram_timing_struct.tras = SELFREFRESHTIME;
166     sdram_timing_struct.trc = ROWCYCLEDELAY;
167     sdram_timing_struct.twr = WRITERECOVERYTIME;
168     sdram_timing_struct.trp = RPDELAY;
169     sdram_timing_struct.trcd = RCDDELAY;
170 
171     xmc_sdram_init(&sdram_init_struct, &sdram_timing_struct);
172 
173 #if SDRAM_TARGET_BANK == 1
174     target_bank = XMC_CMD_BANK1;
175 #else
176     target_bank = XMC_CMD_BANK2;
177 #endif
178 
179     sdram_init_sequence(target_bank);
180 
181 #ifdef RT_USING_MEMHEAP_AS_HEAP
182         /* If RT_USING_MEMHEAP_AS_HEAP is enabled, SDRAM is initialized to the heap */
183         rt_memheap_init(&system_heap, "sdram", (void *)SDRAM_BANK_ADDR, SDRAM_SIZE);
184 #endif
185 
186     return result;
187 }
188 
189 INIT_BOARD_EXPORT(sdram_init);
190 
191 #ifdef DRV_DEBUG
192 #ifdef FINSH_USING_MSH
sdram_sample(void)193 int sdram_sample(void)
194 {
195     int i = 0;
196     uint32_t start_time = 0, time_cast = 0;
197 #if SDRAM_DATA_WIDTH == 8
198     char data_width = 1;
199     uint8_t data = 0;
200 #elif SDRAM_DATA_WIDTH == 16
201     char data_width = 2;
202     uint16_t data = 0;
203 #else
204     char data_width = 4;
205     uint32_t data = 0;
206 #endif
207 
208     /* write data */
209     LOG_D("writing the %ld bytes data, waiting....", SDRAM_SIZE);
210     start_time = rt_tick_get();
211     for (i = 0; i < SDRAM_SIZE / data_width; i++)
212     {
213 #if SDRAM_DATA_WIDTH == 8
214         *(__IO uint8_t *)(SDRAM_BANK_ADDR + i * data_width) = (uint8_t)(i % 100);
215 #elif SDRAM_DATA_WIDTH == 16
216         *(__IO uint16_t *)(SDRAM_BANK_ADDR + i * data_width) = (uint16_t)(i % 1000);
217 #endif
218     }
219     time_cast = rt_tick_get() - start_time;
220     LOG_D("write data success, total time: %d.%03dS.", time_cast / RT_TICK_PER_SECOND,
221           time_cast % RT_TICK_PER_SECOND / ((RT_TICK_PER_SECOND * 1 + 999) / 1000));
222 
223     /* read data */
224     LOG_D("start reading and verifying data, waiting....");
225     for (i = 0; i < SDRAM_SIZE / data_width; i++)
226     {
227 #if SDRAM_DATA_WIDTH == 8
228         data = *(__IO uint8_t *)(SDRAM_BANK_ADDR + i * data_width);
229         if (data != i % 100)
230         {
231             LOG_E("sdram test failed!");
232             break;
233         }
234 #elif SDRAM_DATA_WIDTH == 16
235         data = *(__IO uint16_t *)(SDRAM_BANK_ADDR + i * data_width);
236         if (data != (uint16_t)(i % 1000))
237         {
238             LOG_E("sdram test failed, i = %d!", i);
239             break;
240         }
241 #endif
242     }
243 
244     if (i >= SDRAM_SIZE / data_width)
245     {
246         LOG_D("sdram test success!");
247     }
248 
249     return RT_EOK;
250 }
251 
252 MSH_CMD_EXPORT(sdram_sample, sdram sample test)
253 
254 #endif /* FINSH_USING_MSH */
255 #endif /* DRV_DEBUG */
256 #endif /* BSP_USING_SDRAM */
257