1 /******************************************************************************
2 * Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
3 * All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************/
18 #include "flash.h"
19 #include "core.h"
20 #include "ext_driver/ext_misc.h"
21 #include "mspi.h"
22 #include "plic.h"
23 #include "stimer.h"
24 #include "sys.h"
25 #include "timer.h"
26 #include "watchdog.h"
27
28 #include "los_timer.h"
29 #include "los_task.h"
30
31 #define RAMCODE_OPTIMIZE_UNUSED_FLASH_API_NOT_IMPLEMENT 1
32
33 _attribute_data_retention_sec_ volatile unsigned char flash_cnt = 1;
34
35 static preempt_config_t s_flash_preempt_config = {
36 .preempt_en = 0,
37 .threshold = 1,
38 };
39
40 /**
41 * @brief This function serves to set priority threshold.
42 * when the interrupt priority > Threshold flash process will disturb by interrupt.
43 * @param[in] preempt_en - 1 can disturb by interrupt, 0 can disturb by interrupt.
44 * @param[in] threshold - priority Threshold.
45 * @return none.
46 */
flash_plic_preempt_config(unsigned char preempt_en,unsigned char threshold)47 void flash_plic_preempt_config(unsigned char preempt_en, unsigned char threshold)
48 {
49 s_flash_preempt_config.preempt_en = preempt_en;
50 s_flash_preempt_config.threshold = threshold;
51 }
52
53 /**
54 * @brief This function to determine whether the flash is busy..
55 * @return 1:Indicates that the flash is busy. 0:Indicates that the flash is free
56 */
flash_is_busy(void)57 static inline int flash_is_busy(void)
58 {
59 return mspi_read() & 0x01; // the busy bit, pls check flash spec
60 }
61
62 /**
63 * @brief This function serves to set flash write command.
64 * This function interface is only used internally by flash,
65 * and is currently included in the H file for compatibility with other SDKs. When using this interface,
66 * please ensure that you understand the precautions of flash before using it.
67 * @param[in] cmd - set command.
68 * @return none.
69 */
flash_send_cmd(unsigned char cmd)70 _attribute_ram_code_sec_noinline_ void flash_send_cmd(unsigned char cmd)
71 {
72 mspi_high();
73 CLOCK_DLY_10_CYC;
74 mspi_low();
75 mspi_write(cmd);
76 mspi_wait();
77 }
78
79 /**
80 * @brief This function serves to send flash address.
81 * @param[in] addr - the flash address.
82 * @return none.
83 */
flash_send_addr(unsigned int addr)84 _attribute_ram_code_sec_noinline_ static void flash_send_addr(unsigned int addr)
85 {
86 mspi_write((unsigned char)(addr >> 16));
87 mspi_wait();
88 mspi_write((unsigned char)(addr >> 8));
89 mspi_wait();
90 mspi_write((unsigned char)(addr));
91 mspi_wait();
92 }
93
94 /**
95 * @brief This function serves to wait flash done.(make this a asynchorous version).
96 * @return none.
97 */
flash_wait_done(void)98 _attribute_ram_code_sec_noinline_ static void flash_wait_done(void)
99 {
100 flash_send_cmd(FLASH_READ_STATUS_CMD);
101
102 int i;
103 for (i = 0; i < 10000000; ++i) {
104 if (!flash_is_busy()) {
105 flash_cnt++;
106 break;
107 }
108 }
109 mspi_high();
110 }
111
112 /**
113 * @brief This function serves to erase a sector.
114 * @param[in] addr - the start address of the sector needs to erase.
115 * @return none.
116 */
flash_erase_sector_ram(unsigned long addr)117 _attribute_ram_code_sec_noinline_ void flash_erase_sector_ram(unsigned long addr)
118 {
119 LOS_SysTickTimerGet()->lock();
120 LOS_TaskLock();
121 #if SUPPORT_PFT_ARCH
122 unsigned int r = core_interrupt_disable();
123 reg_irq_threshold = 1;
124 core_restore_interrupt(r);
125 #else
126 unsigned int r = core_interrupt_disable();
127 #endif
128 mspi_stop_xip();
129 flash_send_cmd(FLASH_WRITE_ENABLE_CMD);
130 flash_send_cmd(FLASH_SECT_ERASE_CMD);
131 flash_send_addr(addr);
132 mspi_high();
133 flash_wait_done();
134 CLOCK_DLY_5_CYC;
135 #if SUPPORT_PFT_ARCH
136 r = core_interrupt_disable();
137 reg_irq_threshold = 0;
138 core_restore_interrupt(r);
139 #else
140 core_restore_interrupt(r);
141 #endif
142 LOS_SysTickTimerGet()->unlock();
143 LOS_TaskUnlock();
144 }
flash_erase_sector(unsigned long addr)145 _attribute_text_sec_ void flash_erase_sector(unsigned long addr)
146 {
147 wd_clear(); // clear watch dog (ble team add code)
148 __asm__("csrci mmisc_ctl,8"); // disable BTB
149 flash_erase_sector_ram(addr);
150 __asm__("csrsi mmisc_ctl,8"); // enable BTB
151 }
152
153 /**
154 * @brief This function writes the buffer's content to a page.
155 * @param[in] addr - the start address of the page.
156 * @param[in] len - the length(in byte) of content needs to write into the page.
157 * @param[in] buf - the start address of the content needs to write into.
158 * @return none.
159 */
flash_write_page_ram(unsigned long addr,unsigned long len,unsigned char * buf)160 _attribute_ram_code_sec_noinline_ void flash_write_page_ram(unsigned long addr, unsigned long len, unsigned char *buf)
161 {
162 LOS_SysTickTimerGet()->lock();
163 LOS_TaskLock();
164 #if SUPPORT_PFT_ARCH
165 unsigned int r = core_interrupt_disable();
166 reg_irq_threshold = 1;
167 core_restore_interrupt(r);
168 #else
169 unsigned int r = core_interrupt_disable(); // ???irq_disable();
170 #endif
171 mspi_stop_xip();
172 flash_send_cmd(FLASH_WRITE_ENABLE_CMD);
173 flash_send_cmd(FLASH_WRITE_CMD);
174 flash_send_addr(addr);
175
176 unsigned int i;
177 for (i = 0; i < len; ++i) {
178 mspi_write(buf[i]); /* write data */
179 mspi_wait();
180 }
181 mspi_high();
182 flash_wait_done();
183 CLOCK_DLY_5_CYC;
184
185 #if SUPPORT_PFT_ARCH
186 r = core_interrupt_disable();
187 reg_irq_threshold = 0;
188 core_restore_interrupt(r);
189 #else
190 core_restore_interrupt(r); // ???irq_restore(r);
191 #endif
192 LOS_SysTickTimerGet()->unlock();
193 LOS_TaskUnlock();
194 }
flash_write_page(unsigned long addr,unsigned long len,unsigned char * buf)195 _attribute_text_sec_ void flash_write_page(unsigned long addr, unsigned long len, unsigned char *buf)
196 {
197 unsigned int ns = PAGE_SIZE - (addr & 0xff);
198 int nw = 0;
199
200 do {
201 nw = len > ns ? ns : len;
202 __asm__("csrci mmisc_ctl,8"); // disable BTB
203 flash_write_page_ram(addr, nw, buf);
204 __asm__("csrsi mmisc_ctl,8"); // enable BTB
205 ns = PAGE_SIZE;
206 addr += nw;
207 buf += nw;
208 len -= nw;
209 } while (len > 0);
210 }
211
212 /**
213 * @brief This function reads the content from a page to the buf.
214 * @param[in] addr - the start address of the page.
215 * @param[in] len - the length(in byte) of content needs to read out from the page.
216 * @param[out] buf - the start address of the buffer.
217 * @return none.
218 */
flash_read_page_ram(unsigned long addr,unsigned long len,unsigned char * buf)219 _attribute_ram_code_sec_noinline_ void flash_read_page_ram(unsigned long addr, unsigned long len, unsigned char *buf)
220 {
221 LOS_SysTickTimerGet()->lock();
222 LOS_TaskLock();
223 #if SUPPORT_PFT_ARCH
224 unsigned int r = core_interrupt_disable();
225 reg_irq_threshold = 1;
226 core_restore_interrupt(r);
227 #else
228 unsigned int r = core_interrupt_disable(); // ???irq_disable();
229 #endif
230 mspi_stop_xip();
231 flash_send_cmd(FLASH_READ_CMD);
232 flash_send_addr(addr);
233
234 mspi_write(0x00); /* dummy, to issue clock */
235 mspi_wait();
236 mspi_fm_rd_en(); /* auto mode, mspi_get() automatically triggers mspi_write(0x00) once. */
237 mspi_wait();
238 /* get data */
239 for (unsigned int i = 0; i < len; ++i) {
240 *buf++ = mspi_get();
241 mspi_wait();
242 }
243 mspi_fm_rd_dis(); /* off read auto mode */
244 mspi_high();
245 CLOCK_DLY_5_CYC;
246 #if SUPPORT_PFT_ARCH
247 r = core_interrupt_disable();
248 reg_irq_threshold = 0;
249 core_restore_interrupt(r);
250 #else
251 core_restore_interrupt(r); // ???irq_restore(r);
252 #endif
253 LOS_SysTickTimerGet()->unlock();
254 LOS_TaskUnlock();
255 }
flash_read_page(unsigned long addr,unsigned long len,unsigned char * buf)256 _attribute_text_sec_ void flash_read_page(unsigned long addr, unsigned long len, unsigned char *buf)
257 {
258 __asm__("csrci mmisc_ctl,8"); // disable BTB
259 flash_read_page_ram(addr, len, buf);
260 __asm__("csrsi mmisc_ctl,8"); // enable BTB
261 }
262
263 /**
264 * @brief This function serves to erase a chip.
265 * @return none.
266 */
flash_erase_chip_ram(void)267 _attribute_ram_code_sec_noinline_ void flash_erase_chip_ram(void)
268 {
269 #if SUPPORT_PFT_ARCH
270 unsigned int r = core_interrupt_disable();
271 reg_irq_threshold = 1;
272 core_restore_interrupt(r);
273 #else
274 unsigned int r = core_interrupt_disable();
275 #endif
276 mspi_stop_xip();
277 flash_send_cmd(FLASH_WRITE_ENABLE_CMD);
278 flash_send_cmd(FLASH_CHIP_ERASE_CMD);
279 mspi_high();
280 flash_wait_done();
281 CLOCK_DLY_5_CYC;
282 #if SUPPORT_PFT_ARCH
283 r = core_interrupt_disable();
284 reg_irq_threshold = 0;
285 core_restore_interrupt(r);
286 #else
287 core_restore_interrupt(r);
288 #endif
289 }
flash_erase_chip(void)290 _attribute_text_sec_ void flash_erase_chip(void)
291 {
292 __asm__("csrci mmisc_ctl,8"); // disable BTB
293 flash_erase_chip_ram();
294 __asm__("csrsi mmisc_ctl,8"); // enable BTB
295 }
296
297 #if (!RAMCODE_OPTIMIZE_UNUSED_FLASH_API_NOT_IMPLEMENT)
298 /**
299 * @brief This function serves to erase a page(256 bytes).
300 * @param[in] addr - the start address of the page needs to erase.
301 * @return none.
302 */
flash_erase_page_ram(unsigned int addr)303 _attribute_ram_code_sec_noinline_ void flash_erase_page_ram(unsigned int addr)
304 {
305 #if SUPPORT_PFT_ARCH
306 unsigned int r = core_interrupt_disable();
307 reg_irq_threshold = 1;
308 core_restore_interrupt(r);
309 #else
310 unsigned int r = core_interrupt_disable();
311 #endif
312
313 mspi_stop_xip();
314 flash_send_cmd(FLASH_WRITE_ENABLE_CMD);
315 flash_send_cmd(FLASH_PAGE_ERASE_CMD);
316 flash_send_addr(addr);
317 mspi_high();
318 flash_wait_done();
319 CLOCK_DLY_5_CYC;
320 #if SUPPORT_PFT_ARCH
321 r = core_interrupt_disable();
322 reg_irq_threshold = 0;
323 core_restore_interrupt(r);
324 #else
325 core_restore_interrupt(r); // ???irq_restore(r);
326 #endif
327 }
flash_erase_page(unsigned int addr)328 _attribute_text_sec_ void flash_erase_page(unsigned int addr)
329 {
330 __asm__("csrci mmisc_ctl,8"); // disable BTB
331 flash_erase_page_ram(addr);
332 __asm__("csrsi mmisc_ctl,8"); // enable BTB
333 }
334
335 /**
336 * @brief This function serves to erase a block(32k).
337 * @param[in] addr - the start address of the block needs to erase.
338 * @return none.
339 */
flash_erase_32kblock_ram(unsigned int addr)340 _attribute_ram_code_sec_noinline_ void flash_erase_32kblock_ram(unsigned int addr)
341 {
342 #if SUPPORT_PFT_ARCH
343 unsigned int r = core_interrupt_disable();
344 reg_irq_threshold = 1;
345 core_restore_interrupt(r);
346 #else
347 unsigned int r = core_interrupt_disable();
348 #endif
349
350 mspi_stop_xip();
351 flash_send_cmd(FLASH_WRITE_ENABLE_CMD);
352 flash_send_cmd(FLASH_32KBLK_ERASE_CMD);
353 flash_send_addr(addr);
354 mspi_high();
355 flash_wait_done();
356 CLOCK_DLY_5_CYC;
357 #if SUPPORT_PFT_ARCH
358 r = core_interrupt_disable();
359 reg_irq_threshold = 0;
360 core_restore_interrupt(r);
361 #else
362 core_restore_interrupt(r); // ???irq_restore(r);
363 #endif
364 }
flash_erase_32kblock(unsigned int addr)365 _attribute_text_sec_ void flash_erase_32kblock(unsigned int addr)
366 {
367 __asm__("csrci mmisc_ctl,8"); // disable BTB
368 flash_erase_32kblock_ram(addr);
369 __asm__("csrsi mmisc_ctl,8"); // enable BTB
370 }
371
372 /**
373 * @brief This function serves to erase a block(64k).
374 * @param[in] addr - the start address of the block needs to erase.
375 * @return none.
376 */
flash_erase_64kblock_ram(unsigned int addr)377 _attribute_ram_code_sec_noinline_ void flash_erase_64kblock_ram(unsigned int addr)
378 {
379 #if SUPPORT_PFT_ARCH
380 unsigned int r = core_interrupt_disable();
381 reg_irq_threshold = 1;
382 core_restore_interrupt(r);
383 #else
384 unsigned int r = core_interrupt_disable();
385 #endif
386
387 mspi_stop_xip();
388 flash_send_cmd(FLASH_WRITE_ENABLE_CMD);
389 flash_send_cmd(FLASH_64KBLK_ERASE_CMD);
390 flash_send_addr(addr);
391 mspi_high();
392 flash_wait_done();
393 CLOCK_DLY_5_CYC;
394 #if SUPPORT_PFT_ARCH
395 r = core_interrupt_disable();
396 reg_irq_threshold = 0;
397 core_restore_interrupt(r);
398 #else
399 core_restore_interrupt(r); // ???irq_restore(r);
400 #endif
401 }
flash_erase_64kblock(unsigned int addr)402 _attribute_text_sec_ void flash_erase_64kblock(unsigned int addr)
403 {
404 __asm__("csrci mmisc_ctl,8"); // disable BTB
405 flash_erase_64kblock_ram(addr);
406 __asm__("csrsi mmisc_ctl,8"); // enable BTB
407 }
408
409 /**
410 * @brief This function write the status of flash.
411 * @param[in] data - the value of status.
412 * @return none.
413 */
flash_write_status_ram(unsigned short data)414 _attribute_ram_code_sec_noinline_ void flash_write_status_ram(unsigned short data)
415 {
416 #if SUPPORT_PFT_ARCH
417 unsigned int r = core_interrupt_disable();
418 reg_irq_threshold = 1;
419 core_restore_interrupt(r);
420 #else
421 unsigned int r = core_interrupt_disable();
422 #endif
423 mspi_stop_xip();
424 flash_send_cmd(FLASH_WRITE_ENABLE_CMD);
425 flash_send_cmd(FLASH_WRITE_STATUS_CMD);
426 mspi_write((unsigned char)data);
427 mspi_wait();
428 mspi_write((unsigned char)(data >> 8));
429 mspi_wait();
430 mspi_high();
431 flash_wait_done();
432 mspi_high();
433 CLOCK_DLY_5_CYC;
434 #if SUPPORT_PFT_ARCH
435 r = core_interrupt_disable();
436 reg_irq_threshold = 0;
437 core_restore_interrupt(r);
438 #else
439 core_restore_interrupt(r); // ???irq_restore(r);
440 #endif
441 }
flash_write_status(unsigned short data)442 _attribute_text_sec_ void flash_write_status(unsigned short data)
443 {
444 __asm__("csrci mmisc_ctl,8"); // disable BTB
445 flash_write_status_ram(data);
446 __asm__("csrsi mmisc_ctl,8"); // enable BTB
447 }
448
449 /**
450 * @brief This function reads the status of flash.
451 * @return the value of status.
452 */
flash_read_status_ram(void)453 _attribute_ram_code_sec_noinline_ unsigned short flash_read_status_ram(void)
454 {
455 unsigned short status = 0;
456 #if SUPPORT_PFT_ARCH
457 unsigned int r = core_interrupt_disable();
458 reg_irq_threshold = 1;
459 core_restore_interrupt(r);
460 #else
461 unsigned int r = core_interrupt_disable();
462 #endif
463
464 mspi_stop_xip();
465 flash_send_cmd(FLASH_READ_STATUS_1_CMD); /* get high 8 bit status */
466 status = (mspi_read() << 8);
467 mspi_high();
468 flash_send_cmd(FLASH_READ_STATUS_CMD); /* get low 8 bit status */
469 status |= mspi_read();
470 mspi_high();
471 CLOCK_DLY_5_CYC;
472
473 #if SUPPORT_PFT_ARCH
474 r = core_interrupt_disable();
475 reg_irq_threshold = 0;
476 core_restore_interrupt(r);
477 #else
478 core_restore_interrupt(r); // ???irq_restore(r);
479 #endif
480 return status;
481 }
flash_read_status(void)482 _attribute_text_sec_ unsigned short flash_read_status(void)
483 {
484 __asm__("csrci mmisc_ctl,8"); // disable BTB
485 unsigned short status = flash_read_status_ram();
486 __asm__("csrsi mmisc_ctl,8"); // enable BTB
487 return status;
488 }
489
490 /**
491 * @brief Deep Power Down mode to put the device in the lowest consumption mode
492 * it can be used as an extra software protection mechanism,while the device
493 * is not in active use,since in the mode, all write,Program and Erase commands
494 * are ignored,except the Release from Deep Power-Down and Read Device ID(RDI)
495 * command.This release the device from this mode
496 * @return none.
497 */
flash_deep_powerdown_ram(void)498 _attribute_ram_code_sec_noinline_ void flash_deep_powerdown_ram(void)
499 {
500 #if SUPPORT_PFT_ARCH
501 unsigned int r = core_interrupt_disable();
502 reg_irq_threshold = 1;
503 core_restore_interrupt(r);
504 #else
505 unsigned int r = core_interrupt_disable();
506 #endif
507
508 mspi_stop_xip();
509 flash_send_cmd(FLASH_POWER_DOWN);
510 mspi_high();
511 delay_us(1);
512 CLOCK_DLY_5_CYC;
513
514 #if SUPPORT_PFT_ARCH
515 r = core_interrupt_disable();
516 reg_irq_threshold = 0;
517 core_restore_interrupt(r);
518 #else
519 core_restore_interrupt(r); // ???irq_restore(r);
520 #endif
521 }
flash_deep_powerdown(void)522 _attribute_text_sec_ void flash_deep_powerdown(void)
523 {
524 __asm__("csrci mmisc_ctl,8"); // disable BTB
525 flash_deep_powerdown_ram();
526 __asm__("csrsi mmisc_ctl,8"); // enable BTB
527 }
528
529 /**
530 * @brief The Release from Power-Down or High Performance Mode/Device ID command is a
531 * Multi-purpose command.it can be used to release the device from the power-Down
532 * State or High Performance Mode or obtain the devices electronic identification
533 * (ID)number.Release from Power-Down will take the time duration of tRES1 before
534 * the device will resume normal operation and other command are accepted.The CS#
535 * pin must remain high during the tRES1(8us) time duration.
536 * @return none.
537 */
flash_release_deep_powerdown_ram(void)538 _attribute_ram_code_sec_noinline_ void flash_release_deep_powerdown_ram(void)
539 {
540 #if SUPPORT_PFT_ARCH
541 unsigned int r = core_interrupt_disable();
542 reg_irq_threshold = 1;
543 core_restore_interrupt(r);
544 #else
545 unsigned int r = core_interrupt_disable();
546 #endif
547
548 mspi_stop_xip();
549 flash_send_cmd(FLASH_POWER_DOWN_RELEASE);
550 mspi_high();
551 flash_wait_done();
552 mspi_high();
553 CLOCK_DLY_5_CYC;
554
555 #if SUPPORT_PFT_ARCH
556 r = core_interrupt_disable();
557 reg_irq_threshold = 0;
558 core_restore_interrupt(r);
559 #else
560 core_restore_interrupt(r); // ???irq_restore(r);
561 #endif
562 }
flash_release_deep_powerdown(void)563 _attribute_text_sec_ void flash_release_deep_powerdown(void)
564 {
565 __asm__("csrci mmisc_ctl,8"); // disable BTB
566 flash_release_deep_powerdown_ram();
567 __asm__("csrsi mmisc_ctl,8"); // enable BTB
568 }
569
570 #endif
571
572 /**
573 * @brief This function serves to read MID of flash(MAC id). Before reading UID of flash,
574 * you must read MID of flash. and then you can look up the related table to select
575 * the idcmd and read UID of flash
576 * @param[in] buf - store MID of flash
577 * @return none.
578 */
flash_read_mid_ram(unsigned char * buf)579 _attribute_ram_code_sec_noinline_ void flash_read_mid_ram(unsigned char *buf)
580 {
581 unsigned char j = 0;
582 #if SUPPORT_PFT_ARCH
583 unsigned int r = core_interrupt_disable();
584 reg_irq_threshold = 1;
585 core_restore_interrupt(r);
586 #else
587 unsigned int r = core_interrupt_disable();
588 #endif
589
590 mspi_stop_xip();
591 flash_send_cmd(FLASH_GET_JEDEC_ID);
592 mspi_write(0x00); /* dummy, to issue clock */
593 mspi_wait();
594 mspi_fm_rd_en(); /* auto mode, mspi_get() automatically triggers mspi_write(0x00) once. */
595 mspi_wait();
596
597 for (j = 0; j < 3; ++j) {
598 *buf++ = mspi_get();
599 mspi_wait();
600 }
601 mspi_fm_rd_dis(); /* off read auto mode */
602 mspi_high();
603 CLOCK_DLY_5_CYC;
604
605 #if SUPPORT_PFT_ARCH
606 r = core_interrupt_disable();
607 reg_irq_threshold = 0;
608 core_restore_interrupt(r);
609 #else
610 core_restore_interrupt(r); // ???irq_restore(r);
611 #endif
612 }
flash_read_mid(unsigned char * buf)613 _attribute_text_sec_ void flash_read_mid(unsigned char *buf)
614 {
615 __asm__("csrci mmisc_ctl,8"); // disable BTB
616 flash_read_mid_ram(buf);
617 __asm__("csrsi mmisc_ctl,8"); // enable BTB
618 }
619
620 /**
621 * @brief This function serves to read UID of flash
622 * @param[in] idcmd - different flash vendor have different read-uid command. E.g: GD/PUYA:0x4B; XTX: 0x5A
623 * @param[in] buf - store UID of flash
624 * @return none.
625 */
flash_read_uid_ram(unsigned char idcmd,unsigned char * buf)626 _attribute_ram_code_sec_noinline_ void flash_read_uid_ram(unsigned char idcmd, unsigned char *buf)
627 {
628 unsigned char j = 0;
629 #if SUPPORT_PFT_ARCH
630 unsigned int r = core_interrupt_disable();
631 reg_irq_threshold = 1;
632 core_restore_interrupt(r);
633 #else
634 unsigned int r = core_interrupt_disable();
635 #endif
636
637 mspi_stop_xip();
638 flash_send_cmd(idcmd);
639 if (idcmd == FLASH_GD_PUYA_READ_UID_CMD) { // < GD/puya
640 flash_send_addr(0x00);
641 mspi_write(0x00); /* dummy, to issue clock */
642 mspi_wait();
643 } else if (idcmd == FLASH_XTX_READ_UID_CMD) { // < XTX
644 flash_send_addr(0x80);
645 mspi_write(0x00); /* dummy, to issue clock */
646 mspi_wait();
647 }
648 mspi_write(0x00); /* dummy, to issue clock */
649 mspi_wait();
650 mspi_fm_rd_en(); /* auto mode, mspi_get() automatically triggers mspi_write(0x00) once. */
651 mspi_wait();
652
653 for (j = 0; j < 16; ++j) {
654 *buf++ = mspi_get();
655 mspi_wait();
656 }
657 mspi_fm_rd_dis(); /* off read auto mode */
658 mspi_high();
659 CLOCK_DLY_5_CYC;
660
661 #if SUPPORT_PFT_ARCH
662 r = core_interrupt_disable();
663 reg_irq_threshold = 0;
664 core_restore_interrupt(r);
665 #else
666 core_restore_interrupt(r); // ???irq_restore(r);
667 #endif
668 }
flash_read_uid(unsigned char idcmd,unsigned char * buf)669 _attribute_text_sec_ void flash_read_uid(unsigned char idcmd, unsigned char *buf)
670 {
671 __asm__("csrci mmisc_ctl,8"); // disable BTB
672 flash_read_uid_ram(idcmd, buf);
673 __asm__("csrsi mmisc_ctl,8"); // enable BTB
674 }
675
676 /**
677 * @brief This function serves to read flash mid and uid,and check the correctness of mid and uid.
678 * @param[out] flash_mid - Flash Manufacturer ID
679 * @param[out] flash_uid - Flash Unique ID
680 * @return 0:error 1:ok
681 */
flash_read_mid_uid_with_check_ram(unsigned int * flash_mid,unsigned char * flash_uid)682 _attribute_ram_code_sec_noinline_ int flash_read_mid_uid_with_check_ram(unsigned int *flash_mid,
683 unsigned char *flash_uid)
684 {
685 unsigned char no_uid[16] = {0x51, 0x01, 0x51, 0x01, 0x51, 0x01, 0x51, 0x01,
686 0x51, 0x01, 0x51, 0x01, 0x51, 0x01, 0x51, 0x01};
687 int i, f_cnt = 0;
688 unsigned int mid;
689
690 mspi_stop_xip();
691 flash_read_mid((unsigned char *)&mid);
692 mid = mid & 0xffff;
693 *flash_mid = mid;
694 // CMD MID
695 // GD25LD40C 0x4b 0x60c8
696 // GD25LD05C 0x4b 0x60c8
697 // P25Q40L 0x4b 0x6085
698 // MD25D40DGIG 0x4b 0x4051
699 if ((mid == 0x60C8) || (mid == 0x6085) || (mid == 0x4051)) {
700 flash_read_uid(FLASH_GD_PUYA_READ_UID_CMD, (unsigned char *)flash_uid);
701 } else {
702 return 0;
703 }
704 for (i = 0; i < 16; i++) {
705 if (flash_uid[i] == no_uid[i]) {
706 f_cnt++;
707 }
708 }
709 if (f_cnt == 16) { // no uid flash
710 return 0;
711 } else {
712 return 1;
713 }
714 CLOCK_DLY_5_CYC;
715 }
flash_read_mid_uid_with_check(unsigned int * flash_mid,unsigned char * flash_uid)716 _attribute_text_sec_ int flash_read_mid_uid_with_check(unsigned int *flash_mid, unsigned char *flash_uid)
717 {
718 __asm__("csrci mmisc_ctl,8"); // disable BTB
719 int result = flash_read_mid_uid_with_check_ram(flash_mid, flash_uid);
720 __asm__("csrsi mmisc_ctl,8"); // enable BTB
721 return result;
722 }
723
724 #if (!RAMCODE_OPTIMIZE_UNUSED_FLASH_API_NOT_IMPLEMENT)
725 /**
726 * @brief This function serves to set the protection area of the flash.
727 * @param[in] type - flash type include Puya.
728 * @param[in] data - refer to Driver API Doc.
729 * @return none.
730 */
flash_lock_ram(flash_type_e type,unsigned short data)731 _attribute_ram_code_sec_noinline_ void flash_lock_ram(flash_type_e type, unsigned short data)
732 {
733 #if SUPPORT_PFT_ARCH
734 unsigned int r = core_interrupt_disable();
735 reg_irq_threshold = 1;
736 core_restore_interrupt(r);
737 #else
738 unsigned int r = core_interrupt_disable();
739 #endif
740
741 mspi_stop_xip();
742 flash_send_cmd(FLASH_WRITE_ENABLE_CMD);
743 flash_send_cmd(FLASH_WRITE_STATUS_CMD);
744 if (type == FLASH_TYPE_PUYA) {
745 mspi_write((unsigned char)data);
746 mspi_wait();
747 mspi_write((unsigned char)(data >> 8)); // 16bit status
748 }
749 mspi_wait();
750 mspi_high();
751 flash_wait_done();
752 mspi_high();
753 CLOCK_DLY_5_CYC;
754
755 #if SUPPORT_PFT_ARCH
756 r = core_interrupt_disable();
757 reg_irq_threshold = 0;
758 core_restore_interrupt(r);
759 #else
760 core_restore_interrupt(r); // ???irq_restore(r);
761 #endif
762 }
flash_lock(flash_type_e type,unsigned short data)763 _attribute_text_sec_ void flash_lock(flash_type_e type, unsigned short data)
764 {
765 __asm__("csrci mmisc_ctl,8"); // disable BTB
766 flash_lock_ram(type, data);
767 __asm__("csrsi mmisc_ctl,8"); // enable BTB
768 }
769
770 /**
771 * @brief This function serves to flash release protection.
772 * @param[in] type - flash type include Puya.
773 * @return none.
774 */
flash_unlock_ram(flash_type_e type)775 _attribute_ram_code_sec_noinline_ void flash_unlock_ram(flash_type_e type)
776 {
777 #if SUPPORT_PFT_ARCH
778 unsigned int r = core_interrupt_disable();
779 reg_irq_threshold = 1;
780 core_restore_interrupt(r);
781 #else
782 unsigned int r = core_interrupt_disable();
783 #endif
784
785 mspi_stop_xip();
786 flash_send_cmd(FLASH_WRITE_ENABLE_CMD);
787 flash_send_cmd(FLASH_WRITE_STATUS_CMD);
788 if (type == FLASH_TYPE_PUYA) {
789 mspi_write(0);
790 mspi_wait();
791 mspi_write(0); // 16bit status
792 }
793 mspi_wait();
794 mspi_high();
795 flash_wait_done();
796 mspi_high();
797 CLOCK_DLY_5_CYC;
798 #if SUPPORT_PFT_ARCH
799 r = core_interrupt_disable();
800 reg_irq_threshold = 0;
801 core_restore_interrupt(r);
802 #else
803 core_restore_interrupt(r); // ???irq_restore(r);
804 #endif
805 }
flash_unlock(flash_type_e type)806 _attribute_text_sec_ void flash_unlock(flash_type_e type)
807 {
808 __asm__("csrci mmisc_ctl,8"); // disable BTB
809 flash_unlock_ram(type);
810 __asm__("csrsi mmisc_ctl,8"); // enable BTB
811 }
812
813 #endif
814