📄 nfc_base.c
字号:
/*****************************************************************************
** nfc_base.c
**
** Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
**
** This file contains copyrighted material. Use of this file is
** restricted by the provisions of a Freescale Software License
** Agreement, which has either been electronically accepted by
** you or has been expressly executed between the parties.
**
** Description: Explanation for the usage of this file.
**
** Revision History:
** -----------------
*****************************************************************************/
#include "nand_flash.h"
#include "flash_lib.h"
#include "protocol.h"
#include "nfc_base.h"
#if defined(MCU_MX51)
#include "mx51_nfc.h"
#elif defined(MCU_MX35)
#include "mx35_nfc.h"
#elif defined(MCU_MX37)
#include "mx37_nfc.h"
#elif defined(MCU_MX31) || defined(MCU_MX32)
#include "mx3_nfc.h"
#elif defined(MCU_MX27)
#include "mx27_nfc.h"
#endif
#define NAND_MAN_ID (nand->man_id)
#define NAND_DEV_ID (nand->dev_id)
#define NAND_NUM_OF_ROW_ADDR_CYCLES (nand->row_addr_cycle)
#define NAND_NUM_OF_BLOCKS (nand->blk_count)
#define NAND_NUM_OF_PAGES (nand->ppb)
#define NAND_IO_WIDTH (nand->bus_width)
#define NAND_MAIN_BYTESIZE (nand->page_size)
#define NAND_SPARE_BYTESIZE (nand->oob_size)
#define NAND_BADBLOCK_MARKER_OFFSET (nand->bbm_offset)
#define NAND_BLK_SIZE (NAND_NUM_OF_PAGES * NAND_MAIN_BYTESIZE)
#define NAND_SIZE (u64)(NAND_NUM_OF_BLOCKS * NAND_BLK_SIZE)
#define NAND_BBI_PAGE_OFFSET (nand->bbi_page_offset)
#define NAND_SCAN_PG_NUM (nand->scan_pg_num)
/* extern global nand device
* handle,defined in the
* nand_flash.c file
*/
extern nand_t* nand;
/* indication for bi swap enable
* or not, define in the main.c
* host will send command to
* set this flag
*/
extern BI_SWAP_FLAG flag_bi_swap;
/*!
* Function to do base nfc basic init
* @param none
*/
void nfc_base_init(void)
{
nfc_init();
/* FIXME,some nand
* flash need reset first
*/
nfc_command_input(NAND_CMD_RESET);
}
/*!
* Function to read id
* @param [out] tmp
*/
void nfc_send_read_id(u32* tmp)
{
send_read_id(tmp);
}
/*!
* Function to set fms
* @param [in] bus_width
* @param [in] page_size
* @param [in] oob_size
*/
void nfc_set_fms(u8 bus_width, u32 page_size,u16 oob_size)
{
set_fms(bus_width,page_size,oob_size);
}
/*
* This function does the trick of swapping the 464th byte in the last RAM
* buffer in the main area with the 0th byte in the spare area. This seems
* to be the optimal way of addressing the NFC imcompatibility problem with
* the NAND flash out of factory in terms of BI field.
* Note: this function only operates on the NFC's internal RAM buffers and
* for 2K page only.
*/
void nand_bi_main_sp(void)
{
u16 tmp1, tmp2, new_tmp1;
tmp1 = BAD_BLK_MARKER_MAIN;
tmp2 = BAD_BLK_MARKER_SP_0;
new_tmp1 = (tmp1 & 0xFF00) | (tmp2 >> 8);
tmp2 = (tmp1 << 8) | (tmp2 & 0xFF);
BAD_BLK_MARKER_MAIN = new_tmp1;
BAD_BLK_MARKER_SP_0 = tmp2;
}
/*!
* Function to copy memory content
* Parser the command, and then call the corresponding functions.
* @param [in] SourceAddress - source address
* @param [in] TargetAddress -Destination address
* @param [in] ByteSize -byte size
*/
void nfc_memcpy(u32 s, u32 d, u32 len)
{
u32 i;
for(i = 0; i < len; i += 2)
*(volatile u16 *)(d + i) = *(volatile u16 *)(s + i);
}
/*!
* Function to copy spare content
* @param [in] nd - nand structure
* @param [in] pbuf - data buf address
* @param [in] pspare - spare buf address
* @param [in] len - byte size
* @param [in] bfrom - direction
*/
void copy_spare(nand_t *nd, char *pbuf, char *pspare,int len, u8 bfrom)
{
u16 ooblen = nd->oob_size;
u8 i, count,size;
count = nd->page_size>>9;
size = (ooblen/count >>1)<<1;
if(!pspare)
pspare = (char*)NFC_SAB0_BASE;
if(bfrom){
for(i=0;i<count -1;i++){
/* source,dest,len */
nfc_memcpy((u32)(pspare + i *NFC_SAB_LEN),(u32)(pbuf + i*size), size);
}
nfc_memcpy((u32)(pspare + i *NFC_SAB_LEN),(u32)(pbuf + i*size), len - i *size);
}
else{
for(i=0;i<count -1;i++){
/* source,dest,len */
nfc_memcpy((u32)(pbuf+ i * size),(u32)(pspare + i *NFC_SAB_LEN) , size);
}
nfc_memcpy((u32)(pbuf+ i * size),(u32)(pspare + i *NFC_SAB_LEN), len - i *size);
}
}
/*!
* Function to check whether nand block is good
* @param [in] BlockNum - block number
*/
u8 nand_block_is_good(u32 block)
{
u16 flag;
u32 row;
u8 i,col_addr_cycle;
/* set row_addr_cycle */
col_addr_cycle = NAND_MAIN_BYTESIZE > 512 ? 2 : 1;
/* check first page */
row = (block*NAND_NUM_OF_PAGES);
/* get the offset page */
row += NAND_BBI_PAGE_OFFSET;
for(i=0;i<NAND_SCAN_PG_NUM;i++){
/* send read command */
nfc_command_input(NAND_CMD_READ);
/* address cycle, row & col */
nfc_address_cycle(0, col_addr_cycle);
row +=i;
nfc_address_cycle(row, NAND_NUM_OF_ROW_ADDR_CYCLES);
/* send page read command for large page */
if (NAND_MAIN_BYTESIZE > 512)
nfc_command_input(NAND_CMD_READ_CONFIRM);
/* trans data from nand flash to nfc buffer */
send_read_page();
/* check ecc status */
if(nfc_ecc_uncorrectable_error(NAND_MAIN_BYTESIZE))
return 0;
/* bi swap */
if((flag_bi_swap == BI_SWAP_ENABLE) &&
(NAND_MAIN_BYTESIZE > 512)) {
nand_bi_main_sp();
flag = BAD_BLK_MARKER_SP_0;
}
else {
flag = *(volatile u16 *)(NFC_SAB0_BASE + 4);
}
/* check bad or not */
if ((flag & 0xFF00) != 0xFF00) {
return 0;
}
}
return 1;
}
/*!
* Function to mark bad block
* @param [in] BlockNum - block number
*/
s16 nand_mark_bad_block(u32 block)
{
u8 i,j;
u32 row;
u8 col_addr_cycle = 0;
/* set row_addr_cycle */
col_addr_cycle = NAND_MAIN_BYTESIZE > 512 ? 2 : 1;
/* filled the memory with zero */
for(j=0;j<NFC_SAB_COUNT;j++){
for(i=0; i<NFC_SAB_LEN; i+=2){
*(volatile u16 *)(NFC_SAB0_BASE+i+j*NFC_SAB_LEN) = 0;
}
}
/* bi swap*/
if((flag_bi_swap == BI_SWAP_ENABLE) &&
(NAND_MAIN_BYTESIZE > 512))
nand_bi_main_sp();
/* send prog initial command */
nfc_command_input(NAND_CMD_PAGE_PROG);
/* address cycle */
nfc_address_cycle(0, col_addr_cycle);
row = (block * NAND_NUM_OF_PAGES);
row += NAND_BBI_PAGE_OFFSET;
nfc_address_cycle(row, NAND_NUM_OF_ROW_ADDR_CYCLES);
/* trans data from nfc to nand flash */
send_prog_page();
/* send prog confirm command */
nfc_command_input(NAND_CMD_PAGE_PROG_CONFIRM);
/* wait prog completely*/
while (!(nand_read_status() & NAND_STATUS_READY));
/* check prog status */
if (nand_read_status() & NAND_STATUS_PROG_ERROR)
return FLASH_ERROR_PROG;
return FLASH_ERROR_NO;
}
/*!
* Function to erase nand block
* @param [in] BlockNum - block number
*/
s16 nand_erase_block(u32 block)
{
u32 row;
/* send erase command */
nfc_command_input(NAND_CMD_ERASE);
/* addr cycle only row addr */
row = (block*NAND_NUM_OF_PAGES);
nfc_address_cycle(row, NAND_NUM_OF_ROW_ADDR_CYCLES);
/* send erase confirm command */
nfc_command_input(NAND_CMD_ERASE_CONFIRM);
/* check the status */
if( nand_read_status() & NAND_STATUS_PROG_ERROR )
return FLASH_ERROR_ERASE;
return FLASH_ERROR_NO;
}
/*!
* Function to read one page
* @param [in] BlockNum - block number
* @param [in] PageNum - page number
* @param [in] TargetAddress - destination address
* @param [in] ByteSize - byte size to be read
*/
s16 nand_read_page(u32 block, u32 page, u32 dest, u32 len,u32 offs)
{
u8 col_addr_cycle = 0;
/* set row_addr_cycle */
col_addr_cycle = NAND_MAIN_BYTESIZE > 512 ? 2 : 1;
/* send read command */
nfc_command_input(NAND_CMD_READ);
/* addr cycle: row & col */
nfc_address_cycle(0, col_addr_cycle);
nfc_address_cycle(block * NAND_NUM_OF_PAGES + page, NAND_NUM_OF_ROW_ADDR_CYCLES);
/* send read confirm command for large page */
if (NAND_MAIN_BYTESIZE > 512)
nfc_command_input(NAND_CMD_READ_CONFIRM);
/* trans data from nand to nfc buffer*/
send_read_page();
/* check ecc status */
if(nfc_ecc_uncorrectable_error(NAND_MAIN_BYTESIZE))
return FLASH_ERROR_ECC;
/* bi swap */
if((flag_bi_swap == BI_SWAP_ENABLE) &&
(NAND_MAIN_BYTESIZE > 512))
nand_bi_main_sp();
/* trans data from nfc buffer to data buffer*/
nfc_memcpy(NFC_MAB0_BASE + offs, dest, len);
return FLASH_ERROR_NO;
}
/*!
* Function to write one page
* @param [in] BlockNum - block number
* @param [in] PageNum page number
* @param [in] SourceAddress -source address
* @param [in]ByteSize -byte size to be written
*/
s16 nand_write_page(u32 block, u32 page, u32 src, u32 len,u8 file_format)
{
u8 col_addr_cycle = 0;
/* set row_addr_cycle */
col_addr_cycle = NAND_MAIN_BYTESIZE > 512 ? 2 : 1;
/* set nfc spare data */
set_nfc_spare(file_format);
/* zero buffer in case len < page size */
if( len < nand->page_size)
memset((void *)NFC_MAB0_BASE,0xff,nand->page_size);
/* copy the data */
nfc_memcpy(src, NFC_MAB0_BASE, len);
/* bi swap */
if((flag_bi_swap == BI_SWAP_ENABLE) &&
(NAND_MAIN_BYTESIZE > 512))
nand_bi_main_sp();
/* send prog inital command */
nfc_command_input(NAND_CMD_PAGE_PROG);
/* addr cycle: row & col */
nfc_address_cycle(0, col_addr_cycle);
nfc_address_cycle(block * NAND_NUM_OF_PAGES + page, NAND_NUM_OF_ROW_ADDR_CYCLES);
/* trans data from nfc to nand flash*/
send_prog_page();
/* send prog confirm command */
nfc_command_input(NAND_CMD_PAGE_PROG_CONFIRM);
/* wait prog completely*/
nand_wait();
/* check prog status */
if(nand_read_status() & NAND_STATUS_PROG_ERROR)
return FLASH_ERROR_PROG;
return FLASH_ERROR_NO;
}
/*!
* Function to compare one page
* @param [in] BlockNum - block number
* @param [in] PageNum - page number
* @param [in] TargetAddress -destination address
* @param [in] ByteSize - byte size to be compared
*/
s16 nand_compare_page(u32 block, u32 page, u32 dest, u32 len)
{
u32 i;
u32 error = 0;
u8 col_addr_cycle = 0;
/* set row_addr_cycle */
col_addr_cycle = NAND_MAIN_BYTESIZE > 512 ? 2 : 1;
/* send page read command */
nfc_command_input(NAND_CMD_READ);
/* address cycle, row & col */
nfc_address_cycle(0, col_addr_cycle);
nfc_address_cycle(block * NAND_NUM_OF_PAGES + page, NAND_NUM_OF_ROW_ADDR_CYCLES);
/* send page read confirm command for large page */
if (NAND_MAIN_BYTESIZE > 512)
nfc_command_input(NAND_CMD_READ_CONFIRM);
/* trans data from nand flash to nfc buffer */
send_read_page();
/* check ecc status */
if(nfc_ecc_uncorrectable_error(NAND_MAIN_BYTESIZE))
return FLASH_ERROR_ECC;
/* bi swap */
if((flag_bi_swap == BI_SWAP_ENABLE) &&
(NAND_MAIN_BYTESIZE > 512))
nand_bi_main_sp();
/* compare data */
for(i = 0; i < len; i += 2) {
if((*(volatile u16 *)(NFC_MAB0_BASE+i)) != (*(volatile u16 *)(dest + i))){
error++;
}
}
if(error)
return FLASH_ERROR_VERIFY;
return FLASH_ERROR_NO;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -