lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:   Mon,  5 Sep 2022 20:52:24 +0800
From:   Mengyuan Lou <mengyuanlou@...-swift.com>
To:     netdev@...r.kernel.org
Cc:     jiawenwu@...-swift.com, Mengyuan Lou <mengyuanlou@...-swift.com>
Subject: [PATCH net-next 2] net: ngbe: sw init and hw init

Initialize ngbe adapter
Initialize ngbe hardware configuration

Signed-off-by: Mengyuan Lou <mengyuanlou@...-swift.com>
---
 drivers/net/ethernet/wangxun/ngbe/Makefile    |   2 +-
 drivers/net/ethernet/wangxun/ngbe/ngbe.h      |  51 +-
 drivers/net/ethernet/wangxun/ngbe/ngbe_hw.c   | 694 ++++++++++++++++++
 drivers/net/ethernet/wangxun/ngbe/ngbe_hw.h   |  26 +
 drivers/net/ethernet/wangxun/ngbe/ngbe_main.c | 253 +++++++
 .../net/ethernet/wangxun/ngbe/ngbe_osdep.h    |  31 +
 drivers/net/ethernet/wangxun/ngbe/ngbe_type.h | 432 ++++++++++-
 7 files changed, 1484 insertions(+), 5 deletions(-)
 create mode 100644 drivers/net/ethernet/wangxun/ngbe/ngbe_hw.c
 create mode 100644 drivers/net/ethernet/wangxun/ngbe/ngbe_hw.h
 create mode 100644 drivers/net/ethernet/wangxun/ngbe/ngbe_osdep.h

diff --git a/drivers/net/ethernet/wangxun/ngbe/Makefile b/drivers/net/ethernet/wangxun/ngbe/Makefile
index 0baf75907496..391c2cbc1bb4 100644
--- a/drivers/net/ethernet/wangxun/ngbe/Makefile
+++ b/drivers/net/ethernet/wangxun/ngbe/Makefile
@@ -6,4 +6,4 @@
 
 obj-$(CONFIG_NGBE) += ngbe.o
 
-ngbe-objs := ngbe_main.o
+ngbe-objs := ngbe_main.o ngbe_hw.o
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe.h b/drivers/net/ethernet/wangxun/ngbe/ngbe.h
index f5fa6e5238cc..3d100c7ab22e 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe.h
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe.h
@@ -4,6 +4,7 @@
 #ifndef _NGBE_H_
 #define _NGBE_H_
 
+#include "ngbe_osdep.h"
 #include "ngbe_type.h"
 
 #define NGBE_MAX_FDIR_INDICES		7
@@ -11,14 +12,62 @@
 #define NGBE_MAX_RX_QUEUES		(NGBE_MAX_FDIR_INDICES + 1)
 #define NGBE_MAX_TX_QUEUES		(NGBE_MAX_FDIR_INDICES + 1)
 
+/* TX/RX descriptor defines */
+#define NGBE_DEFAULT_TXD		512 /* default ring size */
+#define NGBE_DEFAULT_TX_WORK		256
+#define NGBE_MAX_TXD			8192
+#define NGBE_MIN_TXD			128
+
+#define NGBE_DEFAULT_RXD		512 /* default ring size */
+#define NGBE_DEFAULT_RX_WORK		256
+#define NGBE_MAX_RXD			8192
+#define NGBE_MIN_RXD			128
+
+struct ngbe_mac_addr {
+	u8 addr[ETH_ALEN];
+	u16 state; /* bitmask */
+	u8 pools;
+};
+
 /* board specific private data structure */
 struct ngbe_adapter {
 	u8 __iomem *io_addr;    /* Mainly for iounmap use */
 	/* OS defined structs */
 	struct net_device *netdev;
 	struct pci_dev *pdev;
+
+	/* structs defined in ngbe_hw.h */
+	struct ngbe_hw hw;
+
+	/* Tx fast path data */
+	int num_tx_queues;
+	u16 tx_itr_setting;
+	u16 tx_work_limit;
+
+	/* Rx fast path data */
+	int num_rx_queues;
+	u16 rx_itr_setting;
+	u16 rx_work_limit;
+
+	struct ngbe_mac_addr *mac_table;
+
+	int num_q_vectors;      /* current number of q_vectors for device */
+	int max_q_vectors;      /* upper limit of q_vectors for device */
+
+	u32 tx_ring_count;
+	u32 rx_ring_count;
+
+#define NGBE_MAX_RETA_ENTRIES 128
+	u8 rss_indir_tbl[NGBE_MAX_RETA_ENTRIES];
+
+#define NGBE_RSS_KEY_SIZE     40  /* size of RSS Hash Key in bytes */
+	u32 *rss_key;
+
+	char eeprom_id[32];
+	u16 eeprom_cap;
+	u16 bd_number;
+	u32 wol;
 };
 
 extern char ngbe_driver_name[];
