Пример #1
0
/* Reads a single page worth of data from the NAND flash at the 
 * specified address into the NFC's buffers. This function will only
 * read one NAND page at a time. If multiple pages need to be
 * read, then the function should be called once per page to
 * read. Data will be loaded into the NFC's buffers after the function
 * completes.
 *
 * Parameters:
 *  flash_bufno first NFC internal buffer to load data to (auto increment will be used )
 *  row_addr    NAND flash row addr for the block to program (up to 24 bits)
 *  col_addr    NAND flash col addr for the page to program (up to 16 bits)
 *
 * NOTE: the column address should be aligned to the NAND page size
 */
void nfc_page_read(uint8 flash_bufno, uint32 row_addr, uint16 col_addr)
{
    /* Clear all status and error bits in the NFC_ISR register */
    NFC_ISR |= ( NFC_ISR_WERRCLR_MASK
                | NFC_ISR_DONECLR_MASK
                | NFC_ISR_IDLECLR_MASK );
    
    /* Make sure ECC is enabled before reading */
    NFC_CFG |= NFC_CFG_ECCMODE(0x7);
        
    /* Set the chip select to use */
    if(NFC_CE == NFC_CE0)
    {
        NFC_RAR = (NFC_RAR_CS0_MASK | NFC_RAR_RB0_MASK);
     }
    else /* (NFC_CE == NFC_CE1) */
    {
        NFC_RAR = (NFC_RAR_CS1_MASK | NFC_RAR_RB1_MASK);
    }	

    /* Set the row address */
    NFC_RAR |= row_addr;      
    
    /* Set the column address */
    NFC_CAR = col_addr;
    
    /* Write the NFC_CMD2 register with the command byte and code for an erase */
    NFC_CMD2 = (NFC_CMD2_BYTE1(PAGE_READ_CMD_BYTE1) 
              | NFC_CMD2_CODE(NFC_READ_PAGE_CMD_CODE) 
              | NFC_CMD2_BUFNO(flash_bufno)                );
    
    /* Write the NFC_CMD1 register with the command byte2 and byte3 for an erase */
    NFC_CMD1 = NFC_CMD1_BYTE2(PAGE_READ_CMD_BYTE2) 
                | NFC_CMD1_BYTE3(READ_STATUS_CMD_BYTE);    

    /* Set Start Bit to send command to the NAND flash */
    NFC_CMD2 |= NFC_CMD2_BUSY_START_MASK;

    /* Wait for start/busy bit to clear indicating command is done */ 
    while (NFC_CMD2 & NFC_CMD2_BUSY_START_MASK);  
}
Пример #2
0
/* Erases the NFC block containing the specified address. This function
 * will only erase one block at a time. If multiple blocks need to be
 * erased, then the function should be called once per block to erase.
 *
 * Parameters:
 *  row_addr   NAND flash row addr for the block to erase (up to 24 bits)
 */
void nfc_block_erase(uint32 row_addr)
{
    /* Clear all status and error bits in the NFC_ISR register */
    NFC_ISR |= ( NFC_ISR_WERRCLR_MASK
                | NFC_ISR_DONECLR_MASK
                | NFC_ISR_IDLECLR_MASK );
    
    /* Disable ECC during block erase */
    NFC_CFG &= ~NFC_CFG_ECCMODE(0x7);
    
    /* Make sure the column address is cleared - not needed for block erase */
    NFC_CAR = 0x0;
	
    /* Set the chip select to use */
    if(NFC_CE == NFC_CE0)
    {
        NFC_RAR = (NFC_RAR_CS0_MASK | NFC_RAR_RB0_MASK);
     }
    else /* (NFC_CE == NFC_CE1) */
    {
        NFC_RAR = (NFC_RAR_CS1_MASK | NFC_RAR_RB1_MASK);
    }	

    /* Set the row address */
    NFC_RAR |= row_addr;      

    /* Write the NFC_CMD2 register with the command byte and code for an erase */
    NFC_CMD2 = (NFC_CMD2_BYTE1(BLOCK_ERASE_CMD_BYTE1) 
              | NFC_CMD2_CODE(NFC_BLOCK_ERASE_CMD_CODE) );
    
    /* Write the NFC_CMD1 register with the command byte2 and byte3 for an erase */
    NFC_CMD1 = NFC_CMD1_BYTE2(BLOCK_ERASE_CMD_BYTE2) 
                | NFC_CMD1_BYTE3(READ_STATUS_CMD_BYTE);    
	
    /* Set Start Bit to send command to the NAND flash */
    NFC_CMD2 |= NFC_CMD2_BUSY_START_MASK;

    /* Wait for start/busy bit to clear indicating command is done */ 
    while (NFC_CMD2 & NFC_CMD2_BUSY_START_MASK);  
}
Пример #3
0
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 */
Пример #4
0
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 */
Пример #5
0
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 */
Пример #6
0
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 */
Пример #7
0
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 */