1 /** @file 2 3 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR> 4 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include "Flash.h" 16 17 NAND_PART_INFO_TABLE gNandPartInfoTable[1] = { 18 { 0x2C, 0xBA, 17, 11 } 19 }; 20 21 NAND_FLASH_INFO *gNandFlashInfo = NULL; 22 UINT8 *gEccCode; 23 UINTN gNum512BytesChunks = 0; 24 25 // 26 27 // Device path for SemiHosting. It contains our autogened Caller ID GUID. 28 29 // 30 31 typedef struct { 32 33 VENDOR_DEVICE_PATH Guid; 34 35 EFI_DEVICE_PATH_PROTOCOL End; 36 37 } FLASH_DEVICE_PATH; 38 39 40 41 FLASH_DEVICE_PATH gDevicePath = { 42 { 43 { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, { sizeof (VENDOR_DEVICE_PATH), 0 } }, 44 EFI_CALLER_ID_GUID 45 }, 46 { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0} } 47 }; 48 49 50 51 //Actual page address = Column address + Page address + Block address. 52 UINTN 53 GetActualPageAddressInBytes ( 54 UINTN BlockIndex, 55 UINTN PageIndex 56 ) 57 { 58 //BlockAddressStart = Start of the Block address in actual NAND 59 //PageAddressStart = Start of the Page address in actual NAND 60 return ((BlockIndex << gNandFlashInfo->BlockAddressStart) + (PageIndex << gNandFlashInfo->PageAddressStart)); 61 } 62 63 VOID 64 NandSendCommand ( 65 UINT8 Command 66 ) 67 { 68 MmioWrite16(GPMC_NAND_COMMAND_0, Command); 69 } 70 71 VOID 72 NandSendAddress ( 73 UINT8 Address 74 ) 75 { 76 MmioWrite16(GPMC_NAND_ADDRESS_0, Address); 77 } 78 79 UINT16 80 NandReadStatus ( 81 VOID 82 ) 83 { 84 //Send READ STATUS command 85 NandSendCommand(READ_STATUS_CMD); 86 87 //Read status. 88 return MmioRead16(GPMC_NAND_DATA_0); 89 } 90 91 VOID 92 NandSendAddressCycles ( 93 UINTN Address 94 ) 95 { 96 //Column address 97 NandSendAddress(Address & 0xff); 98 Address >>= 8; 99 100 //Column address 101 NandSendAddress(Address & 0x07); 102 Address >>= 3; 103 104 //Page and Block address 105 NandSendAddress(Address & 0xff); 106 Address >>= 8; 107 108 //Block address 109 NandSendAddress(Address & 0xff); 110 Address >>= 8; 111 112 //Block address 113 NandSendAddress(Address & 0x01); 114 } 115 116 VOID 117 GpmcInit ( 118 VOID 119 ) 120 { 121 //Enable Smart-idle mode. 122 MmioWrite32 (GPMC_SYSCONFIG, SMARTIDLEMODE); 123 124 //Set IRQSTATUS and IRQENABLE to the reset value 125 MmioWrite32 (GPMC_IRQSTATUS, 0x0); 126 MmioWrite32 (GPMC_IRQENABLE, 0x0); 127 128 //Disable GPMC timeout control. 129 MmioWrite32 (GPMC_TIMEOUT_CONTROL, TIMEOUTDISABLE); 130 131 //Set WRITEPROTECT bit to enable write access. 132 MmioWrite32 (GPMC_CONFIG, WRITEPROTECT_HIGH); 133 134 //NOTE: Following GPMC_CONFIGi_0 register settings are taken from u-boot memory dump. 135 MmioWrite32 (GPMC_CONFIG1_0, DEVICETYPE_NAND | DEVICESIZE_X16); 136 MmioWrite32 (GPMC_CONFIG2_0, CSRDOFFTIME | CSWROFFTIME); 137 MmioWrite32 (GPMC_CONFIG3_0, ADVRDOFFTIME | ADVWROFFTIME); 138 MmioWrite32 (GPMC_CONFIG4_0, OEONTIME | OEOFFTIME | WEONTIME | WEOFFTIME); 139 MmioWrite32 (GPMC_CONFIG5_0, RDCYCLETIME | WRCYCLETIME | RDACCESSTIME | PAGEBURSTACCESSTIME); 140 MmioWrite32 (GPMC_CONFIG6_0, WRACCESSTIME | WRDATAONADMUXBUS | CYCLE2CYCLEDELAY | CYCLE2CYCLESAMECSEN); 141 MmioWrite32 (GPMC_CONFIG7_0, MASKADDRESS_128MB | CSVALID | BASEADDRESS); 142 } 143 144 EFI_STATUS 145 NandDetectPart ( 146 VOID 147 ) 148 { 149 UINT8 NandInfo = 0; 150 UINT8 PartInfo[5]; 151 UINTN Index; 152 BOOLEAN Found = FALSE; 153 154 //Send READ ID command 155 NandSendCommand(READ_ID_CMD); 156 157 //Send one address cycle. 158 NandSendAddress(0); 159 160 //Read 5-bytes to idenfity code programmed into the NAND flash devices. 161 //BYTE 0 = Manufacture ID 162 //Byte 1 = Device ID 163 //Byte 2, 3, 4 = Nand part specific information (Page size, Block size etc) 164 for (Index = 0; Index < sizeof(PartInfo); Index++) { 165 PartInfo[Index] = MmioRead16(GPMC_NAND_DATA_0); 166 } 167 168 //Check if the ManufactureId and DeviceId are part of the currently supported nand parts. 169 for (Index = 0; Index < sizeof(gNandPartInfoTable)/sizeof(NAND_PART_INFO_TABLE); Index++) { 170 if (gNandPartInfoTable[Index].ManufactureId == PartInfo[0] && gNandPartInfoTable[Index].DeviceId == PartInfo[1]) { 171 gNandFlashInfo->BlockAddressStart = gNandPartInfoTable[Index].BlockAddressStart; 172 gNandFlashInfo->PageAddressStart = gNandPartInfoTable[Index].PageAddressStart; 173 Found = TRUE; 174 break; 175 } 176 } 177 178 if (Found == FALSE) { 179 DEBUG ((EFI_D_ERROR, "Nand part is not currently supported. Manufacture id: %x, Device id: %x\n", PartInfo[0], PartInfo[1])); 180 return EFI_NOT_FOUND; 181 } 182 183 //Populate NAND_FLASH_INFO based on the result of READ ID command. 184 gNandFlashInfo->ManufactureId = PartInfo[0]; 185 gNandFlashInfo->DeviceId = PartInfo[1]; 186 NandInfo = PartInfo[3]; 187 188 if (PAGE_SIZE(NandInfo) == PAGE_SIZE_2K_VAL) { 189 gNandFlashInfo->PageSize = PAGE_SIZE_2K; 190 } else { 191 DEBUG ((EFI_D_ERROR, "Unknown Page size.\n")); 192 return EFI_DEVICE_ERROR; 193 } 194 195 if (SPARE_AREA_SIZE(NandInfo) == SPARE_AREA_SIZE_64B_VAL) { 196 gNandFlashInfo->SparePageSize = SPARE_AREA_SIZE_64B; 197 } else { 198 DEBUG ((EFI_D_ERROR, "Unknown Spare area size.\n")); 199 return EFI_DEVICE_ERROR; 200 } 201 202 if (BLOCK_SIZE(NandInfo) == BLOCK_SIZE_128K_VAL) { 203 gNandFlashInfo->BlockSize = BLOCK_SIZE_128K; 204 } else { 205 DEBUG ((EFI_D_ERROR, "Unknown Block size.\n")); 206 return EFI_DEVICE_ERROR; 207 } 208 209 if (ORGANIZATION(NandInfo) == ORGANIZATION_X8) { 210 gNandFlashInfo->Organization = 0; 211 } else if (ORGANIZATION(NandInfo) == ORGANIZATION_X16) { 212 gNandFlashInfo->Organization = 1; 213 } 214 215 //Calculate total number of blocks. 216 gNandFlashInfo->NumPagesPerBlock = DivU64x32(gNandFlashInfo->BlockSize, gNandFlashInfo->PageSize); 217 218 return EFI_SUCCESS; 219 } 220 221 VOID 222 NandConfigureEcc ( 223 VOID 224 ) 225 { 226 //Define ECC size 0 and size 1 to 512 bytes 227 MmioWrite32 (GPMC_ECC_SIZE_CONFIG, (ECCSIZE0_512BYTES | ECCSIZE1_512BYTES)); 228 } 229 230 VOID 231 NandEnableEcc ( 232 VOID 233 ) 234 { 235 //Clear all the ECC result registers and select ECC result register 1 236 MmioWrite32 (GPMC_ECC_CONTROL, (ECCCLEAR | ECCPOINTER_REG1)); 237 238 //Enable ECC engine on CS0 239 MmioWrite32 (GPMC_ECC_CONFIG, (ECCENABLE | ECCCS_0 | ECC16B)); 240 } 241 242 VOID 243 NandDisableEcc ( 244 VOID 245 ) 246 { 247 //Turn off ECC engine. 248 MmioWrite32 (GPMC_ECC_CONFIG, ECCDISABLE); 249 } 250 251 VOID 252 NandCalculateEcc ( 253 VOID 254 ) 255 { 256 UINTN Index; 257 UINTN EccResultRegister; 258 UINTN EccResult; 259 260 //Capture 32-bit ECC result for each 512-bytes chunk. 261 //In our case PageSize is 2K so read ECC1-ECC4 result registers and 262 //generate total of 12-bytes of ECC code for the particular page. 263 264 EccResultRegister = GPMC_ECC1_RESULT; 265 266 for (Index = 0; Index < gNum512BytesChunks; Index++) { 267 268 EccResult = MmioRead32 (EccResultRegister); 269 270 //Calculate ECC code from 32-bit ECC result value. 271 //NOTE: Following calculation is not part of TRM. We got this information 272 //from Beagleboard mailing list. 273 gEccCode[Index * 3] = EccResult & 0xFF; 274 gEccCode[(Index * 3) + 1] = (EccResult >> 16) & 0xFF; 275 gEccCode[(Index * 3) + 2] = (((EccResult >> 20) & 0xF0) | ((EccResult >> 8) & 0x0F)); 276 277 //Point to next ECC result register. 278 EccResultRegister += 4; 279 } 280 } 281 282 EFI_STATUS 283 NandReadPage ( 284 IN UINTN BlockIndex, 285 IN UINTN PageIndex, 286 OUT VOID *Buffer, 287 OUT UINT8 *SpareBuffer 288 ) 289 { 290 UINTN Address; 291 UINTN Index; 292 UINTN NumMainAreaWords = (gNandFlashInfo->PageSize/2); 293 UINTN NumSpareAreaWords = (gNandFlashInfo->SparePageSize/2); 294 UINT16 *MainAreaWordBuffer = Buffer; 295 UINT16 *SpareAreaWordBuffer = (UINT16 *)SpareBuffer; 296 UINTN Timeout = MAX_RETRY_COUNT; 297 298 //Generate device address in bytes to access specific block and page index 299 Address = GetActualPageAddressInBytes(BlockIndex, PageIndex); 300 301 //Send READ command 302 NandSendCommand(PAGE_READ_CMD); 303 304 //Send 5 Address cycles to access specific device address 305 NandSendAddressCycles(Address); 306 307 //Send READ CONFIRM command 308 NandSendCommand(PAGE_READ_CONFIRM_CMD); 309 310 //Poll till device is busy. 311 while (Timeout) { 312 if ((NandReadStatus() & NAND_READY) == NAND_READY) { 313 break; 314 } 315 Timeout--; 316 } 317 318 if (Timeout == 0) { 319 DEBUG ((EFI_D_ERROR, "Read page timed out.\n")); 320 return EFI_TIMEOUT; 321 } 322 323 //Reissue READ command 324 NandSendCommand(PAGE_READ_CMD); 325 326 //Enable ECC engine. 327 NandEnableEcc(); 328 329 //Read data into the buffer. 330 for (Index = 0; Index < NumMainAreaWords; Index++) { 331 *MainAreaWordBuffer++ = MmioRead16(GPMC_NAND_DATA_0); 332 } 333 334 //Read spare area into the buffer. 335 for (Index = 0; Index < NumSpareAreaWords; Index++) { 336 *SpareAreaWordBuffer++ = MmioRead16(GPMC_NAND_DATA_0); 337 } 338 339 //Calculate ECC. 340 NandCalculateEcc(); 341 342 //Turn off ECC engine. 343 NandDisableEcc(); 344 345 //Perform ECC correction. 346 //Need to implement.. 347 348 return EFI_SUCCESS; 349 } 350 351 EFI_STATUS 352 NandWritePage ( 353 IN UINTN BlockIndex, 354 IN UINTN PageIndex, 355 OUT VOID *Buffer, 356 IN UINT8 *SpareBuffer 357 ) 358 { 359 UINTN Address; 360 UINT16 *MainAreaWordBuffer = Buffer; 361 UINT16 *SpareAreaWordBuffer = (UINT16 *)SpareBuffer; 362 UINTN Index; 363 UINTN NandStatus; 364 UINTN Timeout = MAX_RETRY_COUNT; 365 366 //Generate device address in bytes to access specific block and page index 367 Address = GetActualPageAddressInBytes(BlockIndex, PageIndex); 368 369 //Send SERIAL DATA INPUT command 370 NandSendCommand(PROGRAM_PAGE_CMD); 371 372 //Send 5 Address cycles to access specific device address 373 NandSendAddressCycles(Address); 374 375 //Enable ECC engine. 376 NandEnableEcc(); 377 378 //Data input from Buffer 379 for (Index = 0; Index < (gNandFlashInfo->PageSize/2); Index++) { 380 MmioWrite16(GPMC_NAND_DATA_0, *MainAreaWordBuffer++); 381 382 //After each write access, device has to wait to accept data. 383 //Currently we may not be programming proper timing parameters to 384 //the GPMC_CONFIGi_0 registers and we would need to figure that out. 385 //Without following delay, page programming fails. 386 gBS->Stall(1); 387 } 388 389 //Calculate ECC. 390 NandCalculateEcc(); 391 392 //Turn off ECC engine. 393 NandDisableEcc(); 394 395 //Prepare Spare area buffer with ECC codes. 396 SetMem(SpareBuffer, gNandFlashInfo->SparePageSize, 0xFF); 397 CopyMem(&SpareBuffer[ECC_POSITION], gEccCode, gNum512BytesChunks * 3); 398 399 //Program spare area with calculated ECC. 400 for (Index = 0; Index < (gNandFlashInfo->SparePageSize/2); Index++) { 401 MmioWrite16(GPMC_NAND_DATA_0, *SpareAreaWordBuffer++); 402 } 403 404 //Send PROGRAM command 405 NandSendCommand(PROGRAM_PAGE_CONFIRM_CMD); 406 407 //Poll till device is busy. 408 NandStatus = 0; 409 while (Timeout) { 410 NandStatus = NandReadStatus(); 411 if ((NandStatus & NAND_READY) == NAND_READY) { 412 break; 413 } 414 Timeout--; 415 } 416 417 if (Timeout == 0) { 418 DEBUG ((EFI_D_ERROR, "Program page timed out.\n")); 419 return EFI_TIMEOUT; 420 } 421 422 //Bit0 indicates Pass/Fail status 423 if (NandStatus & NAND_FAILURE) { 424 return EFI_DEVICE_ERROR; 425 } 426 427 return EFI_SUCCESS; 428 } 429 430 EFI_STATUS 431 NandEraseBlock ( 432 IN UINTN BlockIndex 433 ) 434 { 435 UINTN Address; 436 UINTN NandStatus; 437 UINTN Timeout = MAX_RETRY_COUNT; 438 439 //Generate device address in bytes to access specific block and page index 440 Address = GetActualPageAddressInBytes(BlockIndex, 0); 441 442 //Send ERASE SETUP command 443 NandSendCommand(BLOCK_ERASE_CMD); 444 445 //Send 3 address cycles to device to access Page address and Block address 446 Address >>= 11; //Ignore column addresses 447 448 NandSendAddress(Address & 0xff); 449 Address >>= 8; 450 451 NandSendAddress(Address & 0xff); 452 Address >>= 8; 453 454 NandSendAddress(Address & 0xff); 455 456 //Send ERASE CONFIRM command 457 NandSendCommand(BLOCK_ERASE_CONFIRM_CMD); 458 459 //Poll till device is busy. 460 NandStatus = 0; 461 while (Timeout) { 462 NandStatus = NandReadStatus(); 463 if ((NandStatus & NAND_READY) == NAND_READY) { 464 break; 465 } 466 Timeout--; 467 gBS->Stall(1); 468 } 469 470 if (Timeout == 0) { 471 DEBUG ((EFI_D_ERROR, "Erase block timed out for Block: %d.\n", BlockIndex)); 472 return EFI_TIMEOUT; 473 } 474 475 //Bit0 indicates Pass/Fail status 476 if (NandStatus & NAND_FAILURE) { 477 return EFI_DEVICE_ERROR; 478 } 479 480 return EFI_SUCCESS; 481 } 482 483 EFI_STATUS 484 NandReadBlock ( 485 IN UINTN StartBlockIndex, 486 IN UINTN EndBlockIndex, 487 OUT VOID *Buffer, 488 OUT VOID *SpareBuffer 489 ) 490 { 491 UINTN BlockIndex; 492 UINTN PageIndex; 493 EFI_STATUS Status = EFI_SUCCESS; 494 495 for (BlockIndex = StartBlockIndex; BlockIndex <= EndBlockIndex; BlockIndex++) { 496 //For each block read number of pages 497 for (PageIndex = 0; PageIndex < gNandFlashInfo->NumPagesPerBlock; PageIndex++) { 498 Status = NandReadPage(BlockIndex, PageIndex, Buffer, SpareBuffer); 499 if (EFI_ERROR(Status)) { 500 return Status; 501 } 502 Buffer = ((UINT8 *)Buffer + gNandFlashInfo->PageSize); 503 } 504 } 505 506 return Status; 507 } 508 509 EFI_STATUS 510 NandWriteBlock ( 511 IN UINTN StartBlockIndex, 512 IN UINTN EndBlockIndex, 513 OUT VOID *Buffer, 514 OUT VOID *SpareBuffer 515 ) 516 { 517 UINTN BlockIndex; 518 UINTN PageIndex; 519 EFI_STATUS Status = EFI_SUCCESS; 520 521 for (BlockIndex = StartBlockIndex; BlockIndex <= EndBlockIndex; BlockIndex++) { 522 //Page programming. 523 for (PageIndex = 0; PageIndex < gNandFlashInfo->NumPagesPerBlock; PageIndex++) { 524 Status = NandWritePage(BlockIndex, PageIndex, Buffer, SpareBuffer); 525 if (EFI_ERROR(Status)) { 526 return Status; 527 } 528 Buffer = ((UINT8 *)Buffer + gNandFlashInfo->PageSize); 529 } 530 } 531 532 return Status; 533 } 534 535 EFI_STATUS 536 EFIAPI 537 NandFlashReset ( 538 IN EFI_BLOCK_IO_PROTOCOL *This, 539 IN BOOLEAN ExtendedVerification 540 ) 541 { 542 UINTN BusyStall = 50; // microSeconds 543 UINTN ResetBusyTimeout = (1000000 / BusyStall); // 1 Second 544 545 //Send RESET command to device. 546 NandSendCommand(RESET_CMD); 547 548 //Wait for 1ms before we check status register. 549 gBS->Stall(1000); 550 551 //Check BIT#5 & BIT#6 in Status register to make sure RESET is done. 552 while ((NandReadStatus() & NAND_RESET_STATUS) != NAND_RESET_STATUS) { 553 554 //In case of extended verification, wait for extended amount of time 555 //to make sure device is reset. 556 if (ExtendedVerification) { 557 if (ResetBusyTimeout == 0) { 558 return EFI_DEVICE_ERROR; 559 } 560 561 gBS->Stall(BusyStall); 562 ResetBusyTimeout--; 563 } 564 } 565 566 return EFI_SUCCESS; 567 } 568 569 EFI_STATUS 570 EFIAPI 571 NandFlashReadBlocks ( 572 IN EFI_BLOCK_IO_PROTOCOL *This, 573 IN UINT32 MediaId, 574 IN EFI_LBA Lba, 575 IN UINTN BufferSize, 576 OUT VOID *Buffer 577 ) 578 { 579 UINTN NumBlocks; 580 UINTN EndBlockIndex; 581 EFI_STATUS Status; 582 UINT8 *SpareBuffer = NULL; 583 584 if (Buffer == NULL) { 585 Status = EFI_INVALID_PARAMETER; 586 goto exit; 587 } 588 589 if (Lba > LAST_BLOCK) { 590 Status = EFI_INVALID_PARAMETER; 591 goto exit; 592 } 593 594 if ((BufferSize % gNandFlashInfo->BlockSize) != 0) { 595 Status = EFI_BAD_BUFFER_SIZE; 596 goto exit; 597 } 598 599 NumBlocks = DivU64x32(BufferSize, gNandFlashInfo->BlockSize); 600 EndBlockIndex = ((UINTN)Lba + NumBlocks) - 1; 601 602 SpareBuffer = (UINT8 *)AllocatePool(gNandFlashInfo->SparePageSize); 603 if (SpareBuffer == NULL) { 604 Status = EFI_OUT_OF_RESOURCES; 605 goto exit; 606 } 607 608 //Read block 609 Status = NandReadBlock((UINTN)Lba, EndBlockIndex, Buffer, SpareBuffer); 610 if (EFI_ERROR(Status)) { 611 DEBUG((EFI_D_ERROR, "Read block fails: %x\n", Status)); 612 goto exit; 613 } 614 615 exit: 616 if (SpareBuffer != NULL) { 617 FreePool (SpareBuffer); 618 } 619 620 return Status; 621 } 622 623 EFI_STATUS 624 EFIAPI 625 NandFlashWriteBlocks ( 626 IN EFI_BLOCK_IO_PROTOCOL *This, 627 IN UINT32 MediaId, 628 IN EFI_LBA Lba, 629 IN UINTN BufferSize, 630 IN VOID *Buffer 631 ) 632 { 633 UINTN BlockIndex; 634 UINTN NumBlocks; 635 UINTN EndBlockIndex; 636 EFI_STATUS Status; 637 UINT8 *SpareBuffer = NULL; 638 639 if (Buffer == NULL) { 640 Status = EFI_INVALID_PARAMETER; 641 goto exit; 642 } 643 644 if (Lba > LAST_BLOCK) { 645 Status = EFI_INVALID_PARAMETER; 646 goto exit; 647 } 648 649 if ((BufferSize % gNandFlashInfo->BlockSize) != 0) { 650 Status = EFI_BAD_BUFFER_SIZE; 651 goto exit; 652 } 653 654 NumBlocks = DivU64x32(BufferSize, gNandFlashInfo->BlockSize); 655 EndBlockIndex = ((UINTN)Lba + NumBlocks) - 1; 656 657 SpareBuffer = (UINT8 *)AllocatePool(gNandFlashInfo->SparePageSize); 658 if (SpareBuffer == NULL) { 659 Status = EFI_OUT_OF_RESOURCES; 660 goto exit; 661 } 662 663 // Erase block 664 for (BlockIndex = (UINTN)Lba; BlockIndex <= EndBlockIndex; BlockIndex++) { 665 Status = NandEraseBlock(BlockIndex); 666 if (EFI_ERROR(Status)) { 667 DEBUG((EFI_D_ERROR, "Erase block failed. Status: %x\n", Status)); 668 goto exit; 669 } 670 } 671 672 // Program data 673 Status = NandWriteBlock((UINTN)Lba, EndBlockIndex, Buffer, SpareBuffer); 674 if (EFI_ERROR(Status)) { 675 DEBUG((EFI_D_ERROR, "Block write fails: %x\n", Status)); 676 goto exit; 677 } 678 679 exit: 680 if (SpareBuffer != NULL) { 681 FreePool (SpareBuffer); 682 } 683 684 return Status; 685 } 686 687 EFI_STATUS 688 EFIAPI 689 NandFlashFlushBlocks ( 690 IN EFI_BLOCK_IO_PROTOCOL *This 691 ) 692 { 693 return EFI_SUCCESS; 694 } 695 696 697 698 EFI_BLOCK_IO_MEDIA gNandFlashMedia = { 699 SIGNATURE_32('n','a','n','d'), // MediaId 700 FALSE, // RemovableMedia 701 TRUE, // MediaPresent 702 FALSE, // LogicalPartition 703 FALSE, // ReadOnly 704 FALSE, // WriteCaching 705 0, // BlockSize 706 2, // IoAlign 707 0, // Pad 708 0 // LastBlock 709 }; 710 711 EFI_BLOCK_IO_PROTOCOL BlockIo = 712 { 713 EFI_BLOCK_IO_INTERFACE_REVISION, // Revision 714 &gNandFlashMedia, // *Media 715 NandFlashReset, // Reset 716 NandFlashReadBlocks, // ReadBlocks 717 NandFlashWriteBlocks, // WriteBlocks 718 NandFlashFlushBlocks // FlushBlocks 719 }; 720 721 EFI_STATUS 722 NandFlashInitialize ( 723 IN EFI_HANDLE ImageHandle, 724 IN EFI_SYSTEM_TABLE *SystemTable 725 ) 726 { 727 EFI_STATUS Status; 728 729 gNandFlashInfo = (NAND_FLASH_INFO *)AllocateZeroPool (sizeof(NAND_FLASH_INFO)); 730 731 //Initialize GPMC module. 732 GpmcInit(); 733 734 //Reset NAND part 735 NandFlashReset(&BlockIo, FALSE); 736 737 //Detect NAND part and populate gNandFlashInfo structure 738 Status = NandDetectPart (); 739 if (EFI_ERROR(Status)) { 740 DEBUG((EFI_D_ERROR, "Nand part id detection failure: Status: %x\n", Status)); 741 return Status; 742 } 743 744 //Count total number of 512Bytes chunk based on the page size. 745 if (gNandFlashInfo->PageSize == PAGE_SIZE_512B) { 746 gNum512BytesChunks = 1; 747 } else if (gNandFlashInfo->PageSize == PAGE_SIZE_2K) { 748 gNum512BytesChunks = 4; 749 } else if (gNandFlashInfo->PageSize == PAGE_SIZE_4K) { 750 gNum512BytesChunks = 8; 751 } 752 753 gEccCode = (UINT8 *)AllocatePool(gNum512BytesChunks * 3); 754 if (gEccCode == NULL) { 755 return EFI_OUT_OF_RESOURCES; 756 } 757 758 //Configure ECC 759 NandConfigureEcc (); 760 761 //Patch EFI_BLOCK_IO_MEDIA structure. 762 gNandFlashMedia.BlockSize = gNandFlashInfo->BlockSize; 763 gNandFlashMedia.LastBlock = LAST_BLOCK; 764 765 //Publish BlockIO. 766 Status = gBS->InstallMultipleProtocolInterfaces ( 767 &ImageHandle, 768 &gEfiBlockIoProtocolGuid, &BlockIo, 769 &gEfiDevicePathProtocolGuid, &gDevicePath, 770 NULL 771 ); 772 return Status; 773 } 774 775