uint_32 nfc_write_phy_page_raw ( /* [IN] the NAND flash information */ IO_NANDFLASH_WL_STRUCT_PTR nandflash_ptr, /* [IN] where to copy data from */ uchar_ptr from_ptr, /* [IN] the first page to write */ uint_32 phy_page_number, /* [IN] the amount of pages to write */ uint_32 page_count ) { /* Body */ uint_32 result = NANDFLASHERR_TIMEOUT; uint_32 count1, count2; uint_32 row, col, num_ecc_bytes; boolean swap = FALSE; uint_32 cfg_bck; NFC_MemMapPtr nfc_ptr; if (nandflash_ptr->CORE_NANDFLASH.WRITE_PROTECT) { (*nandflash_ptr->CORE_NANDFLASH.WRITE_PROTECT)(&nandflash_ptr->CORE_NANDFLASH, FALSE); }/* Endif */ /* Get the pointer to nfc registers structure */ nfc_ptr = (NFC_MemMapPtr)_bsp_get_nfc_address(); /* Set the ECCMODE to 0 - ECC bypass */ cfg_bck = nfc_ptr->CFG; nfc_ptr->CFG &= ~(NFC_CFG_ECCMODE(7)); /* Reset the swap register */ nfc_ptr->SWAP = NFC_SWAP_ADDR1(0x7FF) | NFC_SWAP_ADDR2(0x7FF); for (count1 = phy_page_number; count1 < (phy_page_number + page_count); count1++) { num_ecc_bytes = NANDFLASH_ECC_SIZE_TO_NUM_BYTES_CONV(nandflash_ptr->CORE_NANDFLASH.ECC_SIZE); row = count1; col =0; if(nandflash_ptr->CORE_NANDFLASH.NANDFLASH_INFO_PTR->WIDTH == 16) col = col/2; /* Copy one virtual page into the SRAM buffer #0 */ for ( count2 = 0; count2 < (nandflash_ptr->CORE_NANDFLASH.NANDFLASH_INFO_PTR->PHY_PAGE_SIZE + nandflash_ptr->CORE_NANDFLASH.NANDFLASH_INFO_PTR->SPARE_AREA_SIZE); count2++ ) { // nfc_ptr->SRAM_B0[count2] = *(from_ptr + count2); NFC_SRAM_B0_REG(nfc_ptr, count2) = *(from_ptr + count2); } nfc_ptr->CMD1 = NFC_CMD1_BYTE2(NANDFLASH_CMD_PAGE_PROGRAM_CYCLE2) | NFC_CMD1_BYTE3(NANDFLASH_CMD_READ_STATUS); nfc_ptr->CMD2 = NFC_CMD2_BYTE1(NANDFLASH_CMD_PAGE_PROGRAM_CYCLE1) | NFC_CMD2_CODE(0x7FD8) | NFC_CMD2_BUFNO(0); nfc_ptr->CAR = col & 0xFFFF; nfc_ptr->RAR = NFC_RAR_CS0_MASK | NFC_RAR_RB0_MASK | (row & 0xFFFFFF); nfc_ptr->SECSZ = nandflash_ptr->CORE_NANDFLASH.NANDFLASH_INFO_PTR->PHY_PAGE_SIZE + nandflash_ptr->CORE_NANDFLASH.NANDFLASH_INFO_PTR->SPARE_AREA_SIZE ; nfc_ptr->ISR |= (NFC_ISR_DONECLR_MASK | NFC_ISR_DONEEN_MASK | NFC_ISR_IDLECLR_MASK | NFC_ISR_IDLEEN_MASK); /* Start command execution */ nfc_ptr->CMD2 |= NFC_CMD2_BUSY_START_MASK; for (count2 = 0; count2 <= MAX_WAIT_COMMAND; count2++) { if (nfc_ptr->ISR & NFC_ISR_IDLE_MASK) { if (nfc_ptr->SR2 & NANDFLASH_STATUS_ERR) { result = NANDFLASHERR_WRITE_FAILED; goto exit; } else { result = NANDFLASHERR_NO_ERROR; } break; } } from_ptr += nandflash_ptr->CORE_NANDFLASH.NANDFLASH_INFO_PTR->PHY_PAGE_SIZE; } exit: if (nandflash_ptr->CORE_NANDFLASH.WRITE_PROTECT) { (*nandflash_ptr->CORE_NANDFLASH.WRITE_PROTECT)(&nandflash_ptr->CORE_NANDFLASH, TRUE); }/* Endif */ nfc_ptr->CFG = cfg_bck; return(result); } /* Endbody */
uint_32 nfc_read_phy_page_raw ( /* [IN] the NAND flash information */ IO_NANDFLASH_WL_STRUCT_PTR nandflash_ptr, /* [OUT} where to copy data to */ uchar_ptr to_ptr, /* [IN] the page to read */ uint_32 phy_page_number, /* [IN] the amount of pages to read */ uint_32 page_count ) { /* Body */ uint_32 result = NANDFLASHERR_TIMEOUT; uint_32 count1, count2, count3; uint_32 output_offset = 0; uint_32 row, col; uint_32 num_ecc_bytes; uint_32 count, cfg_bck; NFC_MemMapPtr nfc_ptr; /* Get the pointer to nfc registers structure */ nfc_ptr = (NFC_MemMapPtr)_bsp_get_nfc_address(); /* Set the ECCMODE to 0 - ECC bypass */ cfg_bck = nfc_ptr->CFG; nfc_ptr->CFG &= ~(NFC_CFG_ECCMODE(7)); /* Do not write ECC Status to SRAM */ nfc_ptr->CFG &= ~(NFC_CFG_ECCSRAM_MASK); /* Reset the swap register */ nfc_ptr->SWAP = NFC_SWAP_ADDR1(0x7FF) | NFC_SWAP_ADDR2(0x7FF); for (count1 = phy_page_number; count1 < (phy_page_number + page_count); count1++) { num_ecc_bytes = NANDFLASH_ECC_SIZE_TO_NUM_BYTES_CONV(nandflash_ptr->CORE_NANDFLASH.ECC_SIZE); row = count1; /* Read from begin of physical page */ col = 0; /* Is the bad block byte(s) about to be re-written? */ nfc_ptr->CMD1 = NFC_CMD1_BYTE2(NANDFLASH_CMD_PAGE_READ_CYCLE2); nfc_ptr->CMD2 = NFC_CMD2_BYTE1(NANDFLASH_CMD_PAGE_READ_CYCLE1) | NFC_CMD2_CODE(0x7EE0) | NFC_CMD2_BUFNO(1); nfc_ptr->CAR = col & 0xFFFF; nfc_ptr->RAR = NFC_RAR_CS0_MASK | NFC_RAR_RB0_MASK | (row & 0xFFFFFF); nfc_ptr->SECSZ = nandflash_ptr->CORE_NANDFLASH.NANDFLASH_INFO_PTR->PHY_PAGE_SIZE + nandflash_ptr->CORE_NANDFLASH.NANDFLASH_INFO_PTR->SPARE_AREA_SIZE ; nfc_ptr->ISR |= (NFC_ISR_DONECLR_MASK | NFC_ISR_DONEEN_MASK | NFC_ISR_IDLECLR_MASK | NFC_ISR_IDLEEN_MASK); /* Start command execution */ nfc_ptr->CMD2 |= NFC_CMD2_BUSY_START_MASK; for (count2 = 0; count2 <= MAX_WAIT_COMMAND; count2++) { if (nfc_ptr->ISR & NFC_ISR_IDLE_MASK) { for(count3 = 0; count3 < (nandflash_ptr->CORE_NANDFLASH.NANDFLASH_INFO_PTR->PHY_PAGE_SIZE + nandflash_ptr->CORE_NANDFLASH.NANDFLASH_INFO_PTR->SPARE_AREA_SIZE); count3++) { *(to_ptr + output_offset) = NFC_SRAM_B1_REG(nfc_ptr, count3); output_offset++; } result = NANDFLASHERR_NO_ERROR; break; /* break for (count2 = 0;... */ } /* if nfc_ptr->ISR & NFC_ISR_IDLE */ } } /* for (count1 = phy_page_number */ nfc_ptr->CFG = cfg_bck; return(result); } /* Endbody */
uint_32 nfc_write_page_with_metadata ( /* [IN] the NAND flash information */ IO_NANDFLASH_WL_STRUCT_PTR nandflash_ptr, /* [IN] where to copy data from */ uchar_ptr data_from_ptr, /* [IN] where to copy metadata from */ uchar_ptr metadata_from_ptr, /* [IN] the first page to write */ uint_32 page_number, /* [IN] the amount of pages to write */ uint_32 page_count ) { /* Body */ uint_32 result = NANDFLASHERR_TIMEOUT; uint_32 count1, count2; uint_32 row, col, num_ecc_bytes, num_metadata_bytes; boolean swap = FALSE; uint_32 output_offset = 0; uint_32 output_metadata_offset = 0; uint_32 real_virt_page_offset; NFC_MemMapPtr nfc_ptr; if (nandflash_ptr->CORE_NANDFLASH.WRITE_PROTECT) { (*nandflash_ptr->CORE_NANDFLASH.WRITE_PROTECT)(&nandflash_ptr->CORE_NANDFLASH, FALSE); } /* Endif */ num_ecc_bytes = NANDFLASH_ECC_SIZE_TO_NUM_BYTES_CONV(nandflash_ptr->CORE_NANDFLASH.ECC_SIZE); num_metadata_bytes = nandflash_ptr->CORE_NANDFLASH.NANDFLASH_INFO_PTR->SPARE_AREA_SIZE/nandflash_ptr->CORE_NANDFLASH.PHY_PAGE_SIZE_TO_VIRTUAL_PAGE_SIZE_RATIO - num_ecc_bytes; /* Get the pointer to nfc registers structure */ nfc_ptr = (NFC_MemMapPtr)_bsp_get_nfc_address(); for (count1 = page_number; count1 < (page_number + page_count); count1++) { /* Calculate physical page address */ row = count1/nandflash_ptr->CORE_NANDFLASH.PHY_PAGE_SIZE_TO_VIRTUAL_PAGE_SIZE_RATIO; real_virt_page_offset = nandflash_ptr->CORE_NANDFLASH.PHY_PAGE_SIZE_TO_VIRTUAL_PAGE_SIZE_RATIO - 1 - (count1 - (row * nandflash_ptr->CORE_NANDFLASH.PHY_PAGE_SIZE_TO_VIRTUAL_PAGE_SIZE_RATIO)); /* Calculate byte offset in this physical page */ /* For preserve bad marking block address, we writes all pages in reserved order. * Virtual page 0 <-> write physically in Virtual page 3 * Virtual page 1 <-> write physically in Virtual page 2 */ col = real_virt_page_offset *(nandflash_ptr->CORE_NANDFLASH.VIRTUAL_PAGE_SIZE + num_metadata_bytes + num_ecc_bytes); /* If the last virtual page of the first or the second physical page is about to be written the swapping needs to be switched on due to the bad block marking */ count2 = count1 % ((nandflash_ptr->CORE_NANDFLASH.NANDFLASH_INFO_PTR->BLOCK_SIZE / nandflash_ptr->CORE_NANDFLASH.NANDFLASH_INFO_PTR->PHY_PAGE_SIZE) * nandflash_ptr->CORE_NANDFLASH.PHY_PAGE_SIZE_TO_VIRTUAL_PAGE_SIZE_RATIO); swap = ((count2 == (0)) || (count2 == (nandflash_ptr->CORE_NANDFLASH.PHY_PAGE_SIZE_TO_VIRTUAL_PAGE_SIZE_RATIO))); if(swap) { nfc_ptr->SWAP = NFC_SWAP_ADDR1(nfc_swap_addr1_with_metadata) | NFC_SWAP_ADDR2(nfc_swap_addr2); } else { nfc_ptr->SWAP = NFC_SWAP_ADDR1(0x7FF) | NFC_SWAP_ADDR2(0x7FF); } if(nandflash_ptr->CORE_NANDFLASH.NANDFLASH_INFO_PTR->WIDTH == 16) col = col/2; /* Copy one virtual page data into the SRAM buffer #0 */ for ( count2 = 0; count2 < (nandflash_ptr->CORE_NANDFLASH.VIRTUAL_PAGE_SIZE); count2++ ) { NFC_SRAM_B0_REG(nfc_ptr, count2) = *(data_from_ptr + output_offset); output_offset++; } NFC_LOG("nfc_write_page_with_metadata: copy %d from page DATA to SRAM \n", count2); /* Copy one virtual page metadata into the SRAM buffer #0 */ for ( count2 = nandflash_ptr->CORE_NANDFLASH.VIRTUAL_PAGE_SIZE; count2 < (nandflash_ptr->CORE_NANDFLASH.VIRTUAL_PAGE_SIZE + num_metadata_bytes); count2++) { NFC_SRAM_B0_REG(nfc_ptr, count2) = *(metadata_from_ptr + output_metadata_offset); output_metadata_offset++; } NFC_LOG("nfc_write_page_with_metadata: copy %d from page METADATA to SRAM \n", count2 - nandflash_ptr->CORE_NANDFLASH.VIRTUAL_PAGE_SIZE); nfc_ptr->CMD1 = NFC_CMD1_BYTE2(NANDFLASH_CMD_PAGE_PROGRAM_CYCLE2) | NFC_CMD1_BYTE3(NANDFLASH_CMD_READ_STATUS); nfc_ptr->CMD2 = NFC_CMD2_BYTE1(NANDFLASH_CMD_PAGE_PROGRAM_CYCLE1) | NFC_CMD2_CODE(0x7FD8) | NFC_CMD2_BUFNO(0); nfc_ptr->CAR = col & 0xFFFF; nfc_ptr->RAR = NFC_RAR_CS0_MASK | NFC_RAR_RB0_MASK | (row & 0xFFFFFF); nfc_ptr->SECSZ = (nandflash_ptr->CORE_NANDFLASH.VIRTUAL_PAGE_SIZE)+ num_metadata_bytes + num_ecc_bytes; /* For 16-bit data width flash devices, only odd SIZE is supported */ if((nandflash_ptr->CORE_NANDFLASH.NANDFLASH_INFO_PTR->WIDTH == 16) && !(nfc_ptr->SECSZ % 2)) nfc_ptr->SECSZ += 1; NFC_LOG("nfc_write_page_with_metadata: issue a WRITE cmd w/ SECTZ=%d at COL*2=%d page %d\n", nfc_ptr->SECSZ, col*2, count1); nfc_ptr->ISR |= (NFC_ISR_DONECLR_MASK | NFC_ISR_DONEEN_MASK | NFC_ISR_IDLECLR_MASK | NFC_ISR_IDLEEN_MASK); /* Start command execution */ nfc_ptr->CMD2 |= NFC_CMD2_BUSY_START_MASK; for (count2 = 0; count2 <= MAX_WAIT_COMMAND; count2++) { if (nfc_ptr->ISR & NFC_ISR_IDLE_MASK) { if (nfc_ptr->SR2 & NANDFLASH_STATUS_ERR) { result = NANDFLASHERR_WRITE_FAILED; goto exit; } else { result = NANDFLASHERR_NO_ERROR; } break; } } } exit: if (nandflash_ptr->CORE_NANDFLASH.WRITE_PROTECT) { (*nandflash_ptr->CORE_NANDFLASH.WRITE_PROTECT)(&nandflash_ptr->CORE_NANDFLASH, TRUE); }/* Endif */ nfc_dump_buff(data_from_ptr, output_offset, "Write Page Buffer"); nfc_dump_buff(metadata_from_ptr, output_metadata_offset, "Write Page Metadata Buffer"); return(result); } /* Endbody */
uint_32 nfc_read_page_metadata ( /* [IN] the NAND flash information */ IO_NANDFLASH_WL_STRUCT_PTR nandflash_ptr, /* [OUT} where to copy data to */ uchar_ptr to_ptr, /* [IN] the page to read */ uint_32 page_number, /* [IN] the amount of pages to read */ uint_32 page_count ) { /* Body */ uint_32 result = NANDFLASHERR_TIMEOUT; uint_32 count1, count2, count3; uint_32 output_offset = 0; boolean swap = FALSE; uint_32 row, col, num_ecc_bytes, real_virt_page_offset ; uint_32 num_metadata_bytes; uint_32 cfg_bck; NFC_MemMapPtr nfc_ptr; num_ecc_bytes = NANDFLASH_ECC_SIZE_TO_NUM_BYTES_CONV(nandflash_ptr->CORE_NANDFLASH.ECC_SIZE); num_metadata_bytes = nandflash_ptr->CORE_NANDFLASH.NANDFLASH_INFO_PTR->SPARE_AREA_SIZE/nandflash_ptr->CORE_NANDFLASH.PHY_PAGE_SIZE_TO_VIRTUAL_PAGE_SIZE_RATIO - num_ecc_bytes; /* Get the pointer to nfc registers structure */ nfc_ptr = (NFC_MemMapPtr)_bsp_get_nfc_address(); /* Set the ECCMODE to 0 - ECC bypass */ cfg_bck = nfc_ptr->CFG; nfc_ptr->CFG &= ~(NFC_CFG_ECCMODE(7)); /* Do not write ECC Status to SRAM */ nfc_ptr->CFG &= ~(NFC_CFG_ECCSRAM_MASK); /* Reset the swap register */ nfc_ptr->SWAP = NFC_SWAP_ADDR1(0x7FF) | NFC_SWAP_ADDR2(0x7FF); for (count1 = page_number; count1 < (page_number + page_count); count1++) { row = count1/nandflash_ptr->CORE_NANDFLASH.PHY_PAGE_SIZE_TO_VIRTUAL_PAGE_SIZE_RATIO; real_virt_page_offset = nandflash_ptr->CORE_NANDFLASH.PHY_PAGE_SIZE_TO_VIRTUAL_PAGE_SIZE_RATIO - 1 - (count1 - (row * nandflash_ptr->CORE_NANDFLASH.PHY_PAGE_SIZE_TO_VIRTUAL_PAGE_SIZE_RATIO)); /* Calculate byte offset in this physical page */ /* For preserve bad marking block address, we writes all pages in reserved order. * Virtual page 0 <-> write physically in Virtual page 3 * Virtual page 1 <-> write physically in Virtual page 2 */ col = real_virt_page_offset *(nandflash_ptr->CORE_NANDFLASH.VIRTUAL_PAGE_SIZE + num_metadata_bytes + num_ecc_bytes);row = count1/nandflash_ptr->CORE_NANDFLASH.PHY_PAGE_SIZE_TO_VIRTUAL_PAGE_SIZE_RATIO; real_virt_page_offset = nandflash_ptr->CORE_NANDFLASH.PHY_PAGE_SIZE_TO_VIRTUAL_PAGE_SIZE_RATIO - 1 - (count1 - (row * nandflash_ptr->CORE_NANDFLASH.PHY_PAGE_SIZE_TO_VIRTUAL_PAGE_SIZE_RATIO)); /* Calculate byte offset in this physical page */ /* For preserve bad marking block address, we writes all pages in reserved order. * Virtual page 0 <-> write physically in Virtual page 3 * Virtual page 1 <-> write physically in Virtual page 2 */ col = real_virt_page_offset *(nandflash_ptr->CORE_NANDFLASH.VIRTUAL_PAGE_SIZE + num_metadata_bytes + num_ecc_bytes); col += nandflash_ptr->CORE_NANDFLASH.VIRTUAL_PAGE_SIZE; /* Is the bad block byte(s) about to be re-written? */ count2 = count1 % ((nandflash_ptr->CORE_NANDFLASH.NANDFLASH_INFO_PTR->BLOCK_SIZE / nandflash_ptr->CORE_NANDFLASH.NANDFLASH_INFO_PTR->PHY_PAGE_SIZE) * nandflash_ptr->CORE_NANDFLASH.PHY_PAGE_SIZE_TO_VIRTUAL_PAGE_SIZE_RATIO); swap = ((count2 == (0)) || (count2 == (nandflash_ptr->CORE_NANDFLASH.PHY_PAGE_SIZE_TO_VIRTUAL_PAGE_SIZE_RATIO))); /* If the last virtual page of the first or the second physical page is about to be read the virtual page needs to be enlarged by 8 bytes and swapping switched on due to the bad block marking */ if(swap) { /* Here we are read MD from page MD swapped * * -> we need to calculate to real MD of this * * swapped page */ col -= ( nfc_swap_addr2 - nfc_swap_addr1_with_metadata ) * 8; } if(nandflash_ptr->CORE_NANDFLASH.NANDFLASH_INFO_PTR->WIDTH == 16) col = col/2; nfc_ptr->CMD1 = NFC_CMD1_BYTE2(NANDFLASH_CMD_PAGE_READ_CYCLE2); nfc_ptr->CMD2 = NFC_CMD2_BYTE1(NANDFLASH_CMD_PAGE_READ_CYCLE1) | NFC_CMD2_CODE(0x7EE0) | NFC_CMD2_BUFNO(1); nfc_ptr->CAR = col & 0xFFFF; nfc_ptr->RAR = NFC_RAR_CS0_MASK | NFC_RAR_RB0_MASK | (row & 0xFFFFFF); /* Calculate metadata size for each page (exclude ECC size), * since SPARE_ARE_SIZE is total spare size for each Physical page */ nfc_ptr->SECSZ = num_metadata_bytes +num_ecc_bytes; /* For 16-bit data width flash devices, only odd SIZE is supported */ if((nandflash_ptr->CORE_NANDFLASH.NANDFLASH_INFO_PTR->WIDTH == 16) && !(nfc_ptr->SECSZ % 2)) nfc_ptr->SECSZ += 1; nfc_ptr->ISR |= (NFC_ISR_DONECLR_MASK | NFC_ISR_DONEEN_MASK | NFC_ISR_IDLECLR_MASK | NFC_ISR_IDLEEN_MASK); NFC_LOG("nfc_read_page_metadata: issue a READ cmd w/ col =%d page %d\n", col, count1); /* Start command execution */ nfc_ptr->CMD2 |= NFC_CMD2_BUSY_START_MASK; for (count2 = 0; count2 <= MAX_WAIT_COMMAND; count2++) { if (nfc_ptr->ISR & NFC_ISR_IDLE_MASK) { for(count3 = 0; count3 < (num_metadata_bytes); count3++) { *(to_ptr + output_offset) = NFC_SRAM_B1_REG(nfc_ptr, count3); output_offset++; } result = NANDFLASHERR_NO_ERROR; break; } } } nfc_ptr->CFG = cfg_bck; return(result); } /* Endbody */
uint_32 nfc_read_page_with_metadata ( /* [IN] the NAND flash information */ IO_NANDFLASH_WL_STRUCT_PTR nandflash_ptr, /* [OUT] where to copy data to */ uchar_ptr to_data_ptr, /* [OUT] where to copy metadata to */ uchar_ptr to_metadata_ptr, /* [IN] the page to read */ uint_32 page_number, /* [IN] the amount of pages to read */ uint_32 page_count ) { /* Body */ uint_32 result = NANDFLASHERR_TIMEOUT; uint_32 count1, count2, count3, real_virt_page_offset; uint_32 data_output_offset = 0, metadata_output_offset = 0; boolean ecc_corrected = FALSE, swap = FALSE; uint_32 row, col, num_ecc_bytes, num_metadata_bytes; uint_32 cfg_bck; NFC_MemMapPtr nfc_ptr; uint_8 ecc_num_bit_correct; num_ecc_bytes = NANDFLASH_ECC_SIZE_TO_NUM_BYTES_CONV(nandflash_ptr->CORE_NANDFLASH.ECC_SIZE); num_metadata_bytes = nandflash_ptr->CORE_NANDFLASH.NANDFLASH_INFO_PTR->SPARE_AREA_SIZE/nandflash_ptr->CORE_NANDFLASH.PHY_PAGE_SIZE_TO_VIRTUAL_PAGE_SIZE_RATIO - num_ecc_bytes; /* Get the pointer to nfc registers structure */ nfc_ptr = (NFC_MemMapPtr)_bsp_get_nfc_address(); /* back up current nfc_ptr then change the ECC status position in output read buffer */ cfg_bck = nfc_ptr->CFG; nfc_ptr->CFG = (nfc_ptr->CFG & (~NFC_CFG_ECCAD(0xFFFF))) | NFC_CFG_ECCAD(( (nandflash_ptr->CORE_NANDFLASH.VIRTUAL_PAGE_SIZE +num_metadata_bytes) / 8) + 1); for (count1 = page_number; count1 < (page_number + page_count); count1++) { /* Calculate physical page address */ row = count1/nandflash_ptr->CORE_NANDFLASH.PHY_PAGE_SIZE_TO_VIRTUAL_PAGE_SIZE_RATIO; real_virt_page_offset = nandflash_ptr->CORE_NANDFLASH.PHY_PAGE_SIZE_TO_VIRTUAL_PAGE_SIZE_RATIO - 1 - (count1 - (row * nandflash_ptr->CORE_NANDFLASH.PHY_PAGE_SIZE_TO_VIRTUAL_PAGE_SIZE_RATIO)); /* Calculate byte offset in this physical page */ /* For preserve bad marking block address, we writes all pages in reserved order. * Virtual page 0 <-> write physically in Virtual page 3 * Virtual page 1 <-> write physically in Virtual page 2 */ col = real_virt_page_offset *(nandflash_ptr->CORE_NANDFLASH.VIRTUAL_PAGE_SIZE + num_metadata_bytes + num_ecc_bytes); /* If the last virtual page of the first or the second physical page is about to be written the swapping needs to be switched on due to the bad block marking */ count2 = count1 % ((nandflash_ptr->CORE_NANDFLASH.NANDFLASH_INFO_PTR->BLOCK_SIZE / nandflash_ptr->CORE_NANDFLASH.NANDFLASH_INFO_PTR->PHY_PAGE_SIZE) * nandflash_ptr->CORE_NANDFLASH.PHY_PAGE_SIZE_TO_VIRTUAL_PAGE_SIZE_RATIO); swap = ((count2 == (0)) || (count2 == (nandflash_ptr->CORE_NANDFLASH.PHY_PAGE_SIZE_TO_VIRTUAL_PAGE_SIZE_RATIO))); if(nandflash_ptr->CORE_NANDFLASH.NANDFLASH_INFO_PTR->WIDTH == 16) col = col/2; nfc_ptr->CMD1 = NFC_CMD1_BYTE2(NANDFLASH_CMD_PAGE_READ_CYCLE2); nfc_ptr->CMD2 = NFC_CMD2_BYTE1(NANDFLASH_CMD_PAGE_READ_CYCLE1) | NFC_CMD2_CODE(0x7EE0) | NFC_CMD2_BUFNO(1); nfc_ptr->CAR = col & 0xFFFF; nfc_ptr->RAR = NFC_RAR_CS0_MASK | NFC_RAR_RB0_MASK | (row & 0xFFFFFF); nfc_ptr->SECSZ = (nandflash_ptr->CORE_NANDFLASH.VIRTUAL_PAGE_SIZE)+ num_metadata_bytes +num_ecc_bytes ; /* For 16-bit data width flash devices, only odd SIZE is supported */ if((nandflash_ptr->CORE_NANDFLASH.NANDFLASH_INFO_PTR->WIDTH == 16) && !(nfc_ptr->SECSZ % 2)) nfc_ptr->SECSZ += 1; /* If the last virtual page of the first or the second physical page is about to be read the virtual page needs to be enlarged by 8 bytes and swapping switched on due to the bad block marking */ if(swap) { nfc_ptr->SWAP = NFC_SWAP_ADDR1(nfc_swap_addr1_with_metadata) | NFC_SWAP_ADDR2(nfc_swap_addr2); } else { nfc_ptr->SWAP = NFC_SWAP_ADDR1(0x7FF) | NFC_SWAP_ADDR2(0x7FF); } NFC_LOG("nfc_read_page_with_metadata: issue a READ cmd w/ SECTZ=%d at COL*2=%d, page=%d\n", nfc_ptr->SECSZ, col*2, count1); nfc_ptr->ISR |= (NFC_ISR_DONECLR_MASK | NFC_ISR_DONEEN_MASK | NFC_ISR_IDLECLR_MASK | NFC_ISR_IDLEEN_MASK); /* Start command execution */ nfc_ptr->CMD2 |= NFC_CMD2_BUSY_START_MASK; for (count2 = 0; count2 <= MAX_WAIT_COMMAND; count2++) { if (nfc_ptr->ISR & NFC_ISR_IDLE_MASK) { if ( nandflash_ptr->CORE_NANDFLASH.ECC_SIZE == 0) { if (nfc_ptr->SR2 & NANDFLASH_STATUS_ERR) { result = NANDFLASHERR_ECC_FAILED; break; /* break to out of for MAX_WAIT_COMMAND*/ } } else /* if nandflash_ptr->ECC_SIZE == 0)*/ { if((*(uint_32*)&NFC_SRAM_B1_REG(nfc_ptr, nandflash_ptr->CORE_NANDFLASH.VIRTUAL_PAGE_SIZE + num_metadata_bytes + (num_ecc_bytes + 4))) & NFC_ECC_STATUS_CORFAIL) { /* ECC Fix FAILED */ result = NANDFLASHERR_ECC_FAILED; break; } else { if((*(uint_32*)&NFC_SRAM_B1_REG(nfc_ptr, nandflash_ptr->CORE_NANDFLASH.VIRTUAL_PAGE_SIZE + num_metadata_bytes + (num_ecc_bytes + 4))) & NFC_ECC_STATUS_CORFAIL) { ecc_corrected = TRUE; ecc_num_bit_correct = (*(uint_32*)&NFC_SRAM_B1_REG(nfc_ptr, nandflash_ptr->CORE_NANDFLASH.VIRTUAL_PAGE_SIZE + num_metadata_bytes + (num_ecc_bytes + 4))) & NFC_ECC_STATUS_ERROR_COUNT; result = NANDFLASHERR_ECC_CORRECTED; } else /* ECC is success, we donot need to correct any bits */ { result = NANDFLASHERR_NO_ERROR; } } } /* if nfc_ptr->ISR & NFC_ISR_IDLE*/ /* In case we catch ECC_CORRECTED or NO_ERROR, we still copy data from SRAM -> requested buffer */ /* Copy Page DATA from SRAM buffer to to_data_ptr */ for(count3 = 0; count3 < (nandflash_ptr->CORE_NANDFLASH.VIRTUAL_PAGE_SIZE); count3++) { *(to_data_ptr + data_output_offset) = NFC_SRAM_B1_REG(nfc_ptr, count3); data_output_offset++; } NFC_LOG("nfc_read_page_with_metadata: copy %d from page DATA to SRAM \n", count3); /* Copy Page METADATA from SRAM buffer to to_data_ptr */ for(count3 = nandflash_ptr->CORE_NANDFLASH.VIRTUAL_PAGE_SIZE; count3 < (nandflash_ptr->CORE_NANDFLASH.VIRTUAL_PAGE_SIZE + num_metadata_bytes); count3++) { *(to_metadata_ptr + metadata_output_offset) = NFC_SRAM_B1_REG(nfc_ptr, count3); metadata_output_offset++; } NFC_LOG("nfc_read_page_with_metadata: copy %d from page METADATA to SRAM \n", count3-nandflash_ptr->CORE_NANDFLASH.VIRTUAL_PAGE_SIZE); break; } /* if nfc_ptr->ISR & IDLE */ } /* for MAX_WAIT_COMMAND */ /* Everytime we catch error even ECC_CORRECTED, just quit */ if (NANDFLASHERR_NO_ERROR != result ) { break; /* break out of for count1=page_number */ } } if (ecc_corrected) { if (ecc_num_bit_correct >= _ecc_mode_threshold[curr_ecc_mode]) result = NANDFLASHERR_ECC_CORRECTED_EXCEED_THRESHOLD; else result = NANDFLASHERR_ECC_CORRECTED; } nfc_dump_buff(to_data_ptr, data_output_offset, "Read Page Buffer"); nfc_dump_buff(to_metadata_ptr, metadata_output_offset, "Read Page Metadata Buffer"); /* Restore nfc config */ nfc_ptr->CFG = cfg_bck ; return(result); } /* Endbody */
uint32_t nfc_init ( /* [IN] the NAND flash information */ IO_NANDFLASH_STRUCT_PTR nandflash_ptr ) { /* Body */ uint32_t result = NANDFLASHERR_NO_ERROR; NFC_MemMapPtr nfc_ptr; uint32_t nand_id, block_size_kB, density, num_ecc_bytes; NANDFLASH_INFO_STRUCT_PTR nand_info_ptr; /* Initialize NFC I/O Pins */ nfc_io_init(); /* Get the pointer to nfc registers structure */ nfc_ptr = _bsp_get_nfc_address(); /* Create NANDFLASH_INFO_STRUCT based on NAND ID read from the NAND Flash, if not defined before manually */ if((nandflash_ptr->NANDFLASH_INFO_PTR) == NULL) { nand_info_ptr = (NANDFLASH_INFO_STRUCT_PTR)_mem_alloc_system_zero( (_mem_size)sizeof(NANDFLASH_INFO_STRUCT)); #if MQX_CHECK_MEMORY_ALLOCATION_ERRORS if(nand_info_ptr == NULL) { return((uint32_t)MQX_OUT_OF_MEMORY); } /* Endif */ #endif if (((*nandflash_ptr->IOCTL)(nandflash_ptr,NANDFLASH_IOCTL_GET_ID,&nand_id)) == NANDFLASHERR_NO_ERROR) { nand_info_ptr->PHY_PAGE_SIZE = (_mem_size)(((nand_id & NANDFLASH_ID_PAGE_SIZE_MASK) + 1)*1024); if((nand_id & NANDFLASH_ID_SPARE_BYTES_NUM_MASK)>>2 == 1) { nand_info_ptr->SPARE_AREA_SIZE = (_mem_size)64; } if(nand_id & NANDFLASH_ID_BLOCK_SIZE_MASK) { nand_info_ptr->BLOCK_SIZE = (_mem_size)((nand_id & NANDFLASH_ID_BLOCK_SIZE_MASK)*8192); } else { nand_info_ptr->BLOCK_SIZE = 65536; } block_size_kB = (nand_info_ptr->BLOCK_SIZE)/1024; density = (nand_id & NANDFLASH_ID_DENSITY_MASK)>>16; switch(density) { case NANDFLASH_DENSITY_1Gb: /* nand_info_ptr->NUM_BLOCKS = 1024/8*1024/block_size_kB; */ nand_info_ptr->NUM_BLOCKS = 131072/block_size_kB; break; case NANDFLASH_DENSITY_2Gb: nand_info_ptr->NUM_BLOCKS = 2*131072/block_size_kB; break; case NANDFLASH_DENSITY_4Gb: nand_info_ptr->NUM_BLOCKS = 4*131072/block_size_kB; break; case NANDFLASH_DENSITY_8Gb: nand_info_ptr->NUM_BLOCKS = 8*131072/block_size_kB; break; case NANDFLASH_DENSITY_16Gb: nand_info_ptr->NUM_BLOCKS = 16*131072/block_size_kB; break; default: break; } nand_info_ptr->WIDTH = (_mqx_uint)(8 + ((nand_id & NANDFLASH_ID_WIDTH_MASK)>>3)); nandflash_ptr->NANDFLASH_INFO_PTR = nand_info_ptr; nandflash_ptr->NUM_VIRTUAL_PAGES = ((nand_info_ptr->BLOCK_SIZE)/(nandflash_ptr->VIRTUAL_PAGE_SIZE))*(nand_info_ptr->NUM_BLOCKS); nandflash_ptr->PHY_PAGE_SIZE_TO_VIRTUAL_PAGE_SIZE_RATIO = (nand_info_ptr->PHY_PAGE_SIZE)/(nandflash_ptr->VIRTUAL_PAGE_SIZE); }