1
0
uboot-1.1.4-kirkwood/diag/diag_nand.c

204 lines
4.7 KiB
C
Raw Normal View History

2024-01-09 13:41:15 +01:00
#include <common.h>
#include <nand.h>
#include "diag.h"
extern nand_info_t nand_info[];
/*******************************************************************************
* mvNandDetectTest - Detect NAND flash with its geometry and prints details.
*
* DESCRIPTION:
* This routine prints NAND detection status. Also displays NAND flash size,
* page size, number of blocks if detected.
*
* INPUT:
* None.
*
* OUTPUT:
* None.
*
* RETURN:
* Returns 1 on failure, else 0
*******************************************************************************/
int mvNandDetectTest(void)
{
int testFlag;
testFlag = DIAG_PASS;
if(NULL != nand_info[0].name)
{
printf("\tDevice: 0, Size: %lu MB, Page Size: %d KB, Block Size: %d KB\n", \
(nand_info[0].size/1024)/1024, nand_info[0].oobblock/1024, \
nand_info[0].erasesize/1024);
}
else
{
printf("\tError: NAND not detected!");
testFlag = DIAG_FAIL;
}
printf("\tNAND detection test ");
printf(((testFlag==DIAG_PASS)?"PASSED\n":"FAIL\n"));
return testFlag;
}
/*******************************************************************************
* mvNandBadBlockTest - Prints all bad blocks on NAND memory
*
* DESCRIPTION:
* This routine checks all blocks against bad block table and prints the
* block if it is marked as bad.
*
* INPUT:
* None.
*
* OUTPUT:
* None.
*
* RETURN:
* Returns 1 on failure, else 0
*******************************************************************************/
int mvNandBadBlockTest(void)
{
int testFlag;
unsigned int off;
testFlag = DIAG_PASS;
for (off=0; off < nand_info[0].size; off += nand_info[0].erasesize)
{
if (nand_block_isbad(&nand_info[0], off))
{
printf("\tBad Block: %08x\n", off);
}
}
printf("\tNAND bad-block detection test ");
printf((testFlag==DIAG_PASS)?"PASSED\n":"FAIL\n");
return testFlag;
}
/*******************************************************************************
* mvNandReadWriteTest - Performs read-write test on NAND chip.
*
* DESCRIPTION:
* This routine writes pattern 0x55,0xaa in 16 blocks at offset immediately
* after ENV section and reads them back and verifies.
*
* INPUT:
* None.
*
* OUTPUT:
* None.
*
* RETURN:
* Returns 1 on failure, else 0
*******************************************************************************/
int mvNandReadWriteTest(void)
{
int i,j,ret;
int testFlag;
unsigned int pageSize;
unsigned char rbuf[2048];
nand_write_options_t wr_opts;
nand_erase_options_t er_opts;
nand_read_options_t rd_opts;
testFlag = DIAG_PASS;
printf("\tNAND read/write test ");
do
{
pageSize = nand_info[0].oobblock;
/***************** ERASE ***********************/
memset(&er_opts, 0, sizeof(er_opts));
er_opts.offset = CFG_ENV_OFFSET + CFG_ENV_SIZE;
er_opts.length = pageSize * PAGES_PER_BLOCK * 16;
er_opts.quiet = 1;
ret = nand_erase_opts(&nand_info[0], &er_opts);
if (ret)
{
printf("\tError: NAND Erase faild!\n");
testFlag = DIAG_FAIL;
break;
}
if(DIAG_PASS != testFlag)
{
break;
}
/***************** WRITE ***********************/
memset(&wr_opts, 0, sizeof(wr_opts));
for(i=0; i < pageSize; i=i+2)
{
wr_opts.buffer[i] = 0x55;
wr_opts.buffer[i+1] = 0xaa;
}
wr_opts.length = pageSize;
wr_opts.offset = CFG_ENV_OFFSET + CFG_ENV_SIZE;
/* opts.forcejffs2 = 1; */
wr_opts.pad = 1;
wr_opts.blockalign = 1;
wr_opts.quiet = 1;
for(i=0; i < PAGES_PER_BLOCK * 16;i++)
{
ret = nand_write_opts(&nand_info[0], &wr_opts);
if (ret)
{
printf("\tError: NAND write faild!\n");
testFlag = DIAG_FAIL;
break;
}
wr_opts.offset += pageSize;
}
if(DIAG_PASS != testFlag)
{
break;
}
/**************** READ *************************/
memset(&rd_opts, 0, sizeof(rd_opts));
rd_opts.buffer = rbuf;
rd_opts.length = (ulong)pageSize;
rd_opts.offset = CFG_ENV_OFFSET + CFG_ENV_SIZE;
rd_opts.quiet = 1;
for(i=0; i < PAGES_PER_BLOCK * 16;i++)
{
ret = nand_read_opts(&nand_info[0], &rd_opts);
if (ret)
{
printf("\tError: NAND read faild!\n");
testFlag = DIAG_FAIL;
break;
}
for(j=0; j < pageSize; j=j+4)
{
if (rbuf[j] != 0x55 && rbuf[j+1] != 0xaa && rbuf[j+2] != 0x55 && rbuf[j+3] != 0xaa)
{
printf("\tError: Data verify failed\n");
testFlag = DIAG_FAIL;
break;
}
}
rd_opts.offset += pageSize;
}
if(DIAG_PASS != testFlag)
{
break;
}
}while(0);
printf((testFlag==DIAG_PASS)?"PASSED\n":"FAIL\n");
return testFlag;
}