LinuxがDTSデバイスノードをロードするプロセス(高通一)
ARM:一.起動条件は通常、システム上で電気的に実行されるboot loaderのコードから、boot loaderからlinux kernelにジャンプする最初の命令で実行するには特定の条件が必要です.ここではlinux kernelに入る際に備えなければならない条件について説明します.これは一般的にboot loaderがkernelにジャンプする前に完了する条件です.1.CPUはSVC(supervisor)モードでなければならず、IRQとFIQの割り込みは禁止されている.2.MMU(メモリ管理ユニット)は必ずオフにしなければならない.この場合、仮想アドレスは物理アドレスである.3.データcache(Data cache)はオフであること.命令cache(Instruction cache)は開くことも閉じることもでき、これは強制的な要求がない.5.CPU汎用レジスタ0(r 0)は0でなければならない.6.CPU汎用レジスタ1(r 1)は、ARM Linux machine typeである必要がある(machine typeについては後述).CPU汎用レジスタ2(r 2)は、kernel parameter listの物理アドレス(parameter listはboot loaderによってkernelに渡され、デバイス情報の属性を記述するためのリスト)である必要がある.二.starting kernel KERNEL_RAM_ADDR arch/arm/kernel/head.RAM内のS 0 xc 0008000 kernelの仮想アドレスPAGE_OFFSET include/asm-arm/memeory.h 0 xc 0000000コア空間の開始仮想アドレスTEXT_OFFSET arch/arm/Makefile 0 x 000008000カーネルのRAMにおける開始位置のRAM開始アドレスに対するオフセット
asmlinkage void __init start_kernel(void)-> void __init setup_arch(char **cmdline_p)-> mdesc = setup_machine_fdt(__atags_pointer);//atagsで_pointer取得(devtree=phys_to_virt(dt_phys))void_init unflatten_device_tree(void);
これらの作業はDTSファイルの解析を完了します.グローバルチェーンテーブルallnodesに保存します.その後、boardファイルにシステムが起動すると呼び出される.init_machine、高通プラットフォーム対応はmsm_init().次にof_を呼び出すplatform_populate(….)インタフェース、プラットフォームバスとプラットフォームデバイスをロードします.これで、システムプラットフォーム上のすべての構成済みバスおよびデバイスがシステムに登録されます.注意:dtsiファイル内のすべてのノードが登録されるわけではありません.バスやデバイスを登録するとき、dtsノードの状態を判断します.ノード内のstatus属性が定義されていない場合、またはstatus属性が定義され、値が「ok」または「okay」に設定されている場合、その他の場合はシステムに登録されません.
i 2 cバスを登録するとqup_に呼び出されますi2c_probe()インタフェース.バスリソースを申請し、i 2 cアダプタを追加するためのインタフェース.i 2 cアダプタの追加に成功すると、of_が呼び出されます.i2c_register_デバイス()インタフェース.このインタフェースは、i 2 cバスノードのサブノード(バスにマウントされたi 2 cデバイスノード)を解析し、i 2 cデバイスのアドレス、割り込み番号などのハードウェア情報を取得します.そしてrequest_を呼び出すmodule()デバイス対応のドライバファイルをロードし、i 2 c_を呼び出すnew_デバイス()は、i 2 cデバイスを生成します.デバイスとドライバがロードされ、drvierのprobeメソッドが呼び出されます.
arch/arm/kernel/head-common.S :
00026: /*
00027: * The following fragment of code is executed with the MMU on in MMU mode,
00028: * and uses absolute addresses; this is not position independent.
00029: *
00030: * r0 = cp#15 control register
00031: * r1 = machine ID
00032: * r9 = processor ID
00033: */
00034: .type __mmap_switched, %function
00035: __mmap_switched:
00036: adr r3, __switch_data + 4
00037:
00038: ldmia r3!, {r4, r5, r6, r7}
00039: cmp r4, r5 @ Copy data segment if needed
00040: 1: cmpne r5, r6
00041: ldrne fp, [r4], #4
00042: strne fp, [r5], #4
00043: bne 1b
00044:
00045: mov fp, #0 @ Clear BSS (and zero fp)
00046: 1: cmp r6, r7
00047: strcc fp, [r6],#4
00048: bcc 1b
00049:
00050: ldmia r3, {r4, r5, r6, sp}
00051: str r9, [r4] @ Save processor ID
00052: str r1, [r5] @ Save machine type
00053: bic r4, r0, #CR_A @ Clear 'A' bit
00054: stmia r6, {r0, r4} @ Save control register values
00055: b start_kernel
asmlinkage void __init start_kernel(void)-> void __init setup_arch(char **cmdline_p)-> mdesc = setup_machine_fdt(__atags_pointer);//atagsで_pointer取得(devtree=phys_to_virt(dt_phys))void_init unflatten_device_tree(void);
void __init unflatten_device_tree(void)
{
__unflatten_device_tree(initial_boot_params, &allnodes,
early_init_dt_alloc_memory_arch);
/* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
of_alias_scan(early_init_dt_alloc_memory_arch);
}
これらの作業はDTSファイルの解析を完了します.グローバルチェーンテーブルallnodesに保存します.その後、boardファイルにシステムが起動すると呼び出される.init_machine、高通プラットフォーム対応はmsm_init().次にof_を呼び出すplatform_populate(….)インタフェース、プラットフォームバスとプラットフォームデバイスをロードします.これで、システムプラットフォーム上のすべての構成済みバスおよびデバイスがシステムに登録されます.注意:dtsiファイル内のすべてのノードが登録されるわけではありません.バスやデバイスを登録するとき、dtsノードの状態を判断します.ノード内のstatus属性が定義されていない場合、またはstatus属性が定義され、値が「ok」または「okay」に設定されている場合、その他の場合はシステムに登録されません.
void __init msm8610_init(void)
{
struct of_dev_auxdata *adata = msm8610_auxdata_lookup;
if (socinfo_init() < 0)
pr_err("%s: socinfo_init() failed
", __func__);
msm8610_init_gpiomux();
board_dt_populate(adata);
msm8610_add_drivers();
}
i 2 cバスを登録するとqup_に呼び出されますi2c_probe()インタフェース.バスリソースを申請し、i 2 cアダプタを追加するためのインタフェース.i 2 cアダプタの追加に成功すると、of_が呼び出されます.i2c_register_デバイス()インタフェース.このインタフェースは、i 2 cバスノードのサブノード(バスにマウントされたi 2 cデバイスノード)を解析し、i 2 cデバイスのアドレス、割り込み番号などのハードウェア情報を取得します.そしてrequest_を呼び出すmodule()デバイス対応のドライバファイルをロードし、i 2 c_を呼び出すnew_デバイス()は、i 2 cデバイスを生成します.デバイスとドライバがロードされ、drvierのprobeメソッドが呼び出されます.