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

Reply via email to