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

在第二阶段中:

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

方法:

在board\shanl2440\shanl2440.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 MiB\n", 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的相关信息在在include\linux\mtd\Nand_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, 256, 2, 0x1000, 0},
	{"NAND 4MiB 5V 8-bit", 		0x6b, 512, 4, 0x2000, 0},
	{"NAND 1MiB 3,3V 8-bit", 	0xe8, 256, 1, 0x1000, 0},
	{"NAND 1MiB 3,3V 8-bit", 	0xec, 256, 1, 0x1000, 0},
	{"NAND 2MiB 3,3V 8-bit", 	0xea, 256, 2, 0x1000, 0},
	{"NAND 4MiB 3,3V 8-bit", 	0xd5, 512, 4, 0x2000, 0},
	{"NAND 4MiB 3,3V 8-bit", 	0xe3, 512, 4, 0x2000, 0},
	{"NAND 4MiB 3,3V 8-bit", 	0xe5, 512, 4, 0x2000, 0},
	{"NAND 8MiB 3,3V 8-bit", 	0xd6, 512, 8, 0x2000, 0},

	{"NAND 8MiB 1,8V 8-bit", 	0x39, 512, 8, 0x2000, 0},
	{"NAND 8MiB 3,3V 8-bit", 	0xe6, 512, 8, 0x2000, 0},
	{"NAND 8MiB 1,8V 16-bit", 	0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16},
	{"NAND 8MiB 3,3V 16-bit", 	0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16},

	{"NAND 16MiB 1,8V 8-bit", 	0x33, 512, 16, 0x4000, 0},
	{"NAND 16MiB 3,3V 8-bit", 	0x73, 512, 16, 0x4000, 0},
	{"NAND 16MiB 1,8V 16-bit", 	0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16},
	{"NAND 16MiB 3,3V 16-bit", 	0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16},

	{"NAND 32MiB 1,8V 8-bit", 	0x35, 512, 32, 0x4000, 0},
	{"NAND 32MiB 3,3V 8-bit", 	0x75, 512, 32, 0x4000, 0},
	{"NAND 32MiB 1,8V 16-bit", 	0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16},
	{"NAND 32MiB 3,3V 16-bit", 	0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16},

	{"NAND 64MiB 1,8V 8-bit", 	0x36, 512, 64, 0x4000, 0},
	{"NAND 64MiB 3,3V 8-bit", 	0x76, 512, 64, 0x4000, 0},
	{"NAND 64MiB 1,8V 16-bit", 	0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16},
	{"NAND 64MiB 3,3V 16-bit", 	0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16},

	{"NAND 128MiB 1,8V 8-bit", 	0x78, 512, 128, 0x4000, 0},
	{"NAND 128MiB 3,3V 8-bit", 	0x79, 512, 128, 0x4000, 0},
	{"NAND 128MiB 1,8V 16-bit", 	0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16},
	{"NAND 128MiB 3,3V 16-bit", 	0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16},

	{"NAND 256MiB 3,3V 8-bit", 	0x71, 512, 256, 0x4000, 0},

	{"NAND 512MiB 3,3V 8-bit", 	0xDC, 512, 512, 0x4000, 0},

	/* 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,8V 8-bit", 	0xA1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
	{"NAND 128MiB 3,3V 8-bit", 	0xF1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
	{"NAND 128MiB 1,8V 16-bit", 	0xB1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
	{"NAND 128MiB 3,3V 16-bit", 	0xC1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},

	/* 2 Gigabit */
	{"NAND 256MiB 1,8V 8-bit", 	0xAA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
	{"NAND 256MiB 3,3V 8-bit", 	0xDA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
	{"NAND 256MiB 1,8V 16-bit", 	0xBA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
	{"NAND 256MiB 3,3V 16-bit", 	0xCA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},

	/* 4 Gigabit */
	{"NAND 512MiB 1,8V 8-bit", 	0xAC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
	{"NAND 512MiB 3,3V 8-bit", 	0xDC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
	{"NAND 512MiB 1,8V 16-bit", 	0xBC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
	{"NAND 512MiB 3,3V 16-bit", 	0xCC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},

	/* 8 Gigabit */
	{"NAND 1GiB 1,8V 8-bit", 	0xA3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
	{"NAND 1GiB 3,3V 8-bit", 	0xD3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
	{"NAND 1GiB 1,8V 16-bit", 	0xB3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
	{"NAND 1GiB 3,3V 16-bit", 	0xC3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},

	/* 16 Gigabit */
	{"NAND 2GiB 1,8V 8-bit", 	0xA5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
	{"NAND 2GiB 3,3V 8-bit", 	0xD5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
	{"NAND 2GiB 1,8V 16-bit", 	0xB5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
	{"NAND 2GiB 3,3V 16-bit", 	0xC5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},

	/* 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,3V 8-bit",	0x01, 2048, 128, 0x4000, NAND_IS_AND | NAND_NO_AUTOINCR | NAND_4PAGE_ARRAY},

	{NULL,}
};










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值