1 /**
2 ******************************************************************************
3 * @file rtl8721d_flash_ram.c
4 * @author
5 * @version V1.0.0
6 * @date 2016-05-17
7 * @brief This file provides firmware functions to manage the flash RAM functions.
8 ******************************************************************************
9 * @attention
10 *
11 * This module is a confidential and proprietary property of RealTek and
12 * possession or use of this module requires written permission of RealTek.
13 *
14 * Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved.
15 ******************************************************************************
16 */
17
18 #include "ameba_soc.h"
19
20 static u32 cpu_systick;
21
22 /**
23 * @brief This function is used to handle flash write ipc interrupt.
24 * @param Data: The pointer will be pass the IRQ handler
25 * @param IrqStatus: this specify the IPC_ISR.
26 * @param ChanNum: this specify the IPC channel number.
27 * @retval none
28 */
29 IMAGE2_RAM_TEXT_SECTION
FLASH_Write_IPC_Int(VOID * Data,u32 IrqStatus,u32 ChanNum)30 void FLASH_Write_IPC_Int(VOID *Data, u32 IrqStatus, u32 ChanNum)
31 {
32 /* To avoid gcc warnings */
33 ( void ) Data;
34 ( void ) IrqStatus;
35 ( void ) ChanNum;
36
37 /*disable all interrupts first if primask is clear, or the CPU can't sleep*/
38 if(__get_PRIMASK() == 0) {
39 asm volatile ("cpsid i" : : : "memory");
40 //asm volatile ("cpsid f" : : : "memory");
41
42 asm volatile ("wfe");
43 asm volatile ("wfe");
44
45 asm volatile ("cpsie i" : : : "memory");
46 //asm volatile ("cpsie f" : : : "memory");
47 } else {
48 asm volatile ("wfe");
49 asm volatile ("wfe");
50 }
51 }
52
53 /**
54 * @brief This function is used to lock CPU when write or erase flash under XIP.
55 * @note
56 * - all interrupt include systick will be stopped.
57 * @retval none
58 */
59 IMAGE2_RAM_TEXT_SECTION
FLASH_Write_Lock(void)60 void FLASH_Write_Lock(void)
61 {
62 u32 cpu_id = IPC_CPUID();
63 u32 lp_sleep_state;
64
65 asm volatile ("cpsid i" : : : "memory");
66 cpu_systick = SysTick->CTRL; //disable systick exception
67 SysTick->CTRL = 0;
68
69 //u32 hp_sleep_state;
70 /*IPC request to let the other CPU sleep*/
71 if (cpu_id == 1) {
72 ipc_send_message(IPC_INT_CHAN_FLASHPG_REQ, (uint32_t)NULL);
73 while(1) {
74 lp_sleep_state = HAL_READ32(SYSTEM_CTRL_BASE_LP, REG_LP_KM0_CTRL); /*get KM0 sleep status*/
75 if(lp_sleep_state & BIT_KM0_SLEEPSYS) {
76 break;
77 }
78 }
79 } else {
80 #if defined (ARM_CORE_CM0)
81 u32 hp_sleep_state;
82 if(km4_status_on()) {
83 ipc_send_message(IPC_INT_CHAN_FLASHPG_REQ, (uint32_t)NULL);
84 while(1) {
85 hp_sleep_state = HAL_READ32(SYSTEM_CTRL_BASE_HP, REG_HS_PLATFORM_PARA); /*get KM4 sleep status*/
86 if(hp_sleep_state & BIT_KM4_SLEEP_STATUS) {
87 break;
88 }
89 }
90 }
91 #endif
92 }
93 }
94
95 /**
96 * @brief This function is used to unlock CPU after write or erase flash under XIP.
97 * @note
98 * - all interrupt will be restored.
99 * @retval none
100 */
101 IMAGE2_RAM_TEXT_SECTION
FLASH_Write_Unlock(void)102 void FLASH_Write_Unlock(void)
103 {
104 u32 cpu_id = IPC_CPUID();
105 u32 lp_sleep_state;
106 //u32 hp_sleep_state;
107
108 /*send an event using "sev" instruction to let the other CPU wake up*/
109 asm volatile ("sev");
110 if (cpu_id == 1) {
111 while(1) {
112 lp_sleep_state = HAL_READ32(SYSTEM_CTRL_BASE_LP, REG_LP_KM0_CTRL); /*get KM0 sleep status*/
113 if(!(lp_sleep_state & BIT_KM0_SLEEPSYS)) {
114 break;
115 }
116 }
117 } else {
118 #if defined (ARM_CORE_CM0)
119 u32 hp_sleep_state;
120 if(km4_status_on()) {
121 while(1) {
122 hp_sleep_state = HAL_READ32(SYSTEM_CTRL_BASE_HP, REG_HS_PLATFORM_PARA); /*get KM4 sleep status*/
123 if(!(hp_sleep_state & BIT_KM4_SLEEP_STATUS)) {
124 break;
125 }
126 }
127 }
128 #endif
129 }
130
131 SysTick->CTRL = cpu_systick;//restore systick exception
132 asm volatile ("cpsie i" : : : "memory");
133 }
134
135 /**
136 * @brief This function is used to send Rx command to flash to get status register or flash id, and lock CPU when Rx
137 * @param cmd: command that need to be sent.
138 * @param read_len: the number of bytes that will be read by SPIC after sending cmd.
139 * @param read_data: pointer to a byte array which is used to save received data.
140 * @note This function is only used for rx status/flash id ,not used for read flash data.
141 * Only work in OneBitMode.
142 * @retval none
143 */
144 IMAGE2_RAM_TEXT_SECTION
FLASH_RxCmdXIP(u8 cmd,u32 read_len,u8 * read_data)145 void FLASH_RxCmdXIP(u8 cmd, u32 read_len, u8* read_data)
146 {
147 FLASH_Write_Lock();
148
149 FLASH_RxCmd(cmd, read_len, read_data);
150
151 FLASH_Write_Unlock();
152 }
153
154 /**
155 * @brief FLASH_SetStatus used to set register status. FLASH_WriteEn & FLASH_WaitBusy, and lock CPU when set
156 * are included in this function to avoid hardfault when TxCmd in XIP
157 * @param Cmd: command to be sent
158 * @param Len: the number of bytes to be sent after Cmd
159 * @param Status: pointer to byte array to be sent
160 * @retval none
161 */
162 IMAGE2_RAM_TEXT_SECTION
FLASH_SetStatusXIP(u8 Cmd,u32 Len,u8 * Status)163 void FLASH_SetStatusXIP(u8 Cmd, u32 Len, u8* Status)
164 {
165 FLASH_Write_Lock();
166
167 FLASH_SetStatus(Cmd, Len, Status);
168
169 FLASH_Write_Unlock();
170 }
171
172 /**
173 * @brief FLASH_SetStatusBits set or clear status bits., used to set protect bit or quad enable bit, and lock CPU when set
174 * @param SetBits: 16bits valid, SetBits[7:0] is status1 & SetBits[15:8] is status2
175 * @param NewState: ENABLE/DISABLE
176 * @retval none
177 */
178 IMAGE2_RAM_TEXT_SECTION
FLASH_SetStatusBitsXIP(u32 SetBits,u32 NewState)179 void FLASH_SetStatusBitsXIP(u32 SetBits, u32 NewState)
180 {
181 FLASH_Write_Lock();
182
183 FLASH_SetStatusBits(SetBits, NewState);
184
185 FLASH_Write_Unlock();
186 }
187
188 /**
189 * @brief This function is used to write data to flash in OneBitMode and User Mode, and lock CPU when write.
190 * @param StartAddr: Start address in flash from which SPIC writes.
191 * @param DataPhaseLen: the number of bytes that SPIC sends in Data Phase.
192 * @param pData: pointer to a byte array that is to be sent.
193 * @note
194 * - page program(256B) time typical is 0.7ms: BaudRate=2.9Mbps, so one bit mode is enough.
195 * - page program(12B) time typical is 20+2.5*11= 47.5us BaudRate = 2.02M bps, so program 12B once is enough.
196 * - for compatibility with amebaz, which has 16-byte TX FIFO is 16 byte and max len is 16-cmdlen = 12 byte
197 * @retval none
198 */
199 IMAGE2_RAM_TEXT_SECTION
FLASH_TxData12BXIP(u32 StartAddr,u8 DataPhaseLen,u8 * pData)200 void FLASH_TxData12BXIP(u32 StartAddr, u8 DataPhaseLen, u8* pData)
201 {
202 FLASH_Write_Lock();
203
204 FLASH_TxData12B(StartAddr, DataPhaseLen, pData);
205 Cache_Flush();
206
207 FLASH_Write_Unlock();
208 }
209
210 /**
211 * @brief This function is used to erase flash, and lock CPU when erase.
212 * @param EraseType: can be one of the following parameters:
213 @arg EraseChip: Erase the whole chip.
214 @arg EraseBlock: Erase specified block(64KB)
215 @arg EraseSector: Erase specified sector(4KB)
216 * @param Address should 4 byte align.The block/sector which
217 * the address in will be erased.
218 * @retval none
219 */
220 IMAGE2_RAM_TEXT_SECTION
FLASH_EraseXIP(u32 EraseType,u32 Address)221 void FLASH_EraseXIP(u32 EraseType, u32 Address)
222 {
223 FLASH_Write_Lock();
224
225 FLASH_Erase(EraseType, Address);
226 Cache_Flush();
227
228 FLASH_Write_Unlock();
229 }
230
231 /**
232 * @brief This function is used to erase some dwords, and keep other dwords unchanged in one sector.
233 * @param address: Start address in flash to be erased.
234 * @param dword_num: the number of dwords to be erased.
235 * @note
236 * - this function is just used for change some dwords in one sector.
237 * - this function will erase whole sector and then write back other dwords.
238 * - please dont use this function if not needed !!!!!!!!!!!!!!
239 * - FLASH_EraseXIP is recommended if need
240 * @retval none
241 */
242 IMAGE2_RAM_TEXT_SECTION
FLASH_EreaseDwordsXIP(u32 address,u32 dword_num)243 void FLASH_EreaseDwordsXIP(u32 address, u32 dword_num)
244 {
245 u32 data[2];
246 u32 idx = 0;
247 u32 opt_sector = address & ~(0xFFF);
248 u32 erase_addr = address;
249 u32 erase_num = dword_num;
250
251 /* erase backup sector */
252 FLASH_EraseXIP(EraseSector, FLASH_RESERVED_DATA_BASE);
253
254 /* backup this sector */
255 for (idx = 0; idx < 0x1000; idx += 4) {
256 u32 read_addr = opt_sector + idx;
257
258 _memcpy(data, (const void *)(SPI_FLASH_BASE + read_addr), 4);
259
260 if (erase_num > 0) {
261 if (erase_addr == read_addr) {
262 data[0] = 0xFFFFFFFF;
263 erase_addr += 4;
264 erase_num--;
265 }
266 }
267
268 FLASH_TxData12BXIP((FLASH_RESERVED_DATA_BASE + idx), 4, (u8*)data);
269 }
270
271 /* erase this sector */
272 FLASH_EraseXIP(EraseSector, opt_sector);
273
274 /* write this sector with target data erased */
275 for (idx = 0; idx < 0x1000; idx += 8) {
276 _memcpy(data, (const void *)(SPI_FLASH_BASE + FLASH_RESERVED_DATA_BASE + idx), 8);
277 FLASH_TxData12BXIP((opt_sector + idx), 8, (u8*)data);
278 }
279 }
280
281 /**
282 * @brief This function is used to write data to flash in OneBitMode and User Mode, and lock CPU when write.
283 * @param StartAddr: Start address in flash from which SPIC writes.
284 * @param DataPhaseLen: the number of bytes that SPIC sends in Data Phase.
285 * @param pData: pointer to a byte array that is to be sent.
286 * @note
287 * - page program(256B) time typical is 0.7ms: BaudRate=2.9Mbps, so one bit mode is enough.
288 * - should use FLASH_SW_CS_Control to protect flash write
289 * @retval none
290 */
291 IMAGE2_RAM_TEXT_SECTION
FLASH_TxData256BXIP(u32 StartAddr,u32 DataPhaseLen,u8 * pData)292 void FLASH_TxData256BXIP(u32 StartAddr, u32 DataPhaseLen, u8* pData)
293 {
294 FLASH_Write_Lock();
295
296 FLASH_TxData256B(StartAddr, DataPhaseLen, pData);
297
298 Cache_Flush();
299 FLASH_Write_Unlock();
300 }
301
302 /**
303 * @brief Read a stream of data from specified address
304 * @param obj: Flash object define in application software.
305 * @param address: Specifies the starting address to read from.
306 * @param len: Specifies the length of the data to read.
307 * @param data: Specified the address to save the readback data.
308 * @retval status: Success:1 or Failure: Others.
309 * @note auto mode is ok, because we have flash cache
310 */
311 IMAGE2_RAM_TEXT_SECTION
FLASH_ReadStream(u32 address,u32 len,u8 * data)312 int FLASH_ReadStream(u32 address, u32 len, u8 * data)
313 {
314 assert_param(data != NULL);
315
316 u32 offset_to_align;
317 u32 i;
318 u32 read_word;
319 u8 *ptr;
320 u8 *pbuf;
321
322 offset_to_align = address & 0x03;
323 pbuf = data;
324 if (offset_to_align != 0) {
325 /* the start address is not 4-bytes aligned */
326 read_word = HAL_READ32(SPI_FLASH_BASE, (address - offset_to_align));
327 ptr = (u8*)&read_word + offset_to_align;
328 offset_to_align = 4 - offset_to_align;
329 for (i=0;i<offset_to_align;i++) {
330 *pbuf = *(ptr+i);
331 pbuf++;
332 len--;
333 if (len == 0) {
334 break;
335 }
336 }
337 }
338
339 /* address = next 4-bytes aligned */
340 address = (((address-1) >> 2) + 1) << 2;
341
342 ptr = (u8*)&read_word;
343 if ((u32)pbuf & 0x03) {
344 while (len >= 4) {
345 read_word = HAL_READ32(SPI_FLASH_BASE, address);
346 for (i=0;i<4;i++) {
347 *pbuf = *(ptr+i);
348 pbuf++;
349 }
350 address += 4;
351 len -= 4;
352 }
353 } else {
354 while (len >= 4) {
355 *((u32 *)pbuf) = HAL_READ32(SPI_FLASH_BASE, address);
356 pbuf += 4;
357 address += 4;
358 len -= 4;
359 }
360 }
361
362 if (len > 0) {
363 read_word = HAL_READ32(SPI_FLASH_BASE, address);
364 for (i=0;i<len;i++) {
365 *pbuf = *(ptr+i);
366 pbuf++;
367 }
368 }
369
370 return 1;
371 }
372
373 /**
374 * @brief Write a stream of data to specified address
375 * @param address: Specifies the starting address to write to.
376 * @param len: Specifies the length of the data to write.
377 * @param data: Pointer to a byte array that is to be written.
378 * @retval status: Success:1 or Failure: Others.
379 */
380 IMAGE2_RAM_TEXT_SECTION
FLASH_WriteStream(u32 address,u32 len,u8 * data)381 int FLASH_WriteStream(u32 address, u32 len, u8 * data)
382 {
383 // Check address: 4byte aligned & page(256bytes) aligned
384 u32 page_begin = address & (~0xff);
385 u32 page_end = (address + len) & (~0xff);
386 u32 page_cnt = ((page_end - page_begin) >> 8) + 1;
387
388 u32 addr_begin = address;
389 u32 addr_end = (page_cnt == 1) ? (address + len) : (page_begin + 0x100);
390 u32 size = addr_end - addr_begin;
391 u8 *buffer = data;
392 u8 write_data[12];
393
394 u32 offset_to_align;
395 u32 read_word;
396 u32 i;
397
398 FLASH_Write_Lock();
399 while(page_cnt){
400 offset_to_align = addr_begin & 0x3;
401
402 if(offset_to_align != 0){
403 read_word = HAL_READ32(SPI_FLASH_BASE, addr_begin - offset_to_align);
404 for(i = offset_to_align;i < 4;i++){
405 read_word = (read_word & (~(0xff << (8*i)))) |( (*buffer) <<(8*i));
406 size--;
407 buffer++;
408 if(size == 0)
409 break;
410 }
411 FLASH_TxData12B(addr_begin - offset_to_align, 4, (u8*)&read_word);
412 }
413
414 addr_begin = (((addr_begin-1) >> 2) + 1) << 2;
415 for(;size >= 12 ;size -= 12){
416 _memcpy(write_data, buffer, 12);
417 FLASH_TxData12B(addr_begin, 12, write_data);
418
419 buffer += 12;
420 addr_begin += 12;
421 }
422
423 for(;size >= 4; size -=4){
424 _memcpy(write_data, buffer, 4);
425 FLASH_TxData12B(addr_begin, 4, write_data);
426
427 buffer += 4;
428 addr_begin += 4;
429 }
430
431 if(size > 0){
432 read_word = HAL_READ32(SPI_FLASH_BASE, addr_begin);
433 for( i = 0;i < size;i++){
434 read_word = (read_word & (~(0xff << (8*i)))) | ((*buffer) <<(8*i));
435 buffer++;
436 }
437 FLASH_TxData12B(addr_begin, 4, (u8*)&read_word);
438 }
439
440 page_cnt--;
441 addr_begin = addr_end;
442 addr_end = (page_cnt == 1) ? (address + len) : (((addr_begin>>8) + 1)<<8);
443 size = addr_end - addr_begin;
444 }
445
446 Cache_Flush();
447 FLASH_Write_Unlock();
448
449 return 1;
450 }
451
452 /**
453 * @brief Configure SPIC IP Clock.
454 * @param Source: This parameter can be one of the following values:
455 * @arg BIT_SHIFT_FLASH_CLK_XTAL
456 * @arg BIT_SHIFT_FLASH_CLK_PLL
457 * @param Protection: if disable interrupt when switch clock:
458 * @retval None
459 */
460 IMAGE2_RAM_TEXT_SECTION
FLASH_ClockSwitch(u32 Source,u32 Protection)461 void FLASH_ClockSwitch(u32 Source, u32 Protection)
462 {
463 /* To avoid gcc warnings */
464 ( void ) Source;
465 ( void ) Protection;
466 #if defined (ARM_CORE_CM0)
467 //SPIC_TypeDef *spi_flash = SPIC;
468 u32 Temp = 0;
469 u32 timeout = 20;
470
471 if (Protection) {
472 asm volatile ("cpsid i" : : : "memory");
473 //asm volatile ("cpsid f" : : : "memory");
474 SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
475 }
476
477 /* sequence should be followed strickly */
478 if (Source == BIT_SHIFT_FLASH_CLK_XTAL) {
479 /* 1. clock source switch to XTAL */
480 Temp = HAL_READ32(SYSTEM_CTRL_BASE_LP, REG_LP_CLK_CTRL0);
481 Temp &= ~(BIT_MASK_FLASH_CLK_SEL << BIT_SHIFT_FLASH_CLK_SEL);
482 Temp |= Source;
483 HAL_WRITE32(SYSTEM_CTRL_BASE_LP, REG_LP_CLK_CTRL0, Temp);
484 DelayUs(10);
485
486 /* 2. close 400M & 400MPS */
487 Temp = HAL_READ32(PERI_ON_BASE, REG_LP_FLASH_CTRL);
488 Temp &= ~(BIT_FLASH_CK_PS_DIV_EN | BIT_FLASH_CK_DIV_EN); /* disable clock ps div & disable clock div*/
489 HAL_WRITE32(PERI_ON_BASE, REG_LP_FLASH_CTRL, Temp);
490 FLASH_CalibrationNewCmd(DISABLE);
491
492 Temp = HAL_READ32(SYSTEM_CTRL_BASE_LP, REG_PLL_SYS_PS_REG);
493 Temp &= ~BIT_EN_CK_400M;
494 HAL_WRITE32(SYSTEM_CTRL_BASE_LP, REG_PLL_SYS_PS_REG, Temp);
495
496 Temp = HAL_READ32(SYSTEM_CTRL_BASE_LP, REG_PLL_SYS_PS_REG);
497 Temp &= ~BIT_POW_CKGEN_400M;
498 HAL_WRITE32(SYSTEM_CTRL_BASE_LP, REG_PLL_SYS_PS_REG, Temp);
499
500 /* 3. SPIC Dummy to low speed dummy */
501 flash_init_para.FLASH_rd_sample_phase = SPIC_LOWSPEED_SAMPLE_PHASE;
502 FLASH_SetSpiMode(&flash_init_para, flash_init_para.FLASH_cur_bitmode);
503 } else if (Source == BIT_SHIFT_FLASH_CLK_PLL) {
504 /* 1. enable 400M & 400MPS */
505 Temp = HAL_READ32(SYSTEM_CTRL_BASE_LP, REG_PLL_SYS_PS_REG);
506 Temp |= BIT_POW_CKGEN_400M;
507 HAL_WRITE32(SYSTEM_CTRL_BASE_LP, REG_PLL_SYS_PS_REG, Temp);
508
509 Temp = HAL_READ32(SYSTEM_CTRL_BASE_LP, REG_PLL_SYS_PS_REG);
510 Temp |= BIT_EN_CK_400M;
511 HAL_WRITE32(SYSTEM_CTRL_BASE_LP, REG_PLL_SYS_PS_REG, Temp);
512
513 FLASH_CalibrationNewCmd(ENABLE);
514 Temp = HAL_READ32(PERI_ON_BASE, REG_LP_FLASH_CTRL);
515 Temp |= (BIT_FLASH_CK_PS_DIV_EN | BIT_FLASH_CK_DIV_EN); /* enable clock ps div & enable clock div*/
516 HAL_WRITE32(PERI_ON_BASE, REG_LP_FLASH_CTRL, Temp);
517
518 /* wait clock ready about 40us */
519 while (timeout > 0) {
520 timeout--;
521 Temp = HAL_READ32(PERI_ON_BASE, REG_LP_FLASH_CTRL);
522 if ((Temp & BIT_FLASH_PS_DIV_RDY) && (Temp & BIT_FLASH_DIV_RDY))
523 break;
524 }
525
526 /* 2. clock source switch */
527 Temp = HAL_READ32(SYSTEM_CTRL_BASE_LP, REG_LP_CLK_CTRL0);
528 Temp &= ~(BIT_MASK_FLASH_CLK_SEL << BIT_SHIFT_FLASH_CLK_SEL);
529 Temp |= Source;
530 HAL_WRITE32(SYSTEM_CTRL_BASE_LP, REG_LP_CLK_CTRL0, Temp);
531 DelayUs(10);
532
533 /* 3. SPIC Dummy to high speed dummy */
534 flash_init_para.FLASH_rd_sample_phase = flash_init_para.FLASH_rd_sample_phase_cal;
535 FLASH_SetSpiMode(&flash_init_para, flash_init_para.FLASH_cur_bitmode);
536 }
537
538 if (Protection) {
539 SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
540 asm volatile ("cpsie i" : : : "memory");
541 //asm volatile ("cpsie f" : : : "memory");
542 }
543 #endif
544 }
545
546 IMAGE2_RAM_TEXT_SECTION
FLASH_Invalidate_Auto_Write(void)547 void FLASH_Invalidate_Auto_Write(void)
548 {
549 /* Auto write related bits in valid command register are all set to 0,
550 just need to invalidate write single and write enable cmd in auto mode. */
551 SPIC_TypeDef *spi_flash = SPIC;
552
553 /* Disable SPI_FLASH User Mode */
554 spi_flash->ssienr = 0;
555
556 /* Invalidate write single and write enable cmd in auto mode */
557 spi_flash->wr_single = 0x0;
558 spi_flash->wr_enable = 0x0;
559 }
560
561 /******************* (C) COPYRIGHT 2016 Realtek Semiconductor *****END OF FILE****/
562