はじめに
仕事で Device Tree を触る機会があったので情報をまとめる。
Web上で日本語情報はほぼなかったため後から見返す用。随時追記予定。
少なくともLinux kernel 2.6.38以降導入のため、現状のオライリーの書籍にも記載はなかった。
おそらくいろいろと間違っている可能性が高いですので、以下のリンク先等を正としてください。
2016/6/1 追記: devicetree.org がリニューアルしていたので、リンクを修正しました。
Specifications – Devicetree
=> Device Tree Specification Release X.X のリンク先のPDFを参照
Device Tree - eLinux.org
Device Tree Usage - eLinux.org
Device Tree Reference - eLinux.org
linux/Documentation/devicetree at master · torvalds/linux
"Device Tree for Dummies", ELC 2014 by Thomas Petazzoni (PDF)
Device Tree とは
ARM Linux 向けにで使用されているプロパティ情報を記述した設定ファイルのこと。
Device Treeの仕組み自体は1994年に標準化されたOpen Firmwareというものを元にしている。
デバイスのベースアドレスや、クロック、割り込み番号といった、ハードウェア固有のプロパティをカーネルから分離しデバイスドライバの再利用性を高めることが目的の機能らしい。
Device Tree Souce に記載したプロパティをデバイスドライバから読み込んで使用する。
Device Treeの仕組みは、Linux カーネルのソースのかなりの割合を占めるデバイスドライバの肥大化を防ぐために導入された。
2.6.38 以前のLinuxカーネルにはARMのプラットフォームの依存性を記述する統一的な決まりがなかったため、各プラットフォームごとにそれぞれ独自フォーマットで実装されていた。
Linux コミュニティとしては Device Tree 非対応のデバイスドライバのパッチ受け付けはしない決まりになった模様。
そのため、ARM Linuxを使用する開発者は避けては通れないものになっている。
Linux での Device Tree 標準化の経緯
kernel 2.6.38の時に、Linus氏が肥大するARMコードに激怒したのが発端とのこと。
From: Linus Torvalds <torvalds <at> linux-foundation.org>
Subject: Re: [GIT PULL] omap changes for v2.6.39 merge window
Newsgroups: gmane.linux.kernel, gmane.linux.ports.arm.kernel, gmane.linux.ports.arm.omap
Date: 2011-03-30 19:21:32 GMT (4 years, 31 weeks, 2 days, 17 hours and 24 minutes ago)
(中略)
THAT is an example of something that is totally and utterly screwed
up. Those kinds of random board-level detail files abound in the ARM
tree. They should either be in a per-board file, or (much better) the
ARM people should have standardized this ten f*cking years ago, and
put it in a bootloader or something that just initializes the crap so
that the kernel doesn't have to have random tables like that at all.
ARM right now i a nightmare, and most of it is because ARM hardware
manufacturers are morons. But the way the ARM tree is then laid out
has made that even more painful, and the decision to put all the crazy
board details in the kernel tables instead of trying to have a
per-board boot loader that fills in the details is just crazy.
Look at the dirstat for arch/ in just the current merge window
(cut-off at 5% just to not get too much):
[torvalds <at> i5 linux]$ git diff -C --dirstat=5 --cumulative v2.6.38.. arch
14.0% arch/arm/mach-omap2/
5.8% arch/arm/plat-mxc/include/mach/
6.3% arch/arm/plat-mxc/
57.1% arch/arm/
5.4% arch/m68k/
9.6% arch/unicore32/
6.9% arch/x86/
100.0% arch/
almost *SIXTY* percent of all arch updates were to ARM code. And
that's despite the fact that one of those architectures (unicore32) is
a totally new architecture, and despite m68k having gone through a
first-level unification of nommu and mmu code!
And was this just a fluke? No. Doing the same for 2.3.37..38 gives
58.3% for arch/arm (and in that release we had a blackfin unification
effort, otherwise arm would have been an even bigger percentage).
That's ridiculous. It's entirely due to the whole f*cked-up arm ecosystem.
(後略)
引用: http://article.gmane.org/gmane.linux.kernel/1120436
引用: LKML: Linus Torvalds: Re: [GIT PULL] omap changes for v2.6.39 merge window
上記の議論の流れは以下のスレッド参照。
http://thread.gmane.org/gmane.linux.kernel/1114495/focus=112007
=> 2016/12/20追記: thread.gmane.org/gmane.linux.kernel
のarchiveがなぜか消えてて見つかりませんでした・・・。
用語
DTS : Device Tree Source
Device Treeのソースファイル。専用の形式で書かれている。
拡張子は *.dts
と *.dtsi
の2種類
*.dts
はボード固有の定義が記述されている。
*.dtsi
は通常SoC(System on Chip)固有の情報が含まれており、*.dts/*.dtsi
からCプリプロセッサによりincludeされる。
DTB : Device Tree Blob
Device Tree Sourceをコンパイルしたバイナリファイル。
DTC : Device Tree Compiler
Device Tree Sourceをビルドするためのコンパイラ。
機能として、*.dtb -> *.dtsへの逆アセンブルもサポートしている。
dts の配置場所
linux-4.2.5
の場合
The Linux Kernel Archives からカーネルのソースを取得
※展開後は691MB程度あるので注意
wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.2.5.tar.xz
tar Jxvf linux-4.2.5.tar.xz
Device Tree Source(.dts/.dtsi)のほとんどは以下に配置されている。
/arch/arm/boot/dts/
Device Tree Source の文法について
文法については以下を参照してください。
Specifications – Devicetree
=> Device Tree Specification Release X.X のリンク先のPDFを参照
dtbを実際に使用する場合の注意
dtb の読み出しはブートローダが行う。zImageとは別に配置する必要がある。
ファイルの入れ替えで良いか、dd
コマンドで書き込む必要があるかはブートローダに依存する。
カーネルドライバ内からDeviceTreeのプロパティへのアクセス方法
module_platform_driver
マクロを使用
使用例
/*
* Initialization and module stuff
*/
static const struct of_device_id mpc512x_viu_of_match[] = {
{
.compatible = "fsl,mpc5121-viu", // ※compatibleを指定
},
{},
};
MODULE_DEVICE_TABLE(of, mpc512x_viu_of_match);
static struct platform_driver viu_of_platform_driver = {
.probe = viu_of_probe,
.remove = viu_of_remove,
#ifdef CONFIG_PM
.suspend = viu_suspend,
.resume = viu_resume,
#endif
.driver = {
.name = DRV_NAME,
.of_match_table = mpc512x_viu_of_match, // ※of_match_table に格納
},
};
module_platform_driver(viu_of_platform_driver);
MODULE_DESCRIPTION("Freescale Video-In(VIU)");
MODULE_AUTHOR("Hongjun Chen");
MODULE_LICENSE("GPL");
MODULE_VERSION(VIU_VERSION);
この後のprobeに設定した関数にてDeviceTreeのnodeを取得できる
static int viu_of_probe(struct platform_device *op)
{
struct viu_dev *viu_dev;
struct video_device *vdev;
struct resource r;
struct viu_reg __iomem *viu_regs;
struct i2c_adapter *ad;
int ret, viu_irq;
struct clk *clk;
ret = of_address_to_resource(op->dev.of_node, 0, &r); // ※op->dev.of_nodeで struct device_node を取得
if (ret) {
dev_err(&op->dev, "Can't parse device node resource\n");
return -ENODEV;
}
...
of_find_compatible_node()
を使用
of_find_compatible_node()
を使用してもnodeが取得できる。
デバッグ方法
/proc/device-tree
を参照する
ARM Linuxの場合は、オプションで有効化されている場合は /proc
以下でDeviceTreeの情報を取得できる。
/proc/device-tree
値はhexdump
で確認できる
# hexdump -C '/proc/device-tree/#size-cells'
00000000 00 00 00 01 |....|
00000004
# hexdump -C '/proc/device-tree/axi@0/compatible'
00000000 78 6c 6e 78 2c 70 73 37 2d 61 78 69 2d 69 6e 74 |xlnx,ps7-axi-int|
00000010 65 72 63 6f 6e 6e 65 63 74 2d 31 2e 30 30 2e 61 |erconnect-1.00.a|
00000020 00 73 69 6d 70 6c 65 2d 62 75 73 00 |.simple-bus.|
0000002c
カーネルでどのデバイスツリーが使用中かを判別する
/proc/device-tree/compatible
を確認すれば compatible
の記載文字列が確認できるため、dtsの推測はできる。
$ strings /proc/device-tree/compatible
fsl,imx6dl-sabreauto
fsl,imx6dl
.dtb
を .dts
に戻す
Ubuntuの場合は以下でパッケージを取得できる。
apt-get install device-tree-compiler
逆アセンブルする場合は以下のコマンドで可能。
dtc -I dtb -O dts -o ${hoge}.dts ${hoge}.dtb
エディタ関連
VimのSyntax対応
v7.3.684 (6 Oct 2012) 以降で dts.vim
に対応済み
https://github.com/vim/vim/commit/0c5fa7d740bafefbf0b2ea48a2a660901d7d4f10
参考書籍
Interface2014年10月号、11月号に特集されている。ただし概要程度。
Linux 3.2 に対応したO'Reillyの書籍が出るらしい(延期して2017年11月予定)から解説が乗る可能性はあります。
Linux Device Drivers, 4th Edition - O'Reilly Media
=> 2016/10/13追記: 何故か商品ページが削除されている・・・
参考
Wiki
elinux.org - Device_Tree
Specifications – Devicetree
Device Tree presentations papers articles
発表資料
"Device Tree for Dummies", ELC 2014 by Thomas Petazzoni (PDF)
elinux.org - Solving Device Tree Issues (PDF)
Experiences_With_Device_Tree_Support_Development_For_ARM-Based_SOC (PDF)
記事(ブログ, Qiita, StackOverFlow等)
とあるエンジニアの備忘log - Device Tree 入門
とあるエンジニアの備忘log - Device Tree アクセス関数まとめ (Linux Kernel)
Qiita - メモ:Device tree blob (.dtb)をDevice tree source (.dts)に戻す
A Tutorial on the Device Tree (Zynq) -- Part I | xillybus.com
linux - how to program device tree file(.dts)? - Stack Overflow