Merge branch 'bnx2x-848xx-phy-fixes'

Yuval Mintz says:

====================
bnx2x: Fix 848xx phys

This series contains link-related fixes, mostly for the 848xx phys
[2 patches are for 84833, and 2 patches are for 84858].
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2016-02-21 22:50:55 -05:00
commit dd78dac893
2 changed files with 256 additions and 49 deletions

View File

@ -6185,26 +6185,80 @@ static int bnx2x_format_ver(u32 num, u8 *str, u16 *len)
shift -= 4;
digit = ((num & mask) >> shift);
if (digit == 0 && remove_leading_zeros) {
mask = mask >> 4;
continue;
} else if (digit < 0xa)
*str_ptr = digit + '0';
else
*str_ptr = digit - 0xa + 'a';
remove_leading_zeros = 0;
str_ptr++;
(*len)--;
*str_ptr = '0';
} else {
if (digit < 0xa)
*str_ptr = digit + '0';
else
*str_ptr = digit - 0xa + 'a';
remove_leading_zeros = 0;
str_ptr++;
(*len)--;
}
mask = mask >> 4;
if (shift == 4*4) {
if (remove_leading_zeros) {
str_ptr++;
(*len)--;
}
*str_ptr = '.';
str_ptr++;
(*len)--;
remove_leading_zeros = 1;
}
}
if (remove_leading_zeros)
(*len)--;
return 0;
}
static int bnx2x_3_seq_format_ver(u32 num, u8 *str, u16 *len)
{
u8 *str_ptr = str;
u32 mask = 0x00f00000;
u8 shift = 8*3;
u8 digit;
u8 remove_leading_zeros = 1;
if (*len < 10) {
/* Need more than 10chars for this format */
*str_ptr = '\0';
(*len)--;
return -EINVAL;
}
while (shift > 0) {
shift -= 4;
digit = ((num & mask) >> shift);
if (digit == 0 && remove_leading_zeros) {
*str_ptr = '0';
} else {
if (digit < 0xa)
*str_ptr = digit + '0';
else
*str_ptr = digit - 0xa + 'a';
remove_leading_zeros = 0;
str_ptr++;
(*len)--;
}
mask = mask >> 4;
if ((shift == 4*4) || (shift == 4*2)) {
if (remove_leading_zeros) {
str_ptr++;
(*len)--;
}
*str_ptr = '.';
str_ptr++;
(*len)--;
remove_leading_zeros = 1;
}
}
if (remove_leading_zeros)
(*len)--;
return 0;
}
static int bnx2x_null_format_ver(u32 spirom_ver, u8 *str, u16 *len)
{
@ -9677,8 +9731,9 @@ static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
if (bnx2x_is_8483x_8485x(phy)) {
bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD, 0x400f, &fw_ver1);
bnx2x_save_spirom_version(bp, port, fw_ver1 & 0xfff,
phy->ver_addr);
if (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858)
fw_ver1 &= 0xfff;
bnx2x_save_spirom_version(bp, port, fw_ver1, phy->ver_addr);
} else {
/* For 32-bit registers in 848xx, access via MDIO2ARM i/f. */
/* (1) set reg 0xc200_0014(SPI_BRIDGE_CTRL_2) to 0x03000000 */
@ -9732,16 +9787,32 @@ static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
static void bnx2x_848xx_set_led(struct bnx2x *bp,
struct bnx2x_phy *phy)
{
u16 val, offset, i;
u16 val, led3_blink_rate, offset, i;
static struct bnx2x_reg_set reg_set[] = {
{MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED1_MASK, 0x0080},
{MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED2_MASK, 0x0018},
{MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED3_MASK, 0x0006},
{MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED3_BLINK, 0x0000},
{MDIO_PMA_DEVAD, MDIO_PMA_REG_84823_CTL_SLOW_CLK_CNT_HIGH,
MDIO_PMA_REG_84823_BLINK_RATE_VAL_15P9HZ},
{MDIO_AN_DEVAD, 0xFFFB, 0xFFFD}
};
if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858) {
/* Set LED5 source */
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_8481_LED5_MASK,
0x90);
led3_blink_rate = 0x000f;
} else {
led3_blink_rate = 0x0000;
}
/* Set LED3 BLINK */
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_8481_LED3_BLINK,
led3_blink_rate);
/* PHYC_CTL_LED_CTL */
bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
@ -9749,6 +9820,9 @@ static void bnx2x_848xx_set_led(struct bnx2x *bp,
val &= 0xFE00;
val |= 0x0092;
if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858)
val |= 2 << 12; /* LED5 ON based on source */
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_8481_LINK_SIGNAL, val);
@ -9762,10 +9836,17 @@ static void bnx2x_848xx_set_led(struct bnx2x *bp,
else
offset = MDIO_PMA_REG_84823_CTL_LED_CTL_1;
/* stretch_en for LED3*/
if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858)
val = MDIO_PMA_REG_84858_ALLOW_GPHY_ACT |
MDIO_PMA_REG_84823_LED3_STRETCH_EN;
else
val = MDIO_PMA_REG_84823_LED3_STRETCH_EN;
/* stretch_en for LEDs */
bnx2x_cl45_read_or_write(bp, phy,
MDIO_PMA_DEVAD, offset,
MDIO_PMA_REG_84823_LED3_STRETCH_EN);
MDIO_PMA_DEVAD,
offset,
val);
}
static void bnx2x_848xx_specific_func(struct bnx2x_phy *phy,
@ -9775,7 +9856,7 @@ static void bnx2x_848xx_specific_func(struct bnx2x_phy *phy,
struct bnx2x *bp = params->bp;
switch (action) {
case PHY_INIT:
if (!bnx2x_is_8483x_8485x(phy)) {
if (bnx2x_is_8483x_8485x(phy)) {
/* Save spirom version */
bnx2x_save_848xx_spirom_version(phy, bp, params->port);
}
@ -10036,15 +10117,20 @@ static int bnx2x_84858_cmd_hdlr(struct bnx2x_phy *phy,
static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy,
struct link_params *params, u16 fw_cmd,
u16 cmd_args[], int argc)
u16 cmd_args[], int argc, int process)
{
int idx;
u16 val;
struct bnx2x *bp = params->bp;
/* Write CMD_OPEN_OVERRIDE to STATUS reg */
bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
MDIO_848xx_CMD_HDLR_STATUS,
PHY84833_STATUS_CMD_OPEN_OVERRIDE);
int rc = 0;
if (process == PHY84833_MB_PROCESS2) {
/* Write CMD_OPEN_OVERRIDE to STATUS reg */
bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
MDIO_848xx_CMD_HDLR_STATUS,
PHY84833_STATUS_CMD_OPEN_OVERRIDE);
}
for (idx = 0; idx < PHY848xx_CMDHDLR_WAIT; idx++) {
bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
MDIO_848xx_CMD_HDLR_STATUS, &val);
@ -10054,15 +10140,27 @@ static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy,
}
if (idx >= PHY848xx_CMDHDLR_WAIT) {
DP(NETIF_MSG_LINK, "FW cmd: FW not ready.\n");
/* if the status is CMD_COMPLETE_PASS or CMD_COMPLETE_ERROR
* clear the status to CMD_CLEAR_COMPLETE
*/
if (val == PHY84833_STATUS_CMD_COMPLETE_PASS ||
val == PHY84833_STATUS_CMD_COMPLETE_ERROR) {
bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
MDIO_848xx_CMD_HDLR_STATUS,
PHY84833_STATUS_CMD_CLEAR_COMPLETE);
}
return -EINVAL;
}
/* Prepare argument(s) and issue command */
for (idx = 0; idx < argc; idx++) {
bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
MDIO_848xx_CMD_HDLR_DATA1 + idx,
cmd_args[idx]);
if (process == PHY84833_MB_PROCESS1 ||
process == PHY84833_MB_PROCESS2) {
/* Prepare argument(s) */
for (idx = 0; idx < argc; idx++) {
bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
MDIO_848xx_CMD_HDLR_DATA1 + idx,
cmd_args[idx]);
}
}
bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
MDIO_848xx_CMD_HDLR_COMMAND, fw_cmd);
for (idx = 0; idx < PHY848xx_CMDHDLR_WAIT; idx++) {
@ -10076,24 +10174,30 @@ static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy,
if ((idx >= PHY848xx_CMDHDLR_WAIT) ||
(val == PHY84833_STATUS_CMD_COMPLETE_ERROR)) {
DP(NETIF_MSG_LINK, "FW cmd failed.\n");
return -EINVAL;
rc = -EINVAL;
}
/* Gather returning data */
for (idx = 0; idx < argc; idx++) {
bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
MDIO_848xx_CMD_HDLR_DATA1 + idx,
&cmd_args[idx]);
if (process == PHY84833_MB_PROCESS3 && rc == 0) {
/* Gather returning data */
for (idx = 0; idx < argc; idx++) {
bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
MDIO_848xx_CMD_HDLR_DATA1 + idx,
&cmd_args[idx]);
}
}
bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
MDIO_848xx_CMD_HDLR_STATUS,
PHY84833_STATUS_CMD_CLEAR_COMPLETE);
return 0;
if (val == PHY84833_STATUS_CMD_COMPLETE_ERROR ||
val == PHY84833_STATUS_CMD_COMPLETE_PASS) {
bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
MDIO_848xx_CMD_HDLR_STATUS,
PHY84833_STATUS_CMD_CLEAR_COMPLETE);
}
return rc;
}
static int bnx2x_848xx_cmd_hdlr(struct bnx2x_phy *phy,
struct link_params *params,
u16 fw_cmd,
u16 cmd_args[], int argc)
u16 cmd_args[], int argc,
int process)
{
struct bnx2x *bp = params->bp;
@ -10106,7 +10210,7 @@ static int bnx2x_848xx_cmd_hdlr(struct bnx2x_phy *phy,
argc);
} else {
return bnx2x_84833_cmd_hdlr(phy, params, fw_cmd, cmd_args,
argc);
argc, process);
}
}
@ -10133,7 +10237,7 @@ static int bnx2x_848xx_pair_swap_cfg(struct bnx2x_phy *phy,
status = bnx2x_848xx_cmd_hdlr(phy, params,
PHY848xx_CMD_SET_PAIR_SWAP, data,
PHY848xx_CMDHDLR_MAX_ARGS);
2, PHY84833_MB_PROCESS2);
if (status == 0)
DP(NETIF_MSG_LINK, "Pairswap OK, val=0x%x\n", data[1]);
@ -10222,8 +10326,8 @@ static int bnx2x_8483x_disable_eee(struct bnx2x_phy *phy,
DP(NETIF_MSG_LINK, "Don't Advertise 10GBase-T EEE\n");
/* Prevent Phy from working in EEE and advertising it */
rc = bnx2x_848xx_cmd_hdlr(phy, params,
PHY848xx_CMD_SET_EEE_MODE, &cmd_args, 1);
rc = bnx2x_848xx_cmd_hdlr(phy, params, PHY848xx_CMD_SET_EEE_MODE,
&cmd_args, 1, PHY84833_MB_PROCESS1);
if (rc) {
DP(NETIF_MSG_LINK, "EEE disable failed.\n");
return rc;
@ -10240,8 +10344,8 @@ static int bnx2x_8483x_enable_eee(struct bnx2x_phy *phy,
struct bnx2x *bp = params->bp;
u16 cmd_args = 1;
rc = bnx2x_848xx_cmd_hdlr(phy, params,
PHY848xx_CMD_SET_EEE_MODE, &cmd_args, 1);
rc = bnx2x_848xx_cmd_hdlr(phy, params, PHY848xx_CMD_SET_EEE_MODE,
&cmd_args, 1, PHY84833_MB_PROCESS1);
if (rc) {
DP(NETIF_MSG_LINK, "EEE enable failed.\n");
return rc;
@ -10362,7 +10466,7 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
cmd_args[3] = PHY84833_CONSTANT_LATENCY;
rc = bnx2x_848xx_cmd_hdlr(phy, params,
PHY848xx_CMD_SET_EEE_MODE, cmd_args,
PHY848xx_CMDHDLR_MAX_ARGS);
4, PHY84833_MB_PROCESS1);
if (rc)
DP(NETIF_MSG_LINK, "Cfg AutogrEEEn failed.\n");
}
@ -10416,6 +10520,32 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
vars->eee_status &= ~SHMEM_EEE_SUPPORTED_MASK;
}
if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
/* Additional settings for jumbo packets in 1000BASE-T mode */
/* Allow rx extended length */
bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
MDIO_AN_REG_8481_AUX_CTRL, &val);
val |= 0x4000;
bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
MDIO_AN_REG_8481_AUX_CTRL, val);
/* TX FIFO Elasticity LSB */
bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
MDIO_AN_REG_8481_1G_100T_EXT_CTRL, &val);
val |= 0x1;
bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
MDIO_AN_REG_8481_1G_100T_EXT_CTRL, val);
/* TX FIFO Elasticity MSB */
/* Enable expansion register 0x46 (Pattern Generator status) */
bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
MDIO_AN_REG_8481_EXPANSION_REG_ACCESS, 0xf46);
bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
MDIO_AN_REG_8481_EXPANSION_REG_RD_RW, &val);
val |= 0x4000;
bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
MDIO_AN_REG_8481_EXPANSION_REG_RD_RW, val);
}
if (bnx2x_is_8483x_8485x(phy)) {
/* Bring PHY out of super isolate mode as the final step. */
bnx2x_cl45_read_and_write(bp, phy,
@ -10555,6 +10685,17 @@ static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
return link_up;
}
static int bnx2x_8485x_format_ver(u32 raw_ver, u8 *str, u16 *len)
{
int status = 0;
u32 num;
num = ((raw_ver & 0xF80) >> 7) << 16 | ((raw_ver & 0x7F) << 8) |
((raw_ver & 0xF000) >> 12);
status = bnx2x_3_seq_format_ver(num, str, len);
return status;
}
static int bnx2x_848xx_format_ver(u32 raw_ver, u8 *str, u16 *len)
{
int status = 0;
@ -10651,10 +10792,25 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
0x0);
} else {
/* LED 1 OFF */
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_8481_LED1_MASK,
0x0);
if (phy->type ==
PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858) {
/* LED 2 OFF */
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_8481_LED2_MASK,
0x0);
/* LED 3 OFF */
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_8481_LED3_MASK,
0x0);
}
}
break;
case LED_MODE_FRONT_PANEL_OFF:
@ -10713,6 +10869,19 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
MDIO_PMA_REG_8481_SIGNAL_MASK,
0x0);
}
if (phy->type ==
PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858) {
/* LED 2 OFF */
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_8481_LED2_MASK,
0x0);
/* LED 3 OFF */
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_8481_LED3_MASK,
0x0);
}
}
break;
case LED_MODE_ON:
@ -10776,6 +10945,25 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
params->port*4,
NIG_MASK_MI_INT);
}
}
if (phy->type ==
PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858) {
/* Tell LED3 to constant on */
bnx2x_cl45_read(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_8481_LINK_SIGNAL,
&val);
val &= ~(7<<6);
val |= (2<<6); /* A83B[8:6]= 2 */
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_8481_LINK_SIGNAL,
val);
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_8481_LED3_MASK,
0x20);
} else {
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_8481_SIGNAL_MASK,
@ -10853,6 +11041,17 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_8481_LINK_SIGNAL,
val);
if (phy->type ==
PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84858) {
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_8481_LED2_MASK,
0x18);
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_8481_LED3_MASK,
0x06);
}
if (phy->type ==
PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834) {
/* Restore LED4 source to external link,
@ -11982,7 +12181,7 @@ static const struct bnx2x_phy phy_84858 = {
.read_status = (read_status_t)bnx2x_848xx_read_status,
.link_reset = (link_reset_t)bnx2x_848x3_link_reset,
.config_loopback = (config_loopback_t)NULL,
.format_fw_ver = (format_fw_ver_t)bnx2x_848xx_format_ver,
.format_fw_ver = (format_fw_ver_t)bnx2x_8485x_format_ver,
.hw_reset = (hw_reset_t)bnx2x_84833_hw_reset_phy,
.set_link_led = (set_link_led_t)bnx2x_848xx_set_link_led,
.phy_specific_func = (phy_specific_func_t)bnx2x_848xx_specific_func
@ -13807,8 +14006,10 @@ void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
if (CHIP_IS_E3(bp)) {
struct bnx2x_phy *phy = &params->phy[INT_PHY];
bnx2x_set_aer_mmd(params, phy);
if ((phy->supported & SUPPORTED_20000baseKR2_Full) &&
(phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G))
if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
(phy->speed_cap_mask &
PORT_HW_CFG_SPEED_CAPABILITY_D0_20G)) ||
(phy->req_line_speed == SPEED_20000))
bnx2x_check_kr2_wa(params, vars, phy);
bnx2x_check_over_curr(params, vars);
if (vars->rx_tx_asic_rst)

View File

@ -7296,6 +7296,8 @@ Theotherbitsarereservedandshouldbezero*/
#define MDIO_PMA_REG_84823_CTL_LED_CTL_1 0xa8e3
#define MDIO_PMA_REG_84833_CTL_LED_CTL_1 0xa8ec
#define MDIO_PMA_REG_84823_LED3_STRETCH_EN 0x0080
/* BCM84858 only */
#define MDIO_PMA_REG_84858_ALLOW_GPHY_ACT 0x8000
/* BCM84833 only */
#define MDIO_84833_TOP_CFG_FW_REV 0x400f
@ -7337,6 +7339,10 @@ Theotherbitsarereservedandshouldbezero*/
#define PHY84833_STATUS_CMD_NOT_OPEN_FOR_CMDS 0x0040
#define PHY84833_STATUS_CMD_CLEAR_COMPLETE 0x0080
#define PHY84833_STATUS_CMD_OPEN_OVERRIDE 0xa5a5
/* Mailbox Process */
#define PHY84833_MB_PROCESS1 1
#define PHY84833_MB_PROCESS2 2
#define PHY84833_MB_PROCESS3 3
/* Mailbox status set used by 84858 only */
#define PHY84858_STATUS_CMD_RECEIVED 0x0001