[v6,06/17] net/r8169: add phy registers access routines

Message ID 20241108121123.248797-7-howard_wang@realsil.com.cn (mailing list archive)
State Changes Requested, archived
Delegated to: Ferruh Yigit
Headers
Series Modify code as suggested by the maintainer. |

Checks

Context Check Description
ci/checkpatch warning coding style issues

Commit Message

Howard Wang Nov. 8, 2024, 12:11 p.m. UTC
Signed-off-by: Howard Wang <howard_wang@realsil.com.cn>
---
 drivers/net/r8169/r8169_ethdev.h |   1 +
 drivers/net/r8169/r8169_hw.c     |   2 +-
 drivers/net/r8169/r8169_phy.c    | 219 +++++++++++++++++++++++++++++++
 drivers/net/r8169/r8169_phy.h    |  18 +++
 4 files changed, 239 insertions(+), 1 deletion(-)
  

Patch

diff --git a/drivers/net/r8169/r8169_ethdev.h b/drivers/net/r8169/r8169_ethdev.h
index ac0b3eef47..0d4e6079e0 100644
--- a/drivers/net/r8169/r8169_ethdev.h
+++ b/drivers/net/r8169/r8169_ethdev.h
@@ -16,6 +16,7 @@  struct rtl_hw {
 	u8  *mmio_addr;
 	u32 mcfg;
 	u8  HwSuppIntMitiVer;
+	u16 cur_page;
 
 	/* Enable Tx No Close */
 	u8 EnableTxNoClose;
diff --git a/drivers/net/r8169/r8169_hw.c b/drivers/net/r8169/r8169_hw.c
index 52c387c8e7..9bf3437c6a 100644
--- a/drivers/net/r8169/r8169_hw.c
+++ b/drivers/net/r8169/r8169_hw.c
@@ -355,7 +355,7 @@  void
 rtl_disable_rxdvgate(struct rtl_hw *hw)
 {
 	switch (hw->mcfg) {
-	case CFG_METHOD_1 ... CFG_METHOD_3:
+	case CFG_METHOD_69 ... CFG_METHOD_71:
 		RTL_W8(hw, 0xF2, RTL_R8(hw, 0xF2) & ~BIT_3);
 		rte_delay_ms(2);
 	}
diff --git a/drivers/net/r8169/r8169_phy.c b/drivers/net/r8169/r8169_phy.c
index 11c28deefe..853e1d4922 100644
--- a/drivers/net/r8169/r8169_phy.c
+++ b/drivers/net/r8169/r8169_phy.c
@@ -36,3 +36,222 @@  rtl_set_mac_ocp_bit(struct rtl_hw *hw, u16 addr, u16 mask)
 {
 	rtl_clear_set_mac_ocp_bit(hw, addr, 0, mask);
 }
+
+static u16
+rtl_map_phy_ocp_addr(u16 PageNum, u8 RegNum)
+{
+	u8 ocp_reg_num = 0;
+	u16 ocp_page_num = 0;
+	u16 ocp_phy_address = 0;
+
+	if (PageNum == 0) {
+		ocp_page_num = OCP_STD_PHY_BASE_PAGE + (RegNum / 8);
+		ocp_reg_num = 0x10 + (RegNum % 8);
+	} else {
+		ocp_page_num = PageNum;
+		ocp_reg_num = RegNum;
+	}
+
+	ocp_page_num <<= 4;
+
+	if (ocp_reg_num < 16) {
+		ocp_phy_address = 0;
+	} else {
+		ocp_reg_num -= 16;
+		ocp_reg_num <<= 1;
+
+		ocp_phy_address = ocp_page_num + ocp_reg_num;
+	}
+
+	return ocp_phy_address;
+}
+
+static u32
+rtl_mdio_real_read_phy_ocp(struct rtl_hw *hw, u32 RegAddr)
+{
+	u32 data32;
+	int i, value = 0;
+
+	data32 = RegAddr / 2;
+	data32 <<= OCPR_Addr_Reg_shift;
+
+	RTL_W32(hw, PHYOCP, data32);
+	for (i = 0; i < 100; i++) {
+		rte_delay_us(1);
+
+		if (RTL_R32(hw, PHYOCP) & OCPR_Flag)
+			break;
+	}
+	value = RTL_R32(hw, PHYOCP) & OCPDR_Data_Mask;
+
+	return value;
+}
+
+u32
+rtl_mdio_direct_read_phy_ocp(struct rtl_hw *hw, u32 RegAddr)
+{
+	return rtl_mdio_real_read_phy_ocp(hw, RegAddr);
+}
+
+static u32
+rtl_mdio_read_phy_ocp(struct rtl_hw *hw, u16 PageNum, u32 RegAddr)
+{
+	u16 ocp_addr;
+
+	ocp_addr = rtl_map_phy_ocp_addr(PageNum, RegAddr);
+
+	return rtl_mdio_direct_read_phy_ocp(hw, ocp_addr);
+}
+
+static u32
+rtl_mdio_real_read(struct rtl_hw *hw, u32 RegAddr)
+{
+	return rtl_mdio_read_phy_ocp(hw, hw->cur_page, RegAddr);
+}
+
+static void
+rtl_mdio_real_write_phy_ocp(struct rtl_hw *hw, u32 RegAddr, u32 value)
+{
+	u32 data32;
+	int i;
+
+	data32 = RegAddr / 2;
+	data32 <<= OCPR_Addr_Reg_shift;
+	data32 |= OCPR_Write | value;
+
+	RTL_W32(hw, PHYOCP, data32);
+	for (i = 0; i < 100; i++) {
+		rte_delay_us(1);
+
+		if (!(RTL_R32(hw, PHYOCP) & OCPR_Flag))
+			break;
+	}
+}
+
+void
+rtl_mdio_direct_write_phy_ocp(struct rtl_hw *hw, u32 RegAddr, u32 value)
+{
+	rtl_mdio_real_write_phy_ocp(hw, RegAddr, value);
+}
+
+static void
+rtl_mdio_write_phy_ocp(struct rtl_hw *hw, u16 PageNum, u32 RegAddr, u32 value)
+{
+	u16 ocp_addr;
+
+	ocp_addr = rtl_map_phy_ocp_addr(PageNum, RegAddr);
+
+	rtl_mdio_direct_write_phy_ocp(hw, ocp_addr, value);
+}
+
+static void
+rtl_mdio_real_write(struct rtl_hw *hw, u32 RegAddr, u32 value)
+{
+	if (RegAddr == 0x1F)
+		hw->cur_page = value;
+	rtl_mdio_write_phy_ocp(hw, hw->cur_page, RegAddr, value);
+}
+
+u32
+rtl_mdio_read(struct rtl_hw *hw, u32 RegAddr)
+{
+	return rtl_mdio_real_read(hw, RegAddr);
+}
+
+void
+rtl_mdio_write(struct rtl_hw *hw, u32 RegAddr, u32 value)
+{
+	rtl_mdio_real_write(hw, RegAddr, value);
+}
+
+void
+rtl_clear_and_set_eth_phy_ocp_bit(struct rtl_hw *hw, u16 addr, u16 clearmask,
+				  u16 setmask)
+{
+	u16 phy_reg_value;
+
+	phy_reg_value = rtl_mdio_direct_read_phy_ocp(hw, addr);
+	phy_reg_value &= ~clearmask;
+	phy_reg_value |= setmask;
+	rtl_mdio_direct_write_phy_ocp(hw, addr, phy_reg_value);
+}
+
+void
+rtl_clear_eth_phy_ocp_bit(struct rtl_hw *hw, u16 addr, u16 mask)
+{
+	rtl_clear_and_set_eth_phy_ocp_bit(hw, addr, mask, 0);
+}
+
+void
+rtl_set_eth_phy_ocp_bit(struct rtl_hw *hw, u16 addr, u16 mask)
+{
+	rtl_clear_and_set_eth_phy_ocp_bit(hw, addr, 0, mask);
+}
+
+void
+rtl_ephy_write(struct rtl_hw *hw, int addr, int value)
+{
+	int i;
+
+	RTL_W32(hw, EPHYAR, EPHYAR_Write |
+		(addr & EPHYAR_Reg_Mask_v2) << EPHYAR_Reg_shift |
+		(value & EPHYAR_Data_Mask));
+
+	for (i = 0; i < 10; i++) {
+		rte_delay_us(100);
+
+		/* Check if the NIC has completed EPHY write */
+		if (!(RTL_R32(hw, EPHYAR) & EPHYAR_Flag))
+			break;
+	}
+
+	rte_delay_us(20);
+}
+
+static u16
+rtl_ephy_read(struct rtl_hw *hw, int addr)
+{
+	int i;
+	u16 value = 0xffff;
+
+	RTL_W32(hw, EPHYAR, EPHYAR_Read | (addr & EPHYAR_Reg_Mask_v2) <<
+		EPHYAR_Reg_shift);
+
+	for (i = 0; i < 10; i++) {
+		rte_delay_us(100);
+
+		/* Check if the NIC has completed EPHY read */
+		if (RTL_R32(hw, EPHYAR) & EPHYAR_Flag) {
+			value = (u16)(RTL_R32(hw, EPHYAR) & EPHYAR_Data_Mask);
+			break;
+		}
+	}
+
+	rte_delay_us(20);
+
+	return value;
+}
+
+void
+rtl_clear_and_set_pcie_phy_bit(struct rtl_hw *hw, u8 addr, u16 clearmask,
+			       u16 setmask)
+{
+	u16 ephy_value;
+
+	ephy_value = rtl_ephy_read(hw, addr);
+	ephy_value &= ~clearmask;
+	ephy_value |= setmask;
+	rtl_ephy_write(hw, addr, ephy_value);
+}
+
+void
+rtl_clear_pcie_phy_bit(struct rtl_hw *hw, u8 addr, u16 mask)
+{
+	rtl_clear_and_set_pcie_phy_bit(hw, addr, mask, 0);
+}
+
+void
+rtl_set_pcie_phy_bit(struct rtl_hw *hw, u8 addr, u16 mask)
+{
+	rtl_clear_and_set_pcie_phy_bit(hw, addr, 0, mask);
+}
diff --git a/drivers/net/r8169/r8169_phy.h b/drivers/net/r8169/r8169_phy.h
index ee2aa43fde..66c487210f 100644
--- a/drivers/net/r8169/r8169_phy.h
+++ b/drivers/net/r8169/r8169_phy.h
@@ -16,4 +16,22 @@ 
 void rtl_clear_mac_ocp_bit(struct rtl_hw *hw, u16 addr, u16 mask);
 void rtl_set_mac_ocp_bit(struct rtl_hw *hw, u16 addr, u16 mask);
 
+u32 rtl_mdio_direct_read_phy_ocp(struct rtl_hw *hw, u32 RegAddr);
+void rtl_mdio_direct_write_phy_ocp(struct rtl_hw *hw, u32 RegAddr, u32 value);
+
+u32 rtl_mdio_read(struct rtl_hw *hw, u32 RegAddr);
+void rtl_mdio_write(struct rtl_hw *hw, u32 RegAddr, u32 value);
+
+void rtl_clear_and_set_eth_phy_ocp_bit(struct rtl_hw *hw, u16 addr,
+				       u16 clearmask, u16 setmask);
+void rtl_clear_eth_phy_ocp_bit(struct rtl_hw *hw, u16 addr, u16 mask);
+void rtl_set_eth_phy_ocp_bit(struct rtl_hw *hw, u16 addr, u16 mask);
+
+void rtl_ephy_write(struct rtl_hw *hw, int addr, int value);
+
+void rtl_clear_and_set_pcie_phy_bit(struct rtl_hw *hw, u8 addr, u16 clearmask,
+				    u16 setmask);
+void rtl_clear_pcie_phy_bit(struct rtl_hw *hw, u8 addr, u16 mask);
+void rtl_set_pcie_phy_bit(struct rtl_hw *hw, u8 addr, u16 mask);
+
 #endif