ubuntu 在 R40e 上 還有 Debian 在 Sempron 2600 上

2011年5月12日 星期四

pmic -- regulator & init call sequence

pmic 的 driver 寫在driver/regulator/***.c
其中對外的 function interface 寫在 core.c

其他的 driver 要使用 regulator 的話,要 call core.c 的
regulator_get( ) 取得 regulator 的 ops_function_table。
prototype : struct regulator *regulator_get(struct device *dev, const char *id) 其中的 id 是 string。 就是 regulator 的名子。 regulator module 的 init call 是宣告: core_initcall(regulator_init); core_initcall 宣告在 include/linux/init.h ,有一堆 initcall 宣告: #define pure_initcall(fn) __define_initcall("0",fn,0) #define core_initcall(fn) __define_initcall("1",fn,1) #define core_initcall_sync(fn) __define_initcall("1s",fn,1s) #define postcore_initcall(fn) __define_initcall("2",fn,2) #define postcore_initcall_sync(fn) __define_initcall("2s",fn,2s) #define arch_initcall(fn) __define_initcall("3",fn,3) #define arch_initcall_sync(fn) __define_initcall("3s",fn,3s) #define subsys_initcall(fn) __define_initcall("4",fn,4) #define subsys_initcall_sync(fn) __define_initcall("4s",fn,4s) #define fs_initcall(fn) __define_initcall("5",fn,5) #define fs_initcall_sync(fn) __define_initcall("5s",fn,5s) #define rootfs_initcall(fn) __define_initcall("rootfs",fn,rootfs) #define device_initcall(fn) __define_initcall("6",fn,6) #define device_initcall_sync(fn) __define_initcall("6s",fn,6s) #define late_initcall(fn) __define_initcall("7",fn,7) #define late_initcall_sync(fn) __define_initcall("7s",fn,7s) -- 從這個宣告可以知道 各個 initcall 的執行順序..
driver 中常常用的 : #define __initcall(fn) device_initcall(fn) 還有 #define module_init(x) __initcall(x); .. 所以一般 driver 的 init 是在 device_initcall 時 執行 ..幾乎是最後了。

__define_initcall( ) 是: #define __define_initcall(level,fn,id) \ static initcall_t __initcall_##fn##id __used \ __attribute__((__section__(".initcall" level ".init"))) = fn 所以就是安排在 .initcall?.init section 中。 在 loading script 中有指定: #define INIT_SETUP(initsetup_align) \ . = ALIGN(initsetup_align); \ VMLINUX_SYMBOL(__setup_start) = .; \ *(.init.setup) \ VMLINUX_SYMBOL(__setup_end) = .; #define INITCALLS \ *(.initcallearly.init) \ VMLINUX_SYMBOL(__early_initcall_end) = .; \ *(.initcall0.init) \ *(.initcall0s.init) \ *(.initcall1.init) \ *(.initcall1s.init) \ *(.initcall2.init) \ *(.initcall2s.init) \ *(.initcall3.init) \ *(.initcall3s.init) \ *(.initcall4.init) \ *(.initcall4s.init) \ *(.initcall5.init) \ *(.initcall5s.init) \ *(.initcallrootfs.init) \ *(.initcall6.init) \ *(.initcall6s.init) \ *(.initcall7.init) \ *(.initcall7s.init) #define INIT_CALLS \ VMLINUX_SYMBOL(__initcall_start) = .; \ INITCALLS \ VMLINUX_SYMBOL(__initcall_end) = .; 被放在這個 section 的 function pointer ,在 init/main.c 中,會被一一的呼叫: extern initcall_t __initcall_start[], __initcall_end[], __early_initcall_end[]; static void __init do_initcalls(void) { initcall_t *fn; for (fn = __early_initcall_end; fn < __initcall_end; fn++) do_one_initcall(*fn); /* Make sure there is no pending stuff from the initcall sequence */ flush_scheduled_work(); }


regulator driver 跟一般 driver 不一樣,是 core_init,幾乎是所有 init 最開始的部份..

沒有留言:

標籤

網誌存檔