Skip to content

Commit

Permalink
igb: add 82576 MAC support
Browse files Browse the repository at this point in the history
Signed-off-by: Alexander Duyck <[email protected]>
Signed-off-by: Auke Kok <[email protected]>
Signed-off-by: Jeff Kirsher <[email protected]>
Signed-off-by: Jeff Garzik <[email protected]>
  • Loading branch information
Alexander Duyck authored and Jeff Garzik committed Jul 11, 2008
1 parent 0024fd0 commit 2d064c0
Show file tree
Hide file tree
Showing 9 changed files with 476 additions and 86 deletions.
208 changes: 195 additions & 13 deletions drivers/net/igb/e1000_82575.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

#include <linux/types.h>
#include <linux/slab.h>
#include <linux/if_ether.h>

#include "e1000_mac.h"
#include "e1000_82575.h"
Expand All @@ -45,7 +46,6 @@ static s32 igb_get_cfg_done_82575(struct e1000_hw *);
static s32 igb_init_hw_82575(struct e1000_hw *);
static s32 igb_phy_hw_reset_sgmii_82575(struct e1000_hw *);
static s32 igb_read_phy_reg_sgmii_82575(struct e1000_hw *, u32, u16 *);
static void igb_rar_set_82575(struct e1000_hw *, u8 *, u32);
static s32 igb_reset_hw_82575(struct e1000_hw *);
static s32 igb_set_d0_lplu_state_82575(struct e1000_hw *, bool);
static s32 igb_setup_copper_link_82575(struct e1000_hw *);
Expand Down Expand Up @@ -84,6 +84,12 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
case E1000_DEV_ID_82575GB_QUAD_COPPER:
mac->type = e1000_82575;
break;
case E1000_DEV_ID_82576:
case E1000_DEV_ID_82576_FIBER:
case E1000_DEV_ID_82576_SERDES:
case E1000_DEV_ID_82576_QUAD_COPPER:
mac->type = e1000_82576;
break;
default:
return -E1000_ERR_MAC_INIT;
break;
Expand Down Expand Up @@ -128,6 +134,8 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
mac->mta_reg_count = 128;
/* Set rar entry count */
mac->rar_entry_count = E1000_RAR_ENTRIES_82575;
if (mac->type == e1000_82576)
mac->rar_entry_count = E1000_RAR_ENTRIES_82576;
/* Set if part includes ASF firmware */
mac->asf_firmware_present = true;
/* Set if manageability features are enabled. */
Expand Down Expand Up @@ -694,13 +702,12 @@ static s32 igb_check_for_link_82575(struct e1000_hw *hw)
if ((hw->phy.media_type != e1000_media_type_copper) ||
(igb_sgmii_active_82575(hw)))
ret_val = igb_get_pcs_speed_and_duplex_82575(hw, &speed,
&duplex);
&duplex);
else
ret_val = igb_check_for_copper_link(hw);

return ret_val;
}

/**
* igb_get_pcs_speed_and_duplex_82575 - Retrieve current speed/duplex
* @hw: pointer to the HW structure
Expand Down Expand Up @@ -757,18 +764,129 @@ static s32 igb_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, u16 *speed,
}

/**
* igb_rar_set_82575 - Set receive address register
* igb_init_rx_addrs_82575 - Initialize receive address's
* @hw: pointer to the HW structure
* @rar_count: receive address registers
*
* Setups the receive address registers by setting the base receive address
* register to the devices MAC address and clearing all the other receive
* address registers to 0.
**/
static void igb_init_rx_addrs_82575(struct e1000_hw *hw, u16 rar_count)
{
u32 i;
u8 addr[6] = {0,0,0,0,0,0};
/*
* This function is essentially the same as that of
* e1000_init_rx_addrs_generic. However it also takes care
* of the special case where the register offset of the
* second set of RARs begins elsewhere. This is implicitly taken care by
* function e1000_rar_set_generic.
*/

hw_dbg("e1000_init_rx_addrs_82575");

/* Setup the receive address */
hw_dbg("Programming MAC Address into RAR[0]\n");
hw->mac.ops.rar_set(hw, hw->mac.addr, 0);

/* Zero out the other (rar_entry_count - 1) receive addresses */
hw_dbg("Clearing RAR[1-%u]\n", rar_count-1);
for (i = 1; i < rar_count; i++)
hw->mac.ops.rar_set(hw, addr, i);
}

