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