分类: LINUX
2013-03-21 23:58:05
Arm-linux东东nand之4: nand_command
nand_get_flash_type()->chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
我们一段一段来.因为不能添图片了,实在大多图了.
static void nand_command(struct mtd_info *mtd, unsigned int command,
int column, int page_addr)
{
register struct nand_chip *chip = mtd->priv;
int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;
/*
* Write out the command to the device.
*/
if (command == NAND_CMD_SEQIN) {
int readcmd;
if (column >= mtd->writesize) {
/* OOB area */
column -= mtd->writesize;
readcmd = NAND_CMD_READOOB;
} else if (column < 256) {
/* First 256 bytes --> READ0 */
readcmd = NAND_CMD_READ0;
} else {
column -= 256;
readcmd = NAND_CMD_READ1;
}
chip->cmd_ctrl(mtd, readcmd, ctrl);
ctrl &= ~NAND_CTRL_CHANGE;
}
NAND_CTRL_CLE表示是发送命令.等下会看到如果设了NAND_CTRL_CLE S3C2440就会将数据写到命令寄存器中去. NAND_CTRL_CHANGE用的比较少.表示CHANGE.
如果命令是NAND_CMD_SEQIN就表示有数据了.还记不记得说过一页分为A区B区C区.那总该选一下吧.如果column大于writesize假设是512的页那么就是大于512就表示C区.就发送这样的命令给它NAND_CMD_READOOB 0x50,其他以此类推.就不说了.
有些人就会问了.选中了一个区.而我的数据超过了那个区的容量.那怎么办呀:
看到没有如果是A区开始It depends on how many data are inputted 也就是可以超界.谁叫我是A区呢.从图可以看到只要下面还有区就可以超过.
chip->cmd_ctrl(mtd, readcmd, ctrl);
ctrl &= ~NAND_CTRL_CHANGE;
这两句就是发送命令选择区了.ctrl就更改了值.表示chage.关于怎么样发送.后面说.
ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE;
/* Serially input address */
if (column != -1) {
/* Adjust columns for 16 bit buswidth */
if (chip->options & NAND_BUSWIDTH_16)
column >>= 1;
chip->cmd_ctrl(mtd, column, ctrl);
ctrl &= ~NAND_CTRL_CHANGE;
}
if (page_addr != -1) {
chip->cmd_ctrl(mtd, page_addr, ctrl);
ctrl &= ~NAND_CTRL_CHANGE;
chip->cmd_ctrl(mtd, page_addr >> 8, ctrl);
/* One more address cycle for devices > 32MiB */
if (chip->chipsize > (32 << 20))
chip->cmd_ctrl(mtd, page_addr >> 16, ctrl);
}
接下来就要发送地址了. NAND_CTRL_ALE就表示地址.column为-1就表示没有地址.这里很好理解了.来看一下这个:
/* One more address cycle for devices > 32MiB */
if (chip->chipsize > (32 << 20))
chip->cmd_ctrl(mtd, page_addr >> 16, ctrl);
如果NAND的容量超过了32M才会有第三个页地址.
…………………….
chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
/*
* program and erase have their own busy handlers
* status and sequential in needs no delay
*/
switch (command) {
case NAND_CMD_PAGEPROG:
case NAND_CMD_ERASE1:
case NAND_CMD_ERASE2:
case NAND_CMD_SEQIN:
case NAND_CMD_STATUS:
return;
case NAND_CMD_RESET:
if (chip->dev_ready)
break;
udelay(chip->chip_delay);
chip->cmd_ctrl(mtd, NAND_CMD_STATUS,
NAND_CTRL_CLE | NAND_CTRL_CHANGE);
chip->cmd_ctrl(mtd,
NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) ;
return;
/* This applies to read commands */
default:
/*
* If we don't have access to the busy pin, we apply the given
* command delay
*/
if (!chip->dev_ready) {
udelay(chip->chip_delay);
return;
}
}
/* Apply this short delay always to ensure that we do wait tWB in
* any case on any machine. */
ndelay(100);
nand_wait_ready(mtd);
}
.结合NAND的命令图这一段看懂应该没有问题
拿chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);这个命令来说:
ECH就是厂商ID,Device Code就设备ID.这是三星的NAND
nand_command就这样完了.完了.
还有一个就是: chip->cmd_ctrl
对于S3C2440来说就是:
static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd,
unsigned int ctrl)
{
struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
if (cmd == NAND_CMD_NONE)
return;
if (ctrl & NAND_CLE)
writeb(cmd, info->regs + S3C2440_NFCMD);
else
writeb(cmd, info->regs + S3C2440_NFADDR);
}
NFCMD就是命令寄存器.NFADDR就是地址寄存器.
#define NAND_CLE 0x02
/* Select the address latch by setting ALE to high */
#define NAND_ALE 0x04
#define NAND_CTRL_CLE (NAND_NCE | NAND_CLE)
#define NAND_CTRL_ALE (NAND_NCE | NAND_ALE)
NAND_CTRL_CLE 就是NAND_CLE | NAND_NCE
返回了.真的完了.回来再看