FreeBSD/armがクソなのでNetBSDを使うことにしたのですが、依然USBが使えません。
普通のUSB 2.0サポートは2.0のEHCIと1.0のOHCIなどを組み合わせて使います。この場合OHCIなどはコンパニオンと呼ばれます。
しかしComcertoはEHCIしかありません。まさか2.0のサポートだけで1.0はサポートしてないのでしょうか。
USBバスにはTransaction Translator(TT)というUSB 1.0の通信を2.0に変換してくれる機能があります。この機能をhostやhubがサポートしていることがあり、Comcertoもこの機能がありました。TTがあれば通信は2.0だけにできて、EHCIだけで1.0と2.0をサポートできます。
attachでこの機能の設定を行います。
sc->sc_flags = EHCIF_ETTF;
またこのデバイスではusbの共有コードehci_init()以外にデバイス側のコードで初期化が必要でした。
#define USBMODE 0xa8
#define USBMODE_CM_HC 3
#define USBMODE_SDIS 0x10
static void
m83ehci_init(struct ehci_softc *sc)
{
uint32_t reg;
reg = EOREAD4(sc, EHCI_PORTSC(1));
reg &= ~(EHCI_PS_CSC | EHCI_PS_PEC | EHCI_PS_OCC);
reg |= EHCI_PS_PP | EHCI_PS_PE;
EOWRITE4(sc, EHCI_PORTSC(1), reg);
reg = bus_space_read_4(sc->iot, sc->ioh, USBMODE);
reg |= USBMODE_CM_HC;
/* Set "Streaming disable mode" to avoid Tx under run */
reg |= USBMODE_SDIS;
bus_space_write_4(sc->iot, sc->ioh, USBMODE, reg);
}
この設定に気付くまでかなり手間取りました。comcertoのSDKでLinuxのusb関係で標準のコードに修正が加わっていたのは、ehci-hcd.cとehci-sched.cでした。このうちehci-hcd.cの修正はUSBMODEに関する修正で、NetBSDのdev/usbのコードでUSBMODEの処理をみたのですが、ありません。いろいろ調べてみたところSOCの個別のコードにUSBMODEの処理があり、それをコピーしました。
このコードはimxからコピーしたのですが突っ込みどころ満載です。まず最初のアクセスはマクロなのに後のアクセスはKPIを直書きしています。またUSBMODEは初期値0でREADする必要はないと思います。またいきなりUSBMODE_CM_HCをORをとってますが、デフォルト0で値が3だからいいようなもので、マスクしてORをとるのが正しいのですが、そもそも必要ありません。
armの下に三つくらい似たようなコードがあり、最初に書いた人が上のような汚い書き方したので、そのままコピーされて汚染が広がっています。^ ^;
デバイスドライバではピットフィールドを変更するために読んで、書いてをすることがありますが、ときとして思わぬ動作になることがあるので、注意が必要です。
これをattachの時にscに登録します。
sc->sc_vendor_init = m83ehci_init;
comcertoのSDKでもこの部分をいじっていたので、ここをvendor毎にいじれるようなKPIにした点は評価できます。
これでUSBが見えるようになりました。