1 /*
2 * Copyright (c) 2022 ASR Microelectronics (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
16 #include "duet_psram.h"
17 #include "duet_pinmux.h"
18
19 #define PSRAM_CMD_STOP 0
20 #define PSRAM_CMD_CMD 1
21 #define PSRAM_CMD_ADDR 2
22 #define PSRAM_CMD_DUMMY 3
23 #define PSRAM_CMD_MODE 4
24 #define PSRAM_CMD_MODE2 5
25 #define PSRAM_CMD_MODE4 6
26 #define PSRAM_CMD_READ 7
27 #define PSRAM_CMD_WRITE 8
28 #define PSRAM_CMD_JMP_ON_CS 9
29 #define PSRAM_CMD_ADDR_DDR 10
30 #define PSRAM_CMD_MODE_DDR 11
31 #define PSRAM_CMD_MODE2_DDR 12
32 #define PSRAM_CMD_MODE4_DDR 13
33 #define PSRAM_CMD_READ_DDR 14
34 #define PSRAM_CMD_WRITE_DDR 15
35 #define PSRAM_CMD_DATA_LEARN 16
36 #define PSRAM_CMD_CMD_DDR 17
37 #define PSRAM_CMD_CADDR 18
38 #define PSRAM_CMD_CADDR_DDR 19
39
40 #define PSRAM_SEQ_ID_READ 5
41 #define PSRAM_SEQ_ID_WRITE_EVICT 6
42 #define PSRAM_SEQ_ID_WRITE 7
43 #define PSRAM_SEQ_ID_READ_ID 8
44 #define PSRAM_SEQ_ID_QUAD_ENABLE 9
45 #define PSRAM_SEQ_ID_QUAD_EXIT 10
46 #define PSRAM_SEQ_ID_MODE_REG_READ 11
47 #define PSRAM_SEQ_ID_MODE_REG_WRITE 12
48
49 int mode_config = -1;
50
psram_wait_finish(void)51 static void psram_wait_finish(void)
52 {
53 while (REG_RD(PSRAM_SR) & 0x2);
54 while (!(REG_RD(PSRAM_FR) & 0x1));
55 REG_WR(PSRAM_FR, 1);
56 }
57
psram_init_lut_ps_read(unsigned int seq_id)58 static void psram_init_lut_ps_read(unsigned int seq_id)
59 {
60 REG_WR((PSRAM_LUT0 + 0x10 * seq_id),
61 ((PSRAM_CMD_ADDR << 26) | (0x0 << 24) | (0x18 << 16) | (PSRAM_CMD_CMD << 10) | (0x0 << 8) | FLASH_CMD_READ));
62 REG_WR((PSRAM_LUT1 + 0x10 * seq_id),
63 ((PSRAM_CMD_JMP_ON_CS << 26) | (0x0 << 24) | (0x00 << 16) | (PSRAM_CMD_READ << 10) | (0x0 << 8) | 0x20));
64 REG_WR((PSRAM_LUT2 + 0x10 * seq_id), 0);
65 REG_WR((PSRAM_LUT3 + 0x10 * seq_id), 0);
66 }
67
psram_init_lut_ps_write(unsigned int seq_id)68 static void psram_init_lut_ps_write(unsigned int seq_id)
69 {
70 REG_WR((PSRAM_LUT0 + 0x10 * seq_id),
71 ((PSRAM_CMD_ADDR << 26) | (0x0 << 24) | (0x18 << 16) | (PSRAM_CMD_CMD << 10) | (0x0 << 8) | FLASH_CMD_WRITE));
72 REG_WR((PSRAM_LUT1 + 0x10 * seq_id),
73 ((PSRAM_CMD_JMP_ON_CS << 26) | (0x0 << 24) | (0x00 << 16) | (PSRAM_CMD_WRITE << 10) | (0x0 << 8) | 0x20));
74 REG_WR((PSRAM_LUT2 + 0x10 * seq_id), 0);
75 REG_WR((PSRAM_LUT3 + 0x10 * seq_id), 0);
76 }
77
psram_init_lut_ps_write_evict(unsigned int seq_id)78 static void psram_init_lut_ps_write_evict(unsigned int seq_id)
79 {
80 REG_WR((PSRAM_LUT0 + 0x10 * seq_id),
81 ((PSRAM_CMD_ADDR << 26) | (0x0 << 24) | (0x18 << 16) | (PSRAM_CMD_CMD << 10) | (0x0 << 8) | FLASH_CMD_WRITE));
82 REG_WR((PSRAM_LUT1 + 0x10 * seq_id), ((PSRAM_CMD_JMP_ON_CS << 26) | (0 << 24) | (0x00 << 16) | (21 << 10) | (0 << 8) | 0x20));
83 REG_WR((PSRAM_LUT2 + 0x10 * seq_id), 0);
84 REG_WR((PSRAM_LUT3 + 0x10 * seq_id), 0);
85 }
86
psram_init_lut_ps_mode_register_read(unsigned int seq_id)87 static void psram_init_lut_ps_mode_register_read(unsigned int seq_id)
88 {
89 REG_WR((PSRAM_LUT0 + 0x10 * seq_id),
90 ((PSRAM_CMD_ADDR << 26) | (0x0 << 24) | (0x18 << 16) | (PSRAM_CMD_CMD << 10) | (0x0 << 8) | FLASH_CMD_MODE_REG_READ));
91 REG_WR((PSRAM_LUT1 + 0x10 * seq_id),
92 ((PSRAM_CMD_READ << 26) | (0x0 << 24) | (0x2 << 16) | (PSRAM_CMD_DUMMY << 10) | (0x0 << 8) | (8 - 1)));
93 REG_WR((PSRAM_LUT2 + 0x10 * seq_id), ((PSRAM_CMD_JMP_ON_CS << 10) | (0x0 << 8) | 0x0));
94 REG_WR((PSRAM_LUT3 + 0x10 * seq_id), 0);
95 }
96
psram_init_lut_ps_mode_register_write(unsigned int seq_id)97 static void psram_init_lut_ps_mode_register_write(unsigned int seq_id)
98 {
99 REG_WR((PSRAM_LUT0 + 0x10 * seq_id),
100 ((PSRAM_CMD_ADDR << 26) | (0x0 << 24) | (0x18 << 16) | (PSRAM_CMD_CMD << 10) | (0x0 << 8) | FLASH_CMD_MODE_REG_WRITE));
101 REG_WR((PSRAM_LUT1 + 0x10 * seq_id),
102 ((PSRAM_CMD_JMP_ON_CS << 26) | (0x0 << 24) | (0x00 << 16) | (PSRAM_CMD_WRITE << 10) | (0x0 << 8) | 0x20));
103 REG_WR((PSRAM_LUT2 + 0x10 * seq_id), 0);
104 REG_WR((PSRAM_LUT3 + 0x10 * seq_id), 0);
105 }
106
psram_init_lut_ps_qmode_enable(unsigned int seq_id)107 static void psram_init_lut_ps_qmode_enable(unsigned int seq_id)
108 {
109 REG_WR((PSRAM_LUT0 + 0x10 * seq_id), ((PSRAM_CMD_CMD << 10) | (0 << 8) | FLASH_CMD_ENTER_QUAD_MODE));
110 REG_WR((PSRAM_LUT1 + 0x10 * seq_id), 0);
111 REG_WR((PSRAM_LUT2 + 0x10 * seq_id), 0);
112 REG_WR((PSRAM_LUT3 + 0x10 * seq_id), 0);
113 }
114
psram_init_lut_ps_qmode_exit(unsigned int seq_id)115 static void psram_init_lut_ps_qmode_exit(unsigned int seq_id)
116 {
117 REG_WR((PSRAM_LUT0 + 0x10 * seq_id), ((PSRAM_CMD_CMD << 10) | (0x2 << 8) | FLASH_CMD_EXIT_QUAD_MODE));
118 REG_WR((PSRAM_LUT1 + 0x10 * seq_id), 0);
119 REG_WR((PSRAM_LUT2 + 0x10 * seq_id), 0);
120 REG_WR((PSRAM_LUT3 + 0x10 * seq_id), 0);
121 }
122
psram_init_lut_ps_read_4x(unsigned int seq_id)123 static void psram_init_lut_ps_read_4x(unsigned int seq_id)
124 {
125 REG_WR((PSRAM_LUT0 + 0x10 * seq_id),
126 ((PSRAM_CMD_ADDR << 26) | (0x2 << 24) | (0x18 << 16) | (PSRAM_CMD_CMD << 10) | (0x2 << 8) | FLASH_CMD_FAST_READ_QUAD));
127 REG_WR((PSRAM_LUT1 + 0x10 * seq_id),
128 ((PSRAM_CMD_READ << 26) | (0x2 << 24) | (0x20 << 16) | (PSRAM_CMD_DUMMY << 10) | (0x2 << 8) | (6 - 1)));
129 REG_WR((PSRAM_LUT2 + 0x10 * seq_id), ((PSRAM_CMD_JMP_ON_CS << 10) | (0x2 << 8) | 0x00));
130 REG_WR((PSRAM_LUT3 + 0x10 * seq_id), 0);
131 }
132
psram_init_lut_ps_write_4x(unsigned int seq_id)133 static void psram_init_lut_ps_write_4x(unsigned int seq_id)
134 {
135 REG_WR((PSRAM_LUT0 + 0x10 * seq_id),
136 ((PSRAM_CMD_ADDR << 26) | (0x2 << 24) | (0x18 << 16) | (PSRAM_CMD_CMD << 10) | (0x2 << 8) | FLASH_CMD_WRITE));
137 REG_WR((PSRAM_LUT1 + 0x10 * seq_id),
138 ((PSRAM_CMD_JMP_ON_CS << 26) | (0x2 << 24) | (0x00 << 16) | (PSRAM_CMD_WRITE << 10) | (0x2 << 8) | 0x20));
139 REG_WR((PSRAM_LUT2 + 0x10 * seq_id), 0);
140 REG_WR((PSRAM_LUT3 + 0x10 * seq_id), 0);
141 }
142
psram_init_lut_ps_write_evict_4x(unsigned int seq_id)143 static void psram_init_lut_ps_write_evict_4x(unsigned int seq_id)
144 {
145 REG_WR((PSRAM_LUT0 + 0x10 * seq_id),
146 ((PSRAM_CMD_ADDR << 26) | (0x2 << 24) | (0x18 << 16) | (PSRAM_CMD_CMD << 10) | (0x2 << 8) | FLASH_CMD_WRITE));
147 REG_WR((PSRAM_LUT1 + 0x10 * seq_id), ((PSRAM_CMD_JMP_ON_CS << 26) | (0x2 << 24) | (0x00 << 16) | (21 << 10) | (0x2 << 8) | 0x20));
148 REG_WR((PSRAM_LUT2 + 0x10 * seq_id), 0);
149 REG_WR((PSRAM_LUT3 + 0x10 * seq_id), 0);
150 }
151
psram_init_lut_ps_readid(unsigned int seq_id)152 static void psram_init_lut_ps_readid(unsigned int seq_id)
153 {
154 REG_WR((PSRAM_LUT0 + 0x10 * seq_id),
155 ((PSRAM_CMD_ADDR << 26) | (0x0 << 24) | (0x18 << 16) | (PSRAM_CMD_CMD << 10) | (0x0 << 8) | FLASH_CMD_READ_ID));
156 REG_WR((PSRAM_LUT1 + 0x10 * seq_id), ((PSRAM_CMD_READ << 10) | (0x0 << 8) | 0x9));
157 REG_WR((PSRAM_LUT2 + 0x10 * seq_id), 0);
158 REG_WR((PSRAM_LUT3 + 0x10 * seq_id), 0);
159 }
160
psram_set_channel(duet_psram_channel channel)161 int psram_set_channel(duet_psram_channel channel)
162 {
163 if (channel != PSRAM_CHANNEL_4_9 && channel != PSRAM_CHANNEL_16_21) {
164 return -1;
165 }
166 REG_WR(ADC_SDIO_BLE_DEBUG_CTRL_REG, REG_RD(ADC_SDIO_BLE_DEBUG_CTRL_REG) & (~(1 << 3))); // disable sdio debug
167 if (channel == PSRAM_CHANNEL_4_9) {
168 duet_pinmux_config(PAD4, PF_PSRAM); // set pad4 mux to psram
169 duet_pinmux_config(PAD5, PF_PSRAM); // set pad5 mux to psram
170 duet_pinmux_config(PAD6, PF_PSRAM); // set pad6 mux to psram
171 duet_pinmux_config(PAD7, PF_PSRAM); // set pad7 mux to psram
172 duet_pinmux_config(PAD8, PF_PSRAM); // set pad8 mux to psram
173 duet_pinmux_config(PAD9, PF_PSRAM); // set pad9 mux to psram
174 REG_WR(HW_CTRL_PE_PS,REG_RD(HW_CTRL_PE_PS)& 0xfffffc0f); // set all pad pull up and down
175 } else { // set
176 duet_pinmux_config(PAD16, PF_PSRAM); // sett pad16 mux to psram
177 duet_pinmux_config(PAD17, PF_PSRAM); // set pad17 mux to psr// set
178 duet_pinmux_config(PAD18, PF_PSRAM); // set pad18 mux to psram
179 duet_pinmux_config(PAD19, PF_PSRAM); // set pad19 mux to psram
180 duet_pinmux_config(PAD20, PF_PSRAM); // set pad20 mux to psram
181 duet_pinmux_config(PAD21, PF_PSRAM); // set pad21 mux to psram
182 REG_WR(HW_CTRL_PE_PS,REG_RD(HW_CTRL_PE_PS)& 0xffc0ffff); // set all pad pull up and down
183 }// set
184 REG_WR(PERI_CLK_EN_REG0, (REG_RD(PERI_CLK_EN_REG0) | (0x0000203F))); //open clock of dma and psram
185
186 return 0; // set
187 }
psram_config(duet_psram_mode mode)188 int psram_config(duet_psram_mode mode)
189 {
190 if (mode != PSRAM_MODE_SPI && mode != PSRAM_MODE_QSPI) {
191 return -1;
192 }
193 REG_WR(PSRAM_MCR, REG_RD(PSRAM_MCR) & (~(1 << 14))); // MCR,MDIS = 0
194
195 REG_WR(PSRAM_MCR, REG_RD(PSRAM_MCR) | ((3))); // MCR , AHB and SF domain reset
196
197 REG_WR(PSRAM_MCR, REG_RD(PSRAM_MCR) & 0xfffffffc); // clear AHB and SF reset
198
199 REG_WR(PSRAM_MCR, REG_RD(PSRAM_MCR) | 1 << 14); // MCR , MDIS=1
200
201 if (mode == PSRAM_MODE_SPI) { // the simple logic has been modified. set bit7 means to use the original logic
202 REG_WR(PSRAM_SMPR, 0x00000080); // sampled by sfif_clk_b; half cycle delay
203 } else {
204 REG_WR(PSRAM_SMPR, 0x00000000); // sampled by sfif_clk_b; half cycle delay
205 }
206
207 REG_WR(PSRAM_FLSHCR, 0x00000000); // set setup and hold time for psram
208
209 // Give the default source address:
210 REG_WR(PSRAM_SFAR, PSRAM_FLASH_A1_BASE); // set IDATSIZ
211
212 // lijin: 2018_01_11-11:07 total buffer size is 64*64b = 512B = 0x200B
213 // config the ahb buffer// set
214 REG_WR(PSRAM_BUF0IND, 0x00000080);
215 REG_WR(PSRAM_BUF1IND, 0x00000100);
216 REG_WR(PSRAM_BUF2IND, 0x00000180);
217
218 // lijin: 2018_01_11-11:07 each buffer is 8B * 16 = 128B = 0x80B
219
220 // kzheng: TO DO, now hmaster[3:0] tie0, so need modified here
221 // mst id =0 is CPU
222 // PSRAM0_BUF0CR = 0x00001001; // CPU A9
223 REG_WR(PSRAM_BUF0CR, 0x00001000); // CPU A9
224 REG_WR(PSRAM_BUF1CR, 0x00001006); // CPU M4
225 REG_WR(PSRAM_BUF2CR, 0x00001003); // SDMA
226 REG_WR(PSRAM_BUF3CR, 0x80001002); // other masters
227
228 // config the flash mmap
229 REG_WR(PSRAM_SFA1AD, PSRAM_FLASH_A1_TOP & 0xfffffc00);
230 REG_WR(PSRAM_SFA2AD, PSRAM_FLASH_A2_TOP & 0xfffffc00);
231 REG_WR(PSRAM_SFB1AD, PSRAM_FLASH_B1_TOP & 0xfffffc00);
232 REG_WR(PSRAM_SFB2AD, PSRAM_FLASH_B2_TOP & 0xfffffc00);
233
234 // ISD3FB, ISD2FB, ISD3FA, ISD2FA = 1; ENDIAN = 'h3; END_CFG='h3
235 // DELAY_CLK4X_EN = 1
236 REG_WR(PSRAM_MCR, REG_RD(PSRAM_MCR) | 0x000F000C);
237
238 // ddr_en data aligned with 2x serial flash half clock
239 // REG_WR(PSRAM_FLSHCR, REG_RD(PSRAM_FLSHCR)| 0x00010000);
240
241 // MCR SCLKCFG 0, dqs en =1
242 REG_WR(PSRAM_MCR, REG_RD(PSRAM_MCR) & 0xfbffffff);
243
244 // dqs_loopback_en = 1, dqs_loopback_from_pad = 1
245 REG_WR(PSRAM_MCR, REG_RD(PSRAM_MCR) | (3 << 24));
246
247 // ddr_en = 1, enable 2x and 4x clock
248 /// REG_WR(PSRAM_MCR, REG_RD(PSRAM_MCR)| 1<<7);
249
250 // MDIS = 0, enable psram clocks,must clear MDIS to enable clock for transfer.
251 REG_WR(PSRAM_MCR, REG_RD(PSRAM_MCR) & 0xffffbfff);
252
253 // printf("PSRAM initialize done. \n");
254 // printf("begin initialize LUT tables. \n");
255
256 if (mode == PSRAM_MODE_SPI) {
257 psram_init_lut_ps_read(0);
258 psram_init_lut_ps_read(PSRAM_SEQ_ID_READ);
259 psram_init_lut_ps_write_evict(PSRAM_SEQ_ID_WRITE_EVICT);
260 psram_init_lut_ps_write(PSRAM_SEQ_ID_WRITE);
261 psram_init_lut_ps_readid(PSRAM_SEQ_ID_READ_ID);
262 psram_init_lut_ps_mode_register_read(PSRAM_SEQ_ID_MODE_REG_READ);
263 psram_init_lut_ps_mode_register_write(PSRAM_SEQ_ID_MODE_REG_WRITE);
264 } else {
265 psram_init_lut_ps_read_4x(0);
266 psram_init_lut_ps_read_4x(PSRAM_SEQ_ID_READ);
267 psram_init_lut_ps_write_evict_4x(PSRAM_SEQ_ID_WRITE_EVICT);
268 psram_init_lut_ps_write_4x(PSRAM_SEQ_ID_WRITE);
269 }
270 psram_init_lut_ps_qmode_enable(PSRAM_SEQ_ID_QUAD_ENABLE);
271 psram_init_lut_ps_qmode_exit(PSRAM_SEQ_ID_QUAD_EXIT);
272
273 // printf(" initialize LUT tables done. \n");
274
275 // set read miss cmd, evict is in next lut
276 REG_WR(PSRAM_BFGENCR, PSRAM_SEQ_ID_READ << 12);
277
278 if (mode_config != mode) {
279 if (mode == PSRAM_MODE_SPI) {
280 REG_WR(PSRAM_SFAR, PSRAM_AMBA_BASE);
281 REG_WR(PSRAM_IPCR, PSRAM_SEQ_ID_QUAD_EXIT << 24);
282 psram_wait_finish();
283 } else {
284 REG_WR(PSRAM_SFAR, PSRAM_AMBA_BASE);
285 REG_WR(PSRAM_IPCR, PSRAM_SEQ_ID_QUAD_ENABLE << 24);
286 psram_wait_finish();
287 }
288 }
289 mode_config = mode;
290 return 0;
291 }
292