加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

uboot第2阶段nand的初始化分析

发布时间:2020-12-15 18:14:18 所属栏目:百科 来源:网络整理
导读:在第二阶段中: #if (CONFIG_COMMANDS CFG_CMD_NAND)puts ("NAND: "); //在uboot启动时打印的nand_init();/* go init the NAND */#endif 从上面代码可以看到要对nand进行初始化,需要加入CFG_CMD_NAND的支持。 方法: 在boardshanl2440shanl2440.h中,加入

在第二阶段中:

#if (CONFIG_COMMANDS & CFG_CMD_NAND)
	puts ("NAND:  ");        //在uboot启动时打印的
	nand_init();		/* go init the NAND */
#endif
从上面代码可以看到要对nand进行初始化,需要加入CFG_CMD_NAND的支持。

方法:

在boardshanl2440shanl2440.h中,加入:

#define CONFIG_COMMANDS
(CONFIG_CMD_DFL |
CFG_CMD_CACHE |
CFG_CMD_NAND |
/*CFG_CMD_EEPROM |*/
/*CFG_CMD_I2C |*/
/*CFG_CMD_USB |*/
CFG_CMD_REGINFO ?|
CFG_CMD_DATE |
CFG_CMD_ELF)
下面看下nand_init的实现:

void nand_init(void)
{
	int i;
	unsigned int size = 0;
	for (i = 0; i < CFG_MAX_NAND_DEVICE; i++) {//#define CFG_MAX_NAND_DEVICE ? ? 1 ? 设置nand的芯片有几个。
		nand_init_chip(&nand_info[i],&nand_chip[i],base_address[i]);//对nand进行初始化
		size += nand_info[i].size;//获取到nand chip的容量
		if (nand_curr_device == -1)
			nand_curr_device = i;
	}
	printf("%lu MiBn",size / (1024 * 1024)); //在终端上打印的:NAND:  256 MiB就是这句话

#ifdef CFG_NAND_SELECT_DEVICE
	/*
	 * Select the chip in the board/cpu specific driver
	 */
	board_nand_select_device(nand_info[nand_curr_device].priv,nand_curr_device);
#endif
}

接着往下看:

nand_init_chip
static void nand_init_chip(struct mtd_info *mtd,struct nand_chip *nand,ulong base_addr)
{
	mtd->priv = nand;//将nand_chip付接到mtd_info上

	nand->IO_ADDR_R = nand->IO_ADDR_W = (void  __iomem *)base_addr;//设置读写的io地址,base-adddr为0,
	board_nand_init(nand);

	if (nand_scan(mtd,1) == 0) {
		if (!mtd->name)
			mtd->name = (char *)default_nand_name;
	} else
		mtd->name = NULL;

}
这里面有两个重要的函数:

board_nand_init和nand_scan
1.board_nand_init ?//和具体的平台相关,在移植uboot时,自行添加

void board_nand_init(struct nand_chip *chip)
{
  S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();

  s3c24x0_nand_inithw();//初始化时序和使能nand控制器

  chip->IO_ADDR_R    = (void *)&s3c2440nand->NFDATA;
  chip->IO_ADDR_W    = (void *)&s3c2440nand->NFDATA;
	chip->hwcontrol    = s3c2440_nand_hwcontrol;//硬件指定的控制
	chip->dev_ready    = s3c2440_nand_devready;//nand设备的状态
	chip->select_chip  = s3c2440_nand_select_chip;//片选
	chip->options      = 0;
	chip->eccmode       = NAND_ECC_SOFT;//ecc的模式
}

static void s3c24x0_nand_inithw(void)
{
    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();

#define TACLS   0
#define TWRPH0  2
#define TWRPH1  0

        /* Set flash memory timing */
        s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
        /* Initialize ECC,enable chip select,NAND flash controller enable */
        s3c2440nand->NFCONT = (1<<4)|(0<<1)|(1<<0);
}
2.nand_scan函数对nand_chip结构体进一步填充,不何具体平台有关的代码:

