読者です 読者をやめる 読者になる 読者になる

dts interrupt もう一度

dts の interrupt は通常(何を通常というかわからないが)

     #interrupt-cells = <0x2>;
...

     interrupts = <0x52 0x0>;

みたいになっている。最初の数が IRQ の番号で、次がタイプ(この場合は IRQ_TYPE_NONE、gic では指定できないためか?) linux/irq.h にその値が書いてある。下駄のはき方が 23 だった。

で ARM の gic の場合、昔はそうだった。だから wdt のようなマルチプロセッサのすべてに同時に割り込みを掛けたいようなケースを表現できなかった。device tree を読むときに xlate という変換関数を用意することで、それらの特殊事情に対応できるようになった。

参考までに書くと、interrupts の仕様はバスによる。device tree 自身は仕様を変えていない。それを読む側(gic)の仕様が変わったのだ。

const struct irq_domain_ops gic_irq_domain_ops = {
        .map = gic_irq_domain_map,
        .xlate = gic_irq_domain_xlate,
};

gic_ireq_domain_xlate という関数が変換用の関数。

     #interrupt-cells = <0x3>;
...

     interrupts = <0x0 0x32 0x0>;

同じ UART の番号が 0x52 から 0x32 に変わっている。なんかめんどくさいぞ。
最初の引数である 0 は SPI を使うかどうか。ここでいうSPI はインタフェースの SPI ではない。
ARM の gic は SGI, PPI, SPI とそれぞれソフトウェア割り込み、ここの CPU のみにかけられる割り込み、共通の割り込みと別れている。SGI は 16 こ、PPI は 16 こ。で、通常の場合マルチプロセッサの”どちらかに”かければいいので最初は 0 になる。しかし、wdt のようなりょほうにかかってほしいものは 1 になる。この SPI 使用の 0 と 1 とで xplate での変更の仕方も変わってくる。前者が16で後者が32たす。つまり、各 CPU ごとに設定可能な割り込みは PPI と SPI を使えるように 16 たす。どうやっても SGI は使えない。両方の CPU に設定可能な割り込みは SPI を使えるように 32 をたす。SGI PPI は使えないように考慮されている。実際に両方にかかるかどうかは SPI ステータスレジスタを設定する。

でもって、xlate では #innterupt-cells が 3 であることをチェックしていて、irq のリソース登録時にエラーになるので、ここを間違うと(おそらく)割り込みが使えない。もしかして、立ち上がらなくなっちゃうかな、、、折角 compatible があるのに、有効に使えてない気がする。(まぁいいか)

こんなの絶対忘れちゃうからメモしておく。