[processor-sdk/performance-audio-sr.git] / psdk_cust / pdk_k2g_1_0_1_0_eng / packages / ti / board / src / flash / platform_flash / evm66x_nand.c
1 /*
2 * Copyright (c) 2010-2015, Texas Instruments Incorporated
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
34 /**
35 *
36 * \file evm66x_nand.c
37 *
38 * \brief This contains TCI66xK2x specific nand functions.
39 *
40 *
41 ******************************************************************************/
42 #include "platform_internal.h"
44 #if (PLATFORM_NAND_IN)
46 /************************
47 * Include Files
48 ************************/
50 /************************
51 * Globals
52 ************************/
54 /************************
55 * Defines and Macros
56 ************************/
58 #pragma DATA_SECTION(nandPageBuf,"platform_lib");
59 static uint8_t nandPageBuf[BYTES_PER_PAGE + SPARE_BYTES_PER_PAGE];
61 #if (PLATFORM_NAND_ECC_IN)
63 // Both RBL and Linux offsets are set for 8-bit BCH ECC
64 /*
65 * RBL ECC placement structure for each 512 byte block:
66 *
67 * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
68 * Unused ECC0 ECC1 ECC2 ECC3 ECC4 ECC5 ECC6 ECC7 ECC8 ECC9 ECC10 ECC11 ECC12 Unused
69 */
70 static const uint8_t rbl_eccLoc[4*NAND_MAX_NUM_ECC_BYTES] = {
71 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
72 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
73 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
74 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63
75 };
77 /*
78 * U-Boot ECC placement structure:
79 *
80 * The first 2 bytes are used for Bad block marker - 0xFFFF => Good block
81 * The next 'N' bytes is used for BCH bytes
82 *
83 * N = B * <Number of 512-byte sectors in a page>
84 *
85 * B = 8 bytes per 512 byte sector in BCH4
86 * B = 14 bytes per 512 byte sector in BCH8
87 * B = 26 bytes per 512 byte sector in BCH16
88 *
89 */
90 static const uint8_t linux_eccLoc[4*NAND_MAX_NUM_ECC_BYTES] = {
91 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
92 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
93 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
94 44, 45, 46, 47, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
95 };
97 #endif // #if (PLATFORM_NAND_ECC_IN)
99 NandInfo_t gNandInfo;
100 NandCtrlInfo_t gNandCtrlInfo;
101 NandEccInfo_t gNandEccInfo;
102 NandTimingInfo_t gNandTimingInfo;
104 /******************************************************************************
105 *
106 * Function: NandCmdSet
107 *
108 * Description: This function is used to indicate command cycle occurring
109 * and to send command to NAND device
110 *
111 * Parameters: uint32_t cmd - Command to NAND
112 *
113 * Return Value: None
114 *
115 *****************************************************************************/
116 static void NandCmdSet(uint32_t cmd)
117 {
118 uint16_t *cle_addr = (uint16_t *) NAND_CMD_ADDR;
120 *cle_addr = (uint16_t) cmd;
121 }
123 /******************************************************************************
124 *
125 * Function: NandAleSet
126 *
127 * Description: This function is used to indicate Address cycle occurring
128 * and to send address value to NAND device
129 *
130 * Parameters: uint32_t addr - Address to NAND
131 *
132 * Return Value: None
133 *
134 *****************************************************************************/
135 static void NandAleSet(uint32_t addr)
136 {
137 uint16_t *ale_addr = (uint16_t *) NAND_ALE_ADDR;
139 *ale_addr = (uint16_t) addr;
141 return;
142 }
144 /******************************************************************************
145 *
146 * Function: NandProgAddr
147 *
148 * Description: This function is used to send the column, page and block
149 * address to the NAND device using NandAleSet
150 *
151 * Parameters: NAND_ADDR addr - Address to NAND
152 *
153 * Return Value: None
154 *
155 *****************************************************************************/
156 static void NandProgAddr(NAND_ADDR addr)
157 {
158 /*
159 * Send address of the block + page to be read
160 * Address cycles = 5
161 */
162 NandAleSet((addr.uiColumnAddr >> 0u) & 0xFF); // CA0 -CA7 1st Cycle; Column addr
163 NandAleSet((addr.uiColumnAddr >> 8u) & 0x07); // CA8 -CA10 2nd Cycle; Column addr
164 NandAleSet(((addr.uiBlockAddr << 6u) & 0xC0) | // BA6 -BA7 3rd Cycle; Block addr
165 ((addr.uiPageAddr >> 0u) & 0x3F)); // PA0 -PA5 3rd Cycle; Page addr
166 NandAleSet((addr.uiBlockAddr >> 2u) & 0xFF); // BA8 -BA15 4th Cycle; Block addr
167 NandAleSet((addr.uiBlockAddr >> 10u) & 0x01); // BA16 5th Cycle; Block addr
168 }
170 /******************************************************************************
171 *
172 * Function: NandWaitRdy
173 *
174 * Description: This function waits for the NAND status to be ready
175 *
176 * Parameters: uint32_t in_timeout - time out value in micro seconds
177 *
178 * Return Value: Failure if Ready Pin is not high for prescribed time
179 *
180 *****************************************************************************/
181 static uint32_t NandWaitRdy(uint32_t in_timeout)
182 {
183 uint32_t count = 0;
185 do
186 {
187 platform_delay(1);
189 if (((nandWaitPinStatusGet(&gNandInfo)) & 1) == 1)
190 {
191 break;
192 }
194 count++;
196 } while (count < in_timeout);
198 if (count >= in_timeout)
199 {
200 return FAIL;
201 }
202 else
203 {
204 return SUCCESS;
205 }
206 }
208 #if (PLATFORM_NAND_READ_IN | PLATFORM_NAND_WRITE_IN)
210 /******************************************************************************
211 *
212 * Function: NandReadDataByte
213 *
214 * Description: This function is used to read Nand data byte
215 *
216 * Parameters: uint8_t* puchValue - Pointer to data buffer
217 *
218 * Return Value: None
219 *
220 *****************************************************************************/
221 static void NandReadDataByte(uint8_t* puchValue)
222 {
223 /*8-bit NAND*/
224 uint8_t *data_addr = (uint8_t *) NAND_DATA_ADDR;
226 *puchValue = *data_addr;
227 }
229 /******************************************************************************
230 *
231 * Function: NandReadDataBytes
232 *
233 * Description: This function is used to read data bytes from the NAND device
234 *
235 * Parameters: uiNumBytes - Number of bytes to be read
236 * pBuffer - Data buffer
237 *
238 * Return Value: Error/Success codes
239 *
240 *****************************************************************************/
241 static uint32_t NandReadDataBytes(uint32_t uiNumBytes, uint8_t *pBuffer)
242 {
243 uint32_t i;
245 /* 8-bit NAND */
246 for (i = 0; i < uiNumBytes; i++)
247 {
248 /* NANDRead done directly without checking for nand width */
249 NandReadDataByte((uint8_t *)pBuffer);
250 pBuffer++;
251 }
252 return SUCCESS;
253 }
255 /******************************************************************************
256 *
257 * Function: NandReadDataWord
258 *
259 * Description: This function is used to read Nand data word
260 *
261 * Parameters: uint16_t* pushValue - Pointer to data buffer
262 *
263 * Return Value: None
264 *
265 *****************************************************************************/
266 static void NandReadDataWord(uint16_t* pushValue)
267 {
268 uint16_t *data_addr = (uint16_t *) NAND_DATA_ADDR;
270 *pushValue = *data_addr;
271 }
273 /******************************************************************************
274 *
275 * Function: NandReadDataWords
276 *
277 * Description: This function is used to read data words from the NAND device
278 *
279 * Parameters: uiNumBytes - Number of bytes to be read
280 * pBuffer - Data buffer
281 *
282 * Return Value: Error/Success codes
283 *
284 *****************************************************************************/
285 static uint32_t NandReadDataWords(uint32_t uiNumBytes, uint16_t *pBuffer)
286 {
287 uint32_t i;
289 for (i = 0; i < uiNumBytes/2; i++)
290 {
291 NandReadDataWord(pBuffer);
292 pBuffer++;
293 }
295 return SUCCESS;
296 }
298 static uint32_t NandReadData(PLATFORM_DEVICE_info *p_device, uint32_t uiNumBytes, uint8_t *pBuffer)
299 {
300 uint16_t *ptrData;
301 uint32_t retVal;
303 if(p_device->width == 8)
304 {
305 /* 8-bit NAND */
306 retVal = NandReadDataBytes(uiNumBytes, pBuffer);
307 }
308 else
309 {
310 /* 16-bit NAND */
311 ptrData = (uint16_t *)pBuffer;
312 retVal = NandReadDataWords(uiNumBytes, ptrData);
313 }
315 return (retVal);
316 }
318 /******************************************************************************
319 *
320 * Function: NandReadSpareArea
321 *
322 * Description: Function to read Nand spare area
323 *
324 * Parameters: uiBlkAddr - Block Address
325 * uiPage - Page Number
326 * pBuffer - Data Buffer
327 *
328 * Return Value: Error/Success codes
329 *
330 *****************************************************************************/
331 uint32_t NandReadSpareArea(PLATFORM_DEVICE_info *p_device, uint32_t uiBlkAddr, uint32_t uiPage, uint8_t *pBuffer)
332 {
333 uint32_t ret_val = SUCCESS;
334 uint8_t status;
335 NAND_ADDR address;
338 /* Read the data to the destination buffer and detect error */
339 address.uiColumnAddr = p_device->column;
340 address.uiPageAddr = uiPage;
341 address.uiBlockAddr = uiBlkAddr;
343 /* Send 0x50h command to read the spare area */
344 NandCmdSet(NAND_PAGE_READ); // First cycle send 0
345 platform_delay(10);
347 /* Send address */
348 NandProgAddr(address);
350 NandCmdSet(0x30); // Last cycle send 30h command
351 platform_delay(NAND_WAIT_PIN_POLL_ST_DLY);
353 // Wait for Ready Busy Pin to go HIGH
354 ret_val = NandWaitRdy(NAND_PROG_TIMEOUT);
356 if (ret_val != SUCCESS) {
357 platform_errno = PLATFORM_ERRNO_DEV_BUSY;
358 IFPRINT(platform_write("NandReadSpareArea: Device timeout.\n"));
359 return FAIL;
360 }
362 /* Read the data to the destination buffer and detect error */
363 NandReadData(p_device, p_device->spare_size, pBuffer);
364 printf("[1] pBuffer: 0x%08x, *pBuffer: %x\n",(uint32_t) pBuffer, *pBuffer);
365 printf("[2] pBuffer: 0x%08x, *pBuffer: %x\n",(uint32_t) pBuffer, *pBuffer+4);
366 printf("[3] pBuffer: 0x%08x, *pBuffer: %x\n",(uint32_t) pBuffer, *pBuffer+8);
367 printf("[4] pBuffer: 0x%08x, *pBuffer: %x\n",(uint32_t) pBuffer, *pBuffer+12);
369 NandCmdSet(NAND_STATUS);
370 platform_delay(10);
371 NandReadDataByte(&status);
373 if ((status & 0x01) == 1) {
374 /* if SR0 bit is set to 1, there is Error - operation failed */
375 platform_errno = PLATFORM_ERRNO_DEV_FAIL;
376 IFPRINT(platform_write("NandReadSpareArea: Status (0x%x) has error bit set.\n", status));
377 return FAIL;
378 }
380 return SUCCESS;
381 }
382 #endif
385 /******************************************************************************
386 *
387 * Function: readNandPage
388 *
389 * Description: This function reads a page from NAND flash and detects and
390 * corrects the bit errors if ECC is enabled
391 *
392 * Parameters: NAND_ADDR address - Block Address/Page address of NAND flash
393 * uint8_t* puchBuffer - Pointer to buffer
394 *
395 * Return Value: status
396 *
397 * Assumptions: puchBuffer points to a 2KB buffer
398 *
399 ******************************************************************************/
400 #if (PLATFORM_NAND_READ_IN)
401 uint32_t readNandPage(PLATFORM_DEVICE_info *p_device, NAND_ADDR address, uint8_t* puchBuffer)
402 {
403 int32_t i = 0;
404 int32_t index;
405 uint32_t byte_count;
406 uint8_t *puchSpareAreaBuf;
407 uint8_t *pBuffer_loc;
408 uint32_t ret_val = SUCCESS;
409 uint8_t status;
411 #if (PLATFORM_NAND_ECC_IN)
412 /* ECC locations for the micron nand device */
413 const uint8_t *eccLoc = (p_device->flags == NAND_FLAG_RBL) ? rbl_eccLoc : linux_eccLoc;
414 uint8_t eccCode[4*NAND_MAX_NUM_ECC_BYTES];
415 #endif
417 if(puchBuffer == NULL)
418 return NULL_POINTER_ERROR;
420 pBuffer_loc = nandPageBuf;
421 puchSpareAreaBuf = nandPageBuf + BYTES_PER_PAGE;
422 ret_val = NandReadSpareArea(p_device, address.uiBlockAddr, address.uiPageAddr, puchSpareAreaBuf);
424 if(ret_val != SUCCESS)
425 return FAIL;
427 platform_delay(10);
429 NandCmdSet(NAND_PAGE_READ);
430 platform_delay(10);
432 /* Send address */
433 NandProgAddr(address);
435 NandCmdSet(0x30); // Last cycle send 30h command
436 platform_delay(NAND_WAIT_PIN_POLL_ST_DLY);
438 /* Wait for Ready Busy Pin to go HIGH */
439 ret_val = NandWaitRdy(NAND_PROG_TIMEOUT);
441 if(ret_val != SUCCESS) {
442 platform_errno = PLATFORM_ERRNO_DEV_TIMEOUT;
443 return FAIL;
444 }
446 #if (PLATFORM_NAND_ECC_IN)
447 nandECCReadSet(&gNandInfo);
448 nandECCDisable(&gNandInfo);
449 #endif
451 for(byte_count = 0, index = 0; byte_count < p_device->page_size; pBuffer_loc += ECC_BLOCK_SIZE, index++, byte_count += ECC_BLOCK_SIZE)
452 {
453 #if (PLATFORM_NAND_ECC_IN)
454 /* Start 4-bit ECC HW calculation for read */
455 nandECCEnable(&gNandInfo);
456 #endif
458 /* Read the data to the destination buffer and detect error */
459 NandReadData(p_device, ECC_BLOCK_SIZE, pBuffer_loc);
460 platform_delay(10);
462 #if (PLATFORM_NAND_ECC_IN)
464 /* Read Parity - read parity stored in spare NAND flash */
465 for(i = 0; i < NAND_MAX_NUM_ECC_BYTES; i++)
466 {
467 eccCode[i + (index * NAND_MAX_NUM_ECC_BYTES)] = puchSpareAreaBuf[eccLoc[i + (index * NAND_MAX_NUM_ECC_BYTES)]];
468 }
470 if(nandECCCheckAndCorrect(&gNandInfo, &eccCode[index * NAND_MAX_NUM_ECC_BYTES], pBuffer_loc) != NAND_STATUS_PASSED)
471 {
472 return FAIL;
473 }
475 nandECCDisable(&gNandInfo);
476 #endif
477 }
479 NandCmdSet(NAND_STATUS);
480 platform_delay(10);
482 NandReadDataByte(&status);
484 if ((status & 0x01) == 1) {
485 /* if SR0 bit is set to 1, there is Error - operation failed */
486 platform_errno = PLATFORM_ERRNO_DEV_FAIL;
487 return FAIL;
488 }
490 memcpy(puchBuffer, nandPageBuf, gDeviceNand.page_size);
492 return SUCCESS;
493 }
494 #endif
496 /******************************************************************************
497 *
498 * Function: NandWriteDataBytes
499 *
500 * Description: This function is used to write data bytes to the NAND device
501 *
502 * Parameters: uiNumBytes - Number of bytes to be written
503 * pBuffer - Data buffer
504 *
505 * Return Value: Error/Success codes
506 *
507 *****************************************************************************/
509 #if (PLATFORM_NAND_WRITE_IN)
510 static void NandWriteDataByte(uint8_t uchData)
511 {
512 volatile uint8_t* dest;
514 /* Data is written to the data register on the rising edge of WE# when
515 CE#, CLE, and ALE are LOW, and
516 the device is not busy. */
517 dest = (volatile uint8_t *)(NAND_DATA_ADDR);
518 *dest = uchData;
519 }
521 uint32_t NandWriteDataBytes(uint32_t uiNumBytes, uint8_t *pBuffer)
522 {
523 uint32_t i;
525 for (i = 0; i < uiNumBytes; i++)
526 {
527 /* NAND Write done directly without checking for nand width */
528 NandWriteDataByte( (uint8_t) *pBuffer );
529 pBuffer++;
530 }
532 return SUCCESS;
533 }
535 static void NandWriteDataWord(uint16_t ushData)
536 {
537 volatile uint16_t* dest;
539 /* Data is written to the data register on the rising edge of WE# when
540 CE#, CLE, and ALE are LOW, and
541 the device is not busy. */
542 dest = (volatile uint16_t *)(NAND_DATA_ADDR);
543 *dest = ushData;
544 }
546 uint32_t NandWriteDataWords(uint32_t uiNumBytes, uint16_t *pBuffer)
547 {
548 uint32_t i;
550 for (i = 0; i < uiNumBytes/2; i++)
551 {
552 /* NAND Write done directly without checking for nand width */
553 NandWriteDataWord(*pBuffer);
554 pBuffer++;
555 }
557 return SUCCESS;
558 }
560 uint32_t NandWriteData(PLATFORM_DEVICE_info *p_device, uint32_t uiNumBytes, uint8_t *pBuffer)
561 {
562 uint16_t* pshData;
563 uint32_t retVal;
565 if (p_device->width == 8)
566 {
567 /* 8-bit NAND */
568 retVal = NandWriteDataBytes(uiNumBytes, pBuffer);
569 }
570 else
571 {
572 /* 16-bit NAND */
573 pshData = (uint16_t* )pBuffer;
574 retVal = NandWriteDataWords(uiNumBytes, pshData);
575 }
577 return (retVal);
578 }
580 #endif
582 /******************************************************************************
583 *
584 * Function: writeNandPage
585 *
586 * Description: This function a page to NAND flash. It computes ECC and
587 * and writes it to spare area if ECC is enabled
588 *
589 * Parameters: NAND_ADDR address - Block Address/Page address of NAND flash
590 * uint8_t* puchBuffer - Pointer to buffer
591 *
592 * Return Value: status
593 *
594 * Assumptions: puchBuffer points to a 2KB buffer
595 *
596 ******************************************************************************/
597 #if (PLATFORM_NAND_WRITE_IN)
598 uint32_t writeNandPage(PLATFORM_DEVICE_info *p_device, NAND_ADDR address, uint8_t* puchBuffer)
599 {
600 int32_t iErrors = SUCCESS;
601 int32_t i = 0;
602 uint32_t byte_count, index;
603 uint8_t puchSpareAreaBuf[SPARE_BYTES_PER_PAGE];
604 uint8_t *pBuffer_loc;
605 uint32_t ret_val = SUCCESS;
606 uint8_t status;
608 #if (PLATFORM_NAND_ECC_IN)
609 /* ECC locations for the Numonyx nand device */
610 const uint8_t *eccLoc = (p_device->flags == NAND_FLAG_RBL) ? rbl_eccLoc : linux_eccLoc;
611 uint8_t eccCalc[4*NAND_MAX_NUM_ECC_BYTES];
612 #endif
614 /* Init the buffer by reading the existing values in the spare area */
615 iErrors = NandReadSpareArea(p_device, address.uiBlockAddr, address.uiPageAddr, puchSpareAreaBuf);
616 if(iErrors != SUCCESS)
617 {
618 return iErrors;
619 }
621 #if (PLATFORM_NAND_ECC_IN)
622 nandECCWriteSet(&gNandInfo);
623 nandECCDisable(&gNandInfo);
624 #endif
626 pBuffer_loc = puchBuffer;
627 for(byte_count = 0, index = 0; byte_count < p_device->page_size; pBuffer_loc += ECC_BLOCK_SIZE, index++, byte_count += ECC_BLOCK_SIZE)
628 {
629 NandCmdSet(NAND_PROG_PAGE);
630 platform_delay(10);
632 address.uiColumnAddr = byte_count/2;
633 NandProgAddr(address);
634 platform_delay(NAND_WAIT_PIN_POLL_ST_DLY);
636 #if (PLATFORM_NAND_ECC_IN)
637 /* Start ECC HW calculation for write */
638 nandECCEnable(&gNandInfo);
639 platform_delay (10);
640 #endif
642 /* Write the data */
643 NandWriteData(p_device, ECC_BLOCK_SIZE, pBuffer_loc);
645 platform_delay (10);
647 #if (PLATFORM_NAND_ECC_IN)
649 /* Calculate the ECC bytes for write */
650 nandECCDisable(&gNandInfo);
651 nandECCCalculate(&gNandInfo, &eccCalc[index * NAND_MAX_NUM_ECC_BYTES]);
653 /* Update the calculated ECC bytes to spare area data */
654 for (i = 0; i < NAND_MAX_NUM_ECC_BYTES; i++)
655 {
656 puchSpareAreaBuf[eccLoc[i + (index * NAND_MAX_NUM_ECC_BYTES)]] = eccCalc[i + (index * NAND_MAX_NUM_ECC_BYTES)];
657 }
659 #endif
661 /* Wait for Ready Busy Pin to go HIGH */
662 NandCmdSet(NAND_CMD_10H);
664 platform_delay(NAND_WAIT_PIN_POLL_ST_DLY);
666 ret_val = NandWaitRdy(NAND_PROG_TIMEOUT*50);
668 if (ret_val != SUCCESS) {
669 platform_errno = PLATFORM_ERRNO_DEV_TIMEOUT;
670 return FAIL;
671 }
673 NandCmdSet(NAND_STATUS);
674 platform_delay(10);
676 NandReadDataByte(&status);
678 if ((status & 0x01) == 1) {
679 /* if SR0 bit is set to 1, there is Error - operation failed */
680 platform_errno = PLATFORM_ERRNO_DEV_FAIL;
681 return FAIL;
682 }
683 }
685 /* Write the spare data */
686 ret_val = NandWriteSpareArea(p_device, address.uiBlockAddr, address.uiPageAddr, puchSpareAreaBuf);
688 if (ret_val != SUCCESS)
689 return FAIL;
691 return SUCCESS;
692 }
693 #endif
695 /******************************************************************************
696 *
697 * Function: NandWriteSpareArea
698 *
699 * Description: Function to write a spare area of the NAND
700 *
701 * Parameters: uiBlkAddr - Block Address
702 * uiPage - Page Number
703 * pBuffer - Data Buffer
704 *
705 * Return Value: Error/Success codes
706 *
707 *****************************************************************************/
708 #if (PLATFORM_NAND_WRITE_IN)
709 uint32_t NandWriteSpareArea (PLATFORM_DEVICE_info *p_device, uint32_t uiBlkAddr, uint32_t uiPage, uint8_t *pBuffer)
710 {
711 uint32_t ret_val = SUCCESS;
712 uint8_t status;
713 uint8_t *pBuffer_loc;
714 NAND_ADDR address;
716 /* Read the data to the destination buffer and detect error */
717 address.uiColumnAddr = p_device->column;
718 address.uiPageAddr = uiPage;
719 address.uiBlockAddr = uiBlkAddr;
721 /* Spare Area*/
722 /*NandCmdSet(NAND_PAGE_READ);
723 platform_delay(20);*/
724 NandCmdSet(NAND_PROG_PAGE);
725 platform_delay(10);
727 /* Send address */
728 NandProgAddr(address);
729 platform_delay (NAND_WAIT_PIN_POLL_ST_DLY);
731 /* Write the data */
732 pBuffer_loc = pBuffer;
733 NandWriteData(p_device, p_device->spare_size, (uint8_t *)pBuffer_loc);
735 /* Wait for Ready Busy Pin to go HIGH */
736 NandCmdSet(NAND_CMD_10H);
738 platform_delay(NAND_WAIT_PIN_POLL_ST_DLY);
740 ret_val = NandWaitRdy(NAND_PROG_TIMEOUT*50);
742 if (ret_val != SUCCESS) {
743 platform_errno = PLATFORM_ERRNO_DEV_TIMEOUT;
744 return FAIL;
745 }
747 NandCmdSet(NAND_STATUS);
748 platform_delay(10);
750 NandReadDataByte(&status);
752 if ((status & 0x01) == 1) {
753 /* if SR0 bit is set to 1, there is Error - operation failed */
754 platform_errno = PLATFORM_ERRNO_DEV_FAIL;
755 return FAIL;
756 }
758 return SUCCESS;
759 }
760 #endif
762 /******************************************************************************
763 *
764 * Function: nandFlashBlockErase
765 *
766 * Description: This function erases the specified block of NAND flash
767 *
768 * Parameters: NAND_ADDR address - Block Address of NAND flash
769 *
770 * Return Value: status
771 *
772 *****************************************************************************/
773 #if (PLATFORM_NAND_WRITE_IN)
774 uint32_t nandFlashBlockErase(PLATFORM_DEVICE_info *p_device, uint32_t uiBlockNumber)
775 {
776 uint32_t ret_val = SUCCESS;
777 uint8_t status;
779 NandCmdSet(NAND_BLOCK_ERASE); // Block erase command
780 platform_delay(25);
782 /*
783 * Send address of the block + page to be read
784 * Address cycles = 3
785 */
787 /* Properly adjust the shifts to match to the data sheet */
789 NandAleSet((uiBlockNumber << 6u) & 0xC0); // B0 -B1 1st Cycle; Block addr
790 platform_delay(25);
791 NandAleSet((uiBlockNumber >> 2u) & 0xFF); // B2 -B9 2nd Cycle; Block addr
792 platform_delay(25);
793 NandAleSet((uiBlockNumber >> 10u) & 0x01); // B10-B11 3rd Cycle; Block addr
794 platform_delay(1000);
796 NandCmdSet(NAND_ERASE_CONFIRM); // Erase confirm
797 platform_delay(NAND_WAIT_PIN_POLL_ST_DLY);
799 /* Wait for erase operation to finish: 2msec */
800 ret_val = NandWaitRdy(NAND_BLOCK_ERASE_TIMEOUT);
802 if (ret_val != SUCCESS) {
803 platform_errno = PLATFORM_ERRNO_DEV_TIMEOUT;
804 return FAIL;
805 }
807 NandCmdSet(NAND_STATUS);
808 platform_delay(10);
810 NandReadDataByte(&status);
812 if ((status & 0x01) == 1) {
813 /* if SR0 bit is set to 1, there is Error - operation failed */
814 platform_errno = PLATFORM_ERRNO_DEV_FAIL;
815 return FAIL;
816 }
818 return SUCCESS;
820 }
821 #endif
823 /******************************************************************************
824 * *
825 * \brief Function to initalize the NAND timing info. *
826 * *
827 * \param nandTimimgInfo : Pointer to structure containing *
828 * NAND timing info. *
829 * *
830 * \return none. *
831 * *
832 ******************************************************************************/
833 static void NandTimingInfoInit(NandTimingInfo_t *nandTimingInfo)
834 {
835 nandTimingInfo->CSWrOffTime = NAND_CSWROFFTIME;
836 nandTimingInfo->CSRdOffTime = NAND_CSRDOFFTIME;
837 nandTimingInfo->CSExtDelayFlag = GPMC_CS_EXTRA_NODELAY;
838 nandTimingInfo->CSOnTime = NAND_CSONTIME;
840 nandTimingInfo->ADVAADMuxWrOffTime = NAND_ADVAADMUXWROFFTIME;
841 nandTimingInfo->ADVAADMuxRdOffTime = NAND_ADVAADMUXRDOFFTIME;
842 nandTimingInfo->ADVWrOffTime = NAND_ADVWROFFTIME;
843 nandTimingInfo->ADVRdOffTime = NAND_ADVRDOFFTIME;
844 nandTimingInfo->ADVExtDelayFlag = GPMC_ADV_EXTRA_NODELAY;
845 nandTimingInfo->ADVAADMuxOnTime = NAND_ADVAADMUXONTIME;
846 nandTimingInfo->ADVOnTime = NAND_ADVONTIME;
848 nandTimingInfo->WEOffTime = NAND_WEOFFTIME;
849 nandTimingInfo->WEExtDelayFlag = GPMC_WE_EXTRA_NODELAY;
850 nandTimingInfo->WEOnTime = NAND_WEONTIME;
851 nandTimingInfo->OEAADMuxOffTime = NAND_OEAADMUXOFFTIME;
852 nandTimingInfo->OEOffTime = NAND_OEOFFTIME;
853 nandTimingInfo->OEExtDelayFlag = GPMC_OE_EXTRA_NODELAY;
854 nandTimingInfo->OEAADMuxOnTime = NAND_OEAADMUXONTIME;
855 nandTimingInfo->OEOnTime = NAND_OEONTIME;
857 nandTimingInfo->rdCycleTime = NAND_RDCYCLETIME;
858 nandTimingInfo->wrCycleTime = NAND_WRCYCLETIME;
859 nandTimingInfo->rdAccessTime = NAND_RDACCESSTIME;
860 nandTimingInfo->pageBurstAccessTime = NAND_PAGEBURSTACCESSTIME;
862 nandTimingInfo->cycle2CycleDelay = NAND_CYCLE2CYCLEDELAY;
863 nandTimingInfo->cycle2CycleDelaySameCSCfg = NAND_CYCLE2CYCLESAMECSEN;
864 nandTimingInfo->cycle2CycleDelayDiffCSCfg = NAND_CYCLE2CYCLEDIFFCSEN;
865 nandTimingInfo->busTAtime = NAND_BUSTURNAROUND;
867 nandTimingInfo->wrAccessTime = NAND_WRACCESSTIME;
868 nandTimingInfo->wrDataOnADMux = NAND_WRDATAONADMUXBUS;
869 }
871 /******************************************************************************
872 * *
873 * \brief Function to initalize the NAND configuration info. *
874 * *
875 * \param nandTimimgInfo : Pointer to structure containing *
876 * NAND timing info. *
877 * *
878 * \return none. *
879 * *
880 ******************************************************************************/
881 static void NandInfoInit(NandInfo_t *nandInfo)
882 {
883 NandCtrlInfo_t *hNandCtrlInfo = nandInfo->hNandCtrlInfo;
884 NandEccInfo_t *hNandEccInfo = nandInfo->hNandEccInfo;
886 /* Init the NAND Device Info */
887 nandInfo->eccType = NAND_ECC_ALGO_BCH_8BIT;
888 nandInfo->chipSelectCnt = 1;
889 nandInfo->dieCnt = 1;
890 nandInfo->chipSelects[0] = NAND_CS;
891 nandInfo->busWidth = NAND_BUSWIDTH_16BIT;
892 nandInfo->pageSize = NAND_PAGESIZE_2048BYTES;
893 nandInfo->blkSize = NAND_BLOCKSIZE_128KB;
894 nandInfo->pagesPerBlk = PAGES_PER_BLOCK;
896 /* Init the NAND Controller Info struct */
897 hNandCtrlInfo->hNandTimingInfo = &gNandTimingInfo;
898 hNandCtrlInfo->hGpmc = (gpmcHandle)CSL_GPMC_0_CFG_REGS;
899 hNandCtrlInfo->waitPin = GPMC_WAIT_PIN0;
900 hNandCtrlInfo->waitPinPol = GPMC_WAIT_PIN_POLARITY_LOW;
901 hNandCtrlInfo->wpPinPol = GPMC_WP_PIN_LEVEL_HIGH;
902 hNandCtrlInfo->chipSelectBaseAddr[0] = NAND_CS0_BASEADDR;
903 hNandCtrlInfo->chipSelectRegionSize[0] = NAND_CS0_REGIONSIZE;
904 hNandCtrlInfo->currChipSelect = NAND_CS;
906 hNandEccInfo->hElm = (elmHandle)CSL_ELM_0_CFG_REGS;
907 }
909 /******************************************************************************
910 *
911 * Function: NandConfig
912 *
913 * Description: This function is used to congigure the NAND Device
914 *
915 * Parameters: None
916 *
917 * Return Value: Err Status
918 *
919 *****************************************************************************/
920 static uint32_t NandConfig ()
921 {
922 NandStatus_t status;
924 /* Initialize NAND info */
925 NandInfoInit(&gNandInfo);
927 /* Initialize NAND timing information */
928 NandTimingInfoInit(gNandCtrlInfo.hNandTimingInfo);
930 /* Initialize the controller */
931 status = nandCtrlInit(&gNandInfo);
932 if (status != NAND_STATUS_PASSED)
933 {
934 platform_errno = PLATFORM_ERRNO_DEV_FAIL;
935 IFPRINT(platform_write("NandConfig ... Nand Controller Init Failed \n"));
936 return FAIL;
937 }
939 return SUCCESS;
940 }
942 /******************************************************************************
943 *
944 * Function: NandOpenDevice
945 *
946 * Description: This function is used to open the NAND device and configure it
947 *
948 * Parameters: None
949 *
950 * Return Value: Error/Success codes
951 *
952 *****************************************************************************/
953 static uint32_t NandOpenDevice(void)
954 {
955 uint8_t status;
957 /* Initialize NAND interface */
958 if (NandConfig() != SUCCESS) {
959 IFPRINT(platform_write("NandOpenDevice ... could not initialize the Nand Interface. \n"));
960 return FAIL;
961 }
963 #if (PLATFORM_NAND_ECC_IN)
964 /* Initialize ECC module */
965 if (nandECCInit(&gNandInfo) != NAND_STATUS_PASSED) {
966 IFPRINT(platform_write("nandECCInit ... could not initialize the Nand ECC Interface. \n"));
967 return FAIL;
968 }
969 #endif
971 /* Send reset command to NAND */
972 NandCmdSet(NAND_RST);
973 platform_delay (NAND_WAIT_PIN_POLL_ST_DLY);
975 if (NandWaitRdy(NAND_RESET_TIMEOUT) != SUCCESS) {
976 platform_errno = PLATFORM_ERRNO_DEV_TIMEOUT;
977 IFPRINT(platform_write("NandOpenDevice ... Nand wait ready failed. \n"));
978 return FAIL;
979 }
981 NandCmdSet(NAND_STATUS);
982 platform_delay(10);
984 NandReadDataByte(&status);
986 if ((status & 0x01) == 1) {
987 /* if SR0 bit is set to 1, there is Error - operation failed */
988 platform_errno = PLATFORM_ERRNO_DEV_FAIL;
989 IFPRINT(platform_write("NandOpenDevice ... Nand status error bit was set. \n"));
990 return FAIL;
991 }
993 return SUCCESS;
994 }
996 /******************************************************************************
997 *
998 * Function: NandGetDetails
999 *
1000 * Description: Get details of the NAND flash used from the id and the
1001 * table of NAND
1002 *
1003 * Parameters: pNandInfo - Pointer to Nand Info structure
1004 *
1005 * Return Value: Error/Success codes
1006 *
1007 *****************************************************************************/
1008 uint32_t NandGetDetails(PLATFORM_DEVICE_info *pNandInfo)
1009 {
1010 uint32_t i;
1011 uint32_t uiStatus;
1012 NAND_ADDR address;
1014 /* Clear the Information */
1015 pNandInfo->device_id = pNandInfo->manufacturer_id = 0x0;
1017 /* Read manufacturer ID and device ID */
1018 NandCmdSet(NAND_RDID);
1019 platform_delay(10);
1020 NandAleSet(NAND_ADD_00H);
1021 platform_delay(10);
1023 NandReadDataWord((uint16_t *)&pNandInfo->manufacturer_id);
1024 NandReadDataWord((uint16_t *)&pNandInfo->device_id);
1026 /* Get the bad block table */
1027 address.uiPageAddr = 0;
1028 address.uiColumnAddr = 0;
1030 for (i=0; i < BLOCKS_PER_DEVICE; i++) {
1031 address.uiBlockAddr = i;
1033 /* Clear the Spare Area */
1034 memset(nandPageBuf, 0, SPARE_BYTES_PER_PAGE);
1036 // Read the spare area in to buffer
1037 uiStatus = NandReadSpareArea(pNandInfo, address.uiBlockAddr,
1038 address.uiPageAddr, nandPageBuf);
1039 if(uiStatus != SUCCESS) {
1040 return PLATFORM_ERRNO_NANDBBT;
1041 }
1042 else { // Success in reading the NAND spare area
1043 if (nandPageBuf[pNandInfo->bboffset] == 0xFF) {
1044 pNandInfo->bblist[i] = 0xFF;
1045 } else {
1046 pNandInfo->bblist[i] = 0x00;
1047 }
1048 }
1049 }
1050 return SUCCESS;
1051 }
1053 /******************************************************************************
1054 *
1055 * Function: nandInit
1056 *
1057 * Description: This function initialize the EMIF16 NAND flash controller.
1058 *
1059 * Parameters: None
1060 *
1061 * Return Value: status
1062 *
1063 ******************************************************************************/
1064 uint32_t nandInit(void)
1065 {
1066 uint32_t retVal;
1068 gNandInfo.hNandCtrlInfo = &gNandCtrlInfo;
1069 gNandInfo.hNandEccInfo = &gNandEccInfo;
1071 /* Open the NAND Device */
1072 retVal = NandOpenDevice();
1074 return (retVal);
1075 }
1077 #endif /*(PLATFORM_NAND_IN)*/