summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNoe Rubinstein <nrubinstein@avencall.com>2012-04-13 11:18:12 +0200
committerNoe Rubinstein <nrubinstein@avencall.com>2012-04-24 17:53:30 +0200
commitbfa58b09a14ea766003244a07758ff4c22d4eca3 (patch)
tree553a16bff22996ef728ac10a2ecc5d2409d8f8e9
parentce946f1a84773ca4e1fa92d4ac5cae3d91cfa44f (diff)
e1000: add support for Intel EP80579
This has been written for Avencall's XiVO IPBX Open Hardware platform, and therefore makes several asumptions relative to this platform in order to simplify the code. Making it more general will require some work. Here are some of the areas that are not as generic as they could be: * In e1000_ep80579.c, the media_type is set unconditionally: hw->phy.media_type = e1000_media_type_copper; * The MAC address are set randomly, as the current prototype does not have the mechanism that will be used to store MAC addresses yet. (We don't have an EEPROM for storing the MAC addresses like other e1000 products do. We plan to use a microcontroller that will communicate via SMBus instead) * ops.get_link_up_info is always e1000_get_speed_and_duplex_copper_generic * PHY is assumed to be Marvell M881141 * Autonegociation is assumed
-rw-r--r--src/drivers/net/e1000/e1000_api.c17
-rw-r--r--src/drivers/net/e1000/e1000_api.h1
-rw-r--r--src/drivers/net/e1000/e1000_defines.h7
-rw-r--r--src/drivers/net/e1000/e1000_ep80579.c604
-rw-r--r--src/drivers/net/e1000/e1000_hw.h22
-rw-r--r--src/drivers/net/e1000/e1000_main.c5
-rw-r--r--src/drivers/net/e1000/e1000_osdep.h8
-rw-r--r--src/drivers/net/e1000/e1000_phy.c17
8 files changed, 676 insertions, 5 deletions
diff --git a/src/drivers/net/e1000/e1000_api.c b/src/drivers/net/e1000/e1000_api.c
index 232dc3ec..4694112a 100644
--- a/src/drivers/net/e1000/e1000_api.c
+++ b/src/drivers/net/e1000/e1000_api.c
@@ -185,6 +185,20 @@ s32 e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_82547GI:
mac->type = e1000_82547_rev_2;
break;
+ case E1000_DEV_ID_EP80579_MAC0:
+ case E1000_DEV_ID_EP80579_QA_MAC0:
+ case E1000_DEV_ID_EP80579_RESERVED0_MAC0:
+ case E1000_DEV_ID_EP80579_RESERVED1_MAC0:
+ case E1000_DEV_ID_EP80579_MAC1:
+ case E1000_DEV_ID_EP80579_QA_MAC1:
+ case E1000_DEV_ID_EP80579_RESERVED0_MAC1:
+ case E1000_DEV_ID_EP80579_RESERVED1_MAC1:
+ case E1000_DEV_ID_EP80579_MAC2:
+ case E1000_DEV_ID_EP80579_QA_MAC2:
+ case E1000_DEV_ID_EP80579_RESERVED0_MAC2:
+ case E1000_DEV_ID_EP80579_RESERVED1_MAC2:
+ mac->type = e1000_ep80579;
+ break;
default:
/* Should never have loaded on this device */
ret_val = -E1000_ERR_MAC_INIT;
@@ -257,6 +271,9 @@ s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device)
case e1000_82547_rev_2:
e1000_init_function_pointers_82541(hw);
break;
+ case e1000_ep80579:
+ e1000_init_function_pointers_ep80579(hw);
+ break;
default:
DBG("Hardware not supported\n");
ret_val = -E1000_ERR_CONFIG;
diff --git a/src/drivers/net/e1000/e1000_api.h b/src/drivers/net/e1000/e1000_api.h
index fc1e533d..e1bb2132 100644
--- a/src/drivers/net/e1000/e1000_api.h
+++ b/src/drivers/net/e1000/e1000_api.h
@@ -52,6 +52,7 @@ extern void e1000_init_function_pointers_82542(struct e1000_hw *hw) __attribu
extern void e1000_init_function_pointers_82543(struct e1000_hw *hw) __attribute__((weak));
extern void e1000_init_function_pointers_82540(struct e1000_hw *hw) __attribute__((weak));
extern void e1000_init_function_pointers_82541(struct e1000_hw *hw) __attribute__((weak));
+extern void e1000_init_function_pointers_ep80579(struct e1000_hw *hw) __attribute__((weak));
s32 e1000_set_mac_type(struct e1000_hw *hw);
s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device);
diff --git a/src/drivers/net/e1000/e1000_defines.h b/src/drivers/net/e1000/e1000_defines.h
index 06e4c86c..98efa376 100644
--- a/src/drivers/net/e1000/e1000_defines.h
+++ b/src/drivers/net/e1000/e1000_defines.h
@@ -1200,6 +1200,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
* E = External
*/
#define M88E1000_E_PHY_ID 0x01410C50
+#define M88E1141_E_PHY_ID 0x01410cd0
#define M88E1000_I_PHY_ID 0x01410C30
#define M88E1011_I_PHY_ID 0x01410C20
#define IGP01E1000_I_PHY_ID 0x02A80380
@@ -1224,7 +1225,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define M88E1000_PHY_PAGE_SELECT 0x1D /* Reg 29 for page number setting */
#define M88E1000_PHY_GEN_CONTROL 0x1E /* Its meaning depends on reg 29 */
#define M88E1000_PHY_VCO_REG_BIT8 0x100 /* Bits 8 & 11 are adjusted for */
-#define M88E1000_PHY_VCO_REG_BIT11 0x800 /* improved BER performance */
+#define M88E1000_PHY_VCO_REG_BIT11 0x800 /* improved BER performance */
/* M88E1000 PHY Specific Control Register */
#define M88E1000_PSCR_JABBER_DISABLE 0x0001 /* 1=Jabber Function disabled */
@@ -1316,6 +1317,10 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_7X 0x0C00
#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_8X 0x0E00
+/* RGMII TX and RX Timing Control*/
+#define M88E1000_EPSCR_TX_TIME_CTRL 0x0002 /* Add Delay */
+#define M88E1000_EPSCR_RX_TIME_CTRL 0x0080 /* Add Delay */
+
/*
* Bits...
* 15-5: page
diff --git a/src/drivers/net/e1000/e1000_ep80579.c b/src/drivers/net/e1000/e1000_ep80579.c
new file mode 100644
index 00000000..c9a56f2b
--- /dev/null
+++ b/src/drivers/net/e1000/e1000_ep80579.c
@@ -0,0 +1,604 @@
+/*******************************************************************************
+
+ Intel PRO/1000 Linux driver
+ Copyright(c) 1999 - 2008 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Contact Information:
+ Linux NICS <linux.nics@intel.com>
+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include "e1000_api.h"
+#include "gcu/gcu_if.h"
+#include "e1000_defines.h"
+
+static s32 e1000_init_phy_params_ep80579(struct e1000_hw *hw);
+static s32 e1000_init_nvm_params_ep80579(struct e1000_hw *hw);
+static s32 e1000_init_mac_params_ep80579(struct e1000_hw *hw);
+
+static s32 e1000_reset_hw_ep80579(struct e1000_hw *hw);
+static s32 e1000_phy_read_reg_ep80579(struct e1000_hw *hw, u32 reg_addr,
+ u16 *phy_data);
+static s32 e1000_phy_write_reg_ep80579(struct e1000_hw *hw, u32 reg_addr,
+ u16 phy_data);
+static s32 e1000_init_hw_ep80579(struct e1000_hw *hw);
+static s32 e1000_setup_copper_link_ep80579(struct e1000_hw *hw);
+static void e1000_clear_hw_cntrs_ep80579(struct e1000_hw *hw);
+static s32 e1000_config_mac_to_phy_ep80579(struct e1000_hw *hw);
+s32 e1000_xioh_read_mac_addr(struct e1000_hw *hw);
+s32 e1000_phy_has_link_ep80579(struct e1000_hw *hw, bool *isUp);
+static s32 e1000_phy_hw_reset_ep80579(struct e1000_hw *hw);
+
+/**
+ * e1000_init_phy_params_ep80579 - Init PHY func ptrs.
+ * @hw: pointer to the HW structure
+ **/
+static s32 e1000_init_phy_params_ep80579(struct e1000_hw *hw)
+{
+ struct e1000_phy_info *phy = &hw->phy;
+ int err;
+
+ DBGF;
+
+
+ err = e1000_get_phy_id(hw);
+ if (err < 0)
+ return err;
+
+ switch (phy->id) {
+ case M88E1141_E_PHY_ID:
+ DBG("PHY OK\n");
+ break;
+ default:
+ DBG("PHY not supported for EP80579! id: 0x%08x rev: 0x%08x\n",
+ phy->id, phy->revision);
+ return -E1000_ERR_PHY;
+ }
+
+ phy->ops.read_reg = e1000_phy_read_reg_ep80579;
+ phy->ops.write_reg = e1000_phy_write_reg_ep80579;
+ phy->ops.get_info = e1000_get_phy_info_m88;
+ phy->ops.reset = e1000_phy_hw_reset_ep80579;
+ phy->ops.get_cfg_done = e1000_get_cfg_done_generic;
+ phy->ops.commit = e1000_phy_sw_reset_generic;
+
+ phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+ phy->type = e1000_phy_m88;
+
+ return E1000_SUCCESS;
+}
+
+static s32 e1000_phy_read_reg_ep80579(struct e1000_hw *hw, u32 reg_addr,
+ u16 *phy_data)
+{
+ int err = gcu_read_eth_phy(hw->dev_spec.ep80579.device_number, reg_addr,
+ phy_data);
+#ifdef DEBUG_REGS
+ DBG("%s reg: 0x%08X data: 0x%04X\n", __func__, reg_addr, *phy_data);
+#endif
+ return err;
+}
+
+static s32 e1000_phy_write_reg_ep80579(struct e1000_hw *hw, u32 reg_addr,
+ u16 phy_data)
+{
+#ifdef DEBUG_REGS
+ DBG("%s reg: 0x%08X data: 0x%04X\n", __func__, reg_addr, phy_data);
+#endif
+ return gcu_write_eth_phy(hw->dev_spec.ep80579.device_number, reg_addr,
+ phy_data);
+}
+
+/**
+ * e1000_init_nvm_params_ep80579 - Init NVM func ptrs.
+ * @hw: pointer to the HW structure
+ **/
+static s32 e1000_init_nvm_params_ep80579(struct e1000_hw *hw)
+{
+ (void) hw;
+ DBGF;
+ return E1000_SUCCESS;
+}
+
+/**
+ * e1000_init_mac_params_ep80579 - Init MAC func ptrs.
+ * @hw: pointer to the HW structure
+ **/
+static s32 e1000_init_mac_params_ep80579(struct e1000_hw *hw)
+{
+ static const u8 device_number[] = {
+ [E1000_DEV_ID_EP80579_MAC0] = 0,
+ [E1000_DEV_ID_EP80579_QA_MAC0] = 0,
+ [E1000_DEV_ID_EP80579_RESERVED0_MAC0] = 0,
+ [E1000_DEV_ID_EP80579_RESERVED1_MAC0] = 0,
+ [E1000_DEV_ID_EP80579_MAC1] = 1,
+ [E1000_DEV_ID_EP80579_QA_MAC1] = 1,
+ [E1000_DEV_ID_EP80579_RESERVED0_MAC1] = 1,
+ [E1000_DEV_ID_EP80579_RESERVED1_MAC1] = 1,
+ [E1000_DEV_ID_EP80579_MAC2] = 2,
+ [E1000_DEV_ID_EP80579_QA_MAC2] = 2,
+ [E1000_DEV_ID_EP80579_RESERVED0_MAC2] = 2,
+ [E1000_DEV_ID_EP80579_RESERVED1_MAC2] = 2,
+ };
+
+ struct e1000_mac_info *mac = &hw->mac;
+ DBGF;
+
+ hw->dev_spec.ep80579.device_number = device_number[hw->device_id];
+
+ mac->mta_reg_count = 128;
+
+ mac->ops.reset_hw = e1000_reset_hw_ep80579;
+ mac->ops.read_mac_addr = e1000_xioh_read_mac_addr;
+ mac->ops.init_hw = e1000_init_hw_ep80579;
+ mac->ops.setup_link = e1000_setup_link_generic;
+ mac->ops.get_link_up_info = e1000_get_speed_and_duplex_copper_generic;
+ mac->ops.setup_physical_interface = e1000_setup_copper_link_ep80579;
+ mac->ops.clear_vfta = e1000_clear_vfta_generic;
+ mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_ep80579;
+
+ return E1000_SUCCESS;
+}
+
+static s32 e1000_init_hw_ep80579(struct e1000_hw *hw)
+{
+ struct e1000_mac_info *mac = &hw->mac;
+ u32 txdctl;
+ s32 err;
+ int i;
+
+ DBGF;
+
+ hw->phy.media_type = e1000_media_type_copper;
+
+ mac->rar_entry_count = E1000_RAR_ENTRIES;
+
+ SILENT
+ mac->ops.clear_vfta(hw);
+
+ e1000_init_rx_addrs_generic(hw, mac->rar_entry_count);
+
+ SILENT {
+ /* Zero out the Multicast HASH table */
+ DBG("Zeroing the MTA\n");
+ for (i = 0; i < mac->mta_reg_count; i++) {
+ E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
+ E1000_WRITE_FLUSH(hw);
+ }
+ DBG("Zeroing the Flexible Filter tables\n");
+ for (i = 0; i < E1000_FFMT_SIZE; i++) {
+ E1000_WRITE_REG_ARRAY(hw, E1000_FFMT, i, 0);
+ E1000_WRITE_FLUSH(hw);
+ }
+ for (i = 0; i < E1000_FFVT_SIZE; i++) {
+ E1000_WRITE_REG_ARRAY(hw, E1000_FFVT, i, 0);
+ E1000_WRITE_FLUSH(hw);
+ }
+ }
+
+ err = e1000_setup_link(hw);
+ if (err < 0) {
+ DBG("Couldn't setup link\n");
+ return err;
+ }
+
+ /* Set the transmit descriptor write-back policy */
+ txdctl = E1000_READ_REG(hw, E1000_TXDCTL(0));
+ txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |
+ E1000_TXDCTL_FULL_TX_DESC_WB;
+ E1000_WRITE_REG(hw, E1000_TXDCTL(0), txdctl);
+
+ /* Clear all of the statistics registers (clear on read). It is
+ * important that we do this after we have tried to establish link
+ * because the symbol error count will increment wildly if there
+ * is no link.
+ */
+ e1000_clear_hw_cntrs_ep80579(hw);
+
+ return E1000_SUCCESS;
+}
+
+static s32 e1000_phy_hw_reset_ep80579(struct e1000_hw *hw)
+{
+ u16 reg;
+ int ret_val;
+
+ ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &reg);
+ if (ret_val)
+ goto out;
+
+ reg |= MII_CR_RESET;
+
+ ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, reg);
+ if (ret_val)
+ goto out;
+
+ udelay(1);
+
+out:
+ return ret_val;
+}
+
+#if 0
+static s32 e1000_phy_loopback_setup_m88_autoneg(struct e1000_hw *hw)
+{
+ u16 reg;
+ int ret_val;
+
+ ret_val = hw->phy.ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &reg);
+ if (ret_val)
+ goto out;
+
+ reg |= 5 << 4; //M88E1000_EPSCR_TX_CLK_25;
+
+ ret_val = hw->phy.ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, reg);
+ if (ret_val)
+ goto out;
+
+
+ ret_val = hw->phy.ops.commit(hw);
+ if (ret_val)
+ goto out;
+
+ ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &reg);
+ if (ret_val)
+ goto out;
+
+ reg |= PHY_CONTROL_LB;
+
+ ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, reg);
+ if (ret_val)
+ goto out;
+
+out:
+ return ret_val;
+}
+
+static s32 e1000_phy_loopback_setup_m88_force(struct e1000_hw *hw)
+{
+ u32 ctrl;
+ int ret_val;
+
+ ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, 0xa100);
+ if (ret_val)
+ goto out;
+
+ ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, 0x6100);
+ if (ret_val)
+ goto out;
+
+ ctrl = E1000_READ_REG(hw, E1000_CTRL);
+ ctrl &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */
+ ctrl |= (E1000_CTRL_FRCSPD /* Set the Force Speed Bit */
+ | E1000_CTRL_FRCDPX /* Set the Force Duplex Bit */
+ | E1000_CTRL_SPD_100 /* Force Speed to 1000 */
+ | E1000_CTRL_FD); /* Force Duplex to FULL */
+ /* | E1000_CTRL_ILOS); *//* Invert Loss of Signal */
+
+ E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+
+out:
+ return ret_val;
+}
+#endif
+
+static s32 e1000_setup_copper_link_ep80579(struct e1000_hw *hw)
+{
+ u32 ctrl;
+ s32 ret_val;
+ bool link;
+
+ DBGF;
+
+ ctrl = E1000_READ_REG(hw, E1000_CTRL) | E1000_CTRL_SLU |
+ E1000_CTRL_FRCSPD |
+ E1000_CTRL_FRCDPX;
+ E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+ ret_val = hw->phy.ops.reset(hw);
+ if (ret_val)
+ goto out;
+
+ hw->phy.reset_disable = false;
+
+ /* Set MDI/MDI-X, Polarity Reversal, and downshift settings */
+ ret_val = e1000_copper_link_setup_m88(hw);
+ if (ret_val)
+ goto out;
+
+ ret_val = e1000_copper_link_autoneg(hw);
+ if (ret_val)
+ goto out;
+
+ ret_val = e1000_phy_has_link_ep80579(hw, &link);
+ if (ret_val)
+ goto out;
+
+ if (!link) {
+ DBG("Unable to establish link!!!\n");
+ goto out;
+ }
+
+ DBG("Valid link established!!!\n");
+
+ /* Config the MAC and PHY after link is up */
+ ret_val = e1000_config_mac_to_phy_ep80579(hw);
+ if (ret_val)
+ goto out;
+
+ ret_val = e1000_config_fc_after_link_up_generic(hw);
+ if (ret_val)
+ goto out;
+
+out:
+ return ret_val;
+}
+
+static s32 e1000_config_mac_to_phy_ep80579(struct e1000_hw *hw)
+{
+ u32 ctrl;
+ s32 ret_val = E1000_SUCCESS;
+ u16 phy_data;
+
+ DBGF;
+
+ /* Set the bits to force speed and duplex */
+ ctrl = E1000_READ_REG(hw, E1000_CTRL);
+ ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
+ ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS);
+
+ /*
+ * Set up duplex in the Device Control and Transmit Control
+ * registers depending on negotiated values.
+ */
+ ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
+ if (ret_val)
+ goto out;
+
+ ctrl &= ~E1000_CTRL_FD;
+ if (phy_data & M88E1000_PSSR_DPLX)
+ ctrl |= E1000_CTRL_FD;
+
+ e1000_config_collision_dist_generic(hw);
+
+ /*
+ * Set up speed in the Device Control register depending on
+ * negotiated values.
+ */
+ if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS)
+ ctrl |= E1000_CTRL_SPD_1000;
+ else if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS)
+ ctrl |= E1000_CTRL_SPD_100;
+
+ E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+
+out:
+ return ret_val;
+}
+
+s32 e1000_phy_has_link_ep80579(struct e1000_hw *hw, bool *isUp)
+{
+ struct e1000_phy_info *phy = &hw->phy;
+ u16 phy_data;
+ s32 ret_val;
+
+ DBGF;
+
+ /* WHY is this read TWICE? */
+ phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
+ ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
+
+ if (ret_val)
+ return ret_val;
+
+ *isUp = !!(phy_data & M88E1000_PSSR_LINK);
+
+ return E1000_SUCCESS;
+}
+
+static void e1000_display_frame_cnt_ep80579(struct e1000_hw *hw)
+{
+ u16 phy_data;
+ static int prev_frame_cnt;
+ static int prev_crc_cnt;
+ int curr_frame_cnt, curr_crc_cnt;
+ DBGP("%s\n", __func__);
+
+ hw->phy.ops.read_reg(hw, M88E1000_PHY_PAGE_SELECT, &phy_data);
+ phy_data &= ~0x1f;
+ phy_data |= 12;
+ hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, phy_data);
+
+ hw->phy.ops.read_reg(hw, 30, &phy_data);
+ curr_frame_cnt = phy_data >> 8;
+ curr_crc_cnt = phy_data & 0xff;
+
+ if (curr_frame_cnt != prev_frame_cnt) {
+ dbg_printf("Frame count: %d\n", curr_frame_cnt);
+ prev_frame_cnt = curr_frame_cnt;
+ }
+
+ if (curr_crc_cnt != prev_crc_cnt) {
+ dbg_printf("CRC error count: %d\n", curr_crc_cnt);
+ prev_crc_cnt = curr_crc_cnt;
+ }
+}
+
+/**
+ * e1000_clear_hw_cntrs_ep80579 - Clears all hardware statistics counters.
+ */
+static void e1000_clear_hw_cntrs_ep80579(struct e1000_hw *hw)
+{
+ DBGP("%s\n", __func__);
+
+ e1000_display_frame_cnt_ep80579(hw);
+
+ E1000_DUMP_CNTR(hw, E1000_CRCERRS);
+ E1000_DUMP_CNTR(hw, E1000_SYMERRS);
+ E1000_DUMP_CNTR(hw, E1000_MPC);
+ E1000_DUMP_CNTR(hw, E1000_SCC);
+ E1000_DUMP_CNTR(hw, E1000_ECOL);
+ E1000_DUMP_CNTR(hw, E1000_MCC);
+ E1000_DUMP_CNTR(hw, E1000_LATECOL);
+ E1000_DUMP_CNTR(hw, E1000_COLC);
+ E1000_DUMP_CNTR(hw, E1000_DC);
+ E1000_DUMP_CNTR(hw, E1000_SEC);
+ E1000_DUMP_CNTR(hw, E1000_RLEC);
+ E1000_DUMP_CNTR(hw, E1000_XONRXC);
+ E1000_DUMP_CNTR(hw, E1000_XONTXC);
+ E1000_DUMP_CNTR(hw, E1000_XOFFRXC);
+ E1000_DUMP_CNTR(hw, E1000_XOFFTXC);
+ E1000_DUMP_CNTR(hw, E1000_FCRUC);
+
+ E1000_DUMP_CNTR(hw, E1000_PRC64);
+ E1000_DUMP_CNTR(hw, E1000_PRC127);
+ E1000_DUMP_CNTR(hw, E1000_PRC255);
+ E1000_DUMP_CNTR(hw, E1000_PRC511);
+ E1000_DUMP_CNTR(hw, E1000_PRC1023);
+ E1000_DUMP_CNTR(hw, E1000_PRC1522);
+
+ E1000_DUMP_CNTR(hw, E1000_GPRC);
+ E1000_DUMP_CNTR(hw, E1000_BPRC);
+ E1000_DUMP_CNTR(hw, E1000_MPRC);
+ E1000_DUMP_CNTR(hw, E1000_GPTC);
+ E1000_DUMP_CNTR(hw, E1000_GORCL);
+ E1000_DUMP_CNTR(hw, E1000_GORCH);
+ E1000_DUMP_CNTR(hw, E1000_GOTCL);
+ E1000_DUMP_CNTR(hw, E1000_GOTCH);
+ E1000_DUMP_CNTR(hw, E1000_RNBC);
+ E1000_DUMP_CNTR(hw, E1000_RUC);
+ E1000_DUMP_CNTR(hw, E1000_RFC);
+ E1000_DUMP_CNTR(hw, E1000_ROC);
+ E1000_DUMP_CNTR(hw, E1000_RJC);
+ E1000_DUMP_CNTR(hw, E1000_TORL);
+ E1000_DUMP_CNTR(hw, E1000_TORH);
+ E1000_DUMP_CNTR(hw, E1000_TOTL);
+ E1000_DUMP_CNTR(hw, E1000_TOTH);
+ E1000_DUMP_CNTR(hw, E1000_TPR);
+ E1000_DUMP_CNTR(hw, E1000_TPT);
+
+ E1000_DUMP_CNTR(hw, E1000_PTC64);
+ E1000_DUMP_CNTR(hw, E1000_PTC127);
+ E1000_DUMP_CNTR(hw, E1000_PTC255);
+ E1000_DUMP_CNTR(hw, E1000_PTC511);
+ E1000_DUMP_CNTR(hw, E1000_PTC1023);
+ E1000_DUMP_CNTR(hw, E1000_PTC1522);
+
+ E1000_DUMP_CNTR(hw, E1000_MPTC);
+ E1000_DUMP_CNTR(hw, E1000_BPTC);
+
+ E1000_DUMP_CNTR(hw, E1000_ALGNERRC);
+ E1000_DUMP_CNTR(hw, E1000_RXERRC);
+ E1000_DUMP_CNTR(hw, E1000_TNCRS);
+ E1000_DUMP_CNTR(hw, E1000_CEXTERR);
+ E1000_DUMP_CNTR(hw, E1000_TSCTC);
+ E1000_DUMP_CNTR(hw, E1000_TSCTFC);
+}
+
+s32 e1000_xioh_read_mac_addr(struct e1000_hw *hw)
+{
+ int i;
+
+ DBGF;
+
+ hw->mac.perm_addr[0] = 0x08;
+ hw->mac.perm_addr[1] = 0xd2;
+ hw->mac.perm_addr[2] = 0x9a;
+ hw->mac.perm_addr[3] = random() % 0x100;
+ hw->mac.perm_addr[4] = random() % 0x100;
+ hw->mac.perm_addr[5] = hw->dev_spec.ep80579.device_number + 1;
+
+ for (i = 0; i < ETH_ALEN; i++)
+ hw->mac.addr[i] = hw->mac.perm_addr[i];
+
+ return E1000_SUCCESS;
+}
+
+/**
+ * e1000_init_function_pointers_ep80579 - Init func ptrs.
+ * @hw: pointer to the HW structure
+ *
+ * Called to initialize all function pointers and parameters.
+ **/
+void e1000_init_function_pointers_ep80579(struct e1000_hw *hw)
+{
+ DBGF;
+
+ hw->mac.ops.init_params = e1000_init_mac_params_ep80579;
+ hw->nvm.ops.init_params = e1000_init_nvm_params_ep80579;
+ hw->phy.ops.init_params = e1000_init_phy_params_ep80579;
+}
+
+static s32 e1000_reset_hw_ep80579(struct e1000_hw *hw)
+{
+ s32 ret_val = E1000_SUCCESS;
+ u32 ctrl;
+
+ DBGF;
+
+ DBG("Masking off all interrupts\n");
+ E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
+
+ E1000_WRITE_REG(hw, E1000_RCTL, 0);
+ E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
+ E1000_WRITE_FLUSH(hw);
+
+ /*
+ * Delay to allow any outstanding PCI transactions to complete before
+ * resetting the device
+ */
+ mdelay(10);
+
+ ctrl = E1000_READ_REG(hw, E1000_CTRL);
+
+ DBG("Issuing a soft reset to GbE MAC.\n");
+
+ E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
+ mdelay(6); /* As datasheet says */
+
+ E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
+ E1000_READ_REG(hw, E1000_ICR);
+
+ return ret_val;
+}
+
+static struct pci_device_id e1000_ep80579_nics[] = {
+ PCI_ROM(0x8086, 0x5040, "EP80579_MAC0", "Intel EP80579 Integrated Processor Gigabit Ethernet MAC 0", e1000_ep80579),
+ PCI_ROM(0x8086, 0x5041, "EP80579_QA_MAC0", "Intel EP80579 Integrated Processor with QuickAssist Gigabit Ethernet MAC 0", e1000_ep80579),
+ PCI_ROM(0x8086, 0x5042, "EP80579_RESERVED0_MAC0", "Intel EP80579 Integrated Processor (reserved) Gigabit Ethernet MAC 0", e1000_ep80579),
+ PCI_ROM(0x8086, 0x5043, "EP80579_RESERVED1_MAC0", "Intel EP80579 Integrated Processor (reserved) Gigabit Ethernet MAC 0", e1000_ep80579),
+ PCI_ROM(0x8086, 0x5044, "EP80579_MAC1", "Intel EP80579 Integrated Processor Gigabit Ethernet MAC 1", e1000_ep80579),
+ PCI_ROM(0x8086, 0x5045, "EP80579_QA_MAC1", "Intel EP80579 Integrated Processor with QuickAssist Gigabit Ethernet MAC 1", e1000_ep80579),
+ PCI_ROM(0x8086, 0x5046, "EP80579_RESERVED0_MAC1", "Intel EP80579 Integrated Processor (reserved) Gigabit Ethernet MAC 1", e1000_ep80579),
+ PCI_ROM(0x8086, 0x5047, "EP80579_RESERVED1_MAC1", "Intel EP80579 Integrated Processor (reserved) Gigabit Ethernet MAC 1", e1000_ep80579),
+ PCI_ROM(0x8086, 0x5048, "EP80579_MAC2", "Intel EP80579 Integrated Processor Gigabit Ethernet MAC 2", e1000_ep80579),
+ PCI_ROM(0x8086, 0x5049, "EP80579_QA_MAC2", "Intel EP80579 Integrated Processor with QuickAssist Gigabit Ethernet MAC 2", e1000_ep80579),
+ PCI_ROM(0x8086, 0x504A, "EP80579_RESERVED0_MAC2", "Intel EP80579 Integrated Processor (reserved) Gigabit Ethernet MAC 2", e1000_ep80579),
+ PCI_ROM(0x8086, 0x504B, "EP80579_RESERVED1_MAC2", "Intel EP80579 Integrated Processor (reserved) Gigabit Ethernet MAC 2", e1000_ep80579),
+};
+
+struct pci_driver e1000_ep80579_driver __pci_driver = {
+ .ids = e1000_ep80579_nics,
+ .id_count = (sizeof (e1000_ep80579_nics) / sizeof (e1000_ep80579_nics[0])),
+ .probe = e1000_probe,
+ .remove = e1000_remove,
+};
diff --git a/src/drivers/net/e1000/e1000_hw.h b/src/drivers/net/e1000/e1000_hw.h
index 64a80fae..a63dcd38 100644
--- a/src/drivers/net/e1000/e1000_hw.h
+++ b/src/drivers/net/e1000/e1000_hw.h
@@ -73,6 +73,22 @@ struct e1000_hw;
#define E1000_DEV_ID_82547EI 0x1019
#define E1000_DEV_ID_82547EI_MOBILE 0x101A
#define E1000_DEV_ID_82547GI 0x1075
+
+#define E1000_DEV_ID_EP80579_MAC0 0x5040
+#define E1000_DEV_ID_EP80579_QA_MAC0 0x5041
+#define E1000_DEV_ID_EP80579_RESERVED0_MAC0 0x5042
+#define E1000_DEV_ID_EP80579_RESERVED1_MAC0 0x5043
+#define E1000_DEV_ID_EP80579_MAC1 0x5044
+#define E1000_DEV_ID_EP80579_QA_MAC1 0x5045
+#define E1000_DEV_ID_EP80579_RESERVED0_MAC1 0x5046
+#define E1000_DEV_ID_EP80579_RESERVED1_MAC1 0x5047
+#define E1000_DEV_ID_EP80579_MAC2 0x5048
+#define E1000_DEV_ID_EP80579_QA_MAC2 0x5049
+#define E1000_DEV_ID_EP80579_RESERVED0_MAC2 0x504A
+#define E1000_DEV_ID_EP80579_RESERVED1_MAC2 0x504B
+
+
+
#define E1000_REVISION_0 0
#define E1000_REVISION_1 1
#define E1000_REVISION_2 2
@@ -99,6 +115,7 @@ enum e1000_mac_type {
e1000_82541_rev_2,
e1000_82547,
e1000_82547_rev_2,
+ e1000_ep80579,
e1000_num_macs /* List is 1-based, so subtract 1 for true count. */
};
@@ -687,6 +704,10 @@ struct e1000_dev_spec_82543 {
bool init_phy_disabled;
};
+struct e1000_dev_spec_ep80579 {
+ u8 device_number;
+};
+
struct e1000_hw {
void *back;
@@ -705,6 +726,7 @@ struct e1000_hw {
struct e1000_dev_spec_82541 _82541;
struct e1000_dev_spec_82542 _82542;
struct e1000_dev_spec_82543 _82543;
+ struct e1000_dev_spec_ep80579 ep80579;
} dev_spec;
u16 device_id;
diff --git a/src/drivers/net/e1000/e1000_main.c b/src/drivers/net/e1000/e1000_main.c
index c2355256..a50795d4 100644
--- a/src/drivers/net/e1000/e1000_main.c
+++ b/src/drivers/net/e1000/e1000_main.c
@@ -521,6 +521,9 @@ void e1000_reset ( struct e1000_adapter *adapter )
case e1000_82547_rev_2:
pba = E1000_PBA_30K;
break;
+ case e1000_ep80579:
+ pba = E1000_PBA_48K;
+ break;
case e1000_undefined:
case e1000_num_macs:
break;
@@ -646,6 +649,8 @@ static void e1000_poll ( struct net_device *netdev )
DBGP ( "e1000_poll\n" );
+ //hw->mac.ops.clear_hw_cntrs(hw);
+
/* Acknowledge interrupts */
icr = E1000_READ_REG ( hw, E1000_ICR );
if ( ! icr )
diff --git a/src/drivers/net/e1000/e1000_osdep.h b/src/drivers/net/e1000/e1000_osdep.h
index fd301032..c42de6aa 100644
--- a/src/drivers/net/e1000/e1000_osdep.h
+++ b/src/drivers/net/e1000/e1000_osdep.h
@@ -53,12 +53,12 @@ u32 e1000_translate_register_82542(u32 reg);
static inline u32 e1000_dump_cntr(struct e1000_hw *a, u32 reg, char *regname)
{
u32 res = readl((a)->hw_addr + E1000_REGISTER(a, reg));
-#ifdef DEBUG_REGS
+//#ifdef DEBUG_REGS
if (res)
dbg_printf("NON-ZERO ERROR COUNTER: %s -> 0x%08x\n", regname, res);
-#else
- (void) regname;
-#endif
+//#else
+// (void) regname;
+//#endif
return res;
}
#ifndef DEBUG_REGS
diff --git a/src/drivers/net/e1000/e1000_phy.c b/src/drivers/net/e1000/e1000_phy.c
index 7b8b3baa..1b02df28 100644
--- a/src/drivers/net/e1000/e1000_phy.c
+++ b/src/drivers/net/e1000/e1000_phy.c
@@ -606,6 +606,23 @@ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw)
if (ret_val)
goto out;
+ /*
+ * For Truxton, it is necessary to add RGMII tx and rx
+ * timing delay though the EXT_PHY_SPEC_CTRL register
+ */
+ if (hw->mac.type == e1000_ep80579) {
+ ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
+ if (ret_val)
+ goto out;
+
+ phy_data |= M88E1000_EPSCR_TX_TIME_CTRL;
+ phy_data |= M88E1000_EPSCR_RX_TIME_CTRL;
+
+ ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data);
+ if (ret_val)
+ goto out;
+ }
+
if (phy->revision < E1000_REVISION_4) {
/*
* Force TX_CLK in the Extended PHY Specific Control Register