<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > S5PV210之Nand flash驅(qū)動(dòng)編寫(xiě)

          S5PV210之Nand flash驅(qū)動(dòng)編寫(xiě)

          作者: 時(shí)間:2016-10-15 來(lái)源:網(wǎng)絡(luò) 收藏

          大家好,又到了天嵌【嵌入式分享】的時(shí)間,相對(duì)于前幾期【嵌入式分享】做的主要是TQ335X開(kāi)發(fā)板的技術(shù)分享,本期決定做同是cortex-a8系列的TQ210開(kāi)發(fā)板的技術(shù)分享。本期是關(guān)于TQ210開(kāi)發(fā)板的Nand flash驅(qū)動(dòng)編寫(xiě),可能源碼部分會(huì)比較多,本文由博主girlkoo編寫(xiě),感謝他的分享。

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

          跟裸機(jī)程序一樣,S5PV210(TQ210)的Nand flash模塊跟S3C2440(TQ2440)的Nand flash模塊非常相似,如果不引入ECC,驅(qū)動(dòng)程序的編寫(xiě)也非常簡(jiǎn)單,我是使用的Linux-3.8.6(Linux-3.8.3也一樣)內(nèi)核,驅(qū)動(dòng)的API函數(shù)有些變化,不過(guò)原理是相通的,稍微看一下內(nèi)核源碼并參考下其他平臺(tái)的相關(guān)代碼就可以自己寫(xiě)出Nand flash驅(qū)動(dòng)了,下面是Nand flash驅(qū)動(dòng)的源碼,沒(méi)有啟用ECC,當(dāng)然,你也可以改成軟件ECC,但是我的覺(jué)得既然軟件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;

          //分配驅(qū)動(dòng)相關(guān)結(jié)構(gòu)體

          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;

          }

          //設(shè)置驅(qū)動(dòng)相關(guān)結(jié)構(gòu)體

          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 設(shè)備

          if(nand_scan(s5p_mtd_info, 1)){

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

          goto err_free_info;

          }

          //添加分區(qū)信息

          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);

          上述源碼為嵌入式愛(ài)好者分享,如有更新,請(qǐng)咨詢相關(guān)客服與銷售人員,以便更新與開(kāi)發(fā)。

          操作所使用的硬件:

          TQ210V6開(kāi)發(fā)板



          評(píng)論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();