最经搞关于zynq7000,用到了petalinux,其中用的内核版本为xlnx4.0。再处理nandflash问题是,发现如下问题,阅读关于与扩展地址操作的原代码,从纸面上看应该属于一个小bug。原代码如下:
行号:333
/*
* Update Extended Address/bank selection Register.
* Call with flash->lock locked.
*/
static int write_ear(struct spi_nor *nor, u32 addr)
{
u8 code; //操作代码声明
u8 ear;
int ret;
/* Wait until finished previous write command. */
if (spi_nor_wait_till_ready(nor))
return 1;
if (nor->mtd->size <= (0x1000000) << nor->shift)
return 0;
addr = addr % (u32) nor->mtd->size;
ear = addr >> 24;
if ((!nor->isstacked) && (ear == nor->curbank))
return 0;
if (nor->isstacked && (nor->mtd->size <= 0x2000000))
return 0;
if (nor->jedec_id == CFI_MFR_AMD)
code = SPINOR_OP_BRWR; //amd器件的操作代码
if (nor->jedec_id == CFI_MFR_ST) {
write_enable(nor);
code = SPINOR_OP_WREAR; //st的操作代码
}
nor->cmd_buf[0] = ear;
ret = nor->write_reg(nor, code, nor->cmd_buf, 1, 0);
if (ret < 0)
return ret;
nor->curbank = ear;
return 0;
}
以上代码中不难看出,code没有默认值,中途只处理了AMD和ST器件的操作码,应该是一个bug,同样的问题在read_ear函数中也存在,摘录源码如下:
行号:240
/**
* read_ear - Get the extended/bank address register value
* @nor: Pointer to the flash control structure
*
* This routine reads the Extended/bank address register value
*
* Return: Negative if error occured.
*/
static int read_ear(struct spi_nor *nor, struct flash_info *info)
{
int ret;
u8 val;
u8 code; //code未初始化
/* This is actually Spansion */
if (JEDEC_MFR(info) == CFI_MFR_AMD)
code = SPINOR_OP_BRRD; //amd操作码
/* This is actually Micron */
else if (JEDEC_MFR(info) == CFI_MFR_ST)
code = SPINOR_OP_RDEAR; //st操作码
else
return -EINVAL; //其他的推出,此处应该有问题
ret = nor->read_reg(nor, code, &val, 1);
if (ret < 0)
return ret;
return val;
}
不难看出代码中code没有默认值,而且只处理了AMD和ST的器件,应属于bug,
至于怎么处理,大家是大牛,见仁见智,就不在此赘述了