-
 #endif /* _NGBE_H_ */
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_hw.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_hw.c
new file mode 100644
index 000000000000..f38dc47b8f32
--- /dev/null
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_hw.c
@@ -0,0 +1,694 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2019 - 2022 Beijing WangXun Technology Co., Ltd. */
+
+#include <linux/iopoll.h>
+
+#include "ngbe.h"
+#include "ngbe_hw.h"
+
+u32 rd32m(struct ngbe_hw *hw, u32 reg, u32 mask)
+{
+	u32 val;
+
+	val = rd32(hw, reg);
+	return val & mask;
+}
+
+void wr32m(struct ngbe_hw *hw, u32 reg, u32 mask, u32 field)
+{
+	u32 val;
+
+	val = rd32(hw, reg);
+	val = ((val & ~mask) | (field & mask));
+	wr32(hw, reg, val);
+}
+
+/**
+ * ngbe_hw_to_dev - Get device pointer from the hardware structure
+ * @hw: pointer to the device HW structure
+ *
+ * Used to access the device pointer
+ */
+struct device *ngbe_hw_to_dev(struct ngbe_hw *hw)
+{
+	struct ngbe_adapter *adapter = container_of(hw, struct ngbe_adapter, hw);
+
+	return &adapter->pdev->dev;
+}
+
+/**
+ *  ngbe_init_uta_tables - Initialize the Unicast Table Array
+ *  @hw: pointer to hardware structure
+ **/
+static void ngbe_init_uta_tables(struct ngbe_hw *hw)
+{
+	int i;
+
+	for (i = 0; i < 128; i++)
+		wr32(hw, NGBE_PSR_UC_TBL(i), 0);
+}
+
+/**
+ *  ngbe_get_mac_addr - Generic get MAC address
+ *  @hw: pointer to hardware structure
+ *  @mac_addr: Adapter MAC address
+ *
+ *  Reads the adapter's MAC address from first Receive Address Register (RAR0)
+ *  A reset of the adapter must be performed prior to calling this function
+ *  in order for the MAC address to have been loaded from the EEPROM into RAR0
+ **/
+static void ngbe_get_mac_addr(struct ngbe_hw *hw, u8 *mac_addr)
+{
+	u32 rar_high;
+	u32 rar_low;
+	u16 i;
+
+	wr32(hw, NGBE_PSR_MAC_SWC_IDX, 0);
+	rar_high = rd32(hw, NGBE_PSR_MAC_SWC_AD_H);
+	rar_low = rd32(hw, NGBE_PSR_MAC_SWC_AD_L);
+
+	for (i = 0; i < 2; i++)
+		mac_addr[i] = (u8)(rar_high >> (1 - i) * 8);
+
+	for (i = 0; i < 4; i++)
+		mac_addr[i + 2] = (u8)(rar_low >> (3 - i) * 8);
+}
+
+/**
+ *  ngbe_validate_mac_addr - Validate MAC address
+ *  @mac_addr: pointer to MAC address.
+ *
+ *  Tests a MAC address to ensure it is a valid Individual Address
+ **/
+static int ngbe_validate_mac_addr(u8 *mac_addr)
+{
+	/* Make sure it is not a multicast address */
+	if (is_multicast_ether_addr(mac_addr))
+		return -EINVAL;
+	/* Not a broadcast address */
+	else if (is_broadcast_ether_addr(mac_addr))
+		return -EINVAL;
+	/* Reject the zero address */
+	else if (is_zero_ether_addr(mac_addr))
+		return -EINVAL;
+	return 0;
+}
+
+/**
+ *  ngbe_set_rar - Set Rx address register
+ *  @hw: pointer to hardware structure
+ *  @index: Receive address register to write
+ *  @addr: Address to put into receive address register
+ *  @pools: "pool" index
+ *  @enable_addr: set flag that address is active
+ *
+ *  Puts an ethernet address into a receive address register.
+ **/
+static int ngbe_set_rar(struct ngbe_hw *hw, u32 index, u8 *addr, u64 pools,
+			u32 enable_addr)
+{
+	u32 rar_low, rar_high;
+	u32 rar_entries = hw->mac.num_rar_entries;
+
+	/* Make sure we are using a valid rar index range */
+	if (index >= rar_entries) {
+		dev_err(ngbe_hw_to_dev(hw),
+			"RAR index %d is out of range.\n", index);
+		return -EINVAL;
+	}
+
+	/* select the MAC address */
+	wr32(hw, NGBE_PSR_MAC_SWC_IDX, index);
+
+	/* setup VMDq pool mapping */
+	wr32(hw, NGBE_PSR_MAC_SWC_VM, pools & 0xFFFFFFFF);
+
+	/* HW expects these in little endian so we reverse the byte
+	 * order from network order (big endian) to little endian
+	 */
+	rar_low = ((u32)addr[5] |
+		  ((u32)addr[4] << 8) |
+		  ((u32)addr[3] << 16) |
+		  ((u32)addr[2] << 24));
+	rar_high = ((u32)addr[1] |
+		   ((u32)addr[0] << 8));
+	if (enable_addr != 0)
+		rar_high |= NGBE_PSR_MAC_SWC_AD_H_AV;
+
+	wr32(hw, NGBE_PSR_MAC_SWC_AD_L, rar_low);
+	wr32m(hw, NGBE_PSR_MAC_SWC_AD_H,
+	      (NGBE_PSR_MAC_SWC_AD_H_AD(~0) |
+	      NGBE_PSR_MAC_SWC_AD_H_ADTYPE(~0) |
+	      NGBE_PSR_MAC_SWC_AD_H_AV), rar_high);
+
+	return 0;
+}
+
+/**
+ *  ngbe_init_rx_addrs - Initializes receive address filters.
+ *  @hw: pointer to hardware structure
+ *
+ *  Places the MAC address in receive address register 0 and clears the rest
+ *  of the receive address registers. Clears the multicast table. Assumes
+ *  the receiver is in reset when the routine is called.
+ **/
+static void ngbe_init_rx_addrs(struct ngbe_hw *hw)
+{
+	u32 i;
+	u32 rar_entries = hw->mac.num_rar_entries;
+	u32 psrctl;
+
+	/* If the current mac address is valid, assume it is a software override
+	 * to the permanent address.
+	 * Otherwise, use the permanent address from the eeprom.
+	 */
+	if (ngbe_validate_mac_addr(hw->mac.addr) < 0) {
+		/* Get the MAC address from the RAR0 for later reference */
+		ngbe_get_mac_addr(hw, hw->mac.addr);
+		dev_dbg(ngbe_hw_to_dev(hw),
+			"Keeping Current RAR0 Addr =%.2X %.2X %.2X %.2X %.2X %.2X\n",
+			hw->mac.addr[0], hw->mac.addr[1],
+			hw->mac.addr[2], hw->mac.addr[3],
+			hw->mac.addr[4], hw->mac.addr[5]);
+	} else {
+		/* Setup the receive address. */
+		dev_dbg(ngbe_hw_to_dev(hw), "Overriding MAC Address in RAR[0]\n");
+		dev_dbg(ngbe_hw_to_dev(hw),
+			"New MAC Addr =%.2X %.2X %.2X %.2X %.2X %.2X\n",
+			hw->mac.addr[0], hw->mac.addr[1],
+			hw->mac.addr[2], hw->mac.addr[3],
+			hw->mac.addr[4], hw->mac.addr[5]);
+		ngbe_set_rar(hw, 0, hw->mac.addr, 0, NGBE_PSR_MAC_SWC_AD_H_AV);
+	}
+	hw->addr_ctrl.overflow_promisc = 0;
+	hw->addr_ctrl.rar_used_count = 1;
+	/* Zero out the other receive addresses. */
+	for (i = 1; i < rar_entries; i++) {
+		wr32(hw, NGBE_PSR_MAC_SWC_IDX, i);
+		wr32(hw, NGBE_PSR_MAC_SWC_AD_L, 0);
+		wr32(hw, NGBE_PSR_MAC_SWC_AD_H, 0);
+	}
+	/* Clear the MTA */
+	hw->addr_ctrl.mta_in_use = 0;
+	psrctl = rd32(hw, NGBE_PSR_CTL);
+	psrctl &= ~(NGBE_PSR_CTL_MO | NGBE_PSR_CTL_MFE);
+	psrctl |= hw->mac.mc_filter_type << NGBE_PSR_CTL_MO_SHIFT;
+	wr32(hw, NGBE_PSR_CTL, psrctl);
+	for (i = 0; i < hw->mac.mcft_size; i++)
+		wr32(hw, NGBE_PSR_MC_TBL(i), 0);
+
+	ngbe_init_uta_tables(hw);
+}
+
+static int ngbe_fmgr_cmd_op(struct ngbe_hw *hw, u32 cmd, u32 cmd_addr)
+{
+	u32 cmd_val = 0, val = 0;
+
+	cmd_val = (cmd << NGBE_SPI_CLK_CMD_OFFSET) |
+		  (NGBE_SPI_CLK_DIV << NGBE_SPI_CLK_DIV_OFFSET) | cmd_addr;
+	wr32(hw, NGBE_SPI_H_CMD_REG_ADDR, cmd_val);
+
+	return read_poll_timeout(rd32, val, (val & 0x1), 10, NGBE_SPI_TIME_OUT_VALUE,
+				 false, hw, NGBE_SPI_H_STA_REG_ADDR);
+}
+
+int ngbe_flash_read_dword(struct ngbe_hw *hw, u32 addr, u32 *data)
+{
+	int ret = 0;
+
+	ret = ngbe_fmgr_cmd_op(hw, NGBE_SPI_CMD_READ_DWORD, addr);
+	if (ret < 0)
+		return ret;
+	*data = rd32(hw, NGBE_SPI_H_DAT_REG_ADDR);
+
+	return 0;
+}
+
+int ngbe_check_flash_load(struct ngbe_hw *hw, u32 check_bit)
+{
+	u32 reg = 0, status = 0;
+
+	/* if there's flash existing */
+	if (!(rd32(hw, NGBE_SPI_H_STA_REG_ADDR) &
+	      NGBE_SPI_STATUS_FLASH_BYPASS)) {
+		/* wait hw load flash done */
+		status = read_poll_timeout(rd32, reg, !(reg & check_bit), 1000, 400000,
+					   false, hw, NGBE_SPI_ILDR_STATUS);
+		if (status < 0)
+			return -EBUSY;
+	}
+	return 0;
+}
+
+/**
+ *  ngbe_get_pcie_msix_counts - Gets MSI-X vector count
+ *  @hw: pointer to hardware structure
+ *  @msix_count: number of MSI interrupts that can be obtained
+ *
+ *  Read PCIe configuration space, and get the MSI-X vector count from
+ *  the capabilities table.
+ **/
+int ngbe_get_pcie_msix_counts(struct ngbe_hw *hw, u16 *msix_count)
+{
+	struct ngbe_adapter *adapter = hw->back;
+	struct pci_dev *pdev = adapter->pdev;
+	struct device *dev = &pdev->dev;
+	u16 max_msix_count;
+	int pos;
+
+	*msix_count = 1;
+	/* max_msix_count for emerald */
+	max_msix_count = NGBE_MAX_MSIX_VECTORS;
+	pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
+	if (!pos) {
+		dev_err(dev, "Unable to find MSI-X Capabilities\n");
+		return -EINVAL;
+	}
+	pci_read_config_word(pdev,
+			     pos + PCI_MSIX_FLAGS,
+			     msix_count);
+	*msix_count &= NGBE_PCIE_MSIX_TBL_SZ_MASK;
+	/* MSI-X count is zero-based in HW */
+	*msix_count += 1;
+
+	if (*msix_count > max_msix_count)
+		*msix_count = max_msix_count;
+
+	return 0;
+}
+
+static int ngbe_reset_misc(struct ngbe_hw *hw)
+{
+	int i;
+
+	/* receive packets that size > 2048 */
+	wr32m(hw, NGBE_MAC_RX_CFG, NGBE_MAC_RX_CFG_JE, NGBE_MAC_RX_CFG_JE);
+	/* clear counters on read */
+	wr32m(hw, NGBE_MMC_CONTROL,
+	      NGBE_MMC_CONTROL_RSTONRD, NGBE_MMC_CONTROL_RSTONRD);
+	wr32m(hw, NGBE_MAC_RX_FLOW_CTRL,
+	      NGBE_MAC_RX_FLOW_CTRL_RFE, NGBE_MAC_RX_FLOW_CTRL_RFE);
+	wr32(hw, NGBE_MAC_PKT_FLT, NGBE_MAC_PKT_FLT_PR);
+	wr32m(hw, NGBE_MIS_RST_ST, NGBE_MIS_RST_ST_RST_INIT, 0x1E00);
+	/* errata 4: initialize mng flex tbl and wakeup flex tbl */
+	wr32(hw, NGBE_PSR_MNG_FLEX_SEL, 0);
+	for (i = 0; i < 16; i++) {
+		wr32(hw, NGBE_PSR_MNG_FLEX_DW_L(i), 0);
+		wr32(hw, NGBE_PSR_MNG_FLEX_DW_H(i), 0);
+		wr32(hw, NGBE_PSR_MNG_FLEX_MSK(i), 0);
+	}
+	wr32(hw, NGBE_PSR_LAN_FLEX_SEL, 0);
+	for (i = 0; i < 16; i++) {
+		wr32(hw, NGBE_PSR_LAN_FLEX_DW_L(i), 0);
+		wr32(hw, NGBE_PSR_LAN_FLEX_DW_H(i), 0);
+		wr32(hw, NGBE_PSR_LAN_FLEX_MSK(i), 0);
+	}
+
+	/* set pause frame dst mac addr */
+	wr32(hw, NGBE_RDB_PFCMACDAL, 0xC2000001);
+	wr32(hw, NGBE_RDB_PFCMACDAH, 0x0180);
+	if (hw->mac.type == ngbe_mac_type_rgmii)
+		wr32(hw, NGBE_MDIO_CLAUSE_SELECT, 0xF);
+	if (hw->gpio_ctrl) {
+		/* gpio0 is used to power on/off control*/
+		wr32(hw, NGBE_GPIO_DDR, 0x1);
+		wr32(hw, NGBE_GPIO_DR, NGBE_GPIO_DR_0);
+	}
+	return 0;
+}
+
+/**
+ *  ngbe_reset_hw - Perform hardware reset
+ *  @hw: pointer to hardware structure
+ *
+ *  Resets the hardware by resetting the transmit and receive units, masks
+ *  and clears all interrupts, perform a PHY reset, and perform a link (MAC)
+ *  reset.
+ **/
+int ngbe_reset_hw(struct ngbe_hw *hw)
+{
+	u32 reset_status = 0;
+	u32 rst_delay = 0;
+	int err;
+
+	/* Issue global reset to the MAC.  Needs to be SW reset if link is up.
+	 * If link reset is used when link is up, it might reset the PHY when
+	 * mng is using it.  If link is down or the flag to force full link
+	 * reset is set, then perform link reset.
+	 */
+	if (hw->force_full_reset) {
+		rst_delay = (rd32(hw, NGBE_MIS_RST_ST) &
+			     NGBE_MIS_RST_ST_RST_INIT) >>
+			     NGBE_MIS_RST_ST_RST_INI_SHIFT;
+		if (hw->reset_type == NGBE_SW_RESET) {
+			err = read_poll_timeout(rd32, reset_status,
+						!(reset_status & NGBE_MIS_RST_ST_DEV_RST_ST_MASK),
+						1000, rst_delay + 20000,
+						false, hw,
+						NGBE_MIS_RST_ST);
+			if (!err)
+				return err;
+
+			if (reset_status & NGBE_MIS_RST_ST_DEV_RST_ST_MASK) {
+				err = -EBUSY;
+				dev_err(ngbe_hw_to_dev(hw),
+					"software reset polling failed to complete %d.\n",
+					err);
+				return err;
+			}
+			err = ngbe_check_flash_load(hw, NGBE_SPI_ILDR_STATUS_SW_RESET);
+			if (err != 0)
+				return err;
+		}
+	} else {
+		wr32(hw, NGBE_MIS_RST, 1 << (hw->bus.func + 1) |
+		     rd32(hw, NGBE_MIS_RST));
+		ngbe_flush(hw);
+		msleep(20);
+	}
+
+	err = ngbe_reset_misc(hw);
+	if (err != 0)
+		return err;
+
+	/* Store the permanent mac address */
+	ngbe_get_mac_addr(hw, hw->mac.perm_addr);
+
+	/* reset num_rar_entries to 128 */
+	hw->mac.num_rar_entries = NGBE_RAR_ENTRIES;
+	ngbe_init_rx_addrs(hw);
+	pci_set_master(((struct ngbe_adapter *)hw->back)->pdev);
+
+	return 0;
+}
+
+/**
+ *  ngbe_release_eeprom_semaphore - Release hardware semaphore
+ *  @hw: pointer to hardware structure
+ *
+ *  This function clears hardware semaphore bits.
+ **/
+static void ngbe_release_eeprom_semaphore(struct ngbe_hw *hw)
+{
+	wr32m(hw, NGBE_MIS_SWSM, NGBE_MIS_SWSM_SMBI, 0);
+	ngbe_flush(hw);
+}
+
+/**
+ *  ngbe_get_eeprom_semaphore - Get hardware semaphore
+ *  @hw: pointer to hardware structure
+ *  Sets the hardware semaphores so EEPROM access can occur for bit-bang method
+ **/
+static int ngbe_get_eeprom_semaphore(struct ngbe_hw *hw)
+{
+	int status = 0;
+	u32 times = 10;
+	u32 i;
+	u32 swsm;
+
+	/* Get SMBI software semaphore between device drivers first */
+	for (i = 0; i < times; i++) {
+		/* If the SMBI bit is 0 when we read it, then the bit will be
+		 * set and we have the semaphore
+		 */
+		status = read_poll_timeout(rd32, swsm, !(swsm & NGBE_MIS_SWSM_SMBI), 50,
+					   20000, false, hw, NGBE_MIS_SWSM);
+		if (!status)
+			return 0;
+	}
+
+	if (i == times) {
+		dev_err(ngbe_hw_to_dev(hw),
+			"Driver can't access the Eeprom - SMBI Semaphore not granted.\n");
+		/* this release is particularly important because our attempts
+		 * above to get the semaphore may have succeeded, and if there
+		 * was a timeout, we should unconditionally clear the semaphore
+		 * bits to free the driver to make progress
+		 */
+		ngbe_release_eeprom_semaphore(hw);
+		status = -EBUSY;
+	}
+	/* one last try
+	 * If the SMBI bit is 0 when we read it, then the bit will be
+	 * set and we have the semaphore
+	 */
+	swsm = rd32(hw, NGBE_MIS_SWSM);
+	if (!(swsm & NGBE_MIS_SWSM_SMBI))
+		status = 0;
+	return status;
+}
+
+/**
+ *  ngbe_acquire_swfw_sync - Acquire SWFW semaphore
+ *  @hw: pointer to hardware structure
+ *  @mask: Mask to specify which semaphore to acquire
+ *
+ *  Acquires the SWFW semaphore through the GSSR register for the specified
+ *  function (CSR, PHY0, PHY1, EEPROM, Flash)
+ **/
+static int ngbe_acquire_swfw_sync(struct ngbe_hw *hw, u32 mask)
+{
+	u32 gssr = 0;
+	u32 swmask = mask;
+	u32 fwmask = mask << 16;
+	u32 times = 2000;
+	u32 i;
+
+	for (i = 0; i < times; i++) {
+		/* SW NVM semaphore bit is used for access to all
+		 * SW_FW_SYNC bits (not just NVM)
+		 */
+		if (ngbe_get_eeprom_semaphore(hw))
+			return -EBUSY;
+
+		gssr = rd32(hw, NGBE_MNG_SWFW_SYNC);
+		if (!(gssr & (fwmask | swmask))) {
+			gssr |= swmask;
+			wr32(hw, NGBE_MNG_SWFW_SYNC, gssr);
+			ngbe_release_eeprom_semaphore(hw);
+			return 0;
+		}
+		/* Resource is currently in use by FW or SW */
+		ngbe_release_eeprom_semaphore(hw);
+	}
+
+	/* If time expired clear the bits holding the lock and retry */
+	if (gssr & (fwmask | swmask))
+		ngbe_release_swfw_sync(hw, gssr & (fwmask | swmask));
+
+	return -EBUSY;
+}
+
+/**
+ *  ngbe_release_swfw_sync - Release SWFW semaphore
+ *  @hw: pointer to hardware structure
+ *  @mask: Mask to specify which semaphore to release
+ *
+ *  Releases the SWFW semaphore through the GSSR register for the specified
+ *  function (CSR, PHY0, PHY1, EEPROM, Flash)
+ **/
+void ngbe_release_swfw_sync(struct ngbe_hw *hw, u32 mask)
+{
+	ngbe_get_eeprom_semaphore(hw);
+	wr32m(hw, NGBE_MNG_SWFW_SYNC, mask, 0);
+	ngbe_release_eeprom_semaphore(hw);
+}
+
+/**
+ *  ngbe_host_interface_command - Issue command to manageability block
+ *  @hw: pointer to the HW structure
+ *  @buffer: contains the command to write and where the return status will
+ *   be placed
+ *  @length: length of buffer, must be multiple of 4 bytes
+ *  @timeout: time in ms to wait for command completion
+ *  @return_data: read and return data from the buffer (true) or not (false)
+ *   Needed because FW structures are big endian and decoding of
+ *   these fields can be 8 bit or 16 bit based on command. Decoding
+ *   is not easily understood without making a table of commands.
+ *   So we will leave this up to the caller to read back the data
+ *   in these cases.
+ **/
+int ngbe_host_interface_command(struct ngbe_hw *hw, u32 *buffer,
+				u32 length, u32 timeout, bool return_data)
+{
+	u32 hicr, i, bi;
+	u32 hdr_size = sizeof(struct ngbe_hic_hdr);
+	u16 buf_len;
+	u32 dword_len;
+	int err = 0;
+	u32 buf[64] = {};
+
+	if (length == 0 || length > NGBE_HI_MAX_BLOCK_BYTE_LENGTH) {
+		dev_err(ngbe_hw_to_dev(hw),
+			"Buffer length failure buffersize=%d.\n", length);
+		return -EINVAL;
+	}
+
+	if (ngbe_acquire_swfw_sync(hw, NGBE_MNG_SWFW_SYNC_SW_MB) != 0)
+		return -EBUSY;
+
+	/* Calculate length in DWORDs. We must be DWORD aligned */
+	if ((length % (sizeof(u32))) != 0) {
+		dev_err(ngbe_hw_to_dev(hw),
+			"Buffer length failure, not aligned to dword");
+		err = -EINVAL;
+		goto rel_out;
+	}
+
+	/*read to clean all status*/
+	hicr = rd32(hw, NGBE_MNG_MBOX_CTL);
+	if ((hicr & NGBE_MNG_MBOX_CTL_FWRDY))
+		dev_err(ngbe_hw_to_dev(hw),
+			"fwrdy is set before command.\n");
+	dword_len = length >> 2;
+	/* The device driver writes the relevant command block
+	 * into the ram area.
+	 */
+	for (i = 0; i < dword_len; i++)
+		wr32a(hw, NGBE_MNG_MBOX, i, buffer[i]);
+
+	/* Setting this bit tells the ARC that a new command is pending. */
+	wr32m(hw, NGBE_MNG_MBOX_CTL,
+	      NGBE_MNG_MBOX_CTL_SWRDY, NGBE_MNG_MBOX_CTL_SWRDY);
+
+	for (i = 0; i < timeout; i++) {
+		err = read_poll_timeout(rd32, hicr, hicr & NGBE_MNG_MBOX_CTL_FWRDY, 1000,
+					20000, false, hw, NGBE_MNG_MBOX_CTL);
+		if (!err)
+			break;
+	}
+
+	buf[0] = rd32(hw, NGBE_MNG_MBOX);
+	/* Check command completion */
+	if (timeout != 0 && i == timeout) {
+		dev_err(ngbe_hw_to_dev(hw),
+			"Command has failed with no status valid.\n");
+		if ((buffer[0] & 0xff) != (~buf[0] >> 24)) {
+			err = -EINVAL;
+			goto rel_out;
+		}
+	}
+
+	if (!return_data)
+		goto rel_out;
+
+	/* Calculate length in DWORDs */
+	dword_len = hdr_size >> 2;
+
+	/* first pull in the header so we know the buffer length */
+	for (bi = 0; bi < dword_len; bi++)
+		buffer[bi] = rd32a(hw, NGBE_MNG_MBOX, bi);
+
+	/* If there is any thing in data position pull it in */
+	buf_len = ((struct ngbe_hic_hdr *)buffer)->buf_len;
+	if (buf_len == 0)
+		goto rel_out;
+
+	if (length < buf_len + hdr_size) {
+		dev_err(ngbe_hw_to_dev(hw),
+			"Buffer not large enough for reply message.\n");
+		err = -ENOMEM;
+		goto rel_out;
+	}
+
+	/* Calculate length in DWORDs, add 3 for odd lengths */
+	dword_len = (buf_len + 3) >> 2;
+
+	/* Pull in the rest of the buffer (bi is where we left off) */
+	for (; bi <= dword_len; bi++)
+		buffer[bi] = rd32a(hw, NGBE_MNG_MBOX, bi);
+
+rel_out:
+	ngbe_release_swfw_sync(hw, NGBE_MNG_SWFW_SYNC_SW_MB);
+	return err;
+}
+
+/**
+ *  ngbe_init_eeprom_params - Initialize EEPROM params
+ *  @hw: pointer to hardware structure
+ *
+ *  Initializes the EEPROM parameters ngbe_eeprom_info within the
+ *  ngbe_hw struct in order to set up EEPROM access.
+ **/
+void ngbe_init_eeprom_params(struct ngbe_hw *hw)
+{
+	struct ngbe_eeprom_info *eeprom = &hw->eeprom;
+
+	eeprom->semaphore_delay = 10;
+	eeprom->word_size = 1024 >> 1;
+	eeprom->sw_region_offset = 0x80;
+}
+
+int ngbe_eeprom_chksum_hostif(struct ngbe_hw *hw)
+{
+	int tmp;
+	int status;
+	struct ngbe_hic_read_shadow_ram buffer;
+
+	buffer.hdr.req.cmd = NGBE_FW_EEPROM_CHECKSUM_CMD;
+	buffer.hdr.req.buf_lenh = 0;
+	buffer.hdr.req.buf_lenl = 0;
+	buffer.hdr.req.checksum = NGBE_FW_CMD_DEFAULT_CHECKSUM;
+	/* convert offset from words to bytes */
+	buffer.address = 0;
+	/* one word */
+	buffer.length = 0;
+
+	status = ngbe_host_interface_command(hw, (u32 *)&buffer,
+					     sizeof(buffer),
+					     NGBE_HI_COMMAND_TIMEOUT, false);
+
+	if (status < 0)
+		return status;
+	tmp = (u32)rd32a(hw, NGBE_MNG_MBOX, 1);
+	if (tmp == 0x80658383)
+		status = 0;
+	else
+		return -EIO;
+
+	return status;
+}
+
+static int ngbe_read_ee_hostif_data32(struct ngbe_hw *hw, u16 offset, u32 *data)
+{
+	int status;
+	struct ngbe_hic_read_shadow_ram buffer;
+
+	buffer.hdr.req.cmd = NGBE_FW_READ_SHADOW_RAM_CMD;
+	buffer.hdr.req.buf_lenh = 0;
+	buffer.hdr.req.buf_lenl = NGBE_FW_READ_SHADOW_RAM_LEN;
+	buffer.hdr.req.checksum = NGBE_FW_CMD_DEFAULT_CHECKSUM;
+	/* convert offset from words to bytes */
+	buffer.address = (__force u32)cpu_to_be32(offset * 2);
+	/* one word */
+	buffer.length = (__force u16)cpu_to_be16(sizeof(u32));
+
+	status = ngbe_host_interface_command(hw, (u32 *)&buffer,
+					     sizeof(buffer),
+					     NGBE_HI_COMMAND_TIMEOUT, false);
+	if (status)
+		return status;
+	*data = (u32)rd32a(hw, NGBE_MNG_MBOX, NGBE_FW_NVM_DATA_OFFSET);
+
+	return 0;
+}
+
+/**
+ *  ngbe_read_ee_hostif32 - Read EEPROM word using a host interface cmd
+ *  @hw: pointer to hardware structure
+ *  @offset: offset of  word in the EEPROM to read
+ *  @data: dword read from the EEPROM
+ *
+ *  Reads a dword from the EEPROM using the hostif.
+ **/
+int ngbe_read_ee_hostif32(struct ngbe_hw *hw, u16 offset, u32 *data)
+{
+	int status = 0;
+
+	if (ngbe_acquire_swfw_sync(hw, NGBE_MNG_SWFW_SYNC_SW_FLASH) < 0)
+		return -EBUSY;
+	status = ngbe_read_ee_hostif_data32(hw, offset, data);
+	ngbe_release_swfw_sync(hw, NGBE_MNG_SWFW_SYNC_SW_FLASH);
+
+	return status;
+}
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_hw.h b/drivers/net/ethernet/wangxun/ngbe/ngbe_hw.h
new file mode 100644
index 000000000000..abfe1e6ab779
--- /dev/null
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_hw.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * WangXun Gigabit PCI Express Linux driver
+ * Copyright (c) 2019 - 2022 Beijing WangXun Technology Co., Ltd.
+ */
+
+#ifndef _NGBE_HW_H_
+#define _NGBE_HW_H_
+
+u32 rd32m(struct ngbe_hw *hw, u32 reg, u32 mask);
+void wr32m(struct ngbe_hw *hw, u32 reg, u32 mask, u32 field);
+struct device *ngbe_hw_to_dev(struct ngbe_hw *hw);
+int ngbe_flash_read_dword(struct ngbe_hw *hw, u32 addr, u32 *data);
+int ngbe_check_flash_load(struct ngbe_hw *hw, u32 check_bit);
+/* eeprom ops */
+void ngbe_init_eeprom_params(struct ngbe_hw *hw);
+int ngbe_eeprom_chksum_hostif(struct ngbe_hw *hw);
+int ngbe_read_ee_hostif32(struct ngbe_hw *hw, u16 offset, u32 *data);
+/* flash ops */
+int ngbe_get_pcie_msix_counts(struct ngbe_hw *hw, u16 *msix_count);
+/* mac ops */
+void ngbe_release_swfw_sync(struct ngbe_hw *hw, u32 mask);
+int ngbe_host_interface_command(struct ngbe_hw *hw, u32 *buffer,
+				u32 length, u32 timeout, bool return_data);
+int ngbe_reset_hw(struct ngbe_hw *hw);
+#endif /* _NGBE_HW_H_ */
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
index 7674cb6e5700..d8dd58bed48a 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
@@ -10,6 +10,7 @@
 #include <linux/etherdevice.h>
 
 #include "ngbe.h"