/**
* igb_update_mc_addr_list_82575 - Update Multicast addresses
* @hw: pointer to the HW structure
* @mc_addr_list: array of multicast addresses to program
* @mc_addr_count: number of multicast addresses to program
* @rar_used_count: the first RAR register free to program
* @rar_count: total number of supported Receive Address Registers
*
* Updates the Receive Address Registers and Multicast Table Array.
* The caller must have a packed mc_addr_list of multicast addresses.
* The parameter rar_count will usually be hw->mac.rar_entry_count
* unless there are workarounds that change this.
**/
void igb_update_mc_addr_list_82575(struct e1000_hw *hw,
u8 *mc_addr_list, u32 mc_addr_count,
u32 rar_used_count, u32 rar_count)
{
u32 hash_value;
u32 i;
u8 addr[6] = {0,0,0,0,0,0};
/*
* This function is essentially the same as that of
* igb_update_mc_addr_list_generic. However it also takes care
* of the special case where the register offset of the
* second set of RARs begins elsewhere. This is implicitly taken care by
* function e1000_rar_set_generic.
*/

/*
* Load the first set of multicast addresses into the exact
* filters (RAR). If there are not enough to fill the RAR
* array, clear the filters.
*/
for (i = rar_used_count; i < rar_count; i++) {
if (mc_addr_count) {
igb_rar_set(hw, mc_addr_list, i);
mc_addr_count--;
mc_addr_list += ETH_ALEN;
} else {
igb_rar_set(hw, addr, i);
}
}

/* Clear the old settings from the MTA */
hw_dbg("Clearing MTA\n");
for (i = 0; i < hw->mac.mta_reg_count; i++) {
array_wr32(E1000_MTA, i, 0);
wrfl();
}

/* Load any remaining multicast addresses into the hash table. */
for (; mc_addr_count > 0; mc_addr_count--) {
hash_value = igb_hash_mc_addr(hw, mc_addr_list);
hw_dbg("Hash value = 0x%03X\n", hash_value);
hw->mac.ops.mta_set(hw, hash_value);
mc_addr_list += ETH_ALEN;
}
}

/**
* igb_shutdown_fiber_serdes_link_82575 - Remove link during power down
* @hw: pointer to the HW structure
* @addr: pointer to the receive address
* @index: receive address array register
*
* Sets the receive address array register at index to the address passed
* in by addr.
* In the case of fiber serdes, shut down optics and PCS on driver unload
* when management pass thru is not enabled.
**/
static void igb_rar_set_82575(struct e1000_hw *hw, u8 *addr, u32 index)
void igb_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw)
{
if (index < E1000_RAR_ENTRIES_82575)
igb_rar_set(hw, addr, index);
u32 reg;

if (hw->mac.type != e1000_82576 ||
(hw->phy.media_type != e1000_media_type_fiber &&
hw->phy.media_type != e1000_media_type_internal_serdes))
return;

/* if the management interface is not enabled, then power down */
if (!igb_enable_mng_pass_thru(hw)) {
/* Disable PCS to turn off link */
reg = rd32(E1000_PCS_CFG0);
reg &= ~E1000_PCS_CFG_PCS_EN;
wr32(E1000_PCS_CFG0, reg);

/* shutdown the laser */
reg = rd32(E1000_CTRL_EXT);
reg |= E1000_CTRL_EXT_SDP7_DATA;
wr32(E1000_CTRL_EXT, reg);

/* flush the write to verify completion */
wrfl();
msleep(1);
}

return;
}
Expand Down Expand Up @@ -854,7 +972,7 @@ static s32 igb_init_hw_82575(struct e1000_hw *hw)
igb_clear_vfta(hw);

/* Setup the receive address */
igb_init_rx_addrs(hw, rar_count);
igb_init_rx_addrs_82575(hw, rar_count);
/* Zero out the Multicast HASH table */
hw_dbg("Zeroing the MTA\n");
for (i = 0; i < mac->mta_reg_count; i++)
Expand Down Expand Up @@ -1113,6 +1231,70 @@ static bool igb_sgmii_active_82575(struct e1000_hw *hw)
return ret_val;
}