int nand_scan (struct mtd_info *mtd,int maxchips)
{
	int i,j,nand_maf_id,nand_dev_id,busw;
	struct nand_chip *this = mtd->priv;

	/* Get buswidth to select the correct functions*/
	busw = this->options & NAND_BUSWIDTH_16;   //busw == 0

	/* check for proper chip_delay setup,set 20us if not */
	if (!this->chip_delay)
		this->chip_delay = 20;//设置传输数据到寄存器中的芯片延时

	/* check,if a user supplied command function given */
	if (this->cmdfunc == NULL)
		this->cmdfunc = nand_command;//设置nand的命令

	/* check,if a user supplied wait function given */
	if (this->waitfunc == NULL)
		this->waitfunc = nand_wait;//设置nand等待

	if (!this->select_chip)
		this->select_chip = nand_select_chip;//使用的s3c2440_nand_select_chip
	if (!this->write_byte)
		this->write_byte = busw ? nand_write_byte16 : nand_write_byte; //nand_write_byte
	if (!this->read_byte)
		this->read_byte = busw ? nand_read_byte16 : nand_read_byte;//nand_read_byte
	if (!this->write_word)
		this->write_word = nand_write_word;
	if (!this->read_word)
		this->read_word = nand_read_word;
	if (!this->block_bad)
		this->block_bad = nand_block_bad;
	if (!this->block_markbad)
		this->block_markbad = nand_default_block_markbad;
	if (!this->write_buf)
		this->write_buf = busw ? nand_write_buf16 : nand_write_buf;//nand_write_buf
	if (!this->read_buf)
		this->read_buf = busw ? nand_read_buf16 : nand_read_buf;//nand_read_buf
	if (!this->verify_buf)
		this->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf;//nand_verify_buf
	if (!this->scan_bbt)
		this->scan_bbt = nand_default_bbt;

	/* Select the device */
	this->select_chip(mtd,0);//使用的s3c2440_nand_select_chip

	/* Send the command for reading device ID  读取nand的设备id*/
	this->cmdfunc (mtd,NAND_CMD_READID,0x00,-1);

	/* Read manufacturer and device IDs */
	nand_maf_id = this->read_byte(mtd);
	nand_dev_id = this->read_byte(mtd);

	/* Print and store flash device information */
	for (i = 0; nand_flash_ids[i].name != NULL; i++) {

		if (nand_dev_id != nand_flash_ids[i].id)
			continue;

		if (!mtd->name) mtd->name = nand_flash_ids[i].name;
		this->chipsize = nand_flash_ids[i].chipsize << 20;//获取nand芯片的容量

。。。
}
在这个函数里面读取nand的id,获取nand的容量等等

nandflash的相关信息在在includelinuxmtdNand_ids.h中定义,这个文件中国有各种不同厂商的nand,每个nand的选项包含设备的名字,设备的工厂id,页大小,以M为单位的芯片的大小,块擦除的大小,可选项

struct nand_flash_dev nand_flash_ids[] = {
	{"NAND 1MiB 5V 8-bit",0x6e,256,1,0x1000,0},{"NAND 2MiB 5V 8-bit",0x64,2,{"NAND 4MiB 5V 8-bit",0x6b,512,4,0x2000,{"NAND 1MiB 3,3V 8-bit",0xe8,0xec,{"NAND 2MiB 3,0xea,{"NAND 4MiB 3,0xd5,0xe3,0xe5,{"NAND 8MiB 3,0xd6,8,{"NAND 8MiB 1,8V 8-bit",0x39,0xe6,8V 16-bit",0x49,NAND_BUSWIDTH_16},3V 16-bit",0x59,{"NAND 16MiB 1,0x33,16,0x4000,{"NAND 16MiB 3,0x73,0x43,0x53,{"NAND 32MiB 1,0x35,32,{"NAND 32MiB 3,0x75,0x45,0x55,{"NAND 64MiB 1,0x36,64,{"NAND 64MiB 3,0x76,0x46,0x56,{"NAND 128MiB 1,0x78,128,{"NAND 128MiB 3,0x79,0x72,0x74,{"NAND 256MiB 3,0x71,{"NAND 512MiB 3,0xDC,/* These are the new chips with large page size. The pagesize
	* and the erasesize is determined from the extended id bytes
	*/
	/* 1 Gigabit */
	{"NAND 128MiB 1,0xA1,NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},0xF1,0xB1,NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},0xC1,/* 2 Gigabit */
	{"NAND 256MiB 1,0xAA,0xDA,{"NAND 256MiB 1,0xBA,0xCA,/* 4 Gigabit */
	{"NAND 512MiB 1,0xAC,{"NAND 512MiB 1,0xBC,0xCC,/* 8 Gigabit */
	{"NAND 1GiB 1,0xA3,1024,{"NAND 1GiB 3,0xD3,{"NAND 1GiB 1,0xB3,0xC3,/* 16 Gigabit */
	{"NAND 2GiB 1,0xA5,2048,{"NAND 2GiB 3,0xD5,{"NAND 2GiB 1,0xB5,0xC5,/* Renesas AND 1 Gigabit. Those chips do not support extended id and have a strange page/block layout !
	 * The chosen minimum erasesize is 4 * 2 * 2048 = 16384 Byte,as those chips have an array of 4 page planes
	 * 1 block = 2 pages,but due to plane arrangement the blocks 0-3 consists of page 0 + 4,1 + 5,2 + 6,3 + 7
	 * Anyway JFFS2 would increase the eraseblock size so we chose a combined one which can be erased in one go
	 * There are more speed improvements for reads and writes possible,but not implemented now
	 */
	{"AND 128MiB 3,0x01,NAND_IS_AND | NAND_NO_AUTOINCR | NAND_4PAGE_ARRAY},{NULL,}
};

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读