blob: 82171b6045fceccd665bbf23b877b0ef678b5970 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/******************************************************************************
2 *
3 * (C)Copyright 2005 - 2008 Marvell. All Rights Reserved.
4 *
5 * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MARVELL.
6 * The copyright notice above does not evidence any actual or intended
7 * publication of such source code.
8 * This Module contains Proprietary Information of Marvell and should be
9 * treated as Confidential.
10 * The information in this file is provided for the exclusive use of the
11 * licensees of Marvell.
12 * Such users have the right to use, modify, and incorporate this code into
13 * products for purposes authorized by the license agreement provided they
14 * include this notice and the associated copyright notice with any such
15 * product.
16 * The information in this file is provided "AS IS" without warranty.
17 *
18 ******************************************************************************/
19
20
21#include "Flash.h"
22#include "general.h"
23#include "Typedef.h"
24#include "misc.h"
25#include "Errors.h"
26#include "FM.h"
27#include "sparse_format.h"
28#include "PlatformConfig.h"
29#include "downloader.h"
30
31/**************** Steps to add a new Flash Device **********************
32 *
33 * 1. add #include 'file.h' below
34 * 2. add pointer to the initialize function of the new flash device
35 * in the InitRoutines function pointer array at the correct
36 * location - should aligned with Fuse Config number for that flash
37 *
38 *************************************************************************/
39
40//flash device includes
41#include "nand.h"
42#include "xllp_dfc.h"
43#include "sdmmc_api.h"
44#include "spi.h"
45#include "SPINAND.h"
46#if QSPINOR_CODE
47#include "spi_nor.h"
48#elif SPINOR_CODE
49#include "SPINOR.h"
50#endif
51#if QSPINAND_CODE
52#include "spi_nand.h"
53#endif
54/*static*/ FlashProperties_T FlashProp[2]; // 0 - Boot Flash, 1- Caddo Save State Flash
55static FlashBootType_T CurrentFlashBootType;
56extern SkipBlocksInfoStruct *pSkipAddress;
57UINT_T MMCEraseAll = 0;
58
59P_FlashProperties_T GetFlashProperties(FlashBootType_T FlashBootType)
60{
61
62 if (FlashBootType == BOOT_FLASH)
63 return &FlashProp[0];
64
65 if (FlashBootType == SAVE_STATE_FLASH)
66 return &FlashProp[1];
67}
68
69FlashBootType_T GetCurrentFlashBootType()
70{
71 return CurrentFlashBootType;
72}
73
74void SetCurrentFlashBootType(FlashBootType_T FlashBootType)
75{
76 CurrentFlashBootType = FlashBootType;
77 return;
78}
79
80InitFlash_F GetInitRoutine(UINT8_T FlashNum){
81
82 InitFlash_F Routine = NULL;
83
84 switch(FlashNum){
85 case NAND_FLASH_X16_HM_P:
86 case NAND_FLASH_X8_HM_P:
87 case NAND_FLASH_X16_BCH_P:
88 case NAND_FLASH_X8_BCH_P:
89 #if NAND_CODE
90 Routine = &InitializeNANDDevice;
91 #endif
92 break;
93 case CS0_XIP_FLASH_P:
94 //case CS2_XIP_SIBLEY_P:
95 #if NOR_CODE
96 Routine = &InitializeXIPDevice;
97 #endif
98 break;
99 case SDMMC_FLASH_OPT1_P:
100 case SDMMC_FLASH_OPT2_P:
101 case SDMMC_FLASH_OPT3_P:
102 case SDMMC_FLASH_OPT4_P:
103 #if MMC_CODE
104 Routine = &InitializeSDMMCDevice;
105 #endif
106 break;
107 case SPI_NOR_FLASH_P:
108 case QSPI_NOR_FLASH_P:
109 //TODO, may seperate, need swd/blf changes
110 #if QSPINOR_CODE
111 Routine = &InitializeQSPIDevice;
112 #elif SPINOR_CODE
113 Routine = &InitializeSPIDevice;
114 #endif
115 break;
116 case SPI_NAND_FLASH_P:
117 case QSPI_NAND_FLASH_P:
118 //TODO, may seperate, need swd/blf changes
119 #if QSPINAND_CODE
120 Routine = &InitializeQSPINAND;
121 #elif SPINAND_CODE
122 Routine = &InitializeSPINAND;
123 #endif
124 break;
125 default:
126 break;
127 }
128 return Routine;
129
130}
131//--------------------------------------------------------------------------------------
132// Configure_Flashes()
133//
134// This routine will configure the flashes according what the fuse settings passed in.
135//--------------------------------------------------------------------------------------
136UINT_T Configure_Flashes (UINT8_T FlashNum, FlashBootType_T fbt)
137{
138 UINT_T Retval = InvalidBootTypeError;
139 UINT_T i;
140 InitFlash_F InitializeFunction;
141 P_FlashProperties_T pFlashProp, pFlashPropBoot;
142 P_FMProperties_T pFMProp = GetFMProperties();
143 UINT8_T DefaultPartitionNum;
144
145 // Get a pointer to the FlashProperties structure
146 pFlashProp = GetFlashProperties(fbt);
147 // Need to force grabbing the BOOT_FLASH struct for reasons found in for loop below
148 pFlashPropBoot = GetFlashProperties(BOOT_FLASH);
149
150 // Check, Are we initializing the SaveStateFlash and has the BootFlash already been initialized?
151 // And are they the save flash device?
152 // If so, no need to init hardware again, just copy FlashProperties
153 if ((fbt == SAVE_STATE_FLASH) && (pFlashPropBoot->FlashSettings.FlashInitialized == TRUE))
154 {
155 if(pFlashPropBoot->FlashSettings.FlashNum == FlashNum)
156 {
157 for(i = 0; i < (sizeof(FlashProperties_T) / 4); i++)
158 ((UINT_T *)pFlashProp)[i] = ((UINT_T *)pFlashPropBoot)[i];
159 return NoError;
160 }
161 }
162
163 // If the flash that is passed in has already been initialized, return no error.
164 if ((pFlashProp->FlashSettings.FlashNum == FlashNum) && (pFlashProp->FlashSettings.FlashInitialized == TRUE) )
165 return NoError;
166
167 //Clear the Flash properties structure
168 // (Null out pointers)
169 //-------------------------------------
170 memset( pFlashProp, 0, sizeof(FlashProperties_T));
171
172 //See if we get a pointer to the appropriate
173 //init function for the assigned flash
174 //------------------------------------------
175 InitializeFunction = GetInitRoutine(FlashNum);
176 if(InitializeFunction == NULL) {
177 return InvalidBootTypeError;
178 }
179
180 Retval = InitializeFunction(FlashNum, fbt, &DefaultPartitionNum);
181 if (Retval == NoError)
182 {
183 pFMProp->PI_num = DefaultPartitionNum; // The default partition this device sets to.
184 pFlashProp->FlashSettings.FlashInitialized = TRUE;
185 pFlashProp->FlashSettings.FlashNum = FlashNum;
186 //Clear out the FM properties structure, to get rid of stale data
187 if(fbt == BOOT_FLASH)
188 ClearFM(BOOT_FLASH);
189 }
190
191 return Retval;
192}
193
194UINT_T Finalize_Flashes(FlashBootType_T fbt)
195{
196 UINT_T Retval = NoError;
197 P_FlashProperties_T pFlashProp = GetFlashProperties(fbt);
198 FinalizeFlash_F final = pFlashProp->FinalizeFlash;
199
200 //if the flash is currently not initialized, just return
201 if (pFlashProp->FlashSettings.FlashInitialized == FALSE)
202 return NoError;
203
204#if COPYIMAGESTOFLASH
205 //Finish any Flash Management
206 if(fbt == BOOT_FLASH)
207 FinalizeFM(fbt);
208#endif
209
210 //Shutdown the flash if the appropriate function is linked
211 if(final != NULL)
212 Retval = final(fbt);
213
214 //Clear out the Properties structure
215 //Clear the Flash properties structure
216 // (Null out pointers)
217 //-------------------------------------
218 memset( pFlashProp, 0, sizeof(FlashProperties_T));
219
220 return Retval;
221}
222
223#if COPYIMAGESTOFLASH
224/* Check if a certain block is in skip list*/
225int CheckIfSkip(int blk_num)
226{
227 int i, temp;
228
229 temp = pSkipAddress->Total_Number_Of_SkipBlocks;
230 for (i = 0; i < temp; i++)
231 if(blk_num == pSkipAddress->Skip_Blocks[i])
232 return TRUE;
233
234 return FALSE;
235
236}
237#endif
238
239/* ReadFlash
240 * This API function calls the relative Flash device read command to read data.
241 * This function calls the low level read on a block basis, in order to use
242 * upper level FlashManagement
243 *
244 * Inputs:
245 * flash_addr - address of where to begin read in flash device ++
246 * buffer - pointer to location of where to load the data to
247 * total_size - amount of data, in bytes, to read
248 * fbt - flash boot type: BOOT_FLASH or SAVE_STATE_FLASH
249 * Outputs:
250 * None
251 * Retval value:
252 * NoError - on successful completion
253 * <Other> - Flash device specific read error
254 *
255 * ++ if a partition table is being used, this address MUST be relative the partition's
256 * start address, and not the entire flash device
257 */
258
259UINT_T ReadFlash(UINT_T flash_addr, UINT_T buffer, UINT_T total_size, FlashBootType_T fbt)
260{
261 UINT_T Retval = NoError, Status = NoError;
262 UINT_T BlkNum, BlkSize, BlockMask, PartitionOffset, read_size, read_addr, RelocatedBlock;
263 ReadFlash_F read;
264 P_FlashProperties_T pFlashP = GetFlashProperties(fbt);
265
266#if NAND_CODE
267 P_NAND_Properties_T pNandP = GetNANDProperties();
268 UINT_T spare_size = pNandP->SpareAreaSize;
269 UINT_T page_per_block = pNandP->PagesPerBlock;
270 UINT_T total_spare_size = spare_size * page_per_block;
271#endif
272
273 read = pFlashP->ReadFromFlash;
274
275 if(read == NULL)
276 return FlashFuncNotDefined;
277
278 if (total_size == 0)
279 return NoError;
280
281#if SPINOR_CODE
282 Retval = read(flash_addr, buffer, total_size, fbt);
283#else
284
285 if(total_size & 0x3) //make size 4bytes-align
286 total_size = (total_size+4)&(~3);
287
288 //if flash_addr isn't page(2k) align, then return.
289 //if (flash_addr != 0xffffffff)
290 //{
291 // if((flash_addr & (pFlashP->PageSize-1)) )
292 // return FlashAddrNotChunkAlign;
293 //}
294
295 //set up initial values
296 BlkSize = GetBlockSize(fbt);
297 BlockMask = (BlkSize - 1); // Mask to get offset into a block
298 PartitionOffset = GetPartitionOffset(fbt);
299
300#ifdef ENABLE_BBM
301 //If the flash uses BBM, read a block at a time
302 if(pFlashP->FlashSettings.UseBBM)
303 {
304 //for the first read, only read to the end of the initial block
305 read_size = BlkSize - (BlockMask & flash_addr);
306
307 while (total_size)
308 {
309 // Find block number
310 BlkNum = (flash_addr / BlkSize);
311 // Check for relocations
312 BlkNum = LocateBlock(BlkNum, fbt);
313 // calculate the read address, in case of relocation
314 // Read Address = new block * block size + offset into the block
315 read_addr = (BlkNum * BlkSize) + (flash_addr & BlockMask);
316 // Check read amount
317 read_size = read_size > total_size ? total_size : read_size;
318 // Read in to the buffer
319 Retval = read(read_addr + PartitionOffset, buffer, read_size, fbt);
320 // save off any read disturb data
321#ifdef BITFLIPS_SCRUBBING
322 if (Retval == ReadDisturbError){
323 Retval = ScrubBlock_LegacyExt(BlkNum, &RelocatedBlock);
324 }
325#else
326 if (Retval == ReadDisturbError){
327 Retval = AddReadDisturbEntry(GetFMProperties()->PI_num, BlkNum);
328 }
329#endif
330 if (Retval != NoError)
331 break;
332
333 //update counting stats
334 // - address pointers
335 flash_addr += read_size;
336 buffer += read_size;
337
338 #if NAND_CODE
339 if (upload_nand_spare == TRUE)
340 {
341 buffer += total_spare_size;
342 }
343 #endif
344
345 // - size pointers
346 total_size -= read_size;
347 read_size = BlkSize;
348 } // End of while
349 //make sure to return any ReadDisturb that was caught
350// if(Retval == NoError) TBD_TNA - Read disturbs should be saved in another manner.
351// Retval = Status;
352 }
353 else //BBM not being used, just read the whole thing
354#endif
355 {
356 #if MMC_CODE
357 // DMA max is 16M
358 while(total_size)
359 {
360 if(total_size > 0x1000000)
361 {
362 Retval = read(flash_addr + PartitionOffset, buffer, 0x1000000, fbt);
363 if(Retval != NoError)
364 return Retval;
365
366 flash_addr += 0x1000000 / 512; // use sector address as default
367 total_size -= 0x1000000;
368 buffer += 0x1000000;
369 }
370 else
371 {
372 Retval = read(flash_addr + PartitionOffset, buffer, total_size, fbt);
373 total_size = 0;
374 }
375 }
376
377 #else
378 // this media has no BBM support. use call the media-specific write routine.
379 Retval = read(flash_addr + PartitionOffset, buffer, total_size, fbt);
380 #endif
381 }
382#endif
383 return Retval;
384}
385
386/* WriteFlash
387 * This API function calls the relative Flash device write command to program data.
388 * This function calls the low level program on a block basis, in order to use
389 * upper level FlashManagement.
390 *
391 * Inputs:
392 * flash_addr - address of where to begin write in flash device
393 * buffer - pointer to location of the data
394 * total_size - amount of data, in bytes, to program
395 * fbt - flash boot type: BOOT_FLASH or SAVE_STATE_FLASH
396 * Outputs:
397 * None
398 * Retval value:
399 * NoError - on successful completion
400 * <Other> - Flash device specific read error
401 */
402UINT_T WriteFlash(UINT_T flash_addr, UINT_T buffer, UINT_T total_size, FlashBootType_T fbt)
403{
404 UINT_T Retval = NoError, sparesize;
405#if COPYIMAGESTOFLASH
406 UINT_T BlkNum, BlkSize, BlockMask, PartitionOffset, write_size, write_addr, retry;
407 P_FlashProperties_T pFlashP = GetFlashProperties(fbt);
408 WriteFlash_F write = pFlashP->WriteToFlash;
409 UINT_T PageSize, PageMask;
410 UINT_T UseSpareFlag;
411 ReadFlash_F read = pFlashP->ReadFromFlash;
412 EraseFlash_F erase = pFlashP->EraseFlash;
413 UINT_T RestoreBuffer = 0, RestoreAddr = 0, RestoreLen = 0;
414
415 UseSpareFlag = GetUseSpareArea(BOOT_FLASH);
416
417 //if write is not defined, return with error
418 if(write == NULL)
419 return FlashFuncNotDefined;
420
421 if (total_size == 0)
422 return NoError;
423
424#if SPINOR_CODE
425 Retval = write(flash_addr, buffer, total_size, fbt);
426#else
427
428 //set up initial values
429 retry = TRUE;
430 BlkSize = GetBlockSize(fbt);
431 BlockMask = (BlkSize - 1); // Mask to get offset into a block
432 PartitionOffset = GetPartitionOffset(fbt);
433 PageSize = pFlashP->PageSize;
434 PageMask = (PageSize-1);
435 //for the first write, only write to the end of the initial block
436 write_size = BlkSize - (BlockMask & flash_addr);
437
438 if(total_size & 0x3) //make size 4bytes-align
439 total_size = (total_size+4)&(~3);
440
441
442 //if flash_addr isn't page(2k) align, then return.
443 //if (flash_addr != 0xffffffff)
444 //{
445 // if((flash_addr & PageMask) )
446 // return FlashAddrNotChunkAlign;
447 //}
448
449#ifdef ENABLE_BBM
450 // if this media has BBM support, then attempt retries on failures:
451 if( pFlashP->FlashSettings.UseBBM)
452 {
453 while (total_size)
454 {
455 // Find block number
456 BlkNum = (flash_addr / BlkSize);
457
458 // add here to judge if this block is in the skip list, if it is in skip list, then continue to next block;
459 if(pSkipAddress != NULL)
460 {
461 if(CheckIfSkip(BlkNum))
462 goto NEXT_BLOCK;
463 }
464
465 // Check for relocations
466 BlkNum = LocateBlock(BlkNum, fbt);
467 // calculate the writeaddress, in case of relocation
468 // Write Address = new block * block size + offset into the block
469 write_addr = (BlkNum * BlkSize) + (flash_addr & BlockMask);
470
471 if( UseSpareFlag)
472 {
473 sparesize = (write_size >> 5);
474 write_size = write_size + sparesize;
475 }
476 // Check write amount
477 write_size = write_size > total_size ? total_size : write_size;
478 if (RestoreBuffer) {
479 /* new restore addr due to relocation */
480 RestoreAddr = (write_addr + PartitionOffset) & (~BlockMask);
481 Retval = write(RestoreAddr, RestoreBuffer, RestoreLen, fbt);
482 if (Retval == NoError) {
483 free(RestoreBuffer);
484 RestoreBuffer = 0;
485 Retval = write(write_addr + PartitionOffset, buffer, write_size, fbt);
486 }
487 } else {
488 // Write from the buffer
489 Retval = write(write_addr + PartitionOffset, buffer, write_size, fbt);
490 }
491 //if we hit an error, retry once, then Relocate
492 if (Retval != NoError)
493 {
494 /* write addr is not block aligned, need to save previous content */
495 if(((write_addr + PartitionOffset) & (BlockMask)) && (RestoreBuffer == 0))
496 {
497 RestoreAddr = (write_addr + PartitionOffset) & (~BlockMask);
498 RestoreLen = (write_addr + PartitionOffset) - RestoreAddr;
499 RestoreBuffer = malloc(PageSize);
500 if (RestoreBuffer) {
501 Retval = read(RestoreAddr, RestoreBuffer, RestoreLen, fbt);
502 if (Retval != NoError) {
503 free(RestoreBuffer);
504 RestoreBuffer = 0;
505 }
506 }
507 }
508
509 if(retry == TRUE)
510 {
511 //turn off retry flag
512 retry = FALSE;
513 //try erasing the block
514 Retval = erase(((write_addr + PartitionOffset) & (~BlockMask)), BlkSize, fbt);
515 if (Retval != NoError)
516 Retval = erase(((write_addr + PartitionOffset) & (~BlockMask)), BlkSize, fbt);
517 if (Retval == NoError) {
518 if (RestoreBuffer) {
519 Retval = write(RestoreAddr, RestoreBuffer, RestoreLen, fbt);
520 }
521 }
522 //if the erase(restore) succeeded, retry writing same block
523 if(Retval == NoError) {
524 if (RestoreBuffer) {
525 free(RestoreBuffer);
526 RestoreBuffer = 0;
527 }
528 continue;
529 }
530 //if erase failed, fall through to relocate
531 }
532 //reset retry flag, since we will be using a different block on the next try
533 retry = TRUE;
534 //no need to capture the return BlkNum, as the next LocateBlock will catch it
535 Retval = RelocateBlock(BlkNum, &BlkNum, fbt);
536 if(Retval != NoError)
537 return Retval;
538 #if NAND_CODE //To word around the issue that BootROM disable sprare area
539 else if(IsAccessOBMBlock(flash_addr))
540 DisableSpareAreaForOBM(BlkNum*BlkSize, 0);
541 #endif
542 //retry writing, with the updated block
543 continue;
544 }
545 //update counting stats
546 // - address pointers
547NEXT_BLOCK:
548 if(UseSpareFlag)
549 flash_addr += (write_size-sparesize);
550 else
551 flash_addr += write_size;
552
553 buffer += write_size;
554 // - size pointers
555 total_size -= write_size;
556 write_size = BlkSize;
557 retry = TRUE;
558 } // End of while
559 }
560 else
561#endif
562 {
563
564 #if MMC_CODE
565 // DMA max is 16M
566 while(total_size)
567 {
568 if(total_size > 0x1000000)
569 {
570 Retval = write(flash_addr + PartitionOffset, buffer, 0x1000000, fbt);
571 if(Retval != NoError)
572 return Retval;
573
574 flash_addr += 0x1000000 / 512; // use sector addres as default
575 total_size -= 0x1000000;
576 buffer += 0x1000000;
577 }
578 else
579 {
580 Retval = write(flash_addr + PartitionOffset, buffer, total_size, fbt);
581 total_size = 0;
582 }
583 }
584
585 #else
586 // this media has no BBM support. use call the media-specific write routine.
587 Retval = write(flash_addr + PartitionOffset, buffer, total_size, fbt);
588 #endif
589 }
590#endif
591#endif
592 return Retval;
593}
594
595void ResetBBT()
596{
597 // create a new BBT
598#ifdef BBM_LEGACY_EXT
599 CreateBBT_LegacyExt(NULL);
600#else
601 CreateBBT_Legacy(NULL);
602#endif
603}
604
605#if MMC_CODE
606UINT_T EraseAllFlash(FlashBootType_T fbt)
607{
608 UINT_T Retval = NoError, flash_addr = 0;
609
610 P_SDMMC_Properties_T pSDMMCP = GetSDMMCProperties();
611
612 Retval = SetPartition(MMC_SD_USER_PARTITION, fbt);
613 if (Retval != NoError)
614 return Retval;
615
616#if 0
617 MMCEraseAll = 1;
618 UINT_T user_partition_size = pSDMMCP->CardCapacity;
619 Retval = EraseFlash(0, user_partition_size, fbt);
620#else
621 MMCEraseAll = 0;
622 UINT64 user_partition_size = pSDMMCP->CardCapacity;
623 #define SIZE_1GB 0x40000000
624
625 user_partition_size = user_partition_size * 512;
626 flash_addr = 0;
627 while(user_partition_size)
628 {
629 if(user_partition_size > SIZE_1GB)
630 {
631 Retval = EraseFlash(flash_addr, SIZE_1GB, fbt);
632 if(Retval != NoError)
633 return Retval;
634
635 flash_addr += SIZE_1GB / 512; // use sector address as default
636 user_partition_size -= SIZE_1GB;
637 }
638 else
639 {
640 Retval = EraseFlash(flash_addr, user_partition_size, fbt);
641 user_partition_size = 0;
642 }
643 }
644#endif
645 return Retval;
646}
647
648UINT_T EraseAllFlashWithoutBurn(FlashBootType_T fbt)
649{
650 UINT_T Retval = NoError;
651
652 P_SDMMC_Properties_T pSDMMCP = GetSDMMCProperties();
653 UINT_T user_partition_size = pSDMMCP->CardCapacity;
654 UINT_T boot_partition_size = pSDMMCP->BootPartitionSize;
655
656 EraseAllFlash(fbt);
657
658 MMCEraseAll = 1;
659 Retval = SetPartition(MMC_SD_BOOT_PARTITION, fbt);
660 if (Retval != NoError)
661 return Retval;
662
663 Retval = EraseFlash(0, boot_partition_size, fbt);
664 if (Retval != NoError)
665 return Retval;
666
667 Retval = SetPartition(MMC_SD_BOOT_PARTITION2, fbt);
668 if (Retval != NoError)
669 return Retval;
670
671 Retval = EraseFlash(0, boot_partition_size, fbt);
672 if (Retval != NoError)
673 return Retval;
674
675 return Retval;
676}
677#else
678UINT_T EraseAllFlash(FlashBootType_T fbt)
679{
680 UINT_T Retval = NoError;
681#if (COPYIMAGESTOFLASH)
682 P_FlashProperties_T pFlashP = GetFlashProperties(fbt);
683 P_FMProperties_T pFMProps = GetFMProperties();
684 UINT_T initial_blk, end_blk;
685
686 #if SPINOR_CODE
687 Retval = SPINOR_Wipe();
688 #else
689
690 #if defined(NAND_CODE) || defined(SPINAND_CODE)
691 initial_blk = pFlashP->NumBlocks - 1;
692 #endif
693
694#ifdef BBM_LEGACY_EXT
695 initial_blk -= ABBT_BLOCK_NUM;
696 //Erase the ABBT blocks
697 Retval = EraseFlash((initial_blk+1)*pFlashP->BlockSize, pFlashP->BlockSize*2, fbt);
698 if(Retval != NoError)
699 return Retval;
700 SetABBTState(BBT_ERASED, fbt);
701#endif
702
703 end_blk = initial_blk - (pFlashP->NumBlocks * LEGACY_BBM_RELOC_PERCENTAGE + 99) / 100;
704
705 // erase all blocks except reserved area
706 Retval = EraseFlash(0, pFlashP->BlockSize*(end_blk+1), fbt);
707 #endif
708#endif
709 return Retval;
710}
711
712UINT_T EraseAllFlashWithoutBurn(FlashBootType_T fbt)
713{
714 UINT_T Retval = NoError;
715#if (COPYIMAGESTOFLASH)
716 P_FlashProperties_T pFlashP = GetFlashProperties(fbt);
717 P_FMProperties_T pFMProps = GetFMProperties();
718 UINT_T initial_blk, end_blk;
719
720 #if SPINOR_CODE
721 Retval = SPINOR_Wipe();
722 #else
723
724 #if defined(NAND_CODE) || defined(SPINAND_CODE)
725 initial_blk = pFlashP->NumBlocks - 1;
726 #endif
727
728#ifdef BBM_LEGACY_EXT
729 initial_blk -= ABBT_BLOCK_NUM;
730 //Erase the ABBT blocks
731 Retval = EraseFlash((initial_blk+1)*pFlashP->BlockSize, pFlashP->BlockSize*2, fbt);
732 if(Retval != NoError)
733 return Retval;
734 SetABBTState(BBT_ERASED, fbt);
735#endif
736
737 end_blk = initial_blk - (pFlashP->NumBlocks * LEGACY_BBM_RELOC_PERCENTAGE + 99) / 100;
738 // erase all blocks except reserved area
739 Retval = EraseFlash(0, pFlashP->BlockSize*(end_blk-1), fbt);
740 #endif
741#endif
742 return Retval;
743}
744#endif
745
746
747UINT_T EraseFlash(UINT_T flash_addr, UINT_T size, FlashBootType_T fbt)
748{
749 UINT_T Retval = NoError;
750
751#if (COPYIMAGESTOFLASH)
752
753 UINT_T erase_addr, total_blks, BlkSize, PageSize, PartitionOffset, BlkNum, retry;
754 P_FlashProperties_T pFlashP = GetFlashProperties(fbt);
755
756 P_FMProperties_T pFMProps = GetFMProperties();
757 EraseFlash_F erase = pFlashP->EraseFlash;
758 if(erase == NULL)
759 return FlashFuncNotDefined;
760
761 if (size == 0)
762 return NoError;
763
764#if MMC_CODE
765 Retval = erase(flash_addr, size, BOOT_FLASH);
766 return Retval;
767#elif SPINOR_CODE
768 Retval = erase(flash_addr, size, fbt);
769 return Retval;
770#else
771
772 //set up initial values
773 BlkSize = pFlashP->BlockSize;
774 PageSize = pFlashP->PageSize;
775 retry = TRUE;
776 PartitionOffset = GetPartitionOffset(fbt);
777 // normalize addr and size to the whole blocks
778 BlkNum = (flash_addr / BlkSize);
779 erase_addr = BlkNum * BlkSize;
780
781 while (erase_addr < (flash_addr + size))
782 {
783 // add here to judge if this block is in the skip list, if it is in skip list, then continue to next block;
784 if(pSkipAddress != NULL)
785 {
786 if(CheckIfSkip(BlkNum))
787 goto NEXT_BLOCK;
788 }
789 //check to see if the block being erase contains a BBT or PT
790 CheckFMEraseState(BlkNum, fbt);
791
792 // Check for relocations
793 BlkNum = LocateBlock(BlkNum, fbt);
794
795 // erase the current block
796 Retval = erase( (BlkNum * BlkSize) + PartitionOffset, BlkSize, fbt);
797
798 //erase failure means either the block is bad, or device is wedged
799 if (Retval != NoError)
800 {
801 //try a reset first
802 if(retry == TRUE)
803 { //clear the flag, and reset the device
804 retry = FALSE;
805 Retval = ResetFlash(fbt);
806 //if the reset failed, device is wedged. return error
807 if(Retval != NoError)
808 return Retval;
809 else //if reset succeeded, try the block again
810 continue;
811 }
812 else
813 { //at this point, reset didn't help. so block is BAD
814
815 // if this media doesn't support BBM, there is no other recovery possible.
816 if( !pFlashP->FlashSettings.UseBBM)
817 return Retval;
818
819 //relocate block, but don't worry about catching new BlkNum, as next LocateBlock will pick it up
820 Retval = RelocateBlock(BlkNum, &BlkNum, fbt);
821 if(Retval != NoError)
822 return Retval;
823 #if NAND_CODE //To word around the issue that BootROM disable sprare area
824 else if(IsAccessOBMBlock(flash_addr))
825 DisableSpareAreaForOBM(BlkNum*BlkSize, 0);
826 #endif
827 //reset flag for the new block
828 retry = TRUE;
829 continue;
830 }
831 }
832
833NEXT_BLOCK:
834 //update counting stats
835 // - address pointers
836
837 erase_addr += BlkSize;
838 BlkNum = erase_addr / BlkSize;
839 retry = TRUE;
840 }// End of while
841#endif
842#endif
843 return Retval;
844}
845
846UINT_T ResetFlash(FlashBootType_T fbt)
847{
848 ResetFlash_F reset = GetFlashProperties(fbt)->ResetFlash;
849 if(reset == NULL)
850 return FlashFuncNotDefined;
851 else
852 return reset(fbt);
853}
854
855UINT_T ReadOTP(UINT_T OTPAddress, UINT_T LocalBuffer, UINT_T size, FlashBootType_T fbt)
856{
857#if (COPYIMAGESTOFLASH)
858 ReadOTP_F readotp = GetFlashProperties(fbt)->ReadOTP;
859
860 if(readotp == NULL)
861 return FlashFuncNotDefined;
862 else
863 return readotp(OTPAddress, LocalBuffer, size);
864#else
865 return NoError;
866#endif
867}
868
869UINT_T WriteOTP(UINT_T OTPAddress, UINT_T LocalBuffer, UINT_T size, FlashBootType_T fbt)
870{
871
872#if (COPYIMAGESTOFLASH)
873 WriteOTP_F writeotp = GetFlashProperties(fbt)->WriteOTP;
874
875 if(writeotp == NULL)
876 return FlashFuncNotDefined;
877 else
878 return writeotp(OTPAddress, LocalBuffer, size);
879#else
880 return NoError;
881#endif
882}
883
884UINT_T LockOTP(FlashBootType_T fbt)
885{
886#if (COPYIMAGESTOFLASH)
887 LockOTP_F lockotp = GetFlashProperties(fbt)->LockOTP;
888
889 if(lockotp == NULL)
890 return FlashFuncNotDefined;
891 else
892 return lockotp();
893#else
894 return NoError;
895#endif
896}
897
898#if !NAND_CODE
899UINT_T GetBlockSize(FlashBootType_T fbt)
900{
901 return GetFlashProperties(fbt)->BlockSize;
902}
903
904UINT_T GetPageSize(FlashBootType_T fbt)
905{
906 return GetFlashProperties(fbt)->PageSize;
907}
908#endif
909
910UINT_T GetEraseRegionSize(FlashBootType_T fbt)
911{
912 return GetFlashProperties(fbt)->BlockSize;
913}
914
915#if COPYIMAGESTOFLASH
916UINT_T GetUseSpareArea(FlashBootType_T fbt)
917{
918 return GetFlashProperties(fbt)->FlashSettings.UseSpareArea;
919}
920
921UINT_T SetUseSpareArea(UINT_T bUseSpareArea, FlashBootType_T fbt)
922{
923 P_FlashProperties_T pFlashProps = GetFlashProperties(fbt);
924 pFlashProps->FlashSettings.UseSpareArea = ((bUseSpareArea == 0) ? 0 : 1);
925
926 return GetUseSpareArea(fbt);
927}
928
929#if !NAND_CODE
930UINT_T GetSpareAreaSize(FlashBootType_T fbt)
931{
932 return GetFlashProperties(fbt)->FlashSettings.SASize;
933}
934#endif
935
936UINT_T SetSpareAreaSize(UINT_T SASize, FlashBootType_T fbt)
937{
938 P_FlashProperties_T pFlashProps = GetFlashProperties(fbt);
939 pFlashProps->FlashSettings.SASize = SASize;
940
941 return GetSpareAreaSize(fbt);
942}
943
944UINT_T GetUseHwEcc(FlashBootType_T fbt)
945{
946 return GetFlashProperties(fbt)->FlashSettings.UseHwEcc;
947}
948
949UINT_T SetUseHwEcc(UINT_T bUseHwEcc, FlashBootType_T fbt)
950{
951 P_FlashProperties_T pFlashProps = GetFlashProperties(fbt);
952 pFlashProps->FlashSettings.UseHwEcc = ((bUseHwEcc == 0) ? 0 : 1);
953
954#if NAND_CODE
955 xdfc_enable_ecc( bUseHwEcc );
956#endif
957
958 return GetUseHwEcc(fbt);
959}
960#endif
961
962UINT_T ConvertToLogicalAddr(UINT_T FlashLocation, FlashBootType_T fbt)
963{
964 ConvertToLogicalAddr_F logaddr = GetFlashProperties(fbt)->pConvertToLogicalAddr;
965
966 if(logaddr == NULL)
967 return FlashLocation;
968 else
969 return logaddr(FlashLocation, fbt);
970
971}
972
973#define SPARSE_HEADER_MAJOR_VER 1
974
975UINT_T HandleSparseImage(UINT_T source, UINT_T start_address, UINT_T image_length, FlashBootType_T fbt)
976{
977 sparse_header_t *header = (sparse_header_t *)source;
978 UINT_T i;
979 UINT64 logic_length = 0, outlen = 0, write_len = 0;
980 UINT_T sparse_header_length, chunk_header_length;
981 UINT_T r;
982 UINT64 len = 0;
983 chunk_header_t *chunk;
984 UINT64 tmp_total_blks, tmp_blk_sz;
985
986 if (header->magic != SPARSE_HEADER_MAGIC)
987 {
988 return Sparse_BadMagic;
989 }
990
991 if ((header->major_version != SPARSE_HEADER_MAJOR_VER) ||
992 (header->file_hdr_sz != sizeof(sparse_header_t)) ||
993 (header->chunk_hdr_sz != sizeof(chunk_header_t)))
994 {
995 return Sparse_IncompatibleFormat;
996 }
997
998 tmp_total_blks = header->total_blks;
999 tmp_blk_sz = header->blk_sz;
1000 logic_length = tmp_total_blks * tmp_blk_sz;
1001
1002 sparse_header_length = sizeof(sparse_header_t);
1003 chunk_header_length = sizeof(chunk_header_t);
1004
1005 source += sparse_header_length; // skip the sparse header
1006
1007 for (i = 0; i < header->total_chunks; i++)
1008 {
1009 chunk = (chunk_header_t *)source;
1010
1011 source += chunk_header_length; // skip the chunk header
1012
1013 switch (chunk->chunk_type)
1014 {
1015 case CHUNK_TYPE_RAW:
1016 {
1017 len = chunk->chunk_sz * header->blk_sz;
1018 write_len += len;
1019
1020 if (chunk->total_sz != (len + chunk_header_length))
1021 {
1022 return Sparse_BadChunkSize;
1023 }
1024
1025 outlen += len;
1026 if (outlen > logic_length)
1027 {
1028 return Sparse_ImageLengthLimitExceeded;
1029 }
1030
1031 r = WriteFlash(start_address, source, len, fbt); // write real data to flash
1032 if (r != NoError)
1033 {
1034 return r;
1035 }
1036
1037 start_address += len / 512; // use sector address as default
1038 source += len;
1039
1040 break;
1041 }
1042
1043 case CHUNK_TYPE_DONT_CARE:
1044 {
1045 if (chunk->total_sz != chunk_header_length)
1046 {
1047 return Sparse_BogusDontCareChunk;
1048 }
1049
1050 len = chunk->chunk_sz * header->blk_sz;
1051 outlen += len;
1052
1053 if (outlen > logic_length)
1054 {
1055 return Sparse_ImageLengthLimitExceeded;
1056 }
1057
1058 start_address += len / 512; // use sector address as default
1059
1060 break;
1061 }
1062
1063 default:
1064 return Sparse_UnknownChunkId;
1065 }
1066 }
1067
1068 if (outlen != logic_length)
1069 return Sparse_IncompatibleFormat;
1070
1071 if (write_len + sparse_header_length + header->total_chunks * chunk_header_length != image_length)
1072 return Sparse_WriteError;
1073
1074 return NoError;
1075}
1076