[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20220905125224.2279-1-mengyuanlou@net-swift.com>
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