天天看點

88E15xx寄存器配置

我們先來了解一下88E15xx官方文檔的寄存器類型,該類型決定我們要做什麼操作

88E15xx寄存器配置

圖中可以看到如果寄存器中有Retain或者Update都不在軟體重新開機之前生效。這就意味着你在設定寄存時看到這兩個辨別需要額外進行PHY的軟體複位。那麼什麼寄存器在哪裡寫複位資訊呢?那就看下圖:

88E15xx寄存器配置

上面這張圖告訴你,你要想哪個寄存器設定生效,那麼你就需要在對應的複位寄存器中的對應bit寫1,寫完後PHY會自動重新開機。重新開機後你設定的值就會生效。可能有讀者會不明白0_0.15、0_0.15、20_18.15是什麼意思。下面我就來解析一下。

拿20_18.15來說,這段數字描述的意思是18頁的第20個寄存器的第15位,那麼可以推廣一下0_0.15就是0頁的第0個寄存器的第15位。我們可以使用Register_Page.Bit來表示。至于為什麼會有頁,這是由于IEEE802.3中定義了标準的寄存器隻有0到15。廠家為了拓展就使用了分頁分寄存器來管理PHY和把PHY的狀态通過寄存器的方式對外暴露。

說完了上面的圖,現在就舉個例子來說明一下88E15xx寄存器的配置。這裡以配置20_18.2:0為例,第一步需要切換到第18頁,怎麼切換呢?來看圖

88E15xx寄存器配置

圖中紅色的框框表示切換頁面的寄存,你要切換到哪一頁,那麼就往這個寄存器寫對應的頁數就行了。

我們要切換到18頁,那麼就往第22個寄存器寫18,那麼就可以切換過去第18頁了,接着再往第20個寄存器的低3位寫對應模式資料。看圖

88E15xx寄存器配置

下面展示核心代碼中路徑為drivers/net/phy/marvell.c實作配置寄存器的代碼

static int marvell_of_reg_init(struct phy_device *phydev)
{
	const __be32 *paddr;
	int len, i, saved_page, current_page, page_changed, ret;

	if (!phydev->dev.of_node)
		return 0;

	paddr = of_get_property(phydev->dev.of_node, "marvell,reg-init", &len);		//從裝置樹中查找marvell,reg-init的屬性,一般裝置樹中會有 marvell,reg-init = <page reg mask bit>字樣
	if (!paddr || len < (4 * sizeof(*paddr)))
		return 0;

	saved_page = phy_read(phydev, MII_MARVELL_PHY_PAGE);		//該宏就是22,頁轉換寄存器,先讀原來的頁,後面會切換回去
	if (saved_page < 0)
		return saved_page;
	page_changed = 0;
	current_page = saved_page;

	ret = 0;
	len /= sizeof(*paddr);
	for (i = 0; i < len - 3; i += 4) {
		u16 reg_page = be32_to_cpup(paddr + i);		//擷取頁值
		u16 reg = be32_to_cpup(paddr + i + 1);			//擷取寄存器值
		u16 mask = be32_to_cpup(paddr + i + 2);		//你要哪些内容不變
		u16 val_bits = be32_to_cpup(paddr + i + 3);	//你要設定的參數
		int val;

		if (reg_page != current_page) {
			current_page = reg_page;
			page_changed = 1;
			ret = phy_write(phydev, MII_MARVELL_PHY_PAGE, reg_page);
			if (ret < 0)
				goto err;
		}

		val = 0;
		if (mask) {
			val = phy_read(phydev, reg);
			if (val < 0) {
				ret = val;
				goto err;
			}
			val &= mask;
		}
		val |= val_bits;

		ret = phy_write(phydev, reg, val);
		if (ret < 0)
			goto err;

	}
err:
	if (page_changed) {
		i = phy_write(phydev, MII_MARVELL_PHY_PAGE, saved_page);	//配置完切換回去原來的頁
		if (ret == 0)
			ret = i;
	}
	return ret;
}
           

還是用上面的20_18.2:0為例子,我需要設定RGMII to 1000BASE-X模式,那麼就在裝置樹中配置如下:

marvell,reg-init = <0x12 0x14 0xFFF7 0x2> //第18頁 第20頁 你隻需要改低3位,其他不變 1000BASE-X對應2
           

上面的設定了沒有生效,因為有Update字樣。是以還要添加如下

marvell,reg-init = <0x12 0x14 0xFFF7 0x2> //第18頁 第20頁 你隻需要改低3位,其他不變 1000BASE-X對應2
							<0x12 0x14 0x7FFF 0x8000>	//第18頁 第20頁 你隻需要改最高位,其他不變	最高位職位對應0x8000,也就是重新開機PHY
           

最後介紹一下phytool的使用,phytool read ethx/add/reg可以從網卡号為ethx、MDIO位址為add、寄存器位址為reg讀取資料。phytool write ethx/add/reg value把value寫進網卡為ethx、MDIO位址為add、寄存器位址為reg的地方。

如果部落格中有什麼錯誤,歡迎指出~~~

繼續閱讀