/**
* igb_translate_register_82576 - Translate the proper register offset
* @reg: e1000 register to be read
*
* Registers in 82576 are located in different offsets than other adapters
* even though they function in the same manner. This function takes in
* the name of the register to read and returns the correct offset for
* 82576 silicon.
**/
u32 igb_translate_register_82576(u32 reg)
{
/*
* Some of the Kawela registers are located at different
* offsets than they are in older adapters.
* Despite the difference in location, the registers
* function in the same manner.
*/
switch (reg) {
case E1000_TDBAL(0):
reg = 0x0E000;
break;
case E1000_TDBAH(0):
reg = 0x0E004;
break;
case E1000_TDLEN(0):
reg = 0x0E008;
break;
case E1000_TDH(0):
reg = 0x0E010;
break;
case E1000_TDT(0):
reg = 0x0E018;
break;
case E1000_TXDCTL(0):
reg = 0x0E028;
break;
case E1000_RDBAL(0):
reg = 0x0C000;
break;
case E1000_RDBAH(0):
reg = 0x0C004;
break;
case E1000_RDLEN(0):
reg = 0x0C008;
break;
case E1000_RDH(0):
reg = 0x0C010;
break;
case E1000_RDT(0):
reg = 0x0C018;
break;
case E1000_RXDCTL(0):
reg = 0x0C028;
break;
case E1000_SRRCTL(0):
reg = 0x0C00C;
break;
default:
break;
}

return reg;
}

