• <li id="00i08"><input id="00i08"></input></li>
  • <sup id="00i08"><tbody id="00i08"></tbody></sup>
    <abbr id="00i08"></abbr>
  • 新聞中心

    EEPW首頁 > 嵌入式系統 > 設計應用 > S5PV210之Nand flash驅動編寫

    S5PV210之Nand flash驅動編寫

    作者: 時間:2016-10-15 來源:網絡 收藏

    大家好,又到了天嵌【嵌入式分享】的時間,相對于前幾期【嵌入式分享】做的主要是TQ335X開發板的技術分享,本期決定做同是cortex-a8系列的TQ210開發板的技術分享。本期是關于TQ210開發板的Nand flash驅動編寫,可能源碼部分會比較多,本文由博主girlkoo編寫,感謝他的分享。

    本文引用地址:http://www.czjhyjcfj.com/article/201610/307447.htm

    跟裸機程序一樣,S5PV210(TQ210)的Nand flash模塊跟S3C2440(TQ2440)的Nand flash模塊非常相似,如果不引入ECC,驅動程序的編寫也非常簡單,我是使用的Linux-3.8.6(Linux-3.8.3也一樣)內核,驅動的API函數有些變化,不過原理是相通的,稍微看一下內核源碼并參考下其他平臺的相關代碼就可以自己寫出Nand flash驅動了,下面是Nand flash驅動的源碼,沒有啟用ECC,當然,你也可以改成軟件ECC,但是我的覺得既然軟件ECC不如HWECC快,我就采用硬件ECC吧。

    #include

    #include

    #include

    #include

    #include

    #include

    #include

    #include

    struct s5p_nand_regs{

    unsigned long nfconf;

    unsigned long nfcont;

    unsigned long nfcmmd;

    unsigned long nfaddr;

    unsigned long nfdata;

    unsigned long nfmeccd0;

    unsigned long nfmeccd1;

    unsigned long nfseccd;

    unsigned long nfsblk;

    unsigned long nfeblk;

    unsigned long nfstat;

    unsigned long nfeccerr0;

    unsigned long nfeccerr1;

    unsigned long nfmecc0;

    unsigned long nfmecc1;

    unsigned long nfsecc;

    unsigned long nfmlcbitpt;

    };

    struct s5p_nand_ecc{

    unsigned long nfeccconf;

    unsigned long nfecccont;

    unsigned long nfeccstat;

    unsigned long nfeccsecstat;

    unsigned long nfeccprgecc0;

    unsigned long nfeccprgecc1;

    unsigned long nfeccprgecc2;

    unsigned long nfeccprgecc3;

    unsigned long nfeccprgecc4;

    unsigned long nfeccprgecc5;

    unsigned long nfeccprgecc6;

    unsigned long nfeccerl0;

    unsigned long nfeccerl1;

    unsigned long nfeccerl2;

    unsigned long nfeccerl3;

    unsigned long nfeccerl4;

    unsigned long nfeccerl5;

    unsigned long nfeccerl6;

    unsigned long nfeccerl7;

    unsigned long nfeccerp0;

    unsigned long nfeccerp1;

    unsigned long nfeccerp2;

    unsigned long nfeccerp3;

    unsigned long nfeccconecc0;

    unsigned long nfeccconecc1;

    unsigned long nfeccconecc2;

    unsigned long nfeccconecc3;

    unsigned long nfeccconecc4;

    unsigned long nfeccconecc5;

    unsigned long nfeccconecc6;

    };

    static struct nand_chip *nand_chip;

    static struct mtd_info *s5p_mtd_info;

    static struct s5p_nand_regs *s5p_nand_regs;

    static struct s5p_nand_ecc *s5p_nand_ecc;

    static struct clk *s5p_nand_clk;

    static struct mtd_partition s5p_nand_partions[] = {

    [0] = {

    .name = bootloader,

    .offset = 0,

    .size = SZ_1M,

    },

    [1] = {

    .name = kernel,

    .offset = MTDPART_OFS_APPEND,

    .size = 5*SZ_1M,

    },

    [2] = {

    .name = rootfs,

    .offset = MTDPART_OFS_APPEND,

    .size = MTDPART_SIZ_FULL,

    },

    };

    static void s5p_nand_select_chip(struct mtd_info *mtd, int chipnr){

    if(chipnr == -1){

    s5p_nand_regs->nfcont |= (11);

    }

    else{

    s5p_nand_regs->nfcont = ~(11);

    }

    }

    static void s5p_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)

    {

    if (ctrl NAND_CLE){

    s5p_nand_regs->nfcmmd = cmd;

    }

    else{

    s5p_nand_regs->nfaddr = cmd;

    }

    }

    static int s5p_nand_ready(struct mtd_info *mtd){

    return (s5p_nand_regs->nfstat 0x1);

    }

    static int s5p_nand_probe(struct platform_device *pdev){

    int ret = 0;

    struct resource *mem;

    //硬件部分初始化

    mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);

    if (!mem) {

    dev_err(pdev->dev, can't get I/O resource memn);

    return -ENXIO;

    }

    s5p_nand_regs = (struct s5p_nand_regs *)ioremap(mem->start, resource_size(mem));

    if (s5p_nand_regs == NULL) {

    dev_err(pdev->dev, ioremap failedn);

    ret = -EIO;

    goto err_exit;

    }

    s5p_nand_ecc = (struct s5p_nand_ecc *)ioremap(0xB0E20000, sizeof(struct s5p_nand_ecc));

    if(s5p_nand_ecc == NULL){

    dev_err(pdev->dev, ioremap failedn);

    ret = -EIO;

    goto err_iounmap;

    }

    s5p_nand_clk = clk_get(pdev->dev, nand);

    if(s5p_nand_clk == NULL){

    dev_dbg(pdev->dev, get clk failedn);

    ret = -ENODEV;

    goto err_iounmap;

    }

    clk_enable(s5p_nand_clk);

    s5p_nand_regs->nfconf = (312)|(58)|(34)|(11);

    s5p_nand_regs->nfcont |= 3;

    //分配驅動相關結構體

    nand_chip = (struct nand_chip *)kzalloc(sizeof(struct nand_chip), GFP_KERNEL);

    if(nand_chip == NULL){

    dev_err(pdev->dev, failed to allocate nand_chip structuren);

    ret = -ENOMEM;

    goto err_clk_put;

    }

    s5p_mtd_info = (struct mtd_info *)kzalloc(sizeof(struct mtd_info), GFP_KERNEL);

    if(s5p_mtd_info == NULL){

    dev_err(pdev->dev, failed to allocate mtd_info structuren);

    ret = -ENOMEM;

    goto err_free_chip;

    }

    //設置驅動相關結構體

    nand_chip->select_chip = s5p_nand_select_chip;

    nand_chip->cmd_ctrl = s5p_nand_cmd_ctrl;

    nand_chip->IO_ADDR_R = s5p_nand_regs->nfdata;

    nand_chip->IO_ADDR_W = s5p_nand_regs->nfdata;

    nand_chip->dev_ready = s5p_nand_ready;

    nand_chip->ecc.mode = NAND_ECC_SOFT;

    s5p_mtd_info->priv = nand_chip;

    s5p_mtd_info->owner = THIS_MODULE;

    //掃描Nand flash 設備

    if(nand_scan(s5p_mtd_info, 1)){

    dev_dbg(pdev->dev, nand scan errorn);

    goto err_free_info;

    }

    //添加分區信息

    ret = mtd_device_parse_register(s5p_mtd_info, NULL, NULL, s5p_nand_partions, ARRAY_SIZE(s5p_nand_partions));

    if(!ret)

    return 0;

    err_free_info:

    kfree(s5p_mtd_info);

    err_free_chip:

    kfree(nand_chip);

    err_clk_put:

    clk_disable(s5p_nand_clk);

    clk_put(s5p_nand_clk);

    err_iounmap:

    //if(s5p_nand_ecc == NULL)

    // iounmap(s5p_nand_ecc);

    if(s5p_nand_regs == NULL)

    iounmap(s5p_nand_regs);

    err_exit:

    return ret;

    }

    static int s5p_nand_remove(struct platform_device *pdev){

    nand_release(s5p_mtd_info);

    kfree(s5p_mtd_info);

    kfree(nand_chip);

    clk_disable(s5p_nand_clk);

    clk_put(s5p_nand_clk);

    if(s5p_nand_regs == NULL)

    iounmap(s5p_nand_regs);

    return 0;

    }

    static struct platform_driver s5p_nand_drv = {

    .driver = {

    .owner = THIS_MODULE,

    .name = s5p-nand,

    },

    .probe = s5p_nand_probe,

    .remove = s5p_nand_remove,

    };

    module_platform_driver(s5p_nand_drv);

    MODULE_LICENSE(GPL);

    上述源碼為嵌入式愛好者分享,如有更新,請咨詢相關客服與銷售人員,以便更新與開發。

    操作所使用的硬件:

    TQ210V6開發板



    關鍵詞: 天嵌 嵌入式 開發板

    評論


    相關推薦

    技術專區

    關閉
    主站蜘蛛池模板: 永康市| 阿勒泰市| 嘉祥县| 长丰县| 吉木萨尔县| 凉城县| 星子县| 盐城市| 那坡县| 灵寿县| 嘉善县| 长葛市| 淅川县| 西青区| 顺义区| 阳信县| 宜州市| 新绛县| 永福县| 巴中市| 汝州市| 新和县| 霍林郭勒市| 永清县| 乳源| 台东市| 蒙自县| 乌兰浩特市| 化德县| 枣庄市| 罗田县| 八宿县| 吉林省| 临洮县| 高安市| 杂多县| 开阳县| 巴中市| 东港市| 固始县| 胶州市|