« 自分で作ったデバイスドライバをmenuconfigに出す方法 | トップページ | ZYNQセミナーの資料 第1章 »

2017.12.06

UIOデバイスドライバを組み込む方法

LinuxにUniversal I/Oというドライバがあります。ユーザモードでドライバを組むことができるというものだそうです。

このドライバを使おうと思ったのですが、デバイスツリーに

        uio@b8800000 {
            compatible = "generic-uio";
            reg = <0xb8800000 0x1000>;
            interrupt-parent = <0x3>;
            interrupts = <0x0 0x1d 0x4>;
        };

のように書くだけでは組み込まれないようでした。

uioドライバの一番元のやつはuio_pdrv_genirq.cというファイルのようですが、

Uio1

ソースを見てみると、

static const struct dev_pm_ops uio_pdrv_genirq_dev_pm_ops = {
	.runtime_suspend = uio_pdrv_genirq_runtime_nop,
	.runtime_resume = uio_pdrv_genirq_runtime_nop,
};

#ifdef CONFIG_OF
static struct of_device_id uio_of_genirq_match[] = {
	{ /* This is filled with module_parm */ },
	{ /* Sentinel */ },
};
MODULE_DEVICE_TABLE(of, uio_of_genirq_match);
module_param_string(of_id, uio_of_genirq_match[0].compatible, 128, 0);
MODULE_PARM_DESC(of_id, "Openfirmware id of the device to be handled by uio");
#endif

static struct platform_driver uio_pdrv_genirq = {
	.probe = uio_pdrv_genirq_probe,
	.remove = uio_pdrv_genirq_remove,
	.driver = {
		.name = DRIVER_NAME,
		.pm = &uio_pdrv_genirq_dev_pm_ops,
		.of_match_table = of_match_ptr(uio_of_genirq_match),
	},
};

となっていて、match文字列がありません。

つまり、デバイスツリーにcompatible = "generic-uio";の記述を追加するだけではこのドライバは読み込まれないようです。

UIOドライバが読み込まれるようにするには2つの方法があります。

  • デバイスドライバのソースを書き換えて、uio_of_genirq_matchに{.compatible = "generic-uio"},の記述を追加する
  • device treeのbootargsに指示する

前者の方法だと、ドライバのソースを書き換えて再ビルドしなければならないので、面倒です。

後者の方法だと、デバイスツリーを書き換えるだけで入れることができます。

やり方は、device treeのchosenのbootargsにuio_pdrv_genirq.of_id=generic-uioの記述を追加するだけです。

chosen {
    bootargs = "console=ttyPS0,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 rootwait devtmpfs.mount=1 uio_pdrv_genirq.of_id=generic-uio earlycon earlycon";
    stdout-path = "serial0:115200n8"
};

デバイスドライバの世界ではofといったら、デバイスツリーでモジュールを組み込む仕組みのことをいうようです。

このbootargsへの追加によって、generic-uioというドライバを見たら、uio_pdrv_genireqモジュールを読み込め、ということが指示されます。

なお、詳しく見てみると、UIOドライバはuio.cというのが根本にあるドライバです。uio.cでは、copy_to_user()やcopy_from_user()といった関数で実際のハードウェアを読み書きします。しかし、probe関数がないので、これ自体が組み込まれて実行されるようではないようです。

そのため/class/sys/uioというクラスはできているのですが、実際のデバイスは作られていません。

実際のデバイスが作られるには、probeされる子ドライバの中でuio_register_device(&pdev->dev, &gdev->info);関数が呼び出されたときのようです。uio_register_deviceが呼び出されると、親であるuio.cのuio_unregister_device()が呼び出され、はじめて使えるようになります。

クラスとインスタンスの関係のように、実際のデバイスが認識されてはじめて登録されて、デバイスドライバの実体が出来上がるようですね。

まとめると、使う側としては、

  • デバイスツリーのbootargsに uio_pdrv_genirq.of_id=generic-uio を追加する
  • デバイスツリーにcompatible = "generic-uio";を持つデバイスを追加する

だけでよいようです。

|

« 自分で作ったデバイスドライバをmenuconfigに出す方法 | トップページ | ZYNQセミナーの資料 第1章 »

コメント

コメントを書く



(ウェブ上には掲載しません)




« 自分で作ったデバイスドライバをmenuconfigに出す方法 | トップページ | ZYNQセミナーの資料 第1章 »