AN889の日記

組込みエンジニアのブログ

【Linux】NXP QorIQプロセッサ向けLinuxでのSGMIIリンク設定

NXPのQorIQシリーズT1014/T1024プロセッサーにてMACイーサネットPHYをSGMII接続する際、プロセッサーレジスター SGMII IF Mode (MDIO_SGMII_IF_MODE) でのリンク(MAC-PHY間のリンクです。PHYと対向機(例えばイーサネットスイッチやPC)とのリンクではありません)設定が必要な場合があります。
MACのリンク設定とPHYのリンク(PCS(Physical Coding Sublayer)リンク)設定が同じ(例えばどちらもオートネゴシエーション有効)ならいいのですが、違う場合リンクされません。

PHYのリンク設定ですが、例えばMICROCHIP社製VSC8562
https://www.microchip.com/en-us/product/vsc8562/
の場合、MAC SerDes PCS Controlレジスター(アドレス 16E3)のビット7 MAC SerDes autonegotiation enable でします(このビットはスティッキー(sticky bit)なので、ソフトリセットしても値が保持されます)。

プロセッサーのMDIO_SGMII_IF_MODEレジスター設定はLinux
GitHub - nxp-qoriq/linux at LSDK-19.09-update-311219-V4.14
だとドライバーdrivers/net/ethernet/freescale/fman/fman_memac.csetup_sgmii_internal_phy()でします。
バイスツリーで実PHYを定義している場合、522行目でオートネゴシエーション有効に設定されます。
PHYのPCSリンクをオートネゴシエーション無効にしても、MDIO_SGMII_IF_MODEでオートネゴ有効になるのでリンク確立しません。 そこで、MDIO_SGMII_IF_MODEのリンク設定を選択できるよう、デバイスツリーにプロパティーを新たに設け、ドライバーを改造しました。

  • バイスツリーのプロパティ
    • プロパティ名:fsl,pcs-link-speed
    • 値:100=100Mbps全二重、1000=1000Mbps全二重
    • プロパティ未定義時はオートネゴシエーション有効
    • 定義例
&enet0 {
    fsl,pcs-link-speed = <100>; /* 100M Full */
};

または

ethernet@e0000 {
    cell-index = <0>;
    compatible = "fsl,fman-memac";
    reg = <0xe0000 0x1000>;
    fsl,fman-ports = <&fman0_rx_0x08 &fman0_tx_0x28>;
    ptp-timer = <&ptp_timer0>;
    pcsphy-handle = <&pcsphy0>;
    fsl,pcs-link-speed = <100>; /* 100M Full */
};
  • ドライバー改造
diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c
index a847b9c..2eb9942 100644
--- a/drivers/net/ethernet/freescale/fman/mac.c
+++ b/drivers/net/ethernet/freescale/fman/mac.c
@@ -836,6 +836,19 @@ static int mac_probe(struct platform_device *_of_dev)
        priv->fixed_link->asym_pause = phy->asym_pause;
 
        put_device(&phy->mdio.dev);
+   } else if (mac_dev->phy_node && !of_property_read_u32(mac_node, "fsl,pcs-link-speed", &val)) {
+       priv->fixed_link = kzalloc(sizeof(*priv->fixed_link),
+                      GFP_KERNEL);
+       if (!priv->fixed_link) {
+           err = -ENOMEM;
+           goto _return_of_get_parent;
+       }
+
+       priv->fixed_link->link = 1;
+       priv->fixed_link->speed = (int)val;
+       priv->fixed_link->duplex = DUPLEX_FULL;
+       priv->fixed_link->pause = 0;
+       priv->fixed_link->asym_pause = 0;
    }
 
    err = mac_dev->init(mac_dev);