ARM-Linux驱动--MTD驱动分析


主机:Gentoo Linux 11.2 with linux kernel 3.0.6

硬件平台:FL2440(S3C2440)with linux kernel 2.6.35

MTD(memory technology device内存技术设备) 在硬件和文件系统层之间的提供了一个抽象的接口,MTD是用来访问内存设备(如:ROM、flash)的中间层,它将内存设备的共有特性抽取出来,从而使增加新的内存设备驱动程序变得更简单。MTD的源代码都在/drivers/mtd目录中。

MTD中间层细分为四层,按从上到下依次为:设备节点、MTD设备层、MTD原始设备层和硬件驱动层。MTD中间层层次结构图如下:


从上图可以看出,原始设备是MTD字符设备和MTD块设备的抽象。

MTD设备层、MTD原始设备层和Flash硬件驱动层之间的接口关系如下图:


下面首先分析下MTD原始层设备

1、mtd_info数据结构

[cpp]
  1. struct mtd_info {  
  2.     u_char type;//内存技术类型,例如MTD_RAM,MTD_ROM,MTD_NORFLASH,MTD_NAND_FLASH,MTD_PEROM等   
  3.     uint32_t flags;//标志位   
  4.     uint64_t size;   // Total size of the MTD//MTD设备的大小   
  5.   
  6.     /* "Major" erase size for the device. Naïve users may take this 
  7.      * to be the only erase size available, or may use the more detailed 
  8.      * information below if they desire 
  9.      */  
  10.     uint32_t erasesize;//最小的擦除块大小   
  11.     /* Minimal writable flash unit size. In case of NOR flash it is 1 (even 
  12.      * though individual bits can be cleared), in case of NAND flash it is 
  13.      * one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR 
  14.      * it is of ECC block size, etc. It is illegal to have writesize = 0. 
  15.      * Any driver registering a struct mtd_info must ensure a writesize of 
  16.      * 1 or larger. 
  17.      */  
  18.     uint32_t writesize;//编程块大小   
  19.   
  20.     uint32_t oobsize;   // Amount of OOB data per block (e.g. 16)//oob(Out of band)块大小   
  21.     uint32_t oobavail;  // Available OOB bytes per block//每块的可用的oob字节   
  22.   
  23.     /* 
  24.      * If erasesize is a power of 2 then the shift is stored in 
  25.      * erasesize_shift otherwise erasesize_shift is zero. Ditto writesize. 
  26.      */  
  27.     unsigned int erasesize_shift;  
  28.     unsigned int writesize_shift;  
  29.     /* Masks based on erasesize_shift and writesize_shift */  
  30.     unsigned int erasesize_mask;  
  31.     unsigned int writesize_mask;  
  32.   
  33.     // Kernel-only stuff starts here.   
  34.     const char *name;  
  35.     int index;  
  36.   
  37.     /* ecc layout structure pointer - read only ! */  
  38.     struct nand_ecclayout *ecclayout;//eec布局结构   
  39.   
  40.     /* Data for variable erase regions. If numeraseregions is zero, 
  41.      * it means that the whole device has erasesize as given above. 
  42.      */  
  43.     int numeraseregions;//擦除区域个数,通常为1   
  44.     struct mtd_erase_region_info *eraseregions;//擦除区域的区域信息地址   
  45.   
  46.     /* 
  47.      * Erase is an asynchronous operation.  Device drivers are supposed 
  48.      * to call instr->callback() whenever the operation completes, even 
  49.      * if it completes with a failure. 
  50.      * Callers are supposed to pass a callback function and wait for it 
  51.      * to be called before writing to the block. 
  52.      */  
  53.     int (*erase) (struct mtd_info *mtd, struct erase_info *instr);//函数指针,erase函数的功能是将一个erase_info加入擦除队列   
  54.   
  55.     /* This stuff for eXecute-In-Place */  
  56.     /* phys is optional and may be set to NULL */  
  57.     int (*point) (struct mtd_info *mtd, loff_t from, size_t len,  
  58.             size_t *retlen, void **virt, resource_size_t *phys);//point函数功能是允许片内执行(XIP)   
  59.   
  60.     /* We probably shouldn't allow XIP if the unpoint isn't a NULL */  
  61.     void (*unpoint) (struct mtd_info *mtd, loff_t from, size_t len);//unpoint函数与point函数相反,是禁止片内执行(XIP)   
  62.   
  63.     /* Allow NOMMU mmap() to directly map the device (if not NULL) 
  64.      * - return the address to which the offset maps 
  65.      * - return -ENOSYS to indicate refusal to do the mapping 
  66.      */  
  67.     //如果不是NULL,则允许无MMU单元的地址映射,返回偏移地址   
  68.     unsigned long (*get_unmapped_area) (struct mtd_info *mtd,  
  69.                         unsigned long len,  
  70.                         unsigned long offset,  
  71.                         unsigned long flags);  
  72.   
  73.     /* Backing device capabilities for this device 
  74.      * - provides mmap capabilities 
  75.      */  
  76.     struct backing_dev_info *backing_dev_info;  
  77.   
  78.     //MTD设备的读写函数   
  79.     int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);  
  80.     int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);  
  81.   
  82.     /* In blackbox flight recorder like scenarios we want to make successful 
  83.        writes in interrupt context. panic_write() is only intended to be 
  84.        called when its known the kernel is about to panic and we need the 
  85.        write to succeed. Since the kernel is not going to be running for much 
  86.        longer, this function can break locks and delay to ensure the write 
  87.        succeeds (but not sleep). */  
  88.   
  89.     int (*panic_write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);  
  90.       
  91.     //用于MTD设备的OBB数据读写   
  92.     int (*read_oob) (struct mtd_info *mtd, loff_t from,  
  93.              struct mtd_oob_ops *ops);  
  94.     int (*write_oob) (struct mtd_info *mtd, loff_t to,  
  95.              struct mtd_oob_ops *ops);  
  96.   
  97.     /* 
  98.      * Methods to access the protection register area, present in some 
  99.      * flash devices. The user data is one time programmable but the 
  100.      * factory data is read only. 
  101.      */  
  102.     int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);  
  103.     int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);  
  104.     int (*get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);  
  105.     int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);  
  106.     int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);  
  107.     int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len);  
  108.   
  109.     /* kvec-based read/write methods. 
  110.        NB: The 'count' parameter is the number of _vectors_, each of 
  111.        which contains an (ofs, len) tuple. 
  112.     */  
  113.     int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen);  
  114.   
  115.     /* Sync */  
  116.     //MTD设备的同步函数   
  117.     void (*sync) (struct mtd_info *mtd);  
  118.   
  119.     /* Chip-supported device locking */  
  120.     //芯片的加锁和解锁   
  121.     int (*lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);  
  122.     int (*unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);  
  123.   
  124.     /* Power Management functions */  
  125.     //支持电源管理函数   
  126.     int (*suspend) (struct mtd_info *mtd);  
  127.     void (*resume) (struct mtd_info *mtd);  
  128.   
  129.     /* Bad block management functions */  
  130.     //坏块管理函数   
  131.     int (*block_isbad) (struct mtd_info *mtd, loff_t ofs);  
  132.     int (*block_markbad) (struct mtd_info *mtd, loff_t ofs);  
  133.   
  134.     struct notifier_block reboot_notifier;  /* default mode before reboot */  
  135.   
  136.     /* ECC status information */  
  137.     struct mtd_ecc_stats ecc_stats;//ECC状态信息   
  138.     /* Subpage shift (NAND) */  
  139.     int subpage_sft;  
  140.   
  141.     void *priv;//私有数据指针   
  142.   
  143.     struct module *owner;  
  144.     struct device dev;  
  145.     int usecount;//记录用户的个数   
  146.   
  147.     /* If the driver is something smart, like UBI, it may need to maintain 
  148.      * its own reference counting. The below functions are only for driver. 
  149.      * The driver may register its callbacks. These callbacks are not 
  150.      * supposed to be called by MTD users */  
  151.     //驱动回调函数   
  152.     int (*get_device) (struct mtd_info *mtd);  
  153.     void (*put_device) (struct mtd_info *mtd);  
  154. };  