+#include "ngbe_hw.h"
 char ngbe_driver_name[] = "ngbe";
 
 /* ngbe_pci_tbl - PCI Device ID Table
@@ -56,6 +57,166 @@ static void ngbe_shutdown(struct pci_dev *pdev)
 	}
 }
 
+/**
+ *  ngbe_init_type_code - Initialize the shared code
+ *  @hw: pointer to hardware structure
+ **/
+static void ngbe_init_type_code(struct ngbe_hw *hw)
+{
+	u8 wol_mask = 0, ncsi_mask = 0;
+	u16 type_mask = 0;
+
+	type_mask = (u16)(hw->subsystem_device_id & NGBE_OEM_MASK);
+	ncsi_mask = (u8)(hw->subsystem_device_id & NGBE_NCSI_MASK);
+	wol_mask = (u8)(hw->subsystem_device_id & NGBE_WOL_MASK);
+
+	switch (type_mask) {
+	case NGBE_SUBID_M88E1512_SFP:
+	case NGBE_SUBID_LY_M88E1512_SFP:
+		hw->phy.type = ngbe_phy_m88e1512_sfi;
+		break;
+	case NGBE_SUBID_M88E1512_RJ45:
+		hw->phy.type = ngbe_phy_m88e1512;
+		break;
+	case NGBE_SUBID_M88E1512_MIX:
+		hw->phy.type = ngbe_phy_m88e1512_unknown;
+		break;
+	case NGBE_SUBID_YT8521S_SFP:
+	case NGBE_SUBID_YT8521S_SFP_GPIO:
+	case NGBE_SUBID_LY_YT8521S_SFP:
+		hw->phy.type = ngbe_phy_yt8521s_sfi;
+		break;
+	case NGBE_SUBID_INTERNAL_YT8521S_SFP:
+	case NGBE_SUBID_INTERNAL_YT8521S_SFP_GPIO:
+		hw->phy.type = ngbe_phy_internal_yt8521s_sfi;
+		break;
+	case NGBE_SUBID_RGMII_FPGA:
+	case NGBE_SUBID_OCP_CARD:
+		fallthrough;
+	default:
+		hw->phy.type = ngbe_phy_internal;
+		break;
+	}
+
+	if (hw->phy.type == ngbe_phy_internal ||
+	    hw->phy.type == ngbe_phy_internal_yt8521s_sfi)
+		hw->mac.type = ngbe_mac_type_mdi;
+	else
+		hw->mac.type = ngbe_mac_type_rgmii;
+
+	hw->wol_enabled = (wol_mask == NGBE_WOL_SUP) ? 1 : 0;
+	hw->ncsi_enabled = (ncsi_mask == NGBE_NCSI_MASK ||
+			   type_mask == NGBE_SUBID_OCP_CARD) ? 1 : 0;
+
+	switch (type_mask) {
+	case NGBE_SUBID_LY_YT8521S_SFP:
+	case NGBE_SUBID_LY_M88E1512_SFP:
+	case NGBE_SUBID_YT8521S_SFP_GPIO:
+	case NGBE_SUBID_INTERNAL_YT8521S_SFP_GPIO:
+		hw->gpio_ctrl = 1;
+		break;
+	default:
+		hw->gpio_ctrl = 0;
+		break;
+	}
+}
+
+/**
+ * ngbe_init_rss_key - Initialize adapter RSS key
+ * @adapter: device handle
+ *
+ * Allocates and initializes the RSS key if it is not allocated.
+ **/
+static inline int ngbe_init_rss_key(struct ngbe_adapter *adapter)
+{
+	u32 *rss_key;
+
+	if (!adapter->rss_key) {
+		rss_key = kzalloc(NGBE_RSS_KEY_SIZE, GFP_KERNEL);
+		if (unlikely(!rss_key))
+			return -ENOMEM;
+
+		netdev_rss_key_fill(rss_key, NGBE_RSS_KEY_SIZE);
+		adapter->rss_key = rss_key;
+	}
+
+	return 0;
+}
+
+/**
+ * ngbe_sw_init - Initialize general software structures
+ * @adapter: board private structure to initialize
+ **/
+static int ngbe_sw_init(struct ngbe_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	struct ngbe_hw *hw = &adapter->hw;
+	struct device *dev = &pdev->dev;
+	u16 msix_count = 0;
+	u32 ssid = 0;
+	int err = 0;
+
+	/* PCI config space info */
+	hw->vendor_id = pdev->vendor;
+	hw->device_id = pdev->device;
+	hw->revision_id = pdev->revision;
+	hw->bus.device = PCI_SLOT(pdev->devfn);
+	hw->bus.func = PCI_FUNC(pdev->devfn);
+
+	hw->oem_svid = pdev->subsystem_vendor;
+	hw->oem_ssid = pdev->subsystem_device;
+	if (pdev->subsystem_vendor == PCI_SUB_VID_WANGXUN) {
+		hw->subsystem_vendor_id = pdev->subsystem_vendor;
+		hw->subsystem_device_id = pdev->subsystem_device;
+	} else {
+		err = ngbe_flash_read_dword(hw, 0xfffdc, &ssid);
+		if (err < 0) {
+			dev_err(dev, "Read internal subdid err %d\n", err);
+			return err;
+		}
+		hw->subsystem_device_id = swab16((u16)ssid);
+	}
+
+	/* mac type, phy type , oem type */
+	ngbe_init_type_code(hw);
+
+	hw->mac.max_rx_queues = NGBE_MAX_RX_QUEUES;
+	hw->mac.max_tx_queues = NGBE_MAX_TX_QUEUES;
+	hw->mac.num_rar_entries = NGBE_RAR_ENTRIES;
+	/* Set common capability flags and settings */
+	adapter->max_q_vectors = NGBE_MAX_MSIX_VECTORS;
+
+	err = ngbe_get_pcie_msix_counts(hw, &msix_count);
+	if (err)
+		dev_err(dev, "Do not support MSI-X\n");
+	hw->mac.max_msix_vectors = msix_count;
+
+	adapter->mac_table = kcalloc(hw->mac.num_rar_entries,
+				     sizeof(struct ngbe_mac_addr),
+				     GFP_KERNEL);
+	if (!adapter->mac_table) {
+		dev_err(dev, "mac_table allocation failed: %d\n", err);
+		return -ENOMEM;
+	}
+
+	if (ngbe_init_rss_key(adapter))
+		return -ENOMEM;
+
+	/* enable itr by default in dynamic mode */
+	adapter->rx_itr_setting = 1;
+	adapter->tx_itr_setting = 1;
+
+	/* set default ring sizes */
+	adapter->tx_ring_count = NGBE_DEFAULT_TXD;
+	adapter->rx_ring_count = NGBE_DEFAULT_RXD;
+
+	/* set default work limits */
+	adapter->tx_work_limit = NGBE_DEFAULT_TX_WORK;
+	adapter->rx_work_limit = NGBE_DEFAULT_RX_WORK;
+
+	return 0;
+}
+
 /**
  * ngbe_probe - Device Initialization Routine
  * @pdev: PCI device information struct
@@ -72,6 +233,12 @@ static int ngbe_probe(struct pci_dev *pdev,
 {
 	struct ngbe_adapter *adapter = NULL;
 	struct net_device *netdev;
+	struct ngbe_hw *hw = NULL;
+	u32 e2rom_cksum_cap = 0;
+	static int cards_found;
+	u32 e2rom_verl = 0;
+	u32 etrack_id = 0;
+	u32 saved_ver = 0;
 	int err;
 
 	err = pci_enable_device_mem(pdev);
@@ -111,6 +278,8 @@ static int ngbe_probe(struct pci_dev *pdev,
 	adapter = netdev_priv(netdev);
 	adapter->netdev = netdev;
 	adapter->pdev = pdev;
+	hw = &adapter->hw;
+	hw->back = adapter;
 
 	adapter->io_addr = devm_ioremap(&pdev->dev,
 					pci_resource_start(pdev, 0),
@@ -120,12 +289,93 @@ static int ngbe_probe(struct pci_dev *pdev,
 		goto err_pci_release_regions;
 	}
 
+	hw->hw_addr = adapter->io_addr;
+
 	netdev->features |= NETIF_F_HIGHDMA;
 
+	strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
+	adapter->bd_number = cards_found;
+
+	/* setup the private structure */
+	err = ngbe_sw_init(adapter);
+	if (err)
+		goto err_free_mac_table;
+
+	/* check if flash load is done after hw power up */
+	err = ngbe_check_flash_load(hw, NGBE_SPI_ILDR_STATUS_PERST);
+	if (err)
+		goto err_sw_init;
+	err = ngbe_check_flash_load(hw, NGBE_SPI_ILDR_STATUS_PWRRST);
+	if (err)
+		goto err_sw_init;
+
+	/* reset_hw fills in the perm_addr as well */
+	hw->phy.reset_if_overtemp = true;
+	err = ngbe_reset_hw(hw);
+	hw->phy.reset_if_overtemp = false;
+	if (err) {
+		dev_err(&pdev->dev, "HW reset failed: %d\n", err);
+		goto err_sw_init;
+	}
+
+	if (hw->bus.func == 0) {
+		wr32(hw, NGBE_CALSUM_CAP_STATUS, 0x0);
+		wr32(hw, NGBE_EEPROM_VERSION_STORE_REG, 0x0);
+	} else {
+		e2rom_cksum_cap = rd32(hw, NGBE_CALSUM_CAP_STATUS);
+		saved_ver = rd32(hw, NGBE_EEPROM_VERSION_STORE_REG);
+	}
+
+	ngbe_init_eeprom_params(hw);
+	if (hw->bus.func == 0 || e2rom_cksum_cap == 0) {
+		/* make sure the EEPROM is ready */
+		err = ngbe_eeprom_chksum_hostif(hw);
+		if (err) {
+			dev_err(&pdev->dev, "The EEPROM Checksum Is Not Valid\n");
+			err = -EIO;
+			goto err_sw_init;
+		}
+	}
+
+	adapter->wol = 0;
+	if (hw->wol_enabled)
+		adapter->wol = NGBE_PSR_WKUP_CTL_MAG;
+
+	hw->wol_enabled = !!(adapter->wol);
+	wr32(hw, NGBE_PSR_WKUP_CTL, adapter->wol);
+
+	device_set_wakeup_enable(&pdev->dev, adapter->wol);
+
+	/* Save off EEPROM version number and Option Rom version which
+	 * together make a unique identify for the eeprom
+	 */
+
+	if (saved_ver) {
+		etrack_id = saved_ver;
+	} else {
+		ngbe_read_ee_hostif32(hw,
+				      hw->eeprom.sw_region_offset + NGBE_EEPROM_VERSION_L,
+				      &e2rom_verl);
+		etrack_id = e2rom_verl;
+		wr32(hw, NGBE_EEPROM_VERSION_STORE_REG, etrack_id);
+	}
+	snprintf(adapter->eeprom_id, sizeof(adapter->eeprom_id), "0x%08x", etrack_id);
+
+	eth_hw_addr_set(netdev, hw->mac.perm_addr);
+
+	if (!is_valid_ether_addr(netdev->dev_addr)) {
+		dev_err(&pdev->dev, "invalid MAC address\n");
+		err = -EIO;
+		goto err_sw_init;
+	}
+
 	pci_set_drvdata(pdev, adapter);
 
 	return 0;
 
