Signed-off-by: Howard Wang <howard_w...@realsil.com.cn>
---
 drivers/net/r8169/meson.build    |   1 +
 drivers/net/r8169/r8169_base.h   |  43 +++
 drivers/net/r8169/r8169_dash.c   |  89 +++++
 drivers/net/r8169/r8169_dash.h   |  35 ++
 drivers/net/r8169/r8169_ethdev.c |  47 ++-
 drivers/net/r8169/r8169_ethdev.h |  30 +-
 drivers/net/r8169/r8169_hw.c     | 583 +++++++++++++++++++++++++++++++
 drivers/net/r8169/r8169_hw.h     |  42 +++
 drivers/net/r8169/r8169_phy.h    |  16 +-
 9 files changed, 876 insertions(+), 10 deletions(-)
 create mode 100644 drivers/net/r8169/r8169_dash.c
 create mode 100644 drivers/net/r8169/r8169_dash.h

diff --git a/drivers/net/r8169/meson.build b/drivers/net/r8169/meson.build
index 08995453c7..8235e8ca43 100644
--- a/drivers/net/r8169/meson.build
+++ b/drivers/net/r8169/meson.build
@@ -6,6 +6,7 @@ sources = files(
                'r8169_hw.c',
                'r8169_rxtx.c',
                'r8169_phy.c',
+               'r8169_dash.c',
                'base/rtl8125a.c',
                'base/rtl8125a_mcu.c',
                'base/rtl8125b.c',
diff --git a/drivers/net/r8169/r8169_base.h b/drivers/net/r8169/r8169_base.h
index e01b1e3470..2ee6fc6782 100644
--- a/drivers/net/r8169/r8169_base.h
+++ b/drivers/net/r8169/r8169_base.h
@@ -237,6 +237,10 @@ enum RTL_registers {
        IMR_V4_L2_CLEAR_REG_8125 = 0x0D10,
        IMR_V4_L2_SET_REG_8125   = 0x0D18,
        ISR_V4_L2_8125      = 0x0D14,
+       SW_TAIL_PTR0_8125BP = 0x0D30,
+       SW_TAIL_PTR1_8125BP = 0x0D38,
+       HW_CLO_PTR0_8125BP = 0x0D34,
+       HW_CLO_PTR1_8125BP = 0x0D3C,
        DOUBLE_VLAN_CONFIG = 0x1000,
        TX_NEW_CTRL        = 0x203E,
        TNPDS_Q1_LOW_8125  = 0x2100,
@@ -482,6 +486,16 @@ enum RTL_register_content {
        ISRIMR_V2_LINKCHG    = (1 << 21),
 };
 
+enum RTL_chipset_name {
+       RTL8125A = 0,
+       RTL8125B,
+       RTL8168KB,
+       RTL8125BP,
+       RTL8125D,
+       RTL8126A,
+       UNKNOWN
+};
+
 #define PCI_VENDOR_ID_REALTEK 0x10EC
 
 #define RTL_PCI_REG_ADDR(hw, reg) ((u8 *)(hw)->mmio_addr + (reg))
@@ -522,6 +536,35 @@ enum RTL_register_content {
 
 #define ETH_HLEN        14
 
+#define SPEED_10       10
+#define SPEED_100      100
+#define SPEED_1000     1000
+#define SPEED_2500     2500
+#define SPEED_5000     5000
+
+#define DUPLEX_HALF    1
+#define DUPLEX_FULL    2
+
+#define AUTONEG_ENABLE 1
+#define AUTONEG_DISABLE        0
+
+#define ADVERTISE_10_HALF     0x0001
+#define ADVERTISE_10_FULL     0x0002
+#define ADVERTISE_100_HALF    0x0004
+#define ADVERTISE_100_FULL    0x0008
+#define ADVERTISE_1000_HALF   0x0010 /* Not used, just FYI */
+#define ADVERTISE_1000_FULL   0x0020
+#define ADVERTISE_2500_HALF   0x0040 /* NOT used, just FYI */
+#define ADVERTISE_2500_FULL   0x0080
+#define ADVERTISE_5000_HALF   0x0100 /* NOT used, just FYI */
+#define ADVERTISE_5000_FULL   0x0200
+
+#define RTL8126_ALL_SPEED_DUPLEX (ADVERTISE_10_HALF | ADVERTISE_10_FULL | \
+        ADVERTISE_100_HALF | ADVERTISE_100_FULL | ADVERTISE_1000_FULL | \
+        ADVERTISE_2500_FULL | ADVERTISE_5000_FULL)
+
+#define MAC_ADDR_LEN    RTE_ETHER_ADDR_LEN
+
 static inline u32
 rtl_read32(volatile void *addr)
 {
diff --git a/drivers/net/r8169/r8169_dash.c b/drivers/net/r8169/r8169_dash.c
new file mode 100644
index 0000000000..e803ce8305
--- /dev/null
+++ b/drivers/net/r8169/r8169_dash.c
@@ -0,0 +1,89 @@
+/* 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_driver.h>
+
+#include "r8169_base.h"
+#include "r8169_dash.h"
+#include "r8169_hw.h"
+
+bool
+rtl_is_allow_access_dash_ocp(struct rtl_hw *hw)
+{
+       bool allow_access = false;
+       u16 mac_ocp_data;
+
+       if (!HW_DASH_SUPPORT_DASH(hw))
+               goto exit;
+
+       allow_access = true;
+       switch (hw->mcfg) {
+       case CFG_METHOD_2:
+       case CFG_METHOD_3:
+               mac_ocp_data = rtl_mac_ocp_read(hw, 0xd460);
+               if (mac_ocp_data == 0xffff || !(mac_ocp_data & BIT_0))
+                       allow_access = false;
+               break;
+       case CFG_METHOD_8:
+       case CFG_METHOD_9:
+               mac_ocp_data = rtl_mac_ocp_read(hw, 0xd4c0);
+               if (mac_ocp_data == 0xffff || (mac_ocp_data & BIT_3))
+                       allow_access = false;
+               break;
+       default:
+               goto exit;
+       }
+exit:
+       return allow_access;
+}
+
+static u32
+rtl_get_dash_fw_ver(struct rtl_hw *hw)
+{
+       u32 ver = 0xffffffff;
+
+       if (FALSE == HW_DASH_SUPPORT_GET_FIRMWARE_VERSION(hw))
+               goto exit;
+
+       ver = rtl_ocp_read(hw, OCP_REG_FIRMWARE_MAJOR_VERSION, 4);
+
+exit:
+       return ver;
+}
+
+static int
+_rtl_check_dash(struct rtl_hw *hw)
+{
+       if (!hw->AllowAccessDashOcp)
+               return 0;
+
+       if (HW_DASH_SUPPORT_TYPE_2(hw) || HW_DASH_SUPPORT_TYPE_4(hw)) {
+               if (rtl_ocp_read(hw, 0x128, 1) & BIT_0)
+                       return 1;
+       }
+
+       return 0;
+}
+
+int
+rtl_check_dash(struct rtl_hw *hw)
+{
+       u32 ver;
+
+       if (_rtl_check_dash(hw)) {
+               ver = rtl_get_dash_fw_ver(hw);
+               if (!(ver == 0 || ver == 0xffffffff))
+                       return 1;
+       }
+
+       return 0;
+}
+
diff --git a/drivers/net/r8169/r8169_dash.h b/drivers/net/r8169/r8169_dash.h
new file mode 100644
index 0000000000..d89b2e2d3b
--- /dev/null
+++ b/drivers/net/r8169/r8169_dash.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2024 Realtek Corporation. All rights reserved
+ */
+
+#ifndef _R8169_DASH_H_
+#define _R8169_DASH_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <rte_ethdev.h>
+#include <rte_ethdev_core.h>
+
+#include "r8169_base.h"
+#include "r8169_hw.h"
+
+#define HW_DASH_SUPPORT_DASH(_M)        ((_M)->HwSuppDashVer > 0)
+#define HW_DASH_SUPPORT_TYPE_1(_M)      ((_M)->HwSuppDashVer == 1)
+#define HW_DASH_SUPPORT_TYPE_2(_M)      ((_M)->HwSuppDashVer == 2)
+#define HW_DASH_SUPPORT_TYPE_3(_M)      ((_M)->HwSuppDashVer == 3)
+#define HW_DASH_SUPPORT_TYPE_4(_M)      ((_M)->HwSuppDashVer == 4)
+
+#define HW_DASH_SUPPORT_GET_FIRMWARE_VERSION(_M) (HW_DASH_SUPPORT_TYPE_2(_M) 
|| \
+                                                  HW_DASH_SUPPORT_TYPE_3(_M) 
|| \
+                                                  HW_DASH_SUPPORT_TYPE_4(_M))
+
+#define OCP_REG_FIRMWARE_MAJOR_VERSION 0x120
+
+bool rtl_is_allow_access_dash_ocp(struct rtl_hw *hw);
+
+int rtl_check_dash(struct rtl_hw *hw);
+
+
+#endif
+
diff --git a/drivers/net/r8169/r8169_ethdev.c b/drivers/net/r8169/r8169_ethdev.c
index 294d942862..9af46b390c 100644
--- a/drivers/net/r8169/r8169_ethdev.c
+++ b/drivers/net/r8169/r8169_ethdev.c
@@ -111,6 +111,15 @@ rtl_dev_stop(struct rte_eth_dev *dev)
        if (hw->adapter_stopped)
                return 0;
 
+       rtl_nic_reset(hw);
+
+       switch (hw->mcfg) {
+       case CFG_METHOD_48 ... CFG_METHOD_57:
+       case CFG_METHOD_69 ... CFG_METHOD_71:
+               rtl_mac_ocp_write(hw, 0xE00A, hw->mcu_pme_setting);
+               break;
+       }
+
        rtl_powerdown_pll(hw);
 
        hw->adapter_stopped = 1;
@@ -125,6 +134,8 @@ rtl_dev_stop(struct rte_eth_dev *dev)
 static int
 rtl_dev_close(struct rte_eth_dev *dev)
 {
+       struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
+       struct rtl_hw *hw = &adapter->hw;
        int ret_stp;
 
        if (rte_eal_process_type() != RTE_PROC_PRIMARY)
@@ -132,6 +143,9 @@ rtl_dev_close(struct rte_eth_dev *dev)
 
        ret_stp = rtl_dev_stop(dev);
 
+       /* Reprogram the RAR[0] in case user changed it. */
+       rtl_rar_set(hw, hw->mac_addr);
+
        return ret_stp;
 }
 
@@ -139,9 +153,10 @@ static int
 rtl_dev_init(struct rte_eth_dev *dev)
 {
        struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
-       struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
        struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
        struct rtl_hw *hw = &adapter->hw;
+       struct rte_ether_addr *perm_addr = (struct rte_ether_addr 
*)hw->mac_addr;
+       char buf[RTE_ETHER_ADDR_FMT_SIZE];
 
        dev->dev_ops = &rtl_eth_dev_ops;
        dev->tx_pkt_burst = &rtl_xmit_pkts;
@@ -153,9 +168,39 @@ rtl_dev_init(struct rte_eth_dev *dev)
 
        rte_eth_copy_pci_info(dev, pci_dev);
 
+       hw->mmio_addr = (u8 *)pci_dev->mem_resource[2].addr; /* RTL8169 uses 
BAR2 */
+
+       rtl_get_mac_version(hw, pci_dev);
+
        if (rtl_set_hw_ops(hw))
                return -ENOTSUP;
 
+       rtl_hw_initialize(hw);
+
+       /* Read the permanent MAC address out of ROM */
+       rtl_get_mac_address(hw, perm_addr);
+
+       if (!rte_is_valid_assigned_ether_addr(perm_addr)) {
+               rte_eth_random_addr(&perm_addr->addr_bytes[0]);
+
+               rte_ether_format_addr(buf, sizeof(buf), perm_addr);
+
+               PMD_INIT_LOG(NOTICE, "r8169: Assign randomly generated MAC 
address %s", buf);
+       }
+
+       /* Allocate memory for storing MAC addresses */
+       dev->data->mac_addrs = rte_zmalloc("r8169", RTE_ETHER_ADDR_LEN, 0);
+
+       if (dev->data->mac_addrs == NULL) {
+               PMD_INIT_LOG(ERR, "MAC Malloc failed");
+               return -ENOMEM;
+       }
+
+       /* Copy the permanent MAC address */
+       rte_ether_addr_copy(perm_addr, &dev->data->mac_addrs[0]);
+
+       rtl_rar_set(hw, &perm_addr->addr_bytes[0]);
+
        return 0;
 }
 
diff --git a/drivers/net/r8169/r8169_ethdev.h b/drivers/net/r8169/r8169_ethdev.h
index a0da173685..de90b33289 100644
--- a/drivers/net/r8169/r8169_ethdev.h
+++ b/drivers/net/r8169/r8169_ethdev.h
@@ -23,14 +23,28 @@ struct rtl_hw_ops {
        void (*hw_phy_mcu_config)(struct rtl_hw *hw);
 };
 
+/* Flow control settings */
+enum rtl_fc_mode {
+       rtl_fc_none = 0,
+       rtl_fc_rx_pause,
+       rtl_fc_tx_pause,
+       rtl_fc_full,
+       rtl_fc_default
+};
+
 struct rtl_hw {
        struct rtl_hw_ops hw_ops;
        u8  adapter_stopped;
        u8  *mmio_addr;
+       u8  *cmac_ioaddr; /* cmac memory map physical address */
+       u8  chipset_name;
+       u8  efuse_ver;
+       u8  HwIcVerUnknown;
        u32 mcfg;
        u32 mtu;
        u8  HwSuppIntMitiVer;
        u16 cur_page;
+       u8  mac_addr[MAC_ADDR_LEN];
 
        u8  RequirePhyMdiSwapPatch;
        u8  NotWrMcuPatchCode;
@@ -44,10 +58,24 @@ struct rtl_hw {
        u16 sw_ram_code_ver;
        u16 hw_ram_code_ver;
 
+       u8  autoneg;
+       u8  duplex;
+       u32 speed;
+       u32 advertising;
+       enum rtl_fc_mode fcpause;
+
        u32 HwSuppMaxPhyLinkSpeed;
 
+       u8  HwSuppNowIsOobVer;
+
+       u16 mcu_pme_setting;
+
        /* Enable Tx No Close */
-       u8 EnableTxNoClose;
+       u8  HwSuppTxNoCloseVer;
+       u8  EnableTxNoClose;
+       u16 hw_clo_ptr_reg;
+       u16 sw_tail_ptr_reg;
+       u32 MaxTxDescPtrMask;
 
        /* Dash */
        u8 HwSuppDashVer;
diff --git a/drivers/net/r8169/r8169_hw.c b/drivers/net/r8169/r8169_hw.c
index fb4ea21237..e5d1b249e2 100644
--- a/drivers/net/r8169/r8169_hw.c
+++ b/drivers/net/r8169/r8169_hw.c
@@ -13,6 +13,7 @@
 
 #include "r8169_hw.h"
 #include "r8169_logs.h"
+#include "r8169_dash.h"
 
 static u32
 rtl_eri_read_with_oob_base_address(struct rtl_hw *hw, int addr, int len,
@@ -920,3 +921,585 @@ rtl_write_mac_mcu_ram_code(struct rtl_hw *hw, const u16 
*entry, u16 entry_cnt)
                _rtl_write_mac_mcu_ram_code(hw, entry, entry_cnt);
 }
 
+bool
+rtl_is_speed_mode_valid(u32 speed)
+{
+       switch (speed) {
+       case SPEED_5000:
+       case SPEED_2500:
+       case SPEED_1000:
+       case SPEED_100:
+       case SPEED_10:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool
+rtl_is_duplex_mode_valid(u8 duplex)
+{
+       switch (duplex) {
+       case DUPLEX_FULL:
+       case DUPLEX_HALF:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool
+rtl_is_autoneg_mode_valid(u32 autoneg)
+{
+       switch (autoneg) {
+       case AUTONEG_ENABLE:
+       case AUTONEG_DISABLE:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static void
+rtl_set_link_option(struct rtl_hw *hw, u8 autoneg, u32 speed, u8 duplex,
+                    enum rtl_fc_mode fc)
+{
+       u64 adv;
+
+       if (!rtl_is_speed_mode_valid(speed))
+               speed = SPEED_5000;
+
+       if (!rtl_is_duplex_mode_valid(duplex))
+               duplex = DUPLEX_FULL;
+
+       if (!rtl_is_autoneg_mode_valid(autoneg))
+               autoneg = AUTONEG_ENABLE;
+
+       speed = RTE_MIN(speed, hw->HwSuppMaxPhyLinkSpeed);
+
+       adv = 0;
+       switch (speed) {
+       case SPEED_5000:
+               adv |= ADVERTISE_5000_FULL;
+       /* Fall through */
+       case SPEED_2500:
+               adv |= ADVERTISE_2500_FULL;
+       /* Fall through */
+       default:
+               adv |= (ADVERTISE_10_HALF | ADVERTISE_10_FULL |
+                       ADVERTISE_100_HALF | ADVERTISE_100_FULL |
+                       ADVERTISE_1000_HALF | ADVERTISE_1000_FULL);
+               break;
+       }
+
+       hw->autoneg = autoneg;
+       hw->speed = speed;
+       hw->duplex = duplex;
+       hw->advertising = adv;
+       hw->fcpause = fc;
+}
+
+static void
+rtl_init_software_variable(struct rtl_hw *hw)
+{
+       int tx_no_close_enable = 1;
+       unsigned int speed_mode = SPEED_5000;
+       unsigned int duplex_mode = DUPLEX_FULL;
+       unsigned int autoneg_mode = AUTONEG_ENABLE;
+       u8 tmp;
+
+       switch (hw->mcfg) {
+       case CFG_METHOD_48:
+       case CFG_METHOD_49:
+               tmp = (u8)rtl_mac_ocp_read(hw, 0xD006);
+               if (tmp == 0x02 || tmp == 0x04)
+                       hw->HwSuppDashVer = 2;
+               break;
+       case CFG_METHOD_54:
+       case CFG_METHOD_55:
+               hw->HwSuppDashVer = 4;
+               break;
+       default:
+               hw->HwSuppDashVer = 0;
+               break;
+       }
+
+       switch (hw->mcfg) {
+       case CFG_METHOD_48:
+       case CFG_METHOD_49:
+               if (HW_DASH_SUPPORT_DASH(hw))
+                       hw->HwSuppOcpChannelVer = 2;
+               break;
+       case CFG_METHOD_54:
+       case CFG_METHOD_55:
+               hw->HwSuppOcpChannelVer = 2;
+               break;
+       }
+
+       hw->AllowAccessDashOcp = rtl_is_allow_access_dash_ocp(hw);
+
+       if (HW_DASH_SUPPORT_DASH(hw) && rtl_check_dash(hw))
+               hw->DASH = 1;
+       else
+               hw->DASH = 0;
+
+       if (HW_DASH_SUPPORT_TYPE_2(hw))
+               hw->cmac_ioaddr = hw->mmio_addr;
+
+       switch (hw->mcfg) {
+       case CFG_METHOD_48:
+       case CFG_METHOD_49:
+               hw->chipset_name = RTL8125A;
+               break;
+       case CFG_METHOD_50:
+       case CFG_METHOD_51:
+               hw->chipset_name = RTL8125B;
+               break;
+       case CFG_METHOD_52:
+       case CFG_METHOD_53:
+               hw->chipset_name = RTL8168KB;
+               break;
+       case CFG_METHOD_54:
+       case CFG_METHOD_55:
+               hw->chipset_name = RTL8125BP;
+               break;
+       case CFG_METHOD_56:
+       case CFG_METHOD_57:
+               hw->chipset_name = RTL8125D;
+               break;
+       case CFG_METHOD_69 ... CFG_METHOD_71:
+               hw->chipset_name = RTL8126A;
+               break;
+       default:
+               hw->chipset_name = UNKNOWN;
+               break;
+       }
+
+       switch (hw->mcfg) {
+       case CFG_METHOD_48 ... CFG_METHOD_57:
+       case CFG_METHOD_69 ... CFG_METHOD_71:
+               hw->HwSuppNowIsOobVer = 1;
+       }
+
+       switch (hw->mcfg) {
+       case CFG_METHOD_48 ... CFG_METHOD_57:
+       case CFG_METHOD_69 ... CFG_METHOD_71:
+               hw->HwSuppCheckPhyDisableModeVer = 3;
+       }
+
+       switch (hw->mcfg) {
+       case CFG_METHOD_48 ... CFG_METHOD_51:
+       case CFG_METHOD_54 ... CFG_METHOD_57:
+               hw->HwSuppMaxPhyLinkSpeed = 2500;
+               break;
+       case CFG_METHOD_69 ... CFG_METHOD_71:
+               hw->HwSuppMaxPhyLinkSpeed = 5000;
+               break;
+       default:
+               hw->HwSuppMaxPhyLinkSpeed = 1000;
+               break;
+       }
+
+       switch (hw->mcfg) {
+       case CFG_METHOD_48 ... CFG_METHOD_53:
+               hw->HwSuppTxNoCloseVer = 3;
+               break;
+       case CFG_METHOD_54 ... CFG_METHOD_57:
+               hw->HwSuppTxNoCloseVer = 6;
+               break;
+       case CFG_METHOD_69:
+               hw->HwSuppTxNoCloseVer = 4;
+               break;
+       case CFG_METHOD_70:
+       case CFG_METHOD_71:
+               hw->HwSuppTxNoCloseVer = 5;
+               break;
+       }
+
+       switch (hw->HwSuppTxNoCloseVer) {
+       case 5:
+       case 6:
+               hw->MaxTxDescPtrMask = MAX_TX_NO_CLOSE_DESC_PTR_MASK_V4;
+               break;
+       case 4:
+               hw->MaxTxDescPtrMask = MAX_TX_NO_CLOSE_DESC_PTR_MASK_V3;
+               break;
+       case 3:
+               hw->MaxTxDescPtrMask = MAX_TX_NO_CLOSE_DESC_PTR_MASK_V2;
+               break;
+       default:
+               tx_no_close_enable = 0;
+               break;
+       }
+
+       if (hw->HwSuppTxNoCloseVer > 0 && tx_no_close_enable == 1)
+               hw->EnableTxNoClose = TRUE;
+
+       switch (hw->HwSuppTxNoCloseVer) {
+       case 4:
+       case 5:
+               hw->hw_clo_ptr_reg = HW_CLO_PTR0_8126;
+               hw->sw_tail_ptr_reg = SW_TAIL_PTR0_8126;
+               break;
+       case 6:
+               hw->hw_clo_ptr_reg = HW_CLO_PTR0_8125BP;
+               hw->sw_tail_ptr_reg = SW_TAIL_PTR0_8125BP;
+               break;
+       default:
+               hw->hw_clo_ptr_reg = HW_CLO_PTR0_8125;
+               hw->sw_tail_ptr_reg = SW_TAIL_PTR0_8125;
+               break;
+       }
+
+       switch (hw->mcfg) {
+       case CFG_METHOD_48:
+               hw->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_48;
+               break;
+       case CFG_METHOD_49:
+       case CFG_METHOD_52:
+               hw->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_49;
+               break;
+       case CFG_METHOD_50:
+               hw->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_50;
+               break;
+       case CFG_METHOD_51:
+       case CFG_METHOD_53:
+               hw->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_51;
+               break;
+       case CFG_METHOD_54:
+               hw->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_54;
+               break;
+       case CFG_METHOD_55:
+               hw->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_55;
+               break;
+       case CFG_METHOD_56:
+               hw->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_56;
+               break;
+       case CFG_METHOD_57:
+               hw->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_57;
+               break;
+       case CFG_METHOD_69:
+               hw->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_69;
+               break;
+       case CFG_METHOD_70:
+               hw->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_70;
+               break;
+       case CFG_METHOD_71:
+               hw->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_71;
+               break;
+       }
+
+       if (hw->HwIcVerUnknown) {
+               hw->NotWrRamCodeToMicroP = TRUE;
+               hw->NotWrMcuPatchCode = TRUE;
+       }
+
+       switch (hw->mcfg) {
+       case CFG_METHOD_48 ... CFG_METHOD_57:
+       case CFG_METHOD_69 ... CFG_METHOD_71:
+               hw->HwSuppMacMcuVer = 2;
+               break;
+       }
+
+       switch (hw->mcfg) {
+       case CFG_METHOD_48 ... CFG_METHOD_57:
+       case CFG_METHOD_69 ... CFG_METHOD_71:
+               hw->MacMcuPageSize = RTL_MAC_MCU_PAGE_SIZE;
+               break;
+       }
+
+       switch (hw->mcfg) {
+       case CFG_METHOD_49:
+       case CFG_METHOD_52:
+               if ((rtl_mac_ocp_read(hw, 0xD442) & BIT_5) &&
+                   (rtl_mdio_direct_read_phy_ocp(hw, 0xD068) & BIT_1))
+                       hw->RequirePhyMdiSwapPatch = TRUE;
+               break;
+       }
+
+       switch (hw->mcfg) {
+       case CFG_METHOD_48:
+       case CFG_METHOD_49:
+       case CFG_METHOD_52:
+               hw->HwSuppIntMitiVer = 3;
+               break;
+       case CFG_METHOD_50:
+       case CFG_METHOD_51:
+       case CFG_METHOD_53:
+       case CFG_METHOD_69:
+               hw->HwSuppIntMitiVer = 4;
+               break;
+       case CFG_METHOD_54 ... CFG_METHOD_57:
+               hw->HwSuppIntMitiVer = 6;
+               break;
+       case CFG_METHOD_70:
+       case CFG_METHOD_71:
+               hw->HwSuppIntMitiVer = 5;
+               break;
+       }
+
+       rtl_set_link_option(hw, autoneg_mode, speed_mode, duplex_mode, 
rtl_fc_full);
+
+       switch (hw->mcfg) {
+       case CFG_METHOD_48 ... CFG_METHOD_57:
+       case CFG_METHOD_69 ... CFG_METHOD_71:
+               hw->mcu_pme_setting = rtl_mac_ocp_read(hw, 0xE00A);
+               break;
+       }
+
+       hw->mtu = RTL_DEFAULT_MTU;
+}
+
+static void
+rtl_exit_realwow(struct rtl_hw *hw)
+{
+       /* Disable realwow function */
+       switch (hw->mcfg) {
+       case CFG_METHOD_48 ... CFG_METHOD_57:
+       case CFG_METHOD_69 ... CFG_METHOD_71:
+               rtl_mac_ocp_write(hw, 0xC0BC, 0x00FF);
+               break;
+       }
+}
+
+static void
+rtl_disable_now_is_oob(struct rtl_hw *hw)
+{
+       if (hw->HwSuppNowIsOobVer == 1)
+               RTL_W8(hw, MCUCmd_reg, RTL_R8(hw, MCUCmd_reg) & ~Now_is_oob);
+}
+
+static void
+rtl_wait_ll_share_fifo_ready(struct rtl_hw *hw)
+{
+       int i;
+
+       for (i = 0; i < 10; i++) {
+               udelay(100);
+               if (RTL_R16(hw, 0xD2) & BIT_9)
+                       break;
+       }
+}
+
+static void
+rtl_exit_oob(struct rtl_hw *hw)
+{
+       u16 data16;
+
+       rtl_disable_rx_packet_filter(hw);
+
+       rtl_exit_realwow(hw);
+
+       rtl_nic_reset(hw);
+
+       switch (hw->mcfg) {
+       case CFG_METHOD_48 ... CFG_METHOD_57:
+       case CFG_METHOD_69 ... CFG_METHOD_71:
+               rtl_disable_now_is_oob(hw);
+
+               data16 = rtl_mac_ocp_read(hw, 0xE8DE) & ~BIT_14;
+               rtl_mac_ocp_write(hw, 0xE8DE, data16);
+               rtl_wait_ll_share_fifo_ready(hw);
+
+               rtl_mac_ocp_write(hw, 0xC0AA, 0x07D0);
+
+               rtl_mac_ocp_write(hw, 0xC0A6, 0x01B5);
+
+               rtl_mac_ocp_write(hw, 0xC01E, 0x5555);
+
+               rtl_wait_ll_share_fifo_ready(hw);
+               break;
+       }
+}
+
+static void
+rtl_disable_ups(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, 0xD40A, rtl_mac_ocp_read(hw, 0xD40A) & 
~BIT_4);
+               break;
+       }
+}
+
+static void
+rtl8125_disable_ocp_phy_power_saving(struct rtl_hw *hw)
+{
+       u16 val;
+
+       if (hw->mcfg == CFG_METHOD_48 || hw->mcfg == CFG_METHOD_49 ||
+           hw->mcfg == CFG_METHOD_52) {
+               val = rtl_mdio_direct_read_phy_ocp(hw, 0xC416);
+               if (val != 0x0050) {
+                       rtl_set_phy_mcu_patch_request(hw);
+                       rtl_mdio_direct_write_phy_ocp(hw, 0xC416, 0x0000);
+                       rtl_mdio_direct_write_phy_ocp(hw, 0xC416, 0x0500);
+                       rtl_clear_phy_mcu_patch_request(hw);
+               }
+       }
+}
+
+static void
+rtl_hw_init(struct rtl_hw *hw)
+{
+       switch (hw->mcfg) {
+       case CFG_METHOD_48 ... CFG_METHOD_57:
+       case CFG_METHOD_69 ... CFG_METHOD_71:
+               rtl_enable_aspm_clkreq_lock(hw, 0);
+               rtl_enable_force_clkreq(hw, 0);
+               break;
+       }
+
+       rtl_disable_ups(hw);
+
+       hw->hw_ops.hw_mac_mcu_config(hw);
+
+       /* Disable ocp phy power saving */
+       rtl8125_disable_ocp_phy_power_saving(hw);
+}
+
+void
+rtl_hw_initialize(struct rtl_hw *hw)
+{
+       rtl_init_software_variable(hw);
+
+       rtl_exit_oob(hw);
+
+       rtl_hw_init(hw);
+
+       rtl_nic_reset(hw);
+}
+
+void
+rtl_get_mac_version(struct rtl_hw *hw, struct rte_pci_device *pci_dev)
+{
+       u32 reg, val32;
+       u32 ic_version_id;
+
+       val32 = RTL_R32(hw, TxConfig);
+       reg = val32 & 0x7c800000;
+       ic_version_id = val32 & 0x00700000;
+
+       switch (reg) {
+       case 0x60800000:
+               if (ic_version_id == 0x00000000)
+                       hw->mcfg = CFG_METHOD_48;
+
+               else if (ic_version_id == 0x100000)
+                       hw->mcfg = CFG_METHOD_49;
+
+               else {
+                       hw->mcfg = CFG_METHOD_49;
+                       hw->HwIcVerUnknown = TRUE;
+               }
+
+               hw->efuse_ver = EFUSE_SUPPORT_V4;
+               break;
+       case 0x64000000:
+               if (ic_version_id == 0x00000000)
+                       hw->mcfg = CFG_METHOD_50;
+
+               else if (ic_version_id == 0x100000)
+                       hw->mcfg = CFG_METHOD_51;
+
+               else {
+                       hw->mcfg = CFG_METHOD_51;
+                       hw->HwIcVerUnknown = TRUE;
+               }
+
+               hw->efuse_ver = EFUSE_SUPPORT_V4;
+               break;
+       case 0x68000000:
+               if (ic_version_id == 0x00000000)
+                       hw->mcfg = CFG_METHOD_54;
+               else if (ic_version_id == 0x100000)
+                       hw->mcfg = CFG_METHOD_55;
+               else {
+                       hw->mcfg = CFG_METHOD_55;
+                       hw->HwIcVerUnknown = TRUE;
+               }
+
+               hw->efuse_ver = EFUSE_SUPPORT_V4;
+               break;
+       case 0x68800000:
+               if (ic_version_id == 0x00000000)
+                       hw->mcfg = CFG_METHOD_56;
+               else if (ic_version_id == 0x100000)
+                       hw->mcfg = CFG_METHOD_57;
+               else {
+                       hw->mcfg = CFG_METHOD_57;
+                       hw->HwIcVerUnknown = TRUE;
+               }
+
+               hw->efuse_ver = EFUSE_SUPPORT_V4;
+               break;
+       case 0x64800000:
+               if (ic_version_id == 0x00000000)
+                       hw->mcfg = CFG_METHOD_69;
+               else if (ic_version_id == 0x100000)
+                       hw->mcfg = CFG_METHOD_70;
+               else if (ic_version_id == 0x200000)
+                       hw->mcfg = CFG_METHOD_71;
+               else {
+                       hw->mcfg = CFG_METHOD_71;
+                       hw->HwIcVerUnknown = TRUE;
+               }
+
+               hw->efuse_ver = EFUSE_SUPPORT_V4;
+               break;
+       default:
+               PMD_INIT_LOG(NOTICE, "unknown chip version (%x)", reg);
+               hw->mcfg = CFG_METHOD_DEFAULT;
+               hw->HwIcVerUnknown = TRUE;
+               hw->efuse_ver = EFUSE_NOT_SUPPORT;
+               break;
+       }
+
+       if (pci_dev->id.device_id == 0x8162) {
+               if (hw->mcfg == CFG_METHOD_49)
+                       hw->mcfg = CFG_METHOD_52;
+               else if (hw->mcfg == CFG_METHOD_51)
+                       hw->mcfg = CFG_METHOD_53;
+       }
+}
+
+int
+rtl_get_mac_address(struct rtl_hw *hw, struct rte_ether_addr *ea)
+{
+       u8 mac_addr[MAC_ADDR_LEN];
+
+       switch (hw->mcfg) {
+       case CFG_METHOD_48 ... CFG_METHOD_57:
+       case CFG_METHOD_69 ... CFG_METHOD_71:
+               *(u32 *)&mac_addr[0] = RTL_R32(hw, BACKUP_ADDR0_8125);
+               *(u16 *)&mac_addr[4] = RTL_R16(hw, BACKUP_ADDR1_8125);
+               break;
+       default:
+               break;
+       }
+
+       rte_ether_addr_copy((struct rte_ether_addr *)mac_addr, ea);
+
+       return 0;
+}
+
+void
+rtl_rar_set(struct rtl_hw *hw, uint8_t *addr)
+{
+       uint32_t rar_low = 0;
+       uint32_t rar_high = 0;
+
+       rar_low = ((uint32_t)addr[0] | ((uint32_t)addr[1] << 8) |
+                  ((uint32_t)addr[2] << 16) | ((uint32_t)addr[3] << 24));
+
+       rar_high = ((uint32_t)addr[4] | ((uint32_t)addr[5] << 8));
+
+       rtl_enable_cfg9346_write(hw);
+
+       RTL_W32(hw, MAC0, rar_low);
+       RTL_W32(hw, MAC4, rar_high);
+
+       rtl_disable_cfg9346_write(hw);
+}
+
diff --git a/drivers/net/r8169/r8169_hw.h b/drivers/net/r8169/r8169_hw.h
index 8fd48a3077..3746b46084 100644
--- a/drivers/net/r8169/r8169_hw.h
+++ b/drivers/net/r8169/r8169_hw.h
@@ -42,6 +42,15 @@ void rtl_hw_disable_mac_mcu_bps(struct rtl_hw *hw);
 void rtl_write_mac_mcu_ram_code(struct rtl_hw *hw, const u16 *entry,
                                 u16 entry_cnt);
 
+void rtl_hw_initialize(struct rtl_hw *hw);
+
+bool rtl_is_speed_mode_valid(u32 speed);
+
+void rtl_get_mac_version(struct rtl_hw *hw, struct rte_pci_device *pci_dev);
+int rtl_get_mac_address(struct rtl_hw *hw, struct rte_ether_addr *ea);
+
+void rtl_rar_set(struct rtl_hw *hw, uint8_t *addr);
+
 extern const struct rtl_hw_ops rtl8125a_ops;
 extern const struct rtl_hw_ops rtl8125b_ops;
 extern const struct rtl_hw_ops rtl8125bp_ops;
@@ -60,5 +69,38 @@ extern const struct rtl_hw_ops rtl8126a_ops;
 #define HW_SUPPORT_MAC_MCU(_M)            ((_M)->HwSuppMacMcuVer > 0)
 #define HW_HAS_WRITE_PHY_MCU_RAM_CODE(_M) (((_M)->HwHasWrRamCodeToMicroP == 
TRUE) ? 1 : 0)
 
+/* Tx NO CLOSE */
+#define MAX_TX_NO_CLOSE_DESC_PTR_V2            0x10000
+#define MAX_TX_NO_CLOSE_DESC_PTR_MASK_V2       0xFFFF
+#define MAX_TX_NO_CLOSE_DESC_PTR_V3            0x100000000
+#define MAX_TX_NO_CLOSE_DESC_PTR_MASK_V3       0xFFFFFFFF
+#define MAX_TX_NO_CLOSE_DESC_PTR_V4            0x80000000
+#define MAX_TX_NO_CLOSE_DESC_PTR_MASK_V4       0x7FFFFFFF
+#define TX_NO_CLOSE_SW_PTR_MASK_V2             0x1FFFF
+
+/* Ram code version */
+#define NIC_RAMCODE_VERSION_CFG_METHOD_48  (0x0b11)
+#define NIC_RAMCODE_VERSION_CFG_METHOD_49  (0x0b33)
+#define NIC_RAMCODE_VERSION_CFG_METHOD_50  (0x0b17)
+#define NIC_RAMCODE_VERSION_CFG_METHOD_51  (0x0b99)
+#define NIC_RAMCODE_VERSION_CFG_METHOD_54  (0x0013)
+#define NIC_RAMCODE_VERSION_CFG_METHOD_55  (0x0001)
+#define NIC_RAMCODE_VERSION_CFG_METHOD_56  (0x0016)
+#define NIC_RAMCODE_VERSION_CFG_METHOD_57  (0x0001)
+#define NIC_RAMCODE_VERSION_CFG_METHOD_69  (0x0023)
+#define NIC_RAMCODE_VERSION_CFG_METHOD_70  (0x0033)
+#define NIC_RAMCODE_VERSION_CFG_METHOD_71  (0x0051)
+
+#define RTL_MAC_MCU_PAGE_SIZE 256
+#define RTL_DEFAULT_MTU       1500
+
+enum effuse {
+       EFUSE_NOT_SUPPORT = 0,
+       EFUSE_SUPPORT_V1,
+       EFUSE_SUPPORT_V2,
+       EFUSE_SUPPORT_V3,
+       EFUSE_SUPPORT_V4,
+};
+
 #endif
 
diff --git a/drivers/net/r8169/r8169_phy.h b/drivers/net/r8169/r8169_phy.h
index f4da9f50ed..599a8957c4 100644
--- a/drivers/net/r8169/r8169_phy.h
+++ b/drivers/net/r8169/r8169_phy.h
@@ -20,17 +20,17 @@
 #define MII_PHYSID1            0x02    /* PHYS ID 1                   */
 #define MII_PHYSID2            0x03    /* PHYS ID 2                   */
 #define MII_ADVERTISE          0x04    /* Advertisement control reg   */
-#define MII_LPA                0x05    /* Link partner ability reg    */
+#define MII_LPA                        0x05    /* Link partner ability reg    
*/
 #define MII_EXPANSION          0x06    /* Expansion register          */
 #define MII_CTRL1000           0x09    /* 1000BASE-T control          */
 #define MII_STAT1000           0x0a    /* 1000BASE-T status           */
-#define MII_MMD_CTRL           0x0d    /* MMD Access Control Register */
-#define MII_MMD_DATA           0x0e    /* MMD Access Data Register    */
+#define        MII_MMD_CTRL            0x0d    /* MMD Access Control Register 
*/
+#define        MII_MMD_DATA            0x0e    /* MMD Access Data Register    
*/
 #define MII_ESTATUS            0x0f    /* Extended Status             */
 #define MII_DCOUNTER           0x12    /* Disconnect counter          */
 #define MII_FCSCOUNTER         0x13    /* False carrier counter       */
 #define MII_NWAYTEST           0x14    /* N-way auto-neg test reg     */
-#define MII_RERRCOUNTER        0x15    /* Receive error counter       */
+#define MII_RERRCOUNTER                0x15    /* Receive error counter       
*/
 #define MII_SREVISION          0x16    /* Silicon revision            */
 #define MII_RESV1              0x17    /* Reserved...                 */
 #define MII_LBRERROR           0x18    /* Lpback, rx, bypass error    */
@@ -80,14 +80,14 @@
 #define ADVERTISE_100HALF      0x0080  /* Try for 100mbps half-duplex */
 #define ADVERTISE_1000XPAUSE   0x0080  /* Try for 1000BASE-X pause    */
 #define ADVERTISE_100FULL      0x0100  /* Try for 100mbps full-duplex */
-#define ADVERTISE_1000XPSE_ASYM 0x0100 /* Try for 1000BASE-X asym pause */
+#define ADVERTISE_1000XPSE_ASYM        0x0100  /* Try for 1000BASE-X asym 
pause */
 #define ADVERTISE_100BASE4     0x0200  /* Try for 100mbps 4k packets  */
 #define ADVERTISE_PAUSE_CAP    0x0400  /* Try for pause               */
 #define ADVERTISE_PAUSE_ASYM   0x0800  /* Try for asymetric pause     */
 #define ADVERTISE_RESV         0x1000  /* Unused...                   */
 #define ADVERTISE_RFAULT       0x2000  /* Say we can detect faults    */
-#define ADVERTISE_LPACK        0x4000  /* Ack link partners response  */
-#define ADVERTISE_NPAGE        0x8000  /* Next page bit               */
+#define ADVERTISE_LPACK                0x4000  /* Ack link partners response  
*/
+#define ADVERTISE_NPAGE                0x8000  /* Next page bit               
*/
 
 /* 1000BASE-T Control register */
 #define ADVERTISE_1000FULL     0x0200  /* Advertise 1000BASE-T full duplex */
@@ -95,7 +95,7 @@
 
 #define RTK_ADVERTISE_2500FULL         0x80
 #define RTK_ADVERTISE_5000FULL         0x100
-#define RTK_ADVERTISE_10000FULL        0x1000
+#define RTK_ADVERTISE_10000FULL                0x1000
 #define RTK_LPA_ADVERTISE_2500FULL     0x20
 #define RTK_LPA_ADVERTISE_5000FULL     0x40
 #define RTK_LPA_ADVERTISE_10000FULL    0x800
-- 
2.34.1

Reply via email to