Implement the rtl_hw_config function to configure the hardware.

Signed-off-by: Howard Wang <howard_w...@realsil.com.cn>
---
 drivers/net/r8169/meson.build    |   1 +
 drivers/net/r8169/r8169_base.h   | 125 ++++++
 drivers/net/r8169/r8169_ethdev.c |   2 +
 drivers/net/r8169/r8169_ethdev.h |  15 +-
 drivers/net/r8169/r8169_hw.c     | 710 +++++++++++++++++++++++++++++++
 drivers/net/r8169/r8169_hw.h     |  17 +
 drivers/net/r8169/r8169_phy.c    |  41 ++
 drivers/net/r8169/r8169_phy.h    |  21 +
 8 files changed, 930 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/r8169/r8169_phy.c
 create mode 100644 drivers/net/r8169/r8169_phy.h

diff --git a/drivers/net/r8169/meson.build b/drivers/net/r8169/meson.build
index ff7d6ca4b8..56f857ac8c 100644
--- a/drivers/net/r8169/meson.build
+++ b/drivers/net/r8169/meson.build
@@ -5,5 +5,6 @@ sources = files(
                'r8169_ethdev.c',
                'r8169_hw.c',
                'r8169_rxtx.c',
+               'r8169_phy.c',
 )
 
diff --git a/drivers/net/r8169/r8169_base.h b/drivers/net/r8169/r8169_base.h
index 0e79d8d22a..2e72faeb2c 100644
--- a/drivers/net/r8169/r8169_base.h
+++ b/drivers/net/r8169/r8169_base.h
@@ -23,6 +23,117 @@ typedef uint16_t  u16;
 typedef uint32_t  u32;
 typedef uint64_t  u64;
 
