1.添加gpmc平台设备(board_am335xevm.c)
驱动入口文件board_am335xevm.c -> evm_nand_init() -> omap_init_gpmc() -> omap_device_build() -> omap_device_build_ss() -> omap_device_register() -> platform_device_add(struct platform_device *pdev) -> device_add(struct device *dev)
添加平台设备最终的目的是把platform_device 结构体中的dev添加到设备链表中去
平台设备的名称是"omap-gpmc"
platform_device中platform_data的生成:
在board_am335xevm.c中,和NAND有关的信息有am335x_nand_partitions结构体,记录了NAND的分区,am335x_nand_timings结构体记录了NAND的时序,这些信息被保存在一个gpmc_devices_info结构体中,在omap_device.c中的omap_device_build_ss函数会调用platform_device_add_data函数,最终这些信息被封装在设备链表platform_device->dev.platform_data中.platform_data是一个void类型的指针
平台资源resource的注册:
在board_am335xevm.c -> evm_nand_init() -> omap_init_gpmc()中调用omap_hwmod_lookup函数,用"gpmc"这个name去寻找资源,很明显这又是一个链表,在am33xx_gpmc_hwmod中找到.name = "gpmc",在omap_hwmod_33xx_data.c中找到omap_hwmod_register(am33xx_hwmods) 这个函数把所有的hwmod链接到一个叫omap_hwmod_list的链表中,而调用omap_hwmod_register的函数am33xx_hwmod_init又在board_am335xevm.c中被调用,从而完成了硬件模块的注册。平台资源在omap_hwmod_33xx_data.c的omap_hwmod am33xx_gpmc_hwmod中
platform_device中resourc的生成:
在上一步中平台资源被注册,接下来我们需要那些资源使用.name成员查找即可。在board_am335xevm.c -> evm_nand_init() -> omap_init_gpmc() -> omap_hwmod_lookup(name) -> _lookup(name) -> list_for_each_entry(temp_oh, &omap_hwmod_list, node),list_for_each_entry遍历omap_hwmod_list链表找到name匹配的项,结果omap_hwmod * oh是omap_hwmod_lookup(name)的返回值,接下来调用omap_device_build()->omap_device_build_ss()->omap_device_alloc(),在omap_device.c中调用omap_device_fill_resources和platform_device_add_resources将resources添加到platform_device->resource中。
2.gpmc的驱动(gpmc.c)
在gpmc.c中定义了platform_driver gpmc_driver结构体 ,.name = omap-gpmc,如果之前添加过gpmc的平台设备,.name匹配,gpmc_driver结构体中的gpmc_probe会执行,gpmc_probe传入的platform_device结构体是gpmc_driver中的.name与设备链表匹配的结果。
在gpmc_probe中,首先把platform_device中的空指针platform_data还原成gpmc_devices_info,然后从platform_device的resource中获取GPMC硬件信息,然后将GPMC的硬件信息传到platform_device->dev->p->driver_data中,然后遍历片选,从寄存器中读出基地址和大小写到gpmc->cs_mem[cs](实际上是传到了platform_device->dev->p->driver_data中),然后初始化NAND,初始化时传入一个omap_nand_platform_data类型的参数就是evm_nand_init函数中的gpmc_device[0].pdata(TM绕了这么大一圈,有意思么)
3.添加elm平台设备(board_am335xevm.c)
与添加gpmc平台设备类似,把elm模块的platform_device 结构体中的dev添加到设备链表中去,但elm平台设备没有platform_device->dev.platform_data,只有platform_device->resource
平台设备的名称是"omap2_elm"
平台资源resource的注册:
在board_am335xevm.c -> evm_nand_init() -> omap_init_gpmc()中调用omap_hwmod_lookup函数,用"elm"这个name去寻找资源,平台资源在omap_hwmod_33xx_data.c的omap_hwmod am33xx_elm_hwmod中
4.elm驱动(omap_elm.c)
5.gpmc-nand平台设备 (gpmc-nand.c)
在gpmc的驱动中,gpmc_probe会调用gpmc_nand_init函数,参数就是evm_nand_init中的gpmc_device[0].pdata,gpmc_nand_init函数中首先检查CS,请求CS,设置总线时序,然后将evm_nand_init中的gpmc_device[0].pdata填充到平台设备中,同时指定suspend和resume函数,然后分配CS的寻址,最后注册平台设备,平台设备的名字叫"omap2-nand"
6.gpmc-nand驱动(omap2.c)
平台驱动的名字叫"omap2-nand"
首先看omap_nand_probe函数:
pdata = pdev->dev.platform_data;
pdata 就等于evm_nand_init中的gpmc_device[0].pdata