#ifdef __LINUX
#include <asm/byteorder.h>
#endif
#ifdef USER_LINUX
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <malloc.h>
#endif
#ifdef __FreeBSD__
#endif
#include "bcmtype.h"
#ifdef EDEBUG
#include "edebug_types.h"
#endif
#include "clc.h"
#include "grc_addr.h"
#include "bigmac_addresses.h"
#include "emac_reg_driver.h"
#include "misc_bits.h"
#include "57712_reg.h"
#include "clc_reg.h"
#include "dev_info.h"
#include "license.h"
#include "shmem.h"
#include "aeu_inputs.h"
struct elink_params *params,
/********************************************************/
/* L2 header size + 2*VLANs (8 bytes) + LLC SNAP (8 bytes) */
#define I2C_BSC0 0
/* LED Blink rate that will achieve ~15.9Hz */
/***********************************************************/
/* Macros */
/***********************************************************/
#ifndef OFFSETOF
#endif
(CHIP_REV_IS_SLOW(_chip_id)&& \
(CHIP_REV_IS_SLOW(_chip_id)&& \
CHIP_NUM_57710) || \
CHIP_NUM_57711) || \
CHIP_NUM_57712) || \
CHIP_NUM_57712E) || \
CHIP_NUM_57713) || \
(_chip_family == 0x1680) || \
(_chip_family == 0x16a0))
/* For EMUL: Ax=0xE, Bx=0xC, Cx=0xA. For FPGA: Ax=0xF, Bx=0xD,
* Cx=0xB.
*/
>>1) << CHIP_REV_SHIFT)
OFFSETOF(struct shmem2_region, \
_field))
#ifndef NULL
#define NULL ((void *) 0)
#endif
/***********************************************************/
/* Shortcut definitions */
/***********************************************************/
#define ELINK_NIG_LATCH_BC_ENABLE_MI_INT 0
#define ELINK_NIG_STATUS_EMAC0_MI_INT \
#define ELINK_NIG_STATUS_XGXS0_LINK10G \
#define ELINK_NIG_STATUS_XGXS0_LINK_STATUS \
#define ELINK_NIG_STATUS_XGXS0_LINK_STATUS_SIZE \
#define ELINK_NIG_STATUS_SERDES0_LINK_STATUS \
#define ELINK_NIG_MASK_MI_INT \
#define ELINK_NIG_MASK_XGXS0_LINK10G \
#define ELINK_NIG_MASK_XGXS0_LINK_STATUS \
#define ELINK_NIG_MASK_SERDES0_LINK_STATUS \
#define ELINK_MDIO_AN_CL73_OR_37_COMPLETE \
#define ELINK_XGXS_RESET_BITS \
#define ELINK_SERDES_RESET_BITS \
#define ELINK_AUTONEG_PARALLEL \
#define ELINK_AUTONEG_SGMII_FIBER_AUTODET \
#define ELINK_GP_STATUS_PAUSE_RSOLUTION_TXSIDE \
#define ELINK_GP_STATUS_PAUSE_RSOLUTION_RXSIDE \
#define ELINK_GP_STATUS_SPEED_MASK \
#define ELINK_GP_STATUS_10G_HIG \
#define ELINK_GP_STATUS_10G_CX4 \
#define ELINK_GP_STATUS_10G_KX4 \
#define ELINK_LINK_UPDATE_MASK \
/* ETS defines*/
#ifdef INCLUDE_WARPCORE_UC_LOAD
#endif
/**********************************************************/
/* INTERFACE */
/**********************************************************/
(_phy)->def_md_devad, \
_val)
(_phy)->def_md_devad, \
_val)
#ifdef BNX2X_ADD /* BNX2X_ADD */
struct elink_params *params);
#endif
{
return val;
}
{
return val;
}
/*
* elink_check_lfa - This function checks if link reinitialization is required,
* or link flap can be avoided.
*
* @params: link parameters
* Returns 0 if Link Flap Avoidance conditions are met otherwise, the failed
* condition code.
*/
#ifndef EXCLUDE_NON_COMMON_INIT
{
/* NOTE: must be first condition checked -
* to verify DCC bit is cleared in any case!
*/
if (additional_config & NO_LFA_DUE_TO_DCC_MASK) {
return LFA_DCC_LFA_DISABLED;
}
/* Verify that link is up */
OFFSETOF(struct shmem_region,
if (!(link_status & LINK_STATUS_LINK_UP))
return LFA_LINK_DOWN;
/* if loaded after BOOT from SAN, don't flap the link in any case and
* rely on link set by preboot driver
*/
return 0;
/* Verify that loopback mode is not set */
if (params->loopback_mode)
return LFA_LOOPBACK_ENABLED;
/* Verify that MFW supports LFA */
return LFA_MFW_IS_TOO_OLD;
cfg_size = 2;
lfa_mask = 0xffffffff;
} else {
cfg_size = 1;
lfa_mask = 0xffff;
}
/* Compare Duplex */
return LFA_DUPLEX_MISMATCH;
}
/* Compare Flow Control */
return LFA_FLOW_CTRL_MISMATCH;
}
/* Compare Link Speed */
return LFA_LINK_SPEED_MISMATCH;
}
return LFA_SPEED_CAP_MISMATCH;
}
}
return LFA_FLOW_CTRL_MISMATCH;
}
OFFSETOF(struct shmem2_region,
if (((eee_status & SHMEM_EEE_LPI_REQUESTED_BIT) ^
return LFA_EEE_MISMATCH;
}
/* LFA conditions are met */
return 0;
}
#endif
/******************************************************************/
/******************************************************************/
#if (!defined EXCLUDE_WARPCORE)
{
*en = 0;
/* Sanity check */
if (epio_pin > 31) {
return;
}
/* Set this EPIO to output */
}
{
/* Sanity check */
if (epio_pin > 31) {
return;
}
/* Set this EPIO to output */
if (en)
else
/* Set the value for this EPIO */
}
{
if (pin_cfg == PIN_CFG_NA)
return;
if (pin_cfg >= PIN_CFG_EPIO0) {
} else {
}
}
{
if (pin_cfg == PIN_CFG_NA)
return ELINK_STATUS_ERROR;
if (pin_cfg >= PIN_CFG_EPIO0) {
} else {
}
return ELINK_STATUS_OK;
}
#endif /* (!defined EXCLUDE_WARPCORE) */
/******************************************************************/
/* ETS section */
/******************************************************************/
#ifdef ELINK_ENHANCEMENTS
{
/* ETS disabled configuration*/
/* mapping between entry priority to client number (0,1,2 -debug and
* management clients, 3 - COS0 client, 4 - COS client)(HIGHEST)
* 3bits client num.
* PRI4 | PRI3 | PRI2 | PRI1 | PRI0
* cos1-100 cos0-011 dbg1-010 dbg0-001 MCP-000
*/
/* Bitmap of 5bits length. Each bit specifies whether the entry behaves
* as strict. Bits 0,1,2 - debug and management entries, 3 -
* COS0 entry, 4 - COS1 entry.
* COS1 | COS0 | DEBUG1 | DEBUG0 | MGMT
* bit4 bit3 bit2 bit1 bit0
* MCP and debug are strict
*/
/* defines which entries (clients) are subjected to WFQ arbitration */
/* For strict priority entries defines the number of consecutive
* slots for the highest priority.
*/
/* mapping between the CREDIT_WEIGHT registers and actual client
* numbers
*/
/* ETS mode disable */
/* If ETS mode is enabled (there is no strict priority) defines a WFQ
*/
/* Upper bound that COS0_WEIGHT can reach in the WFQ arbiter */
/* Defines the number of consecutive slots for the strict priority */
}
/******************************************************************************
* Description:
* Getting min_w_val will be set according to line speed .
*.
******************************************************************************/
{
/* Calculate min_w_val.*/
else
} else
/* If the link isn't up (static configuration for example ) The
* link will be according to 20GBPS.
*/
return min_w_val;
}
/******************************************************************************
* Description:
* Getting credit upper bound form min_w_val.
*.
******************************************************************************/
{
return credit_upper_bound;
}
/******************************************************************************
* Description:
* Set credit upper bound for NIG.
*.
******************************************************************************/
static void elink_ets_e3b0_set_credit_upper_bound_nig(
const struct elink_params *params,
{
if (!port) {
}
}
/******************************************************************************
* Description:
* Will return the NIG ETS registers to init values.Except
* credit_upper_bound.
* That isn't used in this configuration (No WFQ is enabled) and will be
* configured acording to spec
*.
******************************************************************************/
const struct elink_vars *vars)
{
/* Mapping between entry priority to client number (0,1,2 -debug and
* management clients, 3 - COS0 client, 4 - COS1, ... 8 -
* COS5)(HIGHEST) 4bits client num.TODO_ETS - Should be done by
* reset value or init tool
*/
if (port) {
} else {
}
/* For strict priority entries defines the number of consecutive
* slots for the highest priority.
*/
/* Mapping between the CREDIT_WEIGHT registers and actual client
* numbers
*/
if (port) {
/*Port 1 has 6 COS*/
} else {
/*Port 0 has 9 COS*/
0x43210876);
}
/* Bitmap of 5bits length. Each bit specifies whether the entry behaves
* as strict. Bits 0,1,2 - debug and management entries, 3 -
* COS0 entry, 4 - COS1 entry.
* COS1 | COS0 | DEBUG1 | DEBUG0 | MGMT
* bit4 bit3 bit2 bit1 bit0
* MCP and debug are strict
*/
if (port)
else
/* defines which entries (clients) are subjected to WFQ arbitration */
/* Please notice the register address are note continuous and a
* for here is note appropriate.In 2 port mode port0 only COS0-5
* can be used. DEBUG1,DEBUG1,MGMT are never used for WFQ* In 4
* port mode port1 only COS0-2 can be used. DEBUG1,DEBUG1,MGMT
* are never used for WFQ
*/
if (!port) {
}
}
/******************************************************************************
* Description:
* Set credit upper bound for PBF.
*.
******************************************************************************/
static void elink_ets_e3b0_set_credit_upper_bound_pbf(
const struct elink_params *params,
{
u8 i = 0;
/* In 2 port mode port0 has COS0-5 that can be used for WFQ.In 4
* port mode port1 has COS0-2 that can be used for WFQ.
*/
if (!port) {
} else {
}
for (i = 0; i < max_cos; i++)
}
/******************************************************************************
* Description:
* Will return the PBF ETS registers to init values.Except
* credit_upper_bound.
* That isn't used in this configuration (No WFQ is enabled) and will be
* configured acording to spec
*.
******************************************************************************/
{
u8 i = 0;
/* Mapping between entry priority to client number 0 - COS0
* client, 2 - COS1, ... 5 - COS5)(HIGHEST) 4bits client num.
* TODO_ETS - Should be done by reset value or init tool
*/
if (port)
/* 0x688 (|011|0 10|00 1|000) */
else
/* (10 1|100 |011|0 10|00 1|000) */
/* TODO_ETS - Should be done by reset value or init tool */
if (port)
/* 0x688 (|011|0 10|00 1|000)*/
else
/* 0x2C688 (10 1|100 |011|0 10|00 1|000) */
PBF_REG_ETS_ARB_NUM_STRICT_ARB_SLOTS_P0 , 0x100);
/* In 2 port mode port0 has COS0-5 that can be used for WFQ.
* In 4 port mode port1 has COS0-2 that can be used for WFQ.
*/
if (!port) {
} else {
}
for (i = 0; i < max_cos; i++)
}
/******************************************************************************
* Description:
* E3B0 disable will return basicly the values to init values.
*.
******************************************************************************/
const struct elink_vars *vars)
{
"elink_ets_e3b0_disabled the chip isn't E3B0\n");
return ELINK_STATUS_ERROR;
}
return ELINK_STATUS_OK;
}
/******************************************************************************
* Description:
* Disable will return basicly the values to init values.
*
******************************************************************************/
struct elink_vars *vars)
{
else {
return ELINK_STATUS_ERROR;
}
return elink_status;
}
/******************************************************************************
* Description
* Set the COS mappimg to SP and BW until this point all the COS are not
* set as SP or BW.
******************************************************************************/
const struct elink_ets_params *ets_params,
const u8 cos_sp_bitmap,
const u8 cos_bw_bitmap)
{
return ELINK_STATUS_OK;
}
/******************************************************************************
* Description:
* This function is needed because NIG ARB_CREDIT_WEIGHT_X are
* not continues and ARB_CREDIT_WEIGHT_0 + offset is suitable.
******************************************************************************/
const u32 min_w_val_nig,
const u32 min_w_val_pbf,
{
/* Calculate and set BW for this COS - use 1 instead of 0 for BW */
switch (cos_entry) {
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
if (port)
return ELINK_STATUS_ERROR;
break;
case 4:
if (port)
return ELINK_STATUS_ERROR;
break;
case 5:
if (port)
return ELINK_STATUS_ERROR;
break;
}
return ELINK_STATUS_OK;
}
/******************************************************************************
* Description:
* Calculate the total BW.A value of 0 isn't legal.
*
******************************************************************************/
const struct elink_params *params,
struct elink_ets_params *ets_params,
{
*total_bw = 0 ;
/* Calculate total BW requested */
is_bw_cos_exist = 1;
"was set to 0\n");
/* This is to prevent a state when ramrods
* can't be sent
*/
= 1;
}
*total_bw +=
}
}
/* Check total BW is valid */
if (*total_bw == 0) {
"elink_ets_E3B0_config total BW shouldn't be 0\n");
return ELINK_STATUS_ERROR;
}
"elink_ets_E3B0_config total BW should be 100\n");
/* We can handle a case whre the BW isn't 100 this can happen
* if the TC are joined.
*/
}
return ELINK_STATUS_OK;
}
/******************************************************************************
* Description:
* Invalidate all the sp_pri_to_cos.
*
******************************************************************************/
{
}
/******************************************************************************
* Description:
* Calculate and set the SP (ARB_PRIORITY_CLIENT) NIG and PBF registers
* according to sp_pri_to_cos.
*
******************************************************************************/
{
if (pri >= max_num_of_cos) {
"parameter Illegal strict priority\n");
return ELINK_STATUS_ERROR;
}
"parameter There can't be two COS's with "
"the same strict pri\n");
return ELINK_STATUS_ERROR;
}
return ELINK_STATUS_OK;
}
/******************************************************************************
* Description:
* Returns the correct value according to COS and priority in
* the sp_pri_cli register.
*
******************************************************************************/
const u8 pri_offset,
const u8 entry_size)
{
(pri_set + pri_offset));
return pri_cli_nig;
}
/******************************************************************************
* Description:
* Returns the correct value according to COS and priority in the
* sp_pri_cli register for NIG.
*
******************************************************************************/
{
/* MCP Dbg0 and dbg1 are always with higher strict pri*/
nig_pri_offset, 4);
}
/******************************************************************************
* Description:
* Returns the correct value according to COS and priority in the
* sp_pri_cli register for PBF.
*
******************************************************************************/
{
pbf_pri_offset, 3);
}
/******************************************************************************
* Description:
* Calculate and set the SP (ARB_PRIORITY_CLIENT) NIG and PBF registers
* according to sp_pri_to_cos.(which COS has higher priority)
*
******************************************************************************/
{
u8 i = 0;
/* MCP Dbg0 and dbg1 are always with higher strict pri*/
/* Set all the strict priority first */
for (i = 0; i < max_num_of_cos; i++) {
if (sp_pri_to_cos[i] != DCBX_INVALID_COS) {
if (sp_pri_to_cos[i] >= ELINK_DCBX_MAX_NUM_COS) {
"elink_ets_e3b0_sp_set_pri_cli_reg "
"invalid cos entry\n");
return ELINK_STATUS_ERROR;
}
sp_pri_to_cos[i], pri_set);
sp_pri_to_cos[i], pri_set);
/* COS is used remove it from bitmap.*/
if (!(pri_bitmask & cos_bit_to_set)) {
"elink_ets_e3b0_sp_set_pri_cli_reg "
"invalid There can't be two COS's with"
" the same strict pri\n");
return ELINK_STATUS_ERROR;
}
pri_set++;
}
}
/* Set all the Non strict priority i= COS*/
for (i = 0; i < max_num_of_cos; i++) {
pri_bitmask = 1 << i;
/* Check if COS was already used for SP */
if (pri_bitmask & cos_bit_to_set) {
/* COS wasn't used for SP */
i, pri_set);
i, pri_set);
/* COS is used remove it from bitmap.*/
pri_set++;
}
}
if (pri_set != max_num_of_cos) {
"entries were set\n");
return ELINK_STATUS_ERROR;
}
if (port) {
/* Only 6 usable clients*/
(u32)pri_cli_nig);
} else {
/* Only 9 usable clients*/
}
return ELINK_STATUS_OK;
}
/******************************************************************************
* Description:
* Configure the COS to ETS according to BW and SP settings.
******************************************************************************/
const struct elink_vars *vars,
struct elink_ets_params *ets_params)
{
"elink_ets_e3b0_disabled the chip isn't E3B0\n");
return ELINK_STATUS_ERROR;
}
"isn't supported\n");
return ELINK_STATUS_ERROR;
}
/* Prepare sp strict priority parameters*/
/* Prepare BW parameters*/
&total_bw);
if (elink_status != ELINK_STATUS_OK) {
"elink_ets_E3B0_config get_total_bw failed\n");
return ELINK_STATUS_ERROR;
}
/* Upper bound is set according to current link speed (min_w_val
* should be the same for upper bound and COS credit val).
*/
/* The function also sets the BW in HW(not the mappin
* yet)
*/
port);
} else if (elink_cos_state_strict ==
} else {
"elink_ets_e3b0_config cos state not valid\n");
return ELINK_STATUS_ERROR;
}
if (elink_status != ELINK_STATUS_OK) {
"elink_ets_e3b0_config set cos bw failed\n");
return elink_status;
}
}
/* Set SP register (which COS has higher priority) */
if (elink_status != ELINK_STATUS_OK) {
"elink_ets_E3B0_config set_pri_cli_reg failed\n");
return elink_status;
}
/* Set client mapping of BW and strict */
if (elink_status != ELINK_STATUS_OK) {
return elink_status;
}
return ELINK_STATUS_OK;
}
{
/* ETS disabled configuration */
/* Defines which entries (clients) are subjected to WFQ arbitration
* COS0 0x8
* COS1 0x10
*/
/* Mapping between the ARB_CREDIT_WEIGHT registers and actual
* client numbers (WEIGHT_0 does not actually have to represent
* client 0)
* PRI4 | PRI3 | PRI2 | PRI1 | PRI0
* cos1-001 cos0-000 dbg1-100 dbg0-011 MCP-010
*/
/* ETS mode enabled*/
/* Defines the number of consecutive slots for the strict priority */
/* Bitmap of 5bits length. Each bit specifies whether the entry behaves
* as strict. Bits 0,1,2 - debug and management entries, 3 - COS0
* entry, 4 - COS1 entry.
* COS1 | COS0 | DEBUG21 | DEBUG0 | MGMT
* bit4 bit3 bit2 bit1 bit0
* MCP and debug are strict
*/
/* Upper bound that COS0_WEIGHT can reach in the WFQ arbiter.*/
}
{
/* ETS disabled configuration*/
if ((!total_bw) ||
(!cos0_bw) ||
(!cos1_bw)) {
return;
}
}
{
/* ETS disabled configuration*/
/* Bitmap of 5bits length. Each bit specifies whether the entry behaves
* as strict. Bits 0,1,2 - debug and management entries,
* 3 - COS0 entry, 4 - COS1 entry.
* COS1 | COS0 | DEBUG21 | DEBUG0 | MGMT
* bit4 bit3 bit2 bit1 bit0
* MCP and debug are strict
*/
/* For strict priority entries defines the number of consecutive slots
* for the highest priority.
*/
/* ETS mode disable */
/* Defines the number of consecutive slots for the strict priority */
/* Defines the number of consecutive slots for the strict priority */
/* Mapping between entry priority to client number (0,1,2 -debug and
* management clients, 3 - COS0 client, 4 - COS client)(HIGHEST)
* 3bits client num.
* PRI4 | PRI3 | PRI2 | PRI1 | PRI0
* dbg0-010 dbg1-001 cos1-100 cos0-011 MCP-000
* dbg0-010 dbg1-001 cos0-011 cos1-100 MCP-000
*/
return ELINK_STATUS_OK;
}
#endif /* ELINK_ENHANCEMENTS */
/******************************************************************/
/* PFC section */
/******************************************************************/
#ifndef EXCLUDE_NON_COMMON_INIT
#ifndef EXCLUDE_WARPCORE
struct elink_vars *vars,
{
/* XMAC base adrr */
/* Initialize pause and pfc registers */
pause_val = 0x18000;
pfc0_val = 0xFFFF8000;
pfc1_val = 0x2;
/* No PFC support */
if (!(params->feature_config_flags &
/* RX flow control - Process pause frame in receive direction
*/
/* TX flow control - Send pause packet when buffer is full */
} else {/* PFC support */
/* Write pause and PFC registers */
}
/* Write pause and PFC registers */
}
#endif // EXCLUDE_WARPCORE
#endif // #ifndef EXCLUDE_NON_COMMON_INIT
#ifdef ELINK_ENHANCEMENTS
#ifndef BNX2X_UPSTREAM /* ! BNX2X_UPSTREAM */
{
/* Read pfc statistic */
/* PFC received frames */
/* PFC received sent */
}
/* Read pfc statistic*/
{
/* Read pfc statistic */
return;
}
}
#endif /* ! BNX2X_UPSTREAM */
#endif /* ELINK_ENHANCEMENTS */
/******************************************************************/
/******************************************************************/
{
/* Set clause 45 mode, slow down the MDIO clock to 2.5MHz
* (a value of 49==0x31) and make sure that the AUTO poll is off
*/
if (ELINK_USES_WARPCORE(chip_id))
else
(cur_mode & (EMAC_MDIO_MODE_CLAUSE_45)))
return;
}
#ifndef EXCLUDE_WARPCORE
{
/* Check 4-port override enabled */
if (port4mode_ovwr_val & (1<<0)) {
/* Return 4-port mode override value */
}
/* Return 4-port mode from input pin */
}
#endif
#ifndef EXCLUDE_NON_COMMON_INIT
struct elink_params *params)
{
/* Set mdio clock per phy */
phy_index++)
}
struct elink_vars *vars)
{
/* reset and unreset the emac core */
/* init emac - use read-modify-write */
/* self clear reset */
timeout = 200;
do {
if (!timeout) {
return;
}
timeout--;
} while (val & EMAC_MODE_RESET);
/* Set mac address */
}
#ifndef EXCLUDE_WARPCORE
{
enable);
enable);
}
{
return;
if (en)
else
/* Disable RX and TX */
}
{
/* Reset UMAC */
/* This register opens the gate for the UMAC despite its name */
switch (vars->line_speed) {
case ELINK_SPEED_10:
val |= (0<<2);
break;
case ELINK_SPEED_100:
break;
case ELINK_SPEED_1000:
break;
case ELINK_SPEED_2500:
break;
default:
vars->line_speed);
break;
}
/* Configure UMAC for EEE */
} else {
}
/* Enable RX and TX */
/* Remove SW Reset */
/* Check loopback mode */
if (lb)
/* Maximum Frame Length (RW). Defines a 14-Bit maximum frame
* length used by the MAC receive logic to check frames.
*/
}
/* Define the XMAC mode */
{
/* In 4-port mode, need to set the mode only once, so if XMAC is
* already out of reset, it means the mode has already been set,
* and it must not* reset the XMAC again, since it controls both
* ports of the path
*/
is_port4mode &&
"XMAC already out of reset in 4-port mode\n");
return;
}
/* Hard reset */
if (is_port4mode) {
/* Set the number of ports on the system side to up to 2 */
/* Set the number of ports on the Warp Core to 10G */
} else {
/* Set the number of ports on the system side to 1 */
if (max_speed == ELINK_SPEED_10000) {
"Init XMAC to 10G x 1 port per path\n");
/* Set the number of ports on the Warp Core to 10G */
} else {
"Init XMAC to 20G x 2 ports per path\n");
/* Set the number of ports on the Warp Core to 20G */
}
}
/* Soft reset */
}
{
/* Send an indication to change the state in the NIG back to XON
* Clearing this bit enables the next set of this bit to get
* rising edge
*/
if (en)
else
}
}
{
/* This register determines on which events the MAC will assert
* error on the i/f to the NIG along w/ EOP.
*/
/* This register tells the NIG whether to send traffic to UMAC
* or XMAC
*/
/* When XMAC is in XLGMII mode, disable sending idles for fault
* detection.
*/
}
/* Set Max packet size */
/* CRC append for Tx packets */
/* update PFC */
} else {
}
/* Enable TX and RX */
/* Set MAC in XLGMII mode for dual-mode */
/* Check loopback mode */
if (lb)
return ELINK_STATUS_OK;
}
#endif // EXCLUDE_WARPCORE
#ifndef EXCLUDE_EMAC
{
/* Disable BMAC */
/* enable emac and not bmac */
#ifdef ELINK_INCLUDE_EMUL
/* for paladium */
/* Use lane 1 (of lanes 0-3) */
}
/* for fpga */
else
#endif
#ifdef ELINK_INCLUDE_FPGA
/* Use lane 1 (of lanes 0-3) */
} else
#endif
/* ASIC */
/* select the master lanes (out of 0-3) */
/* select XGXS */
} else { /* SerDes */
/* select SerDes */
}
#if defined(ELINK_INCLUDE_EMUL) || defined(ELINK_INCLUDE_FPGA)
/* config GMII mode */
} else { /* ASIC */
#endif /* defined(ELINK_INCLUDE_EMUL) || defined(ELINK_INCLUDE_FPGA)*/
if (!(params->feature_config_flags &
} else
#if defined(ELINK_INCLUDE_EMUL) || defined(ELINK_INCLUDE_FPGA)
}
#endif /* defined(ELINK_INCLUDE_EMUL) || defined(ELINK_INCLUDE_FPGA) */
/* KEEP_VLAN_TAG, promiscuous */
/* Setting this bit causes MAC control frames (except for pause
* frames) to be passed on for processing. This setting has no
* affect on the operation of the pause frames. This bit effects
* all packets regardless of RX Parser packet sorting logic.
* Turn the PFC off to make sure we are in Xon state before
* enabling it.
*/
/* Enable PFC again */
((0x0101 <<
(0x00ff <<
}
/* Set Loopback */
if (lb)
val |= 0x810;
else
val &= ~0x810;
/* Enable emac */
#ifndef ELINK_AUX_POWER
/* Enable emac for jumbo packets */
#endif
/* Strip CRC */
val = 0;
if ((params->feature_config_flags &
val = 1;
#ifdef ELINK_INCLUDE_EMUL
/* Take the BigMac out of reset */
/* Enable access for bmac registers */
} else
#endif /* ELINK_INCLUDE_EMUL */
return ELINK_STATUS_OK;
}
#endif //EXCLUDE_EMAC
#ifndef EXCLUDE_BMAC1
struct elink_vars *vars)
{
if ((!(params->feature_config_flags &
/* Enable BigMAC to react on received Pause packets */
wb_data[1] = 0;
/* TX control */
val = 0xc0;
if (!(params->feature_config_flags &
val |= 0x800000;
wb_data[1] = 0;
}
#endif // EXCLUDE_BMAC1
#ifndef EXCLUDE_BMAC2
struct elink_vars *vars,
{
/* Set rx control: Strip CRC and enable BigMAC to relay
* control packets to the system as well
*/
if ((!(params->feature_config_flags &
/* Enable BigMAC to react on received Pause packets */
wb_data[1] = 0;
/* Tx control */
val = 0xc0;
if (!(params->feature_config_flags &
val |= 0x800000;
wb_data[1] = 0;
/* Enable PFC RX & TX & STATS and set 8 COS */
wb_data[0] = 0x0;
wb_data[1] = 0;
wb_data, 2);
/* Clear the force Xon */
} else {
/* Disable PFC RX & TX & STATS and set 8 COS */
wb_data[0] = 0x8;
wb_data[1] = 0;
}
/* Set Time (based unit is 512 bit time) between automatic
* re-sending of PP packets amd enable automatic re-send of
* Per-Priroity Packet as long as pp_gen is asserted and
* pp_disable is low.
*/
val = 0x8000;
wb_data[1] = 0;
wb_data, 2);
/* mac control */
if (is_lb) {
}
/* When PFC enabled, Pass pause frames towards the NIG. */
wb_data[1] = 0;
}
#endif // EXCLUDE_BMAC2
#endif // EXCLUDE_NON_COMMON_INIT
#ifdef ELINK_ENHANCEMENTS
/******************************************************************************
* Description:
* This function is needed because NIG ARB_CREDIT_WEIGHT_X are
* not continues and ARB_CREDIT_WEIGHT_0 + offset is suitable.
******************************************************************************/
{
switch (cos_entry) {
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
if (port)
return ELINK_STATUS_ERROR;
break;
case 4:
if (port)
return ELINK_STATUS_ERROR;
break;
case 5:
if (port)
return ELINK_STATUS_ERROR;
break;
}
return ELINK_STATUS_OK;
}
#endif // ELINK_ENHANCEMENTS
#ifndef EXCLUDE_NON_COMMON_INIT
{
OFFSETOF(struct shmem_region,
}
#ifdef ELINK_ENHANCEMENTS
struct elink_vars *vars,
struct elink_nig_brb_pfc_port_params *nig_params)
{
/* When NIG_LLH0_XCM_MASK_REG_LLHX_XCM_MASK_BCN bit is set
* MAC control frames (that are not pause packets)
* will be forwarded to the XCM.
*/
/* NIG params will override non PFC params, since it's possible to
* do transition from PFC to SAFC
*/
if (set_pfc) {
pause_enable = 0;
llfc_out_en = 0;
llfc_enable = 0;
ppp_enable = 0;
else
ppp_enable = 1;
xcm_out_en = 0;
hwpfc_enable = 1;
} else {
if (nig_params) {
} else /* Default non PFC mode - PAUSE */
pause_enable = 1;
xcm_out_en = 1;
}
/* Output enable for RX_XCM # IF */
/* HW PFC TX enable */
if (nig_params) {
u8 i = 0;
for (i = 0; i < nig_params->num_of_rx_cos_priority_mask; i++)
}
}
struct elink_vars *vars,
struct elink_nig_brb_pfc_port_params *pfc_params)
{
/* The PFC and pause are orthogonal to one another, meaning when
* PFC is enabled, the pause are disabled, and when PFC is
* disabled, pause are set according to the pause result.
*/
else
/* Update NIG params */
return ELINK_STATUS_OK;
} else {
if ((val &
== 0) {
return ELINK_STATUS_OK;
}
else
val = 0;
if ((params->feature_config_flags &
val = 1;
}
return ELINK_STATUS_OK;
}
#endif /* ELINK_ENHANCEMENTS */
#ifndef EXCLUDE_BMAC1
struct elink_vars *vars,
{
/* XGXS control */
wb_data[0] = 0x3c;
wb_data[1] = 0;
wb_data, 2);
/* TX MAC SA */
/* MAC control */
val = 0x3;
if (is_lb) {
val |= 0x4;
}
wb_data[1] = 0;
/* Set rx mtu */
wb_data[1] = 0;
/* Set tx mtu */
wb_data[1] = 0;
/* Set cnt max size */
wb_data[1] = 0;
/* Configure SAFC */
wb_data[0] = 0x1000200;
wb_data[1] = 0;
wb_data, 2);
#ifdef ELINK_INCLUDE_EMUL
/* Fix for emulation */
wb_data[0] = 0xf000;
wb_data[1] = 0;
wb_data, 2);
}
#endif /* ELINK_INCLUDE_EMUL */
return ELINK_STATUS_OK;
}
#endif /* EXCLUDE_BMAC1 */
#ifndef EXCLUDE_BMAC2
struct elink_vars *vars,
{
wb_data[0] = 0;
wb_data[1] = 0;
/* XGXS control: Reset phy HW, MDIO registers, PHY PLL and BMAC */
wb_data[0] = 0x3c;
wb_data[1] = 0;
wb_data, 2);
/* TX MAC SA */
wb_data, 2);
/* Configure SAFC */
wb_data[0] = 0x1000200;
wb_data[1] = 0;
wb_data, 2);
/* Set RX MTU */
wb_data[1] = 0;
/* Set TX MTU */
wb_data[1] = 0;
/* Set cnt max size */
wb_data[1] = 0;
return ELINK_STATUS_OK;
}
#endif /* EXCLUDE_BMAC2 */
#if !defined(EXCLUDE_BMAC2)
struct elink_vars *vars,
{
/* Reset and unreset the BigMac */
if (reset_bmac) {
}
/* Enable access for bmac registers */
/* Enable BMAC according to BMAC type*/
#ifdef ELINK_ENHANCEMENTS
#endif
#ifndef EXCLUDE_BMAC2
#endif
#ifdef ELINK_ENHANCEMENTS
else
#endif
#ifndef EXCLUDE_BMAC1
#endif
val = 0;
if ((params->feature_config_flags &
val = 1;
return rc;
}
#endif /* #if !defined(EXCLUDE_BMAC2) && !defined(EXCLUDE_BMAC1) */
#if !defined(EXCLUDE_BMAC2) && !defined(EXCLUDE_BMAC1)
{
if (CHIP_IS_E2(chip_id))
else
/* Only if the bmac is out of reset */
/* Clear Rx Enable bit in BMAC_CONTROL register */
if (en)
else
wb_data[0] &= ~ELINK_BMAC_CONTROL_RX_ENABLE;
}
}
#endif /* !defined(EXCLUDE_BMAC2) && !defined(EXCLUDE_BMAC1) */
#endif // EXCLUDE_NON_COMMON_INIT
#ifndef ELINK_AUX_POWER
{
/* Disable port */
/* Wait for init credit */
count--;
}
return ELINK_STATUS_ERROR;
}
if (flow_ctrl & ELINK_FLOW_CTRL_RX ||
line_speed == ELINK_SPEED_10 ||
line_speed == ELINK_SPEED_100 ||
line_speed == ELINK_SPEED_1000 ||
line_speed == ELINK_SPEED_2500) {
/* Update threshold */
/* Update init credit */
} else {
ELINK_ETH_OVREHEAD)/16;
/* Update threshold */
/* Update init credit */
switch (line_speed) {
case ELINK_SPEED_10000:
break;
default:
return ELINK_STATUS_ERROR;
}
}
/* Probe the credit changes */
/* Enable port */
return ELINK_STATUS_OK;
}
#endif /* ELINK_AUX_POWER */
#ifndef EXCLUDE_COMMON_INIT
/**
* elink_get_emac_base - retrive emac base address
*
* @bp: driver handle
* @mdc_mdio_access: access type
* @port: port id
*
* emac1) depend on the mdc_mdio_access, port, port swapped. Each
* phy has a default access mode, which could also be overridden
* by nvram configuration. This parameter, whether this is the
* default phy configuration, or the nvram overrun
* configuration, is passed here as mdc_mdio_access and selects
*/
{
switch (mdc_mdio_access) {
break;
else
break;
else
break;
break;
break;
default:
break;
}
return emac_base;
}
#endif /* EXCLUDE_COMMON_INIT */
/******************************************************************/
/* CL22 access functions */
/******************************************************************/
#ifndef EXCLUDE_NON_COMMON_INIT
#ifndef EXCLUDE_BCM54618SE
{
u8 i;
/* Switch to CL22 */
/* Address */
for (i = 0; i < 50; i++) {
if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
break;
}
}
if (tmp & EMAC_MDIO_COMM_START_BUSY) {
}
return rc;
}
{
u16 i;
/* Switch to CL22 */
/* Address */
for (i = 0; i < 50; i++) {
if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
break;
}
}
if (val & EMAC_MDIO_COMM_START_BUSY) {
*ret_val = 0;
}
return rc;
}
#endif
#endif /* EXCLUDE_NON_COMMON_INIT */
/******************************************************************/
/* CL45 access functions */
/******************************************************************/
{
u16 i;
#ifndef ELINK_AUX_POWER
}
#endif /* ELINK_AUX_POWER */
/* Address */
for (i = 0; i < 50; i++) {
if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
break;
}
}
if (val & EMAC_MDIO_COMM_START_BUSY) {
*ret_val = 0;
} else {
/* Data */
for (i = 0; i < 50; i++) {
if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
break;
}
}
if (val & EMAC_MDIO_COMM_START_BUSY) {
*ret_val = 0;
}
}
/* Work around for E3 A0 */
}
}
return rc;
}
{
u8 i;
#ifndef ELINK_AUX_POWER
}
#endif /* ELINK_AUX_POWER */
/* Address */
for (i = 0; i < 50; i++) {
if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
break;
}
}
if (tmp & EMAC_MDIO_COMM_START_BUSY) {
} else {
/* Data */
for (i = 0; i < 50; i++) {
if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
break;
}
}
if (tmp & EMAC_MDIO_COMM_START_BUSY) {
}
}
/* Work around for E3 A0 */
}
}
return rc;
}
/******************************************************************/
/* EEE section */
/******************************************************************/
#ifndef EXCLUDE_NON_COMMON_INIT
#ifndef EXCLUDE_WARPCORE
{
return 0;
return 1;
}
{
switch (nvram_mode) {
break;
break;
break;
default:
*idle_timer = 0;
break;
}
return ELINK_STATUS_OK;
}
{
switch (idle_timer) {
break;
break;
break;
default:
break;
}
return ELINK_STATUS_OK;
}
{
/* time value in eee_mode --> used directly*/
} else {
/* hsi value in eee_mode --> time */
&eee_idle))
return 0;
}
} else {
/* hsi values in nvram --> time*/
eee_power_mode)) &
return 0;
}
return eee_idle;
}
struct elink_vars *vars)
{
if (eee_idle) {
eee_idle);
return ELINK_STATUS_ERROR;
}
/* eee_idle in 1u --> eee_status in 16u */
eee_idle >>= 4;
} else {
return ELINK_STATUS_ERROR;
}
return ELINK_STATUS_OK;
}
{
/* Propogate params' bits --> vars (for migration exposure) */
else
else
}
struct elink_params *params,
struct elink_vars *vars)
{
/* Make Certain LPI is disabled */
return ELINK_STATUS_OK;
}
struct elink_params *params,
{
/* Mask events preventing LPI generation */
if (modes & SHMEM_EEE_10G_ADV) {
val |= 0x8;
}
if (modes & SHMEM_EEE_1G_ADV) {
val |= 0x4;
}
return ELINK_STATUS_OK;
}
{
if (elink_eee_has_cap(params))
OFFSETOF(struct shmem2_region,
}
struct elink_params *params,
struct elink_vars *vars)
{
if (lp & 0x2) {
if (adv & 0x2) {
neg = 1;
}
}
if (lp & 0x14) {
if (adv & 0x14) {
neg = 1;
}
}
if (lp & 0x68) {
if (adv & 0x68) {
neg = 1;
}
}
if (neg) {
}
}
/******************************************************************/
/* BSC access functions from E3 */
/******************************************************************/
{
int idx;
/* Read I2C output PINs */
OFFSETOF(struct shmem_region,
/* Read I2C output value */
OFFSETOF(struct shmem_region,
}
{
if (xfer_cnt > 16) {
xfer_cnt);
return ELINK_STATUS_ERROR;
}
if (params)
/* Enable the engine */
/* Program slave device ID */
/* Start xfer with 0 byte to update the address pointer ???*/
val = (MCPR_IMC_COMMAND_ENABLE) |
(lc_addr << MCPR_IMC_COMMAND_TRANSFER_ADDRESS_BITSHIFT) | (0);
/* Poll for completion */
i = 0;
if (i++ > 1000) {
i);
break;
}
}
if (rc == ELINK_STATUS_TIMEOUT)
return rc;
/* Start xfer with read op */
val = (MCPR_IMC_COMMAND_ENABLE) |
(xfer_cnt);
/* Poll for completion */
i = 0;
if (i++ > 1000) {
break;
}
}
if (rc == ELINK_STATUS_TIMEOUT)
return rc;
#ifdef BIG_ENDIAN
#endif
}
return rc;
}
#endif /* EXCLUDE_WARPCORE */
#endif /* EXCLUDE_NON_COMMON_INIT */
#if !defined(EXCLUDE_NON_COMMON_INIT) || defined(INCLUDE_WARPCORE_UC_LOAD)
{
}
{
}
#endif
#ifdef ELINK_ENHANCEMENTS
{
/* Probe for the phy according to the given phy_addr, and execute
* the read request on it
*/
}
}
return ELINK_STATUS_ERROR;
}
{
/* Probe for the phy according to the given phy_addr, and execute
* the write request on it
*/
}
}
return ELINK_STATUS_ERROR;
}
#endif // ELINK_ENHANCEMENTS
#if (!defined EXCLUDE_NON_COMMON_INIT) || (!defined EXCLUDE_WARPCORE)
struct elink_params *params)
{
#ifndef EXCLUDE_WARPCORE
if (elink_is_4_port_mode(cb)) {
/* Figure out path swap value */
if (path_swap_ovr & 0x1)
else
if (path_swap)
/* Figure out port swap value */
if (port_swap_ovr & 0x1)
else
if (port_swap)
} else { /* Two port mode - no port swap */
/* Figure out path swap value */
if (path_swap_ovr & 0x1) {
} else {
}
if (path_swap)
}
#endif /* #ifndef EXCLUDE_WARPCORE */
return lane;
}
{
/* In Dual-lane mode, two lanes are joined together,
* so in order to configure them, the AER broadcast method is
* used here.
* 0x200 is the broadcast address for lanes 0,1
* 0x201 is the broadcast address for lanes 2,3
*/
else
}
#endif
#ifndef EXCLUDE_SERDES
/******************************************************************/
/* Internal phy section */
/******************************************************************/
{
/* Set Clause 22 */
/* Set Clause 45 */
}
{
}
#endif /* #ifndef EXCLUDE_SERDES */
#ifndef EXCLUDE_NON_COMMON_INIT
#ifndef EXCLUDE_XGXS
struct elink_params *params,
{
switch (action) {
case ELINK_PHY_INIT:
/* Set correct devad */
phy->def_md_devad);
break;
}
}
{
}
#endif // EXCLUDE_XGXS
{
#ifdef ELINK_DEBUG
#endif
/* Resolve pause mode and advertisement Please refer to Table
* 28B-3 of the 802.3ab-1999 spec
*/
switch (phy->req_flow_ctrl) {
case ELINK_FLOW_CTRL_AUTO:
switch (params->req_fc_auto_adv) {
case ELINK_FLOW_CTRL_BOTH:
break;
case ELINK_FLOW_CTRL_RX:
case ELINK_FLOW_CTRL_TX:
*ieee_fc |=
break;
default:
break;
}
break;
case ELINK_FLOW_CTRL_TX:
break;
case ELINK_FLOW_CTRL_RX:
case ELINK_FLOW_CTRL_BOTH:
break;
case ELINK_FLOW_CTRL_NONE:
default:
break;
}
}
#endif /* #ifndef EXCLUDE_NON_COMMON_INIT */
struct elink_vars *vars)
{
#ifdef ELINK_DEBUG
#endif
phy_index++) {
if (phy_config_swapped) {
if (phy_index == ELINK_EXT_PHY1)
else if (phy_index == ELINK_EXT_PHY2)
}
" speed_cap_mask %x\n",
}
}
#ifndef EXCLUDE_NON_COMMON_INIT
struct elink_vars *vars)
{
/* Read modify write pause advertizing */
/* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
}
}
}
{ /* LD LP */
switch (pause_result) { /* ASYM P ASYM P */
case 0xb: /* 1 0 1 1 */
break;
case 0xe: /* 1 1 1 0 */
break;
case 0x5: /* 0 1 0 1 */
case 0x7: /* 0 1 1 1 */
case 0xd: /* 1 1 0 1 */
case 0xf: /* 1 1 1 1 */
break;
default:
break;
}
if (pause_result & (1<<0))
}
struct elink_params *params,
struct elink_vars *vars)
{
#ifndef EXCLUDE_BCM54618SE
#endif
&gp_status);
lane;
} else {
<< 3);
<< 3);
}
} else {
}
pause_result = (ld_pause &
MDIO_AN_REG_ADV_PAUSE_MASK) >> 8;
pause_result |= (lp_pause &
MDIO_AN_REG_ADV_PAUSE_MASK) >> 10;
}
struct elink_params *params,
struct elink_vars *vars)
{
/* But set the flow-control result as the requested one */
ret = 1;
}
return ret;
}
#endif // EXCLUDE_NON_COMMON_INIT
/******************************************************************/
/* Warpcore section */
/******************************************************************/
/* The init_internal_warpcore should mirror the xgxs,
* i.e. reset the lane (if needed), set aer for the
* phy init is done purely in phy_init stage.
*/
((post << MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET) | \
#ifndef EXCLUDE_WARPCORE
#ifndef EXCLUDE_NON_COMMON_INIT
{
OFFSETOF(struct shmem2_region,
}
struct elink_params *params,
struct elink_vars *vars)
{
u16 i;
/* Step 2 - Configure the NP registers */
};
for (i = 0; i < ARRAY_SIZE(reg_set); i++)
/* Start KR2 work-around timer which handles BCM8073 link-parner */
}
struct elink_vars *vars,
{
int i;
};
for (i = 0; i < ARRAY_SIZE(reg_set); i++)
}
struct elink_params *params)
{
MDIO_WC_REG_EEE_COMBO_CONTROL0, 0x7c);
MDIO_WC_REG_DIGITAL4_MISC5, 0xc000);
}
struct elink_params *params)
{
/* Restart autoneg on the leading lane only */
MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1200);
/* Restore AER */
}
struct elink_params *params,
struct elink_vars *vars) {
/* Disable Autoneg: re-enable it after adv is done. */
};
/* Set to default registers that may be overriden by 10G force */
for (i = 0; i < ARRAY_SIZE(reg_set); i++)
cl72_ctrl &= 0x08ff;
cl72_ctrl |= 0x3800;
/* Check adding advertisement for 1G KX */
/* Enable CL37 1G Parallel Detect */
}
/* Check adding advertisement for 10G KR */
/* Enable 10G Parallel Detect */
}
/* Set Transmit PMD settings */
/* Configure the next lane if dual mode */
0x03f0);
0x03f0);
/* Advertised speeds */
/* Advertised and set FEC (Forward Error Correction) */
/* Enable CL37 BAM */
1);
}
/* Advertise pause */
MDIO_WC_REG_DIGITAL5_MISC7, 0x100);
/* Over 1G - AN local device user page 1 */
MDIO_WC_REG_DIGITAL3_UP1, 0x1f);
(1<<11));
MDIO_WC_REG_XGXS_X2_CONTROL3, 0x7);
} else {
/* Enable Auto-Detect to support 1G over CL37 as well */
/* Force cl48 sync_status LOW to avoid getting stuck in CL73
* parallel-detect loop when CL73 and CL37 are enabled.
*/
/* Restore Polarity settings in case it was run over by
* previous link owner
*/
if (wc_lane_config &
else
val);
}
/* Enable Autoneg: only on the main lane */
}
struct elink_params *params,
struct elink_vars *vars)
{
/* Disable Autoneg */
0x3f00},
/* Leave cl72 training enable, needed for KR */
};
for (i = 0; i < ARRAY_SIZE(reg_set); i++)
/* Global registers */
/* Disable CL36 PCS Tx */
/* Restore AER */
MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x2040);
/* Enable encoded forced speed */
MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x30);
/* Turn TX scramble payload only the 64/66 scrambler */
MDIO_WC_REG_TX66_CONTROL, 0x9);
/* Turn RX scramble payload only the 64/66 scrambler */
MDIO_WC_REG_RX66_CONTROL, 0xF9);
/* Set and clear loopback to cause a reset to 64/66 decoder */
MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x4000);
MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x0);
}
struct elink_params *params,
{
/* Hold rxSeqStart */
MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, 0x8000);
/* Hold tx_fifo_reset */
/* Disable CL73 AN */
/* Disable 100FX Enable and Auto-Detect */
MDIO_WC_REG_FX100_CTRL1, 0xFFFA);
/* Disable 100FX Idle detect */
MDIO_WC_REG_FX100_CTRL3, 0x0080);
/* Set Block address to Remote PHY & Clear forced_speed[5] */
MDIO_WC_REG_DIGITAL4_MISC3, 0xFF7F);
/* Turn off auto-detect & fiber mode */
0xFFEE);
/* Set filter_force_link, disable_false_link and parallel_detect */
/* Set XFI / SFI */
misc1_val &= ~(0x1f);
if (is_xfi) {
misc1_val |= 0x5;
} else {
tx_drv_brdct = (cfg_tap_val &
misc1_val |= 0x9;
/* TAP values are controlled by nvram, if value there isn't 0 */
if (tx_equal)
else
if (tx_drv_brdct)
0x06);
else
}
/* Set Transmit PMD settings */
/* Enable fiber mode, enable and invert sig_det */
/* Set Block address to Remote PHY & Set forced_speed[5], 40bit mode */
MDIO_WC_REG_DIGITAL4_MISC3, 0x8080);
/* 10G XFI Full Duplex */
MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x100);
/* Release tx_fifo_reset */
0xFFFE);
/* Release rxSeqStart */
MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, 0x7FFF);
}
#endif //EXCLUDE_NON_COMMON_INIT
#ifndef ELINK_AUX_POWER
struct elink_params *params)
{
/* Set global registers, so set AER lane to 0 */
/* Disable sequencer */
MDIO_AN_REG_CTRL, 0);
/* Turn off CL73 */
/* Set 20G KR2 force speed */
MDIO_WC_REG_SERDESDIGITAL_MISC1, 0x1f);
MDIO_WC_REG_CL72_USERB0_CL72_TX_FIR_TAP, 0x835A);
/* Enable sequencer (over lane 0) */
}
#endif
#ifndef EXCLUDE_COMMON_INIT
{
/* Rx0 anaRxControl1G */
MDIO_WC_REG_RX0_ANARXCONTROL1G, 0x90);
/* Rx2 anaRxControl1G */
MDIO_WC_REG_RX2_ANARXCONTROL1G, 0x90);
MDIO_WC_REG_RX66_SCW0, 0xE070);
MDIO_WC_REG_RX66_SCW1, 0xC0D0);
MDIO_WC_REG_RX66_SCW2, 0xA0B0);
MDIO_WC_REG_RX66_SCW3, 0x8090);
MDIO_WC_REG_RX66_SCW0_MASK, 0xF0F0);
MDIO_WC_REG_RX66_SCW1_MASK, 0xF0F0);
MDIO_WC_REG_RX66_SCW2_MASK, 0xF0F0);
MDIO_WC_REG_RX66_SCW3_MASK, 0xF0F0);
/* Serdes Digital Misc1 */
MDIO_WC_REG_SERDESDIGITAL_MISC1, 0x6008);
/* Serdes Digital4 Misc3 */
MDIO_WC_REG_DIGITAL4_MISC3, 0x8088);
/* Set Transmit PMD settings */
}
#endif
#ifndef EXCLUDE_NON_COMMON_INIT
struct elink_params *params,
{
/* Clear XFI clock comp in non-10G single lane mode. */
/* SGMII Autoneg */
0x1000);
} else {
val16 &= 0xcebf;
switch (phy->req_line_speed) {
case ELINK_SPEED_10:
break;
case ELINK_SPEED_100:
val16 |= 0x2000;
break;
case ELINK_SPEED_1000:
val16 |= 0x0040;
break;
default:
return;
}
val16 |= 0x0100;
}
/* SGMII Slave mode and disable signal detect */
if (fiber_mode)
digctrl_kx1 = 1;
else
digctrl_kx1 &= 0xff4a;
/* Turn off parallel detect */
/* Re-enable parallel detect */
/* Enable autodet */
(digctrl_kx1 | 0x10));
}
#endif //EXCLUDE_NON_COMMON_INIT
{
/* Take lane out of reset after configuration is finished */
if (reset)
val |= 0xC000;
else
val &= 0x3FFF;
}
#ifndef EXCLUDE_NON_COMMON_INIT
struct elink_params *params,
{
u16 i;
{MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0},
0x0195},
0x0007},
0x0002},
};
/* Set XFI clock comp as default. */
for (i = 0; i < ARRAY_SIZE(wc_regs); i++)
}
{
*gpio_num = 0;
*gpio_port = 0;
if (CHIP_IS_E3(chip_id)) {
OFFSETOF(struct shmem_region,
/* Should not happen. This function called upon interrupt
* triggered by GPIO ( since EPIO can only generate interrupts
* to MCP).
* So if this function was called and none of the GPIOs was set,
* it means the shit hit the fan.
*/
if ((cfg_pin < PIN_CFG_GPIO0_P0) ||
(cfg_pin > PIN_CFG_GPIO3_P1)) {
"No cfg pin %x for module detect indication\n",
cfg_pin);
return ELINK_STATUS_ERROR;
}
} else {
}
return ELINK_STATUS_OK;
}
struct elink_params *params)
{
return 0;
/* Call the handling function in case module is detected */
if (gpio_val == 0)
return 1;
else
return 0;
}
struct elink_params *params)
{
}
#ifndef ELINK_AUX_POWER
struct elink_params *params,
struct elink_vars *vars)
{
if (!vars->turn_to_run_wc_rt)
return;
if (vars->rx_tx_asic_rst) {
switch (serdes_net_if) {
/* Do we get link yet? */
&gp_status1);
/*10G KR*/
vars->rx_tx_asic_rst = 0;
} else {
/* Reset the lane to see if link comes up.*/
/* Restart Autoneg */
MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1200);
vars->rx_tx_asic_rst--;
}
break;
default:
break;
}
} /*params->rx_tx_asic_rst*/
}
#endif
struct elink_params *params)
{
#ifdef ELINK_DEBUG
#endif
} else {
}
}
{
OFFSETOF(struct shmem_region,
/* Set the !tx_en since this pin is DISABLE_TX_LASER */
/* For 20G, the expected pin to be used is 3 pins after the current */
}
struct elink_params *params,
struct elink_vars *vars)
{
"serdes_net_if = 0x%x\n",
if ((serdes_net_if == PORT_HW_CFG_NET_SERDES_IF_SGMII) ||
(phy->req_line_speed &&
} else {
switch (serdes_net_if) {
/* Enable KR Auto Neg */
else {
}
break;
} else {
if (ELINK_SINGLE_MEDIA_DIRECT(params)) {
fiber_mode = 1;
} else {
fiber_mode = 0;
}
0);
}
break;
/* Issue Module detection if module is plugged, or
* enabled transmitter to avoid current leakage in case
* no module is connected
*/
else
phy, 1);
}
break;
#ifndef ELINK_AUX_POWER
return;
}
/* Issue Module detection */
break;
#endif
if (!params->loopback_mode) {
} else {
#ifndef ELINK_AUX_POWER
#endif
}
break;
default:
"Unsupported Serdes Net Interface 0x%x\n",
return;
}
}
/* Take lane out of reset after configuration is finished */
}
struct elink_params *params)
{
#ifndef EXCLUDE_LINK_RESET
/* Global register */
/* Clear loopback settings (if any) */
/* 10G & 20G */
MDIO_WC_REG_COMBO_IEEE0_MIICTRL, 0xBFFF);
MDIO_WC_REG_IEEE0BLK_MIICNTL, 0xfffe);
/* Update those 1-copy registers */
/* Enable 1G MDIO (1-copy) */
~0x10);
MDIO_WC_REG_XGXSBLK1_LANECTRL2, 0xff00);
/* Disable CL36 PCS Tx */
}
/* Restore AER */
#endif
}
struct elink_params *params)
{
#ifdef ELINK_INCLUDE_LOOPBACK
/* 10/100/1000/20G-KR2 */
/* Update those 1-copy registers */
/* Enable 1G MDIO (1-copy) */
0x10);
/* Set 1G loopback based on lane (1-copy) */
val16);
/* Switch back to 4-copy registers */
} else {
/* 10G / 20G-DXGXS */
0x4000);
MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1);
}
#endif // #ifdef ELINK_INCLUDE_LOOPBACK
}
#endif // EXCLUDE_NON_COMMON_INIT
#endif // #ifndef EXCLUDE_WARPCORE
#ifdef INCLUDE_WARPCORE_UC_LOAD
{
MDIO_WC_REG_XGXS_X2_CONTROL2, 0x29FB);
/* Figure out path swap value */
if (path_swap_ovr & 0x1)
else
/* Find which lanes to power down according to path swap value */
if (path_swap) {
power_down_lanes[0] = 1;
power_down_lanes[2] = 0;
} else {
power_down_lanes[0] = 0;
}
/* Go through lanes which should be powered down */
for (i = 0; i < 4; i++) {
if (power_down_lanes[i]) {
(1 << i) | (1 << (4+i)) |
(1 << 11));
}
}
}
#endif //INCLUDE_WARPCORE_UC_LOAD
#ifdef INCLUDE_WARPCORE_UC_LOAD
/**
* elink_warpcore_sequencer
*
* @param cb
* @param phy
* @param enable - sequencer
*
* @return u32
*
* there's need disable the sequencer and once all
* configurations are made the sequencer will be enabled again.
* That way it is guaranteed that improper link won't be
* established during the init phase.
*/
if(enable)
val16 |= 0x2000;
else
val16 &= 0xDFFF;
}
{
rx_lane_swap = ((wc_lane_config &
tx_lane_swap = ((wc_lane_config &
/* Rx Lanes */
val16 &= 0xFF00;
val16 |= rx_lane_swap;
/* Tx Lanes */
val16 &= 0xFF00;
val16 |= tx_lane_swap;
}
{
/* Set RX polarity on all lanes; flip and enable the flip. */
/* Set TX polarity on all lanes */
}
{
if (pll_lock & 0x1) {
/* Flush all TX fifo */
break;
}
}
if (time == ELINK_MDIO_ACCESS_TIMEOUT) {
return ELINK_STATUS_ERROR;
}
return ELINK_STATUS_OK;
}
{
/* Need to set lanes 0..3 */
/* Reset Asic lane */
// This access is required only for version 0xd101 of the WC FW
&val);
MDIO_WC_REG_DSC_SMC, 0x8000);
/* Set on clock compensation in WC */
MDIO_WC_REG_RX66_CONTROL, 0x7415);
/* Set on clock compensation in WC
* that clock comensation in cl48 modes is enabled during
* multi-port modes, and disabled during single port modes.
*/
0x8091);
}
}
{
&val);
(3<<6));
/* Set on clock compensation in WC
* that clock comensation in cl48 modes is enabled during
* multi-port modes, and disabled during single port modes.
*/
0x8091);
/* In dual port mode XFI compensation should be disabled by
* setting 0x83C0[14:13] to 2'b00 for each port.
*/
/* This access is required only for version 0xd101 of the
* WC FW
*/
MDIO_WC_REG_DSC_SMC, 0x8000);
}
port_hw_config[0].default_cfg)) &
/* Configure both ports to 20G to enable clock working on both ports */
}
}
{
/* Enable External memory access */
MDIO_WC_REG_UC_INFO_B0_DEAD_TRAP, 0x0000);
MDIO_WC_REG_MICROBLK_CMD3, 0x0407);
/* Initialize ram memory prior to programming it */
MDIO_WC_REG_MICROBLK_CMD, 0x8000);
/* Wait for completion of memory initialization */
if (val & 0x8000)
break;
}
if (cnt >= ELINK_WC_UC_TIMEOUT)
return ELINK_STATUS_TIMEOUT;
/* Load Warpcore microcode for E3 and after */
MDIO_WC_REG_MICROBLK_CMD3, 0x0404);
/* Turn off read_for_cmd bit, check for FW setting this later. */
MDIO_WC_REG_MICROBLK_CMD, 0x0810);
break;
}
if (cnt >= ELINK_WC_RDY_TIMEOUT_MSEC)
return ELINK_STATUS_TIMEOUT;
return ELINK_STATUS_OK;
}
#endif /* INCLUDE_WARPCORE_UC_LOAD */
struct elink_vars *vars)
{
#ifdef ELINK_DEBUG
#endif
switch (vars->link_status &
case ELINK_LINK_10THD:
/* Fall thru */
case ELINK_LINK_10TFD:
break;
case ELINK_LINK_100TXHD:
/* Fall thru */
case ELINK_LINK_100T4:
case ELINK_LINK_100TXFD:
break;
case ELINK_LINK_1000THD:
/* Fall thru */
case ELINK_LINK_1000TFD:
break;
case ELINK_LINK_2500THD:
/* Fall thru */
case ELINK_LINK_2500TFD:
break;
case ELINK_LINK_10GTFD:
break;
case ELINK_LINK_20GTFD:
break;
default:
break;
}
if (vars->line_speed &&
} else {
}
#ifndef EXCLUDE_WARPCORE
if (vars->line_speed &&
#endif /* #ifndef EXCLUDE_WARPCORE */
/* Anything 10 and over uses the bmac */
if (link_10g_plus) {
else
} else {
else
}
} else { /* Link down */
vars->phy_link_up = 0;
vars->line_speed = 0;
/* Indicate no mac active */
}
}
struct elink_vars *vars)
{
/* Update PHY configuration */
OFFSETOF(struct shmem_region,
/* Force link UP in non LOOPBACK_EXT loopback mode(s) */
#ifndef EXCLUDE_NON_COMMON_INIT
#ifndef EXCLUDE_WARPCORE
if (elink_eee_has_cap(params))
OFFSETOF(struct shmem2_region,
#endif
#endif
/* Sync media type */
OFFSETOF(struct shmem_region,
/* Sync AEU offset */
OFFSETOF(struct shmem_region,
/* Sync PFC status */
else
}
#ifndef EXCLUDE_NON_COMMON_INIT
#ifndef EXCLUDE_XGXS
{
/* Set the master_ln for AN */
(new_master_ln | ser_lane));
}
{
u16 i;
/* Reset the unicore */
(mii_control |
#ifndef EXCLUDE_SERDES
if (set_serdes)
#endif /* EXCLUDE_SERDES */
/* Wait for the reset to self clear */
for (i = 0; i < ELINK_MDIO_ACCESS_TIMEOUT; i++) {
/* The reset erased the previous bank value */
&mii_control);
if (!(mii_control & MDIO_COMBO_IEEO_MII_CONTROL_RESET)) {
return ELINK_STATUS_OK;
}
}
elink_cb_event_log(cb, ELINK_LOG_ID_PHY_UNINITIALIZED, params->port); // "Warning: PHY was not initialized,"
// " Port %d\n",
return ELINK_STATUS_ERROR;
}
{
/* Each two bits represents a lane number:
* No swap is 0123 => 0x1b no need to enable the swap
*/
if (rx_lane_swap != 0x1b) {
(rx_lane_swap |
} else {
}
if (tx_lane_swap != 0x1b) {
(tx_lane_swap |
} else {
}
}
struct elink_params *params)
{
&control2);
else
control2);
(phy->speed_cap_mask &
&control2);
control2 |=
control2);
/* Disable parallel detection of HiG */
}
}
struct elink_params *params,
struct elink_vars *vars,
{
/* CL37 Autoneg */
/* CL37 Autoneg Enabled */
else /* CL37 Autoneg Disabled */
else
/* Enable TetonII and BAM autoneg */
®_val);
/* Enable BAM aneg Mode and TetonII aneg Mode */
} else {
/* TetonII and BAM Autoneg Disabled */
}
reg_val);
if (enable_cl73) {
/* Enable Cl73 FSM status bits */
0xe);
/* Enable BAM Station Manager*/
/* Advertise CL73 link speeds */
®_val);
if (phy->speed_cap_mask &
if (phy->speed_cap_mask &
reg_val);
/* CL73 Autoneg Enabled */
} else /* CL73 Autoneg Disabled */
reg_val = 0;
}
/* Program SerDes, forced speed */
struct elink_params *params,
struct elink_vars *vars)
{
/* Program duplex, disable autoneg and sgmii*/
/* Program speed
* - needed only if the speed is greater than 1G (2.5G or 10G)
*/
/* Clearing the speed value before setting the right speed */
reg_val |=
}
}
struct elink_params *params)
{
/* Set extended capabilities */
MDIO_OVER_1G_UP3, 0x400);
}
struct elink_params *params,
{
/* For AN, we are always publishing full duplex */
}
struct elink_params *params,
{
if (enable_cl73) {
&mii_control);
(mii_control |
} else {
&mii_control);
"elink_restart_autoneg mii_control before = 0x%x\n",
(mii_control |
}
}
struct elink_params *params,
struct elink_vars *vars)
{
/* In SGMII mode, the unicore is always slave */
&control1);
/* Set sgmii mode (and not fiber) */
control1);
/* If forced speed */
/* Set speed, disable autoneg */
&mii_control);
switch (vars->line_speed) {
case ELINK_SPEED_100:
mii_control |=
break;
case ELINK_SPEED_1000:
mii_control |=
break;
case ELINK_SPEED_10:
/* There is nothing to set for 10M */
break;
default:
/* Invalid speed for SGMII */
vars->line_speed);
break;
}
/* Setting the full duplex */
mii_control |=
} else { /* AN mode */
/* Enable and restart AN */
}
}
/* Link management
*/
struct elink_params *params)
{
return ELINK_STATUS_OK;
return 1;
}
&pd_10g);
return 1;
}
return ELINK_STATUS_OK;
}
struct elink_params *params,
struct elink_vars *vars,
{
if ((gp_status &
&ld_pause);
&lp_pause);
pause_result = (ld_pause &
pause_result |= (lp_pause &
} else {
&ld_pause);
&lp_pause);
pause_result = (ld_pause &
pause_result |= (lp_pause &
}
}
struct elink_params *params,
struct elink_vars *vars,
{
#ifdef ELINK_DEBUG
#endif
/* Resolve from gp_status in case of AN complete and not sgmii */
/* But set the flow-control result as the requested one */
else if ((gp_status & ELINK_MDIO_AN_CL73_OR_37_COMPLETE) &&
return;
}
}
}
struct elink_params *params)
{
/* Step 1: Make sure signal is detected */
&rx_status);
if ((rx_status & MDIO_RX0_RX_STATUS_SIGDET) !=
"rx_status(0x80b0) = 0x%x\n", rx_status);
return;
}
/* Step 2: Check CL73 state machine */
&ustat_val);
if ((ustat_val &
"ustat_val(0x8371) = 0x%x\n", ustat_val);
return;
}
/* Step 3: Check CL37 Message Pages received to indicate LP
* supports only CL37
*/
if ((cl37_fsm_received &
"misc_rx_status(0x8330) = 0x%x\n",
return;
}
* we are connected to a device which does not support cl73, but
* does support cl37 BAM. In this case we disable cl73 and
* restart cl37 auto-neg
*/
/* Disable CL73 */
0);
/* Restart CL37 autoneg */
}
struct elink_params *params,
struct elink_vars *vars,
{
vars->link_status |=
vars->link_status |=
}
#endif /* EXCLUDE_XGXS */
struct elink_params *params,
struct elink_vars *vars,
{
#ifdef ELINK_DEBUG
#endif
if (is_link_up) {
switch (speed_mask) {
case ELINK_GP_STATUS_10M:
if (is_duplex == DUPLEX_FULL)
else
break;
case ELINK_GP_STATUS_100M:
if (is_duplex == DUPLEX_FULL)
else
break;
case ELINK_GP_STATUS_1G:
case ELINK_GP_STATUS_1G_KX:
if (is_duplex == DUPLEX_FULL)
else
break;
case ELINK_GP_STATUS_2_5G:
if (is_duplex == DUPLEX_FULL)
else
break;
case ELINK_GP_STATUS_5G:
case ELINK_GP_STATUS_6G:
"link speed unsupported gp_status 0x%x\n",
return ELINK_STATUS_ERROR;
case ELINK_GP_STATUS_10G_KX4:
case ELINK_GP_STATUS_10G_HIG:
case ELINK_GP_STATUS_10G_CX4:
case ELINK_GP_STATUS_10G_KR:
case ELINK_GP_STATUS_10G_SFI:
case ELINK_GP_STATUS_10G_XFI:
break;
case ELINK_GP_STATUS_20G_KR2:
break;
default:
"link speed unsupported gp_status 0x%x\n",
return ELINK_STATUS_ERROR;
}
} else { /* link_down */
vars->phy_link_up = 0;
}
return ELINK_STATUS_OK;
}
#ifndef EXCLUDE_XGXS
struct elink_params *params,
struct elink_vars *vars)
{
/* Read gp_status */
&gp_status);
link_up = 1;
duplex);
if (rc == ELINK_STATUS_ERROR)
return rc;
if (ELINK_SINGLE_MEDIA_DIRECT(params)) {
}
} else { /* Link_down */
/* Check signal is detected */
}
}
/* Read LP advertised speeds*/
if (ELINK_SINGLE_MEDIA_DIRECT(params) &&
vars->link_status |=
if (val & (MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4 |
vars->link_status |=
if (val & MDIO_OVER_1G_UP1_2_5G)
vars->link_status |=
vars->link_status |=
}
return rc;
}
#endif // EXCLUDE_XGXS
#ifndef EXCLUDE_WARPCORE
struct elink_params *params,
struct elink_vars *vars)
{
/* Read gp_status */
if ((params->loopback_mode) &&
link_up &= 0x1;
1, &temp_link_up);
1, &link_up);
if (link_up)
} else {
&gp_status1);
/* Check for either KR, 1G, or AN up. */
(gp_status1 >> 12) |
(gp_status1)) &
(1 << lane);
}
/* Check Autoneg complete */
&gp_status4);
vars->link_status |=
/* Check parallel detect used */
&pd);
vars->link_status |=
}
}
}
vars->link_status |=
if (val & (MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4 |
vars->link_status |=
if (val & MDIO_OVER_1G_UP1_2_5G)
vars->link_status |=
vars->link_status |=
}
if (lane < 2) {
} else {
}
if ((lane & 1) == 0)
gp_speed <<= 8;
gp_speed &= 0x3f00;
/* Reset the TX FIFO to fix SGMII issue */
duplex);
/* In case of KR link down, start up the recovering procedure */
return rc;
}
#endif /* #ifndef EXCLUDE_WARPCORE */
#ifndef EXCLUDE_XGXS
{
/* Read precomp */
/* Bits [10:7] at lp_up2, positioned at [15:12] */
if (lp_up2 == 0)
return;
bank,
/* Replace tx_driver bits [15:12] */
if (lp_up2 !=
bank,
}
}
}
struct elink_vars *vars)
{
switch (vars->line_speed) {
case ELINK_SPEED_10:
break;
case ELINK_SPEED_100:
break;
case ELINK_SPEED_1000:
break;
case ELINK_SPEED_2500:
break;
default:
/* 10G not valid for EMAC */
vars->line_speed);
return ELINK_STATUS_ERROR;
}
mode);
return ELINK_STATUS_OK;
}
struct elink_params *params)
{
bank,
phy->rx_preemphasis[i]);
}
bank,
phy->tx_preemphasis[i]);
}
}
struct elink_params *params,
struct elink_vars *vars)
{
#ifdef ELINK_DEBUG
#endif
if (ELINK_SINGLE_MEDIA_DIRECT(params) &&
/* Forced speed requested? */
/* Disable autoneg */
/* Program speed and duplex */
} else { /* AN_mode */
/* AN enabled */
/* Program duplex & pause advertisement (for aneg) */
/* Enable autoneg */
/* Enable and restart AN */
}
} else { /* SGMII mode */
}
}
struct elink_params *params,
struct elink_vars *vars)
{
if ((phy->req_line_speed &&
(!phy->req_line_speed &&
(phy->speed_cap_mask >=
(phy->speed_cap_mask <
else
/* Reset the SerDes and wait for reset bit return low */
if (rc != ELINK_STATUS_OK)
return rc;
/* Setting the masterLn_def again after the reset */
}
return rc;
}
#endif // #ifndef EXCLUDE_NON_COMMON_INIT
#endif /* EXCLUDE_XGXS */
#ifndef EXCLUDE_NON_COMMON_INIT
#ifndef ELINK_EMUL_ONLY
struct elink_params *params)
{
/* Wait for soft reset to get cleared up to 1 sec */
#ifndef EXCLUDE_BCM54618SE
else
#endif
break;
}
if (cnt == 1000)
elink_cb_event_log(cb, ELINK_LOG_ID_PHY_UNINITIALIZED, params->port); // "Warning: PHY was not initialized,"
// " Port %d\n",
return cnt;
}
#endif /* ELINK_EMUL_ONLY */
{
/* Setting the status to report on link up for either XGXS or SerDes */
if (!(ELINK_SINGLE_MEDIA_DIRECT(params)))
if (!(ELINK_SINGLE_MEDIA_DIRECT(params)) &&
}
} else { /* SerDes */
if (!(ELINK_SINGLE_MEDIA_DIRECT(params)) &&
}
}
mask);
}
{
/* Disable the MI INT ( external phy int ) by writing 1 to the
* status register. Link down indication is high-active-signal,
* so in this case we need to write the status to clear the XOR
*/
/* Read Latched signals */
/* Handle only those with latched-signal=up.*/
if (exp_mi_int)
+ port*4,
else
+ port*4,
if (latch_status & 1) {
/* For all latched-signal=up : Re-Arm Latch signals */
}
/* For all latched-signal=up,Write original_signal to status */
}
{
/* First reset all status we assume only one line will be
* change at a time
*/
if (vars->phy_link_up) {
else {
if (is_10g_plus)
/* Disable the link interrupt by writing 1 to
* the relevant lane in the status register
*/
((params->lane_config &
} else
}
mask);
mask);
}
}
#if !defined(ELINK_EMUL_ONLY) && (!defined(EXCLUDE_BCM8727_BCM8073) || !defined(EXCLUDE_SFX7101) || !defined(EXCLUDE_BCM8705) || !defined(EXCLUDE_BCM87x6))
{
#ifdef ELINK_ENHANCEMENTS
if (*len < 10) {
/* Need more than 10chars for this format */
*str_ptr = '\0';
(*len)--;
return ELINK_STATUS_ERROR;
}
while (shift > 0) {
shift -= 4;
if (digit == 0 && remove_leading_zeros) {
continue;
} else if (digit < 0xa)
else
remove_leading_zeros = 0;
str_ptr++;
(*len)--;
*str_ptr = '.';
str_ptr++;
(*len)--;
remove_leading_zeros = 1;
}
}
#endif /* ELINK_ENHANCEMENTS */
return ELINK_STATUS_OK;
}
#endif /* ELINK_EMUL_ONLY */
#ifndef EXCLUDE_BCM8705
{
#ifdef ELINK_ENHANCEMENTS
str[0] = '\0';
(*len)--;
#endif // ELINK_ENHANCEMENTS
return ELINK_STATUS_OK;
}
#endif // EXCLUDE_BCM8705
#ifdef ELINK_ENHANCEMENTS
{
return ELINK_STATUS_ERROR;
/* Extract first external phy*/
version[0] = '\0';
&remain_len);
}
*ver_p = '/';
ver_p++;
remain_len--;
&remain_len);
}
}
*ver_p = '\0';
return status;
}
#endif // ELINK_ENHANCEMENTS
#ifndef EXCLUDE_XGXS
struct elink_params *params)
{
#ifdef ELINK_INCLUDE_LOOPBACK
/* Change the uni_phy_addr in the nig */
port*0x18));
0x5);
}
5,
(MDIO_AER_BLOCK_AER_REG & 0xf)),
0x2800);
5,
(MDIO_CL73_IEEEB0_CL73_AN_CONTROL & 0xf)),
0x6041);
/* Set aer mmd back */
/* And md_devad */
md_devad);
}
} else {
(MDIO_COMBO_IEEE0_MII_CONTROL & 0xf)),
&mii_ctrl);
(MDIO_COMBO_IEEE0_MII_CONTROL & 0xf)),
mii_ctrl |
}
#endif // ELINK_INCLUDE_LOOPBACK
}
#endif /* EXCLUDE_XGXS */
{
speed, hw_led_mode);
/* In case */
}
}
#ifdef ELINK_INCLUDE_EMUL
if (params->feature_config_flags &
return rc;
#endif
switch (mode) {
case ELINK_LED_MODE_OFF:
tmp &= ~(EMAC_LED_1000MB_OVERRIDE |
else
tmp |= EMAC_LED_OVERRIDE;
break;
case ELINK_LED_MODE_OPER:
/* For all other phys, OPER mode is same as ON, so in case
* link is down, do nothing
*/
break;
case ELINK_LED_MODE_ON:
/* This is a work-around for E2+8727 Configurations */
if (mode == ELINK_LED_MODE_ON ||
speed == ELINK_SPEED_10000){
(tmp | EMAC_LED_OVERRIDE));
/* Return here without enabling traffic
* LED blink and setting rate in ON mode.
* In oper mode, enabling LED blink
* and setting rate is needed.
*/
if (mode == ELINK_LED_MODE_ON)
return rc;
}
} else if (ELINK_SINGLE_MEDIA_DIRECT(params)) {
/* This is a work-around for HW issue found when link
* is up in CL73
*/
mode == ELINK_LED_MODE_ON))
(mode == ELINK_LED_MODE_ON))
else
(mode == ELINK_LED_MODE_ON)) {
/* Break here; otherwise, it'll disable the
* intended override.
*/
break;
} else {
}
/* Set blinking rate to ~15.9Hz */
else
(tmp & (~EMAC_LED_OVERRIDE)));
#ifndef ELINK_AUX_POWER
((speed == ELINK_SPEED_2500) ||
(speed == ELINK_SPEED_1000) ||
(speed == ELINK_SPEED_100) ||
(speed == ELINK_SPEED_10))) {
/* For speeds less than 10G LED scheme is different */
port*4, 0);
}
#endif // ELINK_AUX_POWER
break;
default:
mode);
break;
}
return rc;
}
#endif // EXCLUDE_NON_COMMON_INIT
#ifdef ELINK_ENHANCEMENTS
/* This function comes to reflect the actual link state read DIRECTLY from the
* HW
*/
{
#ifdef ELINK_INCLUDE_FPGA
return ELINK_STATUS_OK;
#endif /* ELINK_INCLUDE_FPGA */
#ifdef ELINK_INCLUDE_EMUL
return ELINK_STATUS_OK;
#endif /* ELINK_INCLUDE_EMUL */
> ELINK_SPEED_10000) {
/* Check 20G link */
1, &link_up);
1, &link_up);
} else {
/* Check 10G link and below*/
&gp_status);
}
if (!link_up)
return ELINK_STATUS_NO_LINK;
} else {
&gp_status);
/* Link is up only if both local phy and external phy are up */
return ELINK_STATUS_NO_LINK;
}
/* In XGXS loopback mode, do not check external PHY */
return ELINK_STATUS_OK;
case 1:
/* No external PHY */
return ELINK_STATUS_OK;
case 2:
break;
case 3: /* Dual Media */
phy_index++) {
if (is_serdes != serdes_phy_type)
continue;
}
}
break;
}
if (ext_phy_link_up)
return ELINK_STATUS_OK;
return ELINK_STATUS_NO_LINK;
}
#endif // ELINK_ENHANCEMENT
#ifndef EXCLUDE_NON_COMMON_INIT
struct elink_vars *vars)
{
/* In case of external phy existence, the line speed would be the
* line speed linked up by the external phy. In case it is direct
* only, then the line_speed during initialization will be
* equal to the req_line_speed
*/
/* Initialize the internal phy in case this is a direct board
* (no external phys), or this board has external phy which requires
* to first.
*/
#ifndef EXCLUDE_XGXS
#endif // EXCLUDE_XGXS
/* init ext phy and enable link state int */
if (non_ext_phy ||
#ifndef EXCLUDE_XGXS
#endif // EXCLUDE_XGXS
}
/* Re-read this value in case it was changed inside config_init due to
* limitations of optic module
*/
/* Init external phy*/
if (non_ext_phy) {
} else {
phy_index++) {
/* No need to initialize second phy in case of first
* phy only selection. In case of second phy, we do
* need to initialize the first phy, since they are
* connected.
*/
if (phy_index == ELINK_EXT_PHY2 &&
"Not initializing second phy\n");
continue;
}
}
}
/* Reset the interrupt indication after phy was initialized */
return ELINK_STATUS_OK;
}
#ifndef EXCLUDE_XGXS
struct elink_params *params)
{
#ifndef EXCLUDE_LINK_RESET
#endif // EXCLUDE_LINK_RESET
}
#endif // EXCLUDE_XGXS
#if (!defined ELINK_EMUL_ONLY) && ((!defined EXCLUDE_BCM87x6) || (!defined EXCLUDE_SFX7101) || (!defined EXCLUDE_BCM8705))
struct elink_params *params)
{
#ifndef EXCLUDE_LINK_RESET
/* HW reset */
else
#endif /* EXCLUDE_LINK_RESET */
}
#endif /* ELINK_EMUL_ONLY */
struct elink_vars *vars)
{
/* Indicate no mac active */
/* Update shared memory */
vars->line_speed = 0;
/* Activate nig drain */
/* Disable emac */
#if !defined(EXCLUDE_BMAC2) && !defined(EXCLUDE_BMAC1)
#endif // #if !defined(EXCLUDE_BMAC2) && !defined(EXCLUDE_BMAC1)
#ifndef EXCLUDE_WARPCORE
/* Prevent LPI Generation by chip */
0);
0);
}
#endif // EXCLUDE_WARPCORE
return ELINK_STATUS_OK;
}
struct elink_vars *vars,
{
vars->link_status |=
vars->link_status |=
#ifndef EXCLUDE_WARPCORE
if (link_10g) {
}
} else
}
}
#endif // EXCLUDE_WARPCORE
#ifndef EXCLUDE_XGXS
if (link_10g) {
}
} else {
/* AN complete? */
if ((vars->link_status &
}
}
#endif // EXCLUDE_XGXS
#ifndef ELINK_AUX_POWER
/* PBF - link up */
vars->line_speed);
#endif /* ELINK_AUX_POWER */
/* Disable drain */
/* Update shared memory */
#ifndef EXCLUDE_WARPCORE
#endif /* #ifndef EXCLUDE_WARPCORE */
/* Check remote fault */
break;
}
}
return rc;
}
{
/* Verify the link_change_count is supported by the MFW */
return;
if (clear)
val = 0;
else
}
/* The elink_link_update function should be called upon link
* interrupt.
* Link is considered up as follows:
* - DIRECT_SINGLE_MEDIA - Only XGXS link (internal link) needs
* to be up
* - SINGLE_MEDIA - The link between the 577xx and the external
* phy (XGXS) need to up as well as the external link of the
* phy (PHY_EXT1)
* - DUAL_MEDIA - The link between the 577xx and the first
* external phy needs to be up, and at least one of the 2
* external phy link must be up.
*/
{
phy_index++) {
/* different consideration, since vars holds inner state */
}
/* Disable emac */
/* Step 1:
* Check external link change only for external phys, and apply
* priority selection between them in case the link on both phys
* is up. Note that instead of the common vars, a temporary
* vars argument is used since each phy may have different link/
*/
phy_index++) {
if (!phy->read_status)
continue;
/* Read link status and params of this ext phy */
if (cur_link_up) {
} else {
continue;
}
if (!ext_phy_link_up) {
ext_phy_link_up = 1;
} else {
switch (elink_phy_selection(params)) {
/* In this option, the first PHY makes sure to pass the
* traffic through itself only.
* Its not clear how to reset the link on the second phy
*/
break;
/* In this option, the first PHY makes sure to pass the
* traffic through the second PHY.
*/
break;
default:
/* Link indication on both PHYs with the following cases
* is invalid:
* - FIRST_PHY means that second phy wasn't initialized,
* hence its link is expected to be down
* - SECOND_PHY means that first phy should not be able
* to link up by itself (using configuration)
* - DEFAULT should be overriden during initialiazation
*/
"mpc=0x%x. DISABLING LINK !!!\n",
ext_phy_link_up = 0;
break;
}
}
}
/* Step 2:
* Read the status of the internal phy. In case of
* DIRECT_SINGLE_MEDIA board, this link is the external link,
* otherwise this is the link between the 577xx and the first
* external phy
*/
/* The INT_PHY flow control reside in the vars. This include the
* case where the speed or flow control are not set to AUTO.
* Otherwise, the active external phy flow control result is set
* to the vars. The ext_phy_line_speed is needed to check if the
* speed is different between the internal phy and external phy.
* This case may be result of intermediate link speed change.
*/
if (active_external_phy > ELINK_INT_PHY) {
/* Link speed is taken from the XGXS. AN and FC result from
* the external phy.
*/
/* if active_external_phy is first PHY and link is up - disable
* disable TX on second external PHY
*/
if (active_external_phy == ELINK_EXT_PHY1) {
"Disabling TX on EXT_PHY2\n");
}
}
else
}
phy_index++) {
phy_index ==
break;
}
}
/* Upon link speed change set the NIG into drain mode. Comes to
* deals with possible FIFO glitch due to clk change when speed
* is decreased without link down indicator
*/
if (vars->phy_link_up) {
" different than the external"
vars->phy_link_up = 0;
0);
}
}
/* Anything 10 and over uses the bmac */
/* In case external phy link is up, and internal link is down
* (not initialized yet probably after link initialization, it
* needs to be initialized.
* Note that after link down-up as result of cable plug, the xgxs
* link would probably become up again without the need
* initialize it
*/
if (!(ELINK_SINGLE_MEDIA_DIRECT(params))) {
" init_preceding = %d\n", ext_phy_link_up,
else
vars);
}
}
/* Link is up only if both local phy and external phy (in case of
* non-direct board) are up and no fault detected on active PHY.
*/
(ext_phy_link_up ||
/* Update the PFC configuration in case it was changed */
else
else
#ifndef ELINK_AUX_POWER
/* Update MCP link status was changed */
#endif // ELINK_AUX_POWER
return rc;
}
#endif // EXCLUDE_NON_COMMON_INIT
#ifndef ELINK_EMUL_ONLY
/*****************************************************************************/
/* External Phy section */
/*****************************************************************************/
{
}
#if !defined(EXCLUDE_BCM8727_BCM8073) || !defined(EXCLUDE_SFX7101) || !defined(EXCLUDE_BCM8481) || !defined(EXCLUDE_BCM84833) || !defined(EXCLUDE_SFX7101) || !defined(EXCLUDE_BCM8705) || !defined(EXCLUDE_BCM87x6)
{
if (ver_addr)
}
#if (!defined EXCLUDE_XGXS) && (!defined EXCLUDE_COMMON_INIT)
{
}
#endif // EXCLUDE_XGXS
#ifndef EXCLUDE_NON_COMMON_INIT
struct elink_vars *vars)
{
if ((val & (1<<0)) == 0)
}
#endif // #ifndef EXCLUDE_NON_COMMON_INIT
#endif // #if !defined(EXCLUDE_BCM8727_BCM8073) || !defined(EXCLUDE_BCM8481) || !defined(EXCLUDE_BCM84833) || !defined(EXCLUDE_SFX7101)
/******************************************************************/
/******************************************************************/
#ifndef EXCLUDE_BCM8727_BCM8073
#ifndef EXCLUDE_NON_COMMON_INIT
struct elink_params *params,
struct elink_vars *vars)
{
return;
}
pause_result = (ld_pause &
pause_result |= (lp_pause &
}
}
#endif // EXCLUDE_NON_COMMON_INIT
#ifndef EXCLUDE_COMMON_INIT
{
/* Boot port from external ROM */
/* EDC grst */
0x0001);
/* Ucode reboot and rst */
0x008c);
MDIO_PMA_REG_MISC_CTRL1, 0x0001);
/* Reset internal microprocessor */
/* Release srst bit */
/* Delay 100ms per the PHY specifications */
/* 8073 sometimes taking longer to download */
do {
count++;
if (count > 300) {
"elink_8073_8727_external_rom_boot port %x:"
"Download failed. fw version = 0x%x\n",
break;
}
/* Clear ser_boot_ctl bit */
MDIO_PMA_REG_MISC_CTRL1, 0x0000);
"elink_8073_8727_external_rom_boot port %x:"
"Download complete. fw version = 0x%x\n",
return rc;
}
#endif // EXCLUDE_COMMON_INIT
/******************************************************************/
/* BCM8073 PHY SECTION */
/******************************************************************/
#ifndef EXCLUDE_NON_COMMON_INIT
{
/* This is only required for 8073A1, version 102 only */
/* Read 8073 HW revision*/
if (val != 1) {
/* No need to workaround in 8073 A1 */
return ELINK_STATUS_OK;
}
/* SNR should be applied only for version 0x102 */
if (val != 0x102)
return ELINK_STATUS_OK;
return 1;
}
{
if (val > 0) {
/* No need to workaround in 8073 A1 */
return ELINK_STATUS_OK;
}
/* XAUI workaround in 8073 A0: */
/* After loading the boot ROM and restarting Autoneg, poll
* Dev1, Reg $C820:
*/
&val);
/* If bit [14] = 0 or bit [13] = 0, continue on with
* system initialization (XAUI work-around not required, as
* these bits indicate 2.5G or 1G link up).
*/
return ELINK_STATUS_OK;
/* If bit 15 is 0, then poll Dev1, Reg $C841 until it's
* MSB (bit15) goes to 1 (indicating that the XAUI
* workaround has completed), then continue on with
* system initialization.
*/
"XAUI workaround has completed\n");
return ELINK_STATUS_OK;
}
}
break;
}
}
return ELINK_STATUS_ERROR;
}
#ifdef ELINK_INCLUDE_LOOPBACK
{
/* Force KR or KX */
}
#endif // ELINK_INCLUDE_LOOPBACK
struct elink_vars *vars)
{
/* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
}
}
}
"Ext phy AN advertize cl37 0x%x\n", cl37_val);
#ifndef ELINK_AUX_POWER
#endif // ELINK_AUX_POWER
}
struct elink_params *params,
{
switch (action) {
case ELINK_PHY_INIT:
/* Enable LASI */
break;
}
}
struct elink_params *params,
struct elink_vars *vars)
{
else
/* Restore normal power mode*/
/* Swap polarity if required - Must be done only in non-1G mode */
/* Configure the 8073 to swap _P and _N of the KR lines */
}
/* Enable CL37 BAM */
}
#ifdef ELINK_INCLUDE_LOOPBACK
return ELINK_STATUS_OK;
} else {
}
#endif // ELINK_INCLUDE_LOOPBACK
/* Note that 2.5G works only when used with 1G
* advertisement
*/
} else
} else {
val = 0;
if (phy->speed_cap_mask &
/* Note that 2.5G works only when used with 1G advertisement */
if (phy->speed_cap_mask &
}
/* Allow 2.5G for A1 and above */
&phy_ver);
if (phy_ver > 0)
tmp1 |= 1;
else
tmp1 &= 0xfffe;
} else {
tmp1 &= 0xfffe;
}
/* Add support for CL37 (passive mode) II */
0x20 : 0x40)));
/* Add support for CL37 (passive mode) III */
/* The SNR will improve about 2db by changing BW and FEE main
* tap. Rest commands are executed after link is up
* Change FFE main cursor to 5 in EDC register
*/
0xFB0C);
/* Enable FEC (Forware Error Correction) Request in the AN */
/* Restart autoneg */
return ELINK_STATUS_OK;
}
struct elink_params *params,
struct elink_vars *vars)
{
/* Clear the interrupt LASI status register */
/* Clear MSG-OUT */
/* Check the LASI */
/* Check the link status */
if (link_up &&
return 0;
}
/* Check the link status on 1.1.2 */
/* The SNR will improve about 2dbby changing the BW and FEE main
* tap. The 1st write to change FFE main tap is set before
* restart AN. Change PLL Bandwidth in EDC register
*/
0x26BC);
/* Change CDR Bandwidth in EDC register */
0x0333);
}
&link_status);
/* Bits 0..2 --> speed detected, bits 13..15--> link is down */
link_up = 1;
link_up = 1;
link_up = 1;
} else {
link_up = 0;
}
if (link_up) {
/* Swap polarity if required */
if (params->lane_config &
/* Configure the 8073 to swap P and N of the KR lines */
/* Set bit 3 to invert Rx in 1G mode and clear this bit
* when it`s in 10G mode.
*/
"the 8073\n");
} else
val1);
}
}
vars->link_status |=
vars->link_status |=
}
return link_up;
}
struct elink_params *params)
{
#ifndef EXCLUDE_LINK_RESET
else
#endif // EXCLUDE_LINK_RESET
}
#endif // EXCLUDE_NON_COMMON_INIT
#endif // EXCLUDE_BCM8727_BCM8073
/******************************************************************/
/* BCM8705 PHY SECTION */
/******************************************************************/
#ifndef EXCLUDE_BCM8705
struct elink_params *params,
struct elink_vars *vars)
{
/* Restore normal power mode*/
/* HW reset */
/* BCM8705 doesn't have microcode, hence the 0 */
return ELINK_STATUS_OK;
}
struct elink_params *params,
struct elink_vars *vars)
{
if (link_up) {
}
return link_up;
}
#endif /* EXCLUDE_BCM8705 */
/******************************************************************/
/* SFP+ module Section */
/******************************************************************/
#ifndef EXCLUDE_NON_COMMON_INIT
#ifndef EXCLUDE_BCM8727_BCM8073
{
/* Disable transmitter only for bootcodes which can enable it afterwards
* (for D3 link)
*/
if (pmd_dis) {
if (params->feature_config_flags &
} else {
return;
}
} else
}
#endif // EXCLUDE_BCM8727_BCM8073
#if !defined(EXCLUDE_BCM87x6) || !defined(EXCLUDE_BCM8727_BCM8073)
{
else
}
{
OFFSETOF(struct shmem_region,
switch (tx_en_mode) {
&val);
if (tx_en)
else
val);
break;
{
if (tx_en)
else
break;
}
default:
break;
}
}
#endif /* !defined(EXCLUDE_BCM87x6) || !defined(EXCLUDE_BCM8727_BCM8073) */
{
#ifdef ELINK_ENHANCEMENTS
#endif // ELINK_ENHANCEMENTS
#ifndef EXCLUDE_WARPCORE
#endif // EXCLUDE_WARPCORE
#ifdef ELINK_ENHANCEMENTS
else
#endif // ELINK_ENHANCEMENTS
#if !defined(EXCLUDE_BCM87x6) || !defined(EXCLUDE_BCM8727_BCM8073)
#endif
}
struct elink_params *params,
{
#ifndef EXCLUDE_BCM87x6
u16 i;
if (byte_cnt > ELINK_SFP_EEPROM_PAGE_SIZE) {
"Reading from eeprom is limited to 0xf\n");
return ELINK_STATUS_ERROR;
}
/* Set the read command byte count */
/* Set the read command address */
addr);
/* Activate read command */
0x2c0f);
/* Wait up to 500us for command complete status */
for (i = 0; i < 100; i++) {
if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
break;
}
if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) !=
"Got bad status 0x%x when reading from SFP+ EEPROM\n",
return ELINK_STATUS_ERROR;
}
/* Read the buffer */
for (i = 0; i < byte_cnt; i++) {
}
for (i = 0; i < 100; i++) {
if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
return ELINK_STATUS_OK;
}
#endif // EXCLUDE_BCM87x6
return ELINK_STATUS_ERROR;
}
#ifndef EXCLUDE_WARPCORE
#ifndef EXCLUDE_NON_COMMON_INIT
{
OFFSETOF(struct shmem_region,
if (pin_cfg == PIN_CFG_NA)
return;
/* Low ==> corresponding SFP+ module is powered
* high ==> the SFP+ module is powered down
*/
}
#endif
struct elink_params *params,
{
if (byte_cnt > ELINK_SFP_EEPROM_PAGE_SIZE) {
"Reading from eeprom is limited to 16 bytes\n");
return ELINK_STATUS_ERROR;
}
/* 4 byte aligned address */
do {
/* Note that 100us are not enough here */
}
if (rc == ELINK_STATUS_OK) {
j++;
}
}
return rc;
}
#endif /* EXCLUDE_WARPCORE */
#ifndef EXCLUDE_BCM8727_BCM8073
struct elink_params *params,
{
if (byte_cnt > ELINK_SFP_EEPROM_PAGE_SIZE) {
"Reading from eeprom is limited to 0xf\n");
return ELINK_STATUS_ERROR;
}
/* Set 2-wire transfer rate of SFP+ module EEPROM
* to 100Khz since some DACs(direct attached cables) do
* not work at 400Khz.
*/
/* Need to read from 1.8000 to clear it */
&val);
/* Set the read command byte count */
/* Set the read command address */
addr);
/* Set the destination address */
0x8004,
/* Activate read command */
0x8002);
/* Wait appropriate time for two-wire command to finish before
* polling the status register
*/
/* Wait up to 500us for command complete status */
for (i = 0; i < 100; i++) {
if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
break;
}
if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) !=
"Got bad status 0x%x when reading from SFP+ EEPROM\n",
return ELINK_STATUS_TIMEOUT;
}
/* Read the buffer */
for (i = 0; i < byte_cnt; i++) {
}
for (i = 0; i < 100; i++) {
if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
return ELINK_STATUS_OK;
}
return ELINK_STATUS_ERROR;
}
#endif /* EXCLUDE_BCM8727_BCM8073 */
#endif /* #ifndef EXCLUDE_NON_COMMON_INIT */
#endif /* ELINK_EMUL_ONLY */
#ifndef EXCLUDE_FROM_BNX2X
{
for (i = 0; i < ELINK_SFP_EEPROM_A2_CHECKSUM_RANGE; i++)
checksum += sfp_a2_buf[i];
return ELINK_STATUS_OK;
return ELINK_STATUS_ERROR;
}
#endif
#ifndef EXCLUDE_NON_COMMON_INIT
{
#ifdef ELINK_DEBUG
#endif
return ELINK_STATUS_ERROR;
}
#ifndef ELINK_EMUL_ONLY
break;
#ifndef EXCLUDE_BCM8727_BCM8073
break;
#endif
#ifndef EXCLUDE_WARPCORE
break;
#endif /* EXCLUDE_WARPCORE */
default:
return ELINK_OP_NOT_SUPPORTED;
}
user_data, 0);
}
#endif /* ELINK_EMUL_ONLY */
return rc;
}
#endif // EXCLUDE_NON_COMMON_INIT
#ifndef ELINK_EMUL_ONLY
#ifndef EXCLUDE_NON_COMMON_INIT
struct elink_params *params,
{
/* First check for copper cable */
0,
return ELINK_STATUS_ERROR;
}
#ifndef EXCLUDE_WARPCORE
#endif
switch (val[ELINK_SFP_EEPROM_CON_TYPE_ADDR]) {
{
/* Check if its active cable (includes SFP+ module)
* of passive cable
*/
if (copper_module_type &
else
check_limiting_mode = 1;
} else {
/* Even in case PASSIVE_DAC indication is not set,
* treat it as a passive DAC cable, since some cables
* don't have this indication.
*/
if (copper_module_type &
"Passive Copper cable detected\n");
} else {
"Unknown copper-cable-type\n");
}
}
break;
}
check_limiting_mode = 1;
/* Module is considered as 1G in case it's NOT compliant with
* any 10G ethernet protocol.
*/
ELINK_SFP_EEPROM_10G_COMP_CODE_LRM_MASK)) == 0) {
#ifndef ELINK_AUX_POWER
#endif
#ifndef ELINK_AUX_POWER
}
elink_cb_event_log(cb, ELINK_LOG_ID_NON_10G_MODULE, gport); //"Warning: Link speed was forced to 1000Mbps."
// " Current SFP module in port %d is not"
// " compliant with 10G Ethernet\n",
#endif
}
/* Some 1G-baseT modules will not link up,
* unless TX_EN is toggled with long delay in
* between.
*/
}
} else {
break;
}
}
}
break;
default:
return ELINK_STATUS_ERROR;
}
OFFSETOF(struct shmem_region,
/* Update media type for non-PMF sync */
break;
}
}
if (check_limiting_mode) {
options) != 0) {
"Failed to read Option field from module EEPROM\n");
return ELINK_STATUS_ERROR;
}
if ((options[0] & ELINK_SFP_EEPROM_OPTIONS_LINEAR_RX_OUT_MASK))
else
}
return ELINK_STATUS_OK;
}
#ifdef ELINK_ENHANCEMENTS
/* This function read the relevant field from the module (SFP+), and verify it
* is compliant with this board
*/
struct elink_params *params)
{
if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
return ELINK_STATUS_OK;
}
if (params->feature_config_flags &
/* Use specific phy request */
} else if (params->feature_config_flags &
/* Use first phy request only in case of non-dual media*/
if (ELINK_DUAL_MEDIA(params)) {
"FW does not support OPT MDL verification\n");
return ELINK_STATUS_ERROR;
}
} else {
/* No support in OPT MDL detection */
"FW does not support OPT MDL verification\n");
return ELINK_STATUS_ERROR;
}
if (fw_resp == FW_MSG_CODE_VRFY_OPT_MDL_SUCCESS) {
return ELINK_STATUS_OK;
}
/* Format the warning message */
(u8 *)vendor_name))
vendor_name[0] = '\0';
else
vendor_pn[0] = '\0';
else
elink_cb_event_log(cb, ELINK_LOG_ID_UNQUAL_IO_MODULE, params->port, vendor_name, vendor_pn); // "Warning: Unqualified SFP+ module detected,"
// " Port %d from %s part number %s\n",
if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) !=
return ELINK_STATUS_ERROR;
}
#endif /* ELINK_ENHANCEMENTS */
#ifndef EXCLUDE_BCM8727_BCM8073
struct elink_params *params)
{
/* Initialization time after hot-plug may take up to 300ms for
* some phys type ( e.g. JDSU )
*/
#ifndef EXCLUDE_WARPCORE
1);
else
#endif
if (rc == 0) {
"SFP+ module initialization took %d ms\n",
timeout * 5);
return ELINK_STATUS_OK;
}
}
return rc;
}
#endif /* EXCLUDE_BCM8727_BCM8073 */
#endif /* #if !defined(EXCLUDE_BCM87x6) || !defined(EXCLUDE_BCM8727_BCM8073) || !defined(EXCLUDE_WARPCORE) */
#ifndef EXCLUDE_BCM8727_BCM8073
u8 is_power_up) {
/* Make sure GPIOs are not using for LED mode */
/* In the GPIO register, bit 4 is use to determine if the GPIOs are
* operating as INPUT or as OUTPUT. Bit 1 is for input, and 0 for
* output
* Bits 0-1 determine the GPIOs value for OUTPUT in case bit 4 val is 0
* Bits 8-9 determine the GPIOs value for INPUT in case bit 4 val is 1
* where the 1st bit is the over-current(only input), and 2nd bit is
* for power( only output )
*
* In case of NOC feature is disabled and power is up, set GPIO control
* as input to enable listening of over-current indication
*/
return;
if (is_power_up)
else
/* Set GPIO control to OUTPUT, and set the power bit
* to according to the is_power_up
*/
val);
}
#endif /* EXCLUDE_BCM8727_BCM8073 */
#ifndef EXCLUDE_BCM87x6
{
if (edc_mode == ELINK_EDC_MODE_LIMITING) {
} else { /* LRM mode ( default )*/
/* Changing to LRM mode takes quite few seconds. So do it only
* if current mode is limiting (default is LRM)
*/
return ELINK_STATUS_OK;
0);
0x128);
0x4008);
0xaaaa);
}
return ELINK_STATUS_OK;
}
#endif /* #ifndef EXCLUDE_BCM87x6 */
#ifndef EXCLUDE_BCM8727_BCM8073
{
&rom_ver2_val);
/* Keep the MSB 8-bits, and set the LSB 8-bits with the edc_mode */
return ELINK_STATUS_OK;
}
struct elink_params *params,
{
switch (action) {
case ELINK_DISABLE_TX:
break;
case ELINK_ENABLE_TX:
break;
case ELINK_PHY_INIT:
(1<<2) | (1<<5));
0);
/* Make MOD_ABS give interrupt on change */
&val);
/* Set 8727 GPIOs to input to allow reading from the 8727 GPIO0
* status which reflect SFP+ module over-current
*/
val);
break;
default:
action);
return;
}
}
#ifdef ELINK_ENHANCEMENTS
{
OFFSETOF(struct shmem_region,
switch (fault_led_gpio) {
return;
{
"pin %x port %x mode %x\n",
}
break;
default:
}
}
#endif /* #ifdef ELINK_ENHANCEMENTS */
#endif // EXCLUDE_BCM8727_BCM8073
#endif // EXCLUDE_NON_COMMON_INIT
#ifdef ELINK_ENHANCEMENTS
{
OFFSETOF(struct shmem_region,
}
{
/* Low ==> if SFP+ module is supported otherwise
* High ==> if SFP+ module is not on the approved vendor list
*/
} else
}
#endif /* #ifdef ELINK_ENHANCEMENTS */
#ifndef EXCLUDE_WARPCORE
#ifndef EXCLUDE_NON_COMMON_INIT
struct elink_params *params)
{
/* Put Warpcore in low power mode */
/* Put LCPLL in low power mode */
}
#endif // #ifndef EXCLUDE_NON_COMMON_INIT
#endif // #ifndef EXCLUDE_WARPCORE
#ifndef EXCLUDE_NON_COMMON_INIT
{
#ifdef ELINK_DEBUG
#endif /* ELINK_DEBUG */
#ifndef EXCLUDE_BCM8727_BCM8073
break;
#endif // EXCLUDE_BCM8727_BCM8073
#ifndef EXCLUDE_WARPCORE
break;
#endif // EXCLUDE_WARPCORE
default:
break;
}
}
#ifndef EXCLUDE_WARPCORE
{
/* This is a global register which controls all lanes */
switch (edc_mode) {
case ELINK_EDC_MODE_LINEAR:
case ELINK_EDC_MODE_LIMITING:
break;
break;
default:
break;
}
/* A must read */
/* Restart microcode to re-read the new mode */
}
#endif // EXCLUDE_WARPCORE
{
#ifndef EXCLUDE_BCM87x6
break;
#endif /* #ifndef EXCLUDE_BCM87x6 */
#ifndef EXCLUDE_BCM8727_BCM8073
break;
#endif // EXCLUDE_BCM8727_BCM8073
#ifndef EXCLUDE_WARPCORE
break;
#endif // EXCLUDE_WARPCORE
}
}
struct elink_params *params)
{
/* Enabled transmitter by default */
/* Power up module */
return ELINK_STATUS_ERROR;
#ifdef ELINK_ENHANCEMENTS
/* Check SFP+ module compatibility */
/* Turn on fault module-detected led */
/* Check if need to power down the SFP+ module */
if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
return rc;
}
} else {
/* Turn off fault module-detected led */
#endif // ELINK_ENHANCEMENTS
}
/* Check and set limiting mode / LRM mode on 8726. On 8727 it
* is done automatically
*/
/* Disable transmit for this module if the module is not approved, and
* laser needs to be disabled.
*/
if ((rc != 0) &&
return rc;
}
#endif // EXCLUDE_NON_COMMON_INIT
#ifdef ELINK_ENHANCEMENTS
{
/* Always enable TX laser,will be disabled in case of fault */
} else {
}
return;
}
/* Set valid module led off */
/* Get current gpio val reflecting module plugged in / out*/
/* Call the handling function in case module is detected */
if (gpio_val == 0) {
#ifdef ELINK_AUX_POWER
#endif
/* In case WC is out of reset, reconfigure the
* link speed while taking into account 1G
* module limitation.
*/
if ((!rx_tx_in_reset) &&
(params->link_flags &
}
}
} else {
}
} else {
#ifdef ELINK_AUX_POWER
#endif
/* Module was plugged out.
* Disable transmit for this module
*/
}
}
#endif // ELINK_ENHANCEMENTS
/******************************************************************/
/* Used by 8706 and 8727 */
/******************************************************************/
#ifndef EXCLUDE_NON_COMMON_INIT
#if !defined(EXCLUDE_BCM87x6) || !defined(EXCLUDE_BCM8727_BCM8073)
{
&alarm_status);
&alarm_status);
/* Mask or enable the fault event. */
if (alarm_status & (1<<0))
val &= ~(1<<0);
else
val |= (1<<0);
}
#endif // #if !defined(EXCLUDE_BCM87x6) || !defined(EXCLUDE_BCM8727_BCM8073
/******************************************************************/
/******************************************************************/
#ifndef EXCLUDE_BCM87x6
struct elink_params *params,
struct elink_vars *vars)
{
/* Clear RX Alarm*/
/* Clear LASI indication*/
/* Link is up if both bit 0 of pmd_rx_sd and bit 0 of pcs_status
* are set, or if the autoneg bit 1 is set
*/
if (link_up) {
else
}
/* Capture 10G link fault. Read twice to clear stale value. */
if (val1 & (1<<0))
}
return link_up;
}
/******************************************************************/
/* BCM8706 PHY SECTION */
/******************************************************************/
struct elink_params *params,
struct elink_vars *vars)
{
/* HW reset */
/* Wait until fw is loaded */
if (val)
break;
}
if ((params->feature_config_flags &
u8 i;
for (i = 0; i < 4; i++) {
/* Clear first 3 bits of the control */
val &= ~0x7;
/* Set control bits according to configuration */
}
}
/* Force speed */
MDIO_PMA_REG_DIGITAL_CTRL, 0x400);
0);
/* Arm LASI for link and Tx fault. */
} else {
/* Force 1Gbps using autoneg with 1G advertisement */
/* Allow CL37 through CL73 */
/* Enable Full-Duplex advertisement on CL37 */
/* Enable CL37 AN */
/* 1G support */
/* Enable clause 73 AN */
0x0400);
0x0004);
}
/* If TX Laser is controlled by GPIO_0, do not let PHY go into low
* power mode, if TX Laser is disabled
*/
OFFSETOF(struct shmem_region,
if (tx_en_mode == PORT_HW_CFG_TX_LASER_GPIO0) {
tmp1 |= 0x1;
}
return ELINK_STATUS_OK;
}
struct elink_params *params,
struct elink_vars *vars)
{
}
/******************************************************************/
/* BCM8726 PHY SECTION */
/******************************************************************/
struct elink_params *params)
{
}
struct elink_params *params)
{
/* Need to wait 100ms after reset */
/* Micro controller re-boot */
/* Set soft reset */
MDIO_PMA_REG_MISC_CTRL1, 0x0001);
/* Wait for 150ms for microcode load */
/* Disable serial boot control, tristates pins SS_N, SCK, MOSI, MISO */
MDIO_PMA_REG_MISC_CTRL1, 0x0000);
}
struct elink_params *params,
struct elink_vars *vars)
{
if (link_up) {
&val1);
link_up = 0;
vars->line_speed = 0;
}
}
return link_up;
}
struct elink_params *params,
struct elink_vars *vars)
{
/* Need to call module detected on initialization since the module
* detection triggered by actual module insertion might occur before
* driver is loaded, and when driver is loaded, it reset all
* registers, including the transmitter
*/
0x400);
(phy->speed_cap_mask &
((phy->speed_cap_mask &
/* Set Flow control */
/* Enable RX-ALARM control to receive interrupt for 1G speed
* change
*/
0x400);
} else { /* Default 10G. Set only LASI control */
}
/* Set TX PreEmphasis if needed */
if ((params->feature_config_flags &
"Setting TX_CTRL1 0x%x, TX_CTRL2 0x%x\n",
phy->tx_preemphasis[0],
phy->tx_preemphasis[0]);
}
return ELINK_STATUS_OK;
}
struct elink_params *params)
{
#ifndef EXCLUDE_LINK_RESET
/* Set serial boot control for external load */
MDIO_PMA_REG_GEN_CTRL, 0x0001);
#endif // EXCLUDE_LINK_RESET
}
#endif /* #ifndef EXCLUDE_BCM87x6 */
/******************************************************************/
/* BCM8727 PHY SECTION */
/******************************************************************/
#ifndef EXCLUDE_BCM8727_BCM8073
{
/* Only NOC flavor requires to set the LED specifically */
return;
switch (mode) {
case ELINK_LED_MODE_OFF:
led_mode_bitmask = 0;
gpio_pins_bitmask = 0x03;
break;
case ELINK_LED_MODE_ON:
led_mode_bitmask = 0;
gpio_pins_bitmask = 0x02;
break;
case ELINK_LED_MODE_OPER:
led_mode_bitmask = 0x60;
gpio_pins_bitmask = 0x11;
break;
}
&val);
val &= 0xff8f;
val |= led_mode_bitmask;
val);
&val);
val &= 0xffe0;
val |= gpio_pins_bitmask;
val);
}
struct elink_params *params) {
/* The PHY reset is controlled by GPIO 1. Fake the port number
* to cancel the swap done in set_gpio()
*/
}
struct elink_params *params)
{
/* Set option 1G speed */
/* Power down the XAUI until link is up in case of dual-media
* and 1G
*/
if (ELINK_DUAL_MEDIA(params)) {
}
((phy->speed_cap_mask &
((phy->speed_cap_mask &
} else {
/* Since the 8727 has only single reset pin, need to set the 10G
* registers although it is default
*/
0x0020);
0x0008);
}
}
struct elink_params *params,
struct elink_vars *vars)
{
/* Enable PMD link, MOD_ABS_FLT, and 1G link alarm */
/* Initially configure MOD_ABS to interrupt when module is
* presence( bit 8)
*/
/* Set EDC off by setting OPTXLOS signal input to low (bit 9).
* When the EDC is off it locks onto a reference clock and avoids
* becoming 'lost'
*/
/* Set TX PreEmphasis if needed */
if ((params->feature_config_flags &
phy->tx_preemphasis[0],
phy->tx_preemphasis[0]);
}
/* If TX Laser is controlled by GPIO_0, do not let PHY go into low
* power mode, if TX Laser is disabled
*/
OFFSETOF(struct shmem_region,
if (tx_en_mode == PORT_HW_CFG_TX_LASER_GPIO0) {
tmp2 |= 0x1000;
tmp2 &= 0xFFEF;
&tmp2);
(tmp2 & 0x7fff));
}
return ELINK_STATUS_OK;
}
struct elink_params *params)
{
config));
/* Module is absent */
"MOD_ABS indication show module is absent\n");
/* 1. Set mod_abs to detect next module
* presence event
* 2. Set EDC off by setting OPTXLOS signal input to low
* (bit 9).
* When the EDC is off it locks onto a reference clock and
* avoids becoming 'lost'.
*/
/* Clear RX alarm since it stays up as long as
* the mod_abs wasn't changed
*/
} else {
/* Module is present */
"MOD_ABS indication show module is present\n");
/* First disable transmitter, and if the module is ok, the
* module_detection will enable it
* 1. Set mod_abs to detect next module absent event ( bit 8)
* 2. Restore the default polarity of the OPRXLOS signal and
* this signal will then correctly indicate the presence or
* absence of the Rx signal. (bit 9)
*/
/* Clear RX alarm since it stays up as long as the mod_abs
* wasn't changed. This is need to be done before calling the
* module detection, otherwise it will clear* the link update
* alarm
*/
if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
else
/* Reconfigure link speed based on module type limitations */
}
}
struct elink_params *params,
struct elink_vars *vars)
{
/* If PHY is not initialized, do not check link status */
&lasi_ctrl);
if (!lasi_ctrl)
return 0;
/* Check the LASI on Rx */
vars->line_speed = 0;
/* Clear MSG-OUT */
/* If a module is present and there is need to check
* for over current
*/
/* Check over-current using 8727 GPIO0 input*/
&val1);
#ifndef ELINK_AUX_POWER
"8727 Power fault has been detected on port %d\n",
oc_port);
// "been detected and the power to "
// "that SFP+ module has been removed "
// "to prevent failure of the card. "
// "Please remove the SFP+ module and "
// "restart the system to clear this "
// "error.\n",
#endif
/* Disable all RX_ALARMs except for mod_abs */
/* Wait for module_absent_event */
/* Clear RX alarm */
return 0;
}
} /* Over current check */
/* When module absent bit is set, check module */
/* Enable all mod_abs and link detection bits */
((1<<5) | (1<<2)));
}
} else {
return 0;
}
/* Bits 0..2 --> speed detected,
* Bits 13..15--> link is down
*/
link_up = 1;
link_up = 1;
} else {
link_up = 0;
}
/* Capture 10G link fault. */
if (val1 & (1<<0)) {
}
}
if (link_up) {
}
if ((ELINK_DUAL_MEDIA(params)) &&
/* In case of dual-media board and 1G, power up the XAUI side,
* otherwise power it down. For 10G it is done automatically
*/
if (link_up)
else
}
return link_up;
}
struct elink_params *params)
{
#ifndef EXCLUDE_LINK_RESET
/* Disable Transmitter */
/* Clear LASI */
#endif // EXCLUDE_LINK_RESET
}
#endif /* EXCLUDE_BCM8727_BCM8073 */
#endif // EXCLUDE_NON_COMMON_INIT
/******************************************************************/
/******************************************************************/
#if !defined(EXCLUDE_BCM8481) || !defined(EXCLUDE_BCM84833)
{
#ifndef EXCLUDE_BCM8481
};
#endif
} else {
#ifndef EXCLUDE_BCM8481
/* For 32-bit registers in 848xx, access via MDIO2ARM i/f. */
/* (1) set reg 0xc200_0014(SPI_BRIDGE_CTRL_2) to 0x03000000 */
for (i = 0; i < ARRAY_SIZE(reg_set); i++)
if (val & 1)
break;
}
if (cnt == 100) {
"phy fw version(1)\n");
return;
}
/* 2) read register 0xc200_0000 (SPI_FW_STATUS) */
if (val & 1)
break;
}
if (cnt == 100) {
"version(2)\n");
return;
}
/* lower 16 bits of the register SPI_FW_STATUS */
/* upper 16 bits of register SPI_FW_STATUS */
#endif /* EXCLUDE_BCM8481 */
}
}
#ifndef EXCLUDE_NON_COMMON_INIT
{
};
/* PHYC_CTL_LED_CTL */
val &= 0xFE00;
val |= 0x0092;
for (i = 0; i < ARRAY_SIZE(reg_set); i++)
else
/* stretch_en for LED3*/
}
struct elink_params *params,
{
switch (action) {
case ELINK_PHY_INIT:
/* Save spirom version */
}
/* This phy uses the NIG latch mechanism since link indication
* arrives through its LED4 and not via its LASI signal, so we
* get steady signal instead of clear on read
*/
break;
}
}
struct elink_params *params,
struct elink_vars *vars)
{
/* set 1000 speed advertisement */
&an_1000_val);
&autoneg_val);
/* Disable forced speed */
(phy->speed_cap_mask &
} else
/* Set 10/100 speed advertisement */
if (phy->speed_cap_mask &
/* Enable autoneg and restart autoneg for legacy speeds
*/
}
if (phy->speed_cap_mask &
/* Enable autoneg and restart autoneg for legacy speeds
*/
}
if ((phy->speed_cap_mask &
}
if ((phy->speed_cap_mask &
}
}
/* Only 10/100 are allowed to work in FORCE mode */
/* Enabled AUTO-MDIX when autoneg is disabled */
(1<<15 | 1<<9 | 7<<0));
/* The PHY needs this set even for forced link. */
}
/* Enabled AUTO-MDIX when autoneg is disabled */
(1<<15 | 1<<9 | 7<<0));
}
/* Always write this if this is not 84833/4.
* For 84833/4, write it only when it's a forced speed.
*/
(phy->speed_cap_mask &
/* Restart autoneg for 10G*/
0x1000);
0x3200);
} else
1);
return ELINK_STATUS_OK;
}
#endif // EXCLUDE_NON_COMMON_INIT
#endif // #if !defined(EXCLUDE_BCM8481) || !defined(EXCLUDE_BCM84833)
#ifndef EXCLUDE_BCM8481
#ifndef EXCLUDE_NON_COMMON_INIT
struct elink_params *params,
struct elink_vars *vars)
{
/* Restore normal power mode*/
/* HW reset */
}
#endif // #ifndef EXCLUDE_NON_COMMON_INIT
#endif // EXCLUDE_BCM8481
#ifndef EXCLUDE_BCM84833
{
int idx;
/* Write CMD_OPEN_OVERRIDE to STATUS reg */
if (val == PHY84833_STATUS_CMD_OPEN_FOR_CMDS)
break;
}
if (idx >= PHY84833_CMDHDLR_WAIT) {
return ELINK_STATUS_ERROR;
}
/* Prepare argument(s) and issue command */
}
if ((val == PHY84833_STATUS_CMD_COMPLETE_PASS) ||
break;
}
if ((idx >= PHY84833_CMDHDLR_WAIT) ||
return ELINK_STATUS_ERROR;
}
/* Gather returning data */
}
return ELINK_STATUS_OK;
}
#ifndef EXCLUDE_NON_COMMON_INIT
struct elink_params *params,
struct elink_vars *vars)
{
/* Check for configuration. */
OFFSETOF(struct shmem_region,
if (pair_swap == 0)
return ELINK_STATUS_OK;
/* Only the second argument is used for this command */
if (status == ELINK_STATUS_OK)
return status;
}
#endif // #ifndef EXCLUDE_NON_COMMON_INIT
{
if (CHIP_IS_E3(chip_id)) {
/* Assume that these will be GPIOs, not EPIOs. */
/* Map config param to register bit. */
OFFSETOF(struct shmem_region,
}
} else {
/* E2, look from diff place of shmem. */
OFFSETOF(struct shmem_region,
}
}
return reset_gpios;
}
#ifndef EXCLUDE_NON_COMMON_INIT
struct elink_params *params)
{
OFFSETOF(struct shmem2_region,
/* Work around for 84833 LED failure inside RESET status */
#ifndef EDEBUG
#endif // EDEBUG
return ELINK_STATUS_OK;
}
#endif // EXCLUDE_NON_COMMON_INIT
#endif // #ifndef EXCLUDE_BCM84833
#ifndef EXCLUDE_NON_COMMON_INIT
#ifndef EXCLUDE_WARPCORE
struct elink_params *params,
struct elink_vars *vars)
{
#if defined(ELINK_DEBUG)
#endif
/* Prevent Phy from working in EEE and advertising it */
if (rc != ELINK_STATUS_OK) {
return rc;
}
}
struct elink_params *params,
struct elink_vars *vars)
{
#ifdef ELINK_DEBUG
#endif
if (rc != ELINK_STATUS_OK) {
return rc;
}
}
#endif /* #ifndef EXCLUDE_WARPCORE */
#if !defined(EXCLUDE_BCM8481) || !defined(EXCLUDE_BCM84833)
struct elink_params *params,
struct elink_vars *vars)
{
#ifndef EXCLUDE_BCM84833
#endif // EXCLUDE_BCM84833
else
port);
} else {
/* MDIO reset */
MDIO_PMA_REG_CTRL, 0x8000);
}
/* Wait for GPHY to come out of reset */
#ifndef EXCLUDE_BCM84833
#endif // EXCLUDE_BCM84833
#ifndef EXCLUDE_BCM8481
/* BCM84823 requires that XGXS links up first @ 10G for normal
* behavior.
*/
#endif // EXCLUDE_BCM8481
#ifndef EXCLUDE_BCM84833
}
#endif /* Set dual-media configuration according to configuration */
} else {
}
switch (actual_phy_selection) {
/* Do nothing. Essentially this is like the priority copper */
break;
break;
break;
/* Do nothing here. The first PHY won't be initialized at all */
break;
initialize = 0;
break;
}
#ifndef EXCLUDE_BCM84833
/* Keep AutogrEEEn disabled. */
cmd_args[0] = 0x0;
if (rc != ELINK_STATUS_OK)
}
#endif // #ifndef EXCLUDE_BCM84833
if (initialize)
#ifdef ELINK_ENHANCEMENTS
else
#endif // ELINK_ENHANCEMENTS
/* 84833 PHY has a better feature and doesn't need to support this. */
#ifndef EXCLUDE_BCM8481
OFFSETOF(struct shmem_region,
if (cms_enable)
else
}
#endif /* EXCLUDE_BCM8481 */
#ifndef EXCLUDE_WARPCORE
/* Configure EEE support */
if ((val >= MDIO_84833_TOP_CFG_FW_EEE) &&
(val != MDIO_84833_TOP_CFG_FW_NO_EEE) &&
if (rc != ELINK_STATUS_OK) {
return rc;
}
else
if (rc != ELINK_STATUS_OK) {
return rc;
}
} else {
}
#endif /* #ifndef EXCLUDE_WARPCORE */
#ifndef EXCLUDE_BCM84833
/* Bring PHY out of super isolate mode as the final step. */
}
#endif /* #ifndef EXCLUDE_BCM84833 */
return rc;
}
struct elink_params *params,
struct elink_vars *vars)
{
/* Check 10G-BaseT link status */
/* Check PMD signal ok */
&val2);
/* Check link 10G */
link_up = 1;
} else { /* Check Legacy speed link */
/* Enable expansion register 0x42 (Operation mode status) */
/* Get legacy speed operation status */
if (legacy_speed == (0<<9))
else { /* Should not happen: Treat as link down */
vars->line_speed = 0;
link_up = 0;
}
#ifndef BNX2X_UPSTREAM /* ! BNX2X_UPSTREAM */
if (params->feature_config_flags &
&mii_ctrl);
/* For IEEE testing, check for a fake link. */
}
#endif
if (link_up) {
else
"Link is up in %dMbps, is_duplex_full= %d\n",
/* Check legacy speed AN resolution */
&val);
vars->link_status |=
&val);
if ((val & (1<<0)) == 0)
vars->link_status |=
}
}
if (link_up) {
vars->line_speed);
/* Read LP advertised speeds */
vars->link_status |=
vars->link_status |=
vars->link_status |=
vars->link_status |=
vars->link_status |=
vars->link_status |=
vars->link_status |=
vars->link_status |=
#if (!defined EXCLUDE_BCM84833) && (!defined EXCLUDE_WARPCORE)
/* Determine if EEE was negotiated */
#endif /* #ifndef EXCLUDE_WARPCORE */
}
return link_up;
}
{
#ifdef ELINK_ENHANCEMENTS
#endif // ELINK_ENHANCEMENTS
return status;
}
#ifndef EXCLUDE_BCM8481
struct elink_params *params)
{
}
struct elink_params *params)
{
#ifndef EXCLUDE_LINK_RESET
#endif // EXCLUDE_LINK_RESET
}
#endif // #ifndef EXCLUDE_8481
struct elink_params *params)
{
else
port);
} else {
}
}
{
#ifndef ELINK_AUX_POWER
else
#endif
switch (mode) {
case ELINK_LED_MODE_OFF:
/* Set LED masks */
0x0);
0x0);
0x0);
0x0);
} else {
0x0);
}
break;
port);
/* Set LED masks */
0x0);
0x0);
0x0);
0x20);
} else {
0x0);
/* Disable MI_INT interrupt before setting LED4
* source to constant off.
*/
params->link_flags |=
cb,
}
0x0);
}
}
break;
case ELINK_LED_MODE_ON:
/* Set control reg */
&val);
val &= 0x8000;
val |= 0x2492;
val);
/* Set LED masks */
0x0);
0x20);
0x20);
0x0);
} else {
0x20);
/* Disable MI_INT interrupt before setting LED4
* source to constant on.
*/
params->link_flags |=
cb,
}
0x20);
}
}
break;
case ELINK_LED_MODE_OPER:
/* Set control reg */
&val);
if (!((val &
0xa492);
}
/* Set LED masks */
0x10);
0x80);
0x98);
0x40);
} else {
/* EXTPHY2 LED mode indicate that the 100M/1G/10G LED
* sources are all wired through LED1, rather than only
* 10G in other modes.
*/
val);
/* Tell LED3 to blink on source */
&val);
val);
/* Restore LED4 source to external link,
* and re-enable interrupts.
*/
0x40);
if (params->link_flags &
params->link_flags &=
}
}
}
break;
}
/* This is a workaround for E3+84833 until autoneg
* restart is fixed in f/w
*/
}
}
#endif /* EXCLUDE_BCM8481 / EXCLUDE_BCM8481 */
#endif // EXCLUDE_NON_COMMON_INIT
/******************************************************************/
/* 54618SE PHY SECTION */
/******************************************************************/
#if (!defined EXCLUDE_NON_COMMON_INIT) && (!defined EXCLUDE_BCM54618SE)
#ifdef ELINK_AUX_POWER
struct elink_params *params)
{
/* read all advertisement */
/* In case PHY is in reset */
return 1;
0x09,
&an_1000_val);
0x04,
&autoneg_val);
0x19,
/* Check conditions to avoid link reset in case link was
* already initialized and up
*/
if ((an_1000_val & 0x300) &&
(an_10_100_val & 0x1e0) &&
(autoneg_val & 0x1000) &&
return 0;
return 1;
}
#endif // ELINK_AUX_POWER
struct elink_params *params,
{
switch (action) {
case ELINK_PHY_INIT:
/* Configure LED4: set to INTR (0x6). */
/* Accessing shadow register 0xe. */
&temp);
/* Configure INTR based on link status change. */
break;
}
}
struct elink_params *params,
struct elink_vars *vars)
{
#ifdef ELINK_AUX_POWER
link_init_required = 0;
if (link_init_required) {
#endif
/* This works with E3 only, no need to check the chip
* before determining the port.
*/
OFFSETOF(struct shmem_region,
/* Drive pin high to bring the GPHY out of reset. */
/* wait for GPHY to reset */
/* reset phy */
MDIO_PMA_REG_CTRL, 0x8000);
/* Wait for GPHY to reset */
#ifdef ELINK_AUX_POWER
} // If init required
#endif
/* Flip the signal detect polarity (set 0x1c.0x1e[8]). */
&temp);
/* Set up fc */
/* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
#ifdef ELINK_AUX_POWER
if (!link_init_required)
return ELINK_STATUS_OK;
#endif
fc_val = 0;
/* Read all advertisement */
0x09,
&an_1000_val);
0x04,
&autoneg_val);
/* Disable forced speed */
(1<<11));
(phy->speed_cap_mask &
} else
0x09,
0x09,
&an_1000_val);
/* Advertise 10/100 link speed */
if (phy->speed_cap_mask &
}
if (phy->speed_cap_mask &
}
if (phy->speed_cap_mask &
}
if (phy->speed_cap_mask &
}
}
/* Only 10/100 are allowed to work in FORCE mode */
/* Enabled AUTO-MDIX when autoneg is disabled */
0x18,
(1<<15 | 1<<9 | 7<<0));
}
/* Enabled AUTO-MDIX when autoneg is disabled */
0x18,
(1<<15 | 1<<9 | 7<<0));
}
temp &= 0xfffe;
if (rc != ELINK_STATUS_OK) {
/* Need to advertise EEE only when requested,
* and either no LPI assertion was requested,
* or it was requested and a valid timer was set.
* Also notice full duplex is required for EEE.
*/
} else {
}
} else {
/* Handle legacy auto-grEEEn */
if (params->feature_config_flags &
temp = 6;
} else {
temp = 0;
}
}
}
0x04,
an_10_100_val | fc_val);
return ELINK_STATUS_OK;
}
{
#ifdef ELINK_ENHANCEMENTS
&temp);
temp &= 0xff00;
switch (mode) {
case ELINK_LED_MODE_OFF:
temp |= 0x00ee;
break;
case ELINK_LED_MODE_OPER:
temp |= 0x0001;
break;
case ELINK_LED_MODE_ON:
temp |= 0x00ff;
break;
default:
break;
}
return;
#endif // ELINK_ENHANCEMENTS
}
struct elink_params *params)
{
#ifdef ELINK_AUX_POWER
return;
#endif // ELINK_AUX_POWER
/* In case of no EPIO routed to reset the GPHY, put it
* in low power mode.
*/
/* This works with E3 only, no need to check the chip
* before determining the port.
*/
OFFSETOF(struct shmem_region,
/* Drive pin low to put GPHY in reset. */
}
struct elink_params *params,
struct elink_vars *vars)
{
/* Get speed operation status */
/* Read status to clear the PHY interrupt. */
&val);
if (link_up) {
}
/* Omitting 100Base-T4 for now */
} else /* Should not happen */
vars->line_speed = 0;
"Link is up in %dMbps, is_duplex_full= %d\n",
/* Check legacy speed AN resolution */
0x01,
&val);
vars->link_status |=
0x06,
&val);
if ((val & (1<<0)) == 0)
vars->link_status |=
vars->line_speed);
/* Report LP advertised speeds */
vars->link_status |=
vars->link_status |=
vars->link_status |=
vars->link_status |=
vars->link_status |=
vars->link_status |=
vars->link_status |=
}
}
return link_up;
}
struct elink_params *params)
{
#ifdef ELINK_INCLUDE_LOOPBACK
/* mii write 9 [bits set 11 12] */
/* forced 1G and disable autoneg */
/* set val [mii read 0] */
/* set val [expr $val & [bits clear 6 12 13]] */
/* set val [expr $val | [bits set 6 8]] */
/* mii write 0 $val */
/* Set external loopback and Tx using 6dB coding */
/* mii write 0x18 7 */
/* set val [mii read 0x18] */
/* mii write 0x18 [expr $val | [bits set 10 15]] */
/* This register opens the gate for the UMAC despite its name */
/* Maximum Frame Length (RW). Defines a 14-Bit maximum frame
* length used by the MAC receive logic to check frames.
*/
#endif // ELINK_INCLUDE_LOOPBACK
}
#endif // (!defined EXCLUDE_NON_COMMON_INIT) && (!defined EXCLUDE_BCM54618SE)
/******************************************************************/
/* SFX7101 PHY SECTION */
/******************************************************************/
#ifndef EXCLUDE_SFX7101
struct elink_params *params)
{
/* SFX7101_XGXS_TEST1 */
}
struct elink_params *params,
struct elink_vars *vars)
{
/* Restore normal power mode*/
/* HW reset */
/* Restart autoneg */
val |= 0x200;
/* Save spirom version */
return ELINK_STATUS_OK;
}
struct elink_params *params,
struct elink_vars *vars)
{
/* If link is up print the AN outcome of the SFX7101 PHY */
if (link_up) {
&val2);
/* Read LP advertised speeds */
vars->link_status |=
}
return link_up;
}
{
if (*len < 5)
return ELINK_STATUS_ERROR;
*len -= 5;
return ELINK_STATUS_OK;
}
{
/* Writes a self-clearing reset */
/* Wait for clear */
break;
}
}
struct elink_params *params) {
#ifdef ELINK_ENHANCEMENTS
/* Low power mode is controlled by GPIO 2 */
/* The PHY reset is controlled by GPIO 1 */
#endif // ELINK_ENHANCEMENTS
}
{
switch (mode) {
case ELINK_LED_MODE_OFF:
val = 2;
break;
case ELINK_LED_MODE_ON:
val = 1;
break;
case ELINK_LED_MODE_OPER:
val = 0;
break;
}
val);
}
#endif /* EXCLUDE_SFX7101 */
#endif /* ELINK_EMUL_ONLY */
/******************************************************************/
/* STATIC PHY DECLARATION */
/******************************************************************/
/*.type = */PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN,
/*.addr = */0,
/*.def_md_devad = */0,
/*.flags = */ELINK_FLAGS_INIT_XGXS_FIRST,
/*.rx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
/*.tx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
/*.mdio_ctrl = */0,
/*.supported = */0,
/*.media_type = */ELINK_ETH_PHY_NOT_PRESENT,
/*.ver_addr = */0,
/*.req_flow_ctrl = */0,
/*.req_line_speed = */0,
/*.speed_cap_mask = */0,
/*.req_duplex = */0,
/*.rsrv = */0,
};
#ifndef EXCLUDE_SERDES
/*.type = */PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT,
/*.addr = */0xff,
/*.def_md_devad = */0,
/*.flags = */0,
/*.rx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
/*.tx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
/*.mdio_ctrl = */0,
/*.supported = */(ELINK_SUPPORTED_10baseT_Half |
/*.media_type = */ELINK_ETH_PHY_BASE_T,
/*.ver_addr = */0,
/*.req_flow_ctrl = */0,
/*.req_line_speed = */0,
/*.speed_cap_mask = */0,
/*.req_duplex = */0,
/*.rsrv = */0,
};
#endif /* #ifndef EXCLUDE_SERDES */
#ifndef EXCLUDE_XGXS
/*.type = */PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
/*.addr = */0xff,
/*.def_md_devad = */0,
/*.flags = */0,
/*.rx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
/*.tx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
/*.mdio_ctrl = */0,
/*.supported = */(ELINK_SUPPORTED_10baseT_Half |
/*.media_type = */ELINK_ETH_PHY_CX4,
/*.ver_addr = */0,
/*.req_flow_ctrl = */0,
/*.req_line_speed = */0,
/*.speed_cap_mask = */0,
/*.req_duplex = */0,
/*.rsrv = */0,
#ifndef EXCLUDE_NON_COMMON_INIT
#endif
};
#endif
#ifndef EXCLUDE_WARPCORE
/*.type = */PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
/*.addr = */0xff,
/*.def_md_devad = */0,
/*.flags = */ELINK_FLAGS_TX_ERROR_CHECK,
/*.rx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
/*.tx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
/*.mdio_ctrl = */0,
/*.supported = */(ELINK_SUPPORTED_10baseT_Half |
/*.media_type = */ELINK_ETH_PHY_UNSPECIFIED,
/*.ver_addr = */0,
/*.req_flow_ctrl = */0,
/*.req_line_speed = */0,
/*.speed_cap_mask = */0,
/* req_duplex = */0,
/* rsrv = */0,
#ifndef EXCLUDE_NON_COMMON_INIT
#endif
};
#endif /* #ifndef EXCLUDE_WARPCORE */
#ifndef ELINK_EMUL_ONLY
#ifndef EXCLUDE_SFX7101
/*.type = */PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
/*.addr = */0xff,
/*.def_md_devad = */0,
/*.flags = */ELINK_FLAGS_FAN_FAILURE_DET_REQ,
/*.rx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
/*.tx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
/*.mdio_ctrl = */0,
/*.supported = */(ELINK_SUPPORTED_10000baseT_Full |
/*.media_type = */ELINK_ETH_PHY_BASE_T,
/*.ver_addr = */0,
/*.req_flow_ctrl = */0,
/*.req_line_speed = */0,
/*.speed_cap_mask = */0,
/*.req_duplex = */0,
/*.rsrv = */0,
};
#endif /* EXCLUDE_SFX7101 */
#ifndef EXCLUDE_BCM8727_BCM8073
/*.type = */PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
/*.addr = */0xff,
/*.def_md_devad = */0,
/*.flags = */0,
/*.rx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
/*.tx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
/*.mdio_ctrl = */0,
/*.supported = */(ELINK_SUPPORTED_10000baseT_Full |
/*.media_type = */ELINK_ETH_PHY_KR,
/*.ver_addr = */0,
/*.req_flow_ctrl = */0,
/*.req_line_speed = */0,
/*.speed_cap_mask = */0,
/*.req_duplex = */0,
/*.rsrv = */0,
#ifndef EXCLUDE_NON_COMMON_INIT
#endif
};
#endif
#ifndef EXCLUDE_BCM8705
/*.type = */PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705,
/*.addr = */0xff,
/*.def_md_devad = */0,
/*.flags = */ELINK_FLAGS_INIT_XGXS_FIRST,
/*.rx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
/*.tx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
/*.mdio_ctrl = */0,
/*.supported = */(ELINK_SUPPORTED_10000baseT_Full |
/*.media_type = */ELINK_ETH_PHY_XFP_FIBER,
/*.ver_addr = */0,
/*.req_flow_ctrl = */0,
/*.req_line_speed = */0,
/*.speed_cap_mask = */0,
/*.req_duplex = */0,
/*.rsrv = */0,
};
#endif /* EXCLUDE_BCM8705 */
#ifndef EXCLUDE_BCM87x6
/*.type = */PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706,
/*.addr = */0xff,
/*.def_md_devad = */0,
/*.flags = */ELINK_FLAGS_INIT_XGXS_FIRST,
/*.rx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
/*.tx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
/*.mdio_ctrl = */0,
/*.supported = */(ELINK_SUPPORTED_10000baseT_Full |
/*.media_type = */ELINK_ETH_PHY_SFPP_10G_FIBER,
/*.ver_addr = */0,
/*.req_flow_ctrl = */0,
/*.req_line_speed = */0,
/*.speed_cap_mask = */0,
/*.req_duplex = */0,
/*.rsrv = */0,
};
/*.type = */PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
/*.addr = */0xff,
/*.def_md_devad = */0,
/*.flags = */(ELINK_FLAGS_INIT_XGXS_FIRST |
/*.rx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
/*.tx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
/*.mdio_ctrl = */0,
/*.supported = */(ELINK_SUPPORTED_10000baseT_Full |
/*.media_type = */ELINK_ETH_PHY_NOT_PRESENT,
/*.ver_addr = */0,
/*.req_flow_ctrl = */0,
/*.req_line_speed = */0,
/*.speed_cap_mask = */0,
/*.req_duplex = */0,
/*.rsrv = */0,
};
#endif /* #ifndef EXCLUDE_BCM87x6 */
#ifndef EXCLUDE_BCM8727_BCM8073
/*.type = */PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
/*.addr = */0xff,
/*.def_md_devad = */0,
/*.flags = */(ELINK_FLAGS_FAN_FAILURE_DET_REQ |
/*.rx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
/*.tx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
/*.mdio_ctrl = */0,
/*.supported = */(ELINK_SUPPORTED_10000baseT_Full |
/*.media_type = */ELINK_ETH_PHY_NOT_PRESENT,
/*.ver_addr = */0,
/*.req_flow_ctrl = */0,
/*.req_line_speed = */0,
/*.speed_cap_mask = */0,
/*.req_duplex = */0,
/*.rsrv = */0,
#ifndef EXCLUDE_NON_COMMON_INIT
#endif
};
#endif
#ifndef EXCLUDE_BCM8481
/*.type = */PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
/*.addr = */0xff,
/*.def_md_devad = */0,
/*.flags = */ELINK_FLAGS_FAN_FAILURE_DET_REQ |
/*.rx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
/*.tx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
/*.mdio_ctrl = */0,
/*.supported = */(ELINK_SUPPORTED_10baseT_Half |
/*.media_type = */ELINK_ETH_PHY_BASE_T,
/*.ver_addr = */0,
/*.req_flow_ctrl = */0,
/*.req_line_speed = */0,
/*.speed_cap_mask = */0,
/*.req_duplex = */0,
/*.rsrv = */0,
#ifndef EXCLUDE_NON_COMMON_INIT
#endif
};
/*.type = */PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823,
/*.addr = */0xff,
/*.def_md_devad = */0,
/*.flags = */(ELINK_FLAGS_FAN_FAILURE_DET_REQ |
/*.rx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
/*.tx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
/*.mdio_ctrl = */0,
/*.supported = */(ELINK_SUPPORTED_10baseT_Half |
/*.media_type = */ELINK_ETH_PHY_BASE_T,
/*.ver_addr = */0,
/*.req_flow_ctrl = */0,
/*.req_line_speed = */0,
/*.speed_cap_mask = */0,
/*.req_duplex = */0,
/*.rsrv = */0,
#ifndef EXCLUDE_NON_COMMON_INIT
#endif // #ifndef EXCLUDE_NON_COMMON_INIT
};
#endif /* EXCLUDE_BCM8481 */
#ifndef EXCLUDE_BCM84833
/*.type = */PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833,
/*.addr = */0xff,
/*.def_md_devad = */0,
/*.flags = */(ELINK_FLAGS_FAN_FAILURE_DET_REQ |
/*.rx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
/*.tx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
/*.mdio_ctrl = */0,
/*.supported = */(ELINK_SUPPORTED_100baseT_Half |
/*.media_type = */ELINK_ETH_PHY_BASE_T,
/*.ver_addr = */0,
/*.req_flow_ctrl = */0,
/*.req_line_speed = */0,
/*.speed_cap_mask = */0,
/*.req_duplex = */0,
/*.rsrv = */0,
#ifndef EXCLUDE_NON_COMMON_INIT
#endif
};
/*.type = */PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834,
/*.addr = */0xff,
/*.def_md_devad = */0,
/*.flags = */ELINK_FLAGS_FAN_FAILURE_DET_REQ |
/*.rx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
/*.tx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
/*.mdio_ctrl = */0,
/*.supported = */(ELINK_SUPPORTED_100baseT_Half |
/*.media_type = */ELINK_ETH_PHY_BASE_T,
/*.ver_addr = */0,
/*.req_flow_ctrl = */0,
/*.req_line_speed = */0,
/*.speed_cap_mask = */0,
/*.req_duplex = */0,
/*.rsrv = */0,
#ifndef EXCLUDE_NON_COMMON_INIT
#endif
};
#endif // #ifndef EXCLUDE_BCM84833
#ifndef EXCLUDE_BCM54618SE
/*.type = */PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE,
/*.addr = */0xff,
/*.def_md_devad = */0,
/*.flags = */ELINK_FLAGS_INIT_XGXS_FIRST,
/*.rx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
/*.tx_preemphasis = */{0xffff, 0xffff, 0xffff, 0xffff},
/*.mdio_ctrl = */0,
/*.supported = */(ELINK_SUPPORTED_10baseT_Half |
/*.media_type = */ELINK_ETH_PHY_BASE_T,
/*.ver_addr = */0,
/*.req_flow_ctrl = */0,
/*.req_line_speed = */0,
/*.speed_cap_mask = */0,
/* req_duplex = */0,
/* rsrv = */0,
#ifndef EXCLUDE_NON_COMMON_INIT
#endif
};
#endif
#endif /* ELINK_EMUL_ONLY */
/*****************************************************************/
/* */
/* Populate the phy according. Main function: elink_populate_phy */
/* */
/*****************************************************************/
#ifndef EXCLUDE_COMMON_INIT
{
/* Get the 4 lanes xgxs config rx and tx */
for (i = 0; i < 2; i++) {
/* INT_PHY and ELINK_EXT_PHY1 share the same value location in
* the shmem. When num_phys is greater than 1, than this value
* applies only to ELINK_EXT_PHY1
*/
OFFSETOF(struct shmem_region,
OFFSETOF(struct shmem_region,
} else {
OFFSETOF(struct shmem_region,
OFFSETOF(struct shmem_region,
}
}
}
#ifndef ELINK_EMUL_ONLY
{
switch (phy_index) {
case ELINK_EXT_PHY1:
OFFSETOF(struct shmem_region,
break;
case ELINK_EXT_PHY2:
OFFSETOF(struct shmem_region,
break;
default:
return ELINK_STATUS_ERROR;
}
return ext_phy_config;
}
#endif /* ELINK_EMUL_ONLY */
{
OFFSETOF(struct shmem_region,
#ifndef EXCLUDE_WARPCORE
if (ELINK_USES_WARPCORE(chip_id)) {
*phy = phy_warpcore;
else
/* Check Dual mode */
/* Set the appropriate supported and flags indications per
* interface type of the chip
*/
switch (serdes_net_if) {
break;
break;
break;
break;
break;
break;
default:
break;
}
* was not set as expected. For B0, ECO will be enabled so there
* won't be an issue there
*/
else
} else
#endif
{
switch (switch_cfg) {
#ifndef EXCLUDE_SERDES
case ELINK_SWITCH_CFG_1G:
port * 0x10);
*phy = phy_serdes;
break;
#endif /* #ifndef EXCLUDE_SERDES */
#ifndef EXCLUDE_XGXS
case ELINK_SWITCH_CFG_10G:
port * 0x18);
break;
#endif /* EXCLUDE_XGXS */
default:
return ELINK_STATUS_ERROR;
}
}
port);
if (CHIP_IS_E2(chip_id))
else
return ELINK_STATUS_OK;
}
#ifndef ELINK_EMUL_ONLY
{
/* Select the phy type */
switch (phy_type) {
#ifndef EXCLUDE_BCM8727_BCM8073
break;
#endif
#ifndef EXCLUDE_BCM8705
break;
#endif
#ifndef EXCLUDE_BCM87x6
break;
break;
#endif /* EXCLUDE_BCM87x6 */
#ifndef EXCLUDE_BCM8727_BCM8073
/* BCM8727_NOC => BCM8727 no over current */
break;
break;
#endif
#ifndef EXCLUDE_BCM8481
break;
break;
#endif
#ifndef EXCLUDE_BCM84833
break;
break;
#endif
#ifndef EXCLUDE_BCM54618SE
*phy = phy_54618se;
break;
#endif
#ifndef EXCLUDE_SFX7101
break;
#endif
return ELINK_STATUS_ERROR;
default:
/* In case external PHY wasn't found */
if ((phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
return ELINK_STATUS_ERROR;
return ELINK_STATUS_OK;
}
/* The shmem address of the phy version is located on different
* structures. In case this structure is too old, do not set
* the address
*/
if (phy_index == ELINK_EXT_PHY1) {
/* Check specific mdc mdio settings */
} else {
if (size >
OFFSETOF(struct shmem2_region,
}
/* Check specific mdc mdio settings */
mdc_mdio_access = (config2 &
}
/* Remove 100Mb link supported for BCM84833/4 when phy fw
* version lower than or equal to 1.39
*/
}
return ELINK_STATUS_OK;
}
#endif /* ELINK_EMUL_ONLY */
{
if (phy_index == ELINK_INT_PHY)
#ifndef ELINK_EMUL_ONLY
#endif /* ELINK_EMUL_ONLY */
return status;
}
{
/* Populate the default phy configuration for MF mode */
if (phy_index == ELINK_EXT_PHY2) {
OFFSETOF(struct shmem_region,
} else {
OFFSETOF(struct shmem_region,
}
"Default config phy idx %x cfg 0x%x speed_cap_mask 0x%x\n",
switch (link_config & PORT_FEATURE_LINK_SPEED_MASK) {
break;
break;
break;
break;
break;
default:
break;
}
switch (link_config & PORT_FEATURE_FLOW_CONTROL_MASK) {
break;
break;
break;
break;
default:
break;
}
}
#endif /* EXCLUDE_COMMON_INIT */
{
if (phy_config_swapped) {
switch (prio_cfg) {
break;
break;
break;
break;
}
} else
return return_cfg;
}
#ifndef EXCLUDE_COMMON_INIT
{
#ifdef ELINK_INCLUDE_EMUL
return ELINK_STATUS_OK;
#endif
phy_index++) {
if (phy_config_swapped) {
if (phy_index == ELINK_EXT_PHY1)
else if (phy_index == ELINK_EXT_PHY2)
}
" actual_phy_idx %x\n", phy_config_swapped,
phy) != ELINK_STATUS_OK) {
for (phy_index = ELINK_INT_PHY;
phy_index++)
return ELINK_STATUS_ERROR;
}
break;
if (params->feature_config_flags &
if (!(params->feature_config_flags &
OFFSETOF(struct shmem_region,
/* Update media type for non-PMF sync only for the first time
* In case the media type changes afterwards, it will be updated
* using the update_status function
*/
if ((media_types & (PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK <<
actual_phy_idx))) == 0) {
}
}
return ELINK_STATUS_OK;
}
#endif /* EXCLUDE_COMMON_INIT */
#ifdef ELINK_AUX_POWER
{
/* This function check that at least one of the phy's supports
* temperature read.
*/
phy_index++) {
return 1;
}
return 0;
}
#endif /* ELINK_AUX_POWER */
#ifdef ELINK_INCLUDE_EMUL
struct elink_vars *vars)
{
/* In case link speed is auto, set speed the highest as possible */
if (params->feature_config_flags &
else if (elink_is_4_port_mode(cb))
else
}
if ((params->feature_config_flags &
return ELINK_STATUS_ERROR;
}
switch (vars->line_speed) {
case ELINK_SPEED_10:
break;
case ELINK_SPEED_100:
break;
case ELINK_SPEED_1000:
break;
case ELINK_SPEED_2500:
break;
default:
vars->line_speed);
return ELINK_STATUS_ERROR;
}
else
} else {
/* Link speed >= 10000 requires XMAC enabled */
if (params->feature_config_flags &
return ELINK_STATUS_ERROR;
}
/* Check link speed */
switch (vars->line_speed) {
case ELINK_SPEED_10000:
break;
case ELINK_SPEED_20000:
break;
default:
vars->line_speed);
return ELINK_STATUS_ERROR;
}
else
}
return ELINK_STATUS_OK;
}
struct elink_vars *vars)
{
return ELINK_STATUS_ERROR;
} else {
if (params->feature_config_flags &
if (params->loopback_mode ==
else
} else {
if (params->loopback_mode ==
else
}
}
#ifndef ELINK_AUX_POWER
vars->line_speed);
#endif /* ELINK_AUX_POWER */
/* Disable drain */
/* update shared memory */
return ELINK_STATUS_OK;
}
#endif // ELINK_INCLUDE_EMUL
#ifdef ELINK_INCLUDE_FPGA
struct elink_vars *vars)
{
/* Enable on E1.5 FPGA */
}
switch (vars->line_speed) {
case ELINK_SPEED_AUTO_NEG:
case ELINK_SPEED_2500:
break;
case ELINK_SPEED_1000:
break;
case ELINK_SPEED_100:
break;
case ELINK_SPEED_10:
break;
default:
params->req_line_speed[0]);
return ELINK_STATUS_ERROR;
}
else
} else {
else
}
#ifndef ELINK_AUX_POWER
vars->line_speed);
#endif /* ELINK_AUX_POWER */
/* Disable drain */
/* Update shared memory */
return ELINK_STATUS_OK;
}
#endif // #ifdef ELINK_INCLUDE_FPGA
#ifdef ELINK_INCLUDE_LOOPBACK
struct elink_vars *vars)
{
/* Set bmac loopback */
}
struct elink_vars *vars)
{
/* Set bmac loopback */
}
struct elink_vars *vars)
{
if (!params->req_line_speed[0])
else
/* Set WC to loopback mode since link is required to provide clock
* to the XMAC in 20G mode
*/
params);
}
struct elink_vars *vars)
{
}
struct elink_vars *vars)
{
else
else {
}
} else {
else
}
/* Set 10G XGXS loopback */
} else {
/* Set external phy loopback */
for (phy_index = ELINK_EXT_PHY1;
params);
}
}
#endif // #ifdef ELINK_INCLUDE_LOOPBACK
#ifdef ELINK_ENHANCEMENTS
{
/* Open / close the gate between the NIG and the BRB */
en*0x3);
}
}
#endif /* #ifdef ELINK_ENHANCEMENTS */
#ifndef EXCLUDE_NON_COMMON_INIT
struct elink_vars *vars)
{
/* Sync the link parameters */
/*
* The module verification was already done by previous link owner,
* so this call is meant only to get warning message
*/
if (phy->phy_specific_func) {
}
#ifdef ELINK_ENHANCEMENTS
#endif
}
lfa_sts));
#ifndef EXCLUDE_WARPCORE
if (!dont_clear_stat) {
}
else
#endif
} else {
#ifndef EXCLUDE_BMAC2
else
#endif
}
/* Increment LFA count */
(((((lfa_sts & LINK_FLAP_AVOIDANCE_COUNT_MASK) >>
/* Clear link flap reason */
/* Disable NIG DRAIN */
/* Enable interrupts */
return ELINK_STATUS_OK;
}
struct elink_vars *vars,
int lfa_status)
{
return;
/* Store the new link parameters */
}
/* Clear the "Don't Clear Statistics" bit, and set reason */
/* Set link flap reason */
/* Increment link flap counter */
(((((lfa_sts & LINK_FLAP_COUNT_MASK) >>
<< LINK_FLAP_COUNT_OFFSET));
/* Proceed with regular link initialization */
}
{
int lfa_status;
vars->link_status = 0;
vars->phy_link_up = 0;
vars->line_speed = 0;
vars->check_kr2_recovery_cnt = 0;
#ifdef ELINK_ENHANCEMENTS
/* Driver opens NIG-BRB filters */
#endif
/* Check if link flap can be avoided */
if (lfa_status == 0) {
}
/* Disable attentions */
#ifdef ELINK_INCLUDE_EMUL
if (!(params->feature_config_flags &
#endif //ELINK_INCLUDE_EMUL
return ELINK_STATUS_ERROR;
}
#ifdef ELINK_INCLUDE_FPGA
} else
#endif /* ELINK_INCLUDE_FPGA */
#ifdef ELINK_INCLUDE_EMUL
} else
#endif /* ELINK_INCLUDE_EMUL */
#ifdef ELINK_INCLUDE_LOOPBACK
switch (params->loopback_mode) {
case ELINK_LOOPBACK_BMAC:
break;
case ELINK_LOOPBACK_EMAC:
break;
case ELINK_LOOPBACK_XMAC:
break;
case ELINK_LOOPBACK_UMAC:
break;
case ELINK_LOOPBACK_XGXS:
case ELINK_LOOPBACK_EXT_PHY:
break;
default:
#endif /* ELINK_INCLUDE_LOOPBACK */
#ifndef EXCLUDE_XGXS
#ifndef EXCLUDE_SERDES
else
#endif // EXCLUDE_SERDES
}
#endif /* EXCLUDE_XGXS */
#ifdef ELINK_INCLUDE_LOOPBACK
break;
}
#endif // ELINK_INCLUDE_LOOPBACK
#ifndef EXCLUDE_WARPCORE
#endif /* #ifndef EXCLUDE_BCM84833 */
return ELINK_STATUS_OK;
}
#ifndef EXCLUDE_LINK_RESET
{
/* Disable attentions */
vars->link_status = 0;
#ifndef EXCLUDE_WARPCORE
#endif /* #ifndef EXCLUDE_BCM84833 */
/* Activate nig drain */
/* Disable nig egress interface */
}
#ifdef ELINK_INCLUDE_EMUL
/* Stop BigMac rx */
if (!(params->feature_config_flags &
#endif // ELINK_INCLUDE_EMUL
#if !defined(EXCLUDE_BMAC2) && !defined(EXCLUDE_BMAC1)
#endif // !defined(EXCLUDE_BMAC2) && !defined(EXCLUDE_BMAC1)
#ifndef EXCLUDE_WARPCORE
#ifdef ELINK_INCLUDE_EMUL
if (!(params->feature_config_flags &
#endif // ELINK_INCLUDE_EMUL
}
#endif // EXCLUDE_WARPCORE
/* Disable emac */
/* The PHY reset is controlled by GPIO 1
* Hold it as vars low
*/
/* Clear link led */
phy_index++) {
params);
}
clear_latch_ind = 1;
}
}
if (clear_latch_ind) {
/* Clear latching indication */
}
#if defined(ELINK_INCLUDE_EMUL) || defined(ELINK_INCLUDE_FPGA)
#endif
/* Disable nig ingress interface */
/* Reset BigMac */
} else {
#ifndef EXCLUDE_WARPCORE
elink_set_xumac_nig(params, 0, 0);
#endif // EXCLUDE_WARPCORE
}
return ELINK_STATUS_OK;
}
#endif // EXCLUDE_LINK_RESET
#ifndef ELINK_AUX_POWER
struct elink_vars *vars)
{
/*
* Activate NIG drain so that during this time the device won't send
* anything while it is unable to response.
*/
/*
* Close gracefully the gate from BMAC to NIG such that no half packets
* are passed.
*/
}
/* Wait 10ms for the pipe to clean up*/
#ifdef ELINK_ENHANCEMENTS
/* Clean the NIG-BRB using the network filters in a way that will
* not cut a packet in the middle.
*/
#endif
/*
* Re-open the gate between the BMAC and the NIG, after verifying the
* gate to the BRB is closed, otherwise packets may arrive to the
* firmware before driver had initialized it. The target is to achieve
* minimum management protocol down time.
*/
}
/* Disable NIG drain */
return ELINK_STATUS_OK;
}
#endif /* ELINK_AUX_POWER */
#endif // EXCLUDE_NON_COMMON_INIT
/****************************************************************************/
/* Common function */
/****************************************************************************/
#ifndef EXCLUDE_COMMON_INIT
#ifndef ELINK_EMUL_ONLY
#ifndef EXCLUDE_BCM8727_BCM8073
{
/* PART1 - Reset both phys */
/* In E2, same phy is using for port0 of the two paths */
if (CHIP_IS_E1X(chip_id)) {
shmem_base = shmem_base_path[0];
shmem2_base = shmem2_base_path[0];
port_of_path = port;
} else {
port_of_path = 0;
}
/* Extract the ext phy address for the port */
return ELINK_STATUS_ERROR;
}
/* Disable attentions */
port_of_path*4,
/* Need to take the phy out of low power mode in order
* to write to access its registers
*/
port);
/* Reset the phy */
1<<15);
}
/* Add delay of 150ms after reset */
} else {
}
/* PART2 - Download firmware to both phys */
if (CHIP_IS_E1X(chip_id))
port_of_path = port;
else
port_of_path = 0;
return ELINK_STATUS_ERROR;
/* Only set bit 10 = 1 (Tx power down) */
/* Phase1 of TX_POWER_DOWN reset */
}
/* Toggle Transmitter: Power down and then up with 600ms delay
* between
*/
/* PART3 - complete TX_POWER_DOWN process, and set GPIO2 back to low */
/* Phase2 of POWER_DOWN_RESET */
/* Release bit 10 (Release Tx power down) */
/* Read modify write the SPI-ROM version select register */
/* set GPIO2 back to LOW */
}
return ELINK_STATUS_OK;
}
#endif /* EXCLUDE_BCM8727_BCM8073 */
#ifndef EXCLUDE_BCM87x6
{
/* Use port1 because of the static port-swap */
/* Enable the module detection interrupt */
elink_ext_phy_hw_reset(cb, 0);
/* In E2, same phy is using for port0 of the two paths */
if (CHIP_IS_E1X(chip_id)) {
shmem_base = shmem_base_path[0];
shmem2_base = shmem2_base_path[0];
} else {
}
/* Extract the ext phy address for the port */
return ELINK_STATUS_ERROR;
}
/* Reset phy*/
/* Set fault module detected LED on */
port);
}
return ELINK_STATUS_OK;
}
#endif /* #ifndef EXCLUDE_BCM87x6 */
#ifndef EXCLUDE_BCM8727_BCM8073
{
OFFSETOF(struct shmem_region,
switch (phy_gpio_reset) {
*io_gpio = 0;
*io_port = 0;
break;
*io_gpio = 1;
*io_port = 0;
break;
*io_gpio = 2;
*io_port = 0;
break;
*io_gpio = 3;
*io_port = 0;
break;
*io_gpio = 0;
*io_port = 1;
break;
*io_gpio = 1;
*io_port = 1;
break;
*io_gpio = 2;
*io_port = 1;
break;
*io_gpio = 3;
*io_port = 1;
break;
default:
/* Don't override the io_gpio and io_port */
break;
}
}
{
port = 1;
* Default is GPIO1, PORT1
*/
/* Calculate the port based on port swap */
/* Initiate PHY reset*/
port);
port);
/* PART1 - Reset both phys */
/* In E2, same phy is using for port0 of the two paths */
if (CHIP_IS_E1X(chip_id)) {
shmem_base = shmem_base_path[0];
shmem2_base = shmem2_base_path[0];
port_of_path = port;
} else {
port_of_path = 0;
}
/* Extract the ext phy address for the port */
return ELINK_STATUS_ERROR;
}
/* disable attentions */
port_of_path*4,
/* Reset the phy */
}
/* Add delay of 150ms after reset */
} else {
}
/* PART2 - Download firmware to both phys */
if (CHIP_IS_E1X(chip_id))
port_of_path = port;
else
port_of_path = 0;
return ELINK_STATUS_ERROR;
/* Disable PHY transmitter output */
}
return ELINK_STATUS_OK;
}
#endif /* EXCLUDE_BCM8727_BCM8073 */
#ifndef EXCLUDE_BCM84833
{
#ifndef EDEBUG
#endif
return ELINK_STATUS_OK;
}
#ifndef EXCLUDE_FROM_BNX2X
{
/* Wait for FW completing its initialization. */
MDIO_PMA_REG_CTRL, &val);
break;
}
if (cnt >= 1500) {
return ELINK_STATUS_ERROR;
}
/* Put the port in super isolate mode. */
/* Save spirom version */
return ELINK_STATUS_OK;
}
{
return ELINK_STATUS_ERROR;
}
break;
default:
break;
}
return rc;
}
#endif /* EXCLUDE_FROM_BNX2X */
#endif /* EXCLUDE_BCM84833 */
{
switch (ext_phy_type) {
#ifndef EXCLUDE_BCM8727_BCM8073
break;
break;
#endif
#ifndef EXCLUDE_BCM87x6
/* GPIO1 affects both ports, so there's need to pull
* it for single port alone
*/
break;
#endif /* #ifndef EXCLUDE_BCM87x6 */
#ifndef EXCLUDE_BCM84833
/* GPIO3's are linked, and so both need to be toggled
* to obtain required 2us pulse.
*/
break;
#endif
break;
default:
"ext_phy 0x%x common init not required\n",
break;
}
if (rc != ELINK_STATUS_OK)
// " Port %d\n",
return rc;
}
#ifdef INCLUDE_WARPCORE_UC_LOAD
{
/* Procedure to bring the LCPLL out of reset. */
return ELINK_STATUS_ERROR;
/* Extract the ext phy address for the port */
shmem2_base_path[0],
0, &phy) != ELINK_STATUS_OK) {
return ELINK_STATUS_ERROR;
}
/* Set WC to use CL45 */
/* Set swap lanes and polarity */
/* Power down warpcore lanes */
if (one_port_enabled)
/* Disable sequencer */
else
/* Load Warpcore microcode */
if (rc != ELINK_STATUS_OK)
return rc;
/* RX traffic and TX traffic requires clock sync.
* When transmiting we send data + clock to the Warpcore.
* This clock is provided by lane 0 of the Warpcore.
* So we need to configure this lane to supply us the correct clock
* which will be use for transmit on all lanes
*/
val &= 0xDE1F;
/* To force tx_wclk33 to txckp[0] */
*/
MDIO_WC_REG_XGXS_X2_CONTROL3, 0x7);
} else
val |= 0x2800;
/* Enable sequencer */
return ELINK_STATUS_OK;
}
#endif /* INCLUDE_WARPCORE_UC_LOAD */
#endif /* ELINK_EMUL_ONLY */
{
#ifndef ELINK_EMUL_ONLY
#endif
#if defined(ELINK_INCLUDE_EMUL) || defined(ELINK_INCLUDE_FPGA)
return ELINK_STATUS_OK;
#endif
if (CHIP_IS_E3(chip_id)) {
/* Enable EPIO */
}
#ifndef ELINK_EMUL_ONLY
/* Check if common init was already done */
OFFSETOF(struct shmem_region,
if (phy_ver) {
phy_ver);
return ELINK_STATUS_OK;
}
#ifdef INCLUDE_WARPCORE_UC_LOAD
if (ELINK_USES_WARPCORE(chip_id)) {
}
#endif
/* Read the ext_phy_type for arbitrary port(0) */
phy_index++) {
shmem_base_path[0],
phy_index, 0);
chip_id);
}
#endif /* ELINK_EMUL_ONLY */
return rc;
}
#endif // #ifndef EXCLUDE_COMMON_INIT
#ifndef EXCLUDE_NON_COMMON_INIT
#ifndef EXCLUDE_WARPCORE
struct elink_vars *vars)
{
OFFSETOF(struct shmem_region,
/* Ignore check if no external input PIN available */
return;
if (!pin_val) {
#ifndef ELINK_AUX_POWER
elink_cb_event_log(cb, ELINK_LOG_ID_OVER_CURRENT, params->port); //"Error: Power fault on Port %d has"
// " been detected and the power to "
// "that SFP+ module has been removed"
// " to prevent failure of the card."
// " Please remove the SFP+ module and"
// " restart the system to clear this"
// " error.\n",
#endif /* ELINK_AUX_POWER */
}
} else
}
#endif // EXCLUDE_WARPCORE
/* Returns 0 if no change occured since last check; 1 otherwise. */
{
/* Compare new value with previous value */
if ((status ^ old_status) == 0)
return 0;
/* If values differ */
switch (phy_flag) {
case PHY_HALF_OPEN_CONN_FLAG:
break;
case PHY_SFP_TX_FAULT_FLAG:
break;
default:
}
old_status, status);
/* Do not touch the link in case physical link down */
return 1;
/* a. Update shmem->link_status accordingly
* b. Update elink_vars->link_up
*/
if (status) {
/* activate nig drain */
/* Set LED mode to off since the PHY doesn't know about these
* errors
*/
} else {
/* Clear nig drain */
}
#ifndef ELINK_AUX_POWER
#ifdef ELINK_57711E_SUPPORT
#endif // ELINK_57711E_SUPPORT
#endif // ELINK_AUX_POWER
/* Update the LED according to the link state */
/* Update link status in the shared memory */
/* C. Trigger General Attention */
#ifndef EDEBUG
if (notify)
#endif // EDEBUG
return 1;
}
/******************************************************************************
* Description:
* This function checks for half opened connection change indication.
* When such change occurs, it calls the elink_analyze_link_error
* to check if Remote Fault is set or cleared. Reception of remote fault
* status message in the MAC indicates that the peer's MAC has detected
* a fault, for example, due to break in the TX side of fiber.
*
******************************************************************************/
#ifdef BNX2X_ADD /* BNX2X_ADD */
static
#endif
struct elink_vars *vars,
{
/* In case link status is physically up @ 10G do */
return ELINK_STATUS_OK;
/* Check E3 XMAC */
/* Note that link speed cannot be queried here, since it may be
* zero while link is down. In case UMAC is active, LSS will
* simply not be set
*/
/* Clear stick bits (Requires rising edge) */
lss_status = 1;
/* Check E1X / E2 BMAC */
/* Read BIGMAC_REGISTER_RX_LSS_STATUS */
else
lss_status = (wb_data[0] > 0);
}
return ELINK_STATUS_OK;
}
#ifdef ELINK_ENHANCEMENTS
struct elink_params *params,
struct elink_vars *vars)
{
/* Get The SFP+ TX_Fault controlling pin ([eg]pio) */
return;
}
if (led_change) {
/* Change TX_Fault led, set link status for further syncs */
} else {
}
/* If module is unapproved, led should be on regardless */
led_mode);
}
}
}
#endif
#ifndef EXCLUDE_WARPCORE
struct elink_vars *vars,
{
#ifdef ELINK_DEBUG
#endif // ELINK_DEBUG
}
struct elink_vars *vars,
{
int sigdet;
/* Once KR2 was disabled, wait 5 seconds before checking KR2 recovery
* Since some switches tend to reinit the AN process and clear the
* and recovered many times
*/
if (vars->check_kr2_recovery_cnt > 0) {
return;
}
if (!sigdet) {
}
return;
}
/* CL73 has not begun yet */
if (base_page == 0) {
}
return;
}
/* In case NP bit is not set in the BasePage, or it is set,
* but only KX is advertised, declare this link partner as non-KR2
* device.
*/
(((base_page & 0x8000) &&
/* In case KR2 is already disabled, check if we need to re-enable it */
if (!not_kr2_device) {
}
return;
}
/* KR2 is enabled, but not KR2 device */
if (not_kr2_device) {
/* Disable KR2 on both lanes */
/* Restart AN on leading lane */
return;
}
}
#endif
{
#if defined(ELINK_DEBUG) || defined(ELINK_ENHANCEMENTS)
#endif
break;
}
}
#ifndef EXCLUDE_WARPCORE
#ifdef ELINK_AUX_POWER
}
} else {
}
}
#endif // ELINK_AUX_POWER
#ifdef ELINK_ENHANCEMENTS
if (vars->rx_tx_asic_rst)
} else if (vars->link_status &
/* Clean trail, interrupt corrects the leds */
/* Update link status in the shared memory */
}
}
#endif // ELINK_ENHANCEMENTS
}
#endif /* EXCLUDE_WARPCORE */
}
#ifdef ELINK_ENHANCEMENTS
{
phy_index++) {
!= ELINK_STATUS_OK) {
return 0;
}
}
return fan_failure_det_req;
}
#endif // ELINK_ENHANCEMENTS
#ifdef ELINK_AUX_POWER
{
phy_index++) {
default:
break;
}
}
}
#endif // ELINK_AUX_POWER
{
elink_update_mng(params, 0);
phy_index++) {
params);
}
}
}
#ifdef ELINK_ENHANCEMENTS
{
if (CHIP_IS_E3(chip_id)) {
port,
&gpio_num,
&gpio_port) != ELINK_STATUS_OK)
return;
} else {
phy_index++) {
!= ELINK_STATUS_OK) {
return;
}
break;
}
}
}
if (gpio_num == 0xff)
return;
OFFSETOF(struct shmem_region,
if (port == 0)
else
/* Open appropriate AEU for interrupts */
/* Enable the GPIO to trigger interrupt */
}
#endif // ELINK_ENHANCEMENTS
#endif // EXCLUDE_NON_COMMON_INIT
#ifdef ELINK_AUX_POWER
{
/* Select the phy type */
#ifndef EXCLUDE_WARPCORE
phy = phy_warpcore;
#else
#endif
break;
#ifndef EXCLUDE_BCM8727_BCM8073
break;
#endif
#ifndef EXCLUDE_BCM8705
break;
#endif
#ifndef EXCLUDE_BCM87x6
break;
break;
#endif /* EXCLUDE_BCM87x6 */
#ifndef EXCLUDE_BCM8727_BCM8073
break;
#endif
#ifndef EXCLUDE_BCM8481
break;
break;
#endif
#ifndef EXCLUDE_BCM84833
break;
#endif
#ifndef EXCLUDE_BCM54618SE
phy = phy_54618se;
break;
#endif
#ifndef EXCLUDE_SFX7101
break;
#endif
return;
default:
continue;
}
}
}
#ifndef EXCLUDE_COMMON_INIT
{
/* The temperature returned from this function is expected
* to be degree C. Any conversion from hardware value to
* degree C will be performed here.
*/
else
return rc;
}
}
return ELINK_STATUS_ERROR;
}
#ifndef EXCLUDE_WARPCORE
{
}
{
}
/* Global register - operate on lane 0 */
if (enable)
else
val);
/* Restore AER */
}
#endif /* EXCLUDE_WARPCORE */
#endif /* #ifndef EXCLUDE_COMMON_INIT */
#endif