A template about the nandflash driver

/* I am a newer to the MTD,This template is just write for study,I can not promise it can
*working better,but I think it can help some newer like me to understand the nand driver easy
*thank you for reading,if you have some suggestion,send me a mail:fansongsen@163.com or my QQ:735308843
*/

#include <linux/module.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/cpufreq.h>

#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h>

#include <asm/io.h>

#include <plat/regs-nand.h>
#include <plat/nand.h>
#define REGS_BASE    0x0
#define REGS_SIZE    0x8
struct tt_nand{
//those are the two main structure when you use the mtd
    struct mtd_info    mtd;
    struct nand_chip    chip;
    struct nand_hw_control    controller;        //this is for the nand internal use
//for this template,you only know the register base
    void __iomem    *regs_base;            //this is our nand controler register base
}ttt_nand;
//this is the mtd_partition table of you nand chip,notice the size
static struct mtd_partition ttt_nand_part[] = {
    [0] = {
        .name    = "part0",
        .size    = 0x00040000,
        .offset    = 0,
    },
    [1] = {
        .name    = "part1",
        .offset = 0x00040000,
        .size    = 0x00020000,
    },
    [2] = {
        .name    = "part2",
        .offset = 0x00060000,
        .size    = 0x00500000,
    }
};

static void ttt_nand_select_chip(struct mtd_info *mtd, int chip)    //for this template, this function is no use because we assume one chip
{
    void __iomem    *regs_base=mtd->priv->priv->regs_base;

    //now you can select the chip
}
static void ttt_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)    //read data from the data register
{
    void __iomem    *regs_base=mtd->priv->priv->regs_base;
    //read the nand read buffer
}
static void ttt_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)    //write data to the data register
{
    void __iomem    *regs_base=mtd->priv->priv->regs_base;
    //write the data to the buffer
}
static void ttt_nand_hwcontrol(struct mtd_info *mtd, int cmd,unsigned int ctrl)    //send the nand command
{
    void __iomem    *regs_base=mtd->priv->priv->regs_base;
    if (cmd == NAND_CMD_NONE)
        return;
    if (ctrl & NAND_CLE)
        writeb(cmd, regs_base + TTT_NFCMD);
    else
        writeb(cmd, regs_base + TTT_NFADDR);
}
static int ttt_nand_devready(struct mtd_info *mtd)        //for poll
{
    void __iomem    *regs_base=mtd->priv->priv->regs_base;
    return readb(regs_base + TTT_NFSTAT) & TTT_NFSTAT_BUSY;
}
/*this mainly init the nand controler register based on the mapped ttt_nand.regs_base*/
/*mainly use the two kernel functions:writel(addr,val) and readl(addr)*/
void ttt_nand_hw_init(struct tt_nand ttt_nand)
{
    //caculate the nand controler clock freq and enable it
    //init the nand controler register
}
static int __init s3c2410_nand_init(void)        //this mainly for the kernel used structure init,it was simple enough
{

    ttt_nand.regs_base=ioremap(REGS_BASE,REGS_SIZE);
    ttt_nand_hw_init(ttt_nand);

    spin_lock_init(&ttt_nand.controller.lock);
    init_waitqueue_head(&ttt_nand.controller.wq);
    

    ttt_nand.chip.write_buf    =    ttt_nand_write_buf;
    ttt_nand.chip.read_buf    =    ttt_nand_read_buf;
    ttt_nand.chip.select_chip  =     ttt_nand_select_chip;
    ttt_nand.chip.chip_delay   =     50;
    ttt_nand.chip.priv    =    &ttt_nand;
    ttt_nand.chip.options       =     0;
    ttt_nand.chip.controller    =    &ttt_nand.controller;
    ttt_nand.chip.IO_ADDR_W    =    TTT_NAND_DATAR;
    ttt_nand.chip.cmd_ctrl  =     ttt_nand_hwcontrol;
    ttt_nand.chip.dev_ready =     ttt_nand_devready;
    ttt_nand.chip.IO_ADDR_R =     ttt_nand.chip.IO_ADDR_W;
    ttt_nand.chip.ecc.mode     =     NAND_ECC_SOFT;

    ttt_nand.mtd.priv        = &ttt_nand.chip;
    ttt_nand.mtd.owner       = THIS_MODULE;

    if(0==nand_scan_ident(&ttt_nand.mtd,1))
    {
        nand_scan_tail(&ttt_nand.mtd);
        add_mtd_partitions(&ttt_nand.mtd, ttt_nand_part, ARRAY_SIZE(ttt_nand_part));
        add_mtd_device(&ttt_nand.mtd);
    }

    return 0;

}
static void __exit s3c2410_nand_exit(void)
{
    nand_release(&ttt_nand.mtd);
}



module_init(ttt_nand_init);
module_exit(ttt_nand_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("fansongsen@163.com");
MODULE_DESCRIPTION("A Template of MTD NAND driver");
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值