/*****************************************************************************
* name		: flash_scan_bad
*
* description	: scan bad block, if partition_name is NULL, scan all partitions
*
* input		: char *partition_name: partition to scan
*
* other		: No
*****************************************************************************/
void flash_scan_bad(char *partition_name)
{
    struct ptentry *ptn = NULL;
    struct ST_PART_TBL *part = (struct ST_PART_TBL *)SHM_MEM_PTABLE_ADDR;
    struct nand_spec spec;
    struct ptentry tn;

    if(nand_get_spec(&spec))
    {
        cprintf("ERROR: nand get spec failed!\n");
        return;
    }

    partition_name = bsp_nand_argument_check(partition_name);

    /* scan all partitions */
    if(!partition_name)
    {
        part++;
        while(0 != strcmp(PTABLE_END_STR, part->name))
        {
            if(DATA_VALID == ptable_get_validity(part))
            {
                /* coverity[buffer_size_warning] */
                strncpy(tn.name, part->name, 16);
                tn.start = part->offset;
                tn.length = part->capacity;
                /* coverity[uninit_use_in_call] */
                get_partition_badblock(&tn, &spec);
            }


            part++;
        }
    }
    else /* scan one partition */
    {
        ptn = flash_find_ptn(partition_name);
        if(!ptn)
        {
            cprintf("ERROR: wrong partition name: %s\n", partition_name);
            return;
        }
        /* coverity[uninit_use_in_call] */
        get_partition_badblock(ptn, &spec);
    }

    cprintf("\n\n");
    return;
}
/*****************************************************************************
* name		: flash_erase_force
*
* description	: Erase nand block force, even if it's bad.
*
* input		: char *partition_name: partition to be erase
*
* other		: No
*****************************************************************************/
void flash_erase_force(char *partition_name)
{
	unsigned i = 0;
    unsigned ret = ERROR;
	unsigned block_start = 0;
	unsigned block_end= 0;

    struct nand_spec spec;
    struct ptentry *ptn = NULL;

    ret = nand_get_spec(&spec);
    if(ret)
    {
        cprintf("ERROR: nand get spec failed!\n");
        goto EXIT;
    }

    partition_name = bsp_nand_argument_check(partition_name);
    if(NULL == partition_name)
    {
        cprintf("ERROR: no partition name!\n");
        goto EXIT;
    }

    ptn = flash_find_ptn(partition_name);
    if(!ptn)
    {
        cprintf("ERROR: wrong partition name: %s\n", partition_name);
        goto EXIT;
    }

    /* coverity[uninit_use] */
	block_start = (ptn->start + spec.blocksize- 1) / spec.blocksize;
	block_end = (ptn->start + ptn->length + spec.blocksize - 1) / spec.blocksize;

	for (i = block_start; i < block_end; i++)
	{
	    ret = nand_erase(i);
        if(ret)
        {
            cprintf("ERROR: nand erase error, block id = %d, ret = %d.\n", i, ret);
        }
	}
    cprintf("Erase %s force finished!\n", partition_name);

    return;
EXIT:
    cprintf("ret = 0x%x!\n", ret);
    return;
}
/*****************************************************************************
* name		: flash_erase
*
* description	: Erase nand block
*
* input		: ptentry *ptn: partition to be erase
*
* return		: NANDF_OK: erase OK
*			  NANDF_ERROR_INIT: Init failed
*			  NANDF_ERROR_ARGS: Input error
*			  NANDF_BAD_BLOCK: the block to be erase is a bad block
*			  NANDF_ERROR_ERASE: erase failed, and mark the block as a bad block
*			  NANDF_ERROR_ERASE_MARKBAD: erase failed, and mark bad block failed
*			  NANDF_ERROR_SEMTAKE: apply semphore failed
*			  NANDF_ERROR_SEMGIVE: release semphore failed
*
* other		: No
*****************************************************************************/
int flash_erase(ptentry *ptn)
{
	int ret = ERROR;
	unsigned i = 0;
	unsigned block_start = 0;
	unsigned block_end= 0;
    unsigned bad_flag;
    struct nand_spec spec;

    ret = nand_get_spec(&spec);
    if(ret)
    {
        cprintf("ERROR: nand get spec failed!\n");
        return ERROR;
    }

    /* coverity[uninit_use] */
	block_start = (ptn->start + spec.blocksize- 1) / spec.blocksize;
	block_end = (ptn->start + ptn->length + spec.blocksize - 1) / spec.blocksize;

	for (i = block_start; i < block_end; i++)
	{
	    ret = (s32)nand_isbad(i, &bad_flag);
        if(NANDC_OK != ret || NANDC_BAD_BLOCK == bad_flag)
        {
            cprintf("block %d is bad, not erase, ret=%x\n", i, ret);
            continue;
        }

        ret = (s32)nand_erase(i);
        if(ret)
        {
            cprintf("erase block %d failed, ret=%x\n", i, ret);
        }
	}

    return OK;
}
Exemple #4
0
/**
 * 作用:nandc模块提供对外扫描坏块的函数接口
 *
 * 参数:
 * @start         ---flash开始的地址
 * @length        ---扫描的长度
 * @if_erase      ---如果检测是好块根据此参数来决定是否擦除此块
 * 描述:扫描flash是否是坏块,根据参数来决定是否擦除
 */
