VIVI中MTD驱动的实现(2)
时间:2010-05-17 来源:charming2440
上面一章分析了MTD的实现(未完)接上文
在完成了函数的初始化以后则是调用smc_insert()函数,这个函数包括两个部分
inline int smc_insert(struct nand_chip *this);
1:smc_init()函数的功能就是调用smc_scan()函数
2:然后就是给this结构内部数据申请内存:this->data_buf = mmalloc(sizeof(u_char) *(mymtd->oobblock + mymtd->oobsize));
第2部分很好理解(在vivi的第5部分heap_init中有关于mmalloc函数的源代码)
现在来分析第一部分,smc_scan()函数
在分析smc_scan函数之前,我们先来看一个nsnd_flash_dev结构,这个结构定义了一些常用的nand flash的基本信息:
static struct nand_flash_dev nand_flash_ids[] = {
{"Toshiba TC5816BDC", NAND_MFR_TOSHIBA, 0x64, 21, 1, 2, 0x1000}, // 2Mb 5V
{"Toshiba TC58V16BDC", NAND_MFR_TOSHIBA, 0xea, 21, 1, 2, 0x1000}, // 2Mb 3.3V
{"Toshiba TC5832DC", NAND_MFR_TOSHIBA, 0x6b, 22, 0, 2, 0x2000}, // 4Mb 5V
{"Toshiba TC58V32DC", NAND_MFR_TOSHIBA, 0xe5, 22, 0, 2, 0x2000}, // 4Mb 3.3V
{"Toshiba TC58V64AFT/DC", NAND_MFR_TOSHIBA, 0xe6, 23, 0, 2, 0x2000}, // 8Mb 3.3V
{"Toshiba TH58V128DC", NAND_MFR_TOSHIBA, 0x73, 24, 0, 2, 0x4000}, // 16Mb
{"Toshiba TC58256FT/DC", NAND_MFR_TOSHIBA, 0x75, 25, 0, 2, 0x4000}, // 32Mb
{"Toshiba TH58512FT", NAND_MFR_TOSHIBA, 0x76, 26, 0, 3, 0x4000}, // 64Mb
{"Toshiba TH58NS100/DC", NAND_MFR_TOSHIBA, 0x79, 27, 0, 3, 0x4000}, // 128Mb
{"Samsung KM29N16000", NAND_MFR_SAMSUNG, 0x64, 21, 1, 2, 0x1000}, // 2Mb 5V
{"Samsung KM29W16000", NAND_MFR_SAMSUNG, 0xea, 21, 1, 2, 0x1000}, // 2Mb 3.3V
{"Samsung unknown 4Mb", NAND_MFR_SAMSUNG, 0x6b, 22, 0, 2, 0x2000}, // 4Mb 5V
{"Samsung KM29W32000", NAND_MFR_SAMSUNG, 0xe3, 22, 0, 2, 0x2000}, // 4Mb 3.3V
{"Samsung unknown 4Mb", NAND_MFR_SAMSUNG, 0xe5, 22, 0, 2, 0x2000}, // 4Mb 3.3V
{"Samsung KM29U64000", NAND_MFR_SAMSUNG, 0xe6, 23, 0, 2, 0x2000}, // 8Mb 3.3V
{"Samsung KM29U128T", NAND_MFR_SAMSUNG, 0x73, 24, 0, 2, 0x4000}, // 16Mb
{"Samsung KM29U256T", NAND_MFR_SAMSUNG, 0x75, 25, 0, 2, 0x4000}, // 32Mb
{"Samsung K9D1208V0M", NAND_MFR_SAMSUNG, 0x76, 26, 0, 3, 0x4000}, // 64Mb
{"Samsung K9D1G08V0M", NAND_MFR_SAMSUNG, 0x79, 27, 0, 3, 0x4000}, // 128Mb
{NULL,}
};
先来分析smc_scan(struct mtd_info *mtd)函数的基本流程:
smc_scan-->nand_select()
-->nand_command(mtd, NAND_CMD_READID, 0x00, -1)
-->this->wait_for_ready();等待flash设备准备好
-->在找到于上面结构匹配的flash之后则是对mtd_info结构赋值
-->nand_deselect();
-->解析填充MTD driver中的数据
在知道了大概的流程和功能后我们来对每一个函数进行具体的分析:
一:nand_select();
这个函数是用一个宏来定义的,具体定义如下
#define nand_select() this->hwcontrol(NAND_CTL_SETNCE); \
nand_command(mtd, NAND_CMD_RESET, -1, -1); \
udelay(10);
这个宏定义其实就是调用了3个函数,
第一个函数我们在第一章里面就说明了,其实就是调用smc_hwcontrol(NAND_CTL_SETNCE)函数,作用就是enable the chip select
第二个函数调用:nand_command()函数,现来看看nand_command函数的原型:
(vivi/drivers/mtd/nand/smc_core.c)
/*
* Send command to NAND device
*/
static void
nand_command(struct mtd_info *mtd, unsigned command, int column, int page_addr)
{
register struct nand_chip *this = mtd->priv;
/* Begin command latch cycle */
this->hwcontrol(NAND_CTL_SETCLE);
this->hwcontrol(NAND_CTL_DAT_OUT);
/*
* Write out the command to the device.
*/
if (command != NAND_CMD_SEQIN)
this->write_cmd(command);
else {
if (mtd->oobblock == 256 && column >= 256) {
column -= 256;
this->write_cmd(NAND_CMD_RESET);
this->write_cmd(NAND_CMD_READOOB);
this->write_cmd(NAND_CMD_SEQIN);
} else if (mtd->oobblock == 512 && column >= 256) {
if (column < 512) {
column -= 256;
this->write_cmd(NAND_CMD_READ1);
this->write_cmd(NAND_CMD_SEQIN);
} else {
column -= 512;
this->write_cmd(NAND_CMD_READOOB);
this->write_cmd(NAND_CMD_SEQIN);
}
} else {
this->write_cmd(NAND_CMD_READ0);
this->write_cmd(NAND_CMD_SEQIN);
}
}
/* Set ALE and clear CLE to start address cycle */
this->hwcontrol(NAND_CTL_CLRCLE);
this->hwcontrol(NAND_CTL_SETALE);
/* Serially input address */
if (column != -1)
this->write_addr(column);
if (page_addr != -1) {
this->write_addr((u_char)(page_addr & 0xff));
this->write_addr((u_char)((page_addr >> 8) & 0xff));
/* One more address cycle for higher density devices */
if (mtd->size & 0x0c000000) {
this->write_addr((u_char)((page_addr >> 16) & 0xff));
}
}
/* Latch in address */
this->hwcontrol(NAND_CTL_CLRALE);
this->hwcontrol(NAND_CTL_DAT_IN);
/* Pause for 15us */
udelay(15);
}
从这里可以看出是使得nand_flash重启,
3):延时.
二:nand_command(mtd, NAND_CMD_READID, 0x00, -1);
从上面的nand_command函数的原型中可以看出,这个函数的目的就是读取nand flash的设备ID
三:this->wait_for_ready();
四:遍历常用nand flash结构数组,找到匹配的设备,并且初始化mtd_info 和 nand_chip结构
五:nand_deselect();
这个函数的原型也有一个宏定义;
#define nand_deselect() this->hwcontrol(NAND_CTL_CLRNCE) //disable chip select
继续填充MTD drivers中的数据(初始化各种数据和函数)
下面是vivi中smc_scan(struct mtd_info *mtd)的原型
/*
* Scan for the SMC device
*/
int
smc_scan(struct mtd_info *mtd)
{
int i, nand_maf_id, nand_dev_id;
struct nand_chip *this = mtd->priv;
/* Select the device */
nand_select();
/* Send the command for reading device ID */
nand_command(mtd, NAND_CMD_READID, 0x00, -1);
this->wait_for_ready();
/* Read manufacturer and device IDs */
nand_maf_id = this->read_data();
nand_dev_id = this->read_data();
/* Print and sotre flash device information */
for (i = 0; nand_flash_ids[i].name != NULL; i++) {
if (nand_maf_id == nand_flash_ids[i].manufacture_id &&
nand_dev_id == nand_flash_ids[i].model_id) {
#ifdef USE_256BYTE_NAND_FLASH
if (!mtd->size) {
mtd->name = nand_flash_ids[i].name;
mtd->erasesize = nand_flash_ids[i].erasesize;
mtd->size = (1 << nand_flash_ids[i].chipshift);
mtd->eccsize = 256;
if (nand_flash_ids[i].page256) {
mtd->oobblock = 256;
mtd->oobsize = 8;
this->page_shift = 8;
} else {
mtd->oobblock = 512;
mtd->oobsize = 16;
this->page_shift = 9;
}
this->dev = &nand_smc_info[GET_DI_NUM(nand_flash_ids[i].chipshift)];
}
#else
if (!(mtd->size) && !(nand_flash_ids[i].page256)) {
mtd->name = nand_flash_ids[i].name;
mtd->erasesize = nand_flash_ids[i].erasesize;
mtd->size = (1 << nand_flash_ids[i].chipshift);
mtd->eccsize = 256;
mtd->oobblock = 512;
mtd->oobsize = 16;
this->page_shift = 9;
this->dev = &nand_smc_info[GET_DI_NUM(nand_flash_ids[i].chipshift)];
}
#endif
printk("NAND device: Manufacture ID:" \
" 0x%02x, Chip ID: 0x%02x (%s)\n",
nand_maf_id, nand_dev_id, mtd->name);
break;
}
}
/* De-select the device */
nand_deselect();
/* Print warning message for no device */
if (!mtd->size) {
printk("No NAND device found!!!\n");
return 1;
}
/* Fill in remaining MTD driver data */
mtd->type = MTD_NANDFLASH;
mtd->flags = MTD_CAP_NANDFLASH | MTD_ECC;
mtd->module = NULL;
mtd->ecctype = MTD_ECC_SW;
mtd->erase = nand_erase;
mtd->point = NULL;
mtd->unpoint = NULL;
mtd->read = nand_read;
mtd->write = nand_write;
mtd->read_ecc = nand_read_ecc;
mtd->write_ecc = nand_write_ecc;
mtd->read_oob = nand_read_oob;
mtd->write_oob = nand_write_oob;
mtd->lock = NULL;
mtd->unlock = NULL;
/* Return happy */
return 0;
}
这是函数的整体的概括,后面会陆续分析具体函数的实现。从来彻底了解在vivi中MTD中间驱动层的概念(未完,待续!)
在完成了函数的初始化以后则是调用smc_insert()函数,这个函数包括两个部分
inline int smc_insert(struct nand_chip *this);
1:smc_init()函数的功能就是调用smc_scan()函数
2:然后就是给this结构内部数据申请内存:this->data_buf = mmalloc(sizeof(u_char) *(mymtd->oobblock + mymtd->oobsize));
第2部分很好理解(在vivi的第5部分heap_init中有关于mmalloc函数的源代码)
现在来分析第一部分,smc_scan()函数
在分析smc_scan函数之前,我们先来看一个nsnd_flash_dev结构,这个结构定义了一些常用的nand flash的基本信息:
static struct nand_flash_dev nand_flash_ids[] = {
{"Toshiba TC5816BDC", NAND_MFR_TOSHIBA, 0x64, 21, 1, 2, 0x1000}, // 2Mb 5V
{"Toshiba TC58V16BDC", NAND_MFR_TOSHIBA, 0xea, 21, 1, 2, 0x1000}, // 2Mb 3.3V
{"Toshiba TC5832DC", NAND_MFR_TOSHIBA, 0x6b, 22, 0, 2, 0x2000}, // 4Mb 5V
{"Toshiba TC58V32DC", NAND_MFR_TOSHIBA, 0xe5, 22, 0, 2, 0x2000}, // 4Mb 3.3V
{"Toshiba TC58V64AFT/DC", NAND_MFR_TOSHIBA, 0xe6, 23, 0, 2, 0x2000}, // 8Mb 3.3V
{"Toshiba TH58V128DC", NAND_MFR_TOSHIBA, 0x73, 24, 0, 2, 0x4000}, // 16Mb
{"Toshiba TC58256FT/DC", NAND_MFR_TOSHIBA, 0x75, 25, 0, 2, 0x4000}, // 32Mb
{"Toshiba TH58512FT", NAND_MFR_TOSHIBA, 0x76, 26, 0, 3, 0x4000}, // 64Mb
{"Toshiba TH58NS100/DC", NAND_MFR_TOSHIBA, 0x79, 27, 0, 3, 0x4000}, // 128Mb
{"Samsung KM29N16000", NAND_MFR_SAMSUNG, 0x64, 21, 1, 2, 0x1000}, // 2Mb 5V
{"Samsung KM29W16000", NAND_MFR_SAMSUNG, 0xea, 21, 1, 2, 0x1000}, // 2Mb 3.3V
{"Samsung unknown 4Mb", NAND_MFR_SAMSUNG, 0x6b, 22, 0, 2, 0x2000}, // 4Mb 5V
{"Samsung KM29W32000", NAND_MFR_SAMSUNG, 0xe3, 22, 0, 2, 0x2000}, // 4Mb 3.3V
{"Samsung unknown 4Mb", NAND_MFR_SAMSUNG, 0xe5, 22, 0, 2, 0x2000}, // 4Mb 3.3V
{"Samsung KM29U64000", NAND_MFR_SAMSUNG, 0xe6, 23, 0, 2, 0x2000}, // 8Mb 3.3V
{"Samsung KM29U128T", NAND_MFR_SAMSUNG, 0x73, 24, 0, 2, 0x4000}, // 16Mb
{"Samsung KM29U256T", NAND_MFR_SAMSUNG, 0x75, 25, 0, 2, 0x4000}, // 32Mb
{"Samsung K9D1208V0M", NAND_MFR_SAMSUNG, 0x76, 26, 0, 3, 0x4000}, // 64Mb
{"Samsung K9D1G08V0M", NAND_MFR_SAMSUNG, 0x79, 27, 0, 3, 0x4000}, // 128Mb
{NULL,}
};
先来分析smc_scan(struct mtd_info *mtd)函数的基本流程:
smc_scan-->nand_select()
-->nand_command(mtd, NAND_CMD_READID, 0x00, -1)
-->this->wait_for_ready();等待flash设备准备好
-->在找到于上面结构匹配的flash之后则是对mtd_info结构赋值
-->nand_deselect();
-->解析填充MTD driver中的数据
在知道了大概的流程和功能后我们来对每一个函数进行具体的分析:
一:nand_select();
这个函数是用一个宏来定义的,具体定义如下
#define nand_select() this->hwcontrol(NAND_CTL_SETNCE); \
nand_command(mtd, NAND_CMD_RESET, -1, -1); \
udelay(10);
这个宏定义其实就是调用了3个函数,
第一个函数我们在第一章里面就说明了,其实就是调用smc_hwcontrol(NAND_CTL_SETNCE)函数,作用就是enable the chip select
第二个函数调用:nand_command()函数,现来看看nand_command函数的原型:
(vivi/drivers/mtd/nand/smc_core.c)
/*
* Send command to NAND device
*/
static void
nand_command(struct mtd_info *mtd, unsigned command, int column, int page_addr)
{
register struct nand_chip *this = mtd->priv;
/* Begin command latch cycle */
this->hwcontrol(NAND_CTL_SETCLE);
this->hwcontrol(NAND_CTL_DAT_OUT);
/*
* Write out the command to the device.
*/
if (command != NAND_CMD_SEQIN)
this->write_cmd(command);
else {
if (mtd->oobblock == 256 && column >= 256) {
column -= 256;
this->write_cmd(NAND_CMD_RESET);
this->write_cmd(NAND_CMD_READOOB);
this->write_cmd(NAND_CMD_SEQIN);
} else if (mtd->oobblock == 512 && column >= 256) {
if (column < 512) {
column -= 256;
this->write_cmd(NAND_CMD_READ1);
this->write_cmd(NAND_CMD_SEQIN);
} else {
column -= 512;
this->write_cmd(NAND_CMD_READOOB);
this->write_cmd(NAND_CMD_SEQIN);
}
} else {
this->write_cmd(NAND_CMD_READ0);
this->write_cmd(NAND_CMD_SEQIN);
}
}
/* Set ALE and clear CLE to start address cycle */
this->hwcontrol(NAND_CTL_CLRCLE);
this->hwcontrol(NAND_CTL_SETALE);
/* Serially input address */
if (column != -1)
this->write_addr(column);
if (page_addr != -1) {
this->write_addr((u_char)(page_addr & 0xff));
this->write_addr((u_char)((page_addr >> 8) & 0xff));
/* One more address cycle for higher density devices */
if (mtd->size & 0x0c000000) {
this->write_addr((u_char)((page_addr >> 16) & 0xff));
}
}
/* Latch in address */
this->hwcontrol(NAND_CTL_CLRALE);
this->hwcontrol(NAND_CTL_DAT_IN);
/* Pause for 15us */
udelay(15);
}
从这里可以看出是使得nand_flash重启,
3):延时.
二:nand_command(mtd, NAND_CMD_READID, 0x00, -1);
从上面的nand_command函数的原型中可以看出,这个函数的目的就是读取nand flash的设备ID
三:this->wait_for_ready();
四:遍历常用nand flash结构数组,找到匹配的设备,并且初始化mtd_info 和 nand_chip结构
五:nand_deselect();
这个函数的原型也有一个宏定义;
#define nand_deselect() this->hwcontrol(NAND_CTL_CLRNCE) //disable chip select
继续填充MTD drivers中的数据(初始化各种数据和函数)
下面是vivi中smc_scan(struct mtd_info *mtd)的原型
/*
* Scan for the SMC device
*/
int
smc_scan(struct mtd_info *mtd)
{
int i, nand_maf_id, nand_dev_id;
struct nand_chip *this = mtd->priv;
/* Select the device */
nand_select();
/* Send the command for reading device ID */
nand_command(mtd, NAND_CMD_READID, 0x00, -1);
this->wait_for_ready();
/* Read manufacturer and device IDs */
nand_maf_id = this->read_data();
nand_dev_id = this->read_data();
/* Print and sotre flash device information */
for (i = 0; nand_flash_ids[i].name != NULL; i++) {
if (nand_maf_id == nand_flash_ids[i].manufacture_id &&
nand_dev_id == nand_flash_ids[i].model_id) {
#ifdef USE_256BYTE_NAND_FLASH
if (!mtd->size) {
mtd->name = nand_flash_ids[i].name;
mtd->erasesize = nand_flash_ids[i].erasesize;
mtd->size = (1 << nand_flash_ids[i].chipshift);
mtd->eccsize = 256;
if (nand_flash_ids[i].page256) {
mtd->oobblock = 256;
mtd->oobsize = 8;
this->page_shift = 8;
} else {
mtd->oobblock = 512;
mtd->oobsize = 16;
this->page_shift = 9;
}
this->dev = &nand_smc_info[GET_DI_NUM(nand_flash_ids[i].chipshift)];
}
#else
if (!(mtd->size) && !(nand_flash_ids[i].page256)) {
mtd->name = nand_flash_ids[i].name;
mtd->erasesize = nand_flash_ids[i].erasesize;
mtd->size = (1 << nand_flash_ids[i].chipshift);
mtd->eccsize = 256;
mtd->oobblock = 512;
mtd->oobsize = 16;
this->page_shift = 9;
this->dev = &nand_smc_info[GET_DI_NUM(nand_flash_ids[i].chipshift)];
}
#endif
printk("NAND device: Manufacture ID:" \
" 0x%02x, Chip ID: 0x%02x (%s)\n",
nand_maf_id, nand_dev_id, mtd->name);
break;
}
}
/* De-select the device */
nand_deselect();
/* Print warning message for no device */
if (!mtd->size) {
printk("No NAND device found!!!\n");
return 1;
}
/* Fill in remaining MTD driver data */
mtd->type = MTD_NANDFLASH;
mtd->flags = MTD_CAP_NANDFLASH | MTD_ECC;
mtd->module = NULL;
mtd->ecctype = MTD_ECC_SW;
mtd->erase = nand_erase;
mtd->point = NULL;
mtd->unpoint = NULL;
mtd->read = nand_read;
mtd->write = nand_write;
mtd->read_ecc = nand_read_ecc;
mtd->write_ecc = nand_write_ecc;
mtd->read_oob = nand_read_oob;
mtd->write_oob = nand_write_oob;
mtd->lock = NULL;
mtd->unlock = NULL;
/* Return happy */
return 0;
}
这是函数的整体的概括,后面会陆续分析具体函数的实现。从来彻底了解在vivi中MTD中间驱动层的概念(未完,待续!)
相关阅读 更多 +
排行榜 更多 +