📄 nand_base.c
字号:
case NAND_TIMED_OUT:
{
printk("EDU_read60\n");
//Read has timed out
printk(KERN_ERR "nand_select_cache_is_valid has timed out.\n");
ret = -ETIMEDOUT;
done = 1;
}
break;
default:
{
printk("EDU_read70\n");
BUG_ON(1);
/* Should never get here */
ret = -EINVAL;
done = 1;
}
break;
}//End of switch()
}//End of while()
out:
return ret;
}
#else // NO EDU PRESENT OR EDU DISABLED
/**
* nand_posted_read_cache - [NAND Interface] Read the 512B cache area
* Assuming nand_get_device() has been called to obtain exclusive lock
* @param mtd MTD data structure
* @param oobarea Spare area, pass NULL if not interested
* @param buffer the databuffer to put/get data, pass NULL if only spare area is wanted.
* @param offset offset to read from or write to, must be 512B aligned.
*
* Caller is responsible to pass a buffer that is
* (1) large enough for 512B for data and optionally an oobarea large enough for 16B.
* (2) 4-byte aligned.
*
* Read the cache area into buffer. The size of the cache is mtd-->eccsize and is always 512B.
*/
static int nand_posted_read_cache(struct mtd_info* mtd,
void* buffer, u_char* oobarea, L_OFF_T offset)
{
struct nand_chip* chip = mtd->priv;
L_OFF_T sliceOffset = __ll_and32(offset, ~ (mtd->eccsize - 1));
int i, ret;
int retries = 2, done = 0;
uint32_t* p32 = (uint32_t*) oobarea;
if (gdebug > 3 ) {
printk("%s: offset=%s, oobarea=%p\n", __FUNCTION__, __ll_sprintf(NandMsg, offset), oobarea);}
while (retries > 0 && !done) {
if (unlikely(__ll_isub(offset, sliceOffset))) {
printk(KERN_ERR "%s: offset %08x is not cache aligned, sliceOffset=%08lx, CacheSize=%d\n",
__FUNCTION__, (unsigned int) offset, (unsigned long) sliceOffset, mtd->eccsize);
return -EINVAL;
}
chip->ctrl_writeAddr(chip, sliceOffset, 0);
PLATFORM_IOFLUSH_WAR();
chip->ctrl_write(BCHP_NAND_CMD_START, OP_PAGE_READ);
// Wait until cache is filled up
ret = nand_select_cache_is_valid(mtd, FL_READING, offset);
switch (ret) {
case NAND_CORRECTABLE_ECC_ERROR: /* Success, no errors */
case NAND_SUCCESS:
if (buffer) {
nand_from_flash_memcpy32(chip, buffer, offset, mtd->eccsize);
}
if (oobarea) {
PLATFORM_IOFLUSH_WAR();
for (i = 0; i < 4; i++) {
p32[i] = /* THT 11-30-06 */ be32_to_cpu (chip->ctrl_read(BCHP_NAND_SPARE_AREA_READ_OFS_0 + i*4));
}
if (gdebug) {printk("%s: offset=%08x, oob=\n", __FUNCTION__, __ll_low(sliceOffset)); print_oobbuf(oobarea, 16);}
}
// ret = NAND_CORRECTABLE_ECC_ERROR; // Success
done = 1;
break;
case NAND_UNCORRECTABLE_ECC_ERROR:
{
/* Flash chip returns errors
|| There is a bug in the controller, where if one reads from an erased block that has NOT been written to,
|| this error is raised.
|| (Writing to OOB area does not have any effect on this bug)
|| The workaround is to also look into the OOB area, to see if they are all 0xFF
*/
u_char oobbuf[16];
int erased, allFF;
int i;
if (!oobarea)
oobarea = &oobbuf[0];
p32 = (uint32_t*) oobarea;
for (i = 0; i < 4; i++) {
p32[i] = /* THT 11-30-06 */ be32_to_cpu (chip->ctrl_read(BCHP_NAND_SPARE_AREA_READ_OFS_0 + i*4));
}
if (chip->ecclevel == NAND_ECC_HAMMING) {
erased = (oobarea[6] == 0xff && oobarea[7] == 0xff && oobarea[8] == 0xff);
allFF = (oobarea[6] == 0x00 && oobarea[7] == 0x00 && oobarea[8] == 0x00);
if (gdebug > 3 ) {printk("%s: erased=%d, allFF=%d\n", __FUNCTION__, erased, allFF);}
}
else if (chip->ecclevel >= NAND_ECC_BCH_1 && chip->ecclevel <= NAND_ECC_BCH_12) {
erased = allFF = 1;
// For BCH-n, the ECC bytes are at the end of the OOB area
for (i=chip->eccOobSize-chip->eccbytes; i<chip->eccOobSize; i++) {
erased = erased && (oobarea[i] == 0xff);
allFF = allFF && (oobarea[i] == 0x00);
}
//if (gdebug > 3 )
{printk("%s: eccOobSize=%d, eccbytes=%d, erased=%d, allFF=%d\n", __FUNCTION__,
chip->eccOobSize, chip->eccbytes, erased, allFF);}
}
else {
printk("BUG: Unsupported ECC level %d\n", chip->ecclevel);
BUG();
}
if ( erased || allFF) {
/*
* For the first case, the slice is an erased block, and the ECC bytes are all 0xFF,
* for the 2nd, all bytes are 0xFF, so the Hamming Codes for it are all zeroes.
* The current version of the NAND controller treats these as un-correctable errors.
* For either case, fill data buffer with 0xff and return success. The error has already
* been cleared inside nand_verify_ecc.
* Both case will be handled correctly by the Nand controller in later releases.
*/
p32 = (uint32_t*) buffer;
for (i=0; i < chip->eccsize/4; i++) {
p32[i] = 0xFFFFFFFF;
}
ret = 0; // Success
}
else {
/* Real error: Disturb read returns uncorrectable errors */
ret = -EBADMSG;
if (gdebug > 3 ) {printk("<-- %s: ret -EBADMSG\n", __FUNCTION__);}
}
done = 1;
break;
}
case NAND_FLASH_STATUS_ERROR:
printk(KERN_ERR "nand_cache_is_valid returns 0\n");
ret = -EBADMSG;
done = 1;
break;
case NAND_TIMED_OUT:
//Read has timed out
printk(KERN_ERR "nand_cache_is_valid returns 0\n");
ret = -ETIMEDOUT;
done = 1;
break;
default:
BUG_ON(1);
/* Should never gets here */
ret = -EFAULT;
done = 1;
break;
}
}
if (gdebug > 3 ) {
printk("<-- %s: offset=%s\n", __FUNCTION__, __ll_sprintf(NandMsg, offset));
print_databuf(buffer, 32);
}
return ret;
}
#endif // CONFIG_MTD_NAND_EDU
/**
* nand_posted_read_oob - [NAND Interface] Read the spare area
* @param mtd MTD data structure
* @param oobarea Spare area, pass NULL if not interested
* @param offset offset to read from or write to
*
* This is a little bit faster than nand_posted_read, making this command useful for improving
* the performance of BBT management.
* The 512B flash cache is invalidated.
*
* Read the cache area into buffer. The size of the cache is mtd->writesize and is always 512B,
* for this version of the NAND controller.
*/
static int nand_posted_read_oob(struct mtd_info* mtd,
unsigned char* oobarea, L_OFF_T offset, int raw)
{
struct nand_chip* chip = mtd->priv;
L_OFF_T sliceOffset = __ll_and32(offset, ~(mtd->eccsize - 1));
int i, ret, done = 0;
int retries = 5;
//char msg[20];
PRINTK("->%s: offset=%s\n", __FUNCTION__, __ll_sprintf(NandMsg, offset));
PRINTK("->%s: sliceOffset=%s\n", __FUNCTION__, __ll_sprintf(NandMsg, sliceOffset));
PRINTK("eccsize = %d\n", mtd->eccsize);
if (gdebug > 3 ) {
printk("-->%s: offset=%08x\n", __FUNCTION__, (uint32_t) offset); }
while (retries > 0 && !done) {
if (unlikely(__ll_isub(sliceOffset, offset))) {
printk(KERN_ERR "%s: offset %s is not cache aligned\n",
__FUNCTION__, __ll_sprintf(NandMsg, offset));
return -EINVAL;
}
chip->ctrl_writeAddr(chip, sliceOffset, 0);
chip->ctrl_write(BCHP_NAND_CMD_START, OP_SPARE_AREA_READ);
// Wait until spare area is filled up
switch (nand_spare_is_valid(mtd, FL_READING, raw)) {
case 1:
if (oobarea) {
uint32_t* p32 = (uint32_t*) oobarea;
for (i = 0; i < 4; i++) {
p32[i] = /* THT 11-30-06 */ be32_to_cpu /**/(chip->ctrl_read(BCHP_NAND_SPARE_AREA_READ_OFS_0 + (i<<2)));
}
if (gdebug > 3) {printk("%s: offset=%08x, oob=\n", __FUNCTION__, __ll_low(sliceOffset)); print_oobbuf(oobarea, 16);}
}
ret = 0;
done = 1;
break;
case -1:
ret = -EBADMSG;
if (gdebug > 3 ) {printk("%s: ret = -EBADMSG\n", __FUNCTION__);}
/* nand_spare_is_valid also clears the error bit, so just retry it */
retries--;
break;
case 0:
//Read has timed out or read found bad block. TBD: Find out which is which
ret = -ETIMEDOUT;
done = 1;
break;
default:
BUG_ON(1);
/* NOTREACHED */
ret = -EINVAL;
done = 1;
break; /* Should never gets here */
}
}
if (gdebug > 3 ) {
printk("<--%s: offset=%08x\n", __FUNCTION__, (uint32_t) offset);
print_oobbuf(oobarea, 16);}
return ret;
}
#ifdef CONFIG_MTD_NAND_EDU
/**
* nand_posted_write - [NAND Interface] Write a buffer to the flash cache
* Assuming nand_get_device() has been called to obtain exclusive lock
*
* @param mtd MTD data structure
* @param buffer the databuffer to put/get data
* @param oobarea Spare area, pass NULL if not interested
* @param offset offset to write to, and must be 512B aligned
*
* Write to the cache area TBD 4/26/06
*/
static int nand_posted_write_cache(struct mtd_info *mtd,
const void* buffer, const unsigned char* oobarea, L_OFF_T offset)
{
uint32_t* p32;
int i;
int ret;
struct nand_chip* this = mtd->priv;
int needBBT=0;
L_OFF_T sliceOffset = __ll_and32(offset, ~ (mtd->eccsize - 1));
#ifdef WR_BADBLOCK_SIMULATION
unsigned long tmp = (unsigned long) offset;
DIunion wrFailLocationOffset;
#endif
// printk("%s\n", __FUNCTION__);
// printk("EDU10\n");
if (unlikely(__ll_isub(sliceOffset, offset))) {
printk(KERN_ERR "%s: offset %s is not cache aligned\n",
__FUNCTION__, __ll_sprintf(NandMsg, offset));
ret = -EINVAL;
goto out;
}
this->ctrl_writeAddr(this, sliceOffset, 0);
// printk("EDU20\n");
if (oobarea) {
p32 = (uint32_t*) oobarea;
if (gdebug) {printk("%s: oob=\n", __FUNCTION__); print_oobbuf(oobarea, 16);}
}
else {
// Fill with 0xFF if don't want to change OOB
p32 = (uint32_t*) &ffchars[0];
}
// printk("EDU40\n");
for (i = 0; i < 4; i++) {
this->ctrl_write(BCHP_NAND_SPARE_AREA_WRITE_OFS_0 + i*4, /* THT 11-30-06 */ cpu_to_be32 /* */(p32[i]));
}
PLATFORM_IOFLUSH_WAR(); // Check if this line may be taken-out
#if 0
// printk("EDUWrite\n");
// printk("EDU_write: %08x\n", (uint32) EDU_ldw);
if(this->options & NAND_COMPLEX_OOB_WRITE)
{
EDU_write((uint32)ffchars, (uint32) EDU_ldw);
// printk("EDU45: NAND_COMPLEX_OOB_WRITE... must investigate!\n");
}
else
#endif
{
ret = EDU_write(buffer, EDU_ldw);
if (ret)
goto out;
}
// printk("EDU50\n");
// Wait until flash is ready
ret = nand_select_write_is_complete(mtd, &needBBT);
#ifdef WR_BADBLOCK_SIMULATION
if((tmp == wrBadBlockFailLocation) && (bScanBypass_badBlock == 0))
{
wrFailLocationOffset.s.high = 0;
wrFailLocationOffset.s.low = wrBadBlockFailLocation;
printk("Creating new bad block @ %s\n", __ll_sprintf(NandMsg, wrFailLocationOffset.ll, this->xor_invert_val));
needBBT = 1;
ret = 1;
}
#endif
if (ret)
{
if (!needBBT)
{
ret = 0;
goto out;
}
else
{ // Need BBT
#if defined (ECC_CORRECTABLE_SIMULATION) || defined(ECC_UNCORRECTABLE_SIMULATION) || defined(WR_BADBLOCK_SIMULATION)
printk("%s: Marking bad block @%s\n", __FUNCTION__, __ll_sprintf(NandMsg, offset, this->xor_invert_val));
#endif
ret = this->block_markbad(mtd, offset);
ret = -EINVAL;
//ret = -EINVAL;
goto out;
}
}
//Write has timed out or read found bad block. TBD: Find out which is which
printk(KERN_INFO "%s: Timeout\n", __FUNCTION__);
ret = -ETIMEDOUT;
out:
// printk("EDU99\n");
return ret;
}
#else // NO EDU PRESENT OR EDU DISABLED
/**
* nand_posted_write - [NAND Interface] Write a buffer to the flash cache
* Assuming nand_get_device() has been called to obtain exclusive lock
*
* @param mtd MTD data structure
* @param buffer the databuffer to put/get data
* @param oobarea Spare area, pass NULL if not interested
* @param offset offset to write to, and must be 512B aligned
*
* Write to the cache area TBD 4/26/06
*/
static int nand_posted_write_cache(struct mtd_info *mtd,
const void* buffer, const unsigned char* oobarea, L_OFF_T offset)
{
struct nand_chip* chip = mtd->priv;
L_OFF_T sliceOffset = __ll_and32(offset, ~ (mtd->eccsize - 1));
uint32_t* p32;
int i, needBBT=0;
int ret;
//char msg[20];
if (gdebug > 3 ) {
printk("--> %s: offset=%sx\n", __FUNCTION__, __ll_sprintf(NandMsg, offset));
print_databuf(buffer, 32);}
if (unlikely(__ll_isub(sliceOffset, offset))) {
printk(KERN_ERR "%s: offset %s is not cache aligned\n",
__FUNCTION__, __ll_sprintf(NandMsg, offset));
ret = -EINVAL;
goto out;
}
chip->ctrl_writeAddr(chip, sliceOffset, 0);
if (buffer) {
if (gdebug > 3 ) {print_databuf(buffer, 32);}
nand_to_flash_memcpy32(chip, offset, buffer, mtd->eccsize);
}
#if 0
/* Must write data when NAND_COMPLEX_OOB_WRITE */
else if (chip->options & NAND_COMPLEX_OOB_WRITE) {
nand_to_flash_memcpy32(chip, offset, ffchars, mtd->eccsize);
}
#endif
//printk("30\n");
if (oobarea) {
p32 = (uint32_t*) oobarea;
if (gdebug > 3) {printk("%s: oob=\n", __FUNCTION__); print_oobbuf(oobarea, 16);}
}
else {
// Fill with 0xFF if don't want to change OOB
p32 = (uint32_t*) &ffchars[0];
}
//printk("40\n");
for (i = 0; i < 4; i++) {
chip->ctrl_write(BCHP_NAND_SPARE_AREA_WRITE_OFS_0 + i*4, /* THT 11-30-06 */ cpu_to_be32 /* */(p32[i]));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -