@@ -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',
@@ -232,6 +232,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,
@@ -477,6 +481,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))
@@ -510,6 +524,31 @@ enum RTL_register_content {
#define TRUE 1
#define FALSE 0
+#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 MAC_ADDR_LEN RTE_ETHER_ADDR_LEN
+
static inline u32
rtl_read32(void *addr)
{
new file mode 100644
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2024 Realtek Corporation. All rights reserved
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+
+#include <rte_ether.h>
+#include <ethdev_driver.h>
+
+#include "r8169_compat.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 (HW_DASH_SUPPORT_GET_FIRMWARE_VERSION(hw) == FALSE)
+ 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;
+}
new file mode 100644
@@ -0,0 +1,33 @@
+/* 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_compat.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
@@ -3,16 +3,21 @@
*/
#include <stdio.h>
+#include <errno.h>
#include <stdint.h>
#include <rte_eal.h>
#include <rte_common.h>
+#include <rte_interrupts.h>
+#include <rte_byteorder.h>
#include <rte_pci.h>
#include <bus_pci_driver.h>
#include <rte_ether.h>
#include <ethdev_driver.h>
#include <ethdev_pci.h>
+#include <rte_memory.h>
+#include <rte_malloc.h>
#include <dev_driver.h>
#include "r8169_ethdev.h"
@@ -96,6 +101,15 @@ rtl_dev_stop(struct rte_eth_dev *dev)
struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
struct rtl_hw *hw = &adapter->hw;
+ 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);
return 0;
@@ -107,6 +121,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)
@@ -114,14 +130,20 @@ 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;
}
static int
rtl_dev_init(struct rte_eth_dev *dev)
{
+ struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
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;
@@ -131,9 +153,39 @@ rtl_dev_init(struct rte_eth_dev *dev)
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
return 0;
+ 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;
}
@@ -22,13 +22,27 @@ 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 *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;
@@ -42,10 +56,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;
@@ -11,6 +11,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,
@@ -917,3 +918,585 @@ rtl_write_mac_mcu_ram_code(struct rtl_hw *hw, const u16 *entry, u16 entry_cnt)
else
_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++) {
+ rte_delay_us(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);
+}
@@ -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,4 +69,37 @@ 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
@@ -14,7 +14,6 @@
#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)
@@ -24,8 +24,8 @@
#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 */
@@ -80,7 +80,7 @@
#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 */