FreeBSD/mipsではMediatek(2011年にRalinkを買収)のチップからFDT対応を行っています。ソースは古いコードのsys/mips/rt3050とは別にsys/mips/mediatekに用意されています。
FDT対応にともないmtk_pinctrl.cというコードでGPIOのpinのコントロールサポートされています。
最近の多くのSOCは一つのピンをGPIOか他機能かを切り替えて使うようになっています。この切り替え機能をサポートする仕組みがpinコントロールになり、FreeBSD全体で利用されるようになっています。ただし切り替え内容などはsoc毎に違うので、記述する内容はsoc毎に違ってきます。pinをどのように使うかはsocの設定ではなくboardの設定になるのでsocのdtsiではなく、boardのdtsに記述します。
u-bootの設定にdtsのdefaultを反映した後に、機能がOKでpinctlが有る場合はそれを反映します。
たとえばu-bootがI2CをONにするために0ビットを0にしてあってもdefaultでgpioを指定すれば1になります。
逆にu-bootが1でgpioを指定していてもdtsでi2cをOKにすると0になります。
RT3050でpinコントロールを利用する場合以下のようなブロックをboardのdtsファイルに追加します。
&pinctrl {
state_default: pinctrl0 {
gpio {
ralink,group = "i2c", "jtag";
ralink,function = "gpio";
};
uartf {
ralink,group = "uartf";
ralink,function = "i2s uartf";
};
rgmii {
ralink,group = "rgmii";
ralink,function = "rgmii";
};
mdio {
ralink,group = "mdio";
ralink,function = "mdio";
};
};
};
この例では、gpioのブロックでgroupに含まれるi2cとjtagはfunctionのgpioで利用するという指定になります。すなわちGPIO1,GPIO2とGPIO17-GPIO21とpinコントロール外のGPIO0がgpioとして利用できます。参考までにMIPS 14ピンのJTAGのコネクタの場合は以下のような接続になる。
ピン | JTAG | GPIO | FON2412 |
---|---|---|---|
1 | TRST | GPIO21 | TP1 |
3 | TDI | GPIO18 | TP2 |
5 | TDO | GPIO17 | TP3 |
7 | TMS | GPIO19 | TP4 |
9 | TCK | GPIO20 | TP5 |
FON2412のパターン
rgmiiとmdioもrgmiiとmdioで使うという設定です。
uartfの記述はuartfのGPIO7-GPIO14はGPIOではなく、I2SとUARTFとして使うという定義になります。RT3050のデータシートはネットで入手できるので17ページにこの記述があります。
uartとgpioで使いたい場合は以下のように設定します。これでRXが10でTXが8で二つ目のuartとして使えます。
uartf {
ralink,group = "uartf";
ralink,function = "gpio uartf";
};
この設定を試してみた所uartfがcuau0になり、uart(lite)がcuau1になりました。
GPSのPPSをGPIO12で拾っていますが、ハンダが乗ってるほうがGPIO12です。
RT5350を使ったFON2412も同じようです。
現在のところgpioctlコマンドの状態表示にはpinコントロールの状態は反映されません。
dtsファイルによってどのように設定されたかは起動ログに表示されます。
# dmesg | grep pinctrl0
pinctrl0: <MTK Pin Controller> on ofwbus0
pinctrl0: GPIO mode start: 0x0000029d
pinctrl0: GPIO mode end : 0x0000005d
random: harvesting attach, 8 bytes (4 bits) from pinctrl0
dtsに書いても効いてないケースがあったのでGPIO mode endの設定値が想定しているものになってるか確認することが重要です。正しく設定されてないと、機能が使えません。
なぜこの設定を試してみたかというと、シリアルが2ポートあるターゲットが欲しかったためです。GPIO12,14またはGPIO8,10が出ているRT3050ボードはuartfの設定で2ポート目(実際にはttyu0)のuartが拾いだせます。
FON2405やFON2412GPIO12,14の方をuartにするとLEDが全部つかえなくなるのでちょっと困ります。uartがRXDだけでよければGPIO10を使うのが良いです。
FON2412は写真真ん中のR119がTXD(GPIO8:K2)のプルダウンなので、こことプッシュスイッチ(RXD)でUARTFが取れます。CTS,RTSは使わないのでttyu0ではなくcuau0でアクセスします。
たまたま見つけられたのですが、一番下だけがプルアップで上下の4つもどこかのピンに接続されているものと思われます。
JavaScriptでRT3050のGPIOの設定を確認するスクリプト作ってみました。
AsusのRT-G32というターゲットで、実装されているFlashはCFIなのですが、基盤裏にSPIのパターンがありました。一度gpioに設定してgpioctlで確認してみました。
R14,R188,R189はpullupでR15はpulldownのようなので10Kなどの抵抗になると思います。R186,R187は0オームと思われます。
dtsにspiを追加して試してみたのですが、クロックが出力されません。なにか設定が抜けているのかもしれません。 spiピンをgpioにする設定が残っていて、動かなかったようです。
RT2880のpinコントロール
RT3050のデータシートはネットで手に入りますが、RT2880の物は手に入らないので、調べてみました。
RT2880はRalink時代の1世代目のMIPS SOCでRT3050の前の製品になります。
RT2880(4K)でpci busがありましたが、RT3050(24K)ではなくなってUSBやSwitchなどが追加されていまが、基本的構成は同じです。RalinkのMIPS SOCはRT3050が非常に多く使われていましたが、RT2880の開発があったからこそRT3050が成功できたとも言えます。
Pins Sharing Schemeも一部違いますが以下のようになっているようです。
Func Name | PIN No | MODE |
---|---|---|
I2C | 1-2 | 0x01 |
UARTF | 3-10 | 0x02 |
SPI | 11-14 | 0x04 |
UARTL | 15-16 | 0x08 |
JTAG | 17-21 | 0x10 |
MDIO | 22-23 | 0x20 |
SRAM | ? | 0x40 |
PCI | ? | 0x80 |
たまたまRT2880+RTL8366SRなターゲットが手に入り、FreeBSDを入れてみました。起動時のピンコントロールは0x26(b00100110)となっていて、UARTF,SPI,MDIOがGPIOとして使えるようにu-bootで設定されているようです。
RTL8366SRの97(SCL),98(SDA)ピンにジャンパーをはって、gpioctlで確認したところRTL8366SRのSMIはMDIOに接続されていました。PhyでなくSwitchの接続なので、素直な設計です。
このターゲットにはI2CのEEPROMのパターンがあり、I2CはSMIとは別にしていました。
RT3883のpinコントロール
Func Name | PIN No | MODE | DEV |
---|---|---|---|
I2C | 1-2 | 0x01 | gpioc0 |
SPI | 3-6 | 0x02 | gpioc0 |
UARTF | 7-14 | 0x04 | gpioc0 |
UARTL | 15-16 | 0x08 | gpioc0 |
JTAG | 17-21 | 0x10 | gpioc0 |
MDIO | 22-23 | 0x20 | gpioc0 |
24-31 | gpioc1 | ||
LNA A | 32-34 | gpioc1 | |
LNA G | 35-37 | gpioc1 | |
38-39 | gpioc1 | ||
PCI | 40-71 | gpioc2 | |
GE1 | 72-83 | gpioc3 | |
GE2 | 84-95 | gpioc3 |
ralink,group = "i2c", "jtag", "uartf", "lna a", "lna g";
ralink,function = "gpio";
pinctrl0: GPIO mode end : 0x000f1c5d
0x000f1c5dは二進で1111 0001 0101 1101になります。
DECL_TABLE(rt3883_pintable) = {
GROUP("i2c", SYSCTL_GPIOMODE, 0, 1, i2c_func),
GROUP("spi", SYSCTL_GPIOMODE, 1, 1, spi_func),
GROUP("uartf", SYSCTL_GPIOMODE, 2, 7, uartf_func),
GROUP("uartlite", SYSCTL_GPIOMODE, 5, 1, uartlite_func),
GROUP("jtag", SYSCTL_GPIOMODE, 6, 1, jtag_func),
GROUP("mdio", SYSCTL_GPIOMODE, 7, 1, mdio_func),
GROUP("lna a", SYSCTL_GPIOMODE, 16, 3, lna_a_func),
GROUP("lna g", SYSCTL_GPIOMODE, 18, 3, lna_a_func),
GROUP("pci", SYSCTL_GPIOMODE, 11, 7, rt3883_pci_func),
GROUP("ge1", SYSCTL_GPIOMODE, 9, 1, gex_func),
GROUP("ge2", SYSCTL_GPIOMODE, 10, 1, gex_func),
GROUP_END
};
3番目がビットのオフセットで4番目がビットマスクなので設定できているようです。
MT7620のpinコントロール
dev | pin | no |
---|---|---|
GPIO0 | 0-23 | 0-23 |
GPIO1 | 24-39 | 0-15 |
GPIO2 | 40-71 | 0-31 |
GPIO3 | 72 | 0 |
GPIO0とGPIO2を有効にしてGPIO1がdisabledだとGPIO2が/dev/gpioc1になります。
EtherのPHYのLEDは40から44でgpio2の0-4になります。このピンはJTAGとも兼用のようです。このため設定はjtagではなくephyになります。
11,13ピンもどこかにつながってるようですが、分かりません。
WN-G300R3の未実装のLED1はWLED(GPIO#72)で探すのに苦労しました。
追記:WLEDのgpio3を有効にするとsysctlでクラッシュするので結局ディセーブルのままにしました。(2024/10)
pinコントロールの機能は共通化できたことは評価できるのですが、gpioとの連携ができてないことや動的に変えられないことなど、問題があります。
話は違いますが、Ralink時代のロゴはMediatekのロゴよりかっこ良かったと思います。:)