S3c2410nandflash驱动分析

S3c2410nandflash驱动分析

linux2.6.27

1.平台设备的注册



1.1平台设备的结构体:(.../arch/arm/plat-s3c24xx/devs.c)

struct platform_device s3c_device_nand = {

.name = "s3c2410-nand",

.id = -1,

.num_resources = ARRAY_SIZE(s3c_nand_resource),

.resource = s3c_nand_resource,

};

static struct resource s3c_nand_resource[] = {

[0] = {

.start = S3C2410_PA_NAND,

.end = S3C2410_PA_NAND + S3C24XX_SZ_NAND - 1,

.flags = IORESOURCE_MEM,

}

};

1.2将该结构体添加到所有平台结构的数组中,mach-qt2410这种机器配置为例:

.../arch/arm/mach-s3c2410/mach-qt2410.c

static struct platform_device *qt2410_devices[] __initdata = {

....

&s3c_device_nand,

};

1.3 分区信息

static struct mtd_partition qt2410_nand_part[] = {

[0] = {

.name = "U-Boot",

.size = 0x30000,

.offset = 0,

},

[1] = {

.name = "U-Boot environment",

.offset = 0x30000,

.size = 0x4000,

},

[2] = {

.name = "kernel",

.offset = 0x34000,

.size = SZ_2M,

},

[3] = {

.name = "initrd",

.offset = 0x234000,

.size = SZ_4M,

},

[4] = {

.name = "jffs2",

.offset = 0x634000,

.size = 0x39cc000,

},

};



static struct s3c2410_nand_set qt2410_nand_sets[] = {

[0] = {

.name = "NAND",

.nr_chips = 1,

.nr_partitions = ARRAY_SIZE(qt2410_nand_part),

.partitions = qt2410_nand_part,

},

};

static struct s3c2410_platform_nand qt2410_nand_info = {

.tacls = 20,

.twrph0 = 60,

.twrph1 = 20,

.nr_sets = ARRAY_SIZE(qt2410_nand_sets),

.sets = qt2410_nand_sets,

};

1.4 注册nand平台设备

static void __init qt2410_machine_init(void)

{

// 将分区信息设为平台的平台数据.这样能过平台设备就可以得到分区信息.

s3c_device_nand.dev.platform_data = &qt2410_nand_info;

...

// 注册平台设备.

platform_add_devices(qt2410_devices, ARRAY_SIZE(qt2410_devices));

...

}

这个函数是如何在系统启动时被调用的呢:

内核启动时将运行head.S,再其中将调用.../init/main.c中的start_kernel的函数

asmlinkage void __init start_kernel(void)
{
......
setup_arch(&command_line);
// 1.找到所属的machine_desc,即在arch/arm/mach-s3c2410/qt2410.c中最后定义的一个结构。
// 2.paging_init(&meminfo, mdesc)->devicemaps_init(mdesc)->mdesc->map_io();
// 3.找到该machine_desc定义的初始化函数句柄:
init_arch_irq = mdesc->init_irq;
	system_timer = mdesc->timer;
	init_machine = mdesc->init_machine;
......
init_IRQ();
// 1.初始化了irq_desc数组
// 2.调用了init_arch_irq(),即调用mdesc->init_irq
......
time_init();
// 1.system_timer->init();



}

arch_initcall(customize_machine);
customize_machine(void)->init_machine() 即调用 mdesc->init_machineqt2410_machine_init(void)

start_kernel中将根据bootloader中传递过来MACHINE Id查询到对应的machine_desc,

mach-qt2410.c的最后我们定义了下machine_desc结构:

MACHINE_START(QT2410, "QT2410")

.phys_io = S3C2410_PA_UART,

.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,

.boot_params = S3C2410_SDRAM_PA + 0x100,

.map_io = qt2410_map_io,

.init_irq = s3c24xx_init_irq,

.init_machine = qt2410_machine_init,

.timer = &s3c24xx_timer,

MACHINE_END





2.平台驱动的注册

.../drivers/mtd/nand/s3c2410.c

2.1平台驱动

static struct platform_driver s3c2410_nand_driver = {

.probe = s3c2410_nand_probe,

.remove = s3c2410_nand_remove,

.suspend = s3c24xx_nand_suspend,

.resume = s3c24xx_nand_resume,

.driver = {

.name = "s3c2410-nand",

.owner = THIS_MODULE,

},

};

  1. 2.2 驱动的加载

static int __init s3c2410_nand_init(void)

{

...

return platform_driver_register(&s3c2410_nand_driver);

}

module_init(s3c2410_nand_init);

platform_driver_register的处理过程中,将会在platform总线下注册一个驱动,并且在platform总线下挂有的所有设备中查找名称为"s3c2410-nand"的设备,并调用驱动的probe方法.

2.3 probe方法

static int s3c2410_nand_probe(struct platform_device *dev)

{

return s3c24xx_nand_probe(dev, TYPE_S3C2410);

}

s3c24xx_nand_probe中主要作了以下几个工作:

  1. 创建添充struct s3c2410_nand_info

  2. 创建添充struct s3c2410_nand_mtd[]数组

  3. 创建添充struct mtd_info

  4. 创建添充struct nand_chip

  5. 扫描芯片形成芯片的BBT

  6. 最后调用 add_mtd_partitions注册所有分区.

    最烦锁的是前5.

struct s3c2410_nand_info主要包括一个nand_hw_control,一个struct s3c2410_nand_mtd[]数组,和平台设备指针,物理内存,时钟,配置寄存器,平台数据..

每一个struct s3c2410_nand_mtd包括一个struct mtd_info结构和一个struct nand_chip结构.

四种结构的相互引用关系为:

s3c2410_nand_mtd->info = s3c2410_nand_info

mtd_info->priv = nand_chip

nand_chip->priv = s3c2410_nand_mtd



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值