/**
* igb_reset_init_script_82575 - Inits HW defaults after reset
* @hw: pointer to the HW structure
Expand Down Expand Up @@ -1304,7 +1486,7 @@ static struct e1000_mac_operations e1000_mac_ops_82575 = {
.reset_hw = igb_reset_hw_82575,
.init_hw = igb_init_hw_82575,
.check_for_link = igb_check_for_link_82575,
.rar_set = igb_rar_set_82575,
.rar_set = igb_rar_set,
.read_mac_addr = igb_read_mac_addr_82575,
.get_speed_and_duplex = igb_get_speed_and_duplex_copper,
};
Expand Down
9 changes: 9 additions & 0 deletions drivers/net/igb/e1000_82575.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,13 @@
#ifndef _E1000_82575_H_
#define _E1000_82575_H_

u32 igb_translate_register_82576(u32 reg);
void igb_update_mc_addr_list_82575(struct e1000_hw*, u8*, u32, u32, u32);
extern void igb_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw);
extern void igb_rx_fifo_flush_82575(struct e1000_hw *hw);

#define E1000_RAR_ENTRIES_82575 16
#define E1000_RAR_ENTRIES_82576 24

/* SRRCTL bit definitions */
#define E1000_SRRCTL_BSIZEPKT_SHIFT 10 /* Shift _right_ */
Expand Down Expand Up @@ -159,5 +163,10 @@ struct e1000_adv_tx_context_desc {
#define E1000_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */
#define E1000_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* Tx Desc writeback RO bit */

/* Additional DCA related definitions, note change in position of CPUID */
#define E1000_DCA_TXCTRL_CPUID_MASK_82576 0xFF000000 /* Tx CPUID Mask */
#define E1000_DCA_RXCTRL_CPUID_MASK_82576 0xFF000000 /* Rx CPUID Mask */
#define E1000_DCA_TXCTRL_CPUID_SHIFT 24 /* Tx CPUID now in the last byte */
#define E1000_DCA_RXCTRL_CPUID_SHIFT 24 /* Rx CPUID now in the last byte */

#endif
10 changes: 10 additions & 0 deletions drivers/net/igb/e1000_defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@
#define E1000_I2CCMD_ERROR 0x80000000
#define E1000_MAX_SGMII_PHY_REG_ADDR 255
#define E1000_I2CCMD_PHY_TIMEOUT 200
#define E1000_IVAR_VALID 0x80
#define E1000_GPIE_NSICR 0x00000001
#define E1000_GPIE_MSIX_MODE 0x00000010
#define E1000_GPIE_EIAME 0x40000000
#define E1000_GPIE_PBA 0x80000000

/* Receive Descriptor bit definitions */
#define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */
Expand Down Expand Up @@ -213,6 +218,7 @@
/* Device Control */
#define E1000_CTRL_FD 0x00000001 /* Full duplex.0=half; 1=full */
#define E1000_CTRL_GIO_MASTER_DISABLE 0x00000004 /*Blocks new Master requests */
#define E1000_CTRL_LRST 0x00000008 /* Link reset. 0=normal,1=reset */
#define E1000_CTRL_ASDE 0x00000020 /* Auto-speed detect enable */
#define E1000_CTRL_SLU 0x00000040 /* Set link up (Force Link) */
#define E1000_CTRL_ILOS 0x00000080 /* Invert Loss-Of Signal */
Expand Down Expand Up @@ -244,6 +250,7 @@
*/

#define E1000_CONNSW_ENRGSRC 0x4
#define E1000_PCS_CFG_PCS_EN 8
#define E1000_PCS_LCTL_FLV_LINK_UP 1
#define E1000_PCS_LCTL_FSV_100 2
#define E1000_PCS_LCTL_FSV_1000 4
Expand All @@ -253,6 +260,7 @@
#define E1000_PCS_LCTL_AN_ENABLE 0x10000
#define E1000_PCS_LCTL_AN_RESTART 0x20000
#define E1000_PCS_LCTL_AN_TIMEOUT 0x40000
#define E1000_ENABLE_SERDES_LOOPBACK 0x0410

#define E1000_PCS_LSTS_LINK_OK 1
#define E1000_PCS_LSTS_SPEED_100 2
Expand Down Expand Up @@ -360,6 +368,7 @@
#define E1000_PBA_16K 0x0010 /* 16KB, default TX allocation */
#define E1000_PBA_24K 0x0018
#define E1000_PBA_34K 0x0022
#define E1000_PBA_64K 0x0040 /* 64KB */

#define IFS_MAX 80
#define IFS_MIN 40
Expand Down Expand Up @@ -528,6 +537,7 @@
/* PHY Control Register */
#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */
#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */
#define MII_CR_POWER_DOWN 0x0800 /* Power down */
#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */
#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */
#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */
Expand Down
8 changes: 8 additions & 0 deletions drivers/net/igb/e1000_hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@

struct e1000_hw;

#define E1000_DEV_ID_82576 0x10C9
#define E1000_DEV_ID_82576_FIBER 0x10E6
#define E1000_DEV_ID_82576_SERDES 0x10E7
#define E1000_DEV_ID_82576_QUAD_COPPER 0x10E8
#define E1000_DEV_ID_82575EB_COPPER 0x10A7
#define E1000_DEV_ID_82575EB_FIBER_SERDES 0x10A9
#define E1000_DEV_ID_82575GB_QUAD_COPPER 0x10D6
Expand All @@ -50,6 +54,7 @@ struct e1000_hw;
enum e1000_mac_type {
e1000_undefined = 0,
e1000_82575,
e1000_82576,
e1000_num_macs /* List is 1-based, so subtract 1 for true count. */
};

Expand Down Expand Up @@ -410,14 +415,17 @@ struct e1000_mac_operations {
s32 (*check_for_link)(struct e1000_hw *);
s32 (*reset_hw)(struct e1000_hw *);
s32 (*init_hw)(struct e1000_hw *);
bool (*check_mng_mode)(struct e1000_hw *);
s32 (*setup_physical_interface)(struct e1000_hw *);
void (*rar_set)(struct e1000_hw *, u8 *, u32);
s32 (*read_mac_addr)(struct e1000_hw *);
s32 (*get_speed_and_duplex)(struct e1000_hw *, u16 *, u16 *);
void (*mta_set)(struct e1000_hw *, u32);
};

struct e1000_phy_operations {
s32 (*acquire_phy)(struct e1000_hw *);
s32 (*check_reset_block)(struct e1000_hw *);
s32 (*force_speed_duplex)(struct e1000_hw *);
s32 (*get_cfg_done)(struct e1000_hw *hw);
s32 (*get_cable_length)(struct e1000_hw *);
Expand Down
Loading

0 comments on commit 2d064c0

Please sign in to comment.