Vengineerの戯言

人生は短いけど、長いです。人生を楽しみましょう!

Zynq MPSoCで、コンピュータを学ぼう (その4)

はじめに

「Zynq MPSoCで、コンピュータを学ぼう」のその4です。

  • その1 : Xilinx社のZynqUltrascale+ MPSoC について
  • その2 : Zynq Ultrascale+ MPSoC がどのように立ち上がっていくのか
  • その3 : Linux の dts を見て、どのようなハードウェアを使っているのか?
  • その4 : Linuxデバイスドライバについて
  • その5 : Programmable Logic
  • その6 : QEMU (Zynq Ultrascale+ MPSoC の実物が無くても、Linuxが立ち上がる)

Linuxデバイスドライバ

前回は、Linux の dts ファイルの cpus のところで、CPUを見てみました。CPUと同様に各デバイスドライバも dts ファイルの中に書いてあります。

zynqmp.dtsi ファイルGPU の部分を見ています。

gpu エントリーとして、0xfd4b0000 がレジスタのベースアドレスです。デバイスドライバとして、compatible にある "arm,mali-400", "arm,mali-utgard" を使います。ARM社のGPU Mali-400 (mali-utgard)のデバイスドライバを使います。Zynq Ultrascale+ MPSのEGとEVには、Mali-400MP2が載っています。MP2とは、GPUコアが2個載っています。そのことを示しているのが、clock-names の中の "gpu_pp0" と "gpu_pp1" です。この gpu_pp がGPUコアに対応します。

      gpu: gpu@fd4b0000 {
            status = "disabled";
            compatible = "arm,mali-400", "arm,mali-utgard";
            reg = <0x0 0xfd4b0000 0x0 0x10000>;
            interrupt-parent = <&gic>;
            interrupts = <0 132 4>, <0 132 4>, <0 132 4>, <0 132 4>, <0 132 4>, <0 132 4>;
            interrupt-names = "IRQGP", "IRQGPMMU", "IRQPP0", "IRQPPMMU0", "IRQPP1", "IRQPPMMU1";
            clock-names = "gpu", "gpu_pp0", "gpu_pp1";
            power-domains = <&zynqmp_firmware PD_GPU>;
        };

SPIに対しては、2つ (spi0/spi1) が搭載されています。compatible の "cdns,spi-r1p6" とあるように Cadence社のIPを使ってます。この compatible に対応するデバイスドライバを探せばいいのです。

      spi0: spi@ff040000 {
            compatible = "cdns,spi-r1p6";
            status = "disabled";
            interrupt-parent = <&gic>;
            interrupts = <0 19 4>;
            reg = <0x0 0xff040000 0x0 0x1000>;
            clock-names = "ref_clk", "pclk";
            #address-cells = <1>;
            #size-cells = <0>;
            power-domains = <&zynqmp_firmware PD_SPI_0>;
        };

        spi1: spi@ff050000 {
            compatible = "cdns,spi-r1p6";
            status = "disabled";
            interrupt-parent = <&gic>;
            interrupts = <0 20 4>;
            reg = <0x0 0xff050000 0x0 0x1000>;
            clock-names = "ref_clk", "pclk";
            #address-cells = <1>;
            #size-cells = <0>;
            power-domains = <&zynqmp_firmware PD_SPI_1>;
        };

Cadenceの SPI のデバイスドライバは、spi-cadence.c です。

下記のように、.compatible に、"cdns,spi-r1p6" があります。

static const struct of_device_id cdns_spi_of_match[] = {
    { .compatible = "xlnx,zynq-spi-r1p6" },
    { .compatible = "cdns,spi-r1p6" },
    { /* end of table */ }
};

他のデバイスドライバも dts ファイル内の compatible を見て、デバイスドライバディレクトリ (drivers) の下から見つければいいだけです。 見つけたら、どんなことを行っているのかを調べるだけです。

Linxuのデバイスドライバって、どうなっているの?

Linux 2.6までであれば、下記の「Linuxデバイスドライバ 第3版」を読めばよかったのですが、今のLinuxのバージョンは、6 ですから、もう 2.6 なんていつの頃?って感じですよね。

www.amazon.co.jp

第4版(英語版)ですが、3.2 ですね。

www.kinokuniya.co.jp

平田豊さんの「Linuxデバイスドライバの開発 (I/O BOOKS) 」は、5.2 対応なので、こちらの方がいいですね。

こちらのサイトも参考になりそうです。

wiki.chobits.com

おわりに

今回は、Linuxデバイスドライバについて見てみました。

Zynq Ultrascale+ MPSoC だけでなく、x86-64Apple M1 の Linux でも 各 dts を見れば、どんなデバイスが繋がっていて、そのデバイスドライバソースコードをみることができます。

Asahi LinuxApple M1/M2 の dts ファイルは、下記のところにあります。

是非、調べてみてください。