前回の続き
#デバイスツリーを使わずにUIOを使用する方法
peri_pmcという名のレジスタを0x120a0000からの4KBをユーザー空間からアクセス可能にします。
その情報をセットしてuio_pdrv_genirqのドライバを登録するだけです。
そのコードの全体はgistに貼りました。ここ
要点は以下の部分です。
実質的にplatform_device_register()を呼びだすだけです。
static struct uio_info mydev_mem = {
.name = "my_device",
.version = "0.1",
.irq = UIO_IRQ_NONE,
};
static struct resource uio_resources[] = {
[0] = {
.name = "peri_pmc",
.start = 0x120a0000,
.end = 0x120a0fff,
.flags = IORESOURCE_MEM,
},
[1] = {
.name = "DUMMY",
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device my_dev = {
.name = "uio_pdrv_genirq",
.id = -1,
.dev = {
.platform_data = &mydev_mem,
},
.resource = uio_resources,
.num_resources = ARRAY_SIZE(uio_resources),
};
static int __init uio_init(void)
{
printk(KERN_INFO "uio_init\n");
return platform_device_register(&my_dev);
}
実際に使用するときには、struct resourceの初期化のところだけを変更すればよいと思います。
このソースをビルドしてカーネルモジュールを作成し、それを insmodコマンドで登録すれば、/dev/uio0 のデバイスファイルが作成されます。
あとは前回の記事と同様です。
注意点
-
割り込みを使用しない場合は、上記のようにstruct uio_info のirqにUIO_IRQ_NONEするとともに、struct resourceの方にもダミーのIORESOURCE_IRQのエントリが必要です。これが無いとinsmodしたときに、"failed to get IRQ" というメッセージでエラー終了してしまいます。
-
アクセス可能にするメモリ範囲の情報は struct uio_info ではなくて、struct resourceの方に書きます。
-
rmmodするとデバイスを削除することができますが、カーネルのログに"uio_pdrv_genirqのデバイスにreleaseの関数が実装されていない" という旨のエラーメッセージが出ます。
#余談
私が最初にUIOを試してみたのは、数年前のカーネル3.0の頃でした。その当時はまだARMのデバイスドライバのデバイスツリー化が必須ではなかったので、この記事のカーネルモジュールの方式でやりました。
最近になって、またUIOを試してみようとしたのですが、当時のコードはもう紛失していて、かすかな記憶を頼りに思い出すのに苦労しました。やっぱりブログに書いておくのがいいですね。
UIOのカーネル内のドキュメント、The Userspace I/O HOWTOは最終更新が2006年12月になっていて、その後の更新が反映されていません。
このドキュメントによると、割り込みを使用せずにメモリのマッピングだけ行いたい場合には"uio_pdrv" というドライバを使用すればよいように書かれています。確かにカーネル3.0の当時はこのドライバは存在しました。
しかし、その後の変更で"uio_pdrv" は削除されてしまっています。おそらくは"uio_pdrv_genirq" でirq=UIO_IRQ_NONE にして使えばよいということだったのでしょう。
その後の変更の履歴は追えていませんが、ARMのデバイスツリーの対応が追加されています。
注意点のところにも書きましたが、uio_pdrv_genirqで割り込みを使用しない場合にはuioinfoのirqをUIO_IRQ_NONEにするだけでは足りなくて、struct resourceの方にもダミーのIORESOURCE_IRQのエントリが必要でした。とてもバグくさい挙動です。
UIO_IRQ_NONEの値は0なのですが、どうやらいろいろな人が建て増し的にコードを追加した結果、uio_infoのirqが0である場合に"割り込みは使用しない"という意味と"割り込みは未設定のため他の情報を参照せよ" の2つの意味がごちゃごちゃになってしまっているようです。
本来なら最新版カーネルでも同様の症状が出るかを確認して、バグをレポートしたいところですが、組み込みLinuxでは簡単に最新のカーネルを動かすことができないのがつらいところです。