MTD原始设备与NANDFLASH硬件驱动交互
好久没写博客了,今天再次分析NANDFLASH驱动程序,每一次读源码总有一点的收获 1、首先从入口函数开始
probe函数将是我们遇到的第一个与具体硬件打交道,同时也相对复杂的函数对于很多外设的driver来说,只要能成功实现probe函数,那基本上完成这个外设的driver也就成功了一多半,基于MTD的NAND driver就是一个典型的例子。稍后就可以看到,在NAND driver的probe函数中,就已经涉及到了对NAND芯片的读写。
?
在基于MTD的NAND driver的probe函数中,主要可以分为两部分内容,其一是与很多外设driver类似的一些工作,如申请地址,中断,DMA等资源,kzalloc及初始化一些结构体,分配DMA用的内存等等;其二就是与MTD相关的一
static int s3c24xx_nand_probe(struct platform_device *pdev) static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,?? ??? ??? ??? ??? struct s3c2410_nand_mtd *nmtd,?? ??? ??? ??? ??? struct s3c2410_nand_set *set) { ?? ?struct nand_chip *chip = &nmtd->chip; ?? ?void __iomem *regs = info->regs; ?? ?chip->write_buf??? = s3c2410_nand_write_buf; ?? ?chip->read_buf???? = s3c2410_nand_read_buf; ?? ?chip->select_chip? = s3c2410_nand_select_chip; ?? ?chip->chip_delay?? = 50; ?? ?chip->priv?? ??? = nmtd; ?? ?chip->options?? ??? = set->options; ?? ?chip->controller?? = &info->controller; ?? ?switch (info->cpu_type) { ?? ?case TYPE_S3C2410: ?? ??? ?chip->IO_ADDR_W = regs + S3C2410_NFDATA; ?? ??? ?info->sel_reg?? = regs + S3C2410_NFCONF; ?? ??? ?info->sel_bit?? ?= S3C2410_NFCONF_nFCE; ?? ??? ?chip->cmd_ctrl? = s3c2410_nand_hwcontrol; ?? ??? ?chip->dev_ready = s3c2410_nand_devready; ?? ??? ?break; ?? ?case TYPE_S3C2440: ?? ??? ?chip->IO_ADDR_W = regs + S3C2440_NFDATA; ?? ??? ?info->sel_reg?? = regs + S3C2440_NFCONT; ?? ??? ?info->sel_bit?? ?= S3C2440_NFCONT_nFCE; ?? ??? ?chip->cmd_ctrl? = s3c2440_nand_hwcontrol; ?? ??? ?chip->dev_ready = s3c2440_nand_devready; ?? ??? ?chip->read_buf? = s3c2440_nand_read_buf; ?? ??? ?chip->write_buf?? ?= s3c2440_nand_write_buf; ?? ??? ?break; ?? ?case TYPE_S3C2412: ?? ??? ?chip->IO_ADDR_W = regs + S3C2440_NFDATA; ?? ??? ?info->sel_reg?? = regs + S3C2440_NFCONT; ?? ??? ?info->sel_bit?? ?= S3C2412_NFCONT_nFCE0; ?? ??? ?chip->cmd_ctrl? = s3c2440_nand_hwcontrol; ?? ??? ?chip->dev_ready = s3c2412_nand_devready; ?? ??? ?if (readl(regs + S3C2410_NFCONF) & S3C2412_NFCONF_NANDBOOT) ?? ??? ??? ?dev_info(info->device,"System booted from NANDn"); ?? ??? ?break; ? ?? ?} ?? ?chip->IO_ADDR_R = chip->IO_ADDR_W; ?? ?nmtd->info?? ??? = info; ?? ?nmtd->mtd.priv?? ??? = chip; ?? ?nmtd->mtd.owner??? = THIS_MODULE; ?? ?nmtd->set?? ??? = set; ?? ?if (hardware_ecc) { ?? ??? ?chip->ecc.calculate = s3c2410_nand_calculate_ecc; ?? ??? ?chip->ecc.correct?? = s3c2410_nand_correct_data; ?? ??? ?chip->ecc.mode?? ???? = NAND_ECC_HW; ?? ??? ?switch (info->cpu_type) { ?? ??? ?case TYPE_S3C2410: ?? ??? ??? ?chip->ecc.hwctl?? ???? = s3c2410_nand_enable_hwecc; ?? ??? ??? ?chip->ecc.calculate = s3c2410_nand_calculate_ecc; ?? ??? ??? ?break; ?? ??? ?case TYPE_S3C2412: ? ?? ??? ??? ?chip->ecc.hwctl???? = s3c2412_nand_enable_hwecc; ? ?? ??? ??? ?chip->ecc.calculate = s3c2412_nand_calculate_ecc; ?? ??? ??? ?break; ?? ??? ?case TYPE_S3C2440: ? ?? ??? ??? ?chip->ecc.hwctl???? = s3c2440_nand_enable_hwecc; ? ?? ??? ??? ?chip->ecc.calculate = s3c2440_nand_calculate_ecc; ?? ??? ??? ?break; ?? ??? ?} ?? ?} else { ?? ??? ?chip->ecc.mode?? ???? = NAND_ECC_SOFT; ?? ?} ?? ?if (set->ecc_layout != NULL) ?? ??? ?chip->ecc.layout = set->ecc_layout; ?? ?if (set->disable_ecc) ?? ??? ?chip->ecc.mode?? ?= NAND_ECC_NONE; ?? ?switch (chip->ecc.mode) { ?? ?case NAND_ECC_NONE: ?? ??? ?dev_info(info->device,"NAND ECC disabledn"); ?? ??? ?break; ?? ?case NAND_ECC_SOFT: ?? ??? ?dev_info(info->device,"NAND soft ECCn"); ?? ??? ?break; ?? ?case NAND_ECC_HW: ?? ??? ?dev_info(info->device,"NAND hardware ECCn"); ?? ??? ?break; ?? ?default: ?? ??? ?dev_info(info->device,"NAND ECC UNKNOWNn"); ?? ??? ?break; ?? ?} ?? ?/* If you use u-boot BBT creation code,specifying this flag will ?? ? * let the kernel fish out the BBT from the NAND,and also skip the ?? ? * full NAND scan that can take 1/2s or so. Little things... */ ?? ?if (set->flash_bbt) ?? ??? ?chip->options |= NAND_USE_FLASH_BBT | NAND_SKIP_BBTSCAN; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |