NAND驱动初始化分析
一. 版本说明
代码分析基于龙芯2K1000平台,内核版本为3.10。
二. NAND驱动初始化分析
龙芯平台的NAND驱动初始化代码入口在 drivers/mtd/nand/ls-nand.c
文件中,通过 module_init()
向内核注册初始化函数 ls_nand_init()
。
ls_nand_init()
负责注册平台驱动:
static int __init ls_nand_init(void)
{
pr_info("%s driver initializing\n", DRIVER_NAME);
return platform_driver_register(&ls_nand_driver);
}
内核启动时,将调用注册的probe回调进行驱动初始化,probe函数的关键代码分析如下:
static int ls_nand_probe(struct platform_device *pdev)
{
struct ls2k_nand_plat_data *pdata;
struct mtd_part_parser_data ppdata;
struct ls_nand_info *info;
struct nand_chip *this;
struct mtd_info *mtd;
struct resource *r;
...
//从设备树中获取DMA信息等
...
pdata = devm_kzalloc(&pdev->dev,
sizeof(struct ls2k_nand_plat_data),
GFP_KERNEL); //为ls2k_nand_plat_data结构体分配存储空间
//设置相关参数
pdata->chip_ver = LS2K_VER3;
pdata->cs = 0;
pdata->csrdy = 0x88442200;
pdata->nr_parts = data;
pdata->enable_arbiter = 1;
mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct ls_nand_info),
GFP_KERNEL); //为mtd_info、ls_nand_info结构体分配空间
//设置相关参数
info = (struct ls_nand_info *)(&mtd[1]);
info->pdev = pdev;
info->chip_version = pdata->chip_ver;
info->cs = pdata->cs;
info->csrdy = pdata->csrdy;
...
...
//获取并保存控制器及DMA的地址
...
ret = ls_nand_init_buff(info); //初始化DMA Buffer
irq = platform_get_irq(pdev, 0); //获取中断号
info->irq = irq;
ls_nand_init_mtd(mtd, info); //**初始化NAND操作回调及ECC,详细分析1
ls_nand_init_info(info)