1. 程式人生 > >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函式,這裡不再贅述!