linux2.6.28 MTD 内存技术设备(块设备)platform driver源码分析
//////////////////////drivers/mtd/nand/s3c_nand.cmodule_init(s3c_nand_init);//模块初始化static int __init s3c_nand_init(void){printk(“S3C NAND Driver, © 2008 Samsung Electronics\n”);platform_driver_register(s3c6400_nand_driver);platform_driver_register(s3c6410_nand_driver);}////////////drivers/mtd/nand/s3c_nand.cplatform平台总线驱动结构体static struct platform_driver s3c6410_nand_driver {.probe s3c6410_nand_probe,.remove s3c_nand_remove,.suspend s3c_nand_suspend,.resume s3c_nand_resume,.driver {.name “s3c6410-nand”,.owner THIS_MODULE,},};////////////drivers/mtd/nand/s3c_nand.cstatic int s3c6410_nand_probe(struct platform_devicedev){return s3c_nand_probe(dev, TYPE_S3C6410);}///////////////////////////////////////////////////drivers/mtd/nand/s3c_nand.c/s3c_nand_probe*called by device layer when it finds a device matchingone our driver can handled. This code checks to see ifit can allocate all necessary resources then calls thenand layer to look for devices*///设备 和 驱动匹配到 后执行static int s3c_nand_probe(struct platform_device *pdev, enum s3c_cpu_type cpu_type){//在Mach-smdk6410.c (linux2.6.28\arch\arm\mach-s3c6410)文件中有个函数smdk6410_machine_init//s3c_device_nand.dev.platform_data s3c_nand_mtd_part_info; nand有关struct s3c_nand_mtd_info *plat_info pdev-dev.platform_data;struct mtd_partition *partition_info (struct mtd_partition *)plat_info-partition;struct nand_chip *nand;struct resource *res;int err 0;int ret 0;int i, j, size;#if defined(CONFIG_MTD_NAND_S3C_HWECC)struct nand_flash_dev *type NULL;u_char tmp;#endif/* get the clock source and enable it */ s3c_nand.clk clk_get(pdev-dev, nand); if (IS_ERR(s3c_nand.clk)) { dev_err(pdev-dev, failed to get clock); err -ENOENT; goto exit_error; } clk_enable(s3c_nand.clk); /* allocate and map the resource *///得到I/O内存资源/* currently we assume we have the one resource */res pdev-resource;size res-end - res-start 1;//I/O内存资源申请s3c_nand.area request_mem_region(res-start, size, pdev-name);if (s3c_nand.area NULL) { dev_err(pdev-dev, cannot reserve register region\n); err -ENOENT; goto exit_error; } s3c_nand.cpu_type cpu_type; s3c_nand.device pdev-dev;//将一个IO地址空间映射到内核的虚拟地址空间上去便于访问。s3c_nand.regs ioremap(res-start, size);if (s3c_nand.regs NULL) { dev_err(pdev-dev, cannot reserve register region\n); err -EIO; goto exit_error; } /* allocate memory for MTD device structure and private data */ s3c_mtd kmalloc(sizeof(struct mtd_info) sizeof(struct nand_chip), GFP_KERNEL); if (!s3c_mtd) { printk(Unable to allocate NAND MTD dev structure.\n); return -ENOMEM; } /* Get pointer to private data *///kmalloc(sizeof(struct mtd_info) sizeof(struct nand_chip), GFP_KERNEL); 跳过sizeof(struct mtd_info)个字节nand (struct nand_chip *) (s3c_mtd[1]);/* Initialize structures */ memset((char *) s3c_mtd, 0, sizeof(struct mtd_info)); memset((char *) nand, 0, sizeof(struct nand_chip)); /* Link the private data with the MTD structure */ s3c_mtd-priv nand; for (i 0; i plat_info-chip_nr; i) {//上面s3c_nand.regs ioremap(res-start, size); 所以是nand的基地址////#define S3C_NFDATA S3C2410_NFREG(0x10)图片nand-IO_ADDR_R (char *)(s3c_nand.regs S3C_NFDATA); nand-IO_ADDR_W (char *)(s3c_nand.regs S3C_NFDATA); nand-cmd_ctrl s3c_nand_hwcontrol; nand-dev_ready s3c_nand_device_ready; nand-scan_bbt s3c_nand_scan_bbt; nand-options 0;#if defined(CONFIG_MTD_NAND_S3C_CACHEDPROG)nand-options | NAND_CACHEPRG;#endif#if defined(CONFIG_MTD_NAND_S3C_HWECC)nand-ecc.mode NAND_ECC_HW;nand-ecc.hwctl s3c_nand_enable_hwecc;nand-ecc.calculate s3c_nand_calculate_ecc;nand-ecc.correct s3c_nand_correct_data;s3c_nand_hwcontrol(0, NAND_CMD_READID, NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); s3c_nand_hwcontrol(0, 0x00, NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE); s3c_nand_hwcontrol(0, 0x00, NAND_NCE | NAND_ALE); s3c_nand_hwcontrol(0, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); s3c_nand_device_ready(0); tmp readb(nand-IO_ADDR_R); /* Maf. ID */ 制造商ID tmp readb(nand-IO_ADDR_R); /* Device ID */设备ID for (j 0; nand_flash_ids[j].name ! NULL; j) { if (tmp nand_flash_ids[j].id) { type nand_flash_ids[j]; break; } } if (!type) { printk(Unknown NAND Device.\n); goto exit_error; } nand-cellinfo readb(nand-IO_ADDR_R); /* the 3rd byte */ tmp readb(nand-IO_ADDR_R); /* the 4th byte */ if (!type-pagesize) { if (((nand-cellinfo 2) 0x3) 0) { nand_type S3C_NAND_TYPE_SLC; nand-ecc.size 512; nand-ecc.bytes 4; if ((1024 (tmp 0x3)) 512) { nand-ecc.read_page s3c_nand_read_page_1bit; nand-ecc.write_page s3c_nand_write_page_1bit; nand-ecc.read_oob s3c_nand_read_oob_1bit; nand-ecc.write_oob s3c_nand_write_oob_1bit; nand-ecc.layout s3c_nand_oob_64; } else { nand-ecc.layout s3c_nand_oob_16; } } else { nand_type S3C_NAND_TYPE_MLC; nand-options | NAND_NO_SUBPAGE_WRITE; /* NOP 1 if MLC */ nand-ecc.read_page s3c_nand_read_page_4bit; nand-ecc.write_page s3c_nand_write_page_4bit; nand-ecc.size 512; nand-ecc.bytes 8; /* really 7 bytes */ nand-ecc.layout s3c_nand_oob_mlc_64; } } else { nand_type S3C_NAND_TYPE_SLC; nand-ecc.size 512; nand-cellinfo 0; nand-ecc.bytes 4; nand-ecc.layout s3c_nand_oob_16; } printk(S3C NAND Driver is using hardware ECC.\n);#elsenand-ecc.mode NAND_ECC_SOFT;//软件ECCprintk(“S3C NAND Driver is using software ECC.\n”);#endifif (nand_scan(s3c_mtd, 1)) {//以mtd_info为参数调用nand_scan()函数探测NAND Flash的存在ret -ENXIO;goto exit_error;}/* Register the partitions *///如果要分区则以mtd_info和mtd_partition为参 数调用add_mtd_partitions()添加分区信息add_mtd_partitions(s3c_mtd, partition_info, plat_info-mtd_part_nr);}pr_debug(initialized ok\n); return 0;exit_error:kfree(s3c_mtd);return ret;}/////////////////////////////drivers/mtd/nand/s3c_nand.cstruct s3c_nand_info {/* mtd info */struct nand_hw_control controller;struct s3c_nand_mtd_info *mtds;struct s3c2410_platform_nand *platform;/* device info */ struct device *device; struct resource *area; struct clk *clk; void __iomem *regs; void __iomem *sel_reg; int sel_bit; int mtd_count; enum s3c_cpu_type cpu_type;};static struct s3c_nand_info s3c_nand;
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2430150.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!