DeviceTreeの基礎

2019/03/23import

device.tree.org

devicetreeの実装サイドからの仕様を公開していると思われます。

そもそもdevicetreeとはコンピュータシステムの構成要素を記述するために用いられています。

冒頭で 関連している仕様として、以下が挙げられています:

  • IEEE 1275 Open Firmware standard―IEEE Standard for Boot (Initialization Configuration) Firmware: Core Requirements and Practices [IEEE1275].
  • EPAPR

この仕様書は、2016年からlinaro社, ARM社によって生成されている模様です。

コンピュータシステムの初期化を行う際に、OS起動前に初期化処理の必要なハードウェア類があります。ブートローダ、ハイパーバイザ等が初期化等を行って、最終的にOSへと処理を移します。このプログラム間で情報のやりとりを行うための規定にも使えるもの、とあります。

仕様の詳細は、Devicetree Specificationを参照しましょう。


なぜ必要か

PCでは ACPIがハードウェア情報を提供してくれるため、必要な設定・ドライバのロードが可能でした。

そこで Open Firmwareの頃から powerpcアーキテクチャで devicetreeの利用が始まっていました。その後 Linux kernelソースコードの汚い肥大化をLinusに指摘されたことにより、ARMアーキテクチャにも適用することとなったものです。したがって、poewrpcやARMアーキテクチャのカーネルドライバ・u-bootに関わる方には必須の事項となります。

ブートプログラムがシステム内のハードウェアの初期化処理を行うために必要な情報を得るために必要です。これがなければ、ブートプログラムはシステム内のハードウェア構成にあわせて個々に用意する必要があります。これではブートプログラムの実装効率も悪く、同じようなコードが散乱することになりかねません。そこで、ドライバソフトウェアを個々のハードウェアに対応したものとし、そのリソースを含めて定義できるようにすることでソフトウェアを共通化することができます。

その昔、PC/AT互換機が出てから `Plug and Play` が登場するまでは、ボードのリソース設定等をディップスイッチで行って、インストール作業者がリソース競合を回避するといった作業を行っていました。

PCIデバイスでは、ターゲット側がconfiguration spaceを用意することで、デバイスの素性や要求リソースを検出する仕組みが用意されています。したがって、Devitetreeはこれらのターゲットデバイスの定義を含めないこととしています(例外として、ソフト的にproveできないPCI host bridge deviceを挙げています)。


Devicetree format(概要編)

Devicetree Specificationに詳細な記述仕様があります。ざっと要点を抜粋していきます。

tree状に定義する様式となっており、'/'をルートノードとして、ファイルシステムのディレクトリ階層のように記述していきます。簡単な記述例を以下に示します。実用的な記述ではありませんが、コンパイルは通ります。

/dts-v1/;
/ {
        #address-cells = <1>;
        #size-cells = <1>;

        soc {
                compatible = "simple-bus";
                #address-cells = <1>;
                #size-cells = <1>;
                intc: intc@100 {
                        reg = <1000 100>;
                };
                spi: spi@0 {
                        reg = <0 0>;
                        interrupts = <&intc 1>;
                };
    };
};

ここで socintc@100 はノードといいます。中括弧で括った要素(プロパティ)をまとめる器です。これはバスを表現したり、特定の機能をもつIPコアを表現したり、Flash memoryやセンサICを表現したりします。

また、ノードは何段でも階層化した記述ができ、CPUから見えるシステムバスの多段表現や、その先にあるIPコアのレジスタインタフェースを表現することができます。SoC内部に限らず、SPI・I2C・非同期バスなどを介して接続するデバイスを表現します。

それぞれのノードに、プロパティを定義します。プロパティは 項目名と値とからなる組み合わせで、値がないものも存在します。値はDTspecで規定されているものなら自由に設定できますが、それを参照するのは対応するドライバです。ドライバが判るように設定してあげる必要があります。

kernel versionが新しくなるにつれ、ドキュメントも整備されていきました。kernel/Documentation/devicetree/bindings/ 配下に、ある程度まとめられています。善意の協力のもとで作られていますので、必ずしも欲しい情報が存在する/正しいとは限りません。

自分が商用向けで触ったりする場合には 可能な限りソースコードも参照することをおすすめします。