Nand Flash驱动程序编写(4)


/*判断忙*/
static int s3c_dev_ready(struct mtd_info *mtd)
{
    /*返回"NFSTAT的bit[0]";*/
    return (s3c_nand_regs->nfstat & (1<<0));
}

static void s3c_cmd_ctrl(struct mtd_info *mtd, int dat,unsigned int ctrl)
{

if (ctrl & NAND_CLE)
    {
        /* 发命令: NFCMMD=dat */
        s3c_nand_regs->nfcmd = dat;
        //writeb(cmd, host->io_base + (1 << host->board->cle));/*命令*/
    }
    else
    {
        /* 发地址: NFADDR=dat */
        s3c_nand_regs->nfaddr = dat;
        //writeb(cmd, host->io_base + (1 << host->board->ale));/*地址*/
    }
}


static void s3c_select_chip(struct mtd_info *mtd, int chip)
{
    if(chip ==-1)
    {
        /*表示取消选中 NFCONT[1]设为1  */
        s3c_nand_regs->nfcont |=(1<<1);   
    }
    else
    {
        s3c_nand_regs->nfcont &=~(1<<1);
        /*选中芯片 NFCONT[1]设为0 */
    }   
}


static int s3c_nand_init(void)
{

struct clk *clk;
   
    /*1.分配一个nand_chip结构体*/
    s3c_nand_chip =  kzalloc(sizeof(struct nand_chip), GFP_KERNEL);
   
    s3c_nand_regs = ioremap(0x4E000000, sizeof(struct s3c_nand_regs));
   
    /*2.设置nandc_chip结构体*/
    s3c_nand_chip->IO_ADDR_R = &s3c_nand_regs->nfdata;
    s3c_nand_chip->IO_ADDR_W = &s3c_nand_regs->nfdata;
    s3c_nand_chip->cmd_ctrl = s3c_cmd_ctrl;
    s3c_nand_chip->dev_ready = s3c_dev_ready;
    s3c_nand_chip->select_chip = s3c_select_chip;
    s3c_nand_chip->ecc.mode    = NAND_ECC_SOFT;
    //s3c_nand_chip->chip_delay = 20;

/* 使能NAND FLASH控制器的时钟 */
    clk = clk_get(NULL, "nand");
    clk_enable(clk);              /* CLKCON'bit[4] */
   

/*初始化nand控制器 设置寄存器*/
#define TACLS  0
#define TWRPH0  3
#define TWRPH1  0
    /* HCLK=100MHz
    * TACLS:  发出CLE/ALE之后多长时间才发出nWE信号, 从NAND手册可知CLE/ALE与nWE可以同时发出,所以TACLS=0
    * TWRPH0: nWE的脉冲宽度, HCLK x ( TWRPH0 + 1 ), 从NAND手册可知它要>=12ns, 所以TWRPH0>=1
    * TWRPH1: nWE变为高电平后多长时间CLE/ALE才能变为低电平, 从NAND手册可知它要>=5ns, 所以TWRPH1>=0
    */
    s3c_nand_regs->nfconf=(TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);

/* NFCONT:
    * BIT1-设为1, 取消片选
    * BIT0-设为1, 使能NAND FLASH控制器
    * BIT4-设为0, 未初始化hardware ECC
    */
    s3c_nand_regs->nfcont = (1<<1) | (1<<0);
   
    /*分配一个mtd_info结构体*/
    s3c_mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);

/*设置s3c_mtd结构体*/
    s3c_mtd->owner = THIS_MODULE;
    s3c_mtd->priv = s3c_nand_chip;

/* 识别NAND FLASH, 构造mtd_info */
    nand_scan(s3c_mtd, 1);

/*设置分区表*/
    add_mtd_partitions(s3c_mtd, s3c_nand_parts, 4);
   
    add_mtd_device(s3c_mtd);
    return 0;
}

static void s3c_nand_exit(void)
{
    kfree(s3c_mtd);
    kfree(s3c_nand_chip);
    iounmap(s3c_nand_regs);
}

module_init(s3c_nand_init);
module_exit(s3c_nand_exit);
MODULE_LICENSE("GPL");

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/8de93cc6319f1cca71498a4b52c50343.html