u32 nand_scan_bad(FSZ start, FSZ length, u32 if_erase)
{
	u32 addr_block_align;
	u32 length_block_align;
	u32 blk_id, is_bad, times, ret;
	struct nand_spec spec;
	/*因为是在fastboot中实现,内存的释放是没有实现的,使用静态变量表示一次分配以后都不分配了*/
	static u32 block_buf = 0 ;

	memset(&spec, 0, sizeof(struct nand_spec));
	/*通过此函数得到nandflash的规格参数,知道blocksize的大小*/
	if(NAND_OK != nand_get_spec(&spec))
	{
		NAND_TRACE(("nand_scan_bad: nand_get_spec failed\n"));
		return NAND_ERROR;
	}

	/*扫描块时要块对齐*/
	addr_block_align = start - start%(spec.blocksize);
	/*得到要扫描的块长度*/
	length_block_align = nandc_alige_size(start + length, spec.blocksize) - addr_block_align;
	/*如果没有分配内存就分配内存*/
	if(!block_buf)
	{
		block_buf = (u32)himalloc(spec.blocksize);
		if(NULL == (void*)block_buf)//pclint 58
		{
			NAND_TRACE(("nand_scan_bad: himalloc failed\n"));
			goto ERRO;
		}
	}
	/*还有块长度需要扫描*/
	while(length_block_align > 0)
	{
		/*得到块号地址*/
		blk_id = addr_block_align/spec.blocksize;
		if(NAND_OK != nand_isbad(blk_id, &is_bad))
		{
			NAND_TRACE(("nand_scan_bad: nand_isbad failed\n"));
			goto ERRO;
		}
		if(NANDC_GOOD_BLOCK == is_bad)
		{
			times = 1;
			/*读整块数据如果没有出错的话表示是好坏*/
			while((NANDC_E_READ == nand_read((FSZ)addr_block_align, block_buf, spec.blocksize, 0)) && (times))
			{
			    times--;
			}
			if(0 == times)
			{
			    NAND_TRACE(("nand_scan_bad: find and read error, address:0x%x\n",addr_block_align));

			    ret = nand_bad(blk_id);
			    if(ret)
			    {
			        NAND_TRACE(("nand_scan_bad:nand check bad failed, ret = 0x%x\n",ret));
			    }
			}
			/*是好块如果要擦除的话就擦除*/
			else if(NANDC_TRUE == if_erase)
			{
			    ret = nand_erase(blk_id);
			    if(ret)
			    {
			        NAND_TRACE(("nand_scan_bad:nand erase failed, ret = 0x%x\n",ret));
			    }
			}
			else
			{
			}
		}
		else
		{
			NAND_TRACE(("nand_scan_bad:find bad block: 0x%x\n",addr_block_align));
		}
		length_block_align -= spec.blocksize;
		addr_block_align   += spec.blocksize;
	}

	return NAND_OK;
ERRO:
	return NAND_ERROR;
}