FreeBSDのアドバンスカレンダーの3日目にGPIOの話題があったのでRT1310Aでも使えるようにしてみました。
クリスマスも近いのでLEDをチカチカしてみたいなと思ったのがちょっとした動機だったりします。
まずはRT1310Aのプロダクトブリーフをみて、GPIOが12本であることを確認。
次にRT1310Aはデータシートが手に入らないので、GPLなコードでIOアドレスを覚えます。APBの0xa0000で0x00がPORTAのデータレジスタ、0x04がPORTAのディクリプションレジスタ。同じように0x08,0x0cがPORTBになります。
これだけ覚えたらGPLを忘れるために「中西悟堂」になったつもりで公園を一周してきます。
BSDな気持ちでコーディングに入ります。
FDTのstdファイルにgpioのエントリを追加します。
とりあえずsys/arm/lpc_gpio.cをrt1310_gpio.cとしてコピーします。
lpcはGPIOのピン数も多く複雑なので、基本的にはコードを削っていく事になります。
GPIOのドライバは大まかに各ポートがINかOUTの設定と読み込み、INの場合は読み込みとOUTの場合は書き込みができれば完了です。
とりあえず変数名や関数名などをlpcからrt1310に代えます。
:%s/lpc_/rt1310_/g
機能は実装せずコンパイルしてみます。タイポなどないのですが、デバイスドライバの登録付近でエラーがでます。とりえずsimplebusへの登録のみ残してコンパイルしたら通りました。おそらく現在のlpc_gpio.cは同じようにコンパイル通らないと思います。
ごにょごにょしてとりあえず認識されるようになりました。
gpio0: <RT1310 GPIO> mem 0xa0000-0xbffff irq 8 on simplebus2
gpiobus0: <GPIO bus> on gpio0
random: harvesting attach, 8 bytes (4 bits) from gpiobus0
gpioc0: <GPIO controller> on gpio0
random: harvesting attach, 8 bytes (4 bits) from gpioc0
random: harvesting attach, 8 bytes (4 bits) from gpio0
gpioctlはlibgpio.soが必要なので、rootfsに入れておきます。
で試すとこんな感じです。
# ./gpioctl -l
pin 00: 0 GPIO_00<OUT>
pin 01: 0 GPIO_01<OUT>
pin 02: 1 GPIO_02<IN>
pin 03: 0 GPIO_03<OUT>
pin 04: 0 GPIO_04<OUT>
pin 05: 0 GPIO_05<OUT>
pin 06: 0 GPIO_06<OUT>
pin 07: 0 GPIO_07<IN>
pin 08: 0 GPIO_08<OUT>
pin 09: 1 GPIO_09<IN>
pin 10: 0 GPIO_10<OUT>
pin 11: 0 GPIO_11<OUT>
三つINになっているのはU-Bootで初期化されている、ボタンの入力となります。ボタンとLEDの対応をコツコツ調べたところこんな感じでした。上の写真の赤いLEDが00になります。
lpcのコードと同じようにrt1310_gpio_pin_toggleでpanicするのですが、使われていないのかもしれません。^ ^;
RT1310AのGPIOは割り込みも使えるようですと思ったのですが、GPLなコードには見つからなかったの、ひょっとすると無いかもしれません。FreeBSDでGPIOの割り込みってどのように使うか分からなかったので実装していません。
後日追記
dtsにgpioledを追加してみたのですが、なかなか動くようにならなくてかなりはまりました。
まず、gpioのエントリーにgpio-controllerと#gpio-cells = <2>が必要でした。
これだけではダメでgpioのドライバにfdt用のDEVMETHODを追加する必要がありました。
gpioledが登録されると/dev/led/statusなどができます。これに0,1をcatすると点灯したり消灯したりします。またf1やf9をcatすると点滅するようになります。
RT1310ではGPIOでの割り込みはできなさそうですが、INTRNGでGPIOの割り込みも他のデバイスから使えるようになったようです。