Add implementation for hardware registers access routines such as mmio read/write, mac ocp read/write, csi read/write and so on.
Signed-off-by: Howard Wang <howard_w...@realsil.com.cn> --- drivers/net/r8169/meson.build | 1 + drivers/net/r8169/r8169_compat.h | 377 +++++++++++++++++++++++++++++++ drivers/net/r8169/r8169_ethdev.h | 5 + drivers/net/r8169/r8169_hw.c | 91 ++++++++ drivers/net/r8169/r8169_hw.h | 28 +++ 5 files changed, 502 insertions(+) create mode 100644 drivers/net/r8169/r8169_hw.c create mode 100644 drivers/net/r8169/r8169_hw.h diff --git a/drivers/net/r8169/meson.build b/drivers/net/r8169/meson.build index f14d4ae8fb..918156fbc8 100644 --- a/drivers/net/r8169/meson.build +++ b/drivers/net/r8169/meson.build @@ -3,4 +3,5 @@ sources = files( 'r8169_ethdev.c', + 'r8169_hw.c', ) diff --git a/drivers/net/r8169/r8169_compat.h b/drivers/net/r8169/r8169_compat.h index e337ce3afa..f09fc03f73 100644 --- a/drivers/net/r8169/r8169_compat.h +++ b/drivers/net/r8169/r8169_compat.h @@ -7,11 +7,388 @@ #include <stdint.h> +#include <rte_common.h> +#include <rte_cycles.h> +#include <rte_byteorder.h> +#include <rte_io.h> +#include <rte_ether.h> + typedef uint8_t u8; typedef uint16_t u16; typedef uint32_t u32; typedef uint64_t u64; +enum RTL_registers { + MAC0 = 0x00, /* Ethernet hardware address */ + MAC4 = 0x04, + MAR0 = 0x08, /* Multicast filter */ + CounterAddrLow = 0x10, + CounterAddrHigh = 0x14, + CustomLED = 0x18, + TxDescStartAddrLow = 0x20, + TxDescStartAddrHigh = 0x24, + TxHDescStartAddrLow = 0x28, + TxHDescStartAddrHigh = 0x2C, + FLASH = 0x30, + INT_CFG0_8125 = 0x34, + ERSR = 0x36, + ChipCmd = 0x37, + TxPoll = 0x38, + IntrMask = 0x3C, + IntrStatus = 0x3E, + TxConfig = 0x40, + RxConfig = 0x44, + TCTR = 0x48, + Cfg9346 = 0x50, + Config0 = 0x51, + Config1 = 0x52, + Config2 = 0x53, + Config3 = 0x54, + Config4 = 0x55, + Config5 = 0x56, + TDFNR = 0x57, + TimeInt0 = 0x58, + TimeInt1 = 0x5C, + PHYAR = 0x60, + CSIDR = 0x64, + CSIAR = 0x68, + PHYstatus = 0x6C, + MACDBG = 0x6D, + GPIO = 0x6E, + PMCH = 0x6F, + ERIDR = 0x70, + ERIAR = 0x74, + INT_CFG1_8125 = 0x7A, + EPHY_RXER_NUM = 0x7C, + EPHYAR = 0x80, + TimeInt2 = 0x8C, + OCPDR = 0xB0, + MACOCP = 0xB0, + OCPAR = 0xB4, + SecMAC0 = 0xB4, + SecMAC4 = 0xB8, + PHYOCP = 0xB8, + DBG_reg = 0xD1, + TwiCmdReg = 0xD2, + MCUCmd_reg = 0xD3, + RxMaxSize = 0xDA, + EFUSEAR = 0xDC, + CPlusCmd = 0xE0, + IntrMitigate = 0xE2, + RxDescAddrLow = 0xE4, + RxDescAddrHigh = 0xE8, + MTPS = 0xEC, + FuncEvent = 0xF0, + PPSW = 0xF2, + FuncEventMask = 0xF4, + TimeInt3 = 0xF4, + FuncPresetState = 0xF8, + CMAC_IBCR0 = 0xF8, + CMAC_IBCR2 = 0xF9, + CMAC_IBIMR0 = 0xFA, + CMAC_IBISR0 = 0xFB, + FuncForceEvent = 0xFC, + + /* 8125 */ + IMR0_8125 = 0x38, + ISR0_8125 = 0x3C, + TPPOLL_8125 = 0x90, + IMR1_8125 = 0x800, + ISR1_8125 = 0x802, + IMR2_8125 = 0x804, + ISR2_8125 = 0x806, + IMR3_8125 = 0x808, + ISR3_8125 = 0x80A, + BACKUP_ADDR0_8125 = 0x19E0, + BACKUP_ADDR1_8125 = 0X19E4, + TCTR0_8125 = 0x0048, + TCTR1_8125 = 0x004C, + TCTR2_8125 = 0x0088, + TCTR3_8125 = 0x001C, + TIMER_INT0_8125 = 0x0058, + TIMER_INT1_8125 = 0x005C, + TIMER_INT2_8125 = 0x008C, + TIMER_INT3_8125 = 0x00F4, + INT_MITI_V2_0_RX = 0x0A00, + INT_MITI_V2_0_TX = 0x0A02, + INT_MITI_V2_1_RX = 0x0A08, + INT_MITI_V2_1_TX = 0x0A0A, + IMR_V2_CLEAR_REG_8125 = 0x0D00, + ISR_V2_8125 = 0x0D04, + IMR_V2_SET_REG_8125 = 0x0D0C, + TDU_STA_8125 = 0x0D08, + RDU_STA_8125 = 0x0D0A, + IMR_V4_L2_CLEAR_REG_8125 = 0x0D10, + IMR_V4_L2_SET_REG_8125 = 0x0D18, + ISR_V4_L2_8125 = 0x0D14, + DOUBLE_VLAN_CONFIG = 0x1000, + TX_NEW_CTRL = 0x203E, + TNPDS_Q1_LOW_8125 = 0x2100, + PLA_TXQ0_IDLE_CREDIT = 0x2500, + PLA_TXQ1_IDLE_CREDIT = 0x2504, + SW_TAIL_PTR0_8125 = 0x2800, + HW_CLO_PTR0_8125 = 0x2802, + SW_TAIL_PTR0_8126 = 0x2800, + HW_CLO_PTR0_8126 = 0x2800, + RDSAR_Q1_LOW_8125 = 0x4000, + RSS_CTRL_8125 = 0x4500, + Q_NUM_CTRL_8125 = 0x4800, + RSS_KEY_8125 = 0x4600, + RSS_INDIRECTION_TBL_8125_V2 = 0x4700, + EEE_TXIDLE_TIMER_8125 = 0x6048, +}; + +enum RTL_register_content { + /* Interrupt status bits */ + SYSErr = 0x8000, + PCSTimeout = 0x4000, + SWInt = 0x0100, + TxDescUnavail = 0x0080, + RxFIFOOver = 0x0040, + LinkChg = 0x0020, + RxDescUnavail = 0x0010, + TxErr = 0x0008, + TxOK = 0x0004, + RxErr = 0x0002, + RxOK = 0x0001, + + /* RX status desc */ + RxRWT = (1UL << 22), + RxRES = (1UL << 21), + RxRUNT = (1UL << 20), + RxCRC = (1UL << 19), + + /* ChipCmd bits */ + StopReq = 0x80, + CmdReset = 0x10, + CmdRxEnb = 0x08, + CmdTxEnb = 0x04, + RxBufEmpty = 0x01, + + /* Cfg9346 bits */ + Cfg9346_Lock = 0x00, + Cfg9346_Unlock = 0xC0, + Cfg9346_EEDO = (1UL << 0), + Cfg9346_EEDI = (1UL << 1), + Cfg9346_EESK = (1UL << 2), + Cfg9346_EECS = (1UL << 3), + Cfg9346_EEM0 = (1UL << 6), + Cfg9346_EEM1 = (1UL << 7), + + /* RX mode bits */ + AcceptErr = 0x20, + AcceptRunt = 0x10, + AcceptBroadcast = 0x08, + AcceptMulticast = 0x04, + AcceptMyPhys = 0x02, + AcceptAllPhys = 0x01, + + /* Transmit priority polling */ + HPQ = 0x80, + NPQ = 0x40, + FSWInt = 0x01, + + /* RX config bits */ + Reserved2_shift = 13, + RxCfgDMAShift = 8, + EnableRxDescV3 = (1 << 24), + EnableOuterVlan = (1 << 23), + EnableInnerVlan = (1 << 22), + RxCfg_128_int_en = (1 << 15), + RxCfg_fet_multi_en = (1 << 14), + RxCfg_half_refetch = (1 << 13), + RxCfg_pause_slot_en = (1 << 11), + RxCfg_9356SEL = (1 << 6), + EnableRxDescV4_0 = (1 << 1), /* Not in rcr */ + + /* TX config bits */ + TxInterFrameGapShift = 24, + TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits. */ + TxMACLoopBack = (1UL << 17), /* MAC loopback */ + + /* Config1 register */ + LEDS1 = (1UL << 7), + LEDS0 = (1UL << 6), + Speed_down = (1UL << 4), + MEMMAP = (1UL << 3), + IOMAP = (1UL << 2), + VPD = (1UL << 1), + PMEnable = (1UL << 0), /* Power management enable */ + + /* Config2 register */ + PMSTS_En = (1UL << 5), + + /* Config3 register */ + Isolate_en = (1UL << 12), /* Isolate enable */ + MagicPacket = (1UL << 5), /* Wake up when receives a magic packet */ + LinkUp = (1UL << 4), /* This bit is reserved in RTL8125B. */ + + /* Wake up when the cable connection is re-established */ + ECRCEN = (1UL << 3), /* This bit is reserved in RTL8125B. */ + Jumbo_En0 = (1UL << 2), /* This bit is reserved in RTL8125B. */ + RDY_TO_L23 = (1UL << 1), /* This bit is reserved in RTL8125B. */ + Beacon_en = (1UL << 0), /* This bit is reserved in RTL8125B. */ + + /* Config4 register */ + Jumbo_En1 = (1UL << 1), /* This bit is reserved in RTL8125B. */ + + /* Config5 register */ + BWF = (1UL << 6), /* Accept broadcast wakeup frame */ + MWF = (1UL << 5), /* Accept multicast wakeup frame */ + UWF = (1UL << 4), /* Accept unicast wakeup frame */ + LanWake = (1UL << 1), /* LanWake enable/disable */ + PMEStatus = (1UL << 0), /* PME status can be reset by PCI RST#. */ + + /* CPlusCmd */ + EnableBist = (1UL << 15), + Macdbgo_oe = (1UL << 14), + Normal_mode = (1UL << 13), + Force_halfdup = (1UL << 12), + Force_rxflow_en = (1UL << 11), + Force_txflow_en = (1UL << 10), + Cxpl_dbg_sel = (1UL << 9), /* This bit is reserved in RTL8125B. */ + ASF = (1UL << 8), /* This bit is reserved in RTL8125C. */ + PktCntrDisable = (1UL << 7), + RxVlan = (1UL << 6), + RxChkSum = (1UL << 5), + Macdbgo_sel = 0x001C, + INTT_0 = 0x0000, + INTT_1 = 0x0001, + INTT_2 = 0x0002, + INTT_3 = 0x0003, + + /* PHY status */ + PowerSaveStatus = 0x80, + _2500bpsF = 0x400, + TxFlowCtrl = 0x40, + RxFlowCtrl = 0x20, + _1000bpsF = 0x10, + _100bps = 0x08, + _10bps = 0x04, + LinkStatus = 0x02, + FullDup = 0x01, + + /* DBG reg */ + Fix_Nak_1 = (1UL << 4), + Fix_Nak_2 = (1UL << 3), + DBGPIN_E2 = (1UL << 0), + + /* Reset counter command */ + CounterReset = 0x1, + /* Dump counter command */ + CounterDump = 0x8, + + /* PHY access */ + PHYAR_Flag = 0x80000000, + PHYAR_Write = 0x80000000, + PHYAR_Read = 0x00000000, + PHYAR_Reg_Mask = 0x1f, + PHYAR_Reg_shift = 16, + PHYAR_Data_Mask = 0xffff, + + /* EPHY access */ + EPHYAR_Flag = 0x80000000, + EPHYAR_Write = 0x80000000, + EPHYAR_Read = 0x00000000, + EPHYAR_Reg_Mask = 0x3f, + EPHYAR_Reg_Mask_v2 = 0x7f, + EPHYAR_Reg_shift = 16, + EPHYAR_Data_Mask = 0xffff, + + /* CSI access */ + CSIAR_Flag = 0x80000000, + CSIAR_Write = 0x80000000, + CSIAR_Read = 0x00000000, + CSIAR_ByteEn = 0x0f, + CSIAR_ByteEn_shift = 12, + CSIAR_Addr_Mask = 0x0fff, + + /* ERI access */ + ERIAR_Flag = 0x80000000, + ERIAR_Write = 0x80000000, + ERIAR_Read = 0x00000000, + ERIAR_Addr_Align = 4, /* ERI access register address must be 4 byte alignment. */ + ERIAR_ExGMAC = 0, + ERIAR_MSIX = 1, + ERIAR_ASF = 2, + ERIAR_OOB = 2, + ERIAR_Type_shift = 16, + ERIAR_ByteEn = 0x0f, + ERIAR_ByteEn_shift = 12, + + /* OCP GPHY access */ + OCPDR_Write = 0x80000000, + OCPDR_Read = 0x00000000, + OCPDR_Reg_Mask = 0xFF, + OCPDR_Data_Mask = 0xFFFF, + OCPDR_GPHY_Reg_shift = 16, + OCPAR_Flag = 0x80000000, + OCPAR_GPHY_Write = 0x8000F060, + OCPAR_GPHY_Read = 0x0000F060, + OCPR_Write = 0x80000000, + OCPR_Read = 0x00000000, + OCPR_Addr_Reg_shift = 16, + OCPR_Flag = 0x80000000, + OCP_STD_PHY_BASE_PAGE = 0x0A40, + + /* MCU command */ + Now_is_oob = (1UL << 7), + Txfifo_empty = (1UL << 5), + Rxfifo_empty = (1UL << 4), + + /* E-FUSE access */ + EFUSE_WRITE = 0x80000000, + EFUSE_WRITE_OK = 0x00000000, + EFUSE_READ = 0x00000000, + EFUSE_READ_OK = 0x80000000, + EFUSE_WRITE_V3 = 0x40000000, + EFUSE_WRITE_OK_V3 = 0x00000000, + EFUSE_READ_V3 = 0x80000000, + EFUSE_READ_OK_V3 = 0x00000000, + EFUSE_Reg_Mask = 0x03FF, + EFUSE_Reg_Shift = 8, + EFUSE_Check_Cnt = 300, + EFUSE_READ_FAIL = 0xFF, + EFUSE_Data_Mask = 0x000000FF, + + /* GPIO */ + GPIO_en = (1UL << 0), + + /* New interrupt bits */ + INT_CFG0_ENABLE_8125 = (1 << 0), + INT_CFG0_TIMEOUT0_BYPASS_8125 = (1 << 1), + INT_CFG0_MITIGATION_BYPASS_8125 = (1 << 2), + ISRIMR_V2_ROK_Q0 = (1 << 0), + ISRIMR_TOK_Q0 = (1 << 16), + ISRIMR_TOK_Q1 = (1 << 18), + ISRIMR_V2_LINKCHG = (1 << 21), +}; + #define PCI_VENDOR_ID_REALTEK 0x10EC +#define RTL_PCI_REG_ADDR(hw, reg) ((u8 *)(hw)->mmio_addr + (reg)) + +#define RTL_R8(hw, reg) rte_read8(RTL_PCI_REG_ADDR(hw, reg)) +#define RTL_R16(hw, reg) rtl_read16(RTL_PCI_REG_ADDR(hw, reg)) +#define RTL_R32(hw, reg) rtl_read32(RTL_PCI_REG_ADDR(hw, reg)) + +#define RTL_W8(hw, reg, val) \ + rte_write8((val), RTL_PCI_REG_ADDR(hw, reg)) +#define RTL_W16(hw, reg, val) \ + rte_write16((rte_cpu_to_le_16(val)), RTL_PCI_REG_ADDR(hw, reg)) +#define RTL_W32(hw, reg, val) \ + rte_write32((rte_cpu_to_le_32(val)), RTL_PCI_REG_ADDR(hw, reg)) + +static inline u32 +rtl_read32(void *addr) +{ + return rte_le_to_cpu_32(rte_read32(addr)); +} + +static inline u32 +rtl_read16(void *addr) +{ + return rte_le_to_cpu_16(rte_read16(addr)); +} + #endif diff --git a/drivers/net/r8169/r8169_ethdev.h b/drivers/net/r8169/r8169_ethdev.h index 561caa7acf..8745ff8a6c 100644 --- a/drivers/net/r8169/r8169_ethdev.h +++ b/drivers/net/r8169/r8169_ethdev.h @@ -12,6 +12,10 @@ #include "r8169_compat.h" +struct rtl_hw { + u8 *mmio_addr; +}; + struct rtl_sw_stats { u64 tx_packets; u64 tx_bytes; @@ -22,6 +26,7 @@ struct rtl_sw_stats { }; struct rtl_adapter { + struct rtl_hw hw; struct rtl_sw_stats sw_stats; }; diff --git a/drivers/net/r8169/r8169_hw.c b/drivers/net/r8169/r8169_hw.c new file mode 100644 index 0000000000..a616d84fb9 --- /dev/null +++ b/drivers/net/r8169/r8169_hw.c @@ -0,0 +1,91 @@ +/* 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_hw.h" +#include "r8169_logs.h" + +void +rtl_mac_ocp_write(struct rtl_hw *hw, u16 addr, u16 value) +{ + u32 data32; + + data32 = addr / 2; + data32 <<= OCPR_Addr_Reg_shift; + data32 += value; + data32 |= OCPR_Write; + + RTL_W32(hw, MACOCP, data32); +} + +u16 +rtl_mac_ocp_read(struct rtl_hw *hw, u16 addr) +{ + u32 data32; + u16 data16 = 0; + + data32 = addr / 2; + data32 <<= OCPR_Addr_Reg_shift; + + RTL_W32(hw, MACOCP, data32); + data16 = (u16)RTL_R32(hw, MACOCP); + + return data16; +} + +u32 +rtl_csi_read(struct rtl_hw *hw, u32 addr) +{ + u32 cmd; + int i; + u32 value = 0; + + cmd = CSIAR_Read | CSIAR_ByteEn << CSIAR_ByteEn_shift | + (addr & CSIAR_Addr_Mask); + + RTL_W32(hw, CSIAR, cmd); + + for (i = 0; i < 10; i++) { + rte_delay_us(100); + + /* Check if the NIC has completed CSI read */ + if (RTL_R32(hw, CSIAR) & CSIAR_Flag) { + value = RTL_R32(hw, CSIDR); + break; + } + } + + rte_delay_us(20); + + return value; +} + +void +rtl_csi_write(struct rtl_hw *hw, u32 addr, u32 value) +{ + u32 cmd; + int i; + + RTL_W32(hw, CSIDR, value); + cmd = CSIAR_Write | CSIAR_ByteEn << CSIAR_ByteEn_shift | + (addr & CSIAR_Addr_Mask); + + RTL_W32(hw, CSIAR, cmd); + + for (i = 0; i < RTL_CHANNEL_WAIT_COUNT; i++) { + rte_delay_us(RTL_CHANNEL_WAIT_TIME); + + /* Check if the NIC has completed CSI write */ + if (!(RTL_R32(hw, CSIAR) & CSIAR_Flag)) + break; + } + + rte_delay_us(RTL_CHANNEL_EXIT_DELAY_TIME); +} diff --git a/drivers/net/r8169/r8169_hw.h b/drivers/net/r8169/r8169_hw.h new file mode 100644 index 0000000000..c9ded0f0e4 --- /dev/null +++ b/drivers/net/r8169/r8169_hw.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024 Realtek Corporation. All rights reserved + */ + +#ifndef _R8169_HW_H_ +#define _R8169_HW_H_ + +#include <stdint.h> + +#include <bus_pci_driver.h> +#include <rte_ethdev.h> +#include <rte_ethdev_core.h> + +#include "r8169_compat.h" +#include "r8169_ethdev.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_csi_read(struct rtl_hw *hw, u32 addr); +void rtl_csi_write(struct rtl_hw *hw, u32 addr, u32 value); + +/* Channel wait count */ +#define RTL_CHANNEL_WAIT_COUNT 20000 +#define RTL_CHANNEL_WAIT_TIME 1 /* 1 us */ +#define RTL_CHANNEL_EXIT_DELAY_TIME 20 /* 20 us */ + +#endif -- 2.34.1