Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dd78dac8 authored by David S. Miller's avatar David S. Miller
Browse files

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 9ca69b70 4ec0b6d5
Loading
Loading
Loading
Loading
+250 −49
Original line number Diff line number Diff line
@@ -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 = '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;
	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 */
	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;
	}
	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]);
		}
	}
	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 0;
	}
	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)
+6 −0
Original line number Diff line number Diff line
@@ -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