/*===========================================================================
 
FUNCTION  FLASH_NAND_OPER_REGION_INIT
 
DESCRIPTION
    Initilize user partition info,and get the handle of nand flash
RETURN VALUE
    TRUE if Op Succeed
    FALSE if Op Failure
 
SIDE EFFECTS
  None
 
===========================================================================*/
oper_region_struct_t *flash_nand_oper_region_init(  oper_region_type  oper_region_idx)
{
    uint8                idx              = (uint8)oper_region_idx;
    char                 *parent_name_ptr = NULL;
    unsigned int               offset           = 0;
    
    /* 范围保护 */
    if (idx >= REGION_MAX)
    {
        printk(KERN_ERR "Parm error: idx = %d max_ids = %d\n",idx,REGION_MAX);
        return NULL;
    }
 
    /*lint -e662*/
    parent_name_ptr = (char *)child_region[idx].parent_name;
    printk(KERN_DEBUG "parent_name_ptr =%s \n",parent_name_ptr);
    /*lint +e662*/
    /*lint -e661*/
    offset          = child_region[idx].offset;
    /*lint +e661*/

    /* get mtd device */
    g_mtd = get_mtd_device_nm(parent_name_ptr);
    if (NULL == g_mtd)
    {
        printk(KERN_ERR "get_mtd_device_nm error\n");
        return NULL;
    }

    printk(" info :mtd->erasesize = %d ,mtd->writesize = %d \n",
           g_mtd->erasesize,g_mtd->writesize);
    
    /* get the flash address */
    operation_region[idx].block_size = g_mtd->erasesize;
    operation_region[idx].page_size = g_mtd->writesize;
    operation_region[idx].start_addr = (offset * operation_region[idx].block_size);
    operation_region[idx].buffer = himalloc(operation_region[idx].page_size); 

    printk(KERN_DEBUG "operation_region[%d] = %u \n", idx, (unsigned int)operation_region[idx].start_addr);
    
    if (NULL == operation_region[idx].buffer)
    {
        put_mtd_device(g_mtd);
        return NULL;
    }

    /* 初始化读写flash时使用的缓冲区 */
    memset((void *)operation_region[idx].buffer, NAND_FILL_CHAR_APP,
           operation_region[idx].page_size);
    
    return &operation_region[idx];
}
Esempio n. 2
0
/**
* 作用:读取分区相对偏移地址的标志值,主要是为NV模块用,查询此分区的偏移地址的标志位的值
*
* 参数:
* @partition_name         	---分区名
* @partition_offset         ---分区的相对偏移
* @flag                     ---把检测的分区的标志值存放在此flag中
* 描述:NV模块把一个分区的一个block的最后一页的OOB中存放特定标记值,读此标记值存放在flag中
*/
u32 bsp_nand_read_flag_nv(const char *partition_name, u32 partition_offset, unsigned char *flag)
{
    u32 flash_addr;
    u32 ret = NANDC_ERROR;
    static unsigned char *buffer = NULL;
    struct nand_spec spec;
    struct ST_PART_TBL * ptable = find_partition_by_name((char *)partition_name);
	/*参数不对*/
    if(!ptable)
    {
        goto ERRO;
    }
    if(!flag)
    {
        NAND_TRACE(("argu error.\n"));
        goto ERRO;
    }
	/*得到此分区的nandflash的规格参数*/
    ret = bsp_get_nand_info(&spec);
    if(ret)
    {
        goto ERRO;
    }
	/*没有内存时分配内存*/
    if(!buffer)
    {
        buffer = (unsigned char *)himalloc(spec.pagesize + YAFFS_BYTES_PER_SPARE);
        if(!buffer)
        {
    		NAND_TRACE(("get ram buffer failed!\n"));
    		goto ERRO;
        }
    }

    memset(buffer, 0xFF, spec.pagesize + YAFFS_BYTES_PER_SPARE);

    flash_addr = ptable->offset + partition_offset;
	/*使能ECC功能的带OOB读数据功能*/
    ret = nand_read_oob((flash_addr + spec.blocksize - spec.pagesize),
          (unsigned int)buffer, (spec.pagesize + YAFFS_BYTES_PER_SPARE),YAFFS_BYTES_PER_SPARE ,NULL);
    if(ret)
    {
		NAND_TRACE(("nand read oob failed!\n"));
		goto ERRO;
    }
    *flag = (*(buffer + spec.pagesize) == NV_WRITE_SUCCESS) ? NV_WRITE_SUCCESS : (~NV_WRITE_SUCCESS);

    return NANDC_OK;
ERRO:
    return ret;
}
Esempio n. 3
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;
}
/**********************************************************************************
 * FUNC NAME:
 * ptable_parse_mtd_partitions() - external API: get mtd partitions from flash table
 *
 * PARAMETER:
 * @mtd_parts -[output] pointer to mtd partitions
 * @nr_parts - [output] number of mtd partitions
 *
 *
 * DESCRIPTION:
 *     get mtd partitions from flash table
 *
 * CALL FUNC:
 *
 *********************************************************************************/
u32 ptable_parse_mtd_partitions(struct mtd_partition** mtd_parts, u32 *nr_parts)
{
    struct ST_PART_TBL * ptable = NULL;
    struct mtd_partition *parts = NULL;
    u32 npart;
    u32 last_end = 0;
    u32 last_id = 0;

	if(!(mtd_parts && nr_parts))
	{
		goto ERRO;
	}
    
    /*ensure that there's a ram table exist*/
    /*lint -save -e539*/
    ptable_ensure();
    /*lint -restore*/
    
    ptable_adapt();

#ifdef __FASTBOOT__
    /*show all ptable info*/
#ifndef BSP_CONFIG_EDA
    ptable_show(NULL);
#endif
#endif
   	ptable = ptable_get_ram_data();

    /*get number of partitions*/
    npart = 0;

    while(0 != strcmp(PTABLE_END_STR, ptable->name))
    {
        if(ptable->capacity)    /* skip empty part */
        {
            npart++;
        }

        ptable++;
    }

    /*this memory never free */
    parts = himalloc(sizeof(struct mtd_partition) * npart);
    if(NULL == parts)
    {
        hiout(("ptable_to_mtd_partition, error malloc\r\n"));
        goto ERRO;
    }

    memset(parts, 0x00 , (sizeof(struct mtd_partition) * npart));

    /*lint -save -e613*/
    *mtd_parts = parts;
    /*lint -restore*/
    *nr_parts  = npart;

    /*get address again*/
    ptable = ptable_get_ram_data();

    /*置0以后重新计算实际转移到MTD的分区数*/
    npart = 0;

    /*form flash table to mtd partitions */
    while(0 != strcmp(PTABLE_END_STR, ptable->name))
    {
        /*not first partition (PTABLE_HEAD_STR)*/
        if((last_end != ptable->offset) && (0 != last_id))
        {
            hiout(("ptable check error! "));
            hiout((ptable->name));
            hiout(("\r\n"));
            goto ERRO;
        }

        #ifdef __KERNEL__
        if(ptable->property & MOUNT_MTD){
        #endif
        parts->name   = ptable->name;
        parts->offset = ptable->offset;
        parts->size   = ptable->capacity;
        parts++;
        npart++;
        #ifdef __KERNEL__
        }
        #endif

        last_end = ptable->offset + ptable->capacity;
        last_id  = ptable->image;

        ptable++;
    }

    *nr_parts  = npart;

    return NANDC_OK;

ERRO:
    if(NULL != parts)
    {
        hifree(parts);
    }

    return NANDC_ERROR;
}