TianoCore EDK2 master
Loading...
Searching...
No Matches
SpiNorFlashJedecSfdp.c
Go to the documentation of this file.
1
18#include <Base.h>
19#include <Library/BaseLib.h>
21#include <Library/DebugLib.h>
26#include <Protocol/SpiIo.h>
28#include "SpiNorFlash.h"
30
43VOID
45 IN SPI_NOR_FLASH_INSTANCE *Instance,
46 IN UINT32 FastReadInstruction,
47 IN UINT32 FastReadModeClk,
48 IN UINT32 FastReadDummyClk
49 )
50{
51 SFPD_FAST_READ_CAPBILITY_RECORD *CapabilityEntry;
52
53 CapabilityEntry = AllocateZeroPool (sizeof (SFPD_FAST_READ_CAPBILITY_RECORD));
54 if (CapabilityEntry == NULL) {
55 DEBUG ((DEBUG_ERROR, "%a: Failed to create fast read table\n", __func__));
56 ASSERT (FALSE);
57 return;
58 }
59
60 InitializeListHead (&CapabilityEntry->NextFastReadCap);
61 CapabilityEntry->FastReadInstruction = (UINT8)FastReadInstruction;
62 CapabilityEntry->ModeClocks = (UINT8)FastReadModeClk;
63 CapabilityEntry->WaitStates = (UINT8)FastReadDummyClk;
64 InsertTailList (&Instance->FastReadTableList, &CapabilityEntry->NextFastReadCap);
65 DEBUG ((DEBUG_VERBOSE, "%a: Create and link table.\n", __func__));
66 DEBUG ((DEBUG_VERBOSE, " Instruction : 0x%x\n", FastReadInstruction));
67 DEBUG ((DEBUG_VERBOSE, " Mode bits : 0x%x\n", FastReadModeClk));
68 DEBUG ((DEBUG_VERBOSE, " Wait States (Dummy Clocks): 0x%x\n", FastReadDummyClk));
69}
70
87VOID
89 IN UINT32 SfdpEraseTypicalTime,
90 IN UINT32 SfdpEraseTimeMultiplier,
91 OUT UINT32 *EraseTypicalTime,
92 OUT UINT64 *EraseTimeout
93 )
94{
95 UINT32 UnitInMs;
96
97 UnitInMs = (SfdpEraseTypicalTime & ERASE_TYPICAL_TIME_UNITS_MASK) >> ERASE_TYPICAL_TIME_BIT_POSITION;
98 switch (UnitInMs) {
99 case ERASE_TYPICAL_TIME_UNIT_1_MS_BITMAP:
100 UnitInMs = ERASE_TYPICAL_TIME_UNIT_1_MS;
101 break;
102
103 case ERASE_TYPICAL_TIME_UNIT_16_MS_BITMAP:
104 UnitInMs = ERASE_TYPICAL_TIME_UNIT_16_MS;
105 break;
106
107 case ERASE_TYPICAL_TIME_UNIT_128_MS_BITMAP:
108 UnitInMs = ERASE_TYPICAL_TIME_UNIT_128_MS;
109 break;
110
111 case ERASE_TYPICAL_TIME_UNIT_1000_MS_BITMAP:
112 UnitInMs = ERASE_TYPICAL_TIME_UNIT_1000_MS;
113 break;
114 default:
115 DEBUG ((DEBUG_ERROR, "%a: Unsupported Erase Typical time.\n", __func__));
116 ASSERT (FALSE);
117 }
118
119 *EraseTypicalTime = UnitInMs * ((SfdpEraseTypicalTime & ERASE_TYPICAL_TIME_COUNT_MASK) + 1);
120 *EraseTimeout = 2 * (SfdpEraseTimeMultiplier + 1) * *EraseTypicalTime;
121 return;
122}
123
129VOID
131 IN SFDP_SUPPORTED_ERASE_TYPE_RECORD *SupportedEraseType
132 )
133{
134 DEBUG ((DEBUG_VERBOSE, " Erase Type %d\n", SupportedEraseType->EraseType));
135 DEBUG ((DEBUG_VERBOSE, " Erase Type instruction: 0x%x\n", SupportedEraseType->EraseInstruction));
136 DEBUG ((DEBUG_VERBOSE, " Erase size: 0x%x bytes\n", SupportedEraseType->EraseSizeInByte));
137 DEBUG ((DEBUG_VERBOSE, " Erase time: %d Milliseconds\n", SupportedEraseType->EraseTypicalTime));
138 DEBUG ((DEBUG_VERBOSE, " Erase timeout: %d Milliseconds:\n", SupportedEraseType->EraseTimeout));
139}
140
149VOID
151 IN SPI_NOR_FLASH_INSTANCE *Instance,
152 IN SFDP_SUPPORTED_ERASE_TYPE_RECORD *SupportedEraseType
153 )
154{
155 InitializeListHead (&SupportedEraseType->NextEraseType);
156 InsertTailList (&Instance->SupportedEraseTypes, &SupportedEraseType->NextEraseType);
157
158 DEBUG ((DEBUG_VERBOSE, "%a: Erase Type 0x%x is supported:\n", __func__, SupportedEraseType->EraseType));
159 DebugPrintEraseType (SupportedEraseType);
160}
161
170VOID
172 IN SPI_NOR_FLASH_INSTANCE *Instance
173 )
174{
175 SFDP_SUPPORTED_ERASE_TYPE_RECORD *SupportedEraseType;
176
177 // Build up erase type 1 entry.
178 if (Instance->SfdpBasicFlash->Erase1Size != 0) {
179 SupportedEraseType = AllocateZeroPool (sizeof (SFDP_SUPPORTED_ERASE_TYPE_RECORD));
180 if (SupportedEraseType != NULL) {
181 SupportedEraseType->EraseType = SFDP_ERASE_TYPE_1;
182 SupportedEraseType->EraseInstruction = (UINT8)Instance->SfdpBasicFlash->Erase1Instr;
183 SupportedEraseType->EraseSizeInByte = (UINT32)1 << Instance->SfdpBasicFlash->Erase1Size;
185 Instance->SfdpBasicFlash->Erase1Time,
186 Instance->SfdpBasicFlash->EraseMultiplier,
187 &SupportedEraseType->EraseTypicalTime,
188 &SupportedEraseType->EraseTimeout
189 );
190 CreateEraseTypeEntry (Instance, SupportedEraseType);
191 } else {
192 DEBUG ((DEBUG_ERROR, "%a: Memory allocated failed for SFDP_SUPPORTED_ERASE_TYPE_RECORD (Type 1).\n", __func__));
193 ASSERT (FALSE);
194 }
195 }
196
197 // Build up erase type 2 entry.
198 if (Instance->SfdpBasicFlash->Erase2Size != 0) {
199 SupportedEraseType = AllocateZeroPool (sizeof (SFDP_SUPPORTED_ERASE_TYPE_RECORD));
200 if (SupportedEraseType != NULL) {
201 SupportedEraseType->EraseType = SFDP_ERASE_TYPE_2;
202 SupportedEraseType->EraseInstruction = (UINT8)Instance->SfdpBasicFlash->Erase2Instr;
203 SupportedEraseType->EraseSizeInByte = (UINT32)1 << Instance->SfdpBasicFlash->Erase2Size;
205 Instance->SfdpBasicFlash->Erase2Time,
206 Instance->SfdpBasicFlash->EraseMultiplier,
207 &SupportedEraseType->EraseTypicalTime,
208 &SupportedEraseType->EraseTimeout
209 );
210 CreateEraseTypeEntry (Instance, SupportedEraseType);
211 } else {
212 DEBUG ((DEBUG_ERROR, "%a: Memory allocated failed for SFDP_SUPPORTED_ERASE_TYPE_RECORD (Type 2).\n", __func__));
213 ASSERT (FALSE);
214 }
215 }
216
217 // Build up erase type 3 entry.
218 if (Instance->SfdpBasicFlash->Erase3Size != 0) {
219 SupportedEraseType = AllocateZeroPool (sizeof (SFDP_SUPPORTED_ERASE_TYPE_RECORD));
220 if (SupportedEraseType != NULL) {
221 SupportedEraseType->EraseType = SFDP_ERASE_TYPE_3;
222 SupportedEraseType->EraseInstruction = (UINT8)Instance->SfdpBasicFlash->Erase3Instr;
223 SupportedEraseType->EraseSizeInByte = (UINT32)1 << Instance->SfdpBasicFlash->Erase3Size;
225 Instance->SfdpBasicFlash->Erase3Time,
226 Instance->SfdpBasicFlash->EraseMultiplier,
227 &SupportedEraseType->EraseTypicalTime,
228 &SupportedEraseType->EraseTimeout
229 );
230 CreateEraseTypeEntry (Instance, SupportedEraseType);
231 } else {
232 DEBUG ((DEBUG_ERROR, "%a: Memory allocated failed for SFDP_SUPPORTED_ERASE_TYPE_RECORD (Type 3).\n", __func__));
233 ASSERT (FALSE);
234 }
235 }
236
237 // Build up erase type 4 entry.
238 if (Instance->SfdpBasicFlash->Erase4Size != 0) {
239 SupportedEraseType = AllocateZeroPool (sizeof (SFDP_SUPPORTED_ERASE_TYPE_RECORD));
240 if (SupportedEraseType != NULL) {
241 SupportedEraseType->EraseType = SFDP_ERASE_TYPE_4;
242 SupportedEraseType->EraseInstruction = (UINT8)Instance->SfdpBasicFlash->Erase4Instr;
243 SupportedEraseType->EraseSizeInByte = (UINT32)1 << Instance->SfdpBasicFlash->Erase4Size;
245 Instance->SfdpBasicFlash->Erase4Time,
246 Instance->SfdpBasicFlash->EraseMultiplier,
247 &SupportedEraseType->EraseTypicalTime,
248 &SupportedEraseType->EraseTimeout
249 );
250 CreateEraseTypeEntry (Instance, SupportedEraseType);
251 } else {
252 DEBUG ((DEBUG_ERROR, "%a: Memory allocated failed for SFDP_SUPPORTED_ERASE_TYPE_RECORD (Type 4).\n", __func__));
253 ASSERT (FALSE);
254 }
255 }
256}
257
270BOOLEAN
272 IN UINT16 EraseType,
273 IN UINT8 TargetTypeNum,
274 IN UINT8 *TargetTypes
275 )
276{
277 UINT8 Index;
278
279 for (Index = 0; Index < TargetTypeNum; Index++) {
280 if (EraseType == *(TargetTypes + Index)) {
281 return TRUE;
282 }
283 }
284
285 return FALSE;
286}
287
315 IN SPI_NOR_FLASH_INSTANCE *Instance,
316 IN SFDP_SEARCH_ERASE_TYPE SearchType,
317 IN UINT32 SearchValue,
318 IN UINT8 SupportedTypeTargetNum,
319 IN UINT8 *SupportedTypeTarget OPTIONAL,
320 OUT SFDP_SUPPORTED_ERASE_TYPE_RECORD **EraseTypeRecord
321 )
322{
324 UINT32 ValueToCompare;
325 BOOLEAN ExitSearching;
326
327 if (IsListEmpty (&Instance->SupportedEraseTypes)) {
328 return EFI_NOT_FOUND;
329 }
330
331 *EraseTypeRecord = NULL;
332
333 //
334 // Initial the comapre value.
335 //
336 switch (SearchType) {
337 case SearchEraseTypeByType:
338 case SearchEraseTypeByCommand:
339 case SearchEraseTypeBySize:
340 break;
341 case SearchEraseTypeBySmallestSize:
342 ValueToCompare = (UINT32)-1;
343 break;
344 case SearchEraseTypeByBiggestSize:
345 ValueToCompare = 0;
346 break;
347 default:
348 return EFI_INVALID_PARAMETER;
349 }
350
351 ExitSearching = FALSE;
352 EraseType = (SFDP_SUPPORTED_ERASE_TYPE_RECORD *)GetFirstNode (&Instance->SupportedEraseTypes);
353 while (TRUE) {
354 if ((SupportedTypeTarget == NULL) || IsTargetEraseType (EraseType->EraseType, SupportedTypeTargetNum, SupportedTypeTarget)) {
355 switch (SearchType) {
356 case SearchEraseTypeByType:
357 if (EraseType->EraseType == SearchValue) {
358 *EraseTypeRecord = EraseType;
359 ExitSearching = TRUE;
360 }
361
362 break;
363
364 case SearchEraseTypeBySize:
365 if (EraseType->EraseSizeInByte == SearchValue) {
366 *EraseTypeRecord = EraseType;
367 ExitSearching = TRUE;
368 }
369
370 break;
371
372 case SearchEraseTypeByCommand:
373 if (EraseType->EraseInstruction == (UINT8)SearchValue) {
374 *EraseTypeRecord = EraseType;
375 ExitSearching = TRUE;
376 }
377
378 break;
379
380 case SearchEraseTypeBySmallestSize:
381 if (EraseType->EraseSizeInByte < ValueToCompare) {
382 ValueToCompare = EraseType->EraseSizeInByte;
383 *EraseTypeRecord = EraseType;
384 }
385
386 break;
387
388 case SearchEraseTypeByBiggestSize:
389 if (EraseType->EraseSizeInByte > ValueToCompare) {
390 ValueToCompare = EraseType->EraseSizeInByte;
391 *EraseTypeRecord = EraseType;
392 }
393
394 break;
395
396 default:
397 return EFI_INVALID_PARAMETER;
398 }
399 }
400
401 if (IsNodeAtEnd (&Instance->SupportedEraseTypes, &EraseType->NextEraseType) || ExitSearching) {
402 break;
403 }
404
405 EraseType = (SFDP_SUPPORTED_ERASE_TYPE_RECORD *)GetNextNode (&Instance->SupportedEraseTypes, &EraseType->NextEraseType);
406 }
407
408 if (*EraseTypeRecord == NULL) {
409 return EFI_NOT_FOUND;
410 }
411
412 return EFI_SUCCESS;
413}
414
440 IN SPI_NOR_FLASH_INSTANCE *Instance,
441 IN SFDP_SECTOR_REGION_RECORD *FlashRegion,
442 IN UINT32 FlashAddress,
443 IN UINT32 RemainingSize,
444 IN OUT UINT32 *BlockSizeToErase,
445 IN OUT UINT32 *BlockCountToErase,
446 OUT UINT8 *BlockEraseCommand,
447 OUT UINT32 *TypicalTime,
448 OUT UINT64 *MaximumTimeout
449 )
450{
451 EFI_STATUS Status;
453 UINT32 EraseSize;
454
455 DEBUG ((DEBUG_VERBOSE, "%a: Entry\n", __func__));
456
457 for (EraseSize = SIZE_2GB; EraseSize != 0; EraseSize = EraseSize >> 1) {
458 Status = GetEraseTypeRecord (Instance, SearchEraseTypeBySize, EraseSize, 0, NULL, &EraseType);
459 if (!EFI_ERROR (Status)) {
460 // Validate this erase type.
461 if (((FlashAddress & (EraseType->EraseSizeInByte - 1)) == 0) &&
462 (RemainingSize >= EraseType->EraseSizeInByte))
463 {
464 *BlockSizeToErase = EraseType->EraseSizeInByte;
465 *BlockCountToErase = 1;
466 *BlockEraseCommand = EraseType->EraseInstruction;
467 *TypicalTime = EraseType->EraseTypicalTime;
468 *MaximumTimeout = EraseType->EraseTimeout;
469 Status = EFI_SUCCESS;
470 break;
471 }
472 }
473 }
474
475 if (EraseType == NULL) {
476 return EFI_DEVICE_ERROR;
477 }
478
479 DEBUG ((DEBUG_VERBOSE, " Erase address at 0x%08x.\n", FlashAddress));
480 DEBUG ((DEBUG_VERBOSE, " - Erase block size : 0x%08x.\n", *BlockSizeToErase));
481 DEBUG ((DEBUG_VERBOSE, " - Erase block count : 0x%08x.\n", *BlockCountToErase));
482 DEBUG ((DEBUG_VERBOSE, " - Erase block command: 0x%02x.\n", *BlockEraseCommand));
483 DEBUG ((DEBUG_VERBOSE, " - Remaining size to erase: 0x%08x.\n", RemainingSize));
484 DEBUG ((DEBUG_VERBOSE, " - Erase typical time: %d milliseconds.\n", *TypicalTime));
485 DEBUG ((DEBUG_VERBOSE, " - Erase timeout: %d milliseconds.\n", *MaximumTimeout));
486 return EFI_SUCCESS;
487}
488
504 IN SPI_NOR_FLASH_INSTANCE *Instance,
505 IN UINT32 FlashAddress,
506 OUT SFDP_SECTOR_REGION_RECORD **FlashRegion
507 )
508{
509 SFDP_SECTOR_MAP_RECORD *SectorMapRecord;
510 SFDP_SECTOR_REGION_RECORD *RegionRecord;
511
512 DEBUG ((DEBUG_VERBOSE, "%a: Entry\n", __func__));
513
514 SectorMapRecord = Instance->CurrentSectorMap;
515 if (SectorMapRecord == NULL) {
516 return EFI_DEVICE_ERROR;
517 }
518
519 RegionRecord = (SFDP_SECTOR_REGION_RECORD *)GetFirstNode (&SectorMapRecord->RegionList);
520 while (TRUE) {
521 if ((FlashAddress >= RegionRecord->RegionAddress) &&
522 (FlashAddress < RegionRecord->RegionAddress + RegionRecord->RegionTotalSize))
523 {
524 *FlashRegion = RegionRecord;
525 return EFI_SUCCESS;
526 }
527
528 if (IsNodeAtEnd (&SectorMapRecord->RegionList, &RegionRecord->NextRegion)) {
529 break;
530 }
531
532 RegionRecord = (SFDP_SECTOR_REGION_RECORD *)GetNextNode (&SectorMapRecord->RegionList, &RegionRecord->NextRegion);
533 }
534
535 return EFI_INVALID_PARAMETER;
536}
537
551VOID
553 IN SPI_NOR_FLASH_INSTANCE *Instance
554 )
555{
556 // Build up the standard Fast Read
557 // This will be first picked for the ReadData.
558 // TODO: The mechanism to choose the advance fast read
559 // is not determined yet in this version of
560 // SpiNorFlash driver.
562 Instance,
563 SPI_FLASH_FAST_READ,
564 0,
565 SPI_FLASH_FAST_READ_DUMMY * 8
566 );
567
568 // Build up Fast Read table 1S-1S-4S
569 if (Instance->SfdpBasicFlash->FastRead114 != 0) {
571 Instance,
572 Instance->SfdpBasicFlash->FastRead114Instr,
573 Instance->SfdpBasicFlash->FastRead114ModeClk,
574 Instance->SfdpBasicFlash->FastRead114Dummy
575 );
576 }
577
578 // Build up Fast Read table 1S-2S-2S
579 if (Instance->SfdpBasicFlash->FastRead122 != 0) {
581 Instance,
582 Instance->SfdpBasicFlash->FastRead122Instr,
583 Instance->SfdpBasicFlash->FastRead122ModeClk,
584 Instance->SfdpBasicFlash->FastRead122Dummy
585 );
586 }
587
588 // Build up Fast Read table 2S-2S-2S
589 if (Instance->SfdpBasicFlash->FastRead222 != 0) {
591 Instance,
592 Instance->SfdpBasicFlash->FastRead222Instr,
593 Instance->SfdpBasicFlash->FastRead222ModeClk,
594 Instance->SfdpBasicFlash->FastRead222Dummy
595 );
596 }
597
598 // Build up Fast Read table 1S-4S-4S
599 if (Instance->SfdpBasicFlash->FastRead144 != 0) {
601 Instance,
602 Instance->SfdpBasicFlash->FastRead144Instr,
603 Instance->SfdpBasicFlash->FastRead144ModeClk,
604 Instance->SfdpBasicFlash->FastRead144Dummy
605 );
606 }
607
608 // Build up Fast Read table 4S-4S-4S
609 if (Instance->SfdpBasicFlash->FastRead444 != 0) {
611 Instance,
612 Instance->SfdpBasicFlash->FastRead444Instr,
613 Instance->SfdpBasicFlash->FastRead444ModeClk,
614 Instance->SfdpBasicFlash->FastRead444Dummy
615 );
616 }
617
618 // Build up Fast Read table 1S-1S-8S
619 if (Instance->SfdpBasicFlash->FastRead118Instr != 0) {
621 Instance,
622 Instance->SfdpBasicFlash->FastRead118Instr,
623 Instance->SfdpBasicFlash->FastRead118ModeClk,
624 Instance->SfdpBasicFlash->FastRead118Dummy
625 );
626 }
627
628 // Build up Fast Read table 1S-8S-8S
629 if (Instance->SfdpBasicFlash->FastRead188Instr != 0) {
631 Instance,
632 Instance->SfdpBasicFlash->FastRead188Instr,
633 Instance->SfdpBasicFlash->FastRead188ModeClk,
634 Instance->SfdpBasicFlash->FastRead188Dummy
635 );
636 }
637}
638
654 IN SPI_NOR_FLASH_INSTANCE *Instance,
655 IN SFDP_SECTOR_REGION_RECORD *RegionRecord
656 )
657{
658 SFDP_SUPPORTED_ERASE_TYPE_RECORD *SupportedEraseType;
659 UINT32 MinimumEraseSize;
660
661 if (IsListEmpty (&Instance->SupportedEraseTypes)) {
662 DEBUG ((DEBUG_ERROR, "%a: No erase type suppoted on the flash device.\n", __func__));
663 ASSERT (FALSE);
664 return EFI_DEVICE_ERROR;
665 }
666
667 MinimumEraseSize = (UINT32)-1;
668 SupportedEraseType = (SFDP_SUPPORTED_ERASE_TYPE_RECORD *)GetFirstNode (&Instance->SupportedEraseTypes);
669 while (TRUE) {
670 RegionRecord->SupportedEraseType[RegionRecord->SupportedEraseTypeNum] = (UINT8)SupportedEraseType->EraseType;
671 RegionRecord->SupportedEraseTypeNum++;
672 RegionRecord->EraseTypeBySizeBitmap |= SupportedEraseType->EraseSizeInByte;
673 if (MinimumEraseSize > SupportedEraseType->EraseSizeInByte) {
674 MinimumEraseSize = SupportedEraseType->EraseSizeInByte;
675 }
676
677 if (IsNodeAtEnd (&Instance->SupportedEraseTypes, &SupportedEraseType->NextEraseType)) {
678 break;
679 }
680
681 SupportedEraseType = (SFDP_SUPPORTED_ERASE_TYPE_RECORD *)GetNextNode (&Instance->SupportedEraseTypes, &SupportedEraseType->NextEraseType);
682 }
683
684 RegionRecord->SectorSize = MinimumEraseSize;
685 RegionRecord->RegionTotalSize = Instance->FlashDeviceSize;
686 RegionRecord->RegionSectors = RegionRecord->RegionTotalSize / RegionRecord->SectorSize;
687 return EFI_SUCCESS;
688}
689
702 IN SPI_NOR_FLASH_INSTANCE *Instance
703 )
704{
705 SFDP_SECTOR_MAP_RECORD *SectorMapRecord;
706 SFDP_SECTOR_REGION_RECORD *RegionRecord;
707 UINTN EraseIndex;
708
709 DEBUG ((DEBUG_VERBOSE, "%a: Entry:\n", __func__));
710 SectorMapRecord = (SFDP_SECTOR_MAP_RECORD *)AllocateZeroPool (sizeof (SFDP_SECTOR_MAP_RECORD));
711 if (SectorMapRecord == NULL) {
712 DEBUG ((DEBUG_ERROR, "%a: No memory resource for SFDP_SECTOR_MAP_DETECTION_RECORD.\n", __func__));
713 ASSERT (FALSE);
714 return EFI_OUT_OF_RESOURCES;
715 }
716
717 // Create SFDP_SECTOR_MAP_RECORD.
718 InitializeListHead (&SectorMapRecord->NextDescriptor);
719 InitializeListHead (&SectorMapRecord->RegionList);
720 SectorMapRecord->ConfigurationId = 0;
721 SectorMapRecord->RegionCount = 1;
722 InsertTailList (&Instance->ConfigurationMapList, &SectorMapRecord->NextDescriptor);
723 DEBUG ((DEBUG_VERBOSE, " Sector map configurations ID : 0x%x\n", SectorMapRecord->ConfigurationId));
724 DEBUG ((DEBUG_VERBOSE, " Sector map configurations regions: %d\n", SectorMapRecord->RegionCount));
725
726 // Create SFDP_SECTOR_MAP_RECORD region record.
728 if (RegionRecord == NULL) {
729 DEBUG ((DEBUG_ERROR, "%a: No memory resource for SFDP_SECTOR_REGION_RECORD.\n", __func__));
730 ASSERT (FALSE);
731 return EFI_OUT_OF_RESOURCES;
732 }
733
734 InitializeListHead (&RegionRecord->NextRegion);
735
736 RegionRecord->RegionAddress = 0;
737 //
738 // Setup erase information in the region record.
739 //
740 SetupRegionEraseInfo (Instance, RegionRecord);
741
742 InsertTailList (&SectorMapRecord->RegionList, &RegionRecord->NextRegion);
743
744 Instance->CurrentSectorMap = SectorMapRecord;
745
746 DEBUG ((DEBUG_VERBOSE, " Region totoal size : 0x%x\n", RegionRecord->RegionTotalSize));
747 DEBUG ((DEBUG_VERBOSE, " Region sector size : 0x%x\n", RegionRecord->SectorSize));
748 DEBUG ((DEBUG_VERBOSE, " Region sectors : 0x%x\n", RegionRecord->RegionSectors));
749
750 for (EraseIndex = 0; EraseIndex < RegionRecord->SupportedEraseTypeNum; EraseIndex++) {
751 DEBUG ((DEBUG_VERBOSE, " Region erase type supported: 0x%x\n", RegionRecord->SupportedEraseType[EraseIndex]));
752 }
753
754 return EFI_SUCCESS;
755}
756
769 IN SPI_NOR_FLASH_INSTANCE *Instance
770 )
771{
772 EFI_STATUS Status;
773 SFDP_SUPPORTED_ERASE_TYPE_RECORD *EraseTypeRecord;
774
775 // Use the smallest size for the sector erase.
776 Status = GetEraseTypeRecord (Instance, SearchEraseTypeBySmallestSize, 0, 0, NULL, &EraseTypeRecord);
777 if (!EFI_ERROR (Status)) {
778 Instance->Protocol.EraseBlockBytes = EraseTypeRecord->EraseSizeInByte;
779 DEBUG ((DEBUG_VERBOSE, " Erase block size = 0x%08x\n", EraseTypeRecord->EraseSizeInByte));
780 }
781
782 return Status;
783}
784
798 IN SPI_NOR_FLASH_INSTANCE *Instance
799 )
800{
801 EFI_STATUS Status;
802 UINT32 TransactionBufferLength;
803 UINT8 AddressLength;
804 BOOLEAN UseAddress;
805 UINT32 DummyBytes;
806 UINT8 ReturnByte;
807 UINT8 ConfigurationId;
808 SFDP_SECTOR_MAP_RECORD *SectorMap;
810
811 Instance->CurrentSectorMap = NULL;
812 if (!Instance->ConfigurationCommandsNeeded) {
813 // No command needed measn only one configuration for the flash device sector map.
814 Instance->CurrentSectorMap = (SFDP_SECTOR_MAP_RECORD *)GetFirstNode (&Instance->ConfigurationMapList);
815 return EFI_SUCCESS;
816 }
817
818 //
819 // Send the command to collect interest bit.
820 //
821 ConfigurationId = 0;
822 CommandEntry = (SFDP_SECTOR_MAP_DETECTION_RECORD *)GetFirstNode (&Instance->ConfigurationCommandList);
823 while (TRUE) {
824 // Check not WIP
825 Status = WaitNotWip (Instance, FixedPcdGet32 (PcdSpiNorFlashOperationDelayMicroseconds), FixedPcdGet32 (PcdSpiNorFlashFixedTimeoutRetryCount));
826
827 // Read configuration byte.
828 AddressLength = SPI_ADDR_3BYTE_ONLY;
829 DummyBytes = 1;
830 if (CommandEntry->CommandAddressLength == SpdfConfigurationCommandAddress4Byte) {
831 AddressLength = SPI_ADDR_4BYTE_ONLY;
832 DummyBytes = 0;
833 }
834
835 UseAddress = TRUE;
836 if (CommandEntry->CommandAddress == SpdfConfigurationCommandAddressNone) {
837 UseAddress = FALSE;
838 }
839
840 TransactionBufferLength = FillWriteBuffer (
841 Instance,
842 CommandEntry->CommandInstruction,
843 DummyBytes,
844 AddressLength,
845 UseAddress,
846 CommandEntry->CommandAddress,
847 0,
848 NULL
849 );
850 Status = Instance->SpiIo->Transaction (
851 Instance->SpiIo,
853 FALSE,
854 0,
855 1,
856 8,
857 TransactionBufferLength,
858 Instance->SpiTransactionWriteBuffer,
859 1,
860 &ReturnByte
861 );
862 ASSERT_EFI_ERROR (Status);
863 if (EFI_ERROR (Status)) {
864 DEBUG ((DEBUG_ERROR, "%a: Fails to read the configuration byte.\n", __func__));
865 ASSERT (FALSE);
866 return EFI_DEVICE_ERROR;
867 }
868
869 //
870 // Retrieve the interest bit.
871 //
872 if ((ReturnByte & CommandEntry->ConfigurationBitMask) != 0) {
873 ConfigurationId |= 0x01;
874 }
875
876 if (IsNodeAtEnd (&Instance->ConfigurationCommandList, &CommandEntry->NextCommand)) {
877 break;
878 }
879
880 CommandEntry = (SFDP_SECTOR_MAP_DETECTION_RECORD *)GetNextNode (&Instance->ConfigurationCommandList, &CommandEntry->NextCommand);
881 ConfigurationId = ConfigurationId << 1;
882 }
883
884 //
885 // Now we have current activated configuration ID in ConfigurationId.
886 // Walk through ConfigurationMapList to record the activated flash sector
887 // map configuration.
888 //
889 SectorMap = (SFDP_SECTOR_MAP_RECORD *)GetFirstNode (&Instance->ConfigurationMapList);
890 while (TRUE) {
891 if (SectorMap->ConfigurationId == ConfigurationId) {
892 Instance->CurrentSectorMap = SectorMap;
893 break;
894 }
895
896 if (IsNodeAtEnd (&Instance->ConfigurationMapList, &SectorMap->NextDescriptor)) {
897 break;
898 }
899
900 SectorMap = (SFDP_SECTOR_MAP_RECORD *)GetNextNode (&Instance->ConfigurationMapList, &SectorMap->NextDescriptor);
901 }
902
903 if (Instance->CurrentSectorMap == NULL) {
904 DEBUG ((DEBUG_ERROR, "%a: Activated flash sector map is not found!\n", __func__));
905 ASSERT (FALSE);
906 return EFI_DEVICE_ERROR;
907 }
908
909 return EFI_SUCCESS;
910}
911
928 IN SPI_NOR_FLASH_INSTANCE *Instance
929 )
930{
931 SFDP_SECTOR_MAP_TABLE *SfdpSectorMapTable;
932 SFDP_SECTOR_CONFIGURATION_COMMAND *SfdpDetectionCommand;
934 SFDP_SECTOR_CONFIGURATION_MAP *SfdpConfigurationMap;
935 SFDP_SECTOR_MAP_RECORD *SectorMapRecord;
936 SFDP_SECTOR_REGION *SpdfSectorRegion;
937 SFDP_SECTOR_REGION_RECORD *RegionRecord;
938 SFDP_SUPPORTED_ERASE_TYPE_RECORD *SupportedEraseType;
939 UINT8 RegionCount;
940 UINT8 EraseTypeCount;
941 UINT32 MinimumEraseSize;
942 UINT32 RegionAddress;
943
944 SfdpSectorMapTable = Instance->SfdpFlashSectorMap;
945 SfdpConfigurationMap = &SfdpSectorMapTable->ConfigurationMap;
946 SfdpDetectionCommand = &SfdpSectorMapTable->ConfigurationCommand;
947
948 if (SfdpSectorMapTable->GenericHeader.DescriptorType == SFDP_SECTOR_MAP_TABLE_ENTRY_TYPE_MAP) {
949 // No configuration detection commands are needs.
950 Instance->ConfigurationCommandsNeeded = FALSE;
951 } else {
952 DEBUG ((DEBUG_VERBOSE, "%a: Sector map configuration detection command is needed\n", __func__));
953 Instance->ConfigurationCommandsNeeded = TRUE;
954
955 // Go through the section map detection commands.
956 while (TRUE) {
958 if (CommandEntry == NULL) {
959 DEBUG ((DEBUG_ERROR, "%a: No memory resource for SFDP_SECTOR_MAP_DETECTION_RECORD.\n", __func__));
960 ASSERT (FALSE);
961 return EFI_OUT_OF_RESOURCES;
962 }
963
964 InitializeListHead (&CommandEntry->NextCommand);
965 CommandEntry->CommandAddress = SfdpDetectionCommand->CommandAddress;
967 CommandEntry->CommandInstruction = (UINT8)SfdpDetectionCommand->DetectionInstruction;
968 CommandEntry->ConfigurationBitMask = (UINT8)SfdpDetectionCommand->ReadDataMask;
969 CommandEntry->LatencyInClock = (UINT8)SfdpDetectionCommand->DetectionLatency;
970 InsertTailList (&Instance->ConfigurationCommandList, &CommandEntry->NextCommand);
971 DEBUG ((DEBUG_VERBOSE, " Command instruction : 0x%x\n", CommandEntry->CommandInstruction));
972 DEBUG ((DEBUG_VERBOSE, " Bit selection : 0x%x\n", CommandEntry->ConfigurationBitMask));
973 DEBUG ((DEBUG_VERBOSE, " Command address : 0x%x\n", CommandEntry->CommandAddress));
974 DEBUG ((DEBUG_VERBOSE, " Command address length: %d\n", CommandEntry->CommandAddressLength));
975 DEBUG ((DEBUG_VERBOSE, " Command latency clocks: %d\n\n", CommandEntry->LatencyInClock));
976 if (SfdpDetectionCommand->DescriptorEnd == SFDP_SECTOR_MAP_TABLE_ENTRY_LAST) {
977 break;
978 }
979
980 SfdpDetectionCommand++;
981 }
982
983 SfdpConfigurationMap = (SFDP_SECTOR_CONFIGURATION_MAP *)SfdpDetectionCommand++;
984 }
985
986 //
987 // Go through the region table pointed in SfdpConfigurationMap.
988 //
989 if (SfdpConfigurationMap->DescriptorType != SFDP_SECTOR_MAP_TABLE_ENTRY_TYPE_MAP) {
990 DEBUG ((DEBUG_ERROR, "%a: Incorrect format of Sector Map Parameter.\n", __func__));
991 ASSERT (FALSE);
992 return EFI_DEVICE_ERROR;
993 }
994
995 while (TRUE) {
996 DEBUG ((DEBUG_VERBOSE, "%a: Sector map configurations:\n", __func__));
997 SectorMapRecord = (SFDP_SECTOR_MAP_RECORD *)AllocateZeroPool (sizeof (SFDP_SECTOR_MAP_RECORD));
998 if (SectorMapRecord == NULL) {
999 DEBUG ((DEBUG_ERROR, "%a: No memory resource for SFDP_SECTOR_MAP_DETECTION_RECORD.\n", __func__));
1000 ASSERT (FALSE);
1001 return EFI_OUT_OF_RESOURCES;
1002 }
1003
1004 InitializeListHead (&SectorMapRecord->NextDescriptor);
1005 InitializeListHead (&SectorMapRecord->RegionList);
1006 SectorMapRecord->ConfigurationId = (UINT8)SfdpConfigurationMap->ConfigurationID;
1007 SectorMapRecord->RegionCount = (UINT8)SfdpConfigurationMap->RegionCount;
1008 InsertTailList (&Instance->ConfigurationMapList, &SectorMapRecord->NextDescriptor);
1009 DEBUG ((DEBUG_VERBOSE, " Sector map configurations ID : 0x%x\n", SectorMapRecord->ConfigurationId));
1010 DEBUG ((DEBUG_VERBOSE, " Sector map configurations regions: %d\n", SectorMapRecord->RegionCount));
1011 SpdfSectorRegion = (SFDP_SECTOR_REGION *)SfdpConfigurationMap + 1;
1012 RegionAddress = 0;
1013 for (RegionCount = 0; RegionCount < SectorMapRecord->RegionCount; RegionCount++) {
1015 if (RegionRecord == NULL) {
1016 DEBUG ((DEBUG_ERROR, "%a: No memory resource for SFDP_SECTOR_MAP_DETECTION_RECORD.\n", __func__));
1017 ASSERT (FALSE);
1018 return EFI_OUT_OF_RESOURCES;
1019 }
1020
1021 InitializeListHead (&RegionRecord->NextRegion);
1022 RegionRecord->RegionTotalSize = (SpdfSectorRegion->RegionSize + 1) * SFDP_SECTOR_REGION_SIZE_UNIT;
1023 //
1024 // Construct erase type supported for this region.
1025 //
1026 if (SpdfSectorRegion->EraseType1 != 0) {
1027 RegionRecord->SupportedEraseType[RegionRecord->SupportedEraseTypeNum] = SFDP_ERASE_TYPE_1;
1028 RegionRecord->SupportedEraseTypeNum++;
1029 }
1030
1031 if (SpdfSectorRegion->EraseType2 != 0) {
1032 RegionRecord->SupportedEraseType[RegionRecord->SupportedEraseTypeNum] = SFDP_ERASE_TYPE_2;
1033 RegionRecord->SupportedEraseTypeNum++;
1034 }
1035
1036 if (SpdfSectorRegion->EraseType3 != 0) {
1037 RegionRecord->SupportedEraseType[RegionRecord->SupportedEraseTypeNum] = SFDP_ERASE_TYPE_3;
1038 RegionRecord->SupportedEraseTypeNum++;
1039 }
1040
1041 if (SpdfSectorRegion->EraseType4 != 0) {
1042 RegionRecord->SupportedEraseType[RegionRecord->SupportedEraseTypeNum] = SFDP_ERASE_TYPE_4;
1043 RegionRecord->SupportedEraseTypeNum++;
1044 }
1045
1046 //
1047 // Calculate the sector size and total sectors.
1048 //
1049 if (IsListEmpty (&Instance->SupportedEraseTypes)) {
1050 DEBUG ((DEBUG_ERROR, "%a: No erase type suppoted on the flash device.\n", __func__));
1051 ASSERT (FALSE);
1052 return EFI_DEVICE_ERROR;
1053 }
1054
1055 MinimumEraseSize = (UINT32)-1;
1056 for (EraseTypeCount = 0; EraseTypeCount < RegionRecord->SupportedEraseTypeNum++; EraseTypeCount++) {
1057 //
1058 // Walk through Instance->SupportedEraseTypes to find the matching erase type and
1059 // Use the minimum erase size as the sector size;
1060 //
1061 SupportedEraseType = (SFDP_SUPPORTED_ERASE_TYPE_RECORD *)GetFirstNode (&Instance->SupportedEraseTypes);
1062 while (TRUE) {
1063 if (RegionRecord->SupportedEraseType[EraseTypeCount] == SupportedEraseType->EraseType) {
1064 // Set erase size bitmap.
1065 RegionRecord->EraseTypeBySizeBitmap |= SupportedEraseType->EraseSizeInByte;
1066
1067 if (MinimumEraseSize > SupportedEraseType->EraseSizeInByte) {
1068 MinimumEraseSize = SupportedEraseType->EraseSizeInByte;
1069 break;
1070 }
1071 }
1072
1073 if (IsNodeAtEnd (&Instance->SupportedEraseTypes, &SupportedEraseType->NextEraseType)) {
1074 break;
1075 }
1076
1077 SupportedEraseType = (SFDP_SUPPORTED_ERASE_TYPE_RECORD *)GetNextNode (&Instance->SupportedEraseTypes, &SupportedEraseType->NextEraseType);
1078 }
1079 }
1080
1081 RegionRecord->SectorSize = MinimumEraseSize;
1082 RegionRecord->RegionSectors = RegionRecord->RegionTotalSize / RegionRecord->SectorSize;
1083 RegionRecord->RegionAddress = RegionAddress;
1084
1085 // Insert to link.
1086 InsertTailList (&SectorMapRecord->RegionList, &RegionRecord->NextRegion);
1087 DEBUG ((DEBUG_VERBOSE, " Region: %d\n", RegionCount));
1088 DEBUG ((DEBUG_VERBOSE, " Region totoal size: 0x%x\n", RegionRecord->RegionTotalSize));
1089 DEBUG ((DEBUG_VERBOSE, " Region sector size: 0x%x\n", RegionRecord->SectorSize));
1090 DEBUG ((DEBUG_VERBOSE, " Region sectors : 0x%x\n", RegionRecord->RegionSectors));
1091 DEBUG ((DEBUG_VERBOSE, " Region erase supported bitmap: 0x%x\n", RegionRecord->EraseTypeBySizeBitmap));
1092
1093 SpdfSectorRegion++;
1094 RegionAddress += RegionRecord->RegionTotalSize;
1095 }
1096
1097 if (SfdpConfigurationMap->DescriptorEnd == SFDP_SECTOR_MAP_TABLE_ENTRY_LAST) {
1098 break;
1099 }
1100
1101 SfdpConfigurationMap = (SFDP_SECTOR_CONFIGURATION_MAP *)SpdfSectorRegion;
1102 }
1103
1104 return EFI_SUCCESS;
1105}
1106
1115VOID
1117 IN SPI_NOR_FLASH_INSTANCE *Instance
1118 )
1119{
1120 //
1121 // Set Wrtie Enable command.
1122 //
1123 Instance->WriteEnableLatchRequired = TRUE;
1124 Instance->WriteEnableLatchCommand = SPI_FLASH_WREN;
1125 if (Instance->SfdpBasicFlash->VolatileStatusBlockProtect == 1) {
1126 if (Instance->SfdpBasicFlash->WriteEnableVolatileStatus == 0) {
1127 Instance->WriteEnableLatchCommand = SPI_FLASH_WREN_50H;
1128 }
1129 }
1130
1131 DEBUG ((DEBUG_ERROR, "%a: Use Write Enable Command 0x%x.\n", __func__, Instance->WriteEnableLatchCommand));
1132}
1133
1151 IN SPI_NOR_FLASH_INSTANCE *Instance,
1152 IN OUT UINT8 *FastReadInstruction,
1153 IN OUT UINT8 *FastReadModeBits,
1154 IN OUT UINT8 *FastReadDummyClocks
1155 )
1156{
1157 SFPD_FAST_READ_CAPBILITY_RECORD *FastReadEntry;
1158
1159 if (IsListEmpty (&Instance->FastReadTableList)) {
1160 return EFI_NOT_FOUND;
1161 }
1162
1163 FastReadEntry = (SFPD_FAST_READ_CAPBILITY_RECORD *)GetFirstNode (&Instance->FastReadTableList);
1164 *FastReadInstruction = FastReadEntry->FastReadInstruction;
1165 *FastReadDummyClocks = FastReadEntry->WaitStates;
1166 *FastReadModeBits = FastReadEntry->ModeClocks;
1167
1168 //
1169 // *FastReadOperationClock may be replaced by 8D-8D-8D or 4S-4D-4D Fast Read
1170 // mode clock operation mode. Which is not cosidered in the implementation yet.
1171 //
1172 return EFI_SUCCESS;
1173}
1174
1185UINT32
1187 IN SPI_NOR_FLASH_INSTANCE *Instance
1188 )
1189{
1190 if (Instance == NULL) {
1191 return 0;
1192 }
1193
1194 if ((Instance->SfdpBasicFlash->Density & SFDP_FLASH_MEMORY_DENSITY_4GBIT) == 0) {
1195 //
1196 // The flash device size is <= 256MB.
1197 //
1198 return (Instance->SfdpBasicFlash->Density + 1) / 8;
1199 }
1200
1201 //
1202 // The flash deivce size is >= 512MB.
1203 // Bit [0:30] defines 'N' where the density is computed as 2^N bits.
1204 // N must be >=32 according to the SFDP specification.
1205 //
1206 if ((Instance->SfdpBasicFlash->Density & ~SFDP_FLASH_MEMORY_DENSITY_4GBIT) < 32) {
1207 return 0;
1208 }
1209
1210 return (UINT32)RShiftU64 (LShiftU64 (1, Instance->SfdpBasicFlash->Density & ~SFDP_FLASH_MEMORY_DENSITY_4GBIT), 3);
1211}
1212
1227EFIAPI
1229 IN SPI_NOR_FLASH_INSTANCE *Instance
1230 )
1231{
1232 EFI_STATUS Status;
1233 UINT32 TransactionBufferLength;
1234
1235 // Check not WIP
1236 Status = WaitNotWip (Instance, FixedPcdGet32 (PcdSpiNorFlashOperationDelayMicroseconds), FixedPcdGet32 (PcdSpiNorFlashFixedTimeoutRetryCount));
1237
1238 // Read SFDP Header
1239 TransactionBufferLength = FillWriteBuffer (
1240 Instance,
1241 SPI_FLASH_RDSFDP,
1242 SPI_FLASH_RDSFDP_DUMMY,
1243 SPI_FLASH_RDSFDP_ADDR_BYTES,
1244 TRUE,
1245 0,
1246 0,
1247 NULL
1248 );
1249 Status = Instance->SpiIo->Transaction (
1250 Instance->SpiIo,
1252 FALSE,
1253 0,
1254 1,
1255 8,
1256 TransactionBufferLength,
1257 Instance->SpiTransactionWriteBuffer,
1258 sizeof (SFDP_HEADER),
1259 (UINT8 *)&Instance->SfdpHeader
1260 );
1261 ASSERT_EFI_ERROR (Status);
1262 if (!EFI_ERROR (Status)) {
1263 // Read Basic Flash Parameter Header
1264 if ((Instance->SfdpHeader.Signature != SFDP_HEADER_SIGNATURE) ||
1265 (Instance->SfdpHeader.MajorRev != SFDP_SUPPORTED_MAJOR_REVISION))
1266 {
1267 Status = EFI_DEVICE_ERROR;
1268 } else {
1269 DEBUG ((DEBUG_VERBOSE, "Total %d parameter headers\n", Instance->SfdpHeader.NumParameterHeaders + 1));
1270 }
1271 }
1272
1273 return Status;
1274}
1275
1290 IN SPI_NOR_FLASH_INSTANCE *Instance
1291 )
1292{
1293 EFI_STATUS Status;
1294 SFDP_SUPPORTED_ERASE_TYPE_RECORD *EraseTypeRecord;
1295
1296 InitializeListHead (&Instance->FastReadTableList);
1297 InitializeListHead (&Instance->SupportedEraseTypes);
1298 InitializeListHead (&Instance->ConfigurationCommandList);
1299 InitializeListHead (&Instance->ConfigurationMapList);
1300
1301 DEBUG ((DEBUG_VERBOSE, "%a: Entry\n", __func__));
1302
1303 Status = ReadSfdpHeader (Instance);
1304 if (EFI_ERROR (Status)) {
1305 DEBUG ((DEBUG_ERROR, "%a: Failed to read SFDP header\n", __func__));
1306 ASSERT (FALSE);
1307 return Status;
1308 }
1309
1310 Status = ReadSfdpBasicParameterTable (Instance);
1311 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
1312 DEBUG ((DEBUG_ERROR, "%a: Failed to read SFDP Basic Parameter Table\n", __func__));
1313 ASSERT (FALSE);
1314 return Status;
1315 }
1316
1317 Instance->FlashDeviceSize = SfdpGetFlashSize (Instance);
1318 DEBUG ((DEBUG_VERBOSE, "%a: Flash Size=0x%X\n", __func__, Instance->FlashDeviceSize));
1319 if (Instance->FlashDeviceSize == 0) {
1320 ASSERT (FALSE);
1321 return Status;
1322 }
1323
1324 Status = ReadSfdpSectorMapParameterTable (Instance);
1325 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
1326 DEBUG ((DEBUG_ERROR, "%a: Failed to read SFDP Sector Map Parameter Table\n", __func__));
1327 ASSERT (FALSE);
1328 } else if (Status == EFI_NOT_FOUND) {
1329 DEBUG ((DEBUG_VERBOSE, "%a: The SPI NOR flash device doesn't have SFDP Sector Map Parameter Table implemented:\n", __func__));
1330
1331 //
1332 // No SFDP Sector Map Parameter Table exist.
1333 // Check if device support the uniform 4K erase size.
1334 //
1335 Instance->Uniform4KEraseSupported = FALSE;
1336 if (Instance->SfdpBasicFlash->EraseSizes == SPI_UNIFORM_4K_ERASE_SUPPORTED) {
1337 DEBUG ((DEBUG_VERBOSE, "%a: The SPI NOR flash device supports uniform 4K erase.\n", __func__));
1338
1339 // Check if 4K erase type supported?
1340 Status = GetEraseTypeRecord (Instance, SearchEraseTypeBySize, SIZE_4KB, 0, NULL, &EraseTypeRecord);
1341 if (Status == EFI_NOT_FOUND) {
1342 DEBUG ((DEBUG_ERROR, "However, no corresponding 4K size erase type found.\n"));
1343 ASSERT (FALSE);
1344 }
1345
1346 Instance->Uniform4KEraseSupported = TRUE;
1347 } else {
1348 // Uniform 4K erase unsupported, get the smallest erase block size.
1349 DEBUG ((DEBUG_VERBOSE, "%a: The SPI NOR flash device doesn't support uniform 4K erase.\n", __func__));
1350 }
1351
1352 //
1353 // Build flash map
1354 // Instance->ConfigurationMapList is an empty list because no FDP Sector Map Parameter Table.
1355 //
1356 CreateSingleFlashSectorMap (Instance);
1357 Status = EFI_SUCCESS;
1358 }
1359
1360 return Status;
1361}
1362
1381EFIAPI
1383 IN SPI_NOR_FLASH_INSTANCE *Instance,
1384 IN SFDP_PARAMETER_HEADER *SfdpParameterHeader,
1385 IN UINT8 ParameterIdMsb,
1386 IN UINT8 ParameterIdLsb
1387 )
1388{
1389 EFI_STATUS Status;
1390 UINT32 Index;
1391 SFDP_PARAMETER_HEADER LocalSfdpParameterHeader;
1392 UINT32 TransactionBufferLength;
1393
1394 DEBUG ((DEBUG_VERBOSE, "%a: Entry\n", __func__));
1395 DEBUG ((DEBUG_VERBOSE, " Looking for Parameter Header %02x:%02x\n", ParameterIdMsb, ParameterIdLsb));
1396
1397 //
1398 // Parse Parameter Headers Starting at size eof SFDP_HEADER.
1399 // SfdpHeader.NumParameterHeaders is zero based, 0 means 1 parameter header.
1400 //
1401 ZeroMem (SfdpParameterHeader, sizeof (SFDP_PARAMETER_HEADER));
1402 for (Index = 0; Index < Instance->SfdpHeader.NumParameterHeaders + 1; Index++) {
1403 // Check not WIP
1404 Status = WaitNotWip (Instance, FixedPcdGet32 (PcdSpiNorFlashOperationDelayMicroseconds), FixedPcdGet32 (PcdSpiNorFlashFixedTimeoutRetryCount));
1405 if (!EFI_ERROR (Status)) {
1406 TransactionBufferLength = FillWriteBuffer (
1407 Instance,
1408 SPI_FLASH_RDSFDP,
1409 SPI_FLASH_RDSFDP_DUMMY,
1410 SPI_FLASH_RDSFDP_ADDR_BYTES,
1411 TRUE,
1412 sizeof (SFDP_HEADER) + Index * 8, // Parameter Header Index
1413 0,
1414 NULL
1415 );
1416 Status = Instance->SpiIo->Transaction (
1417 Instance->SpiIo,
1419 FALSE,
1420 0,
1421 1,
1422 8,
1423 TransactionBufferLength,
1424 Instance->SpiTransactionWriteBuffer,
1425 sizeof (LocalSfdpParameterHeader),
1426 (UINT8 *)&LocalSfdpParameterHeader
1427 );
1428 ASSERT_EFI_ERROR (Status);
1429 if (!EFI_ERROR (Status)) {
1430 // Break if SfdParamHeader is Type 0, Basic SPI Protocol Parameters
1431 DEBUG ((
1432 DEBUG_VERBOSE,
1433 " #%d Parameter Header: %02x:%02x, revision: %d.%d\n",
1434 Index,
1435 LocalSfdpParameterHeader.IdMsb,
1436 LocalSfdpParameterHeader.IdLsb,
1437 LocalSfdpParameterHeader.MajorRev,
1438 LocalSfdpParameterHeader.MinorRev >= SfdpParameterHeader->MinorRev
1439 ));
1440 if ((LocalSfdpParameterHeader.IdLsb == ParameterIdLsb) &&
1441 (LocalSfdpParameterHeader.IdMsb == ParameterIdMsb) &&
1442 (LocalSfdpParameterHeader.MajorRev == (UINT32)SFDP_SUPPORTED_MAJOR_REVISION) &&
1443 (LocalSfdpParameterHeader.MinorRev >= SfdpParameterHeader->MinorRev))
1444 {
1445 CopyMem (
1446 (VOID **)SfdpParameterHeader,
1447 (VOID **)&LocalSfdpParameterHeader,
1448 sizeof (SFDP_PARAMETER_HEADER)
1449 );
1450 }
1451 } else {
1452 break;
1453 }
1454 } else {
1455 break;
1456 }
1457 }
1458
1459 if (Status != EFI_DEVICE_ERROR) {
1460 if ((SfdpParameterHeader->IdLsb != ParameterIdLsb) ||
1461 (SfdpParameterHeader->IdMsb != ParameterIdMsb))
1462 {
1463 DEBUG ((DEBUG_ERROR, " Parameter Header: %02x:%02x is not found.\n", ParameterIdMsb, ParameterIdLsb));
1464 Status = EFI_NOT_FOUND;
1465 }
1466 }
1467
1468 return Status;
1469}
1470
1489EFIAPI
1491 IN SPI_NOR_FLASH_INSTANCE *Instance,
1492 IN UINT32 TablePointer,
1493 IN VOID *DestBuffer,
1494 IN UINT32 LengthInBytes
1495 )
1496{
1497 EFI_STATUS Status;
1498 UINT32 Length;
1499 UINT8 *CurrentBuffer;
1500 UINT32 ByteCounter;
1501 UINT32 CurrentAddress;
1502 UINT32 MaximumTransferBytes;
1503 UINT32 TransactionBufferLength;
1504
1505 Length = 0;
1506 MaximumTransferBytes = Instance->SpiIo->MaximumTransferBytes;
1507 CurrentBuffer = (UINT8 *)DestBuffer;
1508 for (ByteCounter = 0; ByteCounter < LengthInBytes; ByteCounter += Length) {
1509 CurrentAddress = TablePointer + ByteCounter;
1510 Length = LengthInBytes - ByteCounter;
1511
1512 // Length must be MaximumTransferBytes or less
1513 if (Length > MaximumTransferBytes) {
1514 Length = MaximumTransferBytes;
1515 }
1516
1517 // Check not WIP
1518 Status = WaitNotWip (Instance, FixedPcdGet32 (PcdSpiNorFlashOperationDelayMicroseconds), FixedPcdGet32 (PcdSpiNorFlashFixedTimeoutRetryCount));
1519
1520 // Read Data
1521 if (!EFI_ERROR (Status)) {
1522 TransactionBufferLength = FillWriteBuffer (
1523 Instance,
1524 SPI_FLASH_RDSFDP,
1525 SPI_FLASH_RDSFDP_DUMMY,
1526 SPI_FLASH_RDSFDP_ADDR_BYTES,
1527 TRUE,
1528 CurrentAddress,
1529 0,
1530 NULL
1531 );
1532 Status = Instance->SpiIo->Transaction (
1533 Instance->SpiIo,
1535 FALSE,
1536 0,
1537 1,
1538 8,
1539 TransactionBufferLength,
1540 Instance->SpiTransactionWriteBuffer,
1541 Length,
1542 CurrentBuffer
1543 );
1544 if (EFI_ERROR (Status)) {
1545 DEBUG ((DEBUG_ERROR, "%a: Fails to read SFDP parameter.\n", __func__));
1546 ASSERT_EFI_ERROR (Status);
1547 }
1548
1549 CurrentBuffer += Length;
1550 } else {
1551 break;
1552 }
1553 }
1554
1555 return Status;
1556}
1557
1573 IN SPI_NOR_FLASH_INSTANCE *Instance
1574 )
1575{
1576 EFI_STATUS Status;
1577 SFDP_PARAMETER_HEADER SfdpParamHeader;
1578
1579 Status = ReadSfdpParameterHeader (
1580 Instance,
1581 &SfdpParamHeader,
1582 SFDP_SECTOR_MAP_PARAMETER_ID_MSB,
1584 );
1585 if (!EFI_ERROR (Status)) {
1586 // Read Sector Map Parameters. Already know it is MajorRev = SFDP_SUPPORTED_MAJOR_REVISION
1587 Instance->SfdpSectorMapByteCount = SfdpParamHeader.Length * sizeof (UINT32);
1588 Instance->SfdpFlashSectorMap = AllocateZeroPool (Instance->SfdpSectorMapByteCount);
1589 if (Instance->SfdpFlashSectorMap != NULL) {
1590 // Read from SFDP Parameter Table Pointer (PTP).
1591 Status = SpiReadSfdpPtp (
1592 Instance,
1593 SfdpParamHeader.TablePointer,
1594 (VOID *)Instance->SfdpFlashSectorMap,
1595 Instance->SfdpSectorMapByteCount
1596 );
1597 if (!EFI_ERROR (Status)) {
1598 Status = BuildSectorMapCommandAndMap (Instance);
1599 if (EFI_ERROR (Status)) {
1600 DEBUG ((DEBUG_ERROR, "%a: Fails to build sector map command and descriptor.\n", __func__));
1601 ASSERT (FALSE);
1602 Status = GetCurrentSectorMapConfiguration (Instance);
1603 if (EFI_ERROR (Status)) {
1604 DEBUG ((DEBUG_ERROR, "%a: Fails to get current sector map configuration.\n", __func__));
1605 ASSERT (FALSE);
1606 }
1607 }
1608 } else {
1609 FreePool (Instance->SfdpFlashSectorMap);
1610 Instance->SfdpFlashSectorMap = NULL;
1611 DEBUG ((DEBUG_ERROR, "%a: Fails to read SFDP Sector Map Parameter.\n", __func__));
1612 ASSERT (FALSE);
1613 }
1614 } else {
1615 if (EFI_ERROR (Status)) {
1616 DEBUG ((DEBUG_ERROR, "%a: Fails to allocate memory for reading SFDP Sector Map Parameter.\n", __func__));
1617 ASSERT (FALSE);
1618 }
1619 }
1620 }
1621
1622 return Status;
1623}
1624
1641 IN SPI_NOR_FLASH_INSTANCE *Instance
1642 )
1643{
1644 EFI_STATUS Status;
1645 SFDP_PARAMETER_HEADER SfdpBasicFlashParamHeader;
1646
1647 Status = ReadSfdpParameterHeader (
1648 Instance,
1649 &SfdpBasicFlashParamHeader,
1650 SFDP_BASIC_PARAMETER_ID_MSB,
1652 );
1653 if (!EFI_ERROR (Status)) {
1654 // Read Basic Flash Parameters. Already know it is MajorRev = SFDP_SUPPORTED_MAJOR_REVISION
1655 Instance->SfdpBasicFlashByteCount = SfdpBasicFlashParamHeader.Length * sizeof (UINT32);
1656 Instance->SfdpBasicFlash = AllocateZeroPool (Instance->SfdpBasicFlashByteCount);
1657 if (Instance->SfdpBasicFlash != NULL) {
1658 // Read from SFDP Parameter Table Pointer (PTP).
1659 Status = SpiReadSfdpPtp (
1660 Instance,
1661 SfdpBasicFlashParamHeader.TablePointer,
1662 (VOID *)Instance->SfdpBasicFlash,
1663 Instance->SfdpBasicFlashByteCount
1664 );
1665 if (!EFI_ERROR (Status)) {
1666 GetWriteEnableCommand (Instance);
1667 //
1668 // Build the Fast Read capability table according to
1669 // the Basic Flash Parameter Table.
1670 //
1671 BuildUpFastReadTable (Instance);
1672 BuildUpEraseTypeTable (Instance); // Build up erase type and size.
1673
1674 // Set current address bytes to 3-Bytes.
1675 Instance->CurrentAddressBytes = 3;
1676 } else {
1677 FreePool (Instance->SfdpBasicFlash);
1678 Instance->SfdpBasicFlash = NULL;
1679 DEBUG ((DEBUG_ERROR, "%a: Fails to read SFDP Basic Parameter.\n", __func__));
1680 ASSERT (FALSE);
1681 }
1682 } else {
1683 if (EFI_ERROR (Status)) {
1684 DEBUG ((DEBUG_ERROR, "%a: Fails to allocate memory for reading SFDP Basic Parameter.\n", __func__));
1685 ASSERT (FALSE);
1686 }
1687 }
1688 }
1689
1690 return Status;
1691}
1692
1711 IN SPI_NOR_FLASH_INSTANCE *Instance
1712 )
1713{
1714 EFI_STATUS Status;
1716
1717 if (Instance == NULL) {
1718 DEBUG ((DEBUG_ERROR, "%a: Instance is NULL.\n", __func__));
1719 return EFI_INVALID_PARAMETER;
1720 }
1721
1722 if ((Instance->SpiIo == NULL) ||
1723 (Instance->SpiIo->SpiPeripheral == NULL) ||
1724 (Instance->SpiIo->SpiPeripheral->SpiBus == NULL)
1725 )
1726 {
1727 DEBUG ((DEBUG_ERROR, "%a: One of SpiIo, SpiPeripheral and SpiBus is NULL.\n", __func__));
1728 return EFI_INVALID_PARAMETER;
1729 }
1730
1731 Instance->Signature = SPI_NOR_FLASH_SIGNATURE;
1732
1733 // Allocate write buffer for SPI IO transactions with extra room for Opcode
1734 // and Address with 10 bytes extra room.
1735 Instance->SpiTransactionWriteBuffer =
1736 AllocatePool (Instance->SpiIo->MaximumTransferBytes + 10);
1737
1738 Protocol = &Instance->Protocol;
1739 Protocol->SpiPeripheral = Instance->SpiIo->SpiPeripheral;
1740 Protocol->GetFlashid = GetFlashId;
1741 Protocol->ReadData = ReadData; // Fast Read transfer
1742 Protocol->LfReadData = LfReadData; // Normal Read transfer
1743 Protocol->ReadStatus = ReadStatus;
1744 Protocol->WriteStatus = WriteStatus;
1745 Protocol->WriteData = WriteData;
1746 Protocol->Erase = Erase;
1747 Status = Protocol->GetFlashid (Protocol, (UINT8 *)&Protocol->Deviceid);
1748 ASSERT_EFI_ERROR (Status);
1749 DEBUG ((
1750 DEBUG_VERBOSE,
1751 "%a: Flash ID: Manufacturer=0x%02X, Device=0x%02X%02X\n",
1752 __func__,
1753 Protocol->Deviceid[0],
1754 Protocol->Deviceid[1],
1755 Protocol->Deviceid[2]
1756 )
1757 );
1758
1759 Status = ReadSfdp (Instance);
1760 if (EFI_ERROR (Status)) {
1761 DEBUG ((DEBUG_ERROR, "%a: Failed to Read SFDP\n", __func__));
1762 ASSERT (FALSE);
1763 }
1764
1765 // Get flash deivce size from SFDP.
1766 Protocol->FlashSize = SfdpGetFlashSize (Instance);
1767 DEBUG ((DEBUG_VERBOSE, "%a: Flash Size=0x%X\n", __func__, Protocol->FlashSize));
1768 if (Protocol->FlashSize == 0) {
1769 ASSERT_EFI_ERROR (Status);
1770 }
1771
1772 // Set flash erase block size.
1773 Status = SetSectorEraseBlockSize (Instance);
1774 if (EFI_ERROR (Status)) {
1775 DEBUG ((DEBUG_ERROR, "%a: Fails to get the smallest erase block size.\n", __func__));
1776 ASSERT (FALSE);
1777 }
1778
1779 return Status;
1780}
UINT64 UINTN
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
LIST_ENTRY *EFIAPI GetNextNode(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:333
BOOLEAN EFIAPI IsNodeAtEnd(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:481
LIST_ENTRY *EFIAPI GetFirstNode(IN CONST LIST_ENTRY *List)
Definition: LinkedList.c:298
UINT64 EFIAPI RShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: RShiftU64.c:28
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
UINT64 EFIAPI LShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: LShiftU64.c:28
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define FixedPcdGet32(TokenName)
Definition: PcdLib.h:92
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
@ SPI_TRANSACTION_WRITE_THEN_READ
Definition: SpiIo.h:51
EFI_STATUS EFIAPI ReadStatus(IN CONST EFI_SPI_NOR_FLASH_PROTOCOL *This, IN UINT32 LengthInBytes, OUT UINT8 *FlashStatus)
Definition: SpiNorFlash.c:707
EFI_STATUS WaitNotWip(IN SPI_NOR_FLASH_INSTANCE *SpiNorFlashInstance, IN UINT32 Timeout, IN UINT32 RetryCount)
Definition: SpiNorFlash.c:246
EFI_STATUS EFIAPI WriteStatus(IN CONST EFI_SPI_NOR_FLASH_PROTOCOL *This, IN UINT32 LengthInBytes, IN UINT8 *FlashStatus)
Definition: SpiNorFlash.c:744
EFI_STATUS EFIAPI LfReadData(IN CONST EFI_SPI_NOR_FLASH_PROTOCOL *This, IN UINT32 FlashAddress, IN UINT32 LengthInBytes, OUT UINT8 *Buffer)
Definition: SpiNorFlash.c:484
EFI_STATUS EFIAPI GetFlashId(IN CONST EFI_SPI_NOR_FLASH_PROTOCOL *This, OUT UINT8 *Buffer)
Definition: SpiNorFlash.c:415
EFI_STATUS EFIAPI Erase(IN CONST EFI_SPI_NOR_FLASH_PROTOCOL *This, IN UINT32 FlashAddress, IN UINT32 BlockCount)
Definition: SpiNorFlash.c:971
UINT32 FillWriteBuffer(IN SPI_NOR_FLASH_INSTANCE *Instance, IN UINT8 Opcode, IN UINT32 DummyBytes, IN UINT8 AddressBytesSupported, IN BOOLEAN UseAddress, IN UINT32 Address, IN UINT32 WriteBytes, IN UINT8 *WriteBuffer)
Definition: SpiNorFlash.c:35
UINT32 SfdpGetFlashSize(IN SPI_NOR_FLASH_INSTANCE *Instance)
EFI_STATUS CreateSingleFlashSectorMap(IN SPI_NOR_FLASH_INSTANCE *Instance)
EFI_STATUS GetEraseTypeRecord(IN SPI_NOR_FLASH_INSTANCE *Instance, IN SFDP_SEARCH_ERASE_TYPE SearchType, IN UINT32 SearchValue, IN UINT8 SupportedTypeTargetNum, IN UINT8 *SupportedTypeTarget OPTIONAL, OUT SFDP_SUPPORTED_ERASE_TYPE_RECORD **EraseTypeRecord)
EFI_STATUS InitialSpiNorFlashSfdpInstance(IN SPI_NOR_FLASH_INSTANCE *Instance)
VOID GetWriteEnableCommand(IN SPI_NOR_FLASH_INSTANCE *Instance)
VOID CreateSpiFastReadTableEntry(IN SPI_NOR_FLASH_INSTANCE *Instance, IN UINT32 FastReadInstruction, IN UINT32 FastReadModeClk, IN UINT32 FastReadDummyClk)
VOID CalculateEraseTiming(IN UINT32 SfdpEraseTypicalTime, IN UINT32 SfdpEraseTimeMultiplier, OUT UINT32 *EraseTypicalTime, OUT UINT64 *EraseTimeout)
BOOLEAN IsTargetEraseType(IN UINT16 EraseType, IN UINT8 TargetTypeNum, IN UINT8 *TargetTypes)
EFI_STATUS GetCurrentSectorMapConfiguration(IN SPI_NOR_FLASH_INSTANCE *Instance)
VOID DebugPrintEraseType(IN SFDP_SUPPORTED_ERASE_TYPE_RECORD *SupportedEraseType)
EFI_STATUS ReadSfdpSectorMapParameterTable(IN SPI_NOR_FLASH_INSTANCE *Instance)
VOID CreateEraseTypeEntry(IN SPI_NOR_FLASH_INSTANCE *Instance, IN SFDP_SUPPORTED_ERASE_TYPE_RECORD *SupportedEraseType)
VOID BuildUpEraseTypeTable(IN SPI_NOR_FLASH_INSTANCE *Instance)
EFI_STATUS SetupRegionEraseInfo(IN SPI_NOR_FLASH_INSTANCE *Instance, IN SFDP_SECTOR_REGION_RECORD *RegionRecord)
EFI_STATUS EFIAPI ReadSfdpParameterHeader(IN SPI_NOR_FLASH_INSTANCE *Instance, IN SFDP_PARAMETER_HEADER *SfdpParameterHeader, IN UINT8 ParameterIdMsb, IN UINT8 ParameterIdLsb)
EFI_STATUS ReadSfdpBasicParameterTable(IN SPI_NOR_FLASH_INSTANCE *Instance)
EFI_STATUS ReadSfdp(IN SPI_NOR_FLASH_INSTANCE *Instance)
EFI_STATUS BuildSectorMapCommandAndMap(IN SPI_NOR_FLASH_INSTANCE *Instance)
EFI_STATUS GetFastReadParameter(IN SPI_NOR_FLASH_INSTANCE *Instance, IN OUT UINT8 *FastReadInstruction, IN OUT UINT8 *FastReadModeBits, IN OUT UINT8 *FastReadDummyClocks)
EFI_STATUS EFIAPI ReadSfdpHeader(IN SPI_NOR_FLASH_INSTANCE *Instance)
EFI_STATUS SetSectorEraseBlockSize(IN SPI_NOR_FLASH_INSTANCE *Instance)
VOID BuildUpFastReadTable(IN SPI_NOR_FLASH_INSTANCE *Instance)
EFI_STATUS GetEraseBlockAttribute(IN SPI_NOR_FLASH_INSTANCE *Instance, IN SFDP_SECTOR_REGION_RECORD *FlashRegion, IN UINT32 FlashAddress, IN UINT32 RemainingSize, IN OUT UINT32 *BlockSizeToErase, IN OUT UINT32 *BlockCountToErase, OUT UINT8 *BlockEraseCommand, OUT UINT32 *TypicalTime, OUT UINT64 *MaximumTimeout)
EFI_STATUS GetRegionByFlashAddress(IN SPI_NOR_FLASH_INSTANCE *Instance, IN UINT32 FlashAddress, OUT SFDP_SECTOR_REGION_RECORD **FlashRegion)
EFI_STATUS EFIAPI SpiReadSfdpPtp(IN SPI_NOR_FLASH_INSTANCE *Instance, IN UINT32 TablePointer, IN VOID *DestBuffer, IN UINT32 LengthInBytes)
#define SFDP_SECTOR_MAP_PARAMETER_ID_LSB
#define SPI_ADDR_3BYTE_ONLY
#define SFDP_BASIC_PARAMETER_ID_LSB
JEDEC Basic Flash Parameter Header.
#define SPI_FLASH_WREN
SPDF_CONFIGURATION_COMMAND_ADDR_LENGTH
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
UINT32 EraseType2
Earse type 2 is supported.
UINT32 EraseType3
Earse type 3 is supported.
UINT32 EraseType1
Earse type 1 is supported.
UINT32 RegionSize
Region size in 256 Byte unit.
UINT32 EraseType4
Earse type 4 is supported.
UINT32 DetectionLatency
Configuration detection command read latency.
UINT32 DetectionCommandAddressLen
Configuration detection command address length.
UINT32 DetectionInstruction
Sector map configuration detection command.
UINT32 DescriptorEnd
Descriptor Sequence End Indicator.
UINT32 CommandAddress
Sector map configuration detection command address.
UINT32 DescriptorEnd
Descriptor Sequence End Indicator.
UINT32 ConfigurationID
ID of this configuration.
UINT32 DescriptorType
Descriptor Type.
UINT32 RegionCount
The region count of this configuration.
LIST_ENTRY NextCommand
Link list to next detection command.
UINT8 CommandInstruction
Detection command instruction.
UINT8 LatencyInClock
Command latency in clocks.
UINT32 CommandAddress
Address to issue the command.
SPDF_CONFIGURATION_COMMAND_ADDR_LENGTH CommandAddressLength
Adddress length of detection command.
UINT8 RegionCount
The regions of this sector map configuration.
LIST_ENTRY RegionList
The linked list of the regions.
UINT8 ConfigurationId
The ID of this configuration.
LIST_ENTRY NextDescriptor
Link list to next flash map descriptor.
UINT8 SupportedEraseType[SFDP_ERASE_TYPES_NUMBER]
Erase types supported.
LIST_ENTRY NextRegion
Link list to the next region.
UINT32 RegionSectors
Sectors in this region.
UINT32 RegionAddress
Region starting address.
UINT8 SupportedEraseTypeNum
Number of erase type supported.
UINT32 SectorSize
Sector size in byte (Minimum blcok erase size)
UINT32 RegionTotalSize
Region total size in bytes.
UINT64 EraseTimeout
Maximum typical erase timeout.
UINT16 EraseType
Erase type this flash device supports.
LIST_ENTRY NextEraseType
Link list to next erase type.
UINT8 FastReadInstruction
Fast read instruction.
UINT8 WaitStates
Fast read wait dummy clocks.
LIST_ENTRY NextFastReadCap
Link list to next Fast read capability.
SFDP_SECTOR_CONFIGURATION_MAP ConfigurationMap
Flash map descriptor.
SFDP_SECTOR_CONFIGURATION_COMMAND ConfigurationCommand
Fash configuration detection command.