2、mtd_part结构体信息

[cpp]
  1. /* Our partition linked list */  
  2. static LIST_HEAD(mtd_partitions);//分区链表  

[cpp]
  1. /* Our partition node structure */  
  2. //分区结构信息   
  3. struct mtd_part {  
  4.     struct mtd_info mtd;//mtd_info数据结构,会被加入mtd_table中   
  5.     struct mtd_info *master;//该分区的主分区   
  6.     uint64_t offset;//该分区的偏移地址   
  7.     struct list_head list;//分区链表   
  8. };  
3、mtd_partition描述mtd具体分区结构

[cpp]
  1. /* 
  2.  * Partition definition structure: 
  3.  * 
  4.  * An array of struct partition is passed along with a MTD object to 
  5.  * add_mtd_partitions() to create them. 
  6.  * 
  7.  * For each partition, these fields are available: 
  8.  * name: string that will be used to label the partition's MTD device. 
  9.  * size: the partition size; if defined as MTDPART_SIZ_FULL, the partition 
  10.  *  will extend to the end of the master MTD device. 
  11.  * offset: absolute starting position within the master MTD device; if 
  12.  *  defined as MTDPART_OFS_APPEND, the partition will start where the 
  13.  *  previous one ended; if MTDPART_OFS_NXTBLK, at the next erase block. 
  14.  * mask_flags: contains flags that have to be masked (removed) from the 
  15.  *  master MTD flag set for the corresponding MTD partition. 
  16.  *  For example, to force a read-only partition, simply adding 
  17.  *  MTD_WRITEABLE to the mask_flags will do the trick. 
  18.  * 
  19.  * Note: writeable partitions require their size and offset be 
  20.  * erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK). 
  21.  */  
  22.   
  23. struct mtd_partition {  
  24.     char *name;         /* identifier string 分区名*/  
  25.     uint64_t size;          /* partition size 分区大小*/  
  26.     uint64_t offset;        /* offset within the master MTD space 偏移地址*/  
  27.     uint32_t mask_flags;        /* master MTD flags to mask out for this partition */  
  28.     struct nand_ecclayout *ecclayout;   /* out of band layout for this partition (NAND only)*/  
  29. };  
下篇分析MTD设备基本管理
  • 1
  • 2
  • 3
  • 下一页

相关内容