Qualcomm IPQ 系列的Ethernet IC 搭配的有 QCA8075, QCA8081 … 等等Qualcomm自家出產的芯片。QSDK中內建可以支持的3rd party芯片,卻寥寥可數。日前,客戶使用车载以太网 - 88Q2112 - Marvell與IPQ6000做搭配。將之記錄下來,以供參考。
方塊圖:
把原本reference board上的QCA8075、QCA8081都換成Marvell的88Q2112。傳輸介面走的protocol也由SGMII+ 、 PSGMII換成SGMII。
IPQ60x8與88Q2112之間有兩個介面,一個是MDC/MDIO的控制介面,一個是GMII的資料傳輸介面。
使用user guide提到的方式,修改DTS
MII node :
所以在本質上應該使用cp02的DTS來做修改。
MDIO node:
改用gpio16來做reset phy的腳位。tlmm的gpio改為gpio16
mdio_pins: mdio_pinmux { …… mux_2 { pins = "gpio16"; function = "gpio"; bias-pull-up; }; }; |
mdio中使用&tlmm 再次指定phy-reset-gpio
mdio: mdio@90000 { pinctrl-0 = <&mdio_pins>; pinctrl-names = "default"; phy-reset-gpio = <&tlmm 16 0>; …… |
後面應該照著原來的設定。因為88Q2112要用Clause 45,所以每個port都要加上compatible="ethernet-phy-ieee802.3-c45"
而那個reg參數 分別對應到 QCA8081的PHYAD[4..2]。
mdio: mdio@90000 { pinctrl-0 = <&mdio_pins>; pinctrl-names = "default"; phy-reset-gpio = <&tlmm 16 0>; status = "ok"; phy0: ethernet-phy@0 { reg = <0x10>; compatible=”ethernet-phy-ieee802.3-c45” }; phy1: ethernet-phy@1 { reg = <0x14>; compatible=”ethernet-phy-ieee802.3-c45” }; }; |
這裡要注意的是 88Q2112 只有定義 PHYAD[2..0],PHYAD[4..3]要填甚麼值需要確認下。當然這個值還是要參考88Q2112的電路bootconf的設定。
ess-switch 應該跟cp02一樣。注意一下phyaddress的設定,以及加上ethernet-phy-ieee802.3-c45;
ess-switch@3a000000 { switch_cpu_bmp = <0x1>; /* cpu port bitmap */ switch_lan_bmp = <0x10>; /* lan port bitmap */ switch_wan_bmp = <0x20>; /* wan port bitmap */ switch_inner_bmp = <0xc0>; /*inner port bitmap*/ switch_mac_mode = <0xf>; /* mac mode for uniphy instance0*/switch_mac_mode1 = <0xf>; /* mac mode for uniphy instance1*/ switch_mac_mode2 = <0xff>; /* mac mode for uniphy instance2*/ qcom,port_phyinfo { port@4 { port_id = <4>; phy_address = <0x10>; port_mac_sel = "QGMAC_PORT"; ethernet-phy-ieee802.3-c45; }; port@5 { port_id = <5>; phy_address = <0x14>; port_mac_sel = "QGMAC_PORT"; ethernet-phy-ieee802.3-c45; }; }; }; |
照理說現在應該可以利用MDIO讀取88Q2112的PHYID。 然後就要看看ssdk中是否有support這個PHY。讓Ethernet Driver可以正常的啟動。
在qsdk/qca/src/qca-ssdk/include/hsl/phy/hsl_phy.h 加個phy id define
/*qca808x_start*/ #define QCA8081_PHY_V1_1 0x004DD101 +#define 88Q2112_PHY 0x002b0983 #define INVALID_PHY_ID 0xFFFFFFFF |
在qsdk/qca/src/qca-ssdk/src/hsl/phy/hsl_phy.c 裡面 借用QCA8081的driver來用。這樣就不用全部重寫。
/*qca808x_start*/ case QCA8081_PHY_V1_1: + case 88Q2112_PHY: phytype = QCA808X_PHY_CHIP; break; |
之後循著 qca-ssdk/src/hsl/phy/qca808x.c, qca808x_phy.c 去debug。
mdio 覺得都無法正常的使用;
ssdk一開始會使用mvl88q_phy_reg_read 這個function。可是marvell的phy不支持Clause22的格式,這個呼叫就會失敗。進而導致異常。所以這裡要直接回應return PHY_INVALID_DATA;給ssdk,讓他不要再使用這個command。
在qca808x_phy.c中有qca808x_phy_reg_read/write, 以及qca808x_phy_mmd_read/write之分,xxx_phy_mmd_read/write 走的就是Clause45的方式來存取phy上的register。
我們在使用mvl88q的時候,就都要改成使用xxx_phy_mmd_read/write的方式。在DTS中加ethernet-phy-ieee802.3-c45;這個參數,無法全面地改用Clause45的方式來存取phy。只會影響部分的api。
尤其是註冊給kernel的ops function。其他模組在調用api的時候,傳進來的參數並沒有附帶c45的flag。 現在明確的分開成兩個api。可以確認,在DUT上可以透過mdio正確的access marvell 88q2112的register了。
因為無法全面使用CAUSE45的方式來存取phy,重新參考aquantia_phy.c 來實作marvell 88Q2112的driver,把最底層讀寫phy reg的函式,套用成 Clause45的格式。
static sw_error_t marvell_phy_reg_read(a_uint32_t dev_id, a_uint32_t phy_id, a_uint32_t reg_mmd, a_uint32_t reg_id, a_uint16_t *phy_data) { sw_error_t rv;
SSDK_INFO("+++++++++++++++++++++++++++++++++++\n"); reg_id = MARVELL_REG_ADDRESS(reg_mmd, reg_id); HSL_PHY_GET(rv, dev_id, phy_id, reg_id, phy_data); SSDK_INFO("+---------------------------------+\n");
return rv; } |
這樣就可以正常的存取Phy了。可見88Q2112 對PHYAD[4..3]是一種Don’t care的狀態。
實際碰到的問題:
在T1 上量測到的波型,像是digital 的訊號。很奇怪。
客人的線路圖中,C110,C113 與C157,C154 使用的數值應該是4700pF。用470pF反而把訊號給濾掉了。把電容換掉,波型就正常,auto nego就正常了。
接著,就一個蘿蔔一個坑的把marvell_phy_api_ops_init 中所指定的call back function 給填寫好就行了。
static int marvell_phy_api_ops_init(void) { int ret; hsl_phy_ops_t *marvell_phy_api_ops = NULL; SSDK_INFO("\n"); SSDK_INFO("+++++++++++++++++++++++++++++++++++\n");
marvell_phy_api_ops = kzalloc(sizeof(hsl_phy_ops_t), GFP_KERNEL); if (marvell_phy_api_ops == NULL) { SSDK_ERROR("marvell phy ops kzalloc failed!\n"); return -ENOMEM; }
phy_api_ops_init(MARVELL_PHY_CHIP);
marvell_phy_api_ops->phy_speed_get = marvell_phy_get_speed; marvell_phy_api_ops->phy_speed_set = marvell_phy_set_speed; marvell_phy_api_ops->phy_duplex_get = marvell_phy_get_duplex; marvell_phy_api_ops->phy_duplex_set = marvell_phy_set_duplex; marvell_phy_api_ops->phy_autoneg_enable_set = marvell_phy_enable_autoneg; marvell_phy_api_ops->phy_restart_autoneg = marvell_phy_restart_autoneg; marvell_phy_api_ops->phy_autoneg_status_get = marvell_phy_autoneg_status; marvell_phy_api_ops->phy_autoneg_adv_set = marvell_phy_set_autoneg_adv; marvell_phy_api_ops->phy_autoneg_adv_get = marvell_phy_get_autoneg_adv; … |
透過QSDK中的ssdk framework,只要follow phy driver的模板把 marvel phy 的api都實作起來。就可以輕鬆地將3’rd party 芯片給porting上了。
參考:
aquantia_phy.c
qca808x_phy.c
linux-4.4\Documentation\devicetree
88Q2110_88Q2112 Datasheet
Marvell New SMI Register Access GUI User Guide
IPQ401x/IPQ806x/IPQ807x NSS Networking Debug User Guide
SOHO Switch Software Development Kit Reference Manual
Q&A:
- 我想換用其他廠牌的Switch IC,高通會幫忙porting嗎?
Ans: 不會,請參考SOHO Switch Software Development Kit Reference Manual自行porting。
- Porting 3’rd party 的Switch/Phy IC 碰到問題,該如何獲得協助?
Ans: 高通本身有完整的產品Switch/Phy IC,基本上不支持porting第三方的IC。Porting 3rd party的switch/phy IC 要靠自己,建議使用高通產品。詮鼎的優質客戶可直接聯繫我們PM。
- 甚麼是Clause45?
- 甚麼是Clause 22?
5. 掛載多的Switch, MDIO介面不夠用怎麼辦?
Ans: MDIO介面可以支持並聯多個Switch的。只要區分好Phy Address就可以。如果真沒辦法,可以使用I2C去模擬送出Clause22以及Clause45的指令,讀寫Switch內的設定。
評論