From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 6F3A945CF3; Wed, 13 Nov 2024 10:30:25 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 5ABE540290; Wed, 13 Nov 2024 10:30:25 +0100 (CET) Received: from rtits2.realtek.com.tw (rtits2.realtek.com [211.75.126.72]) by mails.dpdk.org (Postfix) with ESMTP id C595B40290 for ; Wed, 13 Nov 2024 10:30:23 +0100 (CET) X-SpamFilter-By: ArmorX SpamTrap 5.78 with qID 4AD9ULNO01089374, This message is accepted by code: ctloc85258 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=realsil.com.cn; s=dkim; t=1731490222; bh=FBJmv3GskpwhfT/JSDxMnf1++Irnq7SMscIQr6NbsXQ=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Transfer-Encoding:Content-Type; b=l3bAf63NSz34CmRgDDYMvgJD8jkYgt662gbCxIDZ1noGmJmgPKw7CXRKM1sxTXhkv jEGkFTJoHmm6rhhSp62IE8DuK+X1S+rjUydHzfRcbP2LgwrE4QXYaQ082q8C0ByFtt +M8wOZ4x3qld/9oIKH0ZsptolppQaOroYfpiHknBaWg3QQ2LlX24lRfNX8AXR7qbB7 BfWWeB99VLdlfgoM6q01z0M3Wgxdt/VatFzwrDoBeykfoULg5hoRsGB63SFFfAqv7/ QRScHpWJ9zhCv+hmEQzzjJAmmYaIxTcuiqC4zdzZDK2AJyK4zaOflTrHfYcFbHHw2C nGmU6AxIeDHRQ== Received: from RSEXMBS01.realsil.com.cn ([172.29.17.195]) by rtits2.realtek.com.tw (8.15.2/3.06/5.92) with ESMTPS id 4AD9ULNO01089374 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=FAIL) for ; Wed, 13 Nov 2024 17:30:21 +0800 Received: from RSEXH36502.realsil.com.cn (172.29.17.3) by RSEXMBS01.realsil.com.cn (172.29.17.195) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.35; Wed, 13 Nov 2024 17:30:20 +0800 Received: from 172.29.32.27 (172.29.32.27) by RSEXH36502.realsil.com.cn (172.29.17.3) with Microsoft SMTP Server id 15.1.2507.35 via Frontend Transport; Wed, 13 Nov 2024 17:30:20 +0800 From: Howard Wang To: CC: , Howard Wang Subject: [PATCH v8 05/17] net/r8169: add support for HW config Date: Wed, 13 Nov 2024 17:28:42 +0800 Message-ID: <20241113092854.91445-6-howard_wang@realsil.com.cn> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241113092854.91445-1-howard_wang@realsil.com.cn> References: <20241113092854.91445-1-howard_wang@realsil.com.cn> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Implement the rtl_hw_config function to configure the hardware. This function is similar to rtl81xx_hw_config in Realtek Linux driver, primarily initializing some registers during the start. Signed-off-by: Howard Wang --- drivers/net/r8169/meson.build | 1 + drivers/net/r8169/r8169_compat.h | 125 ++++++ drivers/net/r8169/r8169_ethdev.c | 4 + drivers/net/r8169/r8169_ethdev.h | 16 +- drivers/net/r8169/r8169_hw.c | 710 +++++++++++++++++++++++++++++++ drivers/net/r8169/r8169_hw.h | 17 + drivers/net/r8169/r8169_phy.c | 38 ++ drivers/net/r8169/r8169_phy.h | 19 + 8 files changed, 929 insertions(+), 1 deletion(-) 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 3b6b6aa912..0697e9dc49 100644 --- a/drivers/net/r8169/meson.build +++ b/drivers/net/r8169/meson.build @@ -5,4 +5,5 @@ sources = files( 'r8169_ethdev.c', 'r8169_hw.c', 'r8169_rxtx.c', + 'r8169_phy.c', ) diff --git a/drivers/net/r8169/r8169_compat.h b/drivers/net/r8169/r8169_compat.h index f09fc03f73..44b4daed87 100644 --- a/drivers/net/r8169/r8169_compat.h +++ b/drivers/net/r8169/r8169_compat.h @@ -18,6 +18,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, @@ -358,6 +469,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), @@ -379,6 +492,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(void *addr) { diff --git a/drivers/net/r8169/r8169_ethdev.c b/drivers/net/r8169/r8169_ethdev.c index 3bfac5d011..2dd3ee6786 100644 --- a/drivers/net/r8169/r8169_ethdev.c +++ b/drivers/net/r8169/r8169_ethdev.c @@ -58,8 +58,12 @@ rtl_dev_configure(struct rte_eth_dev *dev __rte_unused) static int rtl_dev_start(struct rte_eth_dev *dev) { + struct rtl_adapter *adapter = RTL_DEV_PRIVATE(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 3f179b0ebb..ac0b3eef47 100644 --- a/drivers/net/r8169/r8169_ethdev.h +++ b/drivers/net/r8169/r8169_ethdev.h @@ -13,7 +13,18 @@ #include "r8169_compat.h" struct rtl_hw { - u8 *mmio_addr; + 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 { @@ -30,6 +41,9 @@ struct rtl_adapter { struct rtl_sw_stats sw_stats; }; +#define RTL_DEV_PRIVATE(eth_dev) \ + ((struct rtl_adapter *)((eth_dev)->data->dev_private)) + int rtl_rx_init(struct rte_eth_dev *dev); int rtl_tx_init(struct rte_eth_dev *dev); diff --git a/drivers/net/r8169/r8169_hw.c b/drivers/net/r8169/r8169_hw.c index a616d84fb9..52c387c8e7 100644 --- a/drivers/net/r8169/r8169_hw.c +++ b/drivers/net/r8169/r8169_hw.c @@ -12,6 +12,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) { @@ -89,3 +339,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); +} diff --git a/drivers/net/r8169/r8169_hw.h b/drivers/net/r8169/r8169_hw.h index c9ded0f0e4..418843a77f 100644 --- a/drivers/net/r8169/r8169_hw.h +++ b/drivers/net/r8169/r8169_hw.h @@ -13,13 +13,30 @@ #include "r8169_compat.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..11c28deefe --- /dev/null +++ b/drivers/net/r8169/r8169_phy.c @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024 Realtek Corporation. All rights reserved + */ + +#include +#include +#include + +#include +#include + +#include "r8169_ethdev.h" +#include "r8169_hw.h" +#include "r8169_phy.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..ee2aa43fde --- /dev/null +++ b/drivers/net/r8169/r8169_phy.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024 Realtek Corporation. All rights reserved + */ + +#ifndef _R8169_PHY_H_ +#define _R8169_PHY_H_ + +#include + +#include +#include + +#include "r8169_compat.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