@@ -5,4 +5,5 @@ sources = files(
'r8169_ethdev.c',
'r8169_hw.c',
'r8169_rxtx.c',
+ 'r8169_phy.c',
)
@@ -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),
@@ -384,6 +497,18 @@ enum RTL_register_content {
#define RTL_W32(hw, reg, val) \
rte_write32((rte_cpu_to_le_32(val)), RTL_PCI_REG_ADDR(hw, reg))
+#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)
{
@@ -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);
@@ -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 {
@@ -14,6 +14,256 @@
#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++) {
+ rte_delay_us(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;
+ }
+ }
+
+ rte_delay_us(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++) {
+ rte_delay_us(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;
+ }
+ }
+
+ rte_delay_us(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)
{
@@ -91,3 +341,463 @@ rtl_csi_write(struct rtl_hw *hw, u32 addr, u32 value)
rte_delay_us(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);
+ rte_delay_ms(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);
+ rte_delay_ms(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++) {
+ rte_delay_us(10);
+ if (!(RTL_R8(hw, ChipCmd) & StopReq))
+ break;
+ }
+
+ break;
+ default:
+ rte_delay_us(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++) {
+ rte_delay_us(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++) {
+ rte_delay_us(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);
+
+ rte_delay_ms(2);
+
+ /* Soft reset the chip. */
+ RTL_W8(hw, ChipCmd, CmdReset);
+
+ /* Check that the chip has finished the reset. */
+ for (i = 100; i > 0; i--) {
+ rte_delay_us(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);
+ rte_delay_us(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);
+
+ rte_delay_us(10);
+}
@@ -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 */
new file mode 100644
@@ -0,0 +1,40 @@
+/* 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);
+}
new file mode 100644
@@ -0,0 +1,20 @@
+/* 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