一、平台设备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中
-
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 }
其中, 在
arch/arm/kernel/vmlinux.lds.S中定义了__initcall_start 与 __init_call_end
51 __initcall_start
= .;
-
52 INITCALLS
-
53 __initcall_end = .;
include/asm-generic/vmlinux.lds.h其中INITCALLS的定义如下:
328 #define INITCALLS
\
-
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)
1.2 其中与平台TQ2440相关的函数smdk2440_machine_init,则是在上述的initcall3.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
1.3 在 arch/arm/mach-s3c440/mach-smdk2440.c中定义了,函数指针init_machine为smdk2440_machine_init
-
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
所以此时就调用smdk2440_machine_init函数: platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices));
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 };
-
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
-
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的添加过程
阅读(522) | 评论(0) | 转发(0) |