+enum mcfg {
+       CFG_METHOD_1 = 1,
+       CFG_METHOD_2,
+       CFG_METHOD_3,
+       CFG_METHOD_4,
+       CFG_METHOD_5,
+       CFG_METHOD_6,
+       CFG_METHOD_7,
+       CFG_METHOD_8,
+       CFG_METHOD_9,
+       CFG_METHOD_10,
+       CFG_METHOD_11,
+       CFG_METHOD_12,
+       CFG_METHOD_13,
+       CFG_METHOD_14,
+       CFG_METHOD_15,
+       CFG_METHOD_16,
+       CFG_METHOD_17,
+       CFG_METHOD_18,
+       CFG_METHOD_19,
+       CFG_METHOD_20,
+       CFG_METHOD_21,
+       CFG_METHOD_22,
+       CFG_METHOD_23,
+       CFG_METHOD_24,
+       CFG_METHOD_25,
+       CFG_METHOD_26,
+       CFG_METHOD_27,
+       CFG_METHOD_28,
+       CFG_METHOD_29,
+       CFG_METHOD_30,
+       CFG_METHOD_31,
+       CFG_METHOD_32,
+       CFG_METHOD_33,
+       CFG_METHOD_34,
+       CFG_METHOD_35,
+       CFG_METHOD_36,
+       CFG_METHOD_37,
+       CFG_METHOD_38,
+       CFG_METHOD_39,
+       CFG_METHOD_40,
+       CFG_METHOD_41,
+       CFG_METHOD_42,
+       CFG_METHOD_43,
+       CFG_METHOD_44,
+       CFG_METHOD_45,
+       CFG_METHOD_46,
+       CFG_METHOD_47,
+       CFG_METHOD_48,
+       CFG_METHOD_49,
+       CFG_METHOD_50,
+       CFG_METHOD_51,
+       CFG_METHOD_52,
+       CFG_METHOD_53,
+       CFG_METHOD_54,
+       CFG_METHOD_55,
+       CFG_METHOD_56,
+       CFG_METHOD_57,
+       CFG_METHOD_58,
+       CFG_METHOD_59,
+       CFG_METHOD_60,
+       CFG_METHOD_61,
+       CFG_METHOD_62,
+       CFG_METHOD_63,
+       CFG_METHOD_64,
+       CFG_METHOD_65,
+       CFG_METHOD_66,
+       CFG_METHOD_67,
+       CFG_METHOD_68,
+       CFG_METHOD_69,
+       CFG_METHOD_70,
+       CFG_METHOD_71,
+       CFG_METHOD_MAX,
+       CFG_METHOD_DEFAULT = 0xFF
+};
+
+enum bits {
+       BIT_0 = (1UL << 0),
+       BIT_1 = (1UL << 1),
+       BIT_2 = (1UL << 2),
+       BIT_3 = (1UL << 3),
+       BIT_4 = (1UL << 4),
+       BIT_5 = (1UL << 5),
+       BIT_6 = (1UL << 6),
+       BIT_7 = (1UL << 7),
+       BIT_8 = (1UL << 8),
+       BIT_9 = (1UL << 9),
+       BIT_10 = (1UL << 10),
+       BIT_11 = (1UL << 11),
+       BIT_12 = (1UL << 12),
+       BIT_13 = (1UL << 13),
+       BIT_14 = (1UL << 14),
+       BIT_15 = (1UL << 15),
+       BIT_16 = (1UL << 16),
+       BIT_17 = (1UL << 17),
+       BIT_18 = (1UL << 18),
+       BIT_19 = (1UL << 19),
+       BIT_20 = (1UL << 20),
+       BIT_21 = (1UL << 21),
+       BIT_22 = (1UL << 22),
+       BIT_23 = (1UL << 23),
+       BIT_24 = (1UL << 24),
+       BIT_25 = (1UL << 25),
+       BIT_26 = (1UL << 26),
+       BIT_27 = (1UL << 27),
+       BIT_28 = (1UL << 28),
+       BIT_29 = (1UL << 29),
+       BIT_30 = (1UL << 30),
+       BIT_31 = (1UL << 31)
+};
+
 enum RTL_registers {
        MAC0            = 0x00,     /* Ethernet hardware address */
        MAC4            = 0x04,
@@ -363,6 +474,8 @@ enum RTL_register_content {
        INT_CFG0_ENABLE_8125            = (1 << 0),
        INT_CFG0_TIMEOUT0_BYPASS_8125   = (1 << 1),
        INT_CFG0_MITIGATION_BYPASS_8125 = (1 << 2),
+       INT_CFG0_RDU_BYPASS_8126        = (1 << 4),
+       INT_CFG0_MSIX_ENTRY_NUM_MODE    = (1 << 5),
        ISRIMR_V2_ROK_Q0     = (1 << 0),
        ISRIMR_TOK_Q0        = (1 << 16),
        ISRIMR_TOK_Q1        = (1 << 18),
@@ -389,6 +502,18 @@ enum RTL_register_content {
 #define msleep rte_delay_ms
 #define usleep rte_delay_us
 
+#define RX_DMA_BURST_unlimited  7   /* Maximum PCI burst, '7' is unlimited */
+#define RX_DMA_BURST_512    5
+#define TX_DMA_BURST_unlimited  7
+#define TX_DMA_BURST_1024   6
+#define TX_DMA_BURST_512    5
+#define TX_DMA_BURST_256    4
+#define TX_DMA_BURST_128    3
+#define TX_DMA_BURST_64     2
+#define TX_DMA_BURST_32     1
+#define TX_DMA_BURST_16     0
+#define InterFrameGap       0x03    /* 3 means InterFrameGap = the shortest 
one */
+
 static inline u32
 rtl_read32(volatile void *addr)
 {
diff --git a/drivers/net/r8169/r8169_ethdev.c b/drivers/net/r8169/r8169_ethdev.c
index 92121ad3fb..a23370c6a1 100644
--- a/drivers/net/r8169/r8169_ethdev.c
+++ b/drivers/net/r8169/r8169_ethdev.c
@@ -72,6 +72,8 @@ rtl_dev_start(struct rte_eth_dev *dev)
        struct rtl_hw *hw = &adapter->hw;
        int err;
 
+       rtl_hw_config(hw);
+
        /* Initialize transmission unit */
        rtl_tx_init(dev);
 
diff --git a/drivers/net/r8169/r8169_ethdev.h b/drivers/net/r8169/r8169_ethdev.h
index 7c6e110e7f..20dbf06c9b 100644
--- a/drivers/net/r8169/r8169_ethdev.h
+++ b/drivers/net/r8169/r8169_ethdev.h
@@ -14,8 +14,19 @@
 #include "r8169_base.h"
 
 struct rtl_hw {
-       u8 adapter_stopped;
-       u8 *mmio_addr;
+       u8  adapter_stopped;
+       u8  *mmio_addr;
+       u32 mcfg;
+       u8  HwSuppIntMitiVer;
+
+       /* Enable Tx No Close */
+       u8 EnableTxNoClose;
+
+       /* Dash */
+       u8 HwSuppDashVer;
+       u8 DASH;
+       u8 HwSuppOcpChannelVer;
+       u8 AllowAccessDashOcp;
 };
 
 struct rtl_sw_stats {
diff --git a/drivers/net/r8169/r8169_hw.c b/drivers/net/r8169/r8169_hw.c
index b3c0c23ecf..06d2ca27d9 100644
--- a/drivers/net/r8169/r8169_hw.c
+++ b/drivers/net/r8169/r8169_hw.c
@@ -14,6 +14,257 @@
 #include "r8169_hw.h"
 #include "r8169_logs.h"
 
+static u32
+rtl_eri_read_with_oob_base_address(struct rtl_hw *hw, int addr, int len,
+                                   int type, const u32 base_address)
+{
+       int i, val_shift, shift = 0;
+       u32 value1 = 0;
+       u32 value2 = 0;
+       u32 eri_cmd, tmp, mask;
+       const u32 transformed_base_address = ((base_address & 0x00FFF000) << 6) 
|
+                                            (base_address & 0x000FFF);
+
+       if (len > 4 || len <= 0)
+               return -1;
+
+       while (len > 0) {
+               val_shift = addr % ERIAR_Addr_Align;
+               addr = addr & ~0x3;
+
+               eri_cmd = ERIAR_Read | transformed_base_address |
+                         type << ERIAR_Type_shift |
+                         ERIAR_ByteEn << ERIAR_ByteEn_shift |
+                         (addr & 0x0FFF);
+               if (addr & 0xF000) {
+                       tmp = addr & 0xF000;
+                       tmp >>= 12;
+                       eri_cmd |= (tmp << 20) & 0x00F00000;
+               }
+
+               RTL_W32(hw, ERIAR, eri_cmd);
+
+               for (i = 0; i < RTL_CHANNEL_WAIT_COUNT; i++) {
+                       udelay(RTL_CHANNEL_WAIT_TIME);
+
+                       /* Check if the NIC has completed ERI read */
+                       if (RTL_R32(hw, ERIAR) & ERIAR_Flag)
+                               break;
+               }
+
+               if (len == 1)
+                       mask = (0xFF << (val_shift * 8)) & 0xFFFFFFFF;
+               else if (len == 2)
+                       mask = (0xFFFF << (val_shift * 8)) & 0xFFFFFFFF;
+               else if (len == 3)
+                       mask = (0xFFFFFF << (val_shift * 8)) & 0xFFFFFFFF;
+               else
+                       mask = (0xFFFFFFFF << (val_shift * 8)) & 0xFFFFFFFF;
+
+               value1 = RTL_R32(hw, ERIDR) & mask;
+               value2 |= (value1 >> val_shift * 8) << shift * 8;
+
+               if (len <= 4 - val_shift)
+                       len = 0;
+               else {
+                       len -= (4 - val_shift);
+                       shift = 4 - val_shift;
+                       addr += 4;
+               }
+       }
+
+       udelay(RTL_CHANNEL_EXIT_DELAY_TIME);
+
+       return value2;
+}
+
+static int
+rtl_eri_write_with_oob_base_address(struct rtl_hw *hw, int addr,
+                                    int len, u32 value, int type, const u32 
base_address)
+{
+       int i, val_shift, shift = 0;
+       u32 value1 = 0;
+       u32 eri_cmd, mask, tmp;
+       const u32 transformed_base_address = ((base_address & 0x00FFF000) << 6) 
|
+                                            (base_address & 0x000FFF);
+
+       if (len > 4 || len <= 0)
+               return -1;
+
+       while (len > 0) {
+               val_shift = addr % ERIAR_Addr_Align;
+               addr = addr & ~0x3;
+
+               if (len == 1)
+                       mask = (0xFF << (val_shift * 8)) & 0xFFFFFFFF;
+               else if (len == 2)
+                       mask = (0xFFFF << (val_shift * 8)) & 0xFFFFFFFF;
+               else if (len == 3)
+                       mask = (0xFFFFFF << (val_shift * 8)) & 0xFFFFFFFF;
+               else
+                       mask = (0xFFFFFFFF << (val_shift * 8)) & 0xFFFFFFFF;
+
+               value1 = rtl_eri_read_with_oob_base_address(hw, addr, 4, type,
+                               base_address) & ~mask;
+               value1 |= ((value << val_shift * 8) >> shift * 8);
+
+               RTL_W32(hw, ERIDR, value1);
+
+               eri_cmd = ERIAR_Write | transformed_base_address |
+                         type << ERIAR_Type_shift |
+                         ERIAR_ByteEn << ERIAR_ByteEn_shift |
+                         (addr & 0x0FFF);
+               if (addr & 0xF000) {
+                       tmp = addr & 0xF000;
+                       tmp >>= 12;
+                       eri_cmd |= (tmp << 20) & 0x00F00000;
+               }
+
+               RTL_W32(hw, ERIAR, eri_cmd);
+
+               for (i = 0; i < RTL_CHANNEL_WAIT_COUNT; i++) {
+                       udelay(RTL_CHANNEL_WAIT_TIME);
+
+                       /* Check if the NIC has completed ERI write */
+                       if (!(RTL_R32(hw, ERIAR) & ERIAR_Flag))
+                               break;
+               }
+
+               if (len <= 4 - val_shift)
+                       len = 0;
+               else {
+                       len -= (4 - val_shift);
+                       shift = 4 - val_shift;
+                       addr += 4;
+               }
+       }
+
+       udelay(RTL_CHANNEL_EXIT_DELAY_TIME);
+
+       return 0;
+}
+
+static u32
+rtl_ocp_read_with_oob_base_address(struct rtl_hw *hw, u16 addr, u8 len,
+                                   const u32 base_address)
+{
+       return rtl_eri_read_with_oob_base_address(hw, addr, len, ERIAR_OOB,
+                       base_address);
+}
+
+u32
+rtl_ocp_read(struct rtl_hw *hw, u16 addr, u8 len)
+{
+       u32 value = 0;
+
+       if (!hw->AllowAccessDashOcp)
+               return 0xffffffff;
+
+       if (hw->HwSuppOcpChannelVer == 2)
+               value = rtl_ocp_read_with_oob_base_address(hw, addr, len, 
NO_BASE_ADDRESS);
+
+       return value;
+}
+
+static u32
+rtl_ocp_write_with_oob_base_address(struct rtl_hw *hw, u16 addr, u8 len,
+                                    u32 value, const u32 base_address)
+{
+       return rtl_eri_write_with_oob_base_address(hw, addr, len, value, 
ERIAR_OOB,
+                       base_address);
+}
+
+void
+rtl_ocp_write(struct rtl_hw *hw, u16 addr, u8 len, u32 value)
+{
+       if (!hw->AllowAccessDashOcp)
+               return;
+
+       if (hw->HwSuppOcpChannelVer == 2)
+               rtl_ocp_write_with_oob_base_address(hw, addr, len, value, 
NO_BASE_ADDRESS);
+}
+
+void
+rtl8125_oob_mutex_lock(struct rtl_hw *hw)
+{
+       u8 reg_16, reg_a0;
+       u16 ocp_reg_mutex_ib;
+       u16 ocp_reg_mutex_oob;
+       u16 ocp_reg_mutex_prio;
+       u32 wait_cnt_0, wait_cnt_1;
+
+       if (!hw->DASH)
+               return;
+
+       switch (hw->mcfg) {
+       case CFG_METHOD_48:
+       case CFG_METHOD_49:
+       case CFG_METHOD_52:
+       case CFG_METHOD_54:
+       case CFG_METHOD_55:
+               ocp_reg_mutex_oob = 0x110;
+               ocp_reg_mutex_ib = 0x114;
+               ocp_reg_mutex_prio = 0x11C;
+               break;
+       default:
+               return;
+       }
+
+       rtl_ocp_write(hw, ocp_reg_mutex_ib, 1, BIT_0);
+       reg_16 = rtl_ocp_read(hw, ocp_reg_mutex_oob, 1);
+       wait_cnt_0 = 0;
+       while (reg_16) {
+               reg_a0 = rtl_ocp_read(hw, ocp_reg_mutex_prio, 1);
+               if (reg_a0) {
+                       rtl_ocp_write(hw, ocp_reg_mutex_ib, 1, 0x00);
+                       reg_a0 = rtl_ocp_read(hw, ocp_reg_mutex_prio, 1);
+                       wait_cnt_1 = 0;
+                       while (reg_a0) {
+                               reg_a0 = rtl_ocp_read(hw, ocp_reg_mutex_prio, 
1);
+
+                               wait_cnt_1++;
+
+                               if (wait_cnt_1 > 2000)
+                                       break;
+                       };
+                       rtl_ocp_write(hw, ocp_reg_mutex_ib, 1, BIT_0);
+
+               }
+               reg_16 = rtl_ocp_read(hw, ocp_reg_mutex_oob, 1);
+
+               wait_cnt_0++;
+
+               if (wait_cnt_0 > 2000)
+                       break;
+       };
+}
+
+void
+rtl8125_oob_mutex_unlock(struct rtl_hw *hw)
+{
+       u16 ocp_reg_mutex_ib;
+       u16 ocp_reg_mutex_prio;
+
+       if (!hw->DASH)
+               return;
+
+       switch (hw->mcfg) {
+       case CFG_METHOD_48:
+       case CFG_METHOD_49:
+       case CFG_METHOD_52:
+       case CFG_METHOD_54:
+       case CFG_METHOD_55:
+               ocp_reg_mutex_ib = 0x114;
+               ocp_reg_mutex_prio = 0x11C;
+               break;
+       default:
+               return;
+       }
+
+       rtl_ocp_write(hw, ocp_reg_mutex_prio, 1, BIT_0);
+       rtl_ocp_write(hw, ocp_reg_mutex_ib, 1, 0x00);
+}
+
 void
 rtl_mac_ocp_write(struct rtl_hw *hw, u16 addr, u16 value)
 {
@@ -92,3 +343,462 @@ rtl_csi_write(struct rtl_hw *hw, u32 addr, u32 value)
        udelay(RTL_CHANNEL_EXIT_DELAY_TIME);
 }
 
+static void
+rtl_enable_rxdvgate(struct rtl_hw *hw)
+{
+       switch (hw->mcfg) {
+       case CFG_METHOD_48 ... CFG_METHOD_57:
+       case CFG_METHOD_69 ... CFG_METHOD_71:
+               RTL_W8(hw, 0xF2, RTL_R8(hw, 0xF2) | BIT_3);
+               mdelay(2);
+       }
+}
+
+void
+rtl_disable_rxdvgate(struct rtl_hw *hw)
+{
+       switch (hw->mcfg) {
+       case CFG_METHOD_1 ... CFG_METHOD_3:
+               RTL_W8(hw, 0xF2, RTL_R8(hw, 0xF2) & ~BIT_3);
+               mdelay(2);
+       }
+}
+
+static void
+rtl_stop_all_request(struct rtl_hw *hw)
+{
+       int i;
+
+       RTL_W8(hw, ChipCmd, RTL_R8(hw, ChipCmd) | StopReq);
+
+       switch (hw->mcfg) {
+       case CFG_METHOD_48:
+       case CFG_METHOD_49:
+       case CFG_METHOD_52:
+               for (i = 0; i < 20; i++) {
+                       udelay(10);
+                       if (!(RTL_R8(hw, ChipCmd) & StopReq))
+                               break;
+               }
+
+               break;
+       default:
+               udelay(200);
+               break;
+       }
+
+       RTL_W8(hw, ChipCmd, RTL_R8(hw, ChipCmd) & (CmdTxEnb | CmdRxEnb));
+}
+
+static void
+rtl_wait_txrx_fifo_empty(struct rtl_hw *hw)
+{
+       int i;
+
+       switch (hw->mcfg) {
+       case CFG_METHOD_48 ... CFG_METHOD_57:
+       case CFG_METHOD_69 ... CFG_METHOD_71:
+               for (i = 0; i < 3000; i++) {
+                       udelay(50);
+                       if ((RTL_R8(hw, MCUCmd_reg) & (Txfifo_empty | 
Rxfifo_empty)) ==
+                           (Txfifo_empty | Rxfifo_empty))
+                               break;
+               }
+               break;
+       }
+
+       switch (hw->mcfg) {
+       case CFG_METHOD_50:
+       case CFG_METHOD_51:
+       case CFG_METHOD_53 ... CFG_METHOD_57:
+       case CFG_METHOD_69 ... CFG_METHOD_71:
+               for (i = 0; i < 3000; i++) {
+                       udelay(50);
+                       if ((RTL_R16(hw, IntrMitigate) & (BIT_0 | BIT_1 | 
BIT_8)) ==
+                           (BIT_0 | BIT_1 | BIT_8))
+                               break;
+               }
+               break;
+       }
+}
+
+static void
+rtl_disable_rx_packet_filter(struct rtl_hw *hw)
+{
+       RTL_W32(hw, RxConfig, RTL_R32(hw, RxConfig) &
+               ~(AcceptErr | AcceptRunt | AcceptBroadcast | AcceptMulticast |
+                 AcceptMyPhys | AcceptAllPhys));
+}
+
+void
+rtl_nic_reset(struct rtl_hw *hw)
+{
+       int i;
+
+       rtl_disable_rx_packet_filter(hw);
+
+       rtl_enable_rxdvgate(hw);
+
+       rtl_stop_all_request(hw);
+
+       rtl_wait_txrx_fifo_empty(hw);
+
+       mdelay(2);
+
+       /* Soft reset the chip. */
+       RTL_W8(hw, ChipCmd, CmdReset);
+
+       /* Check that the chip has finished the reset. */
+       for (i = 100; i > 0; i--) {
+               udelay(100);
+               if ((RTL_R8(hw, ChipCmd) & CmdReset) == 0)
+                       break;
+       }
+}
+
+void
+rtl_enable_cfg9346_write(struct rtl_hw *hw)
+{
+       RTL_W8(hw, Cfg9346, RTL_R8(hw, Cfg9346) | Cfg9346_Unlock);
+}
+
+void
+rtl_disable_cfg9346_write(struct rtl_hw *hw)
+{
+       RTL_W8(hw, Cfg9346, RTL_R8(hw, Cfg9346) & ~Cfg9346_Unlock);
+}
+
+static void
+rtl_enable_force_clkreq(struct rtl_hw *hw, bool enable)
+{
+       if (enable)
+               RTL_W8(hw, 0xF1, RTL_R8(hw, 0xF1) | BIT_7);
+       else
+               RTL_W8(hw, 0xF1, RTL_R8(hw, 0xF1) & ~BIT_7);
+}
+
+static void
+rtl_enable_aspm_clkreq_lock(struct rtl_hw *hw, bool enable)
+{
+       switch (hw->mcfg) {
+       case CFG_METHOD_48 ... CFG_METHOD_57:
+       case CFG_METHOD_69:
+               rtl_enable_cfg9346_write(hw);
+               if (enable) {
+                       RTL_W8(hw, Config2, RTL_R8(hw, Config2) | BIT_7);
+                       RTL_W8(hw, Config5, RTL_R8(hw, Config5) | BIT_0);
+               } else {
+                       RTL_W8(hw, Config2, RTL_R8(hw, Config2) & ~BIT_7);
+                       RTL_W8(hw, Config5, RTL_R8(hw, Config5) & ~BIT_0);
+               }
+               rtl_disable_cfg9346_write(hw);
+               break;
+       case CFG_METHOD_70:
+       case CFG_METHOD_71:
+               rtl_enable_cfg9346_write(hw);
+               if (enable) {
+                       RTL_W8(hw, INT_CFG0_8125, RTL_R8(hw, INT_CFG0_8125) | 
BIT_3);
+                       RTL_W8(hw, Config5, RTL_R8(hw, Config5) | BIT_0);
+               } else {
+                       RTL_W8(hw, INT_CFG0_8125, RTL_R8(hw, INT_CFG0_8125) & 
~BIT_3);
+                       RTL_W8(hw, Config5, RTL_R8(hw, Config5) & ~BIT_0);
+               }
+               rtl_disable_cfg9346_write(hw);
+               break;
+       }
+}
+
+static void
+rtl_disable_l1_timeout(struct rtl_hw *hw)
+{
+       rtl_csi_write(hw, 0x890, rtl_csi_read(hw, 0x890) & ~BIT_0);
+}
+
+static void
+rtl_disable_eee_plus(struct rtl_hw *hw)
+{
+       switch (hw->mcfg) {
+       case CFG_METHOD_48 ... CFG_METHOD_57:
+       case CFG_METHOD_69 ... CFG_METHOD_71:
+               rtl_mac_ocp_write(hw, 0xE080, rtl_mac_ocp_read(hw, 0xE080) & 
~BIT_1);
+               break;
+
+       default:
+               /* Not support EEEPlus */
+               break;
+       }
+}
+
+static void
+rtl_hw_clear_timer_int(struct rtl_hw *hw)
+{
+       switch (hw->mcfg) {
+       case CFG_METHOD_48 ... CFG_METHOD_57:
+       case CFG_METHOD_69 ... CFG_METHOD_71:
+               RTL_W32(hw, TIMER_INT0_8125, 0x0000);
+               RTL_W32(hw, TIMER_INT1_8125, 0x0000);
+               RTL_W32(hw, TIMER_INT2_8125, 0x0000);
+               RTL_W32(hw, TIMER_INT3_8125, 0x0000);
+               break;
+       }
+}
+
+static void
+rtl_hw_clear_int_miti(struct rtl_hw *hw)
+{
+       int i;
+       switch (hw->HwSuppIntMitiVer) {
+       case 3:
+       case 6:
+               /* IntMITI_0-IntMITI_31 */
+               for (i = 0xA00; i < 0xB00; i += 4)
+                       RTL_W32(hw, i, 0x0000);
+               break;
+       case 4:
+       case 5:
+               /* IntMITI_0-IntMITI_15 */
+               for (i = 0xA00; i < 0xA80; i += 4)
+                       RTL_W32(hw, i, 0x0000);
+
+               if (hw->HwSuppIntMitiVer == 5)
+                       RTL_W8(hw, INT_CFG0_8125, RTL_R8(hw, INT_CFG0_8125) &
+                              ~(INT_CFG0_TIMEOUT0_BYPASS_8125 |
+                                INT_CFG0_MITIGATION_BYPASS_8125 |
+                                INT_CFG0_RDU_BYPASS_8126));
+               else
+                       RTL_W8(hw, INT_CFG0_8125, RTL_R8(hw, INT_CFG0_8125) &
+                              ~(INT_CFG0_TIMEOUT0_BYPASS_8125 | 
INT_CFG0_MITIGATION_BYPASS_8125));
+
+               RTL_W16(hw, INT_CFG1_8125, 0x0000);
+               break;
+       }
+}
+
+void
+rtl_hw_config(struct rtl_hw *hw)
+{
+       u32 mac_ocp_data;
+
+       /* Set RxConfig to default */
+       RTL_W32(hw, RxConfig, (RX_DMA_BURST_unlimited << RxCfgDMAShift));
+
+       rtl_nic_reset(hw);
+
+       rtl_enable_cfg9346_write(hw);
+
+       /* Disable aspm clkreq internal */
+       switch (hw->mcfg) {
+       case CFG_METHOD_48 ... CFG_METHOD_57:
+       case CFG_METHOD_69 ... CFG_METHOD_71:
+               rtl_enable_force_clkreq(hw, 0);
+               rtl_enable_aspm_clkreq_lock(hw, 0);
+               break;
+       }
+
+       /* Disable magic packet */
+       switch (hw->mcfg) {
+       case CFG_METHOD_48 ... CFG_METHOD_57:
+       case CFG_METHOD_69 ... CFG_METHOD_71:
+               mac_ocp_data = 0;
+               rtl_mac_ocp_write(hw, 0xC0B6, mac_ocp_data);
+               break;
+       }
+
+       /* Set DMA burst size and interframe gap time */
+       RTL_W32(hw, TxConfig, (TX_DMA_BURST_unlimited << TxDMAShift) |
+               (InterFrameGap << TxInterFrameGapShift));
+
+       if (hw->EnableTxNoClose)
+               RTL_W32(hw, TxConfig, (RTL_R32(hw, TxConfig) | BIT_6));
+
+       /* TCAM */
+       switch (hw->mcfg) {
+       case CFG_METHOD_48 ... CFG_METHOD_53:
+               RTL_W16(hw, 0x382, 0x221B);
+               break;
+       }
+
+       switch (hw->mcfg) {
+       case CFG_METHOD_69 ... CFG_METHOD_71:
+               rtl_disable_l1_timeout(hw);
+               break;
+       }
+
+       switch (hw->mcfg) {
+       case CFG_METHOD_48 ... CFG_METHOD_57:
+       case CFG_METHOD_69 ... CFG_METHOD_71:
+
+               /* RSS_control_0 */
+               RTL_W32(hw, RSS_CTRL_8125, 0x00);
+
+               /* VMQ_control */
+               RTL_W16(hw, Q_NUM_CTRL_8125, 0x0000);
+
+               /* Disable speed down */
+               RTL_W8(hw, Config1, RTL_R8(hw, Config1) & ~0x10);
+
+               /* CRC disable set */
+               rtl_mac_ocp_write(hw, 0xC140, 0xFFFF);
+               rtl_mac_ocp_write(hw, 0xC142, 0xFFFF);
+
+               /* New TX desc format */
+               mac_ocp_data = rtl_mac_ocp_read(hw, 0xEB58);
+               if (hw->mcfg == CFG_METHOD_70 || hw->mcfg == CFG_METHOD_71)
+                       mac_ocp_data &= ~(BIT_0 | BIT_1);
+               mac_ocp_data |= BIT_0;
+               rtl_mac_ocp_write(hw, 0xEB58, mac_ocp_data);
+
+               if (hw->mcfg == CFG_METHOD_70 || hw->mcfg == CFG_METHOD_71)
+                       RTL_W8(hw, 0xD8, RTL_R8(hw, 0xD8) & ~BIT_1);
+
+               /*
+                * MTPS
+                * 15-8 maximum tx use credit number
+                * 7-0 reserved for pcie product line
+                */
+               mac_ocp_data = rtl_mac_ocp_read(hw, 0xE614);
+               mac_ocp_data &= ~(BIT_10 | BIT_9 | BIT_8);
+               if (hw->mcfg == CFG_METHOD_50 || hw->mcfg == CFG_METHOD_51 ||
+                   hw->mcfg == CFG_METHOD_53)
+                       mac_ocp_data |= ((2 & 0x07) << 8);
+               else if (hw->mcfg == CFG_METHOD_69 || hw->mcfg == CFG_METHOD_70 
||
+                        hw->mcfg == CFG_METHOD_71)
+                       mac_ocp_data |= ((4 & 0x07) << 8);
+               else
+                       mac_ocp_data |= ((3 & 0x07) << 8);
+               rtl_mac_ocp_write(hw, 0xE614, mac_ocp_data);
+
+               mac_ocp_data = rtl_mac_ocp_read(hw, 0xE63E);
+               mac_ocp_data &= ~(BIT_5 | BIT_4);
+               if (hw->mcfg == CFG_METHOD_48 || hw->mcfg == CFG_METHOD_49 ||
+                   hw->mcfg == CFG_METHOD_52 || hw->mcfg == CFG_METHOD_69 ||
+                   hw->mcfg == CFG_METHOD_70 || hw->mcfg == CFG_METHOD_71)
+                       mac_ocp_data |= ((0x02 & 0x03) << 4);
+               rtl_mac_ocp_write(hw, 0xE63E, mac_ocp_data);
+
+               /*
+                * FTR_MCU_CTRL
+                * 3-2 txpla packet valid start
+                */
+               mac_ocp_data = rtl_mac_ocp_read(hw, 0xC0B4);
+               mac_ocp_data &= ~BIT_0;
+               rtl_mac_ocp_write(hw, 0xC0B4, mac_ocp_data);
+               mac_ocp_data |= BIT_0;
+               rtl_mac_ocp_write(hw, 0xC0B4, mac_ocp_data);
+
+               mac_ocp_data = rtl_mac_ocp_read(hw, 0xC0B4);
+               mac_ocp_data |= (BIT_3 | BIT_2);
+               rtl_mac_ocp_write(hw, 0xC0B4, mac_ocp_data);
+
+               mac_ocp_data = rtl_mac_ocp_read(hw, 0xEB6A);
+               mac_ocp_data &= ~(BIT_7 | BIT_6 | BIT_5 | BIT_4 | BIT_3 | BIT_2 
| BIT_1 |
+                                 BIT_0);
+               mac_ocp_data |= (BIT_5 | BIT_4 | BIT_1 | BIT_0);
+               rtl_mac_ocp_write(hw, 0xEB6A, mac_ocp_data);
+
+               mac_ocp_data = rtl_mac_ocp_read(hw, 0xEB50);
+               mac_ocp_data &= ~(BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5);
+               mac_ocp_data |= BIT_6;
+               rtl_mac_ocp_write(hw, 0xEB50, mac_ocp_data);
+
+               mac_ocp_data = rtl_mac_ocp_read(hw, 0xE056);
+               mac_ocp_data &= ~(BIT_7 | BIT_6 | BIT_5 | BIT_4);
+               rtl_mac_ocp_write(hw, 0xE056, mac_ocp_data);
+
+               /* EEE_CR */
+               mac_ocp_data = rtl_mac_ocp_read(hw, 0xE040);
+               mac_ocp_data &= ~BIT_12;
+               rtl_mac_ocp_write(hw, 0xE040, mac_ocp_data);
+
+               mac_ocp_data = rtl_mac_ocp_read(hw, 0xEA1C);
+               mac_ocp_data &= ~(BIT_1 | BIT_0);
+               mac_ocp_data |= BIT_0;
+               rtl_mac_ocp_write(hw, 0xEA1C, mac_ocp_data);
+
+               switch (hw->mcfg) {
+               case CFG_METHOD_48:
+               case CFG_METHOD_49:
+               case CFG_METHOD_52:
+               case CFG_METHOD_54:
+               case CFG_METHOD_55:
+                       rtl8125_oob_mutex_lock(hw);
+                       break;
+               }
+
+               /* MAC_PWRDWN_CR0 */
+               rtl_mac_ocp_write(hw, 0xE0C0, 0x4000);
+
+               rtl_set_mac_ocp_bit(hw, 0xE052, (BIT_6 | BIT_5));
+               rtl_clear_mac_ocp_bit(hw, 0xE052, (BIT_3 | BIT_7));
+
+               switch (hw->mcfg) {
+               case CFG_METHOD_48:
+               case CFG_METHOD_49:
+               case CFG_METHOD_52:
+               case CFG_METHOD_54:
+               case CFG_METHOD_55:
+                       rtl8125_oob_mutex_unlock(hw);
+                       break;
+               }
+
+               /*
+                * DMY_PWR_REG_0
+                * (1)ERI(0xD4)(OCP 0xC0AC).bit[7:12]=6'b111111, L1 Mask
+                */
+               rtl_set_mac_ocp_bit(hw, 0xC0AC,
+                                   (BIT_7 | BIT_8 | BIT_9 | BIT_10 | BIT_11 | 
BIT_12));
+
+               mac_ocp_data = rtl_mac_ocp_read(hw, 0xD430);
+               mac_ocp_data &= ~(BIT_11 | BIT_10 | BIT_9 | BIT_8 | BIT_7 | 
BIT_6 | BIT_5 |
+                                 BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0);
+               mac_ocp_data |= 0x45F;
+               rtl_mac_ocp_write(hw, 0xD430, mac_ocp_data);
+
+               if (!hw->DASH)
+                       RTL_W8(hw, 0xD0, RTL_R8(hw, 0xD0) | BIT_6 | BIT_7);
+               else
+                       RTL_W8(hw, 0xD0, RTL_R8(hw, 0xD0) & ~(BIT_6 | BIT_7));
+
+               if (hw->mcfg == CFG_METHOD_48 || hw->mcfg == CFG_METHOD_49 ||
+                   hw->mcfg == CFG_METHOD_52)
+                       RTL_W8(hw, MCUCmd_reg, RTL_R8(hw, MCUCmd_reg) | BIT_0);
+
+               rtl_disable_eee_plus(hw);
+
+               mac_ocp_data = rtl_mac_ocp_read(hw, 0xEA1C);
+               mac_ocp_data &= ~BIT_2;
+               if (hw->mcfg == CFG_METHOD_70 || hw->mcfg == CFG_METHOD_71)
+                       mac_ocp_data &= ~(BIT_9 | BIT_8);
+               rtl_mac_ocp_write(hw, 0xEA1C, mac_ocp_data);
+
+               /* Clear TCAM entries */
+               rtl_set_mac_ocp_bit(hw, 0xEB54, BIT_0);
+               udelay(1);
+               rtl_clear_mac_ocp_bit(hw, 0xEB54, BIT_0);
+
+               RTL_W16(hw, 0x1880, RTL_R16(hw, 0x1880) & ~(BIT_4 | BIT_5));
+
+               switch (hw->mcfg) {
+               case CFG_METHOD_54 ... CFG_METHOD_57:
+                       RTL_W8(hw, 0xd8, RTL_R8(hw, 0xd8) & ~EnableRxDescV4_0);
+                       break;
+               }
+       }
+
+       /* Other hw parameters */
+       rtl_hw_clear_timer_int(hw);
+
+       rtl_hw_clear_int_miti(hw);
+
+       switch (hw->mcfg) {
+       case CFG_METHOD_48 ... CFG_METHOD_57:
+       case CFG_METHOD_69 ... CFG_METHOD_71:
+               rtl_mac_ocp_write(hw, 0xE098, 0xC302);
+               break;
+       }
+
+       rtl_disable_cfg9346_write(hw);
+
+       udelay(10);
+}
+
diff --git a/drivers/net/r8169/r8169_hw.h b/drivers/net/r8169/r8169_hw.h
index e62b99a068..4effe2c6c7 100644
--- a/drivers/net/r8169/r8169_hw.h
+++ b/drivers/net/r8169/r8169_hw.h
@@ -13,13 +13,30 @@
 
 #include "r8169_base.h"
 #include "r8169_ethdev.h"
+#include "r8169_phy.h"
 
 u16 rtl_mac_ocp_read(struct rtl_hw *hw, u16 addr);
 void rtl_mac_ocp_write(struct rtl_hw *hw, u16 addr, u16 value);
 
+u32 rtl_ocp_read(struct rtl_hw *hw, u16 addr, u8 len);
+void rtl_ocp_write(struct rtl_hw *hw, u16 addr, u8 len, u32 value);
+
 u32 rtl_csi_read(struct rtl_hw *hw, u32 addr);
 void rtl_csi_write(struct rtl_hw *hw, u32 addr, u32 value);
 
+void rtl_hw_config(struct rtl_hw *hw);
+void rtl_nic_reset(struct rtl_hw *hw);
+
+void rtl_enable_cfg9346_write(struct rtl_hw *hw);
+void rtl_disable_cfg9346_write(struct rtl_hw *hw);
+
+void rtl8125_oob_mutex_lock(struct rtl_hw *hw);
+void rtl8125_oob_mutex_unlock(struct rtl_hw *hw);
+
+void rtl_disable_rxdvgate(struct rtl_hw *hw);
+
+#define NO_BASE_ADDRESS 0x00000000
+
 /* Channel wait count */
 #define RTL_CHANNEL_WAIT_COUNT      20000
 #define RTL_CHANNEL_WAIT_TIME       1   /*  1 us */
diff --git a/drivers/net/r8169/r8169_phy.c b/drivers/net/r8169/r8169_phy.c
new file mode 100644
index 0000000000..f0a880eeca
--- /dev/null
+++ b/drivers/net/r8169/r8169_phy.c
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2024 Realtek Corporation. All rights reserved */
+
+#include <sys/queue.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdarg.h>
+
+#include <rte_ether.h>
+#include <ethdev_pci.h>
+
+#include "r8169_ethdev.h"
+#include "r8169_hw.h"
+#include "r8169_phy.h"
+#include "r8169_logs.h"
+
+static void
+rtl_clear_set_mac_ocp_bit(struct rtl_hw *hw, u16 addr, u16 clearmask,
+                          u16 setmask)
+{
+       u16 phy_reg_value;
+
+       phy_reg_value = rtl_mac_ocp_read(hw, addr);
+       phy_reg_value &= ~clearmask;
+       phy_reg_value |= setmask;
+       rtl_mac_ocp_write(hw, addr, phy_reg_value);
+}
+
+void
+rtl_clear_mac_ocp_bit(struct rtl_hw *hw, u16 addr, u16 mask)
+{
+       rtl_clear_set_mac_ocp_bit(hw, addr, mask, 0);
+}
+
+void
+rtl_set_mac_ocp_bit(struct rtl_hw *hw, u16 addr, u16 mask)
+{
+       rtl_clear_set_mac_ocp_bit(hw, addr, 0, mask);
+}
+
diff --git a/drivers/net/r8169/r8169_phy.h b/drivers/net/r8169/r8169_phy.h
new file mode 100644
index 0000000000..f31eb163d8
--- /dev/null
+++ b/drivers/net/r8169/r8169_phy.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2024 Realtek Corporation. All rights reserved
+ */
+
+#ifndef _R8169_PHY_H_
+#define _R8169_PHY_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <rte_ethdev.h>
+#include <rte_ethdev_core.h>
+
+#include "r8169_base.h"
+#include "r8169_ethdev.h"
+
+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);
+
+#endif
+
-- 
2.34.1

Reply via email to