+err_sw_init:
+err_free_mac_table:
+	kfree(adapter->mac_table);
 err_pci_release_regions:
 	pci_disable_pcie_error_reporting(pdev);
 	pci_release_selected_regions(pdev,
@@ -146,6 +396,9 @@ static int ngbe_probe(struct pci_dev *pdev,
  **/
 static void ngbe_remove(struct pci_dev *pdev)
 {
+	struct ngbe_adapter *adapter = pci_get_drvdata(pdev);
+
+	kfree(adapter->mac_table);
 	pci_release_selected_regions(pdev,
 				     pci_select_bars(pdev, IORESOURCE_MEM));
 
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_osdep.h b/drivers/net/ethernet/wangxun/ngbe/ngbe_osdep.h
new file mode 100644
index 000000000000..aa8a3c5211cd
--- /dev/null
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_osdep.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * WangXun Gigabit PCI Express Linux driver
+ * Copyright (c) 2019 - 2022 Beijing WangXun Technology Co., Ltd.
+ */
+
+#ifndef _NGBE_OSDEP_H_
+#define _NGBE_OSDEP_H_
+
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/if_ether.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/ctype.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+#include <linux/etherdevice.h>
+
+#define wr32(a, reg, value)	writel((value), ((a)->hw_addr + (reg)))
+#define rd32(a, reg)		readl((a)->hw_addr + (reg))
+#define wr64(a, reg, value)	writeq((value), ((a)->hw_addr + (reg)))
+#define rd64(a, reg)		readq((a)->hw_addr + (reg))
+
+#define wr32a(a, reg, off, val)	wr32((a), (reg) + ((off) << 2), (val))
+#define rd32a(a, reg, offset)	rd32((a), (reg) + ((offset) << 2))
+#define ngbe_flush(a)		rd32((a), 0x10000)
+
+#endif /* _NGBE_OSDEP_H_ */
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
index 26e776c3539a..2c9d70f8c2bb 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
@@ -4,9 +4,6 @@
 #ifndef _NGBE_TYPE_H_
 #define _NGBE_TYPE_H_
 
-#include <linux/types.h>
-#include <linux/netdevice.h>
-
 /************ NGBE_register.h ************/
 /* Vendor ID */
 #ifndef PCI_VENDOR_ID_WANGXUN
@@ -27,6 +24,9 @@
 #define NGBE_DEV_ID_EM_WX1860A1			0x010a
 #define NGBE_DEV_ID_EM_WX1860A1L		0x010b
 
+/* Subsystem Vendor ID*/
+#define PCI_SUB_VID_WANGXUN			0x8088
+
 /* Subsystem ID */
 #define NGBE_SUBID_M88E1512_SFP			0x0003
 #define NGBE_SUBID_OCP_CARD			0x0040
@@ -47,4 +47,430 @@
 #define NGBE_WOL_SUP				0x4000
 #define NGBE_WOL_MASK				0x4000
 
+#define NGBE_ETH_LENGTH_OF_ADDRESS		6
+#define NGBE_MAX_MSIX_VECTORS			0x09
+#define NGBE_RAR_ENTRIES			32
+/* MSI-X capability fields masks */
+#define NGBE_PCIE_MSIX_TBL_SZ_MASK		0x7FF
+#define NGBE_PCI_LINK_STATUS			0xB2
+
+/* Media-dependent registers. */
+#define NGBE_MDIO_PHY_ID_HIGH			0x2 /* PHY ID High Reg*/
+#define NGBE_MDIO_PHY_ID_LOW			0x3 /* PHY ID Low Reg*/
+#define NGBE_MDIO_CLAUSE_SELECT			0x11220
+
+/**************** Global Registers ****************************/
+/* chip control Registers */
+#define NGBE_MIS_RST				0x1000C
+#define NGBE_MIS_PWR				0x10000
+#define NGBE_MIS_CTL				0x10004
+#define NGBE_MIS_PF_SM				0x10008
+#define NGBE_MIS_PRB_CTL			0x10010
+#define NGBE_MIS_ST				0x10028
+#define NGBE_MIS_SWSM				0x1002C
+#define NGBE_MIS_RST_ST				0x10030
+
+/* chip control bit and mask */
+#define NGBE_MIS_RST_SW_RST			BIT(0)
+#define NGBE_MIS_RST_LAN0_RST			BIT(1)
+#define NGBE_MIS_RST_LAN1_RST			BIT(2)
+#define NGBE_MIS_RST_LAN2_RST			BIT(3)
+#define NGBE_MIS_RST_LAN3_RST			BIT(4)
+#define NGBE_MIS_RST_FW_RST			BIT(5)
+
+#define NGBE_MIS_ST_MNG_INIT_DN			BIT(0)
+#define NGBE_MIS_ST_MNG_VETO			BIT(8)
+#define NGBE_MIS_ST_LAN0_ECC			BIT(16)
+#define NGBE_MIS_ST_LAN1_ECC			BIT(17)
+#define NGBE_MIS_ST_LAN2_ECC			BIT(18)
+#define NGBE_MIS_ST_LAN3_ECC			BIT(19)
+#define NGBE_MIS_ST_MNG_ECC			BIT(20)
+#define NGBE_MIS_ST_PCORE_ECC			BIT(21)
+#define NGBE_MIS_ST_PCIWRP_ECC			BIT(22)
+#define NGBE_MIS_ST_PCIEPHY_ECC			BIT(23)
+#define NGBE_MIS_ST_FMGR_ECC			BIT(24)
+#define NGBE_MIS_ST_GPHY_IN_RST(_r)		(BIT(9) << (_r))
+
+#define NGBE_MIS_SWSM_SMBI			BIT(0)
+#define NGBE_MIS_RST_ST_DEV_RST_ST_MASK		0x00180000U
+#define NGBE_MIS_RST_ST_RST_INIT		0x0000FF00U
+#define NGBE_MIS_RST_ST_RST_INI_SHIFT		8
+#define NGBE_MIS_RST_ST_RST_TIM			0x000000FFU
+#define NGBE_MIS_PF_SM_SM			BIT(0)
+#define NGBE_MIS_PRB_CTL_LAN0_UP		BIT(3)
+#define NGBE_MIS_PRB_CTL_LAN1_UP		BIT(2)
+#define NGBE_MIS_PRB_CTL_LAN2_UP		BIT(1)
+#define NGBE_MIS_PRB_CTL_LAN3_UP		BIT(0)
+
+#define NGBE_SPI_CLK_DIV			3
+#define NGBE_SPI_CMD_READ_DWORD			1  /* SPI read a dword cmd */
+#define NGBE_SPI_CLK_CMD_OFFSET			28  /* SPI cmd field off in cmd reg */
+#define NGBE_SPI_CLK_DIV_OFFSET			25  /* SPI clk div field off in cmd reg */
+#define NGBE_SPI_STATUS_FLASH_BYPASS		BIT(31)
+#define NGBE_SPI_TIME_OUT_VALUE			10000
+#define NGBE_SPI_H_CMD_REG_ADDR			0x10104  /* SPI cmd register address */
+#define NGBE_SPI_H_DAT_REG_ADDR			0x10108  /* SPI Data register address */
+#define NGBE_SPI_H_STA_REG_ADDR			0x1010c  /* SPI Status register address */
+#define NGBE_SPI_H_USR_CMD_REG_ADDR		0x10110  /* SPI User cmd register address */
+#define NGBE_SPI_CMD_CFG1_ADDR			0x10118  /* Flash cmd cfg register 1 */
+#define NGBE_MISC_RST_REG_ADDR			0x1000c  /* Misc reset register address */
+
+/* Checksum and EEPROM pointers */
+#define NGBE_CALSUM_COMMAND			0xE9
+#define NGBE_CALSUM_CAP_STATUS			0x10224
+#define NGBE_EEPROM_VERSION_STORE_REG		0x1022C
+#define NGBE_SAN_MAC_ADDR_PTR			0x18
+#define NGBE_DEVICE_CAPS			0x1C
+#define NGBE_EEPROM_VERSION_L			0x1D
+#define NGBE_EEPROM_VERSION_H			0x1E
+
+/* GPIO Registers */
+#define NGBE_GPIO_DR				0x14800
+#define NGBE_GPIO_DDR				0x14804
+#define NGBE_GPIO_CTL				0x14808
+#define NGBE_GPIO_INTEN				0x14830
+#define NGBE_GPIO_INTMASK			0x14834
+#define NGBE_GPIO_INTTYPE_LEVEL			0x14838
+#define NGBE_GPIO_POLARITY			0x1483C
+#define NGBE_GPIO_INTSTATUS			0x14840
+#define NGBE_GPIO_EOI				0x1484C
+/*GPIO bit */
+#define NGBE_GPIO_DR_0				BIT(0) /* SDP0 Data Value */
+#define NGBE_GPIO_DR_1				BIT(1) /* SDP1 Data Value */
+#define NGBE_GPIO_DDR_0				BIT(0) /* SDP0 IO direction */
+#define NGBE_GPIO_DDR_1				BIT(1) /* SDP1 IO direction */
+
+/* Wake up registers */
+#define NGBE_PSR_WKUP_CTL			0x15B80
+/* Wake Up Filter Control Bit */
+#define NGBE_PSR_WKUP_CTL_LNKC			BIT(0) /* Link Status Change Wakeup Enable*/
+#define NGBE_PSR_WKUP_CTL_MAG			BIT(1) /* Magic Packet Wakeup Enable */
+#define NGBE_PSR_WKUP_CTL_EX			BIT(2) /* Directed Exact Wakeup Enable */
+#define NGBE_PSR_WKUP_CTL_MC			BIT(3) /* Directed Multicast Wakeup Enable*/
+#define NGBE_PSR_WKUP_CTL_BC			BIT(4) /* Broadcast Wakeup Enable */
+#define NGBE_PSR_WKUP_CTL_ARP			BIT(5) /* ARP Request Packet Wakeup Enable*/
+#define NGBE_PSR_WKUP_CTL_IPV4			BIT(6) /* Directed IPv4 Pkt Wakeup Enable */
+#define NGBE_PSR_WKUP_CTL_IPV6			BIT(7) /* Directed IPv6 Pkt Wakeup Enable */
+
+/* FMGR Registers */
+#define NGBE_SPI_ILDR_STATUS			0x10120
+#define NGBE_SPI_ILDR_STATUS_PERST		BIT(0) /* PCIE_PERST is done */
+#define NGBE_SPI_ILDR_STATUS_PWRRST		BIT(1) /* Power on reset done */
+#define NGBE_SPI_ILDR_STATUS_SW_RESET		BIT(11) /* software reset done */
+
+/******************************* PSR Registers *******************************/
+/* psr control */
+#define NGBE_PSR_CTL				0x15000
+#define NGBE_PSR_VLAN_CTL			0x15088
+#define NGBE_PSR_VM_CTL				0x151B0
+#define NGBE_PSR_PKT_CNT			0x151B8
+#define NGBE_PSR_MNG_PKT_CNT			0x151BC
+#define NGBE_PSR_DBG_DOP_CNT			0x151C0
+#define NGBE_PSR_MNG_DOP_CNT			0x151C4
+#define NGBE_PSR_VM_FLP_L			0x151C8
+
+/* Header split receive */
+#define NGBE_PSR_CTL_SW_EN			BIT(18)
+#define NGBE_PSR_CTL_PCSD			BIT(13)
+#define NGBE_PSR_CTL_IPPCSE			BIT(12)
+#define NGBE_PSR_CTL_BAM			BIT(10)
+#define NGBE_PSR_CTL_UPE			BIT(9)
+#define NGBE_PSR_CTL_MPE			BIT(8)
+#define NGBE_PSR_CTL_MFE			BIT(7)
+#define NGBE_PSR_CTL_MO				0x00000060U
+#define NGBE_PSR_CTL_TPE			BIT(4)
+#define NGBE_PSR_CTL_MO_SHIFT			5
+
+/* mcasst/ucast overflow tbl */
+#define NGBE_PSR_MC_TBL(_i)			(0x15200  + ((_i) * 4))
+#define NGBE_PSR_UC_TBL(_i)			(0x15400 + ((_i) * 4))
+
+/* vlan tbl */
+#define NGBE_PSR_VLAN_TBL(_i)			(0x16000 + ((_i) * 4))
+
+/************************************** MNG ********************************/
+#define NGBE_MNG_FW_SM				0x1E000
+#define NGBE_MNG_SWFW_SYNC			0x1E008
+#define NGBE_MNG_MBOX				0x1E100
+#define NGBE_MNG_MBOX_CTL			0x1E044
+
+/* SW_FW_SYNC definitions */
+#define NGBE_MNG_SWFW_SYNC_SW_PHY		BIT(0)
+#define NGBE_MNG_SWFW_SYNC_SW_FLASH		BIT(3)
+#define NGBE_MNG_SWFW_SYNC_SW_MB		BIT(2)
+
+#define NGBE_MNG_MBOX_CTL_SWRDY			BIT(0)
+#define NGBE_MNG_MBOX_CTL_SWACK			BIT(1)
+#define NGBE_MNG_MBOX_CTL_FWRDY			BIT(2)
+#define NGBE_MNG_MBOX_CTL_FWACK			BIT(3)
+
+/************************************* ETH MAC *****************************/
+#define NGBE_MAC_TX_CFG				0x11000
+#define NGBE_MAC_RX_CFG				0x11004
+#define NGBE_MAC_PKT_FLT			0x11008
+#define NGBE_MAC_PKT_FLT_PR			BIT(0) /* promiscuous mode */
+#define NGBE_MAC_PKT_FLT_RA			BIT(31) /* receive all */
+#define NGBE_MAC_WDG_TIMEOUT			0x1100C
+#define NGBE_MAC_TX_FLOW_CTRL			0x11070
+#define NGBE_MAC_RX_FLOW_CTRL			0x11090
+#define NGBE_MAC_INT_ST				0x110B0
+#define NGBE_MAC_INT_EN				0x110B4
+#define NGBE_MAC_ADDRESS0_HIGH			0x11300
+#define NGBE_MAC_ADDRESS0_LOW			0x11304
+
+#define NGBE_MAC_TX_CFG_TE			BIT(0)
+#define NGBE_MAC_RX_CFG_RE			BIT(0)
+#define NGBE_MAC_RX_CFG_JE			BIT(8)
+#define NGBE_MAC_RX_CFG_LM			BIT(10)
+#define NGBE_MAC_WDG_TIMEOUT_PWE		BIT(8)
+
+#define NGBE_MAC_RX_FLOW_CTRL_RFE		BIT(0) /* receive fc enable */
+
+/* statistic */
+#define NGBE_MAC_LXOFFRXC			0x11988
+#define NGBE_MAC_PXOFFRXC			0x119DC
+#define NGBE_RX_BC_FRAMES_GOOD_LOW		0x11918
+#define NGBE_RX_CRC_ERROR_FRAMES_LOW		0x11928
+#define NGBE_RX_LEN_ERROR_FRAMES_LOW		0x11978
+#define NGBE_RX_UNDERSIZE_FRAMES_GOOD		0x11938
+#define NGBE_RX_OVERSIZE_FRAMES_GOOD		0x1193C
+#define NGBE_RX_FRAME_CNT_GOOD_BAD_LOW		0x11900
+#define NGBE_TX_FRAME_CNT_GOOD_BAD_LOW		0x1181C
+#define NGBE_TX_MC_FRAMES_GOOD_LOW		0x1182C
+#define NGBE_TX_BC_FRAMES_GOOD_LOW		0x11824
+#define NGBE_MMC_CONTROL			0x11800
+#define NGBE_MMC_CONTROL_RSTONRD		BIT(2) /* reset on read */
+
+/* Manangbeent */
+#define NGBE_PSR_MNG_FIT_CTL			0x15820
+/* Manangbeent Bit Fields and Masks */
+#define NGBE_PSR_MNG_FIT_CTL_MPROXYE		BIT(30) /* Manangbeent Proxy Enable*/
+#define NGBE_PSR_MNG_FIT_CTL_RCV_TCO_EN		BIT(17) /* Rcv TCO packet enable */
+#define NGBE_PSR_MNG_FIT_CTL_EN_BMC2OS		BIT(28) /* Ena BMC2OS and OS2BMC traffic */
+#define NGBE_PSR_MNG_FIT_CTL_EN_BMC2OS_SHIFT	28
+
+#define NGBE_PSR_MNG_FLEX_SEL			0x1582C
+#define NGBE_PSR_MNG_FLEX_DW_L(_i)		(0x15A00  +  ((_i) * 16)) /* [0,15] */
+#define NGBE_PSR_MNG_FLEX_DW_H(_i)		(0x15A04  +  ((_i) * 16))
+#define NGBE_PSR_MNG_FLEX_MSK(_i)		(0x15A08  +  ((_i) * 16))
+
+/* Wake up registers */
+#define NGBE_PSR_WKUP_CTL			0x15B80
+#define NGBE_PSR_WKUP_IPV			0x15B84
+#define NGBE_PSR_LAN_FLEX_SEL			0x15B8C
+#define NGBE_PSR_WKUP_IP4TBL(_i)		(0x15BC0  +  ((_i) * 4)) /* [0,3] */
+#define NGBE_PSR_WKUP_IP6TBL(_i)		(0x15BE0  +  ((_i) * 4))
+#define NGBE_PSR_LAN_FLEX_DW_L(_i)		(0x15C00  +  ((_i) * 16)) /* [0,15] */
+#define NGBE_PSR_LAN_FLEX_DW_H(_i)		(0x15C04  +  ((_i) * 16))
+#define NGBE_PSR_LAN_FLEX_MSK(_i)		(0x15C08  +  ((_i) * 16))
+#define NGBE_PSR_LAN_FLEX_CTL			0x15CFC
+
+/* mac switcher */
+#define NGBE_PSR_MAC_SWC_AD_L			0x16200
+#define NGBE_PSR_MAC_SWC_AD_H			0x16204
+#define NGBE_PSR_MAC_SWC_VM			0x16208
+#define NGBE_PSR_MAC_SWC_IDX			0x16210
+/* RAH */
+#define NGBE_PSR_MAC_SWC_AD_H_AD(v)		(((v) & 0xFFFF))
+#define NGBE_PSR_MAC_SWC_AD_H_ADTYPE(v)		(((v) & 0x1) << 30)
+#define NGBE_PSR_MAC_SWC_AD_H_AV		BIT(31)
+#define NGBE_CLEAR_VMDQ_ALL			0xFFFFFFFFU
+
+/* statistic */
+#define NGBE_RDB_MPCNT				0x19040
+#define NGBE_RDB_PKT_CNT			0x19060
+#define NGBE_RDB_REPLI_CNT			0x19064
+#define NGBE_RDB_DRP_CNT			0x19068
+#define NGBE_RDB_LXONTXC			0x1921C
+#define NGBE_RDB_LXOFFTXC			0x19218
+#define NGBE_RDB_PFCMACDAL			0x19210
+#define NGBE_RDB_PFCMACDAH			0x19214
+#define NGBE_RDB_TXSWERR			0x1906C
+#define NGBE_RDB_TXSWERR_TB_FREE		0x3FF
+
+/****************** Manageablility Host Interface defines ********************/
+#define NGBE_HI_MAX_BLOCK_BYTE_LENGTH		256 /* Num of bytes in range */
+#define NGBE_HI_COMMAND_TIMEOUT			200 /* Process HI command limit */
+#define NGBE_HI_FLASH_ERASE_TIMEOUT		200 /* Process Erase command limit */
+#define NGBE_HI_FLASH_UPDATE_TIMEOUT		200 /* Process Update command limit */
+
+/* CEM Support */
+#define NGBE_FW_READ_SHADOW_RAM_CMD		0x31
+#define NGBE_FW_READ_SHADOW_RAM_LEN		0x6
+#define NGBE_FW_WRITE_SHADOW_RAM_CMD		0x33
+#define NGBE_FW_WRITE_SHADOW_RAM_LEN		0xA /* 8 plus 1 WORD to write */
+#define NGBE_FW_EEPROM_CHECKSUM_CMD		0xE9
+#define NGBE_FW_NVM_DATA_OFFSET			3
+#define NGBE_FW_CMD_DEFAULT_CHECKSUM		0xFF /* checksum always 0xFF */
+
+/* Host Interface Command Structures */
+struct ngbe_hic_hdr {
+	u8 cmd;
+	u8 buf_len;
+	union {
+		u8 cmd_resv;
+		u8 ret_status;
+	} cmd_or_resp;
+	u8 checksum;
+};
+
+struct ngbe_hic_hdr2_req {
+	u8 cmd;
+	u8 buf_lenh;
+	u8 buf_lenl;
+	u8 checksum;
+};
+
+struct ngbe_hic_hdr2_rsp {
+	u8 cmd;
+	u8 buf_lenl;
+	u8 buf_lenh_status;     /* 7-5: high bits of buf_len, 4-0: status */
+	u8 checksum;
+};
+
+union ngbe_hic_hdr2 {
+	struct ngbe_hic_hdr2_req req;
+	struct ngbe_hic_hdr2_rsp rsp;
+};
+
+/* These need to be dword aligned */
+struct ngbe_hic_read_shadow_ram {
+	union ngbe_hic_hdr2 hdr;
+	u32 address;
+	u16 length;
+	u16 pad2;
+	u16 data;
+	u16 pad3;
+};
+
+struct ngbe_hic_write_shadow_ram {
+	union ngbe_hic_hdr2 hdr;
+	u32 address;
+	u16 length;
+	u16 pad2;
+	u16 data;
+	u16 pad3;
+};
+
+enum ngbe_reset_type {
+	NGBE_LAN_RESET = 0,
+	NGBE_SW_RESET,
+	NGBE_GLOBAL_RESET
+};
+
+enum ngbe_phy_type {
+	ngbe_phy_unknown = 0,
+	ngbe_phy_none,
+	ngbe_phy_internal,
+	ngbe_phy_m88e1512,
+	ngbe_phy_m88e1512_sfi,
+	ngbe_phy_m88e1512_unknown,
+	ngbe_phy_yt8521s,
+	ngbe_phy_yt8521s_sfi,
+	ngbe_phy_internal_yt8521s_sfi,
+	ngbe_phy_generic
+};
+
+enum ngbe_media_type {
+	ngbe_media_type_unknown = 0,
+	ngbe_media_type_fiber,
+	ngbe_media_type_copper,
+	ngbe_media_type_backplane,
+	ngbe_media_type_virtual
+};
+
+enum ngbe_mac_type {
+	ngbe_mac_type_unknown = 0,
+	ngbe_mac_type_mdi,
+	ngbe_mac_type_rgmii
+};
+
+struct ngbe_hw;
+
+/* Function pointer table */
+struct ngbe_phy_operations {
+};
+
+struct ngbe_addr_filter_info {
+	u32 num_mc_addrs;
+	u32 rar_used_count;
+	u32 mta_in_use;
+	u32 overflow_promisc;
+	bool user_set_promisc;
+};
+
+/* Bus parameters */
+struct ngbe_bus_info {
+	u8 func;
+	u16 device;
+};
+
+struct ngbe_flash_info {
+	u32 semaphore_delay;
+	u32 dword_size;
+	u16 address_bits;
+};
+
+struct ngbe_eeprom_info {
+	u32 semaphore_delay;
+	u16 word_size;
+	u16 sw_region_offset;
+};
+
+struct ngbe_phy_info {
+	enum ngbe_phy_type type;
+	enum ngbe_media_type media_type;
+
+	u32 addr;
+	u32 id;
+
+	bool reset_if_overtemp;
+
+};
+
+struct ngbe_mac_info {
+	u8 addr[NGBE_ETH_LENGTH_OF_ADDRESS];
+	u8 perm_addr[NGBE_ETH_LENGTH_OF_ADDRESS];
+	u8 san_addr[NGBE_ETH_LENGTH_OF_ADDRESS];
+
+	enum ngbe_mac_type type;
+	u32 max_tx_queues;
+	u32 max_rx_queues;
+	u16 max_msix_vectors;
+	u32 num_rar_entries;
+
+	s32 mc_filter_type;
+	u32 mcft_size;
+};
+
+struct ngbe_hw {
+	u8 __iomem *hw_addr;
+	void *back;
+
+	struct ngbe_addr_filter_info addr_ctrl;
+
+	struct ngbe_bus_info bus;
+	struct ngbe_flash_info flash;
+	struct ngbe_eeprom_info eeprom;
+
+	struct ngbe_mac_info mac;
+	struct ngbe_phy_info phy;
+
+	u16 device_id;
+	u16 vendor_id;
+	u16 subsystem_device_id;
+	u16 subsystem_vendor_id;
+	u16 oem_ssid;
+	u16 oem_svid;
+	u8 revision_id;
+
+	bool wol_enabled;
+	bool ncsi_enabled;
+	bool gpio_ctrl;
+
+	/* for reset */
+	enum ngbe_reset_type reset_type;
+	bool force_full_reset;
+
+};
 #endif /* _NGBE_TYPE_H_ */
-- 
2.37.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