完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
本期决定做同是cortex-a8系列的TQ210开发板的技术分享。本期是关于TQ210开发板的Nand flash驱动编写,可能源码部分会比较多,本文由博主girlkoo编写,感谢他的分享。
|
|
相关推荐
1个回答
|
|
跟裸机程序一样,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 nf***lk; 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 |= (1《《1); } else{ s5p_nand_regs-》nfcont &= ~(1《《1); } } 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 = (3《《12)|(5《《8)|(3《《4)|(1《《1); 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”); |
|
|
|
只有小组成员才能发言,加入小组>>
702 浏览 0 评论
1111 浏览 1 评论
2476 浏览 5 评论
2810 浏览 9 评论
移植了freeRTOS到STMf103之后显示没有定义的原因?
2654 浏览 6 评论
使用eim外接fpga可是端口一点反应都没有有没有大哥指点一下啊
656浏览 9评论
651浏览 7评论
请教大神怎样去解决iMX6Q在linux3.0.35内核上做AP失败的问题呢
785浏览 6评论
632浏览 5评论
672浏览 5评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-24 15:10 , Processed in 0.982573 second(s), Total 80, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号