1、Linux MTD架构
2、MTD创建设备节点。
3、Register一个MTD设备到MTD子系统。
4、MTD file operation 调用底层驱动。
1、架构图
1、设备节点:/dev下MTD字符设备节点(主设备号为90)
2、MTD设备层:分为MTD字符设备层(mtdchar.c)和MTD块设备层(Mtdblock.c),完成flash的基本操作。
3、MTD原始设备层:MTD原始设备的通用代码(mtdcore.c),(mtdpart.c).其中mtdcore.c中定义了描述mtd设备的核心结构mtdinfo.
4、FLASH硬件驱动层:
/mtd/nand目录,实现了对flash的读写擦校验等动作。
2.MTD创建设备节点
流程:
1)mtdchar.c:
init_mtdchar->register_chrdev(MTD_CHAR_MAJOR, "mtd",&mtd_fops);->cdev_add
2)mtdcore.c:
init_mtd -> ret =class_register(&mtd_class);
3)pxa3xx_nand.c:
add_mtd_partitions->add_mtd_device->device_create(&mtd_class,次设备号)
第一步:MTD设备层。(MTD子系统完成)
register_chrdev注册字符型mtd设备,并添加该设备到内核,主设备号为90。但是此时还未在/dev下形成mtd设备节点。
第二步:MTD原始设备层。(MTD子系统完成)
class_register注册一个mtd类mtd_class,后面再注册mtd设备时会用到该class。
第三步:驱动层。(我们调用接口完成)
在添加MTD设备同时,在原始设备层注册的那个class接口上创建了设备节点。/dev/mtdevent1出现
3.Register到MTD子系统
两种注册方式:
1)直接注册整个flash设备(MTDDevice)到MTD。
ret= add_mtd_device(mtd);
2)分partion添加到mtd_table,并将每个partion当成
一个mtd设备注册到MTD。
if(!(partitions&& num_part > 0))
ret= add_mtd_partitions(mtd, parts, num_part);
T920采用方式二分partion注册到MTD:(我们完成)
Flash的partion分区表在N80.C文件中可以查看:
在pxa3xx_nand.c的pxa3xx_nand_probe中完成:
parse_mtd_partitions()->parse_cmdline_partitions
解析mtd结构中的part成员,并返回partion个数。
add_mtd_partitions()->add_one_partition()
slave->mtd.xxx= master->xxx;
add_mtd_device(&slave->mtd);
从master中获得type,read,write等参数。
并将slave作为一个mtd设备添加到mtd_table.
最后注册设备及创建dev下面的设备节点。
4.MTDFile ops调用底层驱动
文件系统->调用MTD设备层:
Mtdchar.c(字符设备,如NANDFLASH)
init_mtdchar(void)中调用了
register_chrdev(MTD_CHAR_MAJOR,"mtd", &mtd_fops);
最终通过cdev->ops =fops;将文件操作赋给了cdev。
其中mtd_fops中实现了mtd设备的读写及ioctl.
5.T920之NANDFLASH驱动层架构
驱动实现层:pxa3xx_nand.cn80.c
1)通过platform注册pxa3xx_nand设备及驱动。
2)在probe中申请资源及实现chipops操作函数。
3)添加mtd设备到MTD。
1)在N80.C中注册Device。
pxa910_add_nand(&pxa910_device_nand,info, xxx)
其中pxa910_device_nand定义了flash所需要的资源,如IO
资源占用,中断资源占用。(pxa910.c中定义这些资源)
其中info即n80_nand_info,
定义了flash分区信息及是否需要DMA。
(在n80.c中定义这些信息)
在pxa3xx_nand.c中注册flash驱动。
platform_driver_register(&pxa3xx_nand_driver);
在pxa3xx_nand_probe(重要,驱动实现的第一步)
alloc_nand_resource(pdev)分配各种资源,包括pxa910_device_nand定义的资源,然后分配chip函数。
add_mtd_partitions,添加mtd设备到MTD子系统中,与硬件抽象层联系起来了。
6.驱动层之Flash读写操作
问题:nand_chip(nandflash的描述符)的读写操作是怎么和MTD的读写操作联系起来的呢?
1)probe->调用nand_scan()->scan_tail;
使用mtd->read= nand_read;这里和mtd挂钩。
2)在nand_read实现中又调用了nand_do_read_ops(mtd,from, &chip->ops);这里和nand_chip联系起来了。
PXA920之NANDFLASH Controller介绍:
NDCR寄存器:nandflash control register
NDTR寄存器: nandflash timing register
NDSR寄存器: nandflash state register
NDCB寄存器: nandflash controller buffer
NDDB寄存器: nandflash data buffer
我们就是对这些寄存器操作来完成通过BB的FLASH控制器操作flash的读写。
T920之NANDFLASH读写控制:NANDFLASH Controller
MTD file ops/MTD层
->nand_do_read_ops
->chip->cmdfunc(mtd,NAND_CMD_READ0, 0x00, page);
/驱动层
->chip->ecc.read_page()
->pxa3xx_read_page
->pxa3xx_nand_cmdfunc对寄存器操作
->中断到,代表对flash控制器的操作完成。
->start_data_dma进行数据读写。
1、pxa3xx_nand_cmdfunc发送命令、发送数据、读写数据。
作用:
对NANDFLASH 控制器的相关寄存器操作,
填充命令,如读,编程,擦除,还有数据。
1)重置timing。
2)写控制命令池。
3)清命令缓冲区。
4)设置地址及数据及传输方式。
5)初始化一个完成量。
6)中断到,运行ND_RUN写寄存器。
1、pxa3xx_nand_transaction传输数据
判断是否支持DMA?
YES:start_data_dma将buffer地址映射到dma缓冲区。
NO:handle_data_pio直接使用__raw_writesl读写映射到用户空间的io寄存器nand->mmio_base。
2、读一个byte,word。
无论是DMA或者IO方式:数据都采用page方式放到了
nand->data_buff中,所以当需要读取一个byte时,只需在
该buffer中取一个字节即可。
读一个字:
retval=
*((u16*)(nand->data_buff+nand->buf_start));