一、平台设备platform_device的添加过程
内核: Linux 2.6.25
硬件: TQ2440
函数调用过程如下:
start_kernel
-->rest_init
--> 开启一个线程: kernel_init
--> do_basic_setup
--> do_initcalls(); //for循环将所有的__initcall都调用一遍包括smdk2440_machine_init
--> customize_machine // 即 . initcall3 . init在do_initcalls中被调用
--> init_machine即smdk2440_machine_init
--> platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices)); //终于找到了
1. 1 下面从do_initcalls开始分析, 在init/main.c中
其中, 在
arch/arm/kernel/vmlinux.lds.S
中定义了__initcall_start 与 __init_call_end
initcall3.init的定义如下:
1.3 在 arch/arm/mach-s3c440/mach-smdk2440.c中定义了,函数指针init_machine为smdk2440_machine_init
所以此时就调用smdk2440_machine_init函数: platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices));
1.4 在 arch/arm/mach-s3c440/mach-smdk2440.c中定义了所有的smdk2440_devices
smdk2440_devices[] 是一个struct platform_device数组
├─ s3c_device_usb //每一个platform_device又包含了一个struct resource
├─ s3c_lcd └── struct resource
└─ s3c_device_iis
在 arch/arm/plat-s3c24xx/devs.c中定义了s3c_device
二、platform_driver的添加过程
内核: Linux 2.6.25
硬件: TQ2440
函数调用过程如下:
start_kernel
-->rest_init
--> 开启一个线程: kernel_init
--> do_basic_setup
--> do_initcalls(); //for循环将所有的__initcall都调用一遍包括smdk2440_machine_init
--> customize_machine // 即 . initcall3 . init在do_initcalls中被调用
--> init_machine即smdk2440_machine_init
--> platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices)); //终于找到了
1. 1 下面从do_initcalls开始分析, 在init/main.c中
- 664 static void __init do_initcalls(void)
- 665 {
- 669 for (call = __initcall_start; call < __initcall_end; call++) { //查找在__initcall_start 与__initcall_end之间的所有函数,并逐个调用(initcall0.init -- initcall7.init)
- ...
- 683 result = (*call)();
- 718 }
- 719
- 720 /* Make sure there is no pending stuff from the initcall sequence */
- 721 flush_scheduled_work();
- 722 }
51 __initcall_start
=
.
;
include/asm-generic/vmlinux.lds.h
其中INITCALLS的定义如下:
- 52 INITCALLS
- 53 __initcall_end = .;
328 #define INITCALLS
\
1.2 其中与平台TQ2440相关的函数smdk2440_machine_init,则是在上述的initcall3.init中调用的.
- 329 *(.initcall0.init) \
- 330 *(.initcall0s.init) \
- 331 *(.initcall1.init) \
- 332 *(.initcall1s.init) \
- 333 *(.initcall2.init) \
- 334 *(.initcall2s.init) \
- 335 *(.initcall3.init) \
- 336 *(.initcall3s.init) \
- 337 *(.initcall4.init) \
- 338 *(.initcall4s.init) \
- 339 *(.initcall5.init) \
- 340 *(.initcall5s.init) \
- 341 *(.initcallrootfs.init) \
- 342 *(.initcall6.init) \
- 343 *(.initcall6s.init) \
- 344 *(.initcall7.init) \
- 345 *(.initcall7s.init)
initcall3.init的定义如下:
- 779 static int __init customize_machine(void)
780 {
781 /* customizes platform devices, or adds new ones */
782 if (init_machine) //如果init_machine不为空指针,则调用init_machine()函数
783 init_machine(); //init_machine函数是在arch/arm/mach-s3c440/mach-smdk2440.c中定义了的
784 return 0;
785 }
786 arch_initcall(customize_machine); //这个宏很重要,下面是分析
-
- include/linux/init.h中
- #define arch_initcall(fn) __define_initcall("3",fn,3) //宏的定义如下
-
- #define __define_initcall(level,fn,id) \
- static initcall_t __initcall_##fn##id __used \
- __attribute__((__section__(".initcall" level ".init"))) = fn
-
- 即:
- static initcall_t __initcall_customize_machine_3 __used \
- __attribute__((__section__(.initcall3.init))) = customize_machine //initcall3.init的调用函数是customize_machine
- 166 static void __init smdk2440_machine_init(void)
167 {
168 s3c24xx_fb_set_platdata(&smdk2440_fb_info);
169
170 platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices));
171 smdk_machine_init();
172 }
173
174 MACHINE_START(S3C2440, "SMDK2440")
175 /* Maintainer: Ben Dooks */
176 .phys_io = S3C2410_PA_UART,
177 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
178 .boot_params = S3C2410_SDRAM_PA + 0x100,
179
180 .init_irq = s3c24xx_init_irq,
181 .map_io = smdk2440_map_io,
182 .init_machine = smdk2440_machine_init,
183 .timer = &s3c24xx_timer,
184 MACHINE_END
1.4 在 arch/arm/mach-s3c440/mach-smdk2440.c中定义了所有的smdk2440_devices
- 151 static struct platform_device *smdk2440_devices[] __initdata = {
152 &s3c_device_usb, // s
153 &s3c_device_lcd,
154 &s3c_device_wdt,
155 &s3c_device_i2c,
156 &s3c_device_iis,
157 };
-
├─ s3c_device_usb //每一个platform_device又包含了一个struct resource
├─ s3c_lcd └── struct resource
└─ s3c_device_iis
在 arch/arm/plat-s3c24xx/devs.c中定义了s3c_device
- 119 static struct resource s3c_usb_resource[] = {
120 [0] = {
121 .start = S3C24XX_PA_USBHOST,
122 .end = S3C24XX_PA_USBHOST + S3C24XX_SZ_USBHOST - 1,
123 .flags = IORESOURCE_MEM,
124 },
125 [1] = {
126 .start = IRQ_USBH,
127 .end = IRQ_USBH,
128 .flags = IORESOURCE_IRQ,
129 }
130 };
131
132 static u64 s3c_device_usb_dmamask = 0xffffffffUL;
133
134 struct platform_device s3c_device_usb = {
135 .name = "s3c2410-ohci",
136 .id = -1,
137 .num_resources = ARRAY_SIZE(s3c_usb_resource),
138 .resource = s3c_usb_resource,
139 .dev = {
140 .dma_mask = &s3c_device_usb_dmamask,
141 .coherent_dma_mask = 0xffffffffUL
142 }
143 };
二、platform_driver的添加过程