天天看點

Ambarella Ethernet PHY rtl9000 Linux driver 調試Ambarella Ethernet PHY rtl9000 Linux driver 調試

Ambarella Ethernet PHY rtl9000 Linux driver 調試

記錄在ambarella CV22平台 調試rtl9000 phy驅動。

rtl9000 工作原理

如圖,PHY使用标準的mac和phy的接口,rtl9000支援rgmii/rmii/mii和mdio/mdc接口,還有reset和外部供電,外部晶振接口。

另外硬體上還需要配置rtl9000的addr和硬體接口。

Ambarella Ethernet PHY rtl9000 Linux driver 調試Ambarella Ethernet PHY rtl9000 Linux driver 調試
Ambarella Ethernet PHY rtl9000 Linux driver 調試Ambarella Ethernet PHY rtl9000 Linux driver 調試
Ambarella Ethernet PHY rtl9000 Linux driver 調試Ambarella Ethernet PHY rtl9000 Linux driver 調試

ambarella dts配置

mac0: [email protected] {
			amb,tx-clk-invert;
			pinctrl-0 = <&rmii_pins &ahb_mdio_pins>;
			amb,ahb-12mhz-div = <5>;
			phy-mode = "rmii";
			amb,ext-ref-clk;
			[email protected] {
				reg = <0>;
				rst-gpios = <&gpio 29 0>;
			};

		};
           

驅動修改

ambarella\kernel\linux-4.14\drivers\net\phy\realtek.c

static struct phy_driver realtek_drvs[] = {
	{
		.phy_id		= 0x001ccb00,
		.name		= "RTL9000 Gigabit Ethernet",
		.phy_id_mask	= 0x001fffff,
		.features       = PHY_BASIC_FEATURES,
		.flags		= PHY_HAS_INTERRUPT,
		.probe = rtl9000_probe,
		.config_aneg	= &rtl9000_config_aneg,
		.aneg_done	= &rtl9000_aneg_done,
		.config_init	= &rtl9000_config_init,
		.read_status	= &rtl9000_read_status,
		.ack_interrupt	= &rtl9000_ack_interrupt,
		.config_intr	= &rtl9000_config_intr,
		.suspend	= genphy_suspend,
		.resume		= genphy_resume,
	},
};

module_phy_driver(realtek_drvs);

static struct mdio_device_id __maybe_unused realtek_tbl[] = {
	{ 0x001ccb00, 0x001fffff },
	{ }
};
           

最重要需要實作的幾個個函數:

.config_aneg	= &rtl9000_config_aneg,
.aneg_done	= &rtl9000_aneg_done,
.config_init	= &rtl9000_config_init,
.read_status	= &rtl9000_read_status,
           

在phy的驅動架構中要求我們必須實作config_aneg和read_status這兩個函數。

Ambarella Ethernet PHY rtl9000 Linux driver 調試Ambarella Ethernet PHY rtl9000 Linux driver 調試

ping不通問題

在調試過程中,發現PHY的id已經讀到了,網卡裝置也建立成功,mac位址也有。但是ping不通主機。

解決:通過ethtool eth0檢視網絡狀态,發現不正确,修改read_status函數如下,可以正常ping通。

static int rtl9000_read_status(struct phy_device *phydev)
{
	
	phydev->duplex = DUPLEX_FULL;
	phydev->speed = SPEED_100;
	phydev->pause = 0;
	phydev->asym_pause = 0;

	phydev->link = 1;
	return 0;
	
}
           
Ambarella Ethernet PHY rtl9000 Linux driver 調試Ambarella Ethernet PHY rtl9000 Linux driver 調試
Ambarella Ethernet PHY rtl9000 Linux driver 調試Ambarella Ethernet PHY rtl9000 Linux driver 調試