MTk kernel启动流程

MTk kernel启动流程

late_initcall
所有的__init函数在区段.initcall.init中还保存了一份函数指针,在初始化时内核会通过这些函数指针调用这些__init函数指针,并在整个初始化完成后,释放整个init区段(包括.init.text,.initcall.init等)。
  注意,这些函数在内核初始化过程中的调用顺序只和这里的函数指针的顺序有关,和1)中所述的这些函数本身在.init.text区段中的顺序无关。initcall.init区段分成7个子区段,分别是

.initcall1.init  
.initcall2.init  
.initcall3.init  
.initcall4.init  
.initcall5.init  
.initcall6.init  
.initcall7.init

  当需要把函数fn放到.initcall1.init区段时,只要声明

core_initcall(fn);

  即可。

其他的各个区段的定义方法分别是:

core_initcall(fn) --->.initcall1.init  
postcore_initcall(fn) --->.initcall2.init  
arch_initcall(fn) --->.initcall3.init  
subsys_initcall(fn) --->.initcall4.init  
fs_initcall(fn) --->.initcall5.init  
device_initcall(fn) --->.initcall6.init  
late_initcall(fn) --->.initcall7.init

在内核中,不同的init函数被放在不同的子区段中,因此也就决定了它们的调用顺序。这样也就解决了一些init函数之间必须保证一定的调用顺序的问题。按照include/linux/init.h文件所写的,我在驱动里偿试了这样两种方式:

__define_initcall("7", fn); 
late_initcall(fn);

都可以把我的驱动调整到最后调用。实际上上面两个是一回事:

#define late_initcall(fn)__define_initcall("7", fn)

linux中把initcall分成了若干种类,主要用来区别不同的initcall的调用次序,由于initcall中的调用次序是随机的,所以不能保证某些重要的初始化先运行。分成了以下几个initcall,按执行顺序先后排列:

pure_initcall:最先运行的,不依赖于任何其他初始化函数。
  core_initcall
  core_initcall_sync
  postcore_initcall
  postcore_initcall_sync
  arch_initcall
  arch_initcall_sync
  subsys_initcall
  subsys_initcall_sync
  fs_initcall
  fs_initcall_sync
  rootfs_initcall
  device_initcall
  device_initcall_sync
  late_initcall
  late_initcall_sync。

如:
Kernel/include/linux/init.h

178 #define __define_initcall(level,fn,id)\
179    static initcall_t __initcall_##fn##id __used \
180    __attribute__((__section__(".initcall" level".init"))) = fn
181
182 /*
183 * Early initcalls run before initializing SMP.
184 *
185 * Only for built-in code, not modules.
186 */
187 #define early_initcall(fn)     __define_initcall("early",fn,early)
188
189 /*
190 * A "pure" initcall has no dependencies on anything else, andpurely
191 * initializes variables that couldn't be statically initialized.
192 *
193 * This only exists for built-in code, not for modules.
194 */
195 #define pure_initcall(fn)       __define_initcall("0",fn,0)
196
197 #define core_initcall(fn)       __define_initcall("1",fn,1)
198 #define core_initcall_sync(fn)      __define_initcall("1s",fn,1s)
199 #define postcore_initcall(fn)       __define_initcall("2",fn,2)
200 #define postcore_initcall_sync(fn)  __define_initcall("2s",fn,2s)
201 #define arch_initcall(fn)       __define_initcall("3",fn,3)
202 #define arch_initcall_sync(fn)      __define_initcall("3s",fn,3s)
203 #define subsys_initcall(fn)     __define_initcall("4",fn,4)
204 #define subsys_initcall_sync(fn)    __define_initcall("4s",fn,4s)
205 #define fs_initcall(fn)         __define_initcall("5",fn,5)
206 #define fs_initcall_sync(fn)        __define_initcall("5s",fn,5s)
207 #define rootfs_initcall(fn)    __define_initcall("rootfs",fn,rootfs)
208 #define device_initcall(fn)     __define_initcall("6",fn,6)
209 #define device_initcall_sync(fn)    __define_initcall("6s",fn,6s)
210 #define late_initcall(fn)       __define_initcall("7",fn,7)
211 #define late_initcall_sync(fn)      __define_initcall("7s",fn,7s)

Meditek kernel启动:
platform/mt6592/kernel/core/board.c
board_init()调mt_board_init();

./platform/mt6592/kernel/core/core.c

111 #ifdef MTK_TABLET_PLATFORM
112 MACHINE_START(MT6592,MTK_TABLET_PLATFORM)
113 #else
114 MACHINE_START(MT6592,"MT6592")
115 #endif
116    .atag_offset    = 0x00000100,
117    .map_io         = mt_map_io,
118    .init_irq       = mt_init_irq,
119    .timer          = &mt_timer,
120    .init_machine   = mt_init,
121    .fixup          = mt_fixup,
122    .restart        =arm_machine_restart,
123    .reserve        = mt_reserve,
124 MACHINE_END

kernel/arch/arm/include/asm/mach/arch.h中定义MACHINE_START

#defineMACHINE_START(_type,_name) \
static conststruct machine_desc __mach_desc_##_type \
 __used \
 __attribute__((__section__(".arch.info.init")))= { \
.nr = MACH_TYPE_##_type, \
.name = _name,
 
#defineMACHINE_END \
};

MACHINE_START主要是定义了"structmachine_desc"的类型,放在 section(".arch.info.init"),是初始化数据,Kernel起来之后将被丢弃。

117     .map_io         = mt_map_io,

这里会把一组平台相关的物理地址(比如总线地址、设备基地址)映射到一组固定虚拟地址上,这组虚拟地址在整个内核空间可见

106 void __init mt_map_io(void)
107 {
108    iotable_init(mt_io_desc, ARRAY_SIZE(mt_io_desc));
109 }


     iotable_init定义位于:

Kernel/arch/arm/mm/mmu.c

785  * Create the architecture specific mappings
 786  */
 787 void __init iotable_init(struct map_desc*io_desc, int nr)
 788 {
 789    struct map_desc *md;
 790    struct vm_struct *vm;
 791
 792    if (!nr)
 793        return;
 794
 795    vm = early_alloc_aligned(sizeof(*vm) * nr, __alignof__(*vm));
 796
 797    for (md = io_desc; nr; md++, nr--) {
 798        create_mapping(md, false);
 799        vm->addr = (void *)(md->virtual & PAGE_MASK);
 800        vm->size = PAGE_ALIGN(md->length + (md->virtual &~PAGE_MASK));
 801        vm->phys_addr = __pfn_to_phys(md->pfn);
 802        vm->flags = VM_IOREMAP | VM_ARM_STATIC_MAPPING;
 803        vm->flags |= VM_ARM_MTYPE(md->type);
 804        vm->caller = iotable_init;
 805        vm_area_add_early(vm++);
 806    }
 807 }

118 .init_irq = mt_init_irq,

platform/mt6592/kernel/core/irq.c

1054 void __initmt_init_irq(void)
1055 {
1056     spin_lock_init(&irq_lock);
1057     mt_gic_dist_init();
1058     mt_gic_cpu_init();
1059 }

119 .timer = &mt_timer,

platform/mt6592/kernel/core/tmer.c

50struct sys_timer mt_timer = {
51   .init = mt_timer_init,
52};

121 .fixup = mt_fixup,
platform/mt6592/kernel/core /mt_devs.c
对memory的一个fix。

122     .restart        = arm_machine_restart,

kernel/arch/arm/kernel/process.c

void arm_machine_restart(char mode, const char *cmd)
146 {
147         /* Flush the console to make sure allthe relevant messages make it
148          * out to theconsole drivers */
149        arm_machine_flush_console();  
150   
151         /* Disableinterrupts first */
152        local_irq_disable();
153         local_fiq_disable();
154   
155         /*
156          * Tell the mmsystem that we are going to reboot -
157          * we may need itto insert some 1:1 mappings so that
158          * soft bootworks.
159          */
160         setup_mm_for_reboot();
161   
162         /* When l1 isdisabled and l2 is enabled, the spinlock cannot get the lock,
163          * so we need todisable the l2 as well. by Chia-Hao Hsu
164          */
165         outer_flush_all();
166         outer_disable();
167         outer_flush_all();
168
169         /* Clean andinvalidate caches */
170         flush_cache_all();
171
172         /* Turn offcaching */
173         cpu_proc_fin();
174
175         /* Push out anyfurther dirty data, and ensure cache is empty */
176         flush_cache_all();
177
178         /*
179          * Now call thearchitecture specific reboot code.
180          */
181         arch_reset(mode,cmd);
183         /*
184          * Whoops - thearchitecture was unable to reboot.
185          * Tell the user!
186          */
187         mdelay(1000);
188        printk("Reboot failed -- System halted\n");
189         while (1);
190 }

123 .reserve = mt_reserve,
platform/mt6592/kernel/core /mt_devs.c
主要是对memory的一个预留。
platform/mt6592/kernel/core /mt_devs.c主要实现以下函数:

HW_TP_Init                 

mt_board_init         

is_pmem_range         

mtk_get_max_DRAM_size 

get_phys_offset       

get_text_region       

mt_reserve            

For example1:(led)
在mt_board_init();
/注册设备信息,例如:***/

#if defined(CONFIG_MTK_LEDS)
         retval= platform_device_register(&mt65xx_leds_device);
         if(retval != 0)
                   returnretval;
         printk("bei:deviceLEDS register\n");
#endif
 
static struct platform_device mt65xx_leds_device = {
         .name= "leds-mt65xx",
         .id= -1
}; 

驱动设备匹配如下:匹配driver name :“leds-mt65xx”,
/platform/mt6592/kernel/drivers/leds/leds.c
./kernel/drivers/leds/leds_drv.c

602 static struct platform_drivermt65xx_leds_driver = {
603    .driver     = {
604        .name   ="leds-mt65xx",
605        .owner  = THIS_MODULE,
606    },
607    .probe      = mt65xx_leds_probe,
608    .remove     = mt65xx_leds_remove,
609    //.suspend  = mt65xx_leds_suspend,
610    .shutdown   =mt65xx_leds_shutdown,
611 };

再继续就是进入我们熟悉的probe函数,这里不再赘述!

你可能感兴趣的:(嵌入式)