bnx2x_link.c revision ce7c048928473220394bb126b08596e92e998a36
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Copyright 2008-2011 Broadcom Corporation
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Unless you and Broadcom execute a separate written software license
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * agreement governing use of this software, this software is licensed to you
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * under the terms of the GNU General Public License version 2, available
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Notwithstanding the above, under no circumstances may you combine this
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * software in any way with any other Broadcom software provided under a
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * license other than the GPL, without Broadcom's express prior written
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * consent.
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Written by Yaniv Rosner
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netdevice.h>
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h>
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ethtool.h>
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mutex.h>
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "bnx2x.h"
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "bnx2x_cmn.h"
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************/
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ETH_HLEN			14
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* L2 header size + 2*VLANs (8 bytes) + LLC SNAP (8 bytes) */
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ETH_OVREHEAD			(ETH_HLEN + 8 + 8)
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ETH_MIN_PACKET_SIZE		60
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ETH_MAX_PACKET_SIZE		1500
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ETH_MAX_JUMBO_PACKET_SIZE	9600
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MDIO_ACCESS_TIMEOUT		1000
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BMAC_CONTROL_RX_ENABLE		2
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WC_LANE_MAX			4
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define I2C_SWITCH_WIDTH		2
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define I2C_BSC0			0
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define I2C_BSC1			1
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define I2C_WA_RETRY_CNT		3
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MCPR_IMC_COMMAND_READ_OP	1
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MCPR_IMC_COMMAND_WRITE_OP	2
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* LED Blink rate that will achieve ~15.9Hz */
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LED_BLINK_RATE_VAL_E3		354
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LED_BLINK_RATE_VAL_E1X_E2	480
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***********************************************************/
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*			Shortcut definitions		   */
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***********************************************************/
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NIG_LATCH_BC_ENABLE_MI_INT 0
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NIG_STATUS_EMAC0_MI_INT \
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_EMAC0_MISC_MI_INT
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NIG_STATUS_XGXS0_LINK10G \
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK10G
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NIG_STATUS_XGXS0_LINK_STATUS \
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NIG_STATUS_XGXS0_LINK_STATUS_SIZE \
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_XGXS0_LINK_STATUS_SIZE
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NIG_STATUS_SERDES0_LINK_STATUS \
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		NIG_STATUS_INTERRUPT_PORT0_REG_STATUS_SERDES0_LINK_STATUS
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NIG_MASK_MI_INT \
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		NIG_MASK_INTERRUPT_PORT0_REG_MASK_EMAC0_MISC_MI_INT
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NIG_MASK_XGXS0_LINK10G \
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK10G
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NIG_MASK_XGXS0_LINK_STATUS \
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		NIG_MASK_INTERRUPT_PORT0_REG_MASK_XGXS0_LINK_STATUS
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NIG_MASK_SERDES0_LINK_STATUS \
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		NIG_MASK_INTERRUPT_PORT0_REG_MASK_SERDES0_LINK_STATUS
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MDIO_AN_CL73_OR_37_COMPLETE \
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE | \
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 MDIO_GP_STATUS_TOP_AN_STATUS1_CL37_AUTONEG_COMPLETE)
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define XGXS_RESET_BITS \
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	(MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_RSTB_HW |   \
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_IDDQ |      \
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_PWRDWN |    \
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_PWRDWN_SD | \
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_XGXS0_TXD_FIFO_RSTB)
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SERDES_RESET_BITS \
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	(MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_RSTB_HW | \
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_IDDQ |    \
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_PWRDWN |  \
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 MISC_REGISTERS_RESET_REG_3_MISC_NIG_MUX_SERDES0_PWRDWN_SD)
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define AUTONEG_CL37		SHARED_HW_CFG_AN_ENABLE_CL37
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define AUTONEG_CL73		SHARED_HW_CFG_AN_ENABLE_CL73
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define AUTONEG_BAM		SHARED_HW_CFG_AN_ENABLE_BAM
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define AUTONEG_PARALLEL \
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				SHARED_HW_CFG_AN_ENABLE_PARALLEL_DETECTION
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define AUTONEG_SGMII_FIBER_AUTODET \
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				SHARED_HW_CFG_AN_EN_SGMII_FIBER_AUTO_DETECT
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define AUTONEG_REMOTE_PHY	SHARED_HW_CFG_AN_ENABLE_REMOTE_PHY
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GP_STATUS_PAUSE_RSOLUTION_TXSIDE \
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			MDIO_GP_STATUS_TOP_AN_STATUS1_PAUSE_RSOLUTION_TXSIDE
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GP_STATUS_PAUSE_RSOLUTION_RXSIDE \
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			MDIO_GP_STATUS_TOP_AN_STATUS1_PAUSE_RSOLUTION_RXSIDE
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GP_STATUS_SPEED_MASK \
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_MASK
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GP_STATUS_10M	MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10M
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GP_STATUS_100M	MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_100M
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GP_STATUS_1G	MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GP_STATUS_2_5G	MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_2_5G
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GP_STATUS_5G	MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_5G
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GP_STATUS_6G	MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_6G
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GP_STATUS_10G_HIG \
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_HIG
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GP_STATUS_10G_CX4 \
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_CX4
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GP_STATUS_1G_KX MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_1G_KX
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GP_STATUS_10G_KX4 \
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KX4
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	GP_STATUS_10G_KR MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KR
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	GP_STATUS_10G_XFI   MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_XFI
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	GP_STATUS_20G_DXGXS MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_DXGXS
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	GP_STATUS_10G_SFI   MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_SFI
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LINK_10THD		LINK_STATUS_SPEED_AND_DUPLEX_10THD
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LINK_10TFD		LINK_STATUS_SPEED_AND_DUPLEX_10TFD
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LINK_100TXHD		LINK_STATUS_SPEED_AND_DUPLEX_100TXHD
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LINK_100T4		LINK_STATUS_SPEED_AND_DUPLEX_100T4
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LINK_100TXFD		LINK_STATUS_SPEED_AND_DUPLEX_100TXFD
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LINK_1000THD		LINK_STATUS_SPEED_AND_DUPLEX_1000THD
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LINK_1000TFD		LINK_STATUS_SPEED_AND_DUPLEX_1000TFD
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LINK_1000XFD		LINK_STATUS_SPEED_AND_DUPLEX_1000XFD
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LINK_2500THD		LINK_STATUS_SPEED_AND_DUPLEX_2500THD
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LINK_2500TFD		LINK_STATUS_SPEED_AND_DUPLEX_2500TFD
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LINK_2500XFD		LINK_STATUS_SPEED_AND_DUPLEX_2500XFD
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LINK_10GTFD		LINK_STATUS_SPEED_AND_DUPLEX_10GTFD
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LINK_10GXFD		LINK_STATUS_SPEED_AND_DUPLEX_10GXFD
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LINK_20GTFD		LINK_STATUS_SPEED_AND_DUPLEX_20GTFD
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LINK_20GXFD		LINK_STATUS_SPEED_AND_DUPLEX_20GXFD
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* */
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SFP_EEPROM_CON_TYPE_ADDR		0x2
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	#define SFP_EEPROM_CON_TYPE_VAL_LC	0x7
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	#define SFP_EEPROM_CON_TYPE_VAL_COPPER	0x21
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SFP_EEPROM_COMP_CODE_ADDR		0x3
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	#define SFP_EEPROM_COMP_CODE_SR_MASK	(1<<4)
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	#define SFP_EEPROM_COMP_CODE_LR_MASK	(1<<5)
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	#define SFP_EEPROM_COMP_CODE_LRM_MASK	(1<<6)
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SFP_EEPROM_FC_TX_TECH_ADDR		0x8
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	#define SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE 0x4
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	#define SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_ACTIVE  0x8
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SFP_EEPROM_OPTIONS_ADDR			0x40
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	#define SFP_EEPROM_OPTIONS_LINEAR_RX_OUT_MASK 0x1
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SFP_EEPROM_OPTIONS_SIZE			2
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define EDC_MODE_LINEAR				0x0022
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define EDC_MODE_LIMITING				0x0044
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define EDC_MODE_PASSIVE_DAC			0x0055
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* BRB thresholds for E2*/
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E2_BRB_MAC_PAUSE_XOFF_THR_PAUSE		170
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E2_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE		0
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E2_BRB_MAC_PAUSE_XON_THR_PAUSE		250
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E2_BRB_MAC_PAUSE_XON_THR_NON_PAUSE		0
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E2_BRB_MAC_FULL_XOFF_THR_PAUSE		10
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E2_BRB_MAC_FULL_XOFF_THR_NON_PAUSE		90
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E2_BRB_MAC_FULL_XON_THR_PAUSE			50
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E2_BRB_MAC_FULL_XON_THR_NON_PAUSE		250
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* BRB thresholds for E3A0 */
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_PAUSE		290
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE		0
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3A0_BRB_MAC_PAUSE_XON_THR_PAUSE		410
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3A0_BRB_MAC_PAUSE_XON_THR_NON_PAUSE		0
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3A0_BRB_MAC_FULL_XOFF_THR_PAUSE		10
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3A0_BRB_MAC_FULL_XOFF_THR_NON_PAUSE		170
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3A0_BRB_MAC_FULL_XON_THR_PAUSE		50
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3A0_BRB_MAC_FULL_XON_THR_NON_PAUSE		410
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* BRB thresholds for E3B0 2 port mode*/
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_PAUSE		1025
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE	0
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_PAUSE		1025
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_NON_PAUSE	0
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_PAUSE		10
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_NON_PAUSE	1025
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_PAUSE		50
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_NON_PAUSE	1025
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* only for E3B0*/
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_2P_BRB_FULL_LB_XOFF_THR			1025
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_2P_BRB_FULL_LB_XON_THR			1025
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Lossy +Lossless GUARANTIED == GUART */
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_2P_MIX_PAUSE_LB_GUART			284
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Lossless +Lossless*/
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_2P_PAUSE_LB_GUART			236
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Lossy +Lossy*/
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_2P_NON_PAUSE_LB_GUART			342
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Lossy +Lossless*/
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_2P_MIX_PAUSE_MAC_0_CLASS_T_GUART		284
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Lossless +Lossless*/
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_2P_PAUSE_MAC_0_CLASS_T_GUART		236
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Lossy +Lossy*/
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_2P_NON_PAUSE_MAC_0_CLASS_T_GUART		336
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_2P_BRB_MAC_0_CLASS_T_GUART_HYST		80
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_2P_BRB_MAC_1_CLASS_T_GUART		0
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_2P_BRB_MAC_1_CLASS_T_GUART_HYST		0
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* BRB thresholds for E3B0 4 port mode */
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_4P_BRB_MAC_PAUSE_XOFF_THR_PAUSE		304
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_4P_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE	0
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_4P_BRB_MAC_PAUSE_XON_THR_PAUSE		384
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_4P_BRB_MAC_PAUSE_XON_THR_NON_PAUSE	0
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_4P_BRB_MAC_FULL_XOFF_THR_PAUSE		10
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_4P_BRB_MAC_FULL_XOFF_THR_NON_PAUSE	304
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_PAUSE		50
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_NON_PAUSE	384
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* only for E3B0*/
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_4P_BRB_FULL_LB_XOFF_THR			304
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_4P_BRB_FULL_LB_XON_THR			384
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_4P_LB_GUART				120
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART		120
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART_HYST		80
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART		80
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART_HYST		120
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DCBX_INVALID_COS					(0xFF)
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ETS_BW_LIMIT_CREDIT_UPPER_BOUND		(0x5000)
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ETS_BW_LIMIT_CREDIT_WEIGHT		(0x5000)
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ETS_E3B0_NIG_MIN_W_VAL_UP_TO_10GBPS		(1360)
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ETS_E3B0_NIG_MIN_W_VAL_20GBPS			(2720)
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ETS_E3B0_PBF_MIN_W_VAL				(10000)
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MAX_PACKET_SIZE					(9700)
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WC_UC_TIMEOUT					100
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MAX_KR_LINK_RETRY				4
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**********************************************************/
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*                     INTERFACE                          */
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**********************************************************/
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CL22_WR_OVER_CL45(_bp, _phy, _bank, _addr, _val) \
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_cl45_write(_bp, _phy, \
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(_phy)->def_md_devad, \
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(_bank + (_addr & 0xf)), \
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		_val)
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CL22_RD_OVER_CL45(_bp, _phy, _bank, _addr, _val) \
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_cl45_read(_bp, _phy, \
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(_phy)->def_md_devad, \
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(_bank + (_addr & 0xf)), \
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		_val)
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28233430dc593f866f5d67ff6a6213b6dd6d7ea3ce1Jean Delvarestatic u32 bnx2x_bits_en(struct bnx2x *bp, u32 reg, u32 bits)
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 val = REG_RD(bp, reg);
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val |= bits;
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, reg, val);
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return val;
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u32 bnx2x_bits_dis(struct bnx2x *bp, u32 reg, u32 bits)
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 val = REG_RD(bp, reg);
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val &= ~bits;
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, reg, val);
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return val;
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************************************/
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*			EPIO/GPIO section			  */
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************************************/
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void bnx2x_get_epio(struct bnx2x *bp, u32 epio_pin, u32 *en)
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 epio_mask, gp_oenable;
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*en = 0;
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Sanity check */
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (epio_pin > 31) {
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DP(NETIF_MSG_LINK, "Invalid EPIO pin %d to get\n", epio_pin);
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	epio_mask = 1 << epio_pin;
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set this EPIO to output */
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	gp_oenable = REG_RD(bp, MCP_REG_MCPR_GP_OENABLE);
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, MCP_REG_MCPR_GP_OENABLE, gp_oenable & ~epio_mask);
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*en = (REG_RD(bp, MCP_REG_MCPR_GP_INPUTS) & epio_mask) >> epio_pin;
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void bnx2x_set_epio(struct bnx2x *bp, u32 epio_pin, u32 en)
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 epio_mask, gp_output, gp_oenable;
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Sanity check */
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (epio_pin > 31) {
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DP(NETIF_MSG_LINK, "Invalid EPIO pin %d to set\n", epio_pin);
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DP(NETIF_MSG_LINK, "Setting EPIO pin %d to %d\n", epio_pin, en);
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	epio_mask = 1 << epio_pin;
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set this EPIO to output */
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	gp_output = REG_RD(bp, MCP_REG_MCPR_GP_OUTPUTS);
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (en)
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		gp_output |= epio_mask;
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		gp_output &= ~epio_mask;
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, MCP_REG_MCPR_GP_OUTPUTS, gp_output);
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set the value for this EPIO */
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	gp_oenable = REG_RD(bp, MCP_REG_MCPR_GP_OENABLE);
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, MCP_REG_MCPR_GP_OENABLE, gp_oenable | epio_mask);
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void bnx2x_set_cfg_pin(struct bnx2x *bp, u32 pin_cfg, u32 val)
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (pin_cfg == PIN_CFG_NA)
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (pin_cfg >= PIN_CFG_EPIO0) {
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bnx2x_set_epio(bp, pin_cfg - PIN_CFG_EPIO0, val);
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u8 gpio_num = (pin_cfg - PIN_CFG_GPIO0_P0) & 0x3;
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u8 gpio_port = (pin_cfg - PIN_CFG_GPIO0_P0) >> 2;
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bnx2x_set_gpio(bp, gpio_num, (u8)val, gpio_port);
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u32 bnx2x_get_cfg_pin(struct bnx2x *bp, u32 pin_cfg, u32 *val)
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (pin_cfg == PIN_CFG_NA)
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (pin_cfg >= PIN_CFG_EPIO0) {
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bnx2x_get_epio(bp, pin_cfg - PIN_CFG_EPIO0, val);
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u8 gpio_num = (pin_cfg - PIN_CFG_GPIO0_P0) & 0x3;
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u8 gpio_port = (pin_cfg - PIN_CFG_GPIO0_P0) >> 2;
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*val = bnx2x_get_gpio(bp, gpio_num, gpio_port);
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************************************/
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*				ETS section			  */
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************************************/
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void bnx2x_ets_e2e3a0_disabled(struct link_params *params)
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* ETS disabled configuration*/
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct bnx2x *bp = params->bp;
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DP(NETIF_MSG_LINK, "ETS E2E3 disabled configuration\n");
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * mapping between entry  priority to client number (0,1,2 -debug and
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * management clients, 3 - COS0 client, 4 - COS client)(HIGHEST)
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * 3bits client num.
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   PRI4    |    PRI3    |    PRI2    |    PRI1    |    PRI0
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * cos1-100     cos0-011     dbg1-010     dbg0-001     MCP-000
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT, 0x4688);
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Bitmap of 5bits length. Each bit specifies whether the entry behaves
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * as strict.  Bits 0,1,2 - debug and management entries, 3 -
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * COS0 entry, 4 - COS1 entry.
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * COS1 | COS0 | DEBUG1 | DEBUG0 | MGMT
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * bit4   bit3	  bit2   bit1	  bit0
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * MCP and debug are strict
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, 0x7);
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* defines which entries (clients) are subjected to WFQ arbitration */
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ, 0);
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * For strict priority entries defines the number of consecutive
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * slots for the highest priority.
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, NIG_REG_P0_TX_ARB_NUM_STRICT_ARB_SLOTS, 0x100);
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * mapping between the CREDIT_WEIGHT registers and actual client
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * numbers
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP, 0);
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0, 0);
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1, 0);
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_0, 0);
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_1, 0);
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, PBF_REG_HIGH_PRIORITY_COS_NUM, 0);
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* ETS mode disable */
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, PBF_REG_ETS_ENABLED, 0);
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If ETS mode is enabled (there is no strict priority) defines a WFQ
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * weight for COS0/COS1.
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, PBF_REG_COS0_WEIGHT, 0x2710);
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, PBF_REG_COS1_WEIGHT, 0x2710);
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Upper bound that COS0_WEIGHT can reach in the WFQ arbiter */
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, PBF_REG_COS0_UPPER_BOUND, 0x989680);
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, PBF_REG_COS1_UPPER_BOUND, 0x989680);
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Defines the number of consecutive slots for the strict priority */
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, PBF_REG_NUM_STRICT_ARB_SLOTS, 0);
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************************************************
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds* Description:
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*	Getting min_w_val will be set according to line speed .
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*.
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds******************************************************************************/
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u32 bnx2x_ets_get_min_w_val_nig(const struct link_vars *vars)
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 min_w_val = 0;
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Calculate min_w_val.*/
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (vars->link_up) {
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (SPEED_20000 == vars->line_speed)
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			min_w_val = ETS_E3B0_NIG_MIN_W_VAL_20GBPS;
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			min_w_val = ETS_E3B0_NIG_MIN_W_VAL_UP_TO_10GBPS;
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		min_w_val = ETS_E3B0_NIG_MIN_W_VAL_20GBPS;
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/**
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *  If the link isn't up (static configuration for example ) The
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *  link will be according to 20GBPS.
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*/
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return min_w_val;
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************************************************
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds* Description:
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*	Getting credit upper bound form min_w_val.
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*.
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds******************************************************************************/
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u32 bnx2x_ets_get_credit_upper_bound(const u32 min_w_val)
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const u32 credit_upper_bound = (u32)MAXVAL((150 * min_w_val),
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						MAX_PACKET_SIZE);
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return credit_upper_bound;
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************************************************
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds* Description:
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*	Set credit upper bound for NIG.
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*.
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds******************************************************************************/
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void bnx2x_ets_e3b0_set_credit_upper_bound_nig(
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const struct link_params *params,
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const u32 min_w_val)
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct bnx2x *bp = params->bp;
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const u8 port = params->port;
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const u32 credit_upper_bound =
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    bnx2x_ets_get_credit_upper_bound(min_w_val);
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_0 :
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_0, credit_upper_bound);
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_1 :
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_1, credit_upper_bound);
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_2 :
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_2, credit_upper_bound);
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_3 :
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_3, credit_upper_bound);
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_4 :
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_4, credit_upper_bound);
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_UPPER_BOUND_5 :
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_5, credit_upper_bound);
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (0 == port) {
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_6,
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			credit_upper_bound);
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_7,
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			credit_upper_bound);
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_8,
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			credit_upper_bound);
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************************************************
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds* Description:
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*	Will return the NIG ETS registers to init values.Except
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*	credit_upper_bound.
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*	That isn't used in this configuration (No WFQ is enabled) and will be
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*	configured acording to spec
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*.
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds******************************************************************************/
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void bnx2x_ets_e3b0_nig_disabled(const struct link_params *params,
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					const struct link_vars *vars)
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct bnx2x *bp = params->bp;
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const u8 port = params->port;
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const u32 min_w_val = bnx2x_ets_get_min_w_val_nig(vars);
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/**
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * mapping between entry  priority to client number (0,1,2 -debug and
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * management clients, 3 - COS0 client, 4 - COS1, ... 8 -
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * COS5)(HIGHEST) 4bits client num.TODO_ETS - Should be done by
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * reset value or init tool
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (port) {
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		REG_WR(bp, NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_LSB, 0x543210);
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		REG_WR(bp, NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_MSB, 0x0);
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_LSB, 0x76543210);
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_MSB, 0x8);
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/**
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	* For strict priority entries defines the number of consecutive
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	* slots for the highest priority.
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*/
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* TODO_ETS - Should be done by reset value or init tool */
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_NUM_STRICT_ARB_SLOTS :
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   NIG_REG_P1_TX_ARB_NUM_STRICT_ARB_SLOTS, 0x100);
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/**
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * mapping between the CREDIT_WEIGHT registers and actual client
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * numbers
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* TODO_ETS - Should be done by reset value or init tool */
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (port) {
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*Port 1 has 6 COS*/
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		REG_WR(bp, NIG_REG_P1_TX_ARB_CLIENT_CREDIT_MAP2_LSB, 0x210543);
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		REG_WR(bp, NIG_REG_P1_TX_ARB_CLIENT_CREDIT_MAP2_MSB, 0x0);
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*Port 0 has 9 COS*/
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP2_LSB,
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       0x43210876);
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP2_MSB, 0x5);
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/**
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Bitmap of 5bits length. Each bit specifies whether the entry behaves
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * as strict.  Bits 0,1,2 - debug and management entries, 3 -
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * COS0 entry, 4 - COS1 entry.
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * COS1 | COS0 | DEBUG1 | DEBUG0 | MGMT
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * bit4   bit3	  bit2   bit1	  bit0
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * MCP and debug are strict
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (port)
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		REG_WR(bp, NIG_REG_P1_TX_ARB_CLIENT_IS_STRICT, 0x3f);
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, 0x1ff);
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* defines which entries (clients) are subjected to WFQ arbitration */
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CLIENT_IS_SUBJECT2WFQ :
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ, 0);
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/**
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	* Please notice the register address are note continuous and a
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	* for here is note appropriate.In 2 port mode port0 only COS0-5
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	* can be used. DEBUG1,DEBUG1,MGMT are never used for WFQ* In 4
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	* port mode port1 only COS0-2 can be used. DEBUG1,DEBUG1,MGMT
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	* are never used for WFQ
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*/
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_0 :
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0, 0x0);
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_1 :
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1, 0x0);
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_2 :
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_2, 0x0);
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_3 :
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_3, 0x0);
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_4 :
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_4, 0x0);
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_5 :
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_5, 0x0);
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (0 == port) {
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_6, 0x0);
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_7, 0x0);
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_8, 0x0);
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_ets_e3b0_set_credit_upper_bound_nig(params, min_w_val);
594096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby}
595096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby/******************************************************************************
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds* Description:
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*	Set credit upper bound for PBF.
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*.
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds******************************************************************************/
60002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_ets_e3b0_set_credit_upper_bound_pbf(
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const struct link_params *params,
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const u32 min_w_val)
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct bnx2x *bp = params->bp;
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const u32 credit_upper_bound =
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    bnx2x_ets_get_credit_upper_bound(min_w_val);
60702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	const u8 port = params->port;
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 base_upper_bound = 0;
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 max_cos = 0;
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 i = 0;
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/**
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	* In 2 port mode port0 has COS0-5 that can be used for WFQ.In 4
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	* port mode port1 has COS0-2 that can be used for WFQ.
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*/
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (0 == port) {
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		base_upper_bound = PBF_REG_COS0_UPPER_BOUND_P0;
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		max_cos = DCBX_E3B0_MAX_NUM_COS_PORT0;
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		base_upper_bound = PBF_REG_COS0_UPPER_BOUND_P1;
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		max_cos = DCBX_E3B0_MAX_NUM_COS_PORT1;
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < max_cos; i++)
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		REG_WR(bp, base_upper_bound + (i << 2), credit_upper_bound);
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************************************************
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds* Description:
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*	Will return the PBF ETS registers to init values.Except
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*	credit_upper_bound.
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*	That isn't used in this configuration (No WFQ is enabled) and will be
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*	configured acording to spec
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*.
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds******************************************************************************/
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void bnx2x_ets_e3b0_pbf_disabled(const struct link_params *params)
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
63733f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox	struct bnx2x *bp = params->bp;
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const u8 port = params->port;
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const u32 min_w_val_pbf = ETS_E3B0_PBF_MIN_W_VAL;
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 i = 0;
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 base_weight = 0;
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 max_cos = 0;
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/**
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * mapping between entry  priority to client number 0 - COS0
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * client, 2 - COS1, ... 5 - COS5)(HIGHEST) 4bits client num.
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * TODO_ETS - Should be done by reset value or init tool
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (port)
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*  0x688 (|011|0 10|00 1|000) */
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		REG_WR(bp, PBF_REG_ETS_ARB_PRIORITY_CLIENT_P1 , 0x688);
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*  (10 1|100 |011|0 10|00 1|000) */
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		REG_WR(bp, PBF_REG_ETS_ARB_PRIORITY_CLIENT_P0 , 0x2C688);
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* TODO_ETS - Should be done by reset value or init tool */
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (port)
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* 0x688 (|011|0 10|00 1|000)*/
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		REG_WR(bp, PBF_REG_ETS_ARB_CLIENT_CREDIT_MAP_P1, 0x688);
66002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	else
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* 0x2C688 (10 1|100 |011|0 10|00 1|000) */
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, PBF_REG_ETS_ARB_CLIENT_CREDIT_MAP_P0, 0x2C688);
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, (port) ? PBF_REG_ETS_ARB_NUM_STRICT_ARB_SLOTS_P1 :
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   PBF_REG_ETS_ARB_NUM_STRICT_ARB_SLOTS_P0 , 0x100);
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, (port) ? PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P1 :
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P0 , 0);
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, (port) ? PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P1 :
67202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		   PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P0 , 0);
67302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/**
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	* In 2 port mode port0 has COS0-5 that can be used for WFQ.
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	* In 4 port mode port1 has COS0-2 that can be used for WFQ.
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*/
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (0 == port) {
678db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby		base_weight = PBF_REG_COS0_WEIGHT_P0;
67902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		max_cos = DCBX_E3B0_MAX_NUM_COS_PORT0;
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
681db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby		base_weight = PBF_REG_COS0_WEIGHT_P1;
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		max_cos = DCBX_E3B0_MAX_NUM_COS_PORT1;
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
684db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < max_cos; i++)
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		REG_WR(bp, base_weight + (0x4 * i), 0);
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_ets_e3b0_set_credit_upper_bound_pbf(params, min_w_val_pbf);
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************************************************
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds* Description:
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*	E3B0 disable will return basicly the values to init values.
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*.
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds******************************************************************************/
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bnx2x_ets_e3b0_disabled(const struct link_params *params,
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   const struct link_vars *vars)
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct bnx2x *bp = params->bp;
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!CHIP_IS_E3B0(bp)) {
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DP(NETIF_MSG_LINK,
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   "bnx2x_ets_e3b0_disabled the chip isn't E3B0\n");
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_ets_e3b0_nig_disabled(params, vars);
70702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
70802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_ets_e3b0_pbf_disabled(params);
70902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
71002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	return 0;
71102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
71202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
71302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/******************************************************************************
71402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby* Description:
71502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby*	Disable will return basicly the values to init values.
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*.
71702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby******************************************************************************/
718fe971071a89c5c5184fc9f3482c7a8e997cf0520Tobias Klauserint bnx2x_ets_disabled(struct link_params *params,
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      struct link_vars *vars)
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct bnx2x *bp = params->bp;
72202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	int bnx2x_status = 0;
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((CHIP_IS_E2(bp)) || (CHIP_IS_E3A0(bp)))
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bnx2x_ets_e2e3a0_disabled(params);
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else if (CHIP_IS_E3B0(bp))
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bnx2x_status = bnx2x_ets_e3b0_disabled(params, vars);
72802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	else {
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DP(NETIF_MSG_LINK, "bnx2x_ets_disabled - chip not supported\n");
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return bnx2x_status;
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************************************************
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds* Description
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*	Set the COS mappimg to SP and BW until this point all the COS are not
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*	set as SP or BW.
74002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby******************************************************************************/
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bnx2x_ets_e3b0_cli_map(const struct link_params *params,
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  const struct bnx2x_ets_params *ets_params,
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  const u8 cos_sp_bitmap,
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  const u8 cos_bw_bitmap)
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct bnx2x *bp = params->bp;
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const u8 port = params->port;
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const u8 nig_cli_sp_bitmap = 0x7 | (cos_sp_bitmap << 3);
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const u8 pbf_cli_sp_bitmap = cos_sp_bitmap;
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const u8 nig_cli_subject2wfq_bitmap = cos_bw_bitmap << 3;
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const u8 pbf_cli_subject2wfq_bitmap = cos_bw_bitmap;
75202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
75302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CLIENT_IS_STRICT :
75402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, nig_cli_sp_bitmap);
75502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
75602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, (port) ? PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P1 :
75702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       PBF_REG_ETS_ARB_CLIENT_IS_STRICT_P0 , pbf_cli_sp_bitmap);
75802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
75902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, (port) ? NIG_REG_P1_TX_ARB_CLIENT_IS_SUBJECT2WFQ :
76002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ,
76102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       nig_cli_subject2wfq_bitmap);
76202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
76302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, (port) ? PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P1 :
76402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       PBF_REG_ETS_ARB_CLIENT_IS_SUBJECT2WFQ_P0,
76502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       pbf_cli_subject2wfq_bitmap);
76602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
76702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	return 0;
76802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
76902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
77002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/******************************************************************************
77102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby* Description:
77202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby*	This function is needed because NIG ARB_CREDIT_WEIGHT_X are
77302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby*	not continues and ARB_CREDIT_WEIGHT_0 + offset is suitable.
77402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby******************************************************************************/
77502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic int bnx2x_ets_e3b0_set_cos_bw(struct bnx2x *bp,
77602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				     const u8 cos_entry,
77702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				     const u32 min_w_val_nig,
77802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				     const u32 min_w_val_pbf,
77902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				     const u16 total_bw,
78002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				     const u8 bw,
78102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				     const u8 port)
78202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
78302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 nig_reg_adress_crd_weight = 0;
78402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 pbf_reg_adress_crd_weight = 0;
78502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Calculate and set BW for this COS - use 1 instead of 0 for BW */
78602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	const u32 cos_bw_nig = ((bw ? bw : 1) * min_w_val_nig) / total_bw;
78702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	const u32 cos_bw_pbf = ((bw ? bw : 1) * min_w_val_pbf) / total_bw;
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (cos_entry) {
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0:
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    nig_reg_adress_crd_weight =
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 (port) ? NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_0 :
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		     NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0;
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	     pbf_reg_adress_crd_weight = (port) ?
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 PBF_REG_COS0_WEIGHT_P1 : PBF_REG_COS0_WEIGHT_P0;
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	     break;
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 1:
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	     nig_reg_adress_crd_weight = (port) ?
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_1 :
80002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		 NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1;
80102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	     pbf_reg_adress_crd_weight = (port) ?
80202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		 PBF_REG_COS1_WEIGHT_P1 : PBF_REG_COS1_WEIGHT_P0;
80302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	     break;
80402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	case 2:
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	     nig_reg_adress_crd_weight = (port) ?
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 NIG_REG_P1_TX_ARB_CREDIT_WEIGHT_2 :
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_2;
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
80902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		 pbf_reg_adress_crd_weight = (port) ?
81002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		     PBF_REG_COS2_WEIGHT_P1 : PBF_REG_COS2_WEIGHT_P0;
81102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	     break;
81202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	case 3:
81302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	    if (port)
81402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			return -EINVAL;
81502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	     nig_reg_adress_crd_weight =
81602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		 NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_3;
81702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	     pbf_reg_adress_crd_weight =
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 PBF_REG_COS3_WEIGHT_P0;
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	     break;
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 4:
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    if (port)
822893de2dffb0923d9bdba4abd66afcec3cf9103baJiri Slaby		return -EINVAL;
823893de2dffb0923d9bdba4abd66afcec3cf9103baJiri Slaby	     nig_reg_adress_crd_weight =
824893de2dffb0923d9bdba4abd66afcec3cf9103baJiri Slaby		 NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_4;
825893de2dffb0923d9bdba4abd66afcec3cf9103baJiri Slaby	     pbf_reg_adress_crd_weight = PBF_REG_COS4_WEIGHT_P0;
826893de2dffb0923d9bdba4abd66afcec3cf9103baJiri Slaby	     break;
827893de2dffb0923d9bdba4abd66afcec3cf9103baJiri Slaby	case 5:
828893de2dffb0923d9bdba4abd66afcec3cf9103baJiri Slaby	    if (port)
829893de2dffb0923d9bdba4abd66afcec3cf9103baJiri Slaby		return -EINVAL;
830893de2dffb0923d9bdba4abd66afcec3cf9103baJiri Slaby	     nig_reg_adress_crd_weight =
831893de2dffb0923d9bdba4abd66afcec3cf9103baJiri Slaby		 NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_5;
83202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	     pbf_reg_adress_crd_weight = PBF_REG_COS5_WEIGHT_P0;
833893de2dffb0923d9bdba4abd66afcec3cf9103baJiri Slaby	     break;
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, nig_reg_adress_crd_weight, cos_bw_nig);
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8381a86b5e34e4d09e3246a983c53929ce38af52275Klaus Kudielka	REG_WR(bp, pbf_reg_adress_crd_weight, cos_bw_pbf);
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
84102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************************************************
84302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby* Description:
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*	Calculate the total BW.A value of 0 isn't legal.
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*.
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds******************************************************************************/
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bnx2x_ets_e3b0_get_total_bw(
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const struct link_params *params,
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const struct bnx2x_ets_params *ets_params,
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 *total_bw)
8518d06afab73a75f40ae2864e6c296356bab1ab473Ingo Molnar{
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct bnx2x *bp = params->bp;
85302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u8 cos_idx = 0;
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*total_bw = 0 ;
85602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Calculate total BW requested */
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (cos_idx = 0; cos_idx < ets_params->num_of_cos; cos_idx++) {
85802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (bnx2x_cos_state_bw == ets_params->cos[cos_idx].state) {
85902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			*total_bw +=
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ets_params->cos[cos_idx].params.bw_params.bw;
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
86202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
863096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby
864096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby	/* Check total BW is valid */
86502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if ((100 != *total_bw) || (0 == *total_bw)) {
86602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (0 == *total_bw) {
86702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			DP(NETIF_MSG_LINK,
86802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			   "bnx2x_ets_E3B0_config toatl BW shouldn't be 0\n");
86902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			return -EINVAL;
870096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby		}
871096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby		DP(NETIF_MSG_LINK,
87202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		   "bnx2x_ets_E3B0_config toatl BW should be 100\n");
87302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/**
87402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		*   We can handle a case whre the BW isn't 100 this can happen
87502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		*   if the TC are joined.
876096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby		*/
877096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby	}
87802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	return 0;
87902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
88102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/******************************************************************************
88202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby* Description:
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*	Invalidate all the sp_pri_to_cos.
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*.
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds******************************************************************************/
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void bnx2x_ets_e3b0_sp_pri_to_cos_init(u8 *sp_pri_to_cos)
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 pri = 0;
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (pri = 0; pri < DCBX_MAX_NUM_COS; pri++)
89002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		sp_pri_to_cos[pri] = DCBX_INVALID_COS;
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
89202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/******************************************************************************
89302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby* Description:
89402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby*	Calculate and set the SP (ARB_PRIORITY_CLIENT) NIG and PBF registers
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*	according to sp_pri_to_cos.
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*.
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds******************************************************************************/
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bnx2x_ets_e3b0_sp_pri_to_cos_set(const struct link_params *params,
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    u8 *sp_pri_to_cos, const u8 pri,
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    const u8 cos_entry)
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct bnx2x *bp = params->bp;
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const u8 port = params->port;
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const u8 max_num_of_cos = (port) ? DCBX_E3B0_MAX_NUM_COS_PORT1 :
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DCBX_E3B0_MAX_NUM_COS_PORT0;
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (DCBX_INVALID_COS != sp_pri_to_cos[pri]) {
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid "
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   "parameter There can't be two COS's with "
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   "the same strict pri\n");
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (pri > max_num_of_cos) {
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid "
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       "parameter Illegal strict priority\n");
917c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells	    return -EINVAL;
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
919c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells
920c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells	sp_pri_to_cos[pri] = cos_entry;
92102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	return 0;
92202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
92302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
92402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
92502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/******************************************************************************
92602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby* Description:
92702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby*	Returns the correct value according to COS and priority in
92802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby*	the sp_pri_cli register.
92902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby*.
93002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby******************************************************************************/
93102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic u64 bnx2x_e3b0_sp_get_pri_cli_reg(const u8 cos, const u8 cos_offset,
93202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					 const u8 pri_set,
93302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					 const u8 pri_offset,
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					 const u8 entry_size)
93502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
93602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u64 pri_cli_nig = 0;
93702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	pri_cli_nig = ((u64)(cos + cos_offset)) << (entry_size *
93802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby						    (pri_set + pri_offset));
93902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
94002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	return pri_cli_nig;
94102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
94202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/******************************************************************************
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds* Description:
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*	Returns the correct value according to COS and priority in the
94502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby*	sp_pri_cli register for NIG.
94602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby*.
94702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby******************************************************************************/
9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u64 bnx2x_e3b0_sp_get_pri_cli_reg_nig(const u8 cos, const u8 pri_set)
94902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
95002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* MCP Dbg0 and dbg1 are always with higher strict pri*/
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const u8 nig_cos_offset = 3;
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const u8 nig_pri_offset = 3;
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return bnx2x_e3b0_sp_get_pri_cli_reg(cos, nig_cos_offset, pri_set,
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nig_pri_offset, 4);
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************************************************
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds* Description:
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*	Returns the correct value according to COS and priority in the
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*	sp_pri_cli register for PBF.
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*.
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds******************************************************************************/
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u64 bnx2x_e3b0_sp_get_pri_cli_reg_pbf(const u8 cos, const u8 pri_set)
96502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const u8 pbf_cos_offset = 0;
967ad39c3004971173baeca80173e77022ee03eb9a1Jiri Slaby	const u8 pbf_pri_offset = 0;
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
96902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	return bnx2x_e3b0_sp_get_pri_cli_reg(cos, pbf_cos_offset, pri_set,
97002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		pbf_pri_offset, 3);
971db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby
97202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
97302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
97402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/******************************************************************************
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds* Description:
97602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby*	Calculate and set the SP (ARB_PRIORITY_CLIENT) NIG and PBF registers
97702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby*	according to sp_pri_to_cos.(which COS has higher priority)
97802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby*.
979096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby******************************************************************************/
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bnx2x_ets_e3b0_sp_set_pri_cli_reg(const struct link_params *params,
98102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					     u8 *sp_pri_to_cos)
98202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct bnx2x *bp = params->bp;
984096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby	u8 i = 0;
98502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	const u8 port = params->port;
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* MCP Dbg0 and dbg1 are always with higher strict pri*/
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u64 pri_cli_nig = 0x210;
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 pri_cli_pbf = 0x0;
98902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u8 pri_set = 0;
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 pri_bitmask = 0;
99102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	const u8 max_num_of_cos = (port) ? DCBX_E3B0_MAX_NUM_COS_PORT1 :
99202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		DCBX_E3B0_MAX_NUM_COS_PORT0;
99302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
99402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u8 cos_bit_to_set = (1 << max_num_of_cos) - 1;
99502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
99602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Set all the strict priority first */
99702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	for (i = 0; i < max_num_of_cos; i++) {
99802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (DCBX_INVALID_COS != sp_pri_to_cos[i]) {
99902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			if (DCBX_MAX_NUM_COS <= sp_pri_to_cos[i]) {
100002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				DP(NETIF_MSG_LINK,
100102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					   "bnx2x_ets_e3b0_sp_set_pri_cli_reg "
100202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					   "invalid cos entry\n");
100302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				return -EINVAL;
100402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			}
100502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
100602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			pri_cli_nig |= bnx2x_e3b0_sp_get_pri_cli_reg_nig(
100702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			    sp_pri_to_cos[i], pri_set);
100802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
100902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			pri_cli_pbf |= bnx2x_e3b0_sp_get_pri_cli_reg_pbf(
101002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			    sp_pri_to_cos[i], pri_set);
101102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			pri_bitmask = 1 << sp_pri_to_cos[i];
101202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			/* COS is used remove it from bitmap.*/
101302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			if (0 == (pri_bitmask & cos_bit_to_set)) {
1014db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby				DP(NETIF_MSG_LINK,
101502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					"bnx2x_ets_e3b0_sp_set_pri_cli_reg "
101602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					"invalid There can't be two COS's with"
101702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					" the same strict pri\n");
101802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				return -EINVAL;
101902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			}
102002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			cos_bit_to_set &= ~pri_bitmask;
102102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			pri_set++;
102202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		}
102302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
1024db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby
1025db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	/* Set all the Non strict priority i= COS*/
102602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	for (i = 0; i < max_num_of_cos; i++) {
102702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		pri_bitmask = 1 << i;
1028db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby		/* Check if COS was already used for SP */
102902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (pri_bitmask & cos_bit_to_set) {
103002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			/* COS wasn't used for SP */
103102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			pri_cli_nig |= bnx2x_e3b0_sp_get_pri_cli_reg_nig(
103202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			    i, pri_set);
103302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
103402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			pri_cli_pbf |= bnx2x_e3b0_sp_get_pri_cli_reg_pbf(
10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    i, pri_set);
103602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			/* COS is used remove it from bitmap.*/
10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cos_bit_to_set &= ~pri_bitmask;
1038e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby			pri_set++;
103902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		}
1040e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby	}
1041e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby
1042e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby	if (pri_set != max_num_of_cos) {
1043ad39c3004971173baeca80173e77022ee03eb9a1Jiri Slaby		DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_set_pri_cli_reg not all "
1044e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby				   "entries were set\n");
1045e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby		return -EINVAL;
1046e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby	}
1047e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby
104802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (port) {
1049e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby		/* Only 6 usable clients*/
105002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		REG_WR(bp, NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_LSB,
1051e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby		       (u32)pri_cli_nig);
105202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
105302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		REG_WR(bp, PBF_REG_ETS_ARB_PRIORITY_CLIENT_P1 , pri_cli_pbf);
1054db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	} else {
105502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* Only 9 usable clients*/
105602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		const u32 pri_cli_nig_lsb = (u32) (pri_cli_nig);
105702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		const u32 pri_cli_nig_msb = (u32) ((pri_cli_nig >> 32) & 0xF);
105802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
1059db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby		REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_LSB,
106002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		       pri_cli_nig_lsb);
106102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_MSB,
106202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		       pri_cli_nig_msb);
106302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
1064db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby		REG_WR(bp, PBF_REG_ETS_ARB_PRIORITY_CLIENT_P0 , pri_cli_pbf);
106502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
106602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	return 0;
1067db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby}
106802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
1069db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby/******************************************************************************
107002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby* Description:
107102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby*	Configure the COS to ETS according to BW and SP settings.
1072db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby******************************************************************************/
107302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabyint bnx2x_ets_e3b0_config(const struct link_params *params,
1074e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby			 const struct link_vars *vars,
1075e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby			 const struct bnx2x_ets_params *ets_params)
107602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
107702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
1078db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	int bnx2x_status = 0;
107902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	const u8 port = params->port;
108002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u16 total_bw = 0;
1081db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	const u32 min_w_val_nig = bnx2x_ets_get_min_w_val_nig(vars);
108202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	const u32 min_w_val_pbf = ETS_E3B0_PBF_MIN_W_VAL;
108302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u8 cos_bw_bitmap = 0;
108402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u8 cos_sp_bitmap = 0;
108502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u8 sp_pri_to_cos[DCBX_MAX_NUM_COS] = {0};
108602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	const u8 max_num_of_cos = (port) ? DCBX_E3B0_MAX_NUM_COS_PORT1 :
108702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		DCBX_E3B0_MAX_NUM_COS_PORT0;
108802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u8 cos_entry = 0;
108902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
109002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (!CHIP_IS_E3B0(bp)) {
109102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		DP(NETIF_MSG_LINK,
109202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		   "bnx2x_ets_e3b0_disabled the chip isn't E3B0\n");
109302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		return -EINVAL;
109402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
109502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
109602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if ((ets_params->num_of_cos > max_num_of_cos)) {
109702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config the number of COS "
109802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				   "isn't supported\n");
109902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		return -EINVAL;
110002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
110102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
1102db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	/* Prepare sp strict priority parameters*/
110302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_ets_e3b0_sp_pri_to_cos_init(sp_pri_to_cos);
110402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
110502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Prepare BW parameters*/
110602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_status = bnx2x_ets_e3b0_get_total_bw(params, ets_params,
110702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby						   &total_bw);
110802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (0 != bnx2x_status) {
110902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		DP(NETIF_MSG_LINK,
111002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		   "bnx2x_ets_E3B0_config get_total_bw failed\n");
111102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		return -EINVAL;
111202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
111302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
111402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/**
1115db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	 *  Upper bound is set according to current link speed (min_w_val
111602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 *  should be the same for upper bound and COS credit val).
111702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 */
111802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_ets_e3b0_set_credit_upper_bound_nig(params, min_w_val_nig);
111902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_ets_e3b0_set_credit_upper_bound_pbf(params, min_w_val_pbf);
112002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
112102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
112202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	for (cos_entry = 0; cos_entry < ets_params->num_of_cos; cos_entry++) {
112302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (bnx2x_cos_state_bw == ets_params->cos[cos_entry].state) {
112402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			cos_bw_bitmap |= (1 << cos_entry);
112502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			/**
112602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 * The function also sets the BW in HW(not the mappin
1127db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby			 * yet)
112802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 */
112902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			bnx2x_status = bnx2x_ets_e3b0_set_cos_bw(
113002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				bp, cos_entry, min_w_val_nig, min_w_val_pbf,
113102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				total_bw,
113202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				ets_params->cos[cos_entry].params.bw_params.bw,
113302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				 port);
113402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		} else if (bnx2x_cos_state_strict ==
113502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			ets_params->cos[cos_entry].state){
113602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			cos_sp_bitmap |= (1 << cos_entry);
113702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
113802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			bnx2x_status = bnx2x_ets_e3b0_sp_pri_to_cos_set(
113902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				params,
114002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				sp_pri_to_cos,
114102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				ets_params->cos[cos_entry].params.sp_params.pri,
114202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				cos_entry);
114302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
114402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		} else {
114502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			DP(NETIF_MSG_LINK,
1146db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby			   "bnx2x_ets_e3b0_config cos state not valid\n");
114702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			return -EINVAL;
114802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		}
114902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (0 != bnx2x_status) {
115002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			DP(NETIF_MSG_LINK,
115102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			   "bnx2x_ets_e3b0_config set cos bw failed\n");
115202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			return bnx2x_status;
115302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		}
115402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
115502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
115602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Set SP register (which COS has higher priority) */
115702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_status = bnx2x_ets_e3b0_sp_set_pri_cli_reg(params,
115802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby							 sp_pri_to_cos);
115902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
116002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (0 != bnx2x_status) {
116102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		DP(NETIF_MSG_LINK,
116202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		   "bnx2x_ets_E3B0_config set_pri_cli_reg failed\n");
116302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		return bnx2x_status;
116402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
116502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
116602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Set client mapping of BW and strict */
116702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_status = bnx2x_ets_e3b0_cli_map(params, ets_params,
116802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					      cos_sp_bitmap,
116902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					      cos_bw_bitmap);
117002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
117102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (0 != bnx2x_status) {
117202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		DP(NETIF_MSG_LINK, "bnx2x_ets_E3B0_config SP failed\n");
117302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		return bnx2x_status;
117402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
117502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	return 0;
117602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
117702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_ets_bw_limit_common(const struct link_params *params)
1178db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby{
117902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* ETS disabled configuration */
1180e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby	struct bnx2x *bp = params->bp;
1181e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby	DP(NETIF_MSG_LINK, "ETS enabled BW limit configuration\n");
118202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/*
118302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * defines which entries (clients) are subjected to WFQ arbitration
118402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * COS0 0x8
118502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * COS1 0x10
118602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 */
1187e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby	REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ, 0x18);
118802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/*
118902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * mapping between the ARB_CREDIT_WEIGHT registers and actual
1190db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	 * client numbers (WEIGHT_0 does not actually have to represent
119102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * client 0)
119202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 *    PRI4    |    PRI3    |    PRI2    |    PRI1    |    PRI0
119302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 *  cos1-001     cos0-000     dbg1-100     dbg0-011     MCP-010
119402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 */
119502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP, 0x111A);
1196e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby
119702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_0,
1198e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby	       ETS_BW_LIMIT_CREDIT_UPPER_BOUND);
119902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_1,
120002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       ETS_BW_LIMIT_CREDIT_UPPER_BOUND);
120102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
120202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* ETS mode enabled*/
1203e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby	REG_WR(bp, PBF_REG_ETS_ENABLED, 1);
120402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
120502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Defines the number of consecutive slots for the strict priority */
120602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, PBF_REG_NUM_STRICT_ARB_SLOTS, 0);
120702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/*
1208e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby	 * Bitmap of 5bits length. Each bit specifies whether the entry behaves
1209e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby	 * as strict.  Bits 0,1,2 - debug and management entries, 3 - COS0
121002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * entry, 4 - COS1 entry.
121102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * COS1 | COS0 | DEBUG21 | DEBUG0 | MGMT
121202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * bit4   bit3	  bit2     bit1	   bit0
121302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * MCP and debug are strict
1214e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby	 */
121502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, 0x7);
1216e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby
1217e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby	/* Upper bound that COS0_WEIGHT can reach in the WFQ arbiter.*/
121802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, PBF_REG_COS0_UPPER_BOUND,
121902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       ETS_BW_LIMIT_CREDIT_UPPER_BOUND);
1220db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	REG_WR(bp, PBF_REG_COS1_UPPER_BOUND,
122102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       ETS_BW_LIMIT_CREDIT_UPPER_BOUND);
122202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
1223db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby
122402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabyvoid bnx2x_ets_bw_limit(const struct link_params *params, const u32 cos0_bw,
122502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			const u32 cos1_bw)
122602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
122702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* ETS disabled configuration*/
122802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
1229db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	const u32 total_bw = cos0_bw + cos1_bw;
123002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 cos0_credit_weight = 0;
123102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 cos1_credit_weight = 0;
1232e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby
123302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	DP(NETIF_MSG_LINK, "ETS enabled BW limit configuration\n");
123402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
123502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if ((0 == total_bw) ||
123602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	    (0 == cos0_bw) ||
1237db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	    (0 == cos1_bw)) {
123802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		DP(NETIF_MSG_LINK, "Total BW can't be zero\n");
123902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		return;
1240e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby	}
124102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
124202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	cos0_credit_weight = (cos0_bw * ETS_BW_LIMIT_CREDIT_WEIGHT)/
124302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		total_bw;
124402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	cos1_credit_weight = (cos1_bw * ETS_BW_LIMIT_CREDIT_WEIGHT)/
124502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		total_bw;
124602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
124702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_ets_bw_limit_common(params);
124802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
124902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_0, cos0_credit_weight);
125002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_WEIGHT_1, cos1_credit_weight);
1251e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby
125202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, PBF_REG_COS0_WEIGHT, cos0_credit_weight);
125302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, PBF_REG_COS1_WEIGHT, cos1_credit_weight);
125402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
125502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
125602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabyint bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos)
125702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
125802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* ETS disabled configuration*/
125902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
126002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 val	= 0;
126102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
126202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	DP(NETIF_MSG_LINK, "ETS enabled strict configuration\n");
126302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/*
126402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * Bitmap of 5bits length. Each bit specifies whether the entry behaves
126502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * as strict.  Bits 0,1,2 - debug and management entries,
1266e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby	 * 3 - COS0 entry, 4 - COS1 entry.
126702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 *  COS1 | COS0 | DEBUG21 | DEBUG0 | MGMT
126802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 *  bit4   bit3	  bit2      bit1     bit0
126902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * MCP and debug are strict
1270db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	 */
127102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, 0x1F);
127202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/*
1273db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	 * For strict priority entries defines the number of consecutive slots
127402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * for the highest priority.
127502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 */
127602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, NIG_REG_P0_TX_ARB_NUM_STRICT_ARB_SLOTS, 0x100);
127702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* ETS mode disable */
1278db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	REG_WR(bp, PBF_REG_ETS_ENABLED, 0);
127902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Defines the number of consecutive slots for the strict priority */
128002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, PBF_REG_NUM_STRICT_ARB_SLOTS, 0x100);
128102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
128202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Defines the number of consecutive slots for the strict priority */
128302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, PBF_REG_HIGH_PRIORITY_COS_NUM, strict_cos);
128402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
128502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/*
1286db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	 * mapping between entry  priority to client number (0,1,2 -debug and
128702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * management clients, 3 - COS0 client, 4 - COS client)(HIGHEST)
128802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * 3bits client num.
128902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 *   PRI4    |    PRI3    |    PRI2    |    PRI1    |    PRI0
129002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * dbg0-010     dbg1-001     cos1-100     cos0-011     MCP-000
129102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * dbg0-010     dbg1-001     cos0-011     cos1-100     MCP-000
1292db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	 */
129302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val = (0 == strict_cos) ? 0x2318 : 0x22E0;
129402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT, val);
129502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
129602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	return 0;
129702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
129802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/******************************************************************/
129902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/*			PFC section				  */
130002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/******************************************************************/
130102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
130202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_update_pfc_xmac(struct link_params *params,
130302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				  struct link_vars *vars,
130402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				  u8 is_lb)
130502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
130602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
130702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 xmac_base;
130802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 pause_val, pfc0_val, pfc1_val;
130902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
131002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* XMAC base adrr */
131102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	xmac_base = (params->port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
131202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
131302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Initialize pause and pfc registers */
131402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	pause_val = 0x18000;
131502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	pfc0_val = 0xFFFF8000;
131602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	pfc1_val = 0x2;
131702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
131802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* No PFC support */
131902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (!(params->feature_config_flags &
132002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	      FEATURE_CONFIG_PFC_ENABLED)) {
132102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
132202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/*
132302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		 * RX flow control - Process pause frame in receive direction
132402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		 */
132502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
132602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			pause_val |= XMAC_PAUSE_CTRL_REG_RX_PAUSE_EN;
132702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
1328e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby		/*
1329e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby		 * TX flow control - Send pause packet when buffer is full
1330e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby		 */
133102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
133202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			pause_val |= XMAC_PAUSE_CTRL_REG_TX_PAUSE_EN;
133302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	} else {/* PFC support */
1334e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby		pfc1_val |= XMAC_PFC_CTRL_HI_REG_PFC_REFRESH_EN |
133502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			XMAC_PFC_CTRL_HI_REG_PFC_STATS_EN |
133602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			XMAC_PFC_CTRL_HI_REG_RX_PFC_EN |
133702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			XMAC_PFC_CTRL_HI_REG_TX_PFC_EN;
133802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
1339e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby
1340e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby	/* Write pause and PFC registers */
134102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, xmac_base + XMAC_REG_PAUSE_CTRL, pause_val);
1342e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby	REG_WR(bp, xmac_base + XMAC_REG_PFC_CTRL, pfc0_val);
134302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, xmac_base + XMAC_REG_PFC_CTRL_HI, pfc1_val);
134402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
1345db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby
134602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Set MAC address for source TX Pause/PFC frames */
134702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, xmac_base + XMAC_REG_CTRL_SA_LO,
134802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       ((params->mac_addr[2] << 24) |
1349db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby		(params->mac_addr[3] << 16) |
135002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		(params->mac_addr[4] << 8) |
135102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		(params->mac_addr[5])));
1352db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	REG_WR(bp, xmac_base + XMAC_REG_CTRL_SA_HI,
1353db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	       ((params->mac_addr[0] << 8) |
135402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		(params->mac_addr[1])));
135502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
135602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	udelay(30);
135702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
135802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
135902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
136002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_emac_get_pfc_stat(struct link_params *params,
136102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				    u32 pfc_frames_sent[2],
136202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				    u32 pfc_frames_received[2])
136302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
136402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Read pfc statistic */
136502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
136602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 emac_base = params->port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
136702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 val_xon = 0;
136802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 val_xoff = 0;
136902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
1370e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby	DP(NETIF_MSG_LINK, "pfc statistic read from EMAC\n");
137102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
137202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* PFC received frames */
137302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val_xoff = REG_RD(bp, emac_base +
137402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				EMAC_REG_RX_PFC_STATS_XOFF_RCVD);
137502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val_xoff &= EMAC_REG_RX_PFC_STATS_XOFF_RCVD_COUNT;
137602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val_xon = REG_RD(bp, emac_base + EMAC_REG_RX_PFC_STATS_XON_RCVD);
137702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val_xon &= EMAC_REG_RX_PFC_STATS_XON_RCVD_COUNT;
137802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
137902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	pfc_frames_received[0] = val_xon + val_xoff;
138002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
138102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* PFC received sent */
138202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val_xoff = REG_RD(bp, emac_base +
138302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				EMAC_REG_RX_PFC_STATS_XOFF_SENT);
138402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val_xoff &= EMAC_REG_RX_PFC_STATS_XOFF_SENT_COUNT;
138502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val_xon = REG_RD(bp, emac_base + EMAC_REG_RX_PFC_STATS_XON_SENT);
138602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val_xon &= EMAC_REG_RX_PFC_STATS_XON_SENT_COUNT;
138702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
138802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	pfc_frames_sent[0] = val_xon + val_xoff;
138902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
1390db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby
139102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/* Read pfc statistic*/
139202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabyvoid bnx2x_pfc_statistic(struct link_params *params, struct link_vars *vars,
139302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 u32 pfc_frames_sent[2],
139402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 u32 pfc_frames_received[2])
139502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
139602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Read pfc statistic */
139702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
139802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
139902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	DP(NETIF_MSG_LINK, "pfc statistic\n");
140002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
140102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (!vars->link_up)
140202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		return;
140302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
1404db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	if (MAC_TYPE_EMAC == vars->mac_type) {
140502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		DP(NETIF_MSG_LINK, "About to read PFC stats from EMAC\n");
140602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		bnx2x_emac_get_pfc_stat(params, pfc_frames_sent,
140702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					pfc_frames_received);
140802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
140902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
141002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/******************************************************************/
141102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/*			MAC/PBF section				  */
141202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/******************************************************************/
141302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_set_mdio_clk(struct bnx2x *bp, u32 chip_id, u8 port)
1414e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby{
1415e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby	u32 mode, emac_base;
141602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/**
141702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * Set clause 45 mode, slow down the MDIO clock to 2.5MHz
141802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * (a value of 49==0x31) and make sure that the AUTO poll is off
141902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 */
1420e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby
1421e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby	if (CHIP_IS_E2(bp))
1422e941027f53648ac3384057032be1ac64da3e8cd0Jiri Slaby		emac_base = GRCBASE_EMAC0;
14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
14241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mode = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE);
14261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mode &= ~(EMAC_MDIO_MODE_AUTO_POLL |
142702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		  EMAC_MDIO_MODE_CLOCK_CNT);
14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (USES_WARPCORE(bp))
142902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		mode |= (74L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT);
143002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	else
143102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		mode |= (49L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT);
143202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
143302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	mode |= (EMAC_MDIO_MODE_CLAUSE_45);
143402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE, mode);
143502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
143602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	udelay(40);
143702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
143902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_emac_init(struct link_params *params,
14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    struct link_vars *vars)
144102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
144202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* reset and unreset the emac core */
144302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
144402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u8 port = params->port;
144502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
144602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 val;
144702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u16 timeout;
144802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
144902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
145002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
145102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	udelay(5);
145202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
145302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
145402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
145502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* init emac - use read-modify-write */
145602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* self clear reset */
145702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
1458db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	EMAC_WR(bp, EMAC_REG_EMAC_MODE, (val | EMAC_MODE_RESET));
145902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
146002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	timeout = 200;
146102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	do {
146202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
146302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		DP(NETIF_MSG_LINK, "EMAC reset reg is %u\n", val);
146402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (!timeout) {
146502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			DP(NETIF_MSG_LINK, "EMAC timeout!\n");
146602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			return;
146702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		}
146802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		timeout--;
146902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	} while (val & EMAC_MODE_RESET);
147002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_set_mdio_clk(bp, params->chip_id, port);
147102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Set mac address */
147202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val = ((params->mac_addr[0] << 8) |
147302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		params->mac_addr[1]);
147402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH, val);
147502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
147602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val = ((params->mac_addr[2] << 24) |
147702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       (params->mac_addr[3] << 16) |
147802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       (params->mac_addr[4] << 8) |
147902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		params->mac_addr[5]);
148002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + 4, val);
148102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void bnx2x_set_xumac_nig(struct link_params *params,
14841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				u16 tx_pause_en,
14851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				u8 enable)
14861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct bnx2x *bp = params->bp;
14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
148902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, params->port ? NIG_REG_P1_MAC_IN_EN : NIG_REG_P0_MAC_IN_EN,
14901a86b5e34e4d09e3246a983c53929ce38af52275Klaus Kudielka	       enable);
14911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, params->port ? NIG_REG_P1_MAC_OUT_EN : NIG_REG_P0_MAC_OUT_EN,
149202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       enable);
149302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, params->port ? NIG_REG_P1_MAC_PAUSE_OUT_EN :
149402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       NIG_REG_P0_MAC_PAUSE_OUT_EN, tx_pause_en);
149502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
149602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
149702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_umac_disable(struct link_params *params)
149802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
1499096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby	u32 umac_base = params->port ? GRCBASE_UMAC1 : GRCBASE_UMAC0;
150002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
1501db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	if (!(REG_RD(bp, MISC_REG_RESET_REG_2) &
150202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		   (MISC_REGISTERS_RESET_REG_2_UMAC0 << params->port)))
150302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		return;
1504db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby
150502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Disable RX and TX */
150602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, umac_base + UMAC_REG_COMMAND_CONFIG, 0);
150702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
1508db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby
1509db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slabystatic void bnx2x_umac_enable(struct link_params *params,
151002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			    struct link_vars *vars, u8 lb)
151102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
151202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 val;
151302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 umac_base = params->port ? GRCBASE_UMAC1 : GRCBASE_UMAC0;
151402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
151502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Reset UMAC */
15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       (MISC_REGISTERS_RESET_REG_2_UMAC0 << params->port));
151802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	usleep_range(1000, 1000);
15191a86b5e34e4d09e3246a983c53929ce38af52275Klaus Kudielka
15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
152102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       (MISC_REGISTERS_RESET_REG_2_UMAC0 << params->port));
152202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
152302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	DP(NETIF_MSG_LINK, "enabling UMAC\n");
15241a86b5e34e4d09e3246a983c53929ce38af52275Klaus Kudielka
152502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/**
152602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * This register determines on which events the MAC will assert
152702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * error on the i/f to the NIG along w/ EOP.
152802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 */
1529096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby
153002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/**
1531db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	 * BD REG_WR(bp, NIG_REG_P0_MAC_RSV_ERR_MASK +
153202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * params->port*0x14,      0xfffff.
153302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 */
153402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* This register opens the gate for the UMAC despite its name */
153502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + params->port*4, 1);
153602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
1537db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	val = UMAC_COMMAND_CONFIG_REG_PROMIS_EN |
153802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		UMAC_COMMAND_CONFIG_REG_PAD_EN |
1539db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby		UMAC_COMMAND_CONFIG_REG_SW_RESET |
154002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		UMAC_COMMAND_CONFIG_REG_NO_LGTH_CHECK;
154102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	switch (vars->line_speed) {
154202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	case SPEED_10:
154302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		val |= (0<<2);
154402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		break;
154502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	case SPEED_100:
154602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		val |= (1<<2);
1547096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby		break;
154802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	case SPEED_1000:
15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val |= (2<<2);
15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1551ad39c3004971173baeca80173e77022ee03eb9a1Jiri Slaby	case SPEED_2500:
1552ad39c3004971173baeca80173e77022ee03eb9a1Jiri Slaby		val |= (3<<2);
15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
155402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	default:
155502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		DP(NETIF_MSG_LINK, "Invalid speed for UMAC %d\n",
1556ad39c3004971173baeca80173e77022ee03eb9a1Jiri Slaby			       vars->line_speed);
155702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		break;
15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
155902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (!(vars->flow_ctrl & BNX2X_FLOW_CTRL_TX))
15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val |= UMAC_COMMAND_CONFIG_REG_IGNORE_TX_PAUSE;
156102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(vars->flow_ctrl & BNX2X_FLOW_CTRL_RX))
1563ad39c3004971173baeca80173e77022ee03eb9a1Jiri Slaby		val |= UMAC_COMMAND_CONFIG_REG_PAUSE_IGNORE;
15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1565db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	REG_WR(bp, umac_base + UMAC_REG_COMMAND_CONFIG, val);
1566db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	udelay(50);
1567db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby
1568db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	/* Set MAC address for source TX Pause/PFC frames (under SW reset) */
156902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, umac_base + UMAC_REG_MAC_ADDR0,
157002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       ((params->mac_addr[2] << 24) |
157102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		(params->mac_addr[3] << 16) |
157202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		(params->mac_addr[4] << 8) |
15731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(params->mac_addr[5])));
157402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, umac_base + UMAC_REG_MAC_ADDR1,
157502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       ((params->mac_addr[0] << 8) |
157602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		(params->mac_addr[1])));
15771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Enable RX and TX */
157902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val &= ~UMAC_COMMAND_CONFIG_REG_PAD_EN;
158002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val |= UMAC_COMMAND_CONFIG_REG_TX_ENA |
158102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		UMAC_COMMAND_CONFIG_REG_RX_ENA;
158202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, umac_base + UMAC_REG_COMMAND_CONFIG, val);
158302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	udelay(50);
15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
158502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Remove SW Reset */
158602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val &= ~UMAC_COMMAND_CONFIG_REG_SW_RESET;
158702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
158802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Check loopback mode */
158902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (lb)
159002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		val |= UMAC_COMMAND_CONFIG_REG_LOOP_ENA;
15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, umac_base + UMAC_REG_COMMAND_CONFIG, val);
159202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
159302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/*
159402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * Maximum Frame Length (RW). Defines a 14-Bit maximum frame
159502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * length used by the MAC receive logic to check frames.
159602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 */
159702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, umac_base + UMAC_REG_MAXFR, 0x2710);
159802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_set_xumac_nig(params,
159902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			    ((vars->flow_ctrl & BNX2X_FLOW_CTRL_TX) != 0), 1);
160002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	vars->mac_type = MAC_TYPE_UMAC;
160102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
160202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
160302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
160402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic u8 bnx2x_is_4_port_mode(struct bnx2x *bp)
160502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
160602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 port4mode_ovwr_val;
160702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Check 4-port override enabled */
160802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	port4mode_ovwr_val = REG_RD(bp, MISC_REG_PORT4MODE_EN_OVWR);
160902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (port4mode_ovwr_val & (1<<0)) {
161002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* Return 4-port mode override value */
161102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		return ((port4mode_ovwr_val & (1<<1)) == (1<<1));
161202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
161302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Return 4-port mode from input pin */
161402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	return (u8)REG_RD(bp, MISC_REG_PORT4MODE_EN);
16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
161602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
161702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/* Define the XMAC mode */
1618db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slabystatic void bnx2x_xmac_init(struct link_params *params, u32 max_speed)
161902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
162002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
162102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 is_port4mode = bnx2x_is_4_port_mode(bp);
162202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
162302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/**
162402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	* In 4-port mode, need to set the mode only once, so if XMAC is
16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	* already out of reset, it means the mode has already been set,
16261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	* and it must not* reset the XMAC again, since it controls both
162702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	* ports of the path
162802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	**/
1629db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby
163002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if ((CHIP_NUM(bp) == CHIP_NUM_57840) &&
163102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	    (REG_RD(bp, MISC_REG_RESET_REG_2) &
163202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	     MISC_REGISTERS_RESET_REG_2_XMAC)) {
163302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		DP(NETIF_MSG_LINK,
1634db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby		   "XMAC already out of reset in 4-port mode\n");
163502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		return;
163602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
16371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
163802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Hard reset */
163902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
164002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       MISC_REGISTERS_RESET_REG_2_XMAC);
164102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	usleep_range(1000, 1000);
164202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       MISC_REGISTERS_RESET_REG_2_XMAC);
16451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (is_port4mode) {
16461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DP(NETIF_MSG_LINK, "Init XMAC to 2 ports x 10G per path\n");
1647ad39c3004971173baeca80173e77022ee03eb9a1Jiri Slaby
1648ad39c3004971173baeca80173e77022ee03eb9a1Jiri Slaby		/*  Set the number of ports on the system side to up to 2 */
16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		REG_WR(bp, MISC_REG_XMAC_CORE_PORT_MODE, 1);
165002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
165102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* Set the number of ports on the Warp Core to 10G */
165202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		REG_WR(bp, MISC_REG_XMAC_PHY_PORT_MODE, 3);
1653ad39c3004971173baeca80173e77022ee03eb9a1Jiri Slaby	} else {
16541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*  Set the number of ports on the system side to 1 */
165502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		REG_WR(bp, MISC_REG_XMAC_CORE_PORT_MODE, 0);
16561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (max_speed == SPEED_10000) {
1657ad39c3004971173baeca80173e77022ee03eb9a1Jiri Slaby			DP(NETIF_MSG_LINK,
16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   "Init XMAC to 10G x 1 port per path\n");
165902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			/* Set the number of ports on the Warp Core to 10G */
166002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			REG_WR(bp, MISC_REG_XMAC_PHY_PORT_MODE, 3);
16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
1662db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby			DP(NETIF_MSG_LINK,
1663db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby			   "Init XMAC to 20G x 2 ports per path\n");
1664db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby			/* Set the number of ports on the Warp Core to 20G */
1665db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby			REG_WR(bp, MISC_REG_XMAC_PHY_PORT_MODE, 1);
166602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		}
166702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
166802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Soft reset */
166902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
16701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       MISC_REGISTERS_RESET_REG_2_XMAC_SOFT);
167102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	usleep_range(1000, 1000);
16721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
167302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
167402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       MISC_REGISTERS_RESET_REG_2_XMAC_SOFT);
167502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
16761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
167702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
167802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_xmac_disable(struct link_params *params)
16791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
168002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u8 port = params->port;
168102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
168202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 pfc_ctrl, xmac_base = (port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
168302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
168402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (REG_RD(bp, MISC_REG_RESET_REG_2) &
168502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	    MISC_REGISTERS_RESET_REG_2_XMAC) {
168602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/*
168702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		 * Send an indication to change the state in the NIG back to XON
16881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Clearing this bit enables the next set of this bit to get
168902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		 * rising edge
169002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		 */
169102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		pfc_ctrl = REG_RD(bp, xmac_base + XMAC_REG_PFC_CTRL_HI);
169202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		REG_WR(bp, xmac_base + XMAC_REG_PFC_CTRL_HI,
169302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		       (pfc_ctrl & ~(1<<1)));
169402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		REG_WR(bp, xmac_base + XMAC_REG_PFC_CTRL_HI,
169502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		       (pfc_ctrl | (1<<1)));
169602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		DP(NETIF_MSG_LINK, "Disable XMAC on port %x\n", port);
169702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		REG_WR(bp, xmac_base + XMAC_REG_CTRL, 0);
169802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
169902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
170002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
170102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic int bnx2x_xmac_enable(struct link_params *params,
170202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			     struct link_vars *vars, u8 lb)
170302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
170402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 val, xmac_base;
170502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
170602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	DP(NETIF_MSG_LINK, "enabling XMAC\n");
170702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
170802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	xmac_base = (params->port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
17091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
171002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_xmac_init(params, vars->line_speed);
171102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
171202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/*
171302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * This register determines on which events the MAC will assert
171402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * error on the i/f to the NIG along w/ EOP.
171502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 */
171602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
171702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/*
171802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * This register tells the NIG whether to send traffic to UMAC
171902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * or XMAC
172002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 */
172102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + params->port*4, 0);
172202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
17231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set Max packet size */
172402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, xmac_base + XMAC_REG_RX_MAX_SIZE, 0x2710);
172502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
172602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* CRC append for Tx packets */
172702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, xmac_base + XMAC_REG_TX_CTRL, 0xC800);
172802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
172902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* update PFC */
17301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_update_pfc_xmac(params, vars, 0);
17311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Enable TX and RX */
173302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val = XMAC_CTRL_REG_TX_EN | XMAC_CTRL_REG_RX_EN;
17341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
173502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Check loopback mode */
173602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (lb)
1737ad39c3004971173baeca80173e77022ee03eb9a1Jiri Slaby		val |= XMAC_CTRL_REG_LINE_LOCAL_LPBK;
1738ad39c3004971173baeca80173e77022ee03eb9a1Jiri Slaby	REG_WR(bp, xmac_base + XMAC_REG_CTRL, val);
1739ad39c3004971173baeca80173e77022ee03eb9a1Jiri Slaby	bnx2x_set_xumac_nig(params,
1740ad39c3004971173baeca80173e77022ee03eb9a1Jiri Slaby			    ((vars->flow_ctrl & BNX2X_FLOW_CTRL_TX) != 0), 1);
1741ad39c3004971173baeca80173e77022ee03eb9a1Jiri Slaby
17421a86b5e34e4d09e3246a983c53929ce38af52275Klaus Kudielka	vars->mac_type = MAC_TYPE_XMAC;
17431a86b5e34e4d09e3246a983c53929ce38af52275Klaus Kudielka
17441a86b5e34e4d09e3246a983c53929ce38af52275Klaus Kudielka	return 0;
17451a86b5e34e4d09e3246a983c53929ce38af52275Klaus Kudielka}
174602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic int bnx2x_emac_enable(struct link_params *params,
174702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			     struct link_vars *vars, u8 lb)
174802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
174902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
1750db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	u8 port = params->port;
175102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
1752db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	u32 val;
1753db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby
175402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	DP(NETIF_MSG_LINK, "enabling EMAC\n");
175502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
175602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Disable BMAC */
175702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
175802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
175902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
176002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* enable emac and not bmac */
176102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 1);
17621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
176302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* ASIC */
176402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (vars->phy_flags & PHY_XGXS_FLAG) {
176502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		u32 ser_lane = ((params->lane_config &
176602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
176702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
176802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
176902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		DP(NETIF_MSG_LINK, "XGXS\n");
177002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* select the master lanes (out of 0-3) */
177102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, ser_lane);
177202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* select XGXS */
177302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 1);
177402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
177502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	} else { /* SerDes */
177602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		DP(NETIF_MSG_LINK, "SerDes\n");
177702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* select SerDes */
177802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 0);
177902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
178002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
178102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_bits_en(bp, emac_base + EMAC_REG_EMAC_RX_MODE,
178202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		      EMAC_RX_MODE_RESET);
178302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_bits_en(bp, emac_base + EMAC_REG_EMAC_TX_MODE,
178402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		      EMAC_TX_MODE_RESET);
178502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
178602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (CHIP_REV_IS_SLOW(bp)) {
1787db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby		/* config GMII mode */
178802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
178902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		EMAC_WR(bp, EMAC_REG_EMAC_MODE, (val | EMAC_MODE_PORT_GMII));
179002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	} else { /* ASIC */
179102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* pause enable/disable */
179202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_RX_MODE,
179302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			       EMAC_RX_MODE_FLOW_EN);
179402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
179502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		bnx2x_bits_dis(bp,  emac_base + EMAC_REG_EMAC_TX_MODE,
179602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			       (EMAC_TX_MODE_EXT_PAUSE_EN |
179702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				EMAC_TX_MODE_FLOW_EN));
179802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (!(params->feature_config_flags &
179902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		      FEATURE_CONFIG_PFC_ENABLED)) {
180002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
180102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				bnx2x_bits_en(bp, emac_base +
180202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					      EMAC_REG_EMAC_RX_MODE,
180302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					      EMAC_RX_MODE_FLOW_EN);
180402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
180502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
180602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				bnx2x_bits_en(bp, emac_base +
180702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					      EMAC_REG_EMAC_TX_MODE,
18081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					      (EMAC_TX_MODE_EXT_PAUSE_EN |
180902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					       EMAC_TX_MODE_FLOW_EN));
181002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		} else
181102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			bnx2x_bits_en(bp, emac_base + EMAC_REG_EMAC_TX_MODE,
18121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				      EMAC_TX_MODE_FLOW_EN);
18131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
181402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
181502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* KEEP_VLAN_TAG, promiscuous */
181602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val = REG_RD(bp, emac_base + EMAC_REG_EMAC_RX_MODE);
181702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val |= EMAC_RX_MODE_KEEP_VLAN_TAG | EMAC_RX_MODE_PROMISCUOUS;
18181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
181902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/*
182002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * Setting this bit causes MAC control frames (except for pause
18211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * frames) to be passed on for processing. This setting has no
182202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * affect on the operation of the pause frames. This bit effects
182302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * all packets regardless of RX Parser packet sorting logic.
182402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * Turn the PFC off to make sure we are in Xon state before
182502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * enabling it.
182602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 */
182702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	EMAC_WR(bp, EMAC_REG_RX_PFC_MODE, 0);
18281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED) {
182902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		DP(NETIF_MSG_LINK, "PFC is enabled\n");
183002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* Enable PFC again */
18311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		EMAC_WR(bp, EMAC_REG_RX_PFC_MODE,
183202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			EMAC_REG_RX_PFC_MODE_RX_EN |
183302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			EMAC_REG_RX_PFC_MODE_TX_EN |
183402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			EMAC_REG_RX_PFC_MODE_PRIORITIES);
183502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
183602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		EMAC_WR(bp, EMAC_REG_RX_PFC_PARAM,
183702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			((0x0101 <<
183802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  EMAC_REG_RX_PFC_PARAM_OPCODE_BITSHIFT) |
183902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 (0x00ff <<
184002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  EMAC_REG_RX_PFC_PARAM_PRIORITY_EN_BITSHIFT)));
184102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		val |= EMAC_RX_MODE_KEEP_MAC_CONTROL;
184202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
184302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	EMAC_WR(bp, EMAC_REG_EMAC_RX_MODE, val);
184402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
18451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set Loopback */
18461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
18471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (lb)
18481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val |= 0x810;
184902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	else
18501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val &= ~0x810;
185102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	EMAC_WR(bp, EMAC_REG_EMAC_MODE, val);
18521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
185302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* enable emac */
18541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 1);
185502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
18561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* enable emac for jumbo packets */
185702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	EMAC_WR(bp, EMAC_REG_EMAC_RX_MTU_SIZE,
185802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		(EMAC_RX_MTU_SIZE_JUMBO_ENA |
18591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 (ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD)));
186002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
18611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* strip CRC */
186202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, NIG_REG_NIG_INGRESS_EMAC0_NO_CRC + port*4, 0x1);
18631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
186402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* disable the NIG in/out to the bmac */
186502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0x0);
18661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + port*4, 0x0);
186702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0x0);
186802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
18691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* enable the NIG in/out to the emac */
187002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0x1);
187102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val = 0;
18721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((params->feature_config_flags &
187302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	      FEATURE_CONFIG_PFC_ENABLED) ||
18741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX))
187502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		val = 1;
187602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
187702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, NIG_REG_EMAC0_PAUSE_OUT_EN + port*4, val);
18781a86b5e34e4d09e3246a983c53929ce38af52275Klaus Kudielka	REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0x1);
187902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
188002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x0);
188102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
188202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	vars->mac_type = MAC_TYPE_EMAC;
188302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	return 0;
188402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
188502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
188602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_update_pfc_bmac1(struct link_params *params,
188702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				   struct link_vars *vars)
188802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
18891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 wb_data[2];
18901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct bnx2x *bp = params->bp;
189102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 bmac_addr =  params->port ? NIG_REG_INGRESS_BMAC1_MEM :
18921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		NIG_REG_INGRESS_BMAC0_MEM;
189302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
18941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 val = 0x14;
189502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if ((!(params->feature_config_flags &
189602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	      FEATURE_CONFIG_PFC_ENABLED)) &&
189702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		(vars->flow_ctrl & BNX2X_FLOW_CTRL_RX))
1898ad39c3004971173baeca80173e77022ee03eb9a1Jiri Slaby		/* Enable BigMAC to react on received Pause packets */
1899ad39c3004971173baeca80173e77022ee03eb9a1Jiri Slaby		val |= (1<<5);
1900ad39c3004971173baeca80173e77022ee03eb9a1Jiri Slaby	wb_data[0] = val;
1901ad39c3004971173baeca80173e77022ee03eb9a1Jiri Slaby	wb_data[1] = 0;
1902ad39c3004971173baeca80173e77022ee03eb9a1Jiri Slaby	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_CONTROL, wb_data, 2);
1903b70509066cba24067757f1422c899c43e433429dJiri Slaby
190402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* tx control */
19051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = 0xc0;
190602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (!(params->feature_config_flags &
190702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	      FEATURE_CONFIG_PFC_ENABLED) &&
190802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		(vars->flow_ctrl & BNX2X_FLOW_CTRL_TX))
190902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		val |= 0x800000;
191002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	wb_data[0] = val;
191102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	wb_data[1] = 0;
191202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_CONTROL, wb_data, 2);
191302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
191402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
191502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_update_pfc_bmac2(struct link_params *params,
1916db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby				   struct link_vars *vars,
191702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				   u8 is_lb)
19181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
19191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
192002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * Set rx control: Strip CRC and enable BigMAC to relay
1921db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	 * control packets to the system as well
192202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 */
192302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 wb_data[2];
192402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
19251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 bmac_addr = params->port ? NIG_REG_INGRESS_BMAC1_MEM :
192602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		NIG_REG_INGRESS_BMAC0_MEM;
19271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 val = 0x14;
192802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
192902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if ((!(params->feature_config_flags &
193002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	      FEATURE_CONFIG_PFC_ENABLED)) &&
193102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		(vars->flow_ctrl & BNX2X_FLOW_CTRL_RX))
193202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* Enable BigMAC to react on received Pause packets */
19331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val |= (1<<5);
193402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	wb_data[0] = val;
193502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	wb_data[1] = 0;
193602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_CONTROL, wb_data, 2);
193702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	udelay(30);
193802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
1939b70509066cba24067757f1422c899c43e433429dJiri Slaby	/* Tx control */
19401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = 0xc0;
1941b70509066cba24067757f1422c899c43e433429dJiri Slaby	if (!(params->feature_config_flags &
194202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				FEATURE_CONFIG_PFC_ENABLED) &&
19431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX))
194402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		val |= 0x800000;
19451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wb_data[0] = val;
19461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wb_data[1] = 0;
19471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_CONTROL, wb_data, 2);
19481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED) {
19501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DP(NETIF_MSG_LINK, "PFC is enabled\n");
19511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Enable PFC RX & TX & STATS and set 8 COS  */
195202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		wb_data[0] = 0x0;
19531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		wb_data[0] |= (1<<0);  /* RX */
195402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		wb_data[0] |= (1<<1);  /* TX */
195502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		wb_data[0] |= (1<<2);  /* Force initial Xon */
195602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		wb_data[0] |= (1<<3);  /* 8 cos */
195702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		wb_data[0] |= (1<<5);  /* STATS */
195802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		wb_data[1] = 0;
19591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_PFC_CONTROL,
196002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			    wb_data, 2);
196102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* Clear the force Xon */
19621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		wb_data[0] &= ~(1<<2);
196302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	} else {
196402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		DP(NETIF_MSG_LINK, "PFC is disabled\n");
196502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* disable PFC RX & TX & STATS and set 8 COS */
19661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		wb_data[0] = 0x8;
196702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		wb_data[1] = 0;
19681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
196902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
197002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_PFC_CONTROL, wb_data, 2);
197102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
197202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/*
19731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Set Time (based unit is 512 bit time) between automatic
197402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * re-sending of PP packets amd enable automatic re-send of
197502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * Per-Priroity Packet as long as pp_gen is asserted and
197602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * pp_disable is low.
197702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 */
197802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val = 0x8000;
197902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED)
198002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		val |= (1<<16); /* enable automatic re-send */
19811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
198202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	wb_data[0] = val;
198302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	wb_data[1] = 0;
198402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_PAUSE_CONTROL,
198502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    wb_data, 2);
19861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
198702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* mac control */
19881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = 0x3; /* Enable RX and TX */
198902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (is_lb) {
19901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val |= 0x4; /* Local loopback */
199102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		DP(NETIF_MSG_LINK, "enable bmac loopback\n");
199202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
199302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* When PFC enabled, Pass pause frames towards the NIG. */
199402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED)
199502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		val |= ((1<<6)|(1<<5));
199602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
19971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wb_data[0] = val;
19981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wb_data[1] = 0;
199902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_BMAC_CONTROL, wb_data, 2);
200002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
200102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
200202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
20031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* PFC BRB internal port configuration params */
200402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystruct bnx2x_pfc_brb_threshold_val {
20051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 pause_xoff;
200602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 pause_xon;
20071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 full_xoff;
200802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 full_xon;
200902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby};
201002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
20111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct bnx2x_pfc_brb_e3b0_val {
201202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 full_lb_xoff_th;
201302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 full_lb_xon_threshold;
20141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 lb_guarantied;
201502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 mac_0_class_t_guarantied;
201602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 mac_0_class_t_guarantied_hyst;
201702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 mac_1_class_t_guarantied;
20181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 mac_1_class_t_guarantied_hyst;
20191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
202002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
202102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystruct bnx2x_pfc_brb_th_val {
2022db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	struct bnx2x_pfc_brb_threshold_val pauseable_th;
2023db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	struct bnx2x_pfc_brb_threshold_val non_pauseable_th;
20241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
20251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bnx2x_pfc_brb_get_config_params(
202602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				struct link_params *params,
2027db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby				struct bnx2x_pfc_brb_th_val *config_val)
202802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
20291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct bnx2x *bp = params->bp;
203002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	DP(NETIF_MSG_LINK, "Setting PFC BRB configuration\n");
203102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (CHIP_IS_E2(bp)) {
203202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		config_val->pauseable_th.pause_xoff =
203302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    PFC_E2_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
203402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		config_val->pauseable_th.pause_xon =
203502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    PFC_E2_BRB_MAC_PAUSE_XON_THR_PAUSE;
203602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		config_val->pauseable_th.full_xoff =
203702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    PFC_E2_BRB_MAC_FULL_XOFF_THR_PAUSE;
203802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		config_val->pauseable_th.full_xon =
20391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    PFC_E2_BRB_MAC_FULL_XON_THR_PAUSE;
204002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* non pause able*/
20411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		config_val->non_pauseable_th.pause_xoff =
204202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    PFC_E2_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
204302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		config_val->non_pauseable_th.pause_xon =
204402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    PFC_E2_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
204502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		config_val->non_pauseable_th.full_xoff =
204602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    PFC_E2_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
204702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		config_val->non_pauseable_th.full_xon =
20481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    PFC_E2_BRB_MAC_FULL_XON_THR_NON_PAUSE;
204902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	} else if (CHIP_IS_E3A0(bp)) {
20501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		config_val->pauseable_th.pause_xoff =
205102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
205202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		config_val->pauseable_th.pause_xon =
205302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    PFC_E3A0_BRB_MAC_PAUSE_XON_THR_PAUSE;
205402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		config_val->pauseable_th.full_xoff =
20551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    PFC_E3A0_BRB_MAC_FULL_XOFF_THR_PAUSE;
205602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		config_val->pauseable_th.full_xon =
2057db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby		    PFC_E3A0_BRB_MAC_FULL_XON_THR_PAUSE;
205802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* non pause able*/
205902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		config_val->non_pauseable_th.pause_xoff =
20601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    PFC_E3A0_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
20611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		config_val->non_pauseable_th.pause_xon =
206202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    PFC_E3A0_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
206302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		config_val->non_pauseable_th.full_xoff =
206402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    PFC_E3A0_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
20651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		config_val->non_pauseable_th.full_xon =
206602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    PFC_E3A0_BRB_MAC_FULL_XON_THR_NON_PAUSE;
20671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if (CHIP_IS_E3B0(bp)) {
206802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (params->phy[INT_PHY].flags &
20691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    FLAGS_4_PORT_MODE) {
20701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			config_val->pauseable_th.pause_xoff =
207102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			    PFC_E3B0_4P_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
207202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			config_val->pauseable_th.pause_xon =
207302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			    PFC_E3B0_4P_BRB_MAC_PAUSE_XON_THR_PAUSE;
20741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			config_val->pauseable_th.full_xoff =
207502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			    PFC_E3B0_4P_BRB_MAC_FULL_XOFF_THR_PAUSE;
207602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			config_val->pauseable_th.full_xon =
207702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			    PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_PAUSE;
20781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* non pause able*/
20791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			config_val->non_pauseable_th.pause_xoff =
208002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			    PFC_E3B0_4P_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
208102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			config_val->non_pauseable_th.pause_xon =
208202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			    PFC_E3B0_4P_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
20831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			config_val->non_pauseable_th.full_xoff =
208402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			    PFC_E3B0_4P_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
208502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			config_val->non_pauseable_th.full_xon =
208602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			    PFC_E3B0_4P_BRB_MAC_FULL_XON_THR_NON_PAUSE;
208702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	    } else {
208802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		config_val->pauseable_th.pause_xoff =
208902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_PAUSE;
209002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		config_val->pauseable_th.pause_xon =
209102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_PAUSE;
209202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		config_val->pauseable_th.full_xoff =
20931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_PAUSE;
209402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		config_val->pauseable_th.full_xon =
209502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_PAUSE;
209602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* non pause able*/
209702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		config_val->non_pauseable_th.pause_xoff =
209802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    PFC_E3B0_2P_BRB_MAC_PAUSE_XOFF_THR_NON_PAUSE;
209902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		config_val->non_pauseable_th.pause_xon =
210002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    PFC_E3B0_2P_BRB_MAC_PAUSE_XON_THR_NON_PAUSE;
21011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		config_val->non_pauseable_th.full_xoff =
210202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    PFC_E3B0_2P_BRB_MAC_FULL_XOFF_THR_NON_PAUSE;
210302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		config_val->non_pauseable_th.full_xon =
210402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    PFC_E3B0_2P_BRB_MAC_FULL_XON_THR_NON_PAUSE;
2105db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	    }
210602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	} else
210702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	    return -EINVAL;
210802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
210902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	return 0;
211002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
211102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
211202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
21131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void bnx2x_pfc_brb_get_e3b0_config_params(struct link_params *params,
211402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby						 struct bnx2x_pfc_brb_e3b0_val
21151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						 *e3b0_val,
21161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						 u32 cos0_pauseable,
211702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby						 u32 cos1_pauseable)
211802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
211902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (params->phy[INT_PHY].flags & FLAGS_4_PORT_MODE) {
212002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		e3b0_val->full_lb_xoff_th =
212102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    PFC_E3B0_4P_BRB_FULL_LB_XOFF_THR;
212202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		e3b0_val->full_lb_xon_threshold =
212302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    PFC_E3B0_4P_BRB_FULL_LB_XON_THR;
212402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		e3b0_val->lb_guarantied =
212502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    PFC_E3B0_4P_LB_GUART;
212602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		e3b0_val->mac_0_class_t_guarantied =
212702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART;
212802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		e3b0_val->mac_0_class_t_guarantied_hyst =
21291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    PFC_E3B0_4P_BRB_MAC_0_CLASS_T_GUART_HYST;
213002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		e3b0_val->mac_1_class_t_guarantied =
21311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART;
21321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e3b0_val->mac_1_class_t_guarantied_hyst =
21331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    PFC_E3B0_4P_BRB_MAC_1_CLASS_T_GUART_HYST;
21341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
21351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e3b0_val->full_lb_xoff_th =
21361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    PFC_E3B0_2P_BRB_FULL_LB_XOFF_THR;
21371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e3b0_val->full_lb_xon_threshold =
21381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    PFC_E3B0_2P_BRB_FULL_LB_XON_THR;
21391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		e3b0_val->mac_0_class_t_guarantied_hyst =
21401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    PFC_E3B0_2P_BRB_MAC_0_CLASS_T_GUART_HYST;
214102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		e3b0_val->mac_1_class_t_guarantied =
21421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    PFC_E3B0_2P_BRB_MAC_1_CLASS_T_GUART;
214302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		e3b0_val->mac_1_class_t_guarantied_hyst =
21441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    PFC_E3B0_2P_BRB_MAC_1_CLASS_T_GUART_HYST;
214502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
214602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (cos0_pauseable != cos1_pauseable) {
214702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			/* nonpauseable= Lossy + pauseable = Lossless*/
21481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			e3b0_val->lb_guarantied =
214902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			    PFC_E3B0_2P_MIX_PAUSE_LB_GUART;
215002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			e3b0_val->mac_0_class_t_guarantied =
215102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			    PFC_E3B0_2P_MIX_PAUSE_MAC_0_CLASS_T_GUART;
215202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		} else if (cos0_pauseable) {
215302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			/* Lossless +Lossless*/
215402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			e3b0_val->lb_guarantied =
215502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			    PFC_E3B0_2P_PAUSE_LB_GUART;
215602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			e3b0_val->mac_0_class_t_guarantied =
215702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			    PFC_E3B0_2P_PAUSE_MAC_0_CLASS_T_GUART;
215802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		} else {
215902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			/* Lossy +Lossy*/
216002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			e3b0_val->lb_guarantied =
2161db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby			    PFC_E3B0_2P_NON_PAUSE_LB_GUART;
216202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			e3b0_val->mac_0_class_t_guarantied =
216302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			    PFC_E3B0_2P_NON_PAUSE_MAC_0_CLASS_T_GUART;
21641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
216502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
21661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
216702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic int bnx2x_update_pfc_brb(struct link_params *params,
216802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				struct link_vars *vars,
216902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				struct bnx2x_nig_brb_pfc_port_params
217002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				*pfc_params)
217102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
217202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
217302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x_pfc_brb_th_val config_val = { {0} };
217402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x_pfc_brb_threshold_val *reg_th_config =
217502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	    &config_val.pauseable_th;
217602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x_pfc_brb_e3b0_val e3b0_val = {0};
217702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	int set_pfc = params->feature_config_flags &
217802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		FEATURE_CONFIG_PFC_ENABLED;
217902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	int bnx2x_status = 0;
21801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 port = params->port;
21811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* default - pause configuration */
21831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	reg_th_config = &config_val.pauseable_th;
21841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_status = bnx2x_pfc_brb_get_config_params(params, &config_val);
218502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (0 != bnx2x_status)
21861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return bnx2x_status;
218702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
218802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (set_pfc && pfc_params)
218902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* First COS */
219002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (!pfc_params->cos0_pauseable)
219102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			reg_th_config = &config_val.non_pauseable_th;
219202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/*
219302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * The number of free blocks below which the pause signal to class 0
219402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * of MAC #n is asserted. n=0,1
219502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 */
219602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, (port) ? BRB1_REG_PAUSE_0_XOFF_THRESHOLD_1 :
219702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       BRB1_REG_PAUSE_0_XOFF_THRESHOLD_0 ,
219802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       reg_th_config->pause_xoff);
219902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/*
220002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * The number of free blocks above which the pause signal to class 0
220102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * of MAC #n is de-asserted. n=0,1
220202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 */
22031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, (port) ? BRB1_REG_PAUSE_0_XON_THRESHOLD_1 :
22041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       BRB1_REG_PAUSE_0_XON_THRESHOLD_0 , reg_th_config->pause_xon);
220502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/*
220602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * The number of free blocks below which the full signal to class 0
220702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * of MAC #n is asserted. n=0,1
22081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
22091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, (port) ? BRB1_REG_FULL_0_XOFF_THRESHOLD_1 :
221002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       BRB1_REG_FULL_0_XOFF_THRESHOLD_0 , reg_th_config->full_xoff);
221102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/*
221202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * The number of free blocks above which the full signal to class 0
221302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * of MAC #n is de-asserted. n=0,1
22141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
221502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, (port) ? BRB1_REG_FULL_0_XON_THRESHOLD_1 :
221602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       BRB1_REG_FULL_0_XON_THRESHOLD_0 , reg_th_config->full_xon);
221702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
221802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (set_pfc && pfc_params) {
221902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* Second COS */
222002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (pfc_params->cos1_pauseable)
222102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			reg_th_config = &config_val.pauseable_th;
222202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		else
222302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			reg_th_config = &config_val.non_pauseable_th;
222402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/*
22251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * The number of free blocks below which the pause signal to
222602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		 * class 1 of MAC #n is asserted. n=0,1
222702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		**/
2228db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby		REG_WR(bp, (port) ? BRB1_REG_PAUSE_1_XOFF_THRESHOLD_1 :
2229db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby		       BRB1_REG_PAUSE_1_XOFF_THRESHOLD_0,
22301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       reg_th_config->pause_xoff);
223102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/*
223202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		 * The number of free blocks above which the pause signal to
223302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		 * class 1 of MAC #n is de-asserted. n=0,1
223402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		 */
223502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		REG_WR(bp, (port) ? BRB1_REG_PAUSE_1_XON_THRESHOLD_1 :
223602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		       BRB1_REG_PAUSE_1_XON_THRESHOLD_0,
223702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		       reg_th_config->pause_xon);
223802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/*
223902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		 * The number of free blocks below which the full signal to
224002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		 * class 1 of MAC #n is asserted. n=0,1
224102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		 */
224202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		REG_WR(bp, (port) ? BRB1_REG_FULL_1_XOFF_THRESHOLD_1 :
224302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		       BRB1_REG_FULL_1_XOFF_THRESHOLD_0,
224402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		       reg_th_config->full_xoff);
224502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/*
224602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		 * The number of free blocks above which the full signal to
224702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		 * class 1 of MAC #n is de-asserted. n=0,1
224802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		 */
22491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		REG_WR(bp, (port) ? BRB1_REG_FULL_1_XON_THRESHOLD_1 :
225002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		       BRB1_REG_FULL_1_XON_THRESHOLD_0,
225102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		       reg_th_config->full_xon);
22521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
225402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (CHIP_IS_E3B0(bp)) {
225502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			/*Should be done by init tool */
225602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			/*
225702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			* BRB_empty_for_dup = BRB1_REG_BRB_EMPTY_THRESHOLD
22581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			* reset value
225902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			* 944
2260db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby			*/
226102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
226202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			/**
22631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * The hysteresis on the guarantied buffer space for the Lb port
226402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 * before signaling XON.
22651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 **/
226602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			REG_WR(bp, BRB1_REG_LB_GUARANTIED_HYST, 80);
226702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
226802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			bnx2x_pfc_brb_get_e3b0_config_params(
226902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			    params,
227002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			    &e3b0_val,
22711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    pfc_params->cos0_pauseable,
227202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			    pfc_params->cos1_pauseable);
227302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			/**
227402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 * The number of free blocks below which the full signal to the
2275db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby			 * LB port is asserted.
227602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			*/
227702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			REG_WR(bp, BRB1_REG_FULL_LB_XOFF_THRESHOLD,
227802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				   e3b0_val.full_lb_xoff_th);
227902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			/**
228002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 * The number of free blocks above which the full signal to the
228102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 * LB port is de-asserted.
228202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			*/
22831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			REG_WR(bp, BRB1_REG_FULL_LB_XON_THRESHOLD,
228402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				   e3b0_val.full_lb_xon_threshold);
22851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/**
228602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			* The number of blocks guarantied for the MAC #n port. n=0,1
22871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*/
228802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
228902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			/*The number of blocks guarantied for the LB port.*/
229002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			REG_WR(bp, BRB1_REG_LB_GUARANTIED,
229102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			       e3b0_val.lb_guarantied);
229202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
229302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			/**
229402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 * The number of blocks guarantied for the MAC #n port.
22951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*/
22961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			REG_WR(bp, BRB1_REG_MAC_GUARANTIED_0,
229702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				   2 * e3b0_val.mac_0_class_t_guarantied);
22981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			REG_WR(bp, BRB1_REG_MAC_GUARANTIED_1,
229902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				   2 * e3b0_val.mac_1_class_t_guarantied);
23001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/**
23011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * The number of blocks guarantied for class #t in MAC0. t=0,1
23021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*/
23031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			REG_WR(bp, BRB1_REG_MAC_0_CLASS_0_GUARANTIED,
23041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       e3b0_val.mac_0_class_t_guarantied);
23051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			REG_WR(bp, BRB1_REG_MAC_0_CLASS_1_GUARANTIED,
23061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       e3b0_val.mac_0_class_t_guarantied);
23071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/**
230802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 * The hysteresis on the guarantied buffer space for class in
230902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 * MAC0.  t=0,1
23101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*/
231102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			REG_WR(bp, BRB1_REG_MAC_0_CLASS_0_GUARANTIED_HYST,
231202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			       e3b0_val.mac_0_class_t_guarantied_hyst);
231302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			REG_WR(bp, BRB1_REG_MAC_0_CLASS_1_GUARANTIED_HYST,
231402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			       e3b0_val.mac_0_class_t_guarantied_hyst);
231502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
231602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			/**
231702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 * The number of blocks guarantied for class #t in MAC1.t=0,1
231802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			*/
231902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			REG_WR(bp, BRB1_REG_MAC_1_CLASS_0_GUARANTIED,
232002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			       e3b0_val.mac_1_class_t_guarantied);
232102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			REG_WR(bp, BRB1_REG_MAC_1_CLASS_1_GUARANTIED,
232202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			       e3b0_val.mac_1_class_t_guarantied);
232302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			/**
232402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 * The hysteresis on the guarantied buffer space for class #t
232502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			* in MAC1.  t=0,1
232602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			*/
232702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			REG_WR(bp, BRB1_REG_MAC_1_CLASS_0_GUARANTIED_HYST,
232802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			       e3b0_val.mac_1_class_t_guarantied_hyst);
2329096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby			REG_WR(bp, BRB1_REG_MAC_1_CLASS_1_GUARANTIED_HYST,
23301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       e3b0_val.mac_1_class_t_guarantied_hyst);
233102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
233202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	    }
233302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
233402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
233502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
233602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	return bnx2x_status;
233702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
233802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
233902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/******************************************************************************
234002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby* Description:
234102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby*  This function is needed because NIG ARB_CREDIT_WEIGHT_X are
234202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby*  not continues and ARB_CREDIT_WEIGHT_0 + offset is suitable.
234302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby******************************************************************************/
234402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabyint bnx2x_pfc_nig_rx_priority_mask(struct bnx2x *bp,
234502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					      u8 cos_entry,
234602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					      u32 priority_mask, u8 port)
234702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
234802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 nig_reg_rx_priority_mask_add = 0;
234902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
23501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (cos_entry) {
235102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	case 0:
235202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	     nig_reg_rx_priority_mask_add = (port) ?
235302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		 NIG_REG_P1_RX_COS0_PRIORITY_MASK :
23541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 NIG_REG_P0_RX_COS0_PRIORITY_MASK;
235502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	     break;
235602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	case 1:
235702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	    nig_reg_rx_priority_mask_add = (port) ?
235802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		NIG_REG_P1_RX_COS1_PRIORITY_MASK :
23591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		NIG_REG_P0_RX_COS1_PRIORITY_MASK;
236002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	    break;
236102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	case 2:
23621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    nig_reg_rx_priority_mask_add = (port) ?
236302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		NIG_REG_P1_RX_COS2_PRIORITY_MASK :
236402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		NIG_REG_P0_RX_COS2_PRIORITY_MASK;
236502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	    break;
236602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	case 3:
236702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	    if (port)
236802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		return -EINVAL;
236902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	    nig_reg_rx_priority_mask_add = NIG_REG_P0_RX_COS3_PRIORITY_MASK;
237002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	    break;
237102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	case 4:
237202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	    if (port)
237302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		return -EINVAL;
237402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	    nig_reg_rx_priority_mask_add = NIG_REG_P0_RX_COS4_PRIORITY_MASK;
237502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	    break;
237602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	case 5:
237702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	    if (port)
237802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		return -EINVAL;
237902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	    nig_reg_rx_priority_mask_add = NIG_REG_P0_RX_COS5_PRIORITY_MASK;
23801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    break;
238102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
238202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
2383db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	REG_WR(bp, nig_reg_rx_priority_mask_add, priority_mask);
2384db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby
23851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
238602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
238702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_update_mng(struct link_params *params, u32 link_status)
23881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
238902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
239002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
239102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, params->shmem_base +
239202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       offsetof(struct shmem_region,
239302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			port_mb[params->port].link_status), link_status);
239402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
239502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
23961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void bnx2x_update_pfc_nig(struct link_params *params,
239702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		struct link_vars *vars,
239802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		struct bnx2x_nig_brb_pfc_port_params *nig_params)
239902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
240002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 xcm_mask = 0, ppp_enable = 0, pause_enable = 0, llfc_out_en = 0;
2401db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	u32 llfc_enable = 0, xcm0_out_en = 0, p0_hwpfc_enable = 0;
240202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 pkt_priority_to_cos = 0;
240302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
240402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u8 port = params->port;
240502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
24061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int set_pfc = params->feature_config_flags &
24071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		FEATURE_CONFIG_PFC_ENABLED;
240802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	DP(NETIF_MSG_LINK, "updating pfc nig parameters\n");
240902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
241002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/*
241102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * When NIG_LLH0_XCM_MASK_REG_LLHX_XCM_MASK_BCN bit is set
24121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * MAC control frames (that are not pause packets)
241302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * will be forwarded to the XCM.
241402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 */
241502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	xcm_mask = REG_RD(bp,
241602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				port ? NIG_REG_LLH1_XCM_MASK :
24171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				NIG_REG_LLH0_XCM_MASK);
241802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/*
24191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * nig params will override non PFC params, since it's possible to
242002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * do transition from PFC to SAFC
242102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 */
242202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (set_pfc) {
242302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		pause_enable = 0;
242402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		llfc_out_en = 0;
242502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		llfc_enable = 0;
242602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (CHIP_IS_E3(bp))
242702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			ppp_enable = 0;
242802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		else
242902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		ppp_enable = 1;
2430cc0a8fbb7ce00f65dc337dd91389b7151f44ed30Milind Arun Choudhary		xcm_mask &= ~(port ? NIG_LLH1_XCM_MASK_REG_LLH1_XCM_MASK_BCN :
243102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				     NIG_LLH0_XCM_MASK_REG_LLH0_XCM_MASK_BCN);
243202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		xcm0_out_en = 0;
243302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		p0_hwpfc_enable = 1;
243402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	} else  {
2435db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby		if (nig_params) {
243602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			llfc_out_en = nig_params->llfc_out_en;
243702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			llfc_enable = nig_params->llfc_enable;
243802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			pause_enable = nig_params->pause_enable;
243902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		} else  /*defaul non PFC mode - PAUSE */
244002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			pause_enable = 1;
244102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
2442db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby		xcm_mask |= (port ? NIG_LLH1_XCM_MASK_REG_LLH1_XCM_MASK_BCN :
2443db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby			NIG_LLH0_XCM_MASK_REG_LLH0_XCM_MASK_BCN);
244402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		xcm0_out_en = 1;
2445db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	}
244602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
244702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (CHIP_IS_E3(bp))
244802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		REG_WR(bp, port ? NIG_REG_BRB1_PAUSE_IN_EN :
244902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		       NIG_REG_BRB0_PAUSE_IN_EN, pause_enable);
245002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, port ? NIG_REG_LLFC_OUT_EN_1 :
24511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       NIG_REG_LLFC_OUT_EN_0, llfc_out_en);
245202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, port ? NIG_REG_LLFC_ENABLE_1 :
24531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       NIG_REG_LLFC_ENABLE_0, llfc_enable);
245402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, port ? NIG_REG_PAUSE_ENABLE_1 :
24551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       NIG_REG_PAUSE_ENABLE_0, pause_enable);
245602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
245702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, port ? NIG_REG_PPP_ENABLE_1 :
245802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       NIG_REG_PPP_ENABLE_0, ppp_enable);
245902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
246002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, port ? NIG_REG_LLH1_XCM_MASK :
246102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       NIG_REG_LLH0_XCM_MASK, xcm_mask);
246202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
246302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp,  NIG_REG_LLFC_EGRESS_SRC_ENABLE_0, 0x7);
2464db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby
246502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* output enable for RX_XCM # IF */
246602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, NIG_REG_XCM0_OUT_EN, xcm0_out_en);
246702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
246802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* HW PFC TX enable */
246902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, NIG_REG_P0_HWPFC_ENABLE, p0_hwpfc_enable);
247002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
247102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (nig_params) {
24721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u8 i = 0;
247302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		pkt_priority_to_cos = nig_params->pkt_priority_to_cos;
247402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
247502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		for (i = 0; i < nig_params->num_of_rx_cos_priority_mask; i++)
247602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			bnx2x_pfc_nig_rx_priority_mask(bp, i,
24771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nig_params->rx_cos_priority_mask[i], port);
247802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
247902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		REG_WR(bp, port ? NIG_REG_LLFC_HIGH_PRIORITY_CLASSES_1 :
24801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       NIG_REG_LLFC_HIGH_PRIORITY_CLASSES_0,
2481cc0a8fbb7ce00f65dc337dd91389b7151f44ed30Milind Arun Choudhary		       nig_params->llfc_high_priority_classes);
248202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
248302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		REG_WR(bp, port ? NIG_REG_LLFC_LOW_PRIORITY_CLASSES_1 :
248402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		       NIG_REG_LLFC_LOW_PRIORITY_CLASSES_0,
24851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       nig_params->llfc_low_priority_classes);
248602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
248702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, port ? NIG_REG_P1_PKT_PRIORITY_TO_COS :
24881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       NIG_REG_P0_PKT_PRIORITY_TO_COS,
248902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       pkt_priority_to_cos);
249002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
24911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
249202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabyint bnx2x_update_pfc(struct link_params *params,
249302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		      struct link_vars *vars,
249402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		      struct bnx2x_nig_brb_pfc_port_params *pfc_params)
24951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
249602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/*
249702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * The PFC and pause are orthogonal to one another, meaning when
249802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * PFC is enabled, the pause are disabled, and when PFC is
249902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * disabled, pause are set according to the pause result.
250002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 */
25011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 val;
25021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct bnx2x *bp = params->bp;
25031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int bnx2x_status = 0;
25041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 bmac_loopback = (params->loopback_mode == LOOPBACK_BMAC);
25051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
250602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED)
25071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vars->link_status |= LINK_STATUS_PFC_ENABLED;
250802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	else
250902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		vars->link_status &= ~LINK_STATUS_PFC_ENABLED;
25101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
251102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_update_mng(params, vars->link_status);
251202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
251302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* update NIG params */
251402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_update_pfc_nig(params, vars, pfc_params);
251502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
251602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* update BRB params */
251702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_status = bnx2x_update_pfc_brb(params, vars, pfc_params);
251802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (0 != bnx2x_status)
25191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return bnx2x_status;
252002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
252102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (!vars->link_up)
252202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		return bnx2x_status;
252302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
252402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	DP(NETIF_MSG_LINK, "About to update PFC in BMAC\n");
252502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (CHIP_IS_E3(bp))
252602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		bnx2x_update_pfc_xmac(params, vars, 0);
252702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	else {
252802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		val = REG_RD(bp, MISC_REG_RESET_REG_2);
2529db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby		if ((val &
253002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		     (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port))
253102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    == 0) {
2532db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby			DP(NETIF_MSG_LINK, "About to update PFC in EMAC\n");
253302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			bnx2x_emac_enable(params, vars, 0);
253402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			return bnx2x_status;
253502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		}
253602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
253702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (CHIP_IS_E2(bp))
253802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			bnx2x_update_pfc_bmac2(params, vars, bmac_loopback);
253902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		else
254002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			bnx2x_update_pfc_bmac1(params, vars);
254102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
254202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		val = 0;
254302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if ((params->feature_config_flags &
254402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		     FEATURE_CONFIG_PFC_ENABLED) ||
254502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX))
254602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			val = 1;
254702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + params->port*4, val);
254802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
254902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	return bnx2x_status;
255002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
255102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
255202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
2553db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slabystatic int bnx2x_bmac1_enable(struct link_params *params,
2554db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby			      struct link_vars *vars,
255502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			      u8 is_lb)
255602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
255702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
255802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u8 port = params->port;
255902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
2560db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby			       NIG_REG_INGRESS_BMAC0_MEM;
256102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 wb_data[2];
256202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 val;
256302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
256402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	DP(NETIF_MSG_LINK, "Enabling BigMAC1\n");
256502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
256602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* XGXS control */
256702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	wb_data[0] = 0x3c;
256802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	wb_data[1] = 0;
2569db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_XGXS_CONTROL,
257002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    wb_data, 2);
257102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
25721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* tx MAC SA */
257302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	wb_data[0] = ((params->mac_addr[2] << 24) |
257402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		       (params->mac_addr[3] << 16) |
257502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		       (params->mac_addr[4] << 8) |
257602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			params->mac_addr[5]);
25771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wb_data[1] = ((params->mac_addr[0] << 8) |
25781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			params->mac_addr[1]);
257902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_SOURCE_ADDR, wb_data, 2);
25801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
258102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* mac control */
258202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val = 0x3;
258302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (is_lb) {
258402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		val |= 0x4;
258502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		DP(NETIF_MSG_LINK, "enable bmac loopback\n");
25861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
258702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	wb_data[0] = val;
258802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	wb_data[1] = 0;
25891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL, wb_data, 2);
259002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
25911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* set rx mtu */
259202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
259302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	wb_data[1] = 0;
25941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_MAX_SIZE, wb_data, 2);
25951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
259602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_update_pfc_bmac1(params, vars);
259702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
259802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* set tx mtu */
259902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
260002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	wb_data[1] = 0;
260102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_MAX_SIZE, wb_data, 2);
2602096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby
260302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* set cnt max size */
26041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
260502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	wb_data[1] = 0;
260602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_CNT_MAX_SIZE, wb_data, 2);
260702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
260802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* configure safc */
260902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	wb_data[0] = 0x1000200;
261002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	wb_data[1] = 0;
261102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_LLFC_MSG_FLDS,
26121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    wb_data, 2);
261302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
261402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	return 0;
26151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
261602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
261702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic int bnx2x_bmac2_enable(struct link_params *params,
26181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			      struct link_vars *vars,
261902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			      u8 is_lb)
262002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
26211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct bnx2x *bp = params->bp;
262202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u8 port = params->port;
26231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
262402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			       NIG_REG_INGRESS_BMAC0_MEM;
262502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 wb_data[2];
262602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
262702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	DP(NETIF_MSG_LINK, "Enabling BigMAC2\n");
262802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
262902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	wb_data[0] = 0;
26301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wb_data[1] = 0;
26311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_BMAC_CONTROL, wb_data, 2);
26321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(30);
26331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
263402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* XGXS control: Reset phy HW, MDIO registers, PHY PLL and BMAC */
26351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wb_data[0] = 0x3c;
2636cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby	wb_data[1] = 0;
263702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_BMAC_XGXS_CONTROL,
263802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    wb_data, 2);
263902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
264002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	udelay(30);
264102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
264202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* tx MAC SA */
264302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	wb_data[0] = ((params->mac_addr[2] << 24) |
264402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		       (params->mac_addr[3] << 16) |
264502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		       (params->mac_addr[4] << 8) |
264602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			params->mac_addr[5]);
26471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wb_data[1] = ((params->mac_addr[0] << 8) |
264802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			params->mac_addr[1]);
264902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_SOURCE_ADDR,
265002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    wb_data, 2);
265102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
265202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	udelay(30);
265302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
265402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Configure SAFC */
265502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	wb_data[0] = 0x1000200;
265602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	wb_data[1] = 0;
265702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_LLFC_MSG_FLDS,
265802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    wb_data, 2);
265902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	udelay(30);
266002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
266102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* set rx mtu */
266202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
266302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	wb_data[1] = 0;
266402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_MAX_SIZE, wb_data, 2);
266502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	udelay(30);
266602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
266702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* set tx mtu */
266802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
266902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	wb_data[1] = 0;
267002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_MAX_SIZE, wb_data, 2);
267102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	udelay(30);
267202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* set cnt max size */
267302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD - 2;
267402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	wb_data[1] = 0;
267502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_CNT_MAX_SIZE, wb_data, 2);
26761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(30);
267702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_update_pfc_bmac2(params, vars, is_lb);
267802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
26791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
268002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
268102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
268202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic int bnx2x_bmac_enable(struct link_params *params,
268302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			     struct link_vars *vars,
268402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			     u8 is_lb)
268502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
268602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	int rc = 0;
268702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u8 port = params->port;
2688db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	struct bnx2x *bp = params->bp;
26891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 val;
269002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* reset and unreset the BigMac */
26911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
269202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
269302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	msleep(1);
269402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
269502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
269602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
269702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
269802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* enable access for bmac registers */
2699096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby	REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x1);
27001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
270102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Enable BMAC according to BMAC type*/
270202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (CHIP_IS_E2(bp))
27031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rc = bnx2x_bmac2_enable(params, vars, is_lb);
270402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	else
27051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rc = bnx2x_bmac1_enable(params, vars, is_lb);
27061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 0x1);
27071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 0x0);
27081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 0x0);
27091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val = 0;
27101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((params->feature_config_flags &
271102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	      FEATURE_CONFIG_PFC_ENABLED) ||
27121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX))
2713cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby		val = 1;
271402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + port*4, val);
27151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0x0);
27161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0x0);
271702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, NIG_REG_EMAC0_PAUSE_OUT_EN + port*4, 0x0);
27181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0x1);
27191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0x1);
272002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
272102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	vars->mac_type = MAC_TYPE_BMAC;
272202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	return rc;
27231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
272402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
272502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_bmac_rx_disable(struct bnx2x *bp, u8 port)
272602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
272702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
272802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			NIG_REG_INGRESS_BMAC0_MEM;
272902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 wb_data[2];
27301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 nig_bmac_enable = REG_RD(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4);
273102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
27321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Only if the bmac is out of reset */
273302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (REG_RD(bp, MISC_REG_RESET_REG_2) &
273402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			(MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port) &&
273502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	    nig_bmac_enable) {
273602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
273702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (CHIP_IS_E2(bp)) {
273802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			/* Clear Rx Enable bit in BMAC_CONTROL register */
273902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			REG_RD_DMAE(bp, bmac_addr +
274002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				    BIGMAC2_REGISTER_BMAC_CONTROL,
274102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				    wb_data, 2);
274202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE;
274302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			REG_WR_DMAE(bp, bmac_addr +
274402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				    BIGMAC2_REGISTER_BMAC_CONTROL,
27451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    wb_data, 2);
274602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		} else {
274702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			/* Clear Rx Enable bit in BMAC_CONTROL register */
27481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			REG_RD_DMAE(bp, bmac_addr +
274902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					BIGMAC_REGISTER_BMAC_CONTROL,
27501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					wb_data, 2);
275102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE;
27521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			REG_WR_DMAE(bp, bmac_addr +
275302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					BIGMAC_REGISTER_BMAC_CONTROL,
27541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					wb_data, 2);
275502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		}
275602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		msleep(1);
275702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
275802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
275902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
27601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl,
276102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			    u32 line_speed)
276202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
276302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
276402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u8 port = params->port;
276502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 init_crd, crd;
276602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 count = 1000;
276702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
276802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* disable port */
27691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, PBF_REG_DISABLE_NEW_TASK_PROC_P0 + port*4, 0x1);
277002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
277102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* wait for init credit */
277202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	init_crd = REG_RD(bp, PBF_REG_P0_INIT_CRD + port*4);
277302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	crd = REG_RD(bp, PBF_REG_P0_CREDIT + port*8);
277402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	DP(NETIF_MSG_LINK, "init_crd 0x%x  crd 0x%x\n", init_crd, crd);
277502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
277602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	while ((init_crd != crd) && count) {
277702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		msleep(5);
277802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
277902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		crd = REG_RD(bp, PBF_REG_P0_CREDIT + port*8);
278002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		count--;
2781db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	}
278202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	crd = REG_RD(bp, PBF_REG_P0_CREDIT + port*8);
278302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (init_crd != crd) {
278402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		DP(NETIF_MSG_LINK, "BUG! init_crd 0x%x != crd 0x%x\n",
278502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  init_crd, crd);
278602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		return -EINVAL;
278702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
278802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
278902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (flow_ctrl & BNX2X_FLOW_CTRL_RX ||
279002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	    line_speed == SPEED_10 ||
279102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	    line_speed == SPEED_100 ||
279202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	    line_speed == SPEED_1000 ||
279302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	    line_speed == SPEED_2500) {
279402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 1);
2795db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby		/* update threshold */
279602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, 0);
279702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* update init credit */
279802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		init_crd = 778;		/* (800-18-4) */
279902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
2800db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	} else {
280102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		u32 thresh = (ETH_MAX_JUMBO_PACKET_SIZE +
280202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			      ETH_OVREHEAD)/16;
280302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		REG_WR(bp, PBF_REG_P0_PAUSE_ENABLE + port*4, 0);
280402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* update threshold */
280502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, thresh);
280602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* update init credit */
280702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		switch (line_speed) {
280802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		case SPEED_10000:
280902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			init_crd = thresh + 553 - 22;
281002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			break;
28111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
281202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n",
281302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				  line_speed);
28141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EINVAL;
281502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		}
281602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
281702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, PBF_REG_P0_INIT_CRD + port*4, init_crd);
281802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	DP(NETIF_MSG_LINK, "PBF updated to speed %d credit %d\n",
28191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 line_speed, init_crd);
282002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
282102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* probe the credit changes */
282202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, PBF_REG_INIT_P0 + port*4, 0x1);
282302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	msleep(5);
282402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, PBF_REG_INIT_P0 + port*4, 0x0);
282502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
282602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* enable port */
282702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, PBF_REG_DISABLE_NEW_TASK_PROC_P0 + port*4, 0x0);
282802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	return 0;
282902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
283002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
283102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/**
283202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * bnx2x_get_emac_base - retrive emac base address
283302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby *
283402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * @bp:			driver handle
28351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @mdc_mdio_access:	access type
28361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @port:		port id
283702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby *
28381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This function selects the MDC/MDIO access (through emac0 or
28391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * emac1) depend on the mdc_mdio_access, port, port swapped. Each
284002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * phy has a default access mode, which could also be overridden
284102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * by nvram configuration. This parameter, whether this is the
28421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * default phy configuration, or the nvram overrun
28431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * configuration, is passed here as mdc_mdio_access and selects
28441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the emac_base for the CL45 read/writes operations
28451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
28461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u32 bnx2x_get_emac_base(struct bnx2x *bp,
28471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       u32 mdc_mdio_access, u8 port)
28481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
28491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 emac_base = 0;
28501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (mdc_mdio_access) {
28511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SHARED_HW_CFG_MDC_MDIO_ACCESS1_PHY_TYPE:
28521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
28531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC0:
28541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (REG_RD(bp, NIG_REG_PORT_SWAP))
28551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			emac_base = GRCBASE_EMAC1;
285602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		else
28571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			emac_base = GRCBASE_EMAC0;
2858cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby		break;
285902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	case SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1:
286002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (REG_RD(bp, NIG_REG_PORT_SWAP))
28611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			emac_base = GRCBASE_EMAC0;
28621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
286302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			emac_base = GRCBASE_EMAC1;
28641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
28651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH:
286602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
286702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		break;
286802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	case SHARED_HW_CFG_MDC_MDIO_ACCESS1_SWAPPED:
28691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		emac_base = (port) ? GRCBASE_EMAC0 : GRCBASE_EMAC1;
287002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		break;
287102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	default:
28721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
287302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
287402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	return emac_base;
287502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
287602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
287702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
287802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/******************************************************************/
287902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/*			CL22 access functions			  */
288002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/******************************************************************/
288102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic int bnx2x_cl22_write(struct bnx2x *bp,
288202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				       struct bnx2x_phy *phy,
288302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				       u16 reg, u16 val)
288402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
288502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 tmp, mode;
288602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u8 i;
288702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	int rc = 0;
288802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Switch to CL22 */
288902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	mode = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
289002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE,
289102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       mode & ~EMAC_MDIO_MODE_CLAUSE_45);
289202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
289302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* address */
289402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	tmp = ((phy->addr << 21) | (reg << 16) | val |
289502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       EMAC_MDIO_COMM_COMMAND_WRITE_22 |
289602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       EMAC_MDIO_COMM_START_BUSY);
289702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
289802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
28991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 50; i++) {
29001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(10);
29011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tmp = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
29031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
29041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			udelay(5);
29051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
29061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
290702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
29081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (tmp & EMAC_MDIO_COMM_START_BUSY) {
2909cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby		DP(NETIF_MSG_LINK, "write phy register failed\n");
291002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		rc = -EFAULT;
29111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
29121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, mode);
291302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	return rc;
29141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
29151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
291602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic int bnx2x_cl22_read(struct bnx2x *bp,
291702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				      struct bnx2x_phy *phy,
29181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				      u16 reg, u16 *ret_val)
291902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
292002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 val, mode;
29211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 i;
292202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	int rc = 0;
292390cc301859ea8840634324a7f5b9680312377667Jiri Slaby
292402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Switch to CL22 */
292502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	mode = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
292602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE,
29271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       mode & ~EMAC_MDIO_MODE_CLAUSE_45);
292802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
292902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* address */
293002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val = ((phy->addr << 21) | (reg << 16) |
29311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       EMAC_MDIO_COMM_COMMAND_READ_22 |
29321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       EMAC_MDIO_COMM_START_BUSY);
293302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
293402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
29351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 50; i++) {
29361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(10);
29371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
29391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
294002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			*ret_val = (u16)(val & EMAC_MDIO_COMM_DATA);
29411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			udelay(5);
2942cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby			break;
294302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		}
29441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
294502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (val & EMAC_MDIO_COMM_START_BUSY) {
29461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DP(NETIF_MSG_LINK, "read phy register failed\n");
29471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
294802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		*ret_val = 0;
294902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		rc = -EFAULT;
29501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
295102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, mode);
295202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	return rc;
295302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
29541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
295502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/******************************************************************/
295602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/*			CL45 access functions			  */
29571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************************************/
29581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
29591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   u8 devad, u16 reg, u16 *ret_val)
29601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
29611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 val;
29621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 i;
29631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rc = 0;
296402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (phy->flags & FLAGS_MDC_MDIO_WA_B0)
29651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bnx2x_bits_en(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS,
2966cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby			      EMAC_MDIO_STATUS_10MB);
296702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* address */
296802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val = ((phy->addr << 21) | (devad << 16) | reg |
29691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       EMAC_MDIO_COMM_COMMAND_ADDRESS |
297002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       EMAC_MDIO_COMM_START_BUSY);
29711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
29721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
297302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	for (i = 0; i < 50; i++) {
297402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		udelay(10);
297502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
297602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		val = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
297702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
297802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			udelay(5);
297902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			break;
29801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
298102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
29821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (val & EMAC_MDIO_COMM_START_BUSY) {
2983cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby		DP(NETIF_MSG_LINK, "read phy register failed\n");
298402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		netdev_err(bp->dev,  "MDC/MDIO access timeout\n");
29851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*ret_val = 0;
298602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		rc = -EFAULT;
298702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	} else {
298802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* data */
298902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		val = ((phy->addr << 21) | (devad << 16) |
299002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		       EMAC_MDIO_COMM_COMMAND_READ_45 |
29911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       EMAC_MDIO_COMM_START_BUSY);
29921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, val);
299302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
299402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		for (i = 0; i < 50; i++) {
29951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			udelay(10);
299602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
29971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			val = REG_RD(bp, phy->mdio_ctrl +
299802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				     EMAC_REG_EMAC_MDIO_COMM);
29991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
300002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				*ret_val = (u16)(val & EMAC_MDIO_COMM_DATA);
3001ad39c3004971173baeca80173e77022ee03eb9a1Jiri Slaby				break;
3002ad39c3004971173baeca80173e77022ee03eb9a1Jiri Slaby			}
3003ad39c3004971173baeca80173e77022ee03eb9a1Jiri Slaby		}
3004ad39c3004971173baeca80173e77022ee03eb9a1Jiri Slaby		if (val & EMAC_MDIO_COMM_START_BUSY) {
300502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			DP(NETIF_MSG_LINK, "read phy register failed\n");
3006ad39c3004971173baeca80173e77022ee03eb9a1Jiri Slaby			netdev_err(bp->dev,  "MDC/MDIO access timeout\n");
300702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			*ret_val = 0;
300802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			rc = -EFAULT;
300902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		}
3010db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	}
301102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Work around for E3 A0 */
301202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (phy->flags & FLAGS_MDC_MDIO_WA) {
301302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		phy->flags ^= FLAGS_DUMMY_READ;
3014db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby		if (phy->flags & FLAGS_DUMMY_READ) {
3015db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby			u16 temp_val;
3016db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby			bnx2x_cl45_read(bp, phy, devad, 0xf, &temp_val);
301702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		}
301802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
301902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
302002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (phy->flags & FLAGS_MDC_MDIO_WA_B0)
30211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bnx2x_bits_dis(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS,
302202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			       EMAC_MDIO_STATUS_10MB);
30231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rc;
3024096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby}
302502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
302602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic int bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
302702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			    u8 devad, u16 reg, u16 val)
30281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
30291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 tmp;
30301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 i;
30311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rc = 0;
30321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (phy->flags & FLAGS_MDC_MDIO_WA_B0)
30331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bnx2x_bits_en(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS,
30341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			      EMAC_MDIO_STATUS_10MB);
30351a86b5e34e4d09e3246a983c53929ce38af52275Klaus Kudielka
30361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* address */
303702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
30381a86b5e34e4d09e3246a983c53929ce38af52275Klaus Kudielka	tmp = ((phy->addr << 21) | (devad << 16) | reg |
303902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       EMAC_MDIO_COMM_COMMAND_ADDRESS |
30401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       EMAC_MDIO_COMM_START_BUSY);
304102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
304202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
304302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	for (i = 0; i < 50; i++) {
304402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		udelay(10);
30451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
304602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		tmp = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
304702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
304802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			udelay(5);
304902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			break;
305002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		}
30511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
305202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (tmp & EMAC_MDIO_COMM_START_BUSY) {
305302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		DP(NETIF_MSG_LINK, "write phy register failed\n");
305402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		netdev_err(bp->dev,  "MDC/MDIO access timeout\n");
30551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rc = -EFAULT;
305602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
305702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	} else {
30581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* data */
30591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tmp = ((phy->addr << 21) | (devad << 16) | val |
30601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       EMAC_MDIO_COMM_COMMAND_WRITE_45 |
30611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       EMAC_MDIO_COMM_START_BUSY);
30621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM, tmp);
30631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
306402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		for (i = 0; i < 50; i++) {
30651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			udelay(10);
306602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
306702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			tmp = REG_RD(bp, phy->mdio_ctrl +
306802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				     EMAC_REG_EMAC_MDIO_COMM);
306902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
307002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				udelay(5);
307102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				break;
307202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			}
307302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		}
307402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (tmp & EMAC_MDIO_COMM_START_BUSY) {
307502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			DP(NETIF_MSG_LINK, "write phy register failed\n");
30761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			netdev_err(bp->dev,  "MDC/MDIO access timeout\n");
307702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			rc = -EFAULT;
307802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		}
30791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
308002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Work around for E3 A0 */
308102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (phy->flags & FLAGS_MDC_MDIO_WA) {
30821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		phy->flags ^= FLAGS_DUMMY_READ;
308302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (phy->flags & FLAGS_DUMMY_READ) {
308402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			u16 temp_val;
308502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			bnx2x_cl45_read(bp, phy, devad, 0xf, &temp_val);
308602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		}
308702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
308802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (phy->flags & FLAGS_MDC_MDIO_WA_B0)
308902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		bnx2x_bits_dis(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS,
309002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			       EMAC_MDIO_STATUS_10MB);
309102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	return rc;
309202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
309302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
309402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
30951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************************************/
309602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/*			BSC access functions from E3	          */
309702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/******************************************************************/
309802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_bsc_module_sel(struct link_params *params)
309902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
310002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	int idx;
310102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 board_cfg, sfp_ctrl;
310202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 i2c_pins[I2C_SWITCH_WIDTH], i2c_val[I2C_SWITCH_WIDTH];
310302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
310402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u8 port = params->port;
310502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Read I2C output PINs */
310602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	board_cfg = REG_RD(bp, params->shmem_base +
310702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			   offsetof(struct shmem_region,
310802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				    dev_info.shared_hw_config.board));
310902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	i2c_pins[I2C_BSC0] = board_cfg & SHARED_HW_CFG_E3_I2C_MUX0_MASK;
311002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	i2c_pins[I2C_BSC1] = (board_cfg & SHARED_HW_CFG_E3_I2C_MUX1_MASK) >>
311102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			SHARED_HW_CFG_E3_I2C_MUX1_SHIFT;
311202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
311302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Read I2C output value */
311402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	sfp_ctrl = REG_RD(bp, params->shmem_base +
311502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  offsetof(struct shmem_region,
311602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				 dev_info.port_hw_config[port].e3_cmn_pin_cfg));
311702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	i2c_val[I2C_BSC0] = (sfp_ctrl & PORT_HW_CFG_E3_I2C_MUX0_MASK) > 0;
311802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	i2c_val[I2C_BSC1] = (sfp_ctrl & PORT_HW_CFG_E3_I2C_MUX1_MASK) > 0;
311902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	DP(NETIF_MSG_LINK, "Setting BSC switch\n");
312002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	for (idx = 0; idx < I2C_SWITCH_WIDTH; idx++)
312102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		bnx2x_set_cfg_pin(bp, i2c_pins[idx], i2c_val[idx]);
312202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
312302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
312402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic int bnx2x_bsc_read(struct link_params *params,
312502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  struct bnx2x_phy *phy,
312602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  u8 sl_devid,
312702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  u16 sl_addr,
312802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  u8 lc_addr,
312902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  u8 xfer_cnt,
313002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  u32 *data_array)
313102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
313202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 val, i;
313302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	int rc = 0;
313402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
313502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
313602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if ((sl_devid != 0xa0) && (sl_devid != 0xa2)) {
313702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		DP(NETIF_MSG_LINK, "invalid sl_devid 0x%x\n", sl_devid);
313802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		return -EINVAL;
313902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
314002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
314102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (xfer_cnt > 16) {
314202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		DP(NETIF_MSG_LINK, "invalid xfer_cnt %d. Max is 16 bytes\n",
314302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					xfer_cnt);
314402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		return -EINVAL;
314502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
314602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_bsc_module_sel(params);
314702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
314802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	xfer_cnt = 16 - lc_addr;
314902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
315002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* enable the engine */
315102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val = REG_RD(bp, MCP_REG_MCPR_IMC_COMMAND);
315202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val |= MCPR_IMC_COMMAND_ENABLE;
315302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, MCP_REG_MCPR_IMC_COMMAND, val);
315402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
315502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* program slave device ID */
315602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val = (sl_devid << 16) | sl_addr;
315702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, MCP_REG_MCPR_IMC_SLAVE_CONTROL, val);
315802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
315902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* start xfer with 0 byte to update the address pointer ???*/
316002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val = (MCPR_IMC_COMMAND_ENABLE) |
316102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	      (MCPR_IMC_COMMAND_WRITE_OP <<
316202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		MCPR_IMC_COMMAND_OPERATION_BITSHIFT) |
316302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		(lc_addr << MCPR_IMC_COMMAND_TRANSFER_ADDRESS_BITSHIFT) | (0);
316402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, MCP_REG_MCPR_IMC_COMMAND, val);
316502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
316602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* poll for completion */
316702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	i = 0;
316802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val = REG_RD(bp, MCP_REG_MCPR_IMC_COMMAND);
316902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	while (((val >> MCPR_IMC_COMMAND_IMC_STATUS_BITSHIFT) & 0x3) != 1) {
317002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		udelay(10);
317102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		val = REG_RD(bp, MCP_REG_MCPR_IMC_COMMAND);
317202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (i++ > 1000) {
317302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			DP(NETIF_MSG_LINK, "wr 0 byte timed out after %d try\n",
317402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby								i);
317502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			rc = -EFAULT;
317602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			break;
317702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		}
317802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
317902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (rc == -EFAULT)
318002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		return rc;
318102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
318202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* start xfer with read op */
318302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val = (MCPR_IMC_COMMAND_ENABLE) |
318402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		(MCPR_IMC_COMMAND_READ_OP <<
318502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		MCPR_IMC_COMMAND_OPERATION_BITSHIFT) |
318602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		(lc_addr << MCPR_IMC_COMMAND_TRANSFER_ADDRESS_BITSHIFT) |
318702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		  (xfer_cnt);
318802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, MCP_REG_MCPR_IMC_COMMAND, val);
318902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
319002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* poll for completion */
319102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	i = 0;
319202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val = REG_RD(bp, MCP_REG_MCPR_IMC_COMMAND);
319302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	while (((val >> MCPR_IMC_COMMAND_IMC_STATUS_BITSHIFT) & 0x3) != 1) {
319402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		udelay(10);
319502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		val = REG_RD(bp, MCP_REG_MCPR_IMC_COMMAND);
319602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (i++ > 1000) {
319702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			DP(NETIF_MSG_LINK, "rd op timed out after %d try\n", i);
319802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			rc = -EFAULT;
319902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			break;
320002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		}
320102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
320202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (rc == -EFAULT)
320302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		return rc;
320402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
320502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	for (i = (lc_addr >> 2); i < 4; i++) {
320602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		data_array[i] = REG_RD(bp, (MCP_REG_MCPR_IMC_DATAREG0 + i*4));
320702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby#ifdef __BIG_ENDIAN
32081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data_array[i] = ((data_array[i] & 0x000000ff) << 24) |
32091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				((data_array[i] & 0x0000ff00) << 8) |
32101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				((data_array[i] & 0x00ff0000) >> 8) |
32111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				((data_array[i] & 0xff000000) >> 24);
32121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
32131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
32141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return rc;
32151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
32161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void bnx2x_cl45_read_or_write(struct bnx2x *bp, struct bnx2x_phy *phy,
32181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     u8 devad, u16 reg, u16 or_val)
321902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
322002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u16 val;
322102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_read(bp, phy, devad, reg, &val);
322202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, devad, reg, val | or_val);
32231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
322402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
322502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabyint bnx2x_phy_read(struct link_params *params, u8 phy_addr,
322602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		   u8 devad, u16 reg, u16 *ret_val)
322702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
322802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u8 phy_index;
322902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/*
323002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * Probe for the phy according to the given phy_addr, and execute
323102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * the read request on it
323202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 */
323302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	for (phy_index = 0; phy_index < params->num_phys; phy_index++) {
323402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (params->phy[phy_index].addr == phy_addr) {
323502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			return bnx2x_cl45_read(params->bp,
323602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					       &params->phy[phy_index], devad,
323702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					       reg, ret_val);
323802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		}
323902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
324002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	return -EINVAL;
324102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
324202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
324302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabyint bnx2x_phy_write(struct link_params *params, u8 phy_addr,
324402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    u8 devad, u16 reg, u16 val)
324502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
324602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u8 phy_index;
324702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/*
324802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * Probe for the phy according to the given phy_addr, and execute
324902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * the write request on it
325002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 */
325102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	for (phy_index = 0; phy_index < params->num_phys; phy_index++) {
325202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (params->phy[phy_index].addr == phy_addr) {
325302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			return bnx2x_cl45_write(params->bp,
325402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby						&params->phy[phy_index], devad,
325502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby						reg, val);
3256db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby		}
325702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
325802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	return -EINVAL;
325902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
326002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic u8 bnx2x_get_warpcore_lane(struct bnx2x_phy *phy,
326102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				  struct link_params *params)
326202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
326302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u8 lane = 0;
326402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
326502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 path_swap, path_swap_ovr;
326602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u8 path, port;
32671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
326802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	path = BP_PATH(bp);
326902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	port = params->port;
3270db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby
327102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (bnx2x_is_4_port_mode(bp)) {
327202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		u32 port_swap, port_swap_ovr;
327302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
327402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/*figure out path swap value */
327502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		path_swap_ovr = REG_RD(bp, MISC_REG_FOUR_PORT_PATH_SWAP_OVWR);
327602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (path_swap_ovr & 0x1)
327702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			path_swap = (path_swap_ovr & 0x2);
327802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		else
327902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			path_swap = REG_RD(bp, MISC_REG_FOUR_PORT_PATH_SWAP);
328002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
328102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (path_swap)
328202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			path = path ^ 1;
328302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
32841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*figure out port swap value */
328502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		port_swap_ovr = REG_RD(bp, MISC_REG_FOUR_PORT_PORT_SWAP_OVWR);
328602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (port_swap_ovr & 0x1)
328702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			port_swap = (port_swap_ovr & 0x2);
328802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		else
328902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			port_swap = REG_RD(bp, MISC_REG_FOUR_PORT_PORT_SWAP);
329002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
329102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (port_swap)
329202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			port = port ^ 1;
329302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
32941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lane = (port<<1) + path;
329502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	} else { /* two port mode - no port swap */
329602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
3297db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby		/*figure out path swap value */
3298db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby		path_swap_ovr =
32991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			REG_RD(bp, MISC_REG_TWO_PORT_PATH_SWAP_OVWR);
330002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (path_swap_ovr & 0x1) {
330102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			path_swap = (path_swap_ovr & 0x2);
330202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		} else {
330302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			path_swap =
330402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				REG_RD(bp, MISC_REG_TWO_PORT_PATH_SWAP);
330502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		}
330602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (path_swap)
330702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			path = path ^ 1;
33081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
330902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		lane = path << 1 ;
331002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
3311db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	return lane;
3312db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby}
33131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
331402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_set_aer_mmd(struct link_params *params,
33151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			      struct bnx2x_phy *phy)
331602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
331702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 ser_lane;
331802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u16 offset, aer_val;
331902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
33201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ser_lane = ((params->lane_config &
33211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		     PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
332202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		     PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
332302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
332402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	offset = (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) ?
332502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		(phy->addr + ser_lane) : 0;
332602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
33271a86b5e34e4d09e3246a983c53929ce38af52275Klaus Kudielka	if (USES_WARPCORE(bp)) {
332802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		aer_val = bnx2x_get_warpcore_lane(phy, params);
33291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
333002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		 * In Dual-lane mode, two lanes are joined together,
333102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		 * so in order to configure them, the AER broadcast method is
333202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		 * used here.
333302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		 * 0x200 is the broadcast address for lanes 0,1
33341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * 0x201 is the broadcast address for lanes 2,3
333502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		 */
3336db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby		if (phy->flags & FLAGS_WC_DUAL_MODE)
333702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			aer_val = (aer_val >> 1) | 0x200;
333802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	} else if (CHIP_IS_E2(bp))
333902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		aer_val = 0x3800 + offset - 1;
334002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	else
334102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		aer_val = 0x3800 + offset;
334202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	DP(NETIF_MSG_LINK, "Set AER to 0x%x\n", aer_val);
334302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
334402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  MDIO_AER_BLOCK_AER_REG, aer_val);
334502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
334602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
334702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
334802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/******************************************************************/
334902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/*			Internal phy section			  */
335002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/******************************************************************/
335102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
335202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_set_serdes_access(struct bnx2x *bp, u8 port)
335302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
335402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
335502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
335602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Set Clause 22 */
335702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_ST + port*0x10, 1);
335802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245f8000);
335902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	udelay(500);
336002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245d000f);
336102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	udelay(500);
336202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 /* Set Clause 45 */
336302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_ST + port*0x10, 0);
336402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
336502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
336602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_serdes_deassert(struct bnx2x *bp, u8 port)
336702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
336802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 val;
33691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
337002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	DP(NETIF_MSG_LINK, "bnx2x_serdes_deassert\n");
337102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
337202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val = SERDES_RESET_BITS << (port*16);
337302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
337402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* reset and unreset the SerDes/XGXS */
337502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val);
337602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	udelay(500);
337702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val);
337802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
337902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_set_serdes_access(bp, port);
338002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
338102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_DEVAD + port*0x10,
338202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       DEFAULT_PHY_DEV_ADDR);
338302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
338402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
338502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_xgxs_deassert(struct link_params *params)
338602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
3387db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	struct bnx2x *bp = params->bp;
338802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u8 port;
338902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 val;
3390db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	DP(NETIF_MSG_LINK, "bnx2x_xgxs_deassert\n");
339102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	port = params->port;
339202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
339302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val = XGXS_RESET_BITS << (port*16);
339402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
339502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* reset and unreset the SerDes/XGXS */
339602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val);
339702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	udelay(500);
339802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val);
339902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
340002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + port*0x18, 0);
34011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
340202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	       params->phy[INT_PHY].def_md_devad);
340302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
340402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
3405db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slabystatic void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy,
340602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				     struct link_params *params, u16 *ieee_fc)
3407db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby{
3408db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	struct bnx2x *bp = params->bp;
340902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	*ieee_fc = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX;
341002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/**
341102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * resolve pause mode and advertisement Please refer to Table
341202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 * 28B-3 of the 802.3ab-1999 spec
341302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 */
341402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
341502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	switch (phy->req_flow_ctrl) {
341602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	case BNX2X_FLOW_CTRL_AUTO:
341702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (params->req_fc_auto_adv == BNX2X_FLOW_CTRL_BOTH)
341802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			*ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
341902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		else
342002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			*ieee_fc |=
342102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
342202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		break;
342302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
342402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	case BNX2X_FLOW_CTRL_TX:
342502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		*ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
342602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		break;
342702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
342802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	case BNX2X_FLOW_CTRL_RX:
342902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	case BNX2X_FLOW_CTRL_BOTH:
343002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		*ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
343102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		break;
343202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
343302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	case BNX2X_FLOW_CTRL_NONE:
343402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	default:
34351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE;
343602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		break;
343702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
3438db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	DP(NETIF_MSG_LINK, "ieee_fc = 0x%x\n", *ieee_fc);
34391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
344002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
34411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void set_phy_vars(struct link_params *params,
344202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 struct link_vars *vars)
344302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
3444db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	struct bnx2x *bp = params->bp;
34451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 actual_phy_idx, phy_index, link_cfg_idx;
344602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u8 phy_config_swapped = params->multi_phy_config &
34471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			PORT_HW_CFG_PHY_SWAPPED_ENABLED;
344802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	for (phy_index = INT_PHY; phy_index < params->num_phys;
34491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	      phy_index++) {
345002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		link_cfg_idx = LINK_CONFIG_IDX(phy_index);
345102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		actual_phy_idx = phy_index;
345202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (phy_config_swapped) {
345302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			if (phy_index == EXT_PHY1)
345402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				actual_phy_idx = EXT_PHY2;
34551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else if (phy_index == EXT_PHY2)
345602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				actual_phy_idx = EXT_PHY1;
345702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		}
345802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		params->phy[actual_phy_idx].req_flow_ctrl =
34591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			params->req_flow_ctrl[link_cfg_idx];
346002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
34611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		params->phy[actual_phy_idx].req_line_speed =
34621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			params->req_line_speed[link_cfg_idx];
346302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
346402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		params->phy[actual_phy_idx].speed_cap_mask =
34651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			params->speed_cap_mask[link_cfg_idx];
346602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
346702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		params->phy[actual_phy_idx].req_duplex =
34681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			params->req_duplex[link_cfg_idx];
346902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
347002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (params->req_line_speed[link_cfg_idx] ==
347102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    SPEED_AUTO_NEG)
347202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_ENABLED;
347302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
347402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		DP(NETIF_MSG_LINK, "req_flow_ctrl %x, req_line_speed %x,"
347502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			   " speed_cap_mask %x\n",
347602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			   params->phy[actual_phy_idx].req_flow_ctrl,
347702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			   params->phy[actual_phy_idx].req_line_speed,
3478d5dedf99e4ca9860ce8a1dd42db1cb666c360632Andrew Morton			   params->phy[actual_phy_idx].speed_cap_mask);
347902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
348002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
348102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
348202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_ext_phy_set_pause(struct link_params *params,
348302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				    struct bnx2x_phy *phy,
34841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    struct link_vars *vars)
34851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
348602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u16 val;
348702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
34881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* read modify write pause advertizing */
348902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, &val);
349002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
349102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH;
349202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
349302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
349402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
349502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if ((vars->ieee_fc &
349602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
349702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
349802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
349902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
350002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if ((vars->ieee_fc &
350102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
350202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
350302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		val |= MDIO_AN_REG_ADV_PAUSE_PAUSE;
350402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
350502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	DP(NETIF_MSG_LINK, "Ext phy AN advertize 0x%x\n", val);
350602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, val);
350702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
350802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
350902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result)
351002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{						/*  LD	    LP	 */
351102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	switch (pause_result) {			/* ASYM P ASYM P */
351202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	case 0xb:				/*   1  0   1  1 */
351302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		vars->flow_ctrl = BNX2X_FLOW_CTRL_TX;
351402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		break;
351502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
351602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	case 0xe:				/*   1  1   1  0 */
351702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		vars->flow_ctrl = BNX2X_FLOW_CTRL_RX;
351802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		break;
351902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
352002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	case 0x5:				/*   0  1   0  1 */
35211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0x7:				/*   0  1   1  1 */
35221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0xd:				/*   1  1   0  1 */
352302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	case 0xf:				/*   1  1   1  1 */
352402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		vars->flow_ctrl = BNX2X_FLOW_CTRL_BOTH;
352502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		break;
352602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
352702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	default:
352802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		break;
352902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
35301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (pause_result & (1<<0))
35311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vars->link_status |= LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE;
35321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (pause_result & (1<<1))
35331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vars->link_status |= LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE;
35341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
35351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy,
35371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   struct link_params *params,
35381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   struct link_vars *vars)
35391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
35401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct bnx2x *bp = params->bp;
354102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u16 ld_pause;		/* local */
35421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 lp_pause;		/* link partner */
354302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u16 pause_result;
354402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u8 ret = 0;
354502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* read twice */
354602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
354702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
35481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
354902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO)
355002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		vars->flow_ctrl = phy->req_flow_ctrl;
355102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	else if (phy->req_line_speed != SPEED_AUTO_NEG)
355202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		vars->flow_ctrl = params->req_fc_auto_adv;
355302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	else if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) {
355402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		ret = 1;
355502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE) {
355602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			bnx2x_cl22_read(bp, phy,
355702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					0x4, &ld_pause);
355802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			bnx2x_cl22_read(bp, phy,
3559db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby					0x5, &lp_pause);
356002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		} else {
356102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			bnx2x_cl45_read(bp, phy,
356202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					MDIO_AN_DEVAD,
356302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					MDIO_AN_REG_ADV_PAUSE, &ld_pause);
356402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			bnx2x_cl45_read(bp, phy,
356502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					MDIO_AN_DEVAD,
356602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					MDIO_AN_REG_LP_AUTO_NEG, &lp_pause);
356702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		}
35681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pause_result = (ld_pause &
35691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				MDIO_AN_REG_ADV_PAUSE_MASK) >> 8;
357002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		pause_result |= (lp_pause &
35711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 MDIO_AN_REG_ADV_PAUSE_MASK) >> 10;
3572cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby		DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x\n",
357302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		   pause_result);
357402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		bnx2x_pause_resolve(vars, pause_result);
357502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
357602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	return ret;
357702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
357802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/******************************************************************/
357902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/*			Warpcore section			  */
358002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/******************************************************************/
358102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby/* The init_internal_warpcore should mirror the xgxs,
358202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * i.e. reset the lane (if needed), set aer for the
358302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * init configuration, and set/clear SGMII flag. Internal
358402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby * phy init is done purely in phy_init stage.
358502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby */
35861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
358702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					struct link_params *params,
358802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					struct link_vars *vars) {
358902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u16 val16 = 0, lane, bam37 = 0;
359002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
359102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	DP(NETIF_MSG_LINK, "Enable Auto Negotiation for KR\n");
359202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
359302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Disable Autoneg: re-enable it after adv is done. */
359402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
35951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0);
359602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
359702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Check adding advertisement for 1G KX */
3598db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	if (((vars->line_speed == SPEED_AUTO_NEG) &&
3599db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	     (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
360002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	    (vars->line_speed == SPEED_1000)) {
360102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		u16 sd_digital;
360202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		val16 |= (1<<5);
360302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
360402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* Enable CL37 1G Parallel Detect */
360502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
360602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, &sd_digital);
360702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
360802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2,
360902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				 (sd_digital | 0x1));
361002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
361102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		DP(NETIF_MSG_LINK, "Advertize 1G\n");
361202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
36131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (((vars->line_speed == SPEED_AUTO_NEG) &&
361402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	     (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) ||
36151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (vars->line_speed ==  SPEED_10000)) {
361602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* Check adding advertisement for 10G KR */
361702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		val16 |= (1<<7);
361802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* Enable 10G Parallel Detect */
36191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
362002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				MDIO_WC_REG_PAR_DET_10G_CTRL, 1);
362102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
362202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		DP(NETIF_MSG_LINK, "Advertize 10G\n");
3623db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	}
362402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
362502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Set Transmit PMD settings */
3626db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	lane = bnx2x_get_warpcore_lane(phy, params);
362702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
362802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		      MDIO_WC_REG_TX0_TX_DRIVER + 0x10*lane,
362902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		     ((0x02 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
363002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		      (0x06 << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
363102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		      (0x09 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET)));
363202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
363302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_CL72_USERB0_CL72_OS_DEF_CTRL,
363402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 0x03f0);
363502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
363602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_CL72_USERB0_CL72_2P5_DEF_CTRL,
36371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 0x03f0);
363802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
363902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Advertised speeds */
364002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
36411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, val16);
36421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Advertised and set FEC (Forward Error Correction) */
364402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
36451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT2,
3646cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby			 (MDIO_WC_REG_AN_IEEE1BLK_AN_ADV2_FEC_ABILITY |
364702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  MDIO_WC_REG_AN_IEEE1BLK_AN_ADV2_FEC_REQ));
364802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
364902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Enable CL37 BAM */
365002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (REG_RD(bp, params->shmem_base +
365102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		   offsetof(struct shmem_region, dev_info.
365202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			    port_hw_config[params->port].default_cfg)) &
365302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	    PORT_HW_CFG_ENABLE_BAM_ON_KR_ENABLED) {
365402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
365502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				MDIO_WC_REG_DIGITAL6_MP5_NEXTPAGECTRL, &bam37);
365602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
365702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_WC_REG_DIGITAL6_MP5_NEXTPAGECTRL, bam37 | 1);
365802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		DP(NETIF_MSG_LINK, "Enable CL37 BAM on KR\n");
365902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
366002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
366102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Advertise pause */
366202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_ext_phy_set_pause(params, phy, vars);
366302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
366402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY;
366502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
366602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
366702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_WC_REG_DIGITAL5_MISC7, &val16);
366802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
366902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
367002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_DIGITAL5_MISC7, val16 | 0x100);
367102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
367202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Over 1G - AN local device user page 1 */
367302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
367402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_WC_REG_DIGITAL3_UP1, 0x1f);
367502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
367602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Enable Autoneg */
367702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
367802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1000);
367902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
368002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
368102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
368202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,
368302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				      struct link_params *params,
368402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				      struct link_vars *vars)
368502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
368602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
368702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u16 val;
368802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
368902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Disable Autoneg */
369002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
369102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7);
369202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
369302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
369402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_PAR_DET_10G_CTRL, 0);
369502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
369602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
369702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, 0x3f00);
369802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
369902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
370002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, 0);
370102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
370202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
370302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x0);
370402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
37051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
370602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_WC_REG_DIGITAL3_UP1, 0x1);
370702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
3708db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
3709db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby			 MDIO_WC_REG_DIGITAL5_MISC7, 0xa);
37101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
371102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Disable CL36 PCS Tx */
371202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
371302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0x0);
371402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
371502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Double Wide Single Data Rate @ pll rate */
371602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
371702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0xFFFF);
371802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
371902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Leave cl72 training enable, needed for KR */
372002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD,
372102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		MDIO_WC_REG_PMD_IEEE9BLK_TENGBASE_KR_PMD_CONTROL_REGISTER_150,
372202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		0x2);
372302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
37241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Leave CL72 enabled */
37251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
372602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
372702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 &val);
3728db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
3729db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby			 MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
37301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 val | 0x3800);
373102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
373202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Set speed via PMA/PMD register */
373302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD,
373402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x2040);
373502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
373602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD,
373702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_IEEE0BLK_AUTONEGNP, 0xB);
373802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
3739db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	/*Enable encoded forced speed */
374002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
374102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x30);
374202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
374302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Turn TX scramble payload only the 64/66 scrambler */
374402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
374502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_TX66_CONTROL, 0x9);
3746db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby
3747db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	/* Turn RX scramble payload only the 64/66 scrambler */
374802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
374902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				 MDIO_WC_REG_RX66_CONTROL, 0xF9);
375002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
375102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* set and clear loopback to cause a reset to 64/66 decoder */
375202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
3753db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby			 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x4000);
3754db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
375502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x0);
375602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
375702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
375802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
375902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_warpcore_set_10G_XFI(struct bnx2x_phy *phy,
3760db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby				       struct link_params *params,
3761db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby				       u8 is_xfi)
37621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
376302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
37641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 misc1_val, tap_val, tx_driver_val, lane, val;
376502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Hold rxSeqStart */
376602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
376702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, &val);
376802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
376902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, (val | 0x8000));
3770db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby
3771db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	/* Hold tx_fifo_reset */
37721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
377302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, &val);
37741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
377502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, (val | 0x1));
377602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
377702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Disable CL73 AN */
377802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0);
377902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
378002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Disable 100FX Enable and Auto-Detect */
378102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
378202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_WC_REG_FX100_CTRL1, &val);
378302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
378402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_FX100_CTRL1, (val & 0xFFFA));
378502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
378602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Disable 100FX Idle detect */
378702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
37881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			MDIO_WC_REG_FX100_CTRL3, &val);
378902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
379002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_FX100_CTRL3, (val | 0x0080));
37911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set Block address to Remote PHY & Clear forced_speed[5] */
37931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
37941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			MDIO_WC_REG_DIGITAL4_MISC3, &val);
379502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
37961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 MDIO_WC_REG_DIGITAL4_MISC3, (val & 0xFF7F));
3797cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby
379802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Turn off auto-detect & fiber mode */
37991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
380002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, &val);
380102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
38021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1,
380302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 (val & 0xFFEE));
380402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
380502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Set filter_force_link, disable_false_link and parallel_detect */
380602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
380702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, &val);
380802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
380902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2,
381002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 ((val | 0x0006) & 0xFFFE));
381102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
381202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Set XFI / SFI */
381302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
381402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_WC_REG_SERDESDIGITAL_MISC1, &misc1_val);
381502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
381602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	misc1_val &= ~(0x1f);
381702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
381802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (is_xfi) {
381902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		misc1_val |= 0x5;
382002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		tap_val = ((0x08 << MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET) |
382102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			   (0x37 << MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_OFFSET) |
382202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			   (0x00 << MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_OFFSET));
382302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		tx_driver_val =
382402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		      ((0x00 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
382502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		       (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
38261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       (0x03 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET));
38271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
382802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	} else {
382902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		misc1_val |= 0x9;
383002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		tap_val = ((0x12 << MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET) |
383102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			   (0x2d << MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_OFFSET) |
383202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			   (0x00 << MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_OFFSET));
383302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		tx_driver_val =
383402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		      ((0x02 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
383502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		       (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
383602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		       (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET));
383702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
383802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
383902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_SERDESDIGITAL_MISC1, misc1_val);
384002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
384102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Set Transmit PMD settings */
384202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	lane = bnx2x_get_warpcore_lane(phy, params);
384302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
384402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_TX_FIR_TAP,
384502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 tap_val | MDIO_WC_REG_TX_FIR_TAP_ENABLE);
38461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
38471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 MDIO_WC_REG_TX0_TX_DRIVER + 0x10*lane,
384802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 tx_driver_val);
384902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
38501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Enable fiber mode, enable and invert sig_det */
38511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
385202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, &val);
38531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
38541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, val | 0xd);
385502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
385602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Set Block address to Remote PHY & Set forced_speed[5], 40bit mode */
385702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
385802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_WC_REG_DIGITAL4_MISC3, &val);
385902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
386002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_DIGITAL4_MISC3, val | 0x8080);
386102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
386202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* 10G XFI Full Duplex */
38631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
386402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x100);
38651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
386602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Release tx_fifo_reset */
386702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
386802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, &val);
38691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
387002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, val & 0xFFFE);
387102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
387202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Release rxSeqStart */
387302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
387402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, &val);
387502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
387602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, (val & 0x7FFF));
387702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
387802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
387902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_warpcore_set_20G_KR2(struct bnx2x *bp,
388002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				       struct bnx2x_phy *phy)
38811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
388202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	DP(NETIF_MSG_LINK, "KR2 still not supported !!!\n");
388302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
388402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
388502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_warpcore_set_20G_DXGXS(struct bnx2x *bp,
388602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					 struct bnx2x_phy *phy,
3887096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby					 u16 lane)
388802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
388902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Rx0 anaRxControl1G */
389002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
38911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 MDIO_WC_REG_RX0_ANARXCONTROL1G, 0x90);
38921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
389302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Rx2 anaRxControl1G */
38941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
389502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_RX2_ANARXCONTROL1G, 0x90);
389602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
389702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
38981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 MDIO_WC_REG_RX66_SCW0, 0xE070);
389902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
390002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
390102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_RX66_SCW1, 0xC0D0);
390202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
390302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
390402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_RX66_SCW2, 0xA0B0);
390502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
390602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
390702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_RX66_SCW3, 0x8090);
3908db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby
390902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
391002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_RX66_SCW0_MASK, 0xF0F0);
3911096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby
391202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
391302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_RX66_SCW1_MASK, 0xF0F0);
391402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
39151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
39161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 MDIO_WC_REG_RX66_SCW2_MASK, 0xF0F0);
391702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
39181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
391902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_RX66_SCW3_MASK, 0xF0F0);
392002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
392102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Serdes Digital Misc1 */
39221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
39231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 MDIO_WC_REG_SERDESDIGITAL_MISC1, 0x6008);
392402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
39251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Serdes Digital4 Misc3 */
392602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
392702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_DIGITAL4_MISC3, 0x8088);
39281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
392902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Set Transmit PMD settings */
39301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
393102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_TX_FIR_TAP,
393202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			((0x12 << MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET) |
393302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 (0x2d << MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_OFFSET) |
39341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 (0x00 << MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_OFFSET) |
393502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_TX_FIR_TAP_ENABLE));
393602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
393702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		      MDIO_WC_REG_TX0_TX_DRIVER + 0x10*lane,
393802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		     ((0x02 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
393902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		      (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
394002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		      (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET)));
394102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
394202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
39431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void bnx2x_warpcore_set_sgmii_speed(struct bnx2x_phy *phy,
394402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					   struct link_params *params,
394502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					   u8 fiber_mode)
394602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
394702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
3948096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby	u16 val16, digctrl_kx1, digctrl_kx2;
394902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u8 lane;
395002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
395102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	lane = bnx2x_get_warpcore_lane(phy, params);
39521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
395302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Clear XFI clock comp in non-10G single lane mode. */
39541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
395502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_WC_REG_RX66_CONTROL, &val16);
395602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
395702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_RX66_CONTROL, val16 & ~(3<<13));
39581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
395902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (phy->req_line_speed == SPEED_AUTO_NEG) {
396002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* SGMII Autoneg */
396102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
396202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
396302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
396402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				 MDIO_WC_REG_COMBO_IEEE0_MIICTRL,
396502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				 val16 | 0x1000);
396602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		DP(NETIF_MSG_LINK, "set SGMII AUTONEG\n");
396702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	} else {
3968db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
396902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
397002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		val16 &= 0xcfbf;
3971096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby		switch (phy->req_line_speed) {
397202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		case SPEED_10:
397302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			break;
397402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		case SPEED_100:
39751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			val16 |= 0x2000;
397602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			break;
39771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case SPEED_1000:
397802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			val16 |= 0x0040;
397902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			break;
398002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		default:
39811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			DP(NETIF_MSG_LINK,
39821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   "Speed not supported: 0x%x\n", phy->req_line_speed);
398302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			return;
39841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
398502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
398602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (phy->req_duplex == DUPLEX_FULL)
39871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			val16 |= 0x0100;
39881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
39901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				MDIO_WC_REG_COMBO_IEEE0_MIICTRL, val16);
39911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DP(NETIF_MSG_LINK, "set SGMII force speed %d\n",
39931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       phy->req_line_speed);
399402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
399502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
39961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DP(NETIF_MSG_LINK, "  (readback) %x\n", val16);
3997cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby	}
399802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
399902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* SGMII Slave mode and disable signal detect */
400002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
400102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, &digctrl_kx1);
400202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (fiber_mode)
400302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		digctrl_kx1 = 1;
400402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	else
400502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		digctrl_kx1 &= 0xff4a;
40061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
400802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1,
40091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			digctrl_kx1);
40101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
401102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Turn off parallel detect */
401202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
401302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, &digctrl_kx2);
401402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
401502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2,
401602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			(digctrl_kx2 & ~(1<<2)));
401702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
401802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Re-enable parallel detect */
401902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
402002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2,
402102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			(digctrl_kx2 | (1<<2)));
402202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
402302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Enable autodet */
402402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
402502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1,
402602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			(digctrl_kx1 | 0x10));
402702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
402802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
402902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_warpcore_reset_lane(struct bnx2x *bp,
403002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				      struct bnx2x_phy *phy,
403102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				      u8 reset)
403202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
403302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u16 val;
403402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Take lane out of reset after configuration is finished */
403502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
403602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_WC_REG_DIGITAL5_MISC6, &val);
403702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (reset)
403802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		val |= 0xC000;
40391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
404002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		val &= 0x3FFF;
404102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
404202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_DIGITAL5_MISC6, val);
40431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
404402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_DIGITAL5_MISC6, &val);
404502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
40461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
404702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
404802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Clear SFI/XFI link settings registers */
404902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_warpcore_clear_regs(struct bnx2x_phy *phy,
40501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				      struct link_params *params,
405102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				      u16 lane)
405202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
40531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct bnx2x *bp = params->bp;
405402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u16 val16;
405502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
405602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Set XFI clock comp as default. */
405702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
405802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_WC_REG_RX66_CONTROL, &val16);
405902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
40601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 MDIO_WC_REG_RX66_CONTROL, val16 | (3<<13));
40611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
406202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_warpcore_reset_lane(bp, phy, 1);
406302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0);
40641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
40651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 MDIO_WC_REG_FX100_CTRL1, 0x014a);
406602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
406702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_FX100_CTRL3, 0x0800);
406802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
40691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 MDIO_WC_REG_DIGITAL4_MISC3, 0x8008);
407002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
407102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, 0x0195);
407202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
40731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x0007);
407402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
407502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, 0x0002);
407602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
40771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 MDIO_WC_REG_SERDESDIGITAL_MISC1, 0x6000);
407802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	lane = bnx2x_get_warpcore_lane(phy, params);
407902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
408002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_TX_FIR_TAP, 0x0000);
408102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
408202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_TX0_TX_DRIVER + 0x10*lane, 0x0990);
408302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
408402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x2040);
408502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
408602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_COMBO_IEEE0_MIICTRL, 0x0140);
408702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_warpcore_reset_lane(bp, phy, 0);
408802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
408902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
409002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic int bnx2x_get_mod_abs_int_cfg(struct bnx2x *bp,
409102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby						u32 chip_id,
409202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby						u32 shmem_base, u8 port,
409302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby						u8 *gpio_num, u8 *gpio_port)
409402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
40951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 cfg_pin;
40961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*gpio_num = 0;
409702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	*gpio_port = 0;
409802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (CHIP_IS_E3(bp)) {
40991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cfg_pin = (REG_RD(bp, shmem_base +
410002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				offsetof(struct shmem_region,
410102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				dev_info.port_hw_config[port].e3_sfp_ctrl)) &
410202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				PORT_HW_CFG_E3_MOD_ABS_MASK) >>
410302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				PORT_HW_CFG_E3_MOD_ABS_SHIFT;
410402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
410502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/*
41061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Should not happen. This function called upon interrupt
410702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		 * triggered by GPIO ( since EPIO can only generate interrupts
410802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		 * to MCP).
410902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		 * So if this function was called and none of the GPIOs was set,
411002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		 * it means the shit hit the fan.
411102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		 */
411202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if ((cfg_pin < PIN_CFG_GPIO0_P0) ||
411302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    (cfg_pin > PIN_CFG_GPIO3_P1)) {
411402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			DP(NETIF_MSG_LINK,
411502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			   "ERROR: Invalid cfg pin %x for module detect indication\n",
411602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			   cfg_pin);
411702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			return -EINVAL;
411802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		}
411902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
412002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		*gpio_num = (cfg_pin - PIN_CFG_GPIO0_P0) & 0x3;
412102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		*gpio_port = (cfg_pin - PIN_CFG_GPIO0_P0) >> 2;
41221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
412302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		*gpio_num = MISC_REGISTERS_GPIO_3;
41241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*gpio_port = port;
412502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
412602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	DP(NETIF_MSG_LINK, "MOD_ABS int GPIO%d_P%d\n", *gpio_num, *gpio_port);
412702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	return 0;
412802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
412902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
413002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic int bnx2x_is_sfp_module_plugged(struct bnx2x_phy *phy,
41311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       struct link_params *params)
413202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
413302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
413402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u8 gpio_num, gpio_port;
413502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 gpio_val;
413602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (bnx2x_get_mod_abs_int_cfg(bp, params->chip_id,
413702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				      params->shmem_base, params->port,
413802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				      &gpio_num, &gpio_port) != 0)
413902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		return 0;
414002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	gpio_val = bnx2x_get_gpio(bp, gpio_num, gpio_port);
414102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
414202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Call the handling function in case module is detected */
414302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (gpio_val == 0)
414402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		return 1;
414502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	else
414602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		return 0;
414702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
414802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic int bnx2x_warpcore_get_sigdet(struct bnx2x_phy *phy,
414902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					struct link_params *params)
415002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
415102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u16 gp2_status_reg0, lane;
415202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
415302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
415402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	lane = bnx2x_get_warpcore_lane(phy, params);
415502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
415602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, MDIO_WC_REG_GP2_STATUS_GP_2_0,
415702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				 &gp2_status_reg0);
415802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
415902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	return (gp2_status_reg0 >> (8+lane)) & 0x1;
416002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
416102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
416202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_warpcore_config_runtime(struct bnx2x_phy *phy,
416302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				       struct link_params *params,
416402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				       struct link_vars *vars)
416502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
416602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
416702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 serdes_net_if;
416802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u16 gp_status1 = 0, lnkup = 0, lnkup_kr = 0;
416902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u16 lane = bnx2x_get_warpcore_lane(phy, params);
417002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
417102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	vars->turn_to_run_wc_rt = vars->turn_to_run_wc_rt ? 0 : 1;
417202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
417302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (!vars->turn_to_run_wc_rt)
41741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
41751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
417602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* return if there is no link partner */
41771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(bnx2x_warpcore_get_sigdet(phy, params))) {
41781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DP(NETIF_MSG_LINK, "bnx2x_warpcore_get_sigdet false\n");
417902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		return;
418002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
41811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (vars->rx_tx_asic_rst) {
41831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		serdes_net_if = (REG_RD(bp, params->shmem_base +
41841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				offsetof(struct shmem_region, dev_info.
41851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				port_hw_config[params->port].default_cfg)) &
41861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				PORT_HW_CFG_NET_SERDES_IF_MASK);
41871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
418802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		switch (serdes_net_if) {
41891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case PORT_HW_CFG_NET_SERDES_IF_KR:
4190cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby			/* Do we get link yet? */
41911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, 0x81d1,
41921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds								&gp_status1);
419302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			lnkup = (gp_status1 >> (8+lane)) & 0x1;/* 1G */
41941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/*10G KR*/
41951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			lnkup_kr = (gp_status1 >> (12+lane)) & 0x1;
419602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
419702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			DP(NETIF_MSG_LINK,
419802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				"gp_status1 0x%x\n", gp_status1);
419902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
420002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			if (lnkup_kr || lnkup) {
420102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					vars->rx_tx_asic_rst = 0;
420202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					DP(NETIF_MSG_LINK,
420302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					"link up, rx_tx_asic_rst 0x%x\n",
420402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					vars->rx_tx_asic_rst);
420502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			} else {
420602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				/*reset the lane to see if link comes up.*/
42071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				bnx2x_warpcore_reset_lane(bp, phy, 1);
420802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				bnx2x_warpcore_reset_lane(bp, phy, 0);
420902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
421002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				/* restart Autoneg */
421102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
421202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1200);
421302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
421402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				vars->rx_tx_asic_rst--;
421502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				DP(NETIF_MSG_LINK, "0x%x retry left\n",
421602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				vars->rx_tx_asic_rst);
42171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
421802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			break;
42191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
42201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
42211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
42221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
422302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
42241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} /*params->rx_tx_asic_rst*/
4225cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby
42261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
42271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
422802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
42291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       struct link_params *params,
42301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       struct link_vars *vars)
423102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
42321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct bnx2x *bp = params->bp;
42331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 serdes_net_if;
423402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u8 fiber_mode;
42351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 lane = bnx2x_get_warpcore_lane(phy, params);
42361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	serdes_net_if = (REG_RD(bp, params->shmem_base +
42371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 offsetof(struct shmem_region, dev_info.
42381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  port_hw_config[params->port].default_cfg)) &
423902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 PORT_HW_CFG_NET_SERDES_IF_MASK);
424002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	DP(NETIF_MSG_LINK, "Begin Warpcore init, link_speed %d, "
424102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			   "serdes_net_if = 0x%x\n",
424202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		       vars->line_speed, serdes_net_if);
424302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_set_aer_mmd(params, phy);
424402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
424502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	vars->phy_flags |= PHY_XGXS_FLAG;
42461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((serdes_net_if == PORT_HW_CFG_NET_SERDES_IF_SGMII) ||
42471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (phy->req_line_speed &&
42481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	     ((phy->req_line_speed == SPEED_100) ||
42491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	      (phy->req_line_speed == SPEED_10)))) {
42501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vars->phy_flags |= PHY_SGMII_FLAG;
42511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DP(NETIF_MSG_LINK, "Setting SGMII mode\n");
42521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bnx2x_warpcore_clear_regs(phy, params, lane);
425302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		bnx2x_warpcore_set_sgmii_speed(phy, params, 0);
42541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
4255cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby		switch (serdes_net_if) {
425602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		case PORT_HW_CFG_NET_SERDES_IF_KR:
425702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			/* Enable KR Auto Neg */
425802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			if (params->loopback_mode == LOOPBACK_NONE)
42591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				bnx2x_warpcore_enable_AN_KR(phy, params, vars);
42601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else {
426102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				DP(NETIF_MSG_LINK, "Setting KR 10G-Force\n");
42621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				bnx2x_warpcore_set_10G_KR(phy, params, vars);
426302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			}
426402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			break;
42651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
42661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case PORT_HW_CFG_NET_SERDES_IF_XFI:
426702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			bnx2x_warpcore_clear_regs(phy, params, lane);
426802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			if (vars->line_speed == SPEED_10000) {
426902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				DP(NETIF_MSG_LINK, "Setting 10G XFI\n");
427002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				bnx2x_warpcore_set_10G_XFI(phy, params, 1);
427102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			} else {
427202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				if (SINGLE_MEDIA_DIRECT(params)) {
427302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					DP(NETIF_MSG_LINK, "1G Fiber\n");
427402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					fiber_mode = 1;
427502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				} else {
427602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					DP(NETIF_MSG_LINK, "10/100/1G SGMII\n");
427702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					fiber_mode = 0;
427802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				}
42791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				bnx2x_warpcore_set_sgmii_speed(phy,
428002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby								params,
428102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby								fiber_mode);
428202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			}
428302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
428402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			break;
428502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
428602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		case PORT_HW_CFG_NET_SERDES_IF_SFI:
428702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
428802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			bnx2x_warpcore_clear_regs(phy, params, lane);
428902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			if (vars->line_speed == SPEED_10000) {
429002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				DP(NETIF_MSG_LINK, "Setting 10G SFI\n");
429102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				bnx2x_warpcore_set_10G_XFI(phy, params, 0);
429202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			} else if (vars->line_speed == SPEED_1000) {
429302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				DP(NETIF_MSG_LINK, "Setting 1G Fiber\n");
429402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				bnx2x_warpcore_set_sgmii_speed(phy, params, 1);
429502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			}
429602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			/* Issue Module detection */
429702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			if (bnx2x_is_sfp_module_plugged(phy, params))
429802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				bnx2x_sfp_module_detection(phy, params);
429902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			break;
430002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
430102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		case PORT_HW_CFG_NET_SERDES_IF_DXGXS:
430202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			if (vars->line_speed != SPEED_20000) {
430302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				DP(NETIF_MSG_LINK, "Speed not supported yet\n");
430402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				return;
43051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
43061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			DP(NETIF_MSG_LINK, "Setting 20G DXGXS\n");
43071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			bnx2x_warpcore_set_20G_DXGXS(bp, phy, lane);
43081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Issue Module detection */
43091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
43101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			bnx2x_sfp_module_detection(phy, params);
431102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			break;
43121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4313cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby		case PORT_HW_CFG_NET_SERDES_IF_KR2:
431402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			if (vars->line_speed != SPEED_20000) {
431502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				DP(NETIF_MSG_LINK, "Speed not supported yet\n");
431602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				return;
43171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
43181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			DP(NETIF_MSG_LINK, "Setting 20G KR2\n");
431902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			bnx2x_warpcore_set_20G_KR2(bp, phy);
432002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			break;
432102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
432202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		default:
43231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			DP(NETIF_MSG_LINK,
43241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   "Unsupported Serdes Net Interface 0x%x\n",
432502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			   serdes_net_if);
432602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			return;
432702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		}
43281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
432902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
433002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Take lane out of reset after configuration is finished */
433102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_warpcore_reset_lane(bp, phy, 0);
433202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	DP(NETIF_MSG_LINK, "Exit config init\n");
433302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
43341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
43351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void bnx2x_sfp_e3_set_transmitter(struct link_params *params,
433602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					 struct bnx2x_phy *phy,
433702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					 u8 tx_en)
433802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
433902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
434002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 cfg_pin;
434102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u8 port = params->port;
434202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
434302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	cfg_pin = REG_RD(bp, params->shmem_base +
434402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				offsetof(struct shmem_region,
434502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				dev_info.port_hw_config[port].e3_sfp_ctrl)) &
434602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				PORT_HW_CFG_TX_LASER_MASK;
434702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Set the !tx_en since this pin is DISABLE_TX_LASER */
434802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	DP(NETIF_MSG_LINK, "Setting WC TX to %d\n", tx_en);
434902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* For 20G, the expected pin to be used is 3 pins after the current */
435002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
435102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_set_cfg_pin(bp, cfg_pin, tx_en ^ 1);
435202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G)
435302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		bnx2x_set_cfg_pin(bp, cfg_pin + 3, tx_en ^ 1);
435402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
435502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
435602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy,
435702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				      struct link_params *params)
435802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
435902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
436002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u16 val16;
436102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_sfp_e3_set_transmitter(params, phy, 0);
43621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_set_mdio_clk(bp, params->chip_id, params->port);
43631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_set_aer_mmd(params, phy);
43641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Global register */
43651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_warpcore_reset_lane(bp, phy, 1);
436602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
43671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Clear loopback settings (if any) */
436802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* 10G & 20G */
4369cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
437002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
437102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
437202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_COMBO_IEEE0_MIICTRL, val16 &
43731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 0xBFFF);
43741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
437502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
43761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			MDIO_WC_REG_IEEE0BLK_MIICNTL, &val16);
43771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
437802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_WC_REG_IEEE0BLK_MIICNTL, val16 & 0xfffe);
437902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
43801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Update those 1-copy registers */
438102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
438202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  MDIO_AER_BLOCK_AER_REG, 0);
438302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* Enable 1G MDIO (1-copy) */
438402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
438502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
438602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			&val16);
438702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
438802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
43891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 val16 & ~0x10);
439002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
439102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
439202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_WC_REG_XGXSBLK1_LANECTRL2, &val16);
439302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
4394db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby			 MDIO_WC_REG_XGXSBLK1_LANECTRL2,
439502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 val16 & 0xff00);
439602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
4397096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby}
439802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
439902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_set_warpcore_loopback(struct bnx2x_phy *phy,
44001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					struct link_params *params)
440102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
44021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct bnx2x *bp = params->bp;
440302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u16 val16;
4404cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby	u32 lane;
440502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	DP(NETIF_MSG_LINK, "Setting Warpcore loopback type %x, speed %d\n",
440602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		       params->loopback_mode, phy->req_line_speed);
440702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
44081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (phy->req_line_speed < SPEED_10000) {
44091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* 10/100/1000 */
441002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
44111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Update those 1-copy registers */
44121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
441302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				  MDIO_AER_BLOCK_AER_REG, 0);
441402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* Enable 1G MDIO (1-copy) */
44151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
441602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
441702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				&val16);
441802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
441902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
442002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				val16 | 0x10);
442102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* Set 1G loopback based on lane (1-copy) */
442202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		lane = bnx2x_get_warpcore_lane(phy, params);
442302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
44241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				MDIO_WC_REG_XGXSBLK1_LANECTRL2, &val16);
442502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
442602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				MDIO_WC_REG_XGXSBLK1_LANECTRL2,
442702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				val16 | (1<<lane));
4428db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby
442902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* Switch back to 4-copy registers */
443002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		bnx2x_set_aer_mmd(params, phy);
4431096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby		/* Global loopback, not recommended. */
443202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
443302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
44341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
443502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				MDIO_WC_REG_COMBO_IEEE0_MIICTRL, val16 |
44361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				0x4000);
4437cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby	} else {
443802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* 10G & 20G */
443902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
444002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
44411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
444202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				MDIO_WC_REG_COMBO_IEEE0_MIICTRL, val16 |
44431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 0x4000);
44441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
444502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
444602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				MDIO_WC_REG_IEEE0BLK_MIICNTL, &val16);
44471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
444802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				MDIO_WC_REG_IEEE0BLK_MIICNTL, val16 | 0x1);
444902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
44501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
44511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
445202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
44531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid bnx2x_link_status_update(struct link_params *params,
44541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			      struct link_vars *vars)
445502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
445602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
445702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u8 link_10g_plus;
445802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u8 port = params->port;
445902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u32 sync_offset, media_types;
446002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Update PHY configuration */
446102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	set_phy_vars(params, vars);
446202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
446302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	vars->link_status = REG_RD(bp, params->shmem_base +
446402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				   offsetof(struct shmem_region,
446502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					    port_mb[port].link_status));
446602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
446702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP);
44681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vars->phy_flags = PHY_XGXS_FLAG;
44691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (vars->link_status & LINK_STATUS_PHYSICAL_LINK_FLAG)
44701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vars->phy_flags |= PHY_PHYSICAL_LINK_FLAG;
44711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
447202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (vars->link_up) {
44731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DP(NETIF_MSG_LINK, "phy link up\n");
4474cab9bdd14dd7d8091b0aac7877ae9f29724eb741Jiri Slaby
447502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		vars->phy_link_up = 1;
44761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		vars->duplex = DUPLEX_FULL;
447702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		switch (vars->link_status &
44781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			LINK_STATUS_SPEED_AND_DUPLEX_MASK) {
44791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case LINK_10THD:
448002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				vars->duplex = DUPLEX_HALF;
448102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				/* fall thru */
44821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case LINK_10TFD:
448302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				vars->line_speed = SPEED_10;
448402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				break;
448502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
448602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			case LINK_100TXHD:
44871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				vars->duplex = DUPLEX_HALF;
448802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				/* fall thru */
44891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case LINK_100T4:
449002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			case LINK_100TXFD:
449102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				vars->line_speed = SPEED_100;
449202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				break;
449302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
44941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case LINK_1000THD:
44951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				vars->duplex = DUPLEX_HALF;
44961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* fall thru */
44971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case LINK_1000TFD:
44981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				vars->line_speed = SPEED_1000;
44991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
45001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
45011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case LINK_2500THD:
45021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				vars->duplex = DUPLEX_HALF;
45030809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby				/* fall thru */
45040809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			case LINK_2500TFD:
45050809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby				vars->line_speed = SPEED_2500;
45060809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby				break;
45070809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby
45080809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			case LINK_10GTFD:
45090809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby				vars->line_speed = SPEED_10000;
45100809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby				break;
45110809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			case LINK_20GTFD:
45120809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby				vars->line_speed = SPEED_20000;
45130809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby				break;
45140809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			default:
45150809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby				break;
45160809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		}
45170809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		vars->flow_ctrl = 0;
45180809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		if (vars->link_status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED)
45190809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			vars->flow_ctrl |= BNX2X_FLOW_CTRL_TX;
45200809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby
45210809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		if (vars->link_status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED)
45220809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			vars->flow_ctrl |= BNX2X_FLOW_CTRL_RX;
45230809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby
45240809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		if (!vars->flow_ctrl)
45250809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
45260809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby
45270809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		if (vars->line_speed &&
45280809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		    ((vars->line_speed == SPEED_10) ||
45290809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		     (vars->line_speed == SPEED_100))) {
45300809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			vars->phy_flags |= PHY_SGMII_FLAG;
45310809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		} else {
45320809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			vars->phy_flags &= ~PHY_SGMII_FLAG;
45330809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		}
45340809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		if (vars->line_speed &&
45350809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		    USES_WARPCORE(bp) &&
45360809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		    (vars->line_speed == SPEED_1000))
45370809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			vars->phy_flags |= PHY_SGMII_FLAG;
45380809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		/* anything 10 and over uses the bmac */
45390809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		link_10g_plus = (vars->line_speed >= SPEED_10000);
45400809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby
45410809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		if (link_10g_plus) {
45420809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			if (USES_WARPCORE(bp))
45430809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby				vars->mac_type = MAC_TYPE_XMAC;
45440809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			else
45450809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby				vars->mac_type = MAC_TYPE_BMAC;
45460809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		} else {
45470809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			if (USES_WARPCORE(bp))
45480809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby				vars->mac_type = MAC_TYPE_UMAC;
45490809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			else
45500809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby				vars->mac_type = MAC_TYPE_EMAC;
45510809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		}
45520809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	} else { /* link down */
45530809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		DP(NETIF_MSG_LINK, "phy link down\n");
45540809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby
45550809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		vars->phy_link_up = 0;
45560809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby
45570809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		vars->line_speed = 0;
45580809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		vars->duplex = DUPLEX_FULL;
45590809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
45600809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby
45610809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		/* indicate no mac active */
45620809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		vars->mac_type = MAC_TYPE_NONE;
45630809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		if (vars->link_status & LINK_STATUS_PHYSICAL_LINK_FLAG)
45640809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
45650809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	}
45660809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby
45670809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	/* Sync media type */
45680809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	sync_offset = params->shmem_base +
45690809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			offsetof(struct shmem_region,
45700809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby				 dev_info.port_hw_config[port].media_type);
45710809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	media_types = REG_RD(bp, sync_offset);
45720809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby
45730809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	params->phy[INT_PHY].media_type =
45740809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		(media_types & PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK) >>
45750809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		PORT_HW_CFG_MEDIA_TYPE_PHY0_SHIFT;
45760809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	params->phy[EXT_PHY1].media_type =
45770809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		(media_types & PORT_HW_CFG_MEDIA_TYPE_PHY1_MASK) >>
45780809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT;
45790809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	params->phy[EXT_PHY2].media_type =
45800809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		(media_types & PORT_HW_CFG_MEDIA_TYPE_PHY2_MASK) >>
45810809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		PORT_HW_CFG_MEDIA_TYPE_PHY2_SHIFT;
45820809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	DP(NETIF_MSG_LINK, "media_types = 0x%x\n", media_types);
45830809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby
45840809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	/* Sync AEU offset */
45850809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	sync_offset = params->shmem_base +
45860809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			offsetof(struct shmem_region,
45870809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby				 dev_info.port_hw_config[port].aeu_int_mask);
45880809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby
45890809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	vars->aeu_int_mask = REG_RD(bp, sync_offset);
45900809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby
45910809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	/* Sync PFC status */
45920809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	if (vars->link_status & LINK_STATUS_PFC_ENABLED)
45930809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		params->feature_config_flags |=
45940809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby					FEATURE_CONFIG_PFC_ENABLED;
45950809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	else
45960809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		params->feature_config_flags &=
45970809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby					~FEATURE_CONFIG_PFC_ENABLED;
45980809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby
45990809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	DP(NETIF_MSG_LINK, "link_status 0x%x  phy_link_up %x int_mask 0x%x\n",
46000809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		 vars->link_status, vars->phy_link_up, vars->aeu_int_mask);
46010809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	DP(NETIF_MSG_LINK, "line_speed %x  duplex %x  flow_ctrl 0x%x\n",
46020809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		 vars->line_speed, vars->duplex, vars->flow_ctrl);
46030809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby}
46040809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby
46050809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby
46060809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slabystatic void bnx2x_set_master_ln(struct link_params *params,
46070809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby				struct bnx2x_phy *phy)
46080809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby{
46090809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	struct bnx2x *bp = params->bp;
46100809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	u16 new_master_ln, ser_lane;
46110809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	ser_lane = ((params->lane_config &
46120809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		     PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
46130809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		    PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
46140809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby
46150809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	/* set the master_ln for AN */
46160809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	CL22_RD_OVER_CL45(bp, phy,
46170809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			  MDIO_REG_BANK_XGXS_BLOCK2,
46180809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			  MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
46190809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			  &new_master_ln);
46200809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby
46210809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	CL22_WR_OVER_CL45(bp, phy,
46220809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			  MDIO_REG_BANK_XGXS_BLOCK2 ,
46230809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			  MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
46240809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			  (new_master_ln | ser_lane));
46250809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby}
46260809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby
46270809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slabystatic int bnx2x_reset_unicore(struct link_params *params,
46280809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			       struct bnx2x_phy *phy,
46290809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			       u8 set_serdes)
46300809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby{
46310809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	struct bnx2x *bp = params->bp;
46320809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	u16 mii_control;
46330809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	u16 i;
46340809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	CL22_RD_OVER_CL45(bp, phy,
46350809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			  MDIO_REG_BANK_COMBO_IEEE0,
46360809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			  MDIO_COMBO_IEEE0_MII_CONTROL, &mii_control);
46370809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby
46380809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	/* reset the unicore */
46390809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	CL22_WR_OVER_CL45(bp, phy,
46400809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			  MDIO_REG_BANK_COMBO_IEEE0,
46410809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			  MDIO_COMBO_IEEE0_MII_CONTROL,
46420809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			  (mii_control |
46430809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby			   MDIO_COMBO_IEEO_MII_CONTROL_RESET));
46440809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	if (set_serdes)
46450809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		bnx2x_set_serdes_access(bp, params->port);
46460809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby
46470809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	/* wait for the reset to self clear */
46480809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby	for (i = 0; i < MDIO_ACCESS_TIMEOUT; i++) {
46490809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		udelay(5);
46500809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby
46510809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		/* the reset erased the previous bank value */
46520809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby		CL22_RD_OVER_CL45(bp, phy,
46530809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby				  MDIO_REG_BANK_COMBO_IEEE0,
46540809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby				  MDIO_COMBO_IEEE0_MII_CONTROL,
46550809e2671d804f6caa8b3bd5e4de4b52f649cf73Jiri Slaby				  &mii_control);
46561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
46571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!(mii_control & MDIO_COMBO_IEEO_MII_CONTROL_RESET)) {
46581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			udelay(5);
465902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			return 0;
46601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
466102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
466202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
466302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	netdev_err(bp->dev,  "Warning: PHY was not initialized,"
466402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			      " Port %d\n",
466502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 params->port);
466602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	DP(NETIF_MSG_LINK, "BUG! XGXS is still in reset!\n");
466702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	return -EINVAL;
466802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
466902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
467002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
467102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_set_swap_lanes(struct link_params *params,
467202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				 struct bnx2x_phy *phy)
467302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
4674db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	struct bnx2x *bp = params->bp;
467502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/*
467602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 *  Each two bits represents a lane number:
467702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 *  No swap is 0123 => 0x1b no need to enable the swap
467802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 */
467902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u16 ser_lane, rx_lane_swap, tx_lane_swap;
468002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
468102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	ser_lane = ((params->lane_config &
468202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		     PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
468302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
468402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	rx_lane_swap = ((params->lane_config &
468502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 PORT_HW_CFG_LANE_SWAP_CFG_RX_MASK) >>
468602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			PORT_HW_CFG_LANE_SWAP_CFG_RX_SHIFT);
468702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	tx_lane_swap = ((params->lane_config &
468802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 PORT_HW_CFG_LANE_SWAP_CFG_TX_MASK) >>
468902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			PORT_HW_CFG_LANE_SWAP_CFG_TX_SHIFT);
469002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
4691db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	if (rx_lane_swap != 0x1b) {
469202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		CL22_WR_OVER_CL45(bp, phy,
469302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				  MDIO_REG_BANK_XGXS_BLOCK2,
469402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				  MDIO_XGXS_BLOCK2_RX_LN_SWAP,
469502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				  (rx_lane_swap |
469602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				   MDIO_XGXS_BLOCK2_RX_LN_SWAP_ENABLE |
469702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				   MDIO_XGXS_BLOCK2_RX_LN_SWAP_FORCE_ENABLE));
469802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	} else {
469902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		CL22_WR_OVER_CL45(bp, phy,
4700db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby				  MDIO_REG_BANK_XGXS_BLOCK2,
470102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				  MDIO_XGXS_BLOCK2_RX_LN_SWAP, 0);
470202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
470302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
470402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (tx_lane_swap != 0x1b) {
470502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		CL22_WR_OVER_CL45(bp, phy,
470602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				  MDIO_REG_BANK_XGXS_BLOCK2,
470702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				  MDIO_XGXS_BLOCK2_TX_LN_SWAP,
4708db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby				  (tx_lane_swap |
470902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				   MDIO_XGXS_BLOCK2_TX_LN_SWAP_ENABLE));
471002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	} else {
471102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		CL22_WR_OVER_CL45(bp, phy,
471202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				  MDIO_REG_BANK_XGXS_BLOCK2,
471302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				  MDIO_XGXS_BLOCK2_TX_LN_SWAP, 0);
471402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
471502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
471602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
471702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_set_parallel_detection(struct bnx2x_phy *phy,
471802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					 struct link_params *params)
4719db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby{
472002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
472102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u16 control2;
472202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	CL22_RD_OVER_CL45(bp, phy,
472302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  MDIO_REG_BANK_SERDES_DIGITAL,
472402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
472502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  &control2);
472602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
472702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		control2 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN;
47281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
472902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		control2 &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN;
473002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	DP(NETIF_MSG_LINK, "phy->speed_cap_mask = 0x%x, control2 = 0x%x\n",
473102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		phy->speed_cap_mask, control2);
4732db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby	CL22_WR_OVER_CL45(bp, phy,
473302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  MDIO_REG_BANK_SERDES_DIGITAL,
473402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
473502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  control2);
473602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
47371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
47381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	     (phy->speed_cap_mask &
47391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) {
47401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DP(NETIF_MSG_LINK, "XGXS\n");
47411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
47421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		CL22_WR_OVER_CL45(bp, phy,
47431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 MDIO_REG_BANK_10G_PARALLEL_DETECT,
474402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK,
47451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK_CNT);
47461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
474702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		CL22_RD_OVER_CL45(bp, phy,
474802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				  MDIO_REG_BANK_10G_PARALLEL_DETECT,
474902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				  MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
47501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  &control2);
475102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
47521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
47531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		control2 |=
475402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL_PARDET10G_EN;
47551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
47561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		CL22_WR_OVER_CL45(bp, phy,
47571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  MDIO_REG_BANK_10G_PARALLEL_DETECT,
475802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				  MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
475902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				  control2);
476002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
476102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* Disable parallel detection of HiG */
476202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		CL22_WR_OVER_CL45(bp, phy,
476302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				  MDIO_REG_BANK_XGXS_BLOCK2,
476402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				  MDIO_XGXS_BLOCK2_UNICORE_MODE_10G,
47651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_CX4_XGXS |
47661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_HIGIG_XGXS);
47671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
476802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
476902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
477002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_set_autoneg(struct bnx2x_phy *phy,
477102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			      struct link_params *params,
4772096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby			      struct link_vars *vars,
477302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			      u8 enable_cl73)
47741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
477502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
47761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 reg_val;
477702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
477802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* CL37 Autoneg */
477902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	CL22_RD_OVER_CL45(bp, phy,
478002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  MDIO_REG_BANK_COMBO_IEEE0,
478102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);
47821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
47831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* CL37 Autoneg Enabled */
478402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (vars->line_speed == SPEED_AUTO_NEG)
47851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_AN_EN;
47861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else /* CL37 Autoneg Disabled */
478702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
478802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			     MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN);
478902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
479002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	CL22_WR_OVER_CL45(bp, phy,
479102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  MDIO_REG_BANK_COMBO_IEEE0,
479202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);
479302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
479402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Enable/Disable Autodetection */
479502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
479602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	CL22_RD_OVER_CL45(bp, phy,
479702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  MDIO_REG_BANK_SERDES_DIGITAL,
479802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, &reg_val);
479902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	reg_val &= ~(MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_SIGNAL_DETECT_EN |
480002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_INVERT_SIGNAL_DETECT);
480102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	reg_val |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_FIBER_MODE;
4802096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby	if (vars->line_speed == SPEED_AUTO_NEG)
480302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		reg_val |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET;
480402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	else
480502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		reg_val &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET;
480602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
480702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	CL22_WR_OVER_CL45(bp, phy,
480802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  MDIO_REG_BANK_SERDES_DIGITAL,
480902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, reg_val);
481002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
481102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Enable TetonII and BAM autoneg */
481202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	CL22_RD_OVER_CL45(bp, phy,
481302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  MDIO_REG_BANK_BAM_NEXT_PAGE,
481402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
4815096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby			  &reg_val);
481602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (vars->line_speed == SPEED_AUTO_NEG) {
481702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* Enable BAM aneg Mode and TetonII aneg Mode */
481802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		reg_val |= (MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE |
481902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			    MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN);
482002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	} else {
482102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* TetonII and BAM Autoneg Disabled */
482202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		reg_val &= ~(MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE |
482302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			     MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN);
4824096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby	}
482502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	CL22_WR_OVER_CL45(bp, phy,
482602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  MDIO_REG_BANK_BAM_NEXT_PAGE,
482702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
482802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  reg_val);
482902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
483002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (enable_cl73) {
483102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* Enable Cl73 FSM status bits */
483202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		CL22_WR_OVER_CL45(bp, phy,
483302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				  MDIO_REG_BANK_CL73_USERB0,
4834f3851e73ecdd070bc379677ed7aad958446f26e7Jiri Slaby				  MDIO_CL73_USERB0_CL73_UCTRL,
483502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				  0xe);
483602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
483702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* Enable BAM Station Manager*/
483802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		CL22_WR_OVER_CL45(bp, phy,
483902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_REG_BANK_CL73_USERB0,
484002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_CL73_USERB0_CL73_BAM_CTRL1,
484102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_EN |
484202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_STATION_MNGR_EN |
484302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_NP_AFTER_BP_EN);
484402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
484502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* Advertise CL73 link speeds */
4846096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby		CL22_RD_OVER_CL45(bp, phy,
48471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  MDIO_REG_BANK_CL73_IEEEB1,
4848096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby				  MDIO_CL73_IEEEB1_AN_ADV2,
484902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				  &reg_val);
485002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (phy->speed_cap_mask &
48511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
485258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4;
485358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		if (phy->speed_cap_mask &
48541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
485502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX;
4856db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby
485702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		CL22_WR_OVER_CL45(bp, phy,
4858db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby				  MDIO_REG_BANK_CL73_IEEEB1,
485902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				  MDIO_CL73_IEEEB1_AN_ADV2,
486002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				  reg_val);
4861db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby
486202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* CL73 Autoneg Enabled */
4863db05c3b1ddaa06e658548f3d99e31a188b0b3bccJiri Slaby		reg_val = MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN;
48641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
48651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else /* CL73 Autoneg Disabled */
4866d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby		reg_val = 0;
4867d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby
4868d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	CL22_WR_OVER_CL45(bp, phy,
48692b1da41fb3eb41fab1e27cdcce7712b61ef45186Jiri Slaby			  MDIO_REG_BANK_CL73_IEEEB0,
4870d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby			  MDIO_CL73_IEEEB0_CL73_AN_CONTROL, reg_val);
48712b1da41fb3eb41fab1e27cdcce7712b61ef45186Jiri Slaby}
4872d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby
4873d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby/* program SerDes, forced speed */
4874d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slabystatic void bnx2x_program_serdes(struct bnx2x_phy *phy,
48752b1da41fb3eb41fab1e27cdcce7712b61ef45186Jiri Slaby				 struct link_params *params,
48762b1da41fb3eb41fab1e27cdcce7712b61ef45186Jiri Slaby				 struct link_vars *vars)
4877d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby{
4878d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	struct bnx2x *bp = params->bp;
4879d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	u16 reg_val;
4880d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby
4881d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	/* program duplex, disable autoneg and sgmii*/
4882d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	CL22_RD_OVER_CL45(bp, phy,
4883d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby			  MDIO_REG_BANK_COMBO_IEEE0,
4884d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby			  MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);
4885d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX |
4886d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby		     MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
4887d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby		     MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK);
4888d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	if (phy->req_duplex == DUPLEX_FULL)
4889d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby		reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
4890d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	CL22_WR_OVER_CL45(bp, phy,
4891d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby			  MDIO_REG_BANK_COMBO_IEEE0,
4892d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby			  MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);
4893d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby
4894d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	/*
4895d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	 * program speed
4896d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	 *  - needed only if the speed is greater than 1G (2.5G or 10G)
4897d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	 */
4898d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	CL22_RD_OVER_CL45(bp, phy,
4899d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby			  MDIO_REG_BANK_SERDES_DIGITAL,
4900d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby			  MDIO_SERDES_DIGITAL_MISC1, &reg_val);
4901d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	/* clearing the speed value before setting the right speed */
4902d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	DP(NETIF_MSG_LINK, "MDIO_REG_BANK_SERDES_DIGITAL = 0x%x\n", reg_val);
4903d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby
4904d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	reg_val &= ~(MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_MASK |
4905d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby		     MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_SEL);
4906d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby
4907d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	if (!((vars->line_speed == SPEED_1000) ||
4908d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	      (vars->line_speed == SPEED_100) ||
4909d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	      (vars->line_speed == SPEED_10))) {
4910d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby
4911d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby		reg_val |= (MDIO_SERDES_DIGITAL_MISC1_REFCLK_SEL_156_25M |
4912d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby			    MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_SEL);
4913d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby		if (vars->line_speed == SPEED_10000)
4914d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby			reg_val |=
4915d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby				MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_10G_CX4;
4916d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	}
4917d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby
4918d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	CL22_WR_OVER_CL45(bp, phy,
4919d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby			  MDIO_REG_BANK_SERDES_DIGITAL,
4920d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby			  MDIO_SERDES_DIGITAL_MISC1, reg_val);
4921d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby
4922d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby}
4923d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby
4924d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slabystatic void bnx2x_set_brcm_cl37_advertisement(struct bnx2x_phy *phy,
4925d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby					      struct link_params *params)
4926d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby{
4927d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	struct bnx2x *bp = params->bp;
4928d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	u16 val = 0;
4929d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby
4930d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	/* configure the 48 bits for BAM AN */
4931d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby
4932f3851e73ecdd070bc379677ed7aad958446f26e7Jiri Slaby	/* set extended capabilities */
493338d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby	if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)
4934d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby		val |= MDIO_OVER_1G_UP1_2_5G;
4935d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
4936d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby		val |= MDIO_OVER_1G_UP1_10G;
4937d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	CL22_WR_OVER_CL45(bp, phy,
4938d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby			  MDIO_REG_BANK_OVER_1G,
4939d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby			  MDIO_OVER_1G_UP1, val);
4940d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby
4941d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	CL22_WR_OVER_CL45(bp, phy,
4942d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby			  MDIO_REG_BANK_OVER_1G,
4943d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby			  MDIO_OVER_1G_UP3, 0x400);
4944d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby}
4945d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby
4946d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slabystatic void bnx2x_set_ieee_aneg_advertisement(struct bnx2x_phy *phy,
4947d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby					      struct link_params *params,
4948d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby					      u16 ieee_fc)
4949d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby{
4950d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	struct bnx2x *bp = params->bp;
4951d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	u16 val;
4952d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	/* for AN, we are always publishing full duplex */
4953d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby
4954d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby	CL22_WR_OVER_CL45(bp, phy,
4955d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby			  MDIO_REG_BANK_COMBO_IEEE0,
495658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			  MDIO_COMBO_IEEE0_AUTO_NEG_ADV, ieee_fc);
495758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	CL22_RD_OVER_CL45(bp, phy,
49581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			  MDIO_REG_BANK_CL73_IEEEB1,
495902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  MDIO_CL73_IEEEB1_AN_ADV1, &val);
496058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	val &= ~MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_BOTH;
496158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	val |= ((ieee_fc<<3) & MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK);
496202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	CL22_WR_OVER_CL45(bp, phy,
496358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			  MDIO_REG_BANK_CL73_IEEEB1,
496458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			  MDIO_CL73_IEEEB1_AN_ADV1, val);
4965d407c78188c718c00e997ce7f8b8d45e92ee2dd6Jiri Slaby}
496602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
496758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slabystatic void bnx2x_restart_autoneg(struct bnx2x_phy *phy,
496858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				  struct link_params *params,
496958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				  u8 enable_cl73)
497058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby{
497158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	struct bnx2x *bp = params->bp;
49721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 mii_control;
497358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby
497458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	DP(NETIF_MSG_LINK, "bnx2x_restart_autoneg\n");
497558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	/* Enable and restart BAM/CL37 aneg */
497658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby
497758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	if (enable_cl73) {
49781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		CL22_RD_OVER_CL45(bp, phy,
497958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				  MDIO_REG_BANK_CL73_IEEEB0,
49801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
498158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				  &mii_control);
498258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby
498358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		CL22_WR_OVER_CL45(bp, phy,
498458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				  MDIO_REG_BANK_CL73_IEEEB0,
498558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				  MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
498658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				  (mii_control |
498758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				  MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN |
498858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				  MDIO_CL73_IEEEB0_CL73_AN_CONTROL_RESTART_AN));
498958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	} else {
499058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby
499158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		CL22_RD_OVER_CL45(bp, phy,
49921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  MDIO_REG_BANK_COMBO_IEEE0,
499358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				  MDIO_COMBO_IEEE0_MII_CONTROL,
499458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				  &mii_control);
499558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		DP(NETIF_MSG_LINK,
499658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			 "bnx2x_restart_autoneg mii_control before = 0x%x\n",
499758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			 mii_control);
49981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		CL22_WR_OVER_CL45(bp, phy,
499958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				  MDIO_REG_BANK_COMBO_IEEE0,
500058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				  MDIO_COMBO_IEEE0_MII_CONTROL,
500158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				  (mii_control |
500258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				   MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
500358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				   MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN));
500458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	}
500558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby}
500658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby
500758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slabystatic void bnx2x_initialize_sgmii_process(struct bnx2x_phy *phy,
500858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby					   struct link_params *params,
500958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby					   struct link_vars *vars)
501002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
501102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
501202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u16 control1;
501302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
501402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* in SGMII mode, the unicore is always slave */
501502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
501658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	CL22_RD_OVER_CL45(bp, phy,
501758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			  MDIO_REG_BANK_SERDES_DIGITAL,
501858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			  MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
501958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			  &control1);
502058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	control1 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_INVERT_SIGNAL_DETECT;
502158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	/* set sgmii mode (and not fiber) */
50221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	control1 &= ~(MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_FIBER_MODE |
502358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		      MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET |
502458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		      MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_MSTR_MODE);
50251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	CL22_WR_OVER_CL45(bp, phy,
50261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			  MDIO_REG_BANK_SERDES_DIGITAL,
502758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			  MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
502858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			  control1);
502958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby
50301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* if forced speed */
503158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	if (!(vars->line_speed == SPEED_AUTO_NEG)) {
503258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		/* set speed, disable autoneg */
503358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		u16 mii_control;
503458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby
503558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		CL22_RD_OVER_CL45(bp, phy,
503658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				  MDIO_REG_BANK_COMBO_IEEE0,
503758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				  MDIO_COMBO_IEEE0_MII_CONTROL,
503858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				  &mii_control);
503958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		mii_control &= ~(MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
504058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				 MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK|
504158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				 MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX);
504258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby
504358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		switch (vars->line_speed) {
504458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		case SPEED_100:
504558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			mii_control |=
504658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_100;
504758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			break;
504858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		case SPEED_1000:
504958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			mii_control |=
505002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_1000;
505158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			break;
505258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		case SPEED_10:
505358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			/* there is nothing to set for 10M */
505458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			break;
505558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		default:
505658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			/* invalid speed for SGMII */
505758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n",
505858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				  vars->line_speed);
505958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			break;
506002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		}
506158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby
506258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		/* setting the full duplex */
506358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		if (phy->req_duplex == DUPLEX_FULL)
506458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			mii_control |=
506558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
506658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		CL22_WR_OVER_CL45(bp, phy,
506758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				  MDIO_REG_BANK_COMBO_IEEE0,
506858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				  MDIO_COMBO_IEEE0_MII_CONTROL,
506958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				  mii_control);
507058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby
507102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	} else { /* AN mode */
507258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		/* enable and restart AN */
507358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		bnx2x_restart_autoneg(phy, params, 0);
507458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	}
507558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby}
507658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby
507758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby
507858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby/*
507958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby * link management
508058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby */
508158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby
5082f3851e73ecdd070bc379677ed7aad958446f26e7Jiri Slabystatic int bnx2x_direct_parallel_detect_used(struct bnx2x_phy *phy,
508358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby					     struct link_params *params)
508402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
508558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	struct bnx2x *bp = params->bp;
508658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	u16 pd_10g, status2_1000x;
508758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	if (phy->req_line_speed != SPEED_AUTO_NEG)
508858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		return 0;
508958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	CL22_RD_OVER_CL45(bp, phy,
509058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			  MDIO_REG_BANK_SERDES_DIGITAL,
509102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  MDIO_SERDES_DIGITAL_A_1000X_STATUS2,
509202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  &status2_1000x);
509358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	CL22_RD_OVER_CL45(bp, phy,
509458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			  MDIO_REG_BANK_SERDES_DIGITAL,
509558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			  MDIO_SERDES_DIGITAL_A_1000X_STATUS2,
509602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  &status2_1000x);
509702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (status2_1000x & MDIO_SERDES_DIGITAL_A_1000X_STATUS2_AN_DISABLED) {
509858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		DP(NETIF_MSG_LINK, "1G parallel detect link on port %d\n",
509958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			 params->port);
510058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		return 1;
510158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	}
510258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby
510302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	CL22_RD_OVER_CL45(bp, phy,
510458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			  MDIO_REG_BANK_10G_PARALLEL_DETECT,
510502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS,
510658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			  &pd_10g);
510758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby
510858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	if (pd_10g & MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS_PD_LINK) {
510958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		DP(NETIF_MSG_LINK, "10G parallel detect link on port %d\n",
511002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			 params->port);
511158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		return 1;
511258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	}
511358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	return 0;
511458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby}
511558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby
511658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slabystatic void bnx2x_flow_ctrl_resolve(struct bnx2x_phy *phy,
511758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				    struct link_params *params,
51181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    struct link_vars *vars,
511958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				    u32 gp_status)
512058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby{
512158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	struct bnx2x *bp = params->bp;
512258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	u16 ld_pause;   /* local driver */
512358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	u16 lp_pause;   /* link partner */
512458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	u16 pause_result;
512558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby
512658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
512758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby
512858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	/* resolve from gp_status in case of AN complete and not sgmii */
512958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO)
513058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		vars->flow_ctrl = phy->req_flow_ctrl;
513158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	else if (phy->req_line_speed != SPEED_AUTO_NEG)
513258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		vars->flow_ctrl = params->req_fc_auto_adv;
513358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	else if ((gp_status & MDIO_AN_CL73_OR_37_COMPLETE) &&
513458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		 (!(vars->phy_flags & PHY_SGMII_FLAG))) {
513558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		if (bnx2x_direct_parallel_detect_used(phy, params)) {
513658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			vars->flow_ctrl = params->req_fc_auto_adv;
513758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			return;
513858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		}
513958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		if ((gp_status &
514058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		    (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE |
514158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		     MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) ==
514258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		    (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE |
514358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		     MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) {
514458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby
514558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			CL22_RD_OVER_CL45(bp, phy,
514658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby					  MDIO_REG_BANK_CL73_IEEEB1,
514758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby					  MDIO_CL73_IEEEB1_AN_ADV1,
514858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby					  &ld_pause);
514958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			CL22_RD_OVER_CL45(bp, phy,
515058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby					  MDIO_REG_BANK_CL73_IEEEB1,
515158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby					  MDIO_CL73_IEEEB1_AN_LP_ADV1,
515258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby					  &lp_pause);
515358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			pause_result = (ld_pause &
515458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby					MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK)
515558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby					>> 8;
515602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			pause_result |= (lp_pause &
515758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby					MDIO_CL73_IEEEB1_AN_LP_ADV1_PAUSE_MASK)
515858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby					>> 10;
515958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			DP(NETIF_MSG_LINK, "pause_result CL73 0x%x\n",
516058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				 pause_result);
516158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		} else {
516258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			CL22_RD_OVER_CL45(bp, phy,
516358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby					  MDIO_REG_BANK_COMBO_IEEE0,
516458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby					  MDIO_COMBO_IEEE0_AUTO_NEG_ADV,
516558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby					  &ld_pause);
516658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			CL22_RD_OVER_CL45(bp, phy,
516758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				MDIO_REG_BANK_COMBO_IEEE0,
516858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1,
516958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				&lp_pause);
517058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			pause_result = (ld_pause &
517158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>5;
517258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			pause_result |= (lp_pause &
517358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>7;
517458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			DP(NETIF_MSG_LINK, "pause_result CL37 0x%x\n",
517558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				 pause_result);
517658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		}
517758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		bnx2x_pause_resolve(vars, pause_result);
517858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	}
517958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	DP(NETIF_MSG_LINK, "flow_ctrl 0x%x\n", vars->flow_ctrl);
518058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby}
518158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby
518258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slabystatic void bnx2x_check_fallback_to_cl37(struct bnx2x_phy *phy,
51831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					 struct link_params *params)
51841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
518558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	struct bnx2x *bp = params->bp;
518658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	u16 rx_status, ustat_val, cl37_fsm_received;
518758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	DP(NETIF_MSG_LINK, "bnx2x_check_fallback_to_cl37\n");
518858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	/* Step 1: Make sure signal is detected */
518958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	CL22_RD_OVER_CL45(bp, phy,
519058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			  MDIO_REG_BANK_RX0,
519158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			  MDIO_RX0_RX_STATUS,
519258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			  &rx_status);
519358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	if ((rx_status & MDIO_RX0_RX_STATUS_SIGDET) !=
519458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	    (MDIO_RX0_RX_STATUS_SIGDET)) {
519558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		DP(NETIF_MSG_LINK, "Signal is not detected. Restoring CL73."
519658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			     "rx_status(0x80b0) = 0x%x\n", rx_status);
519758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		CL22_WR_OVER_CL45(bp, phy,
519858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				  MDIO_REG_BANK_CL73_IEEEB0,
519958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				  MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
520058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				  MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN);
520158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		return;
520258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	}
520358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	/* Step 2: Check CL73 state machine */
520458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	CL22_RD_OVER_CL45(bp, phy,
520558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			  MDIO_REG_BANK_CL73_USERB0,
520658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			  MDIO_CL73_USERB0_CL73_USTAT1,
52071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			  &ustat_val);
520858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	if ((ustat_val &
520958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	     (MDIO_CL73_USERB0_CL73_USTAT1_LINK_STATUS_CHECK |
521058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	      MDIO_CL73_USERB0_CL73_USTAT1_AN_GOOD_CHECK_BAM37)) !=
521158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	    (MDIO_CL73_USERB0_CL73_USTAT1_LINK_STATUS_CHECK |
521258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	      MDIO_CL73_USERB0_CL73_USTAT1_AN_GOOD_CHECK_BAM37)) {
521358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		DP(NETIF_MSG_LINK, "CL73 state-machine is not stable. "
521458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			     "ustat_val(0x8371) = 0x%x\n", ustat_val);
521558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		return;
521658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	}
521758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	/*
521858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	 * Step 3: Check CL37 Message Pages received to indicate LP
521958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	 * supports only CL37
522058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	 */
522158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	CL22_RD_OVER_CL45(bp, phy,
522258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			  MDIO_REG_BANK_REMOTE_PHY,
522358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			  MDIO_REMOTE_PHY_MISC_RX_STATUS,
522458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			  &cl37_fsm_received);
522558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	if ((cl37_fsm_received &
522658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	     (MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_OVER1G_MSG |
52271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	     MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_BRCM_OUI_MSG)) !=
522858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	    (MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_OVER1G_MSG |
522958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	      MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_BRCM_OUI_MSG)) {
523058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		DP(NETIF_MSG_LINK, "No CL37 FSM were received. "
523158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			     "misc_rx_status(0x8330) = 0x%x\n",
523258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			 cl37_fsm_received);
523358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		return;
523458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	}
523558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	/*
523658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	 * The combined cl37/cl73 fsm state information indicating that
523758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	 * we are connected to a device which does not support cl73, but
523858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	 * does support cl37 BAM. In this case we disable cl73 and
523958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	 * restart cl37 auto-neg
524002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	 */
524158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby
524258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	/* Disable CL73 */
524358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	CL22_WR_OVER_CL45(bp, phy,
524458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			  MDIO_REG_BANK_CL73_IEEEB0,
524558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			  MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
524658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			  0);
524758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	/* Restart CL37 autoneg */
524858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	bnx2x_restart_autoneg(phy, params, 0);
524958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	DP(NETIF_MSG_LINK, "Disabling CL73, and restarting CL37 autoneg\n");
525058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby}
525158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby
525202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_xgxs_an_resolve(struct bnx2x_phy *phy,
525358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				  struct link_params *params,
525402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				  struct link_vars *vars,
525502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				  u32 gp_status)
525658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby{
525758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE)
525858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		vars->link_status |=
525958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
526058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby
526158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	if (bnx2x_direct_parallel_detect_used(phy, params))
526258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		vars->link_status |=
526358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			LINK_STATUS_PARALLEL_DETECTION_USED;
526458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby}
526558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slabystatic int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy,
5266f3851e73ecdd070bc379677ed7aad958446f26e7Jiri Slaby				     struct link_params *params,
526758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				      struct link_vars *vars,
526858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				      u16 is_link_up,
526958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				      u16 speed_mask,
52701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				      u16 is_duplex)
527158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby{
527258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	struct bnx2x *bp = params->bp;
527358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	if (phy->req_line_speed == SPEED_AUTO_NEG)
527458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_ENABLED;
527558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby	if (is_link_up) {
527658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		DP(NETIF_MSG_LINK, "phy link up\n");
527758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby
527802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		vars->phy_link_up = 1;
527958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		vars->link_status |= LINK_STATUS_LINK_UP;
528058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby
528158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		switch (speed_mask) {
528258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		case GP_STATUS_10M:
528358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			vars->line_speed = SPEED_10;
528458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			if (vars->duplex == DUPLEX_FULL)
528558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				vars->link_status |= LINK_10TFD;
528658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			else
528758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				vars->link_status |= LINK_10THD;
528858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			break;
528958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby
529058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		case GP_STATUS_100M:
529158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			vars->line_speed = SPEED_100;
529258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			if (vars->duplex == DUPLEX_FULL)
529358936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				vars->link_status |= LINK_100TXFD;
529458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			else
529558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				vars->link_status |= LINK_100TXHD;
529658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			break;
529758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby
529858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		case GP_STATUS_1G:
529958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		case GP_STATUS_1G_KX:
530058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			vars->line_speed = SPEED_1000;
530158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			if (vars->duplex == DUPLEX_FULL)
530258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				vars->link_status |= LINK_1000TFD;
530302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			else
530458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				vars->link_status |= LINK_1000THD;
530558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			break;
530658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby
530758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		case GP_STATUS_2_5G:
530858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			vars->line_speed = SPEED_2500;
530958936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			if (vars->duplex == DUPLEX_FULL)
531058936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				vars->link_status |= LINK_2500TFD;
531158936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			else
531258936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				vars->link_status |= LINK_2500THD;
53131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
531458936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby
531558936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		case GP_STATUS_5G:
531658936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby		case GP_STATUS_6G:
531758936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby			DP(NETIF_MSG_LINK,
531858936d8d944e27b75c99b1c59cfeea3f253b03cbJiri Slaby				 "link speed unsupported  gp_status 0x%x\n",
531902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				  speed_mask);
53201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EINVAL;
5321096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby
53221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case GP_STATUS_10G_KX4:
5323096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby		case GP_STATUS_10G_HIG:
532402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		case GP_STATUS_10G_CX4:
532502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		case GP_STATUS_10G_KR:
53261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case GP_STATUS_10G_SFI:
532738d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby		case GP_STATUS_10G_XFI:
532838d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby			vars->line_speed = SPEED_10000;
532938d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby			vars->link_status |= LINK_10GTFD;
533038d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby			break;
5331f3851e73ecdd070bc379677ed7aad958446f26e7Jiri Slaby		case GP_STATUS_20G_DXGXS:
533238d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby			vars->line_speed = SPEED_20000;
533338d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby			vars->link_status |= LINK_20GTFD;
533438d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby			break;
533538d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby		default:
533638d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby			DP(NETIF_MSG_LINK,
533738d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby				  "link speed unsupported gp_status 0x%x\n",
533838d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby				  speed_mask);
533938d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby			return -EINVAL;
534038d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby		}
534138d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby	} else { /* link_down */
534238d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby		DP(NETIF_MSG_LINK, "phy link down\n");
534338d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby
534438d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby		vars->phy_link_up = 0;
5345f3851e73ecdd070bc379677ed7aad958446f26e7Jiri Slaby
5346f3851e73ecdd070bc379677ed7aad958446f26e7Jiri Slaby		vars->duplex = DUPLEX_FULL;
5347f3851e73ecdd070bc379677ed7aad958446f26e7Jiri Slaby		vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
5348f3851e73ecdd070bc379677ed7aad958446f26e7Jiri Slaby		vars->mac_type = MAC_TYPE_NONE;
534938d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby	}
535038d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby	DP(NETIF_MSG_LINK, " phy_link_up %x line_speed %d\n",
535138d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby		    vars->phy_link_up, vars->line_speed);
53521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
53531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
53541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
53551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bnx2x_link_settings_status(struct bnx2x_phy *phy,
535602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				      struct link_params *params,
53571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				      struct link_vars *vars)
5358096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby{
535902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
536002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
536102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
536202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u16 gp_status, duplex = DUPLEX_HALF, link_up = 0, speed_mask;
53631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rc = 0;
536402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
53651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Read gp_status */
536602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	CL22_RD_OVER_CL45(bp, phy,
536702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  MDIO_REG_BANK_GP_STATUS,
536802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  MDIO_GP_STATUS_TOP_AN_STATUS1,
536902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			  &gp_status);
537002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_DUPLEX_STATUS)
537102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		duplex = DUPLEX_FULL;
537202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS)
537302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		link_up = 1;
537402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	speed_mask = gp_status & GP_STATUS_SPEED_MASK;
537502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	DP(NETIF_MSG_LINK, "gp_status 0x%x, is_link_up %d, speed_mask 0x%x\n",
537602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		       gp_status, link_up, speed_mask);
537702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	rc = bnx2x_get_link_speed_duplex(phy, params, vars, link_up, speed_mask,
53781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					 duplex);
53791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rc == -EINVAL)
538002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		return rc;
538102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
538202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {
538302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (SINGLE_MEDIA_DIRECT(params)) {
538402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			bnx2x_flow_ctrl_resolve(phy, params, vars, gp_status);
538502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			if (phy->req_line_speed == SPEED_AUTO_NEG)
538602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				bnx2x_xgxs_an_resolve(phy, params, vars,
5387096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby						      gp_status);
538802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		}
5389096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby	} else { /* link_down */
539002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if ((phy->req_line_speed == SPEED_AUTO_NEG) &&
5391096dcfce39f952292b019a2c42c241782c9ca226Jiri Slaby		    SINGLE_MEDIA_DIRECT(params)) {
539202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			/* Check signal is detected */
539302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			bnx2x_check_fallback_to_cl37(phy, params);
539402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		}
539502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
539602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
539702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	DP(NETIF_MSG_LINK, "duplex %x  flow_ctrl 0x%x link_status 0x%x\n",
539802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		   vars->duplex, vars->flow_ctrl, vars->link_status);
539902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	return rc;
540002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
540102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
540202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic int bnx2x_warpcore_read_status(struct bnx2x_phy *phy,
540302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				     struct link_params *params,
540402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				     struct link_vars *vars)
540502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
540602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
54071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct bnx2x *bp = params->bp;
540802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
54091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 lane;
541002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u16 gp_status1, gp_speed, link_up, duplex = DUPLEX_FULL;
541102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	int rc = 0;
541202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	lane = bnx2x_get_warpcore_lane(phy, params);
541302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* Read gp_status */
541402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (phy->req_line_speed > SPEED_10000) {
541502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		u16 temp_link_up;
541602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
54171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				1, &temp_link_up);
54181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
54191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				1, &link_up);
54201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DP(NETIF_MSG_LINK, "PCS RX link status = 0x%x-->0x%x\n",
54211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       temp_link_up, link_up);
54221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		link_up &= (1<<2);
54231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (link_up)
54241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			bnx2x_ext_phy_resolve_fc(phy, params, vars);
54251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
54261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
54271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				MDIO_WC_REG_GP2_STATUS_GP_2_1, &gp_status1);
54281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DP(NETIF_MSG_LINK, "0x81d1 = 0x%x\n", gp_status1);
54291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Check for either KR or generic link up. */
54301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		gp_status1 = ((gp_status1 >> 8) & 0xf) |
54311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			((gp_status1 >> 12) & 0xf);
54321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		link_up = gp_status1 & (1 << lane);
54331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (link_up && SINGLE_MEDIA_DIRECT(params)) {
54341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			u16 pd, gp_status4;
54351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (phy->req_line_speed == SPEED_AUTO_NEG) {
54361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* Check Autoneg complete */
5437b68e31d0ebbcc909d1941f9f230c9d062a3a13d3Jeff Dike				bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
543802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby						MDIO_WC_REG_GP2_STATUS_GP_2_4,
543902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby						&gp_status4);
544002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				if (gp_status4 & ((1<<12)<<lane))
544102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					vars->link_status |=
544202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
544302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
544402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				/* Check parallel detect used */
544502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
544602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby						MDIO_WC_REG_PAR_DET_10G_STATUS,
544702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby						&pd);
544802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				if (pd & (1<<15))
544902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					vars->link_status |=
545002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					LINK_STATUS_PARALLEL_DETECTION_USED;
545102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			}
545202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			bnx2x_ext_phy_resolve_fc(phy, params, vars);
545302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		}
545402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
545502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
545602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (lane < 2) {
545702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
54581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				MDIO_WC_REG_GP2_STATUS_GP_2_2, &gp_speed);
54591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
546002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
54611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				MDIO_WC_REG_GP2_STATUS_GP_2_3, &gp_speed);
546214a55a6789d8409e58329310f9a18fc141deb4c2Jiri Slaby	}
54639dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby	DP(NETIF_MSG_LINK, "lane %d gp_speed 0x%x\n", lane, gp_speed);
546402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
546502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if ((lane & 1) == 0)
546602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		gp_speed <<= 8;
54679dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby	gp_speed &= 0x3f00;
546802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
546902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
547002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	rc = bnx2x_get_link_speed_duplex(phy, params, vars, link_up, gp_speed,
547102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					 duplex);
547202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
547302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	DP(NETIF_MSG_LINK, "duplex %x  flow_ctrl 0x%x link_status 0x%x\n",
547402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		   vars->duplex, vars->flow_ctrl, vars->link_status);
547502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	return rc;
547602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
547702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slabystatic void bnx2x_set_gmii_tx_driver(struct link_params *params)
547802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby{
547902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x *bp = params->bp;
548002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	struct bnx2x_phy *phy = &params->phy[INT_PHY];
548102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u16 lp_up2;
548202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u16 tx_driver;
548302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	u16 bank;
548402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
54859dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby	/* read precomp */
54869dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby	CL22_RD_OVER_CL45(bp, phy,
54879dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby			  MDIO_REG_BANK_OVER_1G,
54889dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby			  MDIO_OVER_1G_LP_UP2, &lp_up2);
54899dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby
549002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	/* bits [10:7] at lp_up2, positioned at [15:12] */
549102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	lp_up2 = (((lp_up2 & MDIO_OVER_1G_LP_UP2_PREEMPHASIS_MASK) >>
549202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		   MDIO_OVER_1G_LP_UP2_PREEMPHASIS_SHIFT) <<
549302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		  MDIO_TX0_TX_DRIVER_PREEMPHASIS_SHIFT);
549402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
549502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	if (lp_up2 == 0)
5496f3851e73ecdd070bc379677ed7aad958446f26e7Jiri Slaby		return;
5497f3851e73ecdd070bc379677ed7aad958446f26e7Jiri Slaby
5498f3851e73ecdd070bc379677ed7aad958446f26e7Jiri Slaby	for (bank = MDIO_REG_BANK_TX0; bank <= MDIO_REG_BANK_TX3;
5499f3851e73ecdd070bc379677ed7aad958446f26e7Jiri Slaby	      bank += (MDIO_REG_BANK_TX1 - MDIO_REG_BANK_TX0)) {
5500f3851e73ecdd070bc379677ed7aad958446f26e7Jiri Slaby		CL22_RD_OVER_CL45(bp, phy,
5501f3851e73ecdd070bc379677ed7aad958446f26e7Jiri Slaby				  bank,
550202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby				  MDIO_TX0_TX_DRIVER, &tx_driver);
550302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
550402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		/* replace tx_driver bits [15:12] */
550502f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		if (lp_up2 !=
550602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		    (tx_driver & MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK)) {
550702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			tx_driver &= ~MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK;
550802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			tx_driver |= lp_up2;
550902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			CL22_WR_OVER_CL45(bp, phy,
551014a55a6789d8409e58329310f9a18fc141deb4c2Jiri Slaby					  bank,
551102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby					  MDIO_TX0_TX_DRIVER, tx_driver);
551202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		}
551314a55a6789d8409e58329310f9a18fc141deb4c2Jiri Slaby	}
551402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby}
55159dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby
55169dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slabystatic int bnx2x_emac_program(struct link_params *params,
55179dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby			      struct link_vars *vars)
55189dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby{
55199dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby	struct bnx2x *bp = params->bp;
55209dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby	u8 port = params->port;
55219dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby	u16 mode = 0;
55229dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby
55239dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby	DP(NETIF_MSG_LINK, "setting link speed & duplex\n");
55249dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby	bnx2x_bits_dis(bp, GRCBASE_EMAC0 + port*0x400 +
55259dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby		       EMAC_REG_EMAC_MODE,
55269dacf3b2f0cc657a5621e7f6d67ed27ce598f405Jiri Slaby		       (EMAC_MODE_25G_MODE |
552702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			EMAC_MODE_PORT_MII_10M |
55281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			EMAC_MODE_HALF_DUPLEX));
552902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	switch (vars->line_speed) {
55301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SPEED_10:
553102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		mode |= EMAC_MODE_PORT_MII_10M;
55321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
55331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5534b70509066cba24067757f1422c899c43e433429dJiri Slaby	case SPEED_100:
55351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mode |= EMAC_MODE_PORT_MII;
55361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
553702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
553802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	case SPEED_1000:
553902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		mode |= EMAC_MODE_PORT_GMII;
55401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
554102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
55421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case SPEED_2500:
554302f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		mode |= (EMAC_MODE_25G_MODE | EMAC_MODE_PORT_GMII);
554402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		break;
554538d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby
554638d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby	default:
554738d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby		/* 10G not valid for EMAC */
554838d090932564140454e5a0bc915beca07d8a65a0Jiri Slaby		DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n",
554902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby			   vars->line_speed);
555002f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		return -EINVAL;
555102f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	}
555202f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
55531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (vars->duplex == DUPLEX_HALF)
555402f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		mode |= EMAC_MODE_HALF_DUPLEX;
55551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bnx2x_bits_en(bp,
555602f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		      GRCBASE_EMAC0 + port*0x400 + EMAC_REG_EMAC_MODE,
555702f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby		      mode);
555802f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby
555902f1175c8737802b5609aa2c0b1fb3ca2c23069fJiri Slaby	bnx2x_set_led(params, vars, LED_MODE_OPER, vars->line_speed);
55601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
55611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
55621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
55631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void bnx2x_set_preemphasis(struct bnx2x_phy *phy,
55641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  struct link_params *params)
55651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5566
5567	u16 bank, i = 0;
5568	struct bnx2x *bp = params->bp;
5569
5570	for (bank = MDIO_REG_BANK_RX0, i = 0; bank <= MDIO_REG_BANK_RX3;
5571	      bank += (MDIO_REG_BANK_RX1-MDIO_REG_BANK_RX0), i++) {
5572			CL22_WR_OVER_CL45(bp, phy,
5573					  bank,
5574					  MDIO_RX0_RX_EQ_BOOST,
5575					  phy->rx_preemphasis[i]);
5576	}
5577
5578	for (bank = MDIO_REG_BANK_TX0, i = 0; bank <= MDIO_REG_BANK_TX3;
5579		      bank += (MDIO_REG_BANK_TX1 - MDIO_REG_BANK_TX0), i++) {
5580			CL22_WR_OVER_CL45(bp, phy,
5581					  bank,
5582					  MDIO_TX0_TX_DRIVER,
5583					  phy->tx_preemphasis[i]);
5584	}
5585}
5586
5587static void bnx2x_xgxs_config_init(struct bnx2x_phy *phy,
5588				   struct link_params *params,
5589				   struct link_vars *vars)
5590{
5591	struct bnx2x *bp = params->bp;
5592	u8 enable_cl73 = (SINGLE_MEDIA_DIRECT(params) ||
5593			  (params->loopback_mode == LOOPBACK_XGXS));
5594	if (!(vars->phy_flags & PHY_SGMII_FLAG)) {
5595		if (SINGLE_MEDIA_DIRECT(params) &&
5596		    (params->feature_config_flags &
5597		     FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED))
5598			bnx2x_set_preemphasis(phy, params);
5599
5600		/* forced speed requested? */
5601		if (vars->line_speed != SPEED_AUTO_NEG ||
5602		    (SINGLE_MEDIA_DIRECT(params) &&
5603		     params->loopback_mode == LOOPBACK_EXT)) {
5604			DP(NETIF_MSG_LINK, "not SGMII, no AN\n");
5605
5606			/* disable autoneg */
5607			bnx2x_set_autoneg(phy, params, vars, 0);
5608
5609			/* program speed and duplex */
5610			bnx2x_program_serdes(phy, params, vars);
5611
5612		} else { /* AN_mode */
5613			DP(NETIF_MSG_LINK, "not SGMII, AN\n");
5614
5615			/* AN enabled */
5616			bnx2x_set_brcm_cl37_advertisement(phy, params);
5617
5618			/* program duplex & pause advertisement (for aneg) */
5619			bnx2x_set_ieee_aneg_advertisement(phy, params,
5620							  vars->ieee_fc);
5621
5622			/* enable autoneg */
5623			bnx2x_set_autoneg(phy, params, vars, enable_cl73);
5624
5625			/* enable and restart AN */
5626			bnx2x_restart_autoneg(phy, params, enable_cl73);
5627		}
5628
5629	} else { /* SGMII mode */
5630		DP(NETIF_MSG_LINK, "SGMII\n");
5631
5632		bnx2x_initialize_sgmii_process(phy, params, vars);
5633	}
5634}
5635
5636static int bnx2x_prepare_xgxs(struct bnx2x_phy *phy,
5637			  struct link_params *params,
5638			  struct link_vars *vars)
5639{
5640	int rc;
5641	vars->phy_flags |= PHY_XGXS_FLAG;
5642	if ((phy->req_line_speed &&
5643	     ((phy->req_line_speed == SPEED_100) ||
5644	      (phy->req_line_speed == SPEED_10))) ||
5645	    (!phy->req_line_speed &&
5646	     (phy->speed_cap_mask >=
5647	      PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) &&
5648	     (phy->speed_cap_mask <
5649	      PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
5650	    (phy->type == PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT_SD))
5651		vars->phy_flags |= PHY_SGMII_FLAG;
5652	else
5653		vars->phy_flags &= ~PHY_SGMII_FLAG;
5654
5655	bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
5656	bnx2x_set_aer_mmd(params, phy);
5657	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)
5658		bnx2x_set_master_ln(params, phy);
5659
5660	rc = bnx2x_reset_unicore(params, phy, 0);
5661	/* reset the SerDes and wait for reset bit return low */
5662	if (rc != 0)
5663		return rc;
5664
5665	bnx2x_set_aer_mmd(params, phy);
5666	/* setting the masterLn_def again after the reset */
5667	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) {
5668		bnx2x_set_master_ln(params, phy);
5669		bnx2x_set_swap_lanes(params, phy);
5670	}
5671
5672	return rc;
5673}
5674
5675static u16 bnx2x_wait_reset_complete(struct bnx2x *bp,
5676				     struct bnx2x_phy *phy,
5677				     struct link_params *params)
5678{
5679	u16 cnt, ctrl;
5680	/* Wait for soft reset to get cleared up to 1 sec */
5681	for (cnt = 0; cnt < 1000; cnt++) {
5682		if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE)
5683			bnx2x_cl22_read(bp, phy,
5684				MDIO_PMA_REG_CTRL, &ctrl);
5685		else
5686			bnx2x_cl45_read(bp, phy,
5687				MDIO_PMA_DEVAD,
5688				MDIO_PMA_REG_CTRL, &ctrl);
5689		if (!(ctrl & (1<<15)))
5690			break;
5691		msleep(1);
5692	}
5693
5694	if (cnt == 1000)
5695		netdev_err(bp->dev,  "Warning: PHY was not initialized,"
5696				      " Port %d\n",
5697			 params->port);
5698	DP(NETIF_MSG_LINK, "control reg 0x%x (after %d ms)\n", ctrl, cnt);
5699	return cnt;
5700}
5701
5702static void bnx2x_link_int_enable(struct link_params *params)
5703{
5704	u8 port = params->port;
5705	u32 mask;
5706	struct bnx2x *bp = params->bp;
5707
5708	/* Setting the status to report on link up for either XGXS or SerDes */
5709	if (CHIP_IS_E3(bp)) {
5710		mask = NIG_MASK_XGXS0_LINK_STATUS;
5711		if (!(SINGLE_MEDIA_DIRECT(params)))
5712			mask |= NIG_MASK_MI_INT;
5713	} else if (params->switch_cfg == SWITCH_CFG_10G) {
5714		mask = (NIG_MASK_XGXS0_LINK10G |
5715			NIG_MASK_XGXS0_LINK_STATUS);
5716		DP(NETIF_MSG_LINK, "enabled XGXS interrupt\n");
5717		if (!(SINGLE_MEDIA_DIRECT(params)) &&
5718			params->phy[INT_PHY].type !=
5719				PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) {
5720			mask |= NIG_MASK_MI_INT;
5721			DP(NETIF_MSG_LINK, "enabled external phy int\n");
5722		}
5723
5724	} else { /* SerDes */
5725		mask = NIG_MASK_SERDES0_LINK_STATUS;
5726		DP(NETIF_MSG_LINK, "enabled SerDes interrupt\n");
5727		if (!(SINGLE_MEDIA_DIRECT(params)) &&
5728			params->phy[INT_PHY].type !=
5729				PORT_HW_CFG_SERDES_EXT_PHY_TYPE_NOT_CONN) {
5730			mask |= NIG_MASK_MI_INT;
5731			DP(NETIF_MSG_LINK, "enabled external phy int\n");
5732		}
5733	}
5734	bnx2x_bits_en(bp,
5735		      NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
5736		      mask);
5737
5738	DP(NETIF_MSG_LINK, "port %x, is_xgxs %x, int_status 0x%x\n", port,
5739		 (params->switch_cfg == SWITCH_CFG_10G),
5740		 REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
5741	DP(NETIF_MSG_LINK, " int_mask 0x%x, MI_INT %x, SERDES_LINK %x\n",
5742		 REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4),
5743		 REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18),
5744		 REG_RD(bp, NIG_REG_SERDES0_STATUS_LINK_STATUS+port*0x3c));
5745	DP(NETIF_MSG_LINK, " 10G %x, XGXS_LINK %x\n",
5746	   REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
5747	   REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
5748}
5749
5750static void bnx2x_rearm_latch_signal(struct bnx2x *bp, u8 port,
5751				     u8 exp_mi_int)
5752{
5753	u32 latch_status = 0;
5754
5755	/*
5756	 * Disable the MI INT ( external phy int ) by writing 1 to the
5757	 * status register. Link down indication is high-active-signal,
5758	 * so in this case we need to write the status to clear the XOR
5759	 */
5760	/* Read Latched signals */
5761	latch_status = REG_RD(bp,
5762				    NIG_REG_LATCH_STATUS_0 + port*8);
5763	DP(NETIF_MSG_LINK, "latch_status = 0x%x\n", latch_status);
5764	/* Handle only those with latched-signal=up.*/
5765	if (exp_mi_int)
5766		bnx2x_bits_en(bp,
5767			      NIG_REG_STATUS_INTERRUPT_PORT0
5768			      + port*4,
5769			      NIG_STATUS_EMAC0_MI_INT);
5770	else
5771		bnx2x_bits_dis(bp,
5772			       NIG_REG_STATUS_INTERRUPT_PORT0
5773			       + port*4,
5774			       NIG_STATUS_EMAC0_MI_INT);
5775
5776	if (latch_status & 1) {
5777
5778		/* For all latched-signal=up : Re-Arm Latch signals */
5779		REG_WR(bp, NIG_REG_LATCH_STATUS_0 + port*8,
5780		       (latch_status & 0xfffe) | (latch_status & 1));
5781	}
5782	/* For all latched-signal=up,Write original_signal to status */
5783}
5784
5785static void bnx2x_link_int_ack(struct link_params *params,
5786			       struct link_vars *vars, u8 is_10g_plus)
5787{
5788	struct bnx2x *bp = params->bp;
5789	u8 port = params->port;
5790	u32 mask;
5791	/*
5792	 * First reset all status we assume only one line will be
5793	 * change at a time
5794	 */
5795	bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
5796		       (NIG_STATUS_XGXS0_LINK10G |
5797			NIG_STATUS_XGXS0_LINK_STATUS |
5798			NIG_STATUS_SERDES0_LINK_STATUS));
5799	if (vars->phy_link_up) {
5800		if (USES_WARPCORE(bp))
5801			mask = NIG_STATUS_XGXS0_LINK_STATUS;
5802		else {
5803			if (is_10g_plus)
5804				mask = NIG_STATUS_XGXS0_LINK10G;
5805			else if (params->switch_cfg == SWITCH_CFG_10G) {
5806				/*
5807				 * Disable the link interrupt by writing 1 to
5808				 * the relevant lane in the status register
5809				 */
5810				u32 ser_lane =
5811					((params->lane_config &
5812				    PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
5813				    PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
5814				mask = ((1 << ser_lane) <<
5815				       NIG_STATUS_XGXS0_LINK_STATUS_SIZE);
5816			} else
5817				mask = NIG_STATUS_SERDES0_LINK_STATUS;
5818		}
5819		DP(NETIF_MSG_LINK, "Ack link up interrupt with mask 0x%x\n",
5820			       mask);
5821		bnx2x_bits_en(bp,
5822			      NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
5823			      mask);
5824	}
5825}
5826
5827static int bnx2x_format_ver(u32 num, u8 *str, u16 *len)
5828{
5829	u8 *str_ptr = str;
5830	u32 mask = 0xf0000000;
5831	u8 shift = 8*4;
5832	u8 digit;
5833	u8 remove_leading_zeros = 1;
5834	if (*len < 10) {
5835		/* Need more than 10chars for this format */
5836		*str_ptr = '\0';
5837		(*len)--;
5838		return -EINVAL;
5839	}
5840	while (shift > 0) {
5841
5842		shift -= 4;
5843		digit = ((num & mask) >> shift);
5844		if (digit == 0 && remove_leading_zeros) {
5845			mask = mask >> 4;
5846			continue;
5847		} else if (digit < 0xa)
5848			*str_ptr = digit + '0';
5849		else
5850			*str_ptr = digit - 0xa + 'a';
5851		remove_leading_zeros = 0;
5852		str_ptr++;
5853		(*len)--;
5854		mask = mask >> 4;
5855		if (shift == 4*4) {
5856			*str_ptr = '.';
5857			str_ptr++;
5858			(*len)--;
5859			remove_leading_zeros = 1;
5860		}
5861	}
5862	return 0;
5863}
5864
5865
5866static int bnx2x_null_format_ver(u32 spirom_ver, u8 *str, u16 *len)
5867{
5868	str[0] = '\0';
5869	(*len)--;
5870	return 0;
5871}
5872
5873int bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
5874				 u8 *version, u16 len)
5875{
5876	struct bnx2x *bp;
5877	u32 spirom_ver = 0;
5878	int status = 0;
5879	u8 *ver_p = version;
5880	u16 remain_len = len;
5881	if (version == NULL || params == NULL)
5882		return -EINVAL;
5883	bp = params->bp;
5884
5885	/* Extract first external phy*/
5886	version[0] = '\0';
5887	spirom_ver = REG_RD(bp, params->phy[EXT_PHY1].ver_addr);
5888
5889	if (params->phy[EXT_PHY1].format_fw_ver) {
5890		status |= params->phy[EXT_PHY1].format_fw_ver(spirom_ver,
5891							      ver_p,
5892							      &remain_len);
5893		ver_p += (len - remain_len);
5894	}
5895	if ((params->num_phys == MAX_PHYS) &&
5896	    (params->phy[EXT_PHY2].ver_addr != 0)) {
5897		spirom_ver = REG_RD(bp, params->phy[EXT_PHY2].ver_addr);
5898		if (params->phy[EXT_PHY2].format_fw_ver) {
5899			*ver_p = '/';
5900			ver_p++;
5901			remain_len--;
5902			status |= params->phy[EXT_PHY2].format_fw_ver(
5903				spirom_ver,
5904				ver_p,
5905				&remain_len);
5906			ver_p = version + (len - remain_len);
5907		}
5908	}
5909	*ver_p = '\0';
5910	return status;
5911}
5912
5913static void bnx2x_set_xgxs_loopback(struct bnx2x_phy *phy,
5914				    struct link_params *params)
5915{
5916	u8 port = params->port;
5917	struct bnx2x *bp = params->bp;
5918
5919	if (phy->req_line_speed != SPEED_1000) {
5920		u32 md_devad = 0;
5921
5922		DP(NETIF_MSG_LINK, "XGXS 10G loopback enable\n");
5923
5924		if (!CHIP_IS_E3(bp)) {
5925			/* change the uni_phy_addr in the nig */
5926			md_devad = REG_RD(bp, (NIG_REG_XGXS0_CTRL_MD_DEVAD +
5927					       port*0x18));
5928
5929			REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
5930			       0x5);
5931		}
5932
5933		bnx2x_cl45_write(bp, phy,
5934				 5,
5935				 (MDIO_REG_BANK_AER_BLOCK +
5936				  (MDIO_AER_BLOCK_AER_REG & 0xf)),
5937				 0x2800);
5938
5939		bnx2x_cl45_write(bp, phy,
5940				 5,
5941				 (MDIO_REG_BANK_CL73_IEEEB0 +
5942				  (MDIO_CL73_IEEEB0_CL73_AN_CONTROL & 0xf)),
5943				 0x6041);
5944		msleep(200);
5945		/* set aer mmd back */
5946		bnx2x_set_aer_mmd(params, phy);
5947
5948		if (!CHIP_IS_E3(bp)) {
5949			/* and md_devad */
5950			REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
5951			       md_devad);
5952		}
5953	} else {
5954		u16 mii_ctrl;
5955		DP(NETIF_MSG_LINK, "XGXS 1G loopback enable\n");
5956		bnx2x_cl45_read(bp, phy, 5,
5957				(MDIO_REG_BANK_COMBO_IEEE0 +
5958				(MDIO_COMBO_IEEE0_MII_CONTROL & 0xf)),
5959				&mii_ctrl);
5960		bnx2x_cl45_write(bp, phy, 5,
5961				 (MDIO_REG_BANK_COMBO_IEEE0 +
5962				 (MDIO_COMBO_IEEE0_MII_CONTROL & 0xf)),
5963				 mii_ctrl |
5964				 MDIO_COMBO_IEEO_MII_CONTROL_LOOPBACK);
5965	}
5966}
5967
5968int bnx2x_set_led(struct link_params *params,
5969		  struct link_vars *vars, u8 mode, u32 speed)
5970{
5971	u8 port = params->port;
5972	u16 hw_led_mode = params->hw_led_mode;
5973	int rc = 0;
5974	u8 phy_idx;
5975	u32 tmp;
5976	u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
5977	struct bnx2x *bp = params->bp;
5978	DP(NETIF_MSG_LINK, "bnx2x_set_led: port %x, mode %d\n", port, mode);
5979	DP(NETIF_MSG_LINK, "speed 0x%x, hw_led_mode 0x%x\n",
5980		 speed, hw_led_mode);
5981	/* In case */
5982	for (phy_idx = EXT_PHY1; phy_idx < MAX_PHYS; phy_idx++) {
5983		if (params->phy[phy_idx].set_link_led) {
5984			params->phy[phy_idx].set_link_led(
5985				&params->phy[phy_idx], params, mode);
5986		}
5987	}
5988
5989	switch (mode) {
5990	case LED_MODE_FRONT_PANEL_OFF:
5991	case LED_MODE_OFF:
5992		REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 0);
5993		REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4,
5994		       SHARED_HW_CFG_LED_MAC1);
5995
5996		tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
5997		EMAC_WR(bp, EMAC_REG_EMAC_LED, (tmp | EMAC_LED_OVERRIDE));
5998		break;
5999
6000	case LED_MODE_OPER:
6001		/*
6002		 * For all other phys, OPER mode is same as ON, so in case
6003		 * link is down, do nothing
6004		 */
6005		if (!vars->link_up)
6006			break;
6007	case LED_MODE_ON:
6008		if (((params->phy[EXT_PHY1].type ==
6009			  PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727) ||
6010			 (params->phy[EXT_PHY1].type ==
6011			  PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722)) &&
6012		    CHIP_IS_E2(bp) && params->num_phys == 2) {
6013			/*
6014			 * This is a work-around for E2+8727 Configurations
6015			 */
6016			if (mode == LED_MODE_ON ||
6017				speed == SPEED_10000){
6018				REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, 0);
6019				REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 1);
6020
6021				tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
6022				EMAC_WR(bp, EMAC_REG_EMAC_LED,
6023					(tmp | EMAC_LED_OVERRIDE));
6024				/*
6025				 * return here without enabling traffic
6026				 * LED blink and setting rate in ON mode.
6027				 * In oper mode, enabling LED blink
6028				 * and setting rate is needed.
6029				 */
6030				if (mode == LED_MODE_ON)
6031					return rc;
6032			}
6033		} else if (SINGLE_MEDIA_DIRECT(params)) {
6034			/*
6035			 * This is a work-around for HW issue found when link
6036			 * is up in CL73
6037			 */
6038			if ((!CHIP_IS_E3(bp)) ||
6039			    (CHIP_IS_E3(bp) &&
6040			     mode == LED_MODE_ON))
6041				REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 1);
6042
6043			if (CHIP_IS_E1x(bp) ||
6044			    CHIP_IS_E2(bp) ||
6045			    (mode == LED_MODE_ON))
6046				REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, 0);
6047			else
6048				REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4,
6049				       hw_led_mode);
6050		} else
6051			REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, hw_led_mode);
6052
6053		REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 + port*4, 0);
6054		/* Set blinking rate to ~15.9Hz */
6055		if (CHIP_IS_E3(bp))
6056			REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_P0 + port*4,
6057			       LED_BLINK_RATE_VAL_E3);
6058		else
6059			REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_P0 + port*4,
6060			       LED_BLINK_RATE_VAL_E1X_E2);
6061		REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_ENA_P0 +
6062		       port*4, 1);
6063		tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
6064		EMAC_WR(bp, EMAC_REG_EMAC_LED, (tmp & (~EMAC_LED_OVERRIDE)));
6065
6066		if (CHIP_IS_E1(bp) &&
6067		    ((speed == SPEED_2500) ||
6068		     (speed == SPEED_1000) ||
6069		     (speed == SPEED_100) ||
6070		     (speed == SPEED_10))) {
6071			/*
6072			 * On Everest 1 Ax chip versions for speeds less than
6073			 * 10G LED scheme is different
6074			 */
6075			REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0
6076			       + port*4, 1);
6077			REG_WR(bp, NIG_REG_LED_CONTROL_TRAFFIC_P0 +
6078			       port*4, 0);
6079			REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_TRAFFIC_P0 +
6080			       port*4, 1);
6081		}
6082		break;
6083
6084	default:
6085		rc = -EINVAL;
6086		DP(NETIF_MSG_LINK, "bnx2x_set_led: Invalid led mode %d\n",
6087			 mode);
6088		break;
6089	}
6090	return rc;
6091
6092}
6093
6094/*
6095 * This function comes to reflect the actual link state read DIRECTLY from the
6096 * HW
6097 */
6098int bnx2x_test_link(struct link_params *params, struct link_vars *vars,
6099		    u8 is_serdes)
6100{
6101	struct bnx2x *bp = params->bp;
6102	u16 gp_status = 0, phy_index = 0;
6103	u8 ext_phy_link_up = 0, serdes_phy_type;
6104	struct link_vars temp_vars;
6105	struct bnx2x_phy *int_phy = &params->phy[INT_PHY];
6106
6107	if (CHIP_IS_E3(bp)) {
6108		u16 link_up;
6109		if (params->req_line_speed[LINK_CONFIG_IDX(INT_PHY)]
6110		    > SPEED_10000) {
6111			/* Check 20G link */
6112			bnx2x_cl45_read(bp, int_phy, MDIO_WC_DEVAD,
6113					1, &link_up);
6114			bnx2x_cl45_read(bp, int_phy, MDIO_WC_DEVAD,
6115					1, &link_up);
6116			link_up &= (1<<2);
6117		} else {
6118			/* Check 10G link and below*/
6119			u8 lane = bnx2x_get_warpcore_lane(int_phy, params);
6120			bnx2x_cl45_read(bp, int_phy, MDIO_WC_DEVAD,
6121					MDIO_WC_REG_GP2_STATUS_GP_2_1,
6122					&gp_status);
6123			gp_status = ((gp_status >> 8) & 0xf) |
6124				((gp_status >> 12) & 0xf);
6125			link_up = gp_status & (1 << lane);
6126		}
6127		if (!link_up)
6128			return -ESRCH;
6129	} else {
6130		CL22_RD_OVER_CL45(bp, int_phy,
6131			  MDIO_REG_BANK_GP_STATUS,
6132			  MDIO_GP_STATUS_TOP_AN_STATUS1,
6133			  &gp_status);
6134	/* link is up only if both local phy and external phy are up */
6135	if (!(gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS))
6136		return -ESRCH;
6137	}
6138	/* In XGXS loopback mode, do not check external PHY */
6139	if (params->loopback_mode == LOOPBACK_XGXS)
6140		return 0;
6141
6142	switch (params->num_phys) {
6143	case 1:
6144		/* No external PHY */
6145		return 0;
6146	case 2:
6147		ext_phy_link_up = params->phy[EXT_PHY1].read_status(
6148			&params->phy[EXT_PHY1],
6149			params, &temp_vars);
6150		break;
6151	case 3: /* Dual Media */
6152		for (phy_index = EXT_PHY1; phy_index < params->num_phys;
6153		      phy_index++) {
6154			serdes_phy_type = ((params->phy[phy_index].media_type ==
6155					    ETH_PHY_SFP_FIBER) ||
6156					   (params->phy[phy_index].media_type ==
6157					    ETH_PHY_XFP_FIBER) ||
6158					   (params->phy[phy_index].media_type ==
6159					    ETH_PHY_DA_TWINAX));
6160
6161			if (is_serdes != serdes_phy_type)
6162				continue;
6163			if (params->phy[phy_index].read_status) {
6164				ext_phy_link_up |=
6165					params->phy[phy_index].read_status(
6166						&params->phy[phy_index],
6167						params, &temp_vars);
6168			}
6169		}
6170		break;
6171	}
6172	if (ext_phy_link_up)
6173		return 0;
6174	return -ESRCH;
6175}
6176
6177static int bnx2x_link_initialize(struct link_params *params,
6178				 struct link_vars *vars)
6179{
6180	int rc = 0;
6181	u8 phy_index, non_ext_phy;
6182	struct bnx2x *bp = params->bp;
6183	/*
6184	 * In case of external phy existence, the line speed would be the
6185	 * line speed linked up by the external phy. In case it is direct
6186	 * only, then the line_speed during initialization will be
6187	 * equal to the req_line_speed
6188	 */
6189	vars->line_speed = params->phy[INT_PHY].req_line_speed;
6190
6191	/*
6192	 * Initialize the internal phy in case this is a direct board
6193	 * (no external phys), or this board has external phy which requires
6194	 * to first.
6195	 */
6196	if (!USES_WARPCORE(bp))
6197		bnx2x_prepare_xgxs(&params->phy[INT_PHY], params, vars);
6198	/* init ext phy and enable link state int */
6199	non_ext_phy = (SINGLE_MEDIA_DIRECT(params) ||
6200		       (params->loopback_mode == LOOPBACK_XGXS));
6201
6202	if (non_ext_phy ||
6203	    (params->phy[EXT_PHY1].flags & FLAGS_INIT_XGXS_FIRST) ||
6204	    (params->loopback_mode == LOOPBACK_EXT_PHY)) {
6205		struct bnx2x_phy *phy = &params->phy[INT_PHY];
6206		if (vars->line_speed == SPEED_AUTO_NEG &&
6207		    (CHIP_IS_E1x(bp) ||
6208		     CHIP_IS_E2(bp)))
6209			bnx2x_set_parallel_detection(phy, params);
6210			if (params->phy[INT_PHY].config_init)
6211				params->phy[INT_PHY].config_init(phy,
6212								 params,
6213								 vars);
6214	}
6215
6216	/* Init external phy*/
6217	if (non_ext_phy) {
6218		if (params->phy[INT_PHY].supported &
6219		    SUPPORTED_FIBRE)
6220			vars->link_status |= LINK_STATUS_SERDES_LINK;
6221	} else {
6222		for (phy_index = EXT_PHY1; phy_index < params->num_phys;
6223		      phy_index++) {
6224			/*
6225			 * No need to initialize second phy in case of first
6226			 * phy only selection. In case of second phy, we do
6227			 * need to initialize the first phy, since they are
6228			 * connected.
6229			 */
6230			if (params->phy[phy_index].supported &
6231			    SUPPORTED_FIBRE)
6232				vars->link_status |= LINK_STATUS_SERDES_LINK;
6233
6234			if (phy_index == EXT_PHY2 &&
6235			    (bnx2x_phy_selection(params) ==
6236			     PORT_HW_CFG_PHY_SELECTION_FIRST_PHY)) {
6237				DP(NETIF_MSG_LINK,
6238				   "Not initializing second phy\n");
6239				continue;
6240			}
6241			params->phy[phy_index].config_init(
6242				&params->phy[phy_index],
6243				params, vars);
6244		}
6245	}
6246	/* Reset the interrupt indication after phy was initialized */
6247	bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 +
6248		       params->port*4,
6249		       (NIG_STATUS_XGXS0_LINK10G |
6250			NIG_STATUS_XGXS0_LINK_STATUS |
6251			NIG_STATUS_SERDES0_LINK_STATUS |
6252			NIG_MASK_MI_INT));
6253	bnx2x_update_mng(params, vars->link_status);
6254	return rc;
6255}
6256
6257static void bnx2x_int_link_reset(struct bnx2x_phy *phy,
6258				 struct link_params *params)
6259{
6260	/* reset the SerDes/XGXS */
6261	REG_WR(params->bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR,
6262	       (0x1ff << (params->port*16)));
6263}
6264
6265static void bnx2x_common_ext_link_reset(struct bnx2x_phy *phy,
6266					struct link_params *params)
6267{
6268	struct bnx2x *bp = params->bp;
6269	u8 gpio_port;
6270	/* HW reset */
6271	if (CHIP_IS_E2(bp))
6272		gpio_port = BP_PATH(bp);
6273	else
6274		gpio_port = params->port;
6275	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
6276		       MISC_REGISTERS_GPIO_OUTPUT_LOW,
6277		       gpio_port);
6278	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
6279		       MISC_REGISTERS_GPIO_OUTPUT_LOW,
6280		       gpio_port);
6281	DP(NETIF_MSG_LINK, "reset external PHY\n");
6282}
6283
6284static int bnx2x_update_link_down(struct link_params *params,
6285				  struct link_vars *vars)
6286{
6287	struct bnx2x *bp = params->bp;
6288	u8 port = params->port;
6289
6290	DP(NETIF_MSG_LINK, "Port %x: Link is down\n", port);
6291	bnx2x_set_led(params, vars, LED_MODE_OFF, 0);
6292	vars->phy_flags &= ~PHY_PHYSICAL_LINK_FLAG;
6293	/* indicate no mac active */
6294	vars->mac_type = MAC_TYPE_NONE;
6295
6296	/* update shared memory */
6297	vars->link_status &= ~(LINK_STATUS_SPEED_AND_DUPLEX_MASK |
6298			       LINK_STATUS_LINK_UP |
6299			       LINK_STATUS_PHYSICAL_LINK_FLAG |
6300			       LINK_STATUS_AUTO_NEGOTIATE_COMPLETE |
6301			       LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK |
6302			       LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK |
6303			       LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK);
6304	vars->line_speed = 0;
6305	bnx2x_update_mng(params, vars->link_status);
6306
6307	/* activate nig drain */
6308	REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
6309
6310	/* disable emac */
6311	if (!CHIP_IS_E3(bp))
6312		REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
6313
6314	msleep(10);
6315	/* reset BigMac/Xmac */
6316	if (CHIP_IS_E1x(bp) ||
6317	    CHIP_IS_E2(bp)) {
6318		bnx2x_bmac_rx_disable(bp, params->port);
6319		REG_WR(bp, GRCBASE_MISC +
6320		       MISC_REGISTERS_RESET_REG_2_CLEAR,
6321	       (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
6322	}
6323	if (CHIP_IS_E3(bp)) {
6324		bnx2x_xmac_disable(params);
6325		bnx2x_umac_disable(params);
6326	}
6327
6328	return 0;
6329}
6330
6331static int bnx2x_update_link_up(struct link_params *params,
6332				struct link_vars *vars,
6333				u8 link_10g)
6334{
6335	struct bnx2x *bp = params->bp;
6336	u8 port = params->port;
6337	int rc = 0;
6338
6339	vars->link_status |= (LINK_STATUS_LINK_UP |
6340			      LINK_STATUS_PHYSICAL_LINK_FLAG);
6341	vars->phy_flags |= PHY_PHYSICAL_LINK_FLAG;
6342
6343	if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
6344		vars->link_status |=
6345			LINK_STATUS_TX_FLOW_CONTROL_ENABLED;
6346
6347	if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
6348		vars->link_status |=
6349			LINK_STATUS_RX_FLOW_CONTROL_ENABLED;
6350	if (USES_WARPCORE(bp)) {
6351		if (link_10g) {
6352			if (bnx2x_xmac_enable(params, vars, 0) ==
6353			    -ESRCH) {
6354				DP(NETIF_MSG_LINK, "Found errors on XMAC\n");
6355				vars->link_up = 0;
6356				vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
6357				vars->link_status &= ~LINK_STATUS_LINK_UP;
6358			}
6359		} else
6360			bnx2x_umac_enable(params, vars, 0);
6361		bnx2x_set_led(params, vars,
6362			      LED_MODE_OPER, vars->line_speed);
6363	}
6364	if ((CHIP_IS_E1x(bp) ||
6365	     CHIP_IS_E2(bp))) {
6366		if (link_10g) {
6367			if (bnx2x_bmac_enable(params, vars, 0) ==
6368			    -ESRCH) {
6369				DP(NETIF_MSG_LINK, "Found errors on BMAC\n");
6370				vars->link_up = 0;
6371				vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
6372				vars->link_status &= ~LINK_STATUS_LINK_UP;
6373			}
6374
6375			bnx2x_set_led(params, vars,
6376				      LED_MODE_OPER, SPEED_10000);
6377		} else {
6378			rc = bnx2x_emac_program(params, vars);
6379			bnx2x_emac_enable(params, vars, 0);
6380
6381			/* AN complete? */
6382			if ((vars->link_status &
6383			     LINK_STATUS_AUTO_NEGOTIATE_COMPLETE)
6384			    && (!(vars->phy_flags & PHY_SGMII_FLAG)) &&
6385			    SINGLE_MEDIA_DIRECT(params))
6386				bnx2x_set_gmii_tx_driver(params);
6387		}
6388	}
6389
6390	/* PBF - link up */
6391	if (CHIP_IS_E1x(bp))
6392		rc |= bnx2x_pbf_update(params, vars->flow_ctrl,
6393				       vars->line_speed);
6394
6395	/* disable drain */
6396	REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 0);
6397
6398	/* update shared memory */
6399	bnx2x_update_mng(params, vars->link_status);
6400	msleep(20);
6401	return rc;
6402}
6403/*
6404 * The bnx2x_link_update function should be called upon link
6405 * interrupt.
6406 * Link is considered up as follows:
6407 * - DIRECT_SINGLE_MEDIA - Only XGXS link (internal link) needs
6408 *   to be up
6409 * - SINGLE_MEDIA - The link between the 577xx and the external
6410 *   phy (XGXS) need to up as well as the external link of the
6411 *   phy (PHY_EXT1)
6412 * - DUAL_MEDIA - The link between the 577xx and the first
6413 *   external phy needs to be up, and at least one of the 2
6414 *   external phy link must be up.
6415 */
6416int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
6417{
6418	struct bnx2x *bp = params->bp;
6419	struct link_vars phy_vars[MAX_PHYS];
6420	u8 port = params->port;
6421	u8 link_10g_plus, phy_index;
6422	u8 ext_phy_link_up = 0, cur_link_up;
6423	int rc = 0;
6424	u8 is_mi_int = 0;
6425	u16 ext_phy_line_speed = 0, prev_line_speed = vars->line_speed;
6426	u8 active_external_phy = INT_PHY;
6427	vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG;
6428	for (phy_index = INT_PHY; phy_index < params->num_phys;
6429	      phy_index++) {
6430		phy_vars[phy_index].flow_ctrl = 0;
6431		phy_vars[phy_index].link_status = 0;
6432		phy_vars[phy_index].line_speed = 0;
6433		phy_vars[phy_index].duplex = DUPLEX_FULL;
6434		phy_vars[phy_index].phy_link_up = 0;
6435		phy_vars[phy_index].link_up = 0;
6436		phy_vars[phy_index].fault_detected = 0;
6437	}
6438
6439	if (USES_WARPCORE(bp))
6440		bnx2x_set_aer_mmd(params, &params->phy[INT_PHY]);
6441
6442	DP(NETIF_MSG_LINK, "port %x, XGXS?%x, int_status 0x%x\n",
6443		 port, (vars->phy_flags & PHY_XGXS_FLAG),
6444		 REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
6445
6446	is_mi_int = (u8)(REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT +
6447				port*0x18) > 0);
6448	DP(NETIF_MSG_LINK, "int_mask 0x%x MI_INT %x, SERDES_LINK %x\n",
6449		 REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4),
6450		 is_mi_int,
6451		 REG_RD(bp, NIG_REG_SERDES0_STATUS_LINK_STATUS + port*0x3c));
6452
6453	DP(NETIF_MSG_LINK, " 10G %x, XGXS_LINK %x\n",
6454	  REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
6455	  REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
6456
6457	/* disable emac */
6458	if (!CHIP_IS_E3(bp))
6459		REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
6460
6461	/*
6462	 * Step 1:
6463	 * Check external link change only for external phys, and apply
6464	 * priority selection between them in case the link on both phys
6465	 * is up. Note that instead of the common vars, a temporary
6466	 * vars argument is used since each phy may have different link/
6467	 * speed/duplex result
6468	 */
6469	for (phy_index = EXT_PHY1; phy_index < params->num_phys;
6470	      phy_index++) {
6471		struct bnx2x_phy *phy = &params->phy[phy_index];
6472		if (!phy->read_status)
6473			continue;
6474		/* Read link status and params of this ext phy */
6475		cur_link_up = phy->read_status(phy, params,
6476					       &phy_vars[phy_index]);
6477		if (cur_link_up) {
6478			DP(NETIF_MSG_LINK, "phy in index %d link is up\n",
6479				   phy_index);
6480		} else {
6481			DP(NETIF_MSG_LINK, "phy in index %d link is down\n",
6482				   phy_index);
6483			continue;
6484		}
6485
6486		if (!ext_phy_link_up) {
6487			ext_phy_link_up = 1;
6488			active_external_phy = phy_index;
6489		} else {
6490			switch (bnx2x_phy_selection(params)) {
6491			case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT:
6492			case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
6493			/*
6494			 * In this option, the first PHY makes sure to pass the
6495			 * traffic through itself only.
6496			 * Its not clear how to reset the link on the second phy
6497			 */
6498				active_external_phy = EXT_PHY1;
6499				break;
6500			case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
6501			/*
6502			 * In this option, the first PHY makes sure to pass the
6503			 * traffic through the second PHY.
6504			 */
6505				active_external_phy = EXT_PHY2;
6506				break;
6507			default:
6508			/*
6509			 * Link indication on both PHYs with the following cases
6510			 * is invalid:
6511			 * - FIRST_PHY means that second phy wasn't initialized,
6512			 * hence its link is expected to be down
6513			 * - SECOND_PHY means that first phy should not be able
6514			 * to link up by itself (using configuration)
6515			 * - DEFAULT should be overriden during initialiazation
6516			 */
6517				DP(NETIF_MSG_LINK, "Invalid link indication"
6518					   "mpc=0x%x. DISABLING LINK !!!\n",
6519					   params->multi_phy_config);
6520				ext_phy_link_up = 0;
6521				break;
6522			}
6523		}
6524	}
6525	prev_line_speed = vars->line_speed;
6526	/*
6527	 * Step 2:
6528	 * Read the status of the internal phy. In case of
6529	 * DIRECT_SINGLE_MEDIA board, this link is the external link,
6530	 * otherwise this is the link between the 577xx and the first
6531	 * external phy
6532	 */
6533	if (params->phy[INT_PHY].read_status)
6534		params->phy[INT_PHY].read_status(
6535			&params->phy[INT_PHY],
6536			params, vars);
6537	/*
6538	 * The INT_PHY flow control reside in the vars. This include the
6539	 * case where the speed or flow control are not set to AUTO.
6540	 * Otherwise, the active external phy flow control result is set
6541	 * to the vars. The ext_phy_line_speed is needed to check if the
6542	 * speed is different between the internal phy and external phy.
6543	 * This case may be result of intermediate link speed change.
6544	 */
6545	if (active_external_phy > INT_PHY) {
6546		vars->flow_ctrl = phy_vars[active_external_phy].flow_ctrl;
6547		/*
6548		 * Link speed is taken from the XGXS. AN and FC result from
6549		 * the external phy.
6550		 */
6551		vars->link_status |= phy_vars[active_external_phy].link_status;
6552
6553		/*
6554		 * if active_external_phy is first PHY and link is up - disable
6555		 * disable TX on second external PHY
6556		 */
6557		if (active_external_phy == EXT_PHY1) {
6558			if (params->phy[EXT_PHY2].phy_specific_func) {
6559				DP(NETIF_MSG_LINK,
6560				   "Disabling TX on EXT_PHY2\n");
6561				params->phy[EXT_PHY2].phy_specific_func(
6562					&params->phy[EXT_PHY2],
6563					params, DISABLE_TX);
6564			}
6565		}
6566
6567		ext_phy_line_speed = phy_vars[active_external_phy].line_speed;
6568		vars->duplex = phy_vars[active_external_phy].duplex;
6569		if (params->phy[active_external_phy].supported &
6570		    SUPPORTED_FIBRE)
6571			vars->link_status |= LINK_STATUS_SERDES_LINK;
6572		else
6573			vars->link_status &= ~LINK_STATUS_SERDES_LINK;
6574		DP(NETIF_MSG_LINK, "Active external phy selected: %x\n",
6575			   active_external_phy);
6576	}
6577
6578	for (phy_index = EXT_PHY1; phy_index < params->num_phys;
6579	      phy_index++) {
6580		if (params->phy[phy_index].flags &
6581		    FLAGS_REARM_LATCH_SIGNAL) {
6582			bnx2x_rearm_latch_signal(bp, port,
6583						 phy_index ==
6584						 active_external_phy);
6585			break;
6586		}
6587	}
6588	DP(NETIF_MSG_LINK, "vars->flow_ctrl = 0x%x, vars->link_status = 0x%x,"
6589		   " ext_phy_line_speed = %d\n", vars->flow_ctrl,
6590		   vars->link_status, ext_phy_line_speed);
6591	/*
6592	 * Upon link speed change set the NIG into drain mode. Comes to
6593	 * deals with possible FIFO glitch due to clk change when speed
6594	 * is decreased without link down indicator
6595	 */
6596
6597	if (vars->phy_link_up) {
6598		if (!(SINGLE_MEDIA_DIRECT(params)) && ext_phy_link_up &&
6599		    (ext_phy_line_speed != vars->line_speed)) {
6600			DP(NETIF_MSG_LINK, "Internal link speed %d is"
6601				   " different than the external"
6602				   " link speed %d\n", vars->line_speed,
6603				   ext_phy_line_speed);
6604			vars->phy_link_up = 0;
6605		} else if (prev_line_speed != vars->line_speed) {
6606			REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4,
6607			       0);
6608			msleep(1);
6609		}
6610	}
6611
6612	/* anything 10 and over uses the bmac */
6613	link_10g_plus = (vars->line_speed >= SPEED_10000);
6614
6615	bnx2x_link_int_ack(params, vars, link_10g_plus);
6616
6617	/*
6618	 * In case external phy link is up, and internal link is down
6619	 * (not initialized yet probably after link initialization, it
6620	 * needs to be initialized.
6621	 * Note that after link down-up as result of cable plug, the xgxs
6622	 * link would probably become up again without the need
6623	 * initialize it
6624	 */
6625	if (!(SINGLE_MEDIA_DIRECT(params))) {
6626		DP(NETIF_MSG_LINK, "ext_phy_link_up = %d, int_link_up = %d,"
6627			   " init_preceding = %d\n", ext_phy_link_up,
6628			   vars->phy_link_up,
6629			   params->phy[EXT_PHY1].flags &
6630			   FLAGS_INIT_XGXS_FIRST);
6631		if (!(params->phy[EXT_PHY1].flags &
6632		      FLAGS_INIT_XGXS_FIRST)
6633		    && ext_phy_link_up && !vars->phy_link_up) {
6634			vars->line_speed = ext_phy_line_speed;
6635			if (vars->line_speed < SPEED_1000)
6636				vars->phy_flags |= PHY_SGMII_FLAG;
6637			else
6638				vars->phy_flags &= ~PHY_SGMII_FLAG;
6639
6640			if (params->phy[INT_PHY].config_init)
6641				params->phy[INT_PHY].config_init(
6642					&params->phy[INT_PHY], params,
6643						vars);
6644		}
6645	}
6646	/*
6647	 * Link is up only if both local phy and external phy (in case of
6648	 * non-direct board) are up and no fault detected on active PHY.
6649	 */
6650	vars->link_up = (vars->phy_link_up &&
6651			 (ext_phy_link_up ||
6652			  SINGLE_MEDIA_DIRECT(params)) &&
6653			 (phy_vars[active_external_phy].fault_detected == 0));
6654
6655	if (vars->link_up)
6656		rc = bnx2x_update_link_up(params, vars, link_10g_plus);
6657	else
6658		rc = bnx2x_update_link_down(params, vars);
6659
6660	return rc;
6661}
6662
6663
6664/*****************************************************************************/
6665/*			    External Phy section			     */
6666/*****************************************************************************/
6667void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port)
6668{
6669	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
6670		       MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
6671	msleep(1);
6672	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
6673		       MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
6674}
6675
6676static void bnx2x_save_spirom_version(struct bnx2x *bp, u8 port,
6677				      u32 spirom_ver, u32 ver_addr)
6678{
6679	DP(NETIF_MSG_LINK, "FW version 0x%x:0x%x for port %d\n",
6680		 (u16)(spirom_ver>>16), (u16)spirom_ver, port);
6681
6682	if (ver_addr)
6683		REG_WR(bp, ver_addr, spirom_ver);
6684}
6685
6686static void bnx2x_save_bcm_spirom_ver(struct bnx2x *bp,
6687				      struct bnx2x_phy *phy,
6688				      u8 port)
6689{
6690	u16 fw_ver1, fw_ver2;
6691
6692	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
6693			MDIO_PMA_REG_ROM_VER1, &fw_ver1);
6694	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
6695			MDIO_PMA_REG_ROM_VER2, &fw_ver2);
6696	bnx2x_save_spirom_version(bp, port, (u32)(fw_ver1<<16 | fw_ver2),
6697				  phy->ver_addr);
6698}
6699
6700static void bnx2x_ext_phy_10G_an_resolve(struct bnx2x *bp,
6701				       struct bnx2x_phy *phy,
6702				       struct link_vars *vars)
6703{
6704	u16 val;
6705	bnx2x_cl45_read(bp, phy,
6706			MDIO_AN_DEVAD,
6707			MDIO_AN_REG_STATUS, &val);
6708	bnx2x_cl45_read(bp, phy,
6709			MDIO_AN_DEVAD,
6710			MDIO_AN_REG_STATUS, &val);
6711	if (val & (1<<5))
6712		vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
6713	if ((val & (1<<0)) == 0)
6714		vars->link_status |= LINK_STATUS_PARALLEL_DETECTION_USED;
6715}
6716
6717/******************************************************************/
6718/*		common BCM8073/BCM8727 PHY SECTION		  */
6719/******************************************************************/
6720static void bnx2x_8073_resolve_fc(struct bnx2x_phy *phy,
6721				  struct link_params *params,
6722				  struct link_vars *vars)
6723{
6724	struct bnx2x *bp = params->bp;
6725	if (phy->req_line_speed == SPEED_10 ||
6726	    phy->req_line_speed == SPEED_100) {
6727		vars->flow_ctrl = phy->req_flow_ctrl;
6728		return;
6729	}
6730
6731	if (bnx2x_ext_phy_resolve_fc(phy, params, vars) &&
6732	    (vars->flow_ctrl == BNX2X_FLOW_CTRL_NONE)) {
6733		u16 pause_result;
6734		u16 ld_pause;		/* local */
6735		u16 lp_pause;		/* link partner */
6736		bnx2x_cl45_read(bp, phy,
6737				MDIO_AN_DEVAD,
6738				MDIO_AN_REG_CL37_FC_LD, &ld_pause);
6739
6740		bnx2x_cl45_read(bp, phy,
6741				MDIO_AN_DEVAD,
6742				MDIO_AN_REG_CL37_FC_LP, &lp_pause);
6743		pause_result = (ld_pause &
6744				MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 5;
6745		pause_result |= (lp_pause &
6746				 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 7;
6747
6748		bnx2x_pause_resolve(vars, pause_result);
6749		DP(NETIF_MSG_LINK, "Ext PHY CL37 pause result 0x%x\n",
6750			   pause_result);
6751	}
6752}
6753static int bnx2x_8073_8727_external_rom_boot(struct bnx2x *bp,
6754					     struct bnx2x_phy *phy,
6755					     u8 port)
6756{
6757	u32 count = 0;
6758	u16 fw_ver1, fw_msgout;
6759	int rc = 0;
6760
6761	/* Boot port from external ROM  */
6762	/* EDC grst */
6763	bnx2x_cl45_write(bp, phy,
6764			 MDIO_PMA_DEVAD,
6765			 MDIO_PMA_REG_GEN_CTRL,
6766			 0x0001);
6767
6768	/* ucode reboot and rst */
6769	bnx2x_cl45_write(bp, phy,
6770			 MDIO_PMA_DEVAD,
6771			 MDIO_PMA_REG_GEN_CTRL,
6772			 0x008c);
6773
6774	bnx2x_cl45_write(bp, phy,
6775			 MDIO_PMA_DEVAD,
6776			 MDIO_PMA_REG_MISC_CTRL1, 0x0001);
6777
6778	/* Reset internal microprocessor */
6779	bnx2x_cl45_write(bp, phy,
6780			 MDIO_PMA_DEVAD,
6781			 MDIO_PMA_REG_GEN_CTRL,
6782			 MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
6783
6784	/* Release srst bit */
6785	bnx2x_cl45_write(bp, phy,
6786			 MDIO_PMA_DEVAD,
6787			 MDIO_PMA_REG_GEN_CTRL,
6788			 MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
6789
6790	/* Delay 100ms per the PHY specifications */
6791	msleep(100);
6792
6793	/* 8073 sometimes taking longer to download */
6794	do {
6795		count++;
6796		if (count > 300) {
6797			DP(NETIF_MSG_LINK,
6798				 "bnx2x_8073_8727_external_rom_boot port %x:"
6799				 "Download failed. fw version = 0x%x\n",
6800				 port, fw_ver1);
6801			rc = -EINVAL;
6802			break;
6803		}
6804
6805		bnx2x_cl45_read(bp, phy,
6806				MDIO_PMA_DEVAD,
6807				MDIO_PMA_REG_ROM_VER1, &fw_ver1);
6808		bnx2x_cl45_read(bp, phy,
6809				MDIO_PMA_DEVAD,
6810				MDIO_PMA_REG_M8051_MSGOUT_REG, &fw_msgout);
6811
6812		msleep(1);
6813	} while (fw_ver1 == 0 || fw_ver1 == 0x4321 ||
6814			((fw_msgout & 0xff) != 0x03 && (phy->type ==
6815			PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073)));
6816
6817	/* Clear ser_boot_ctl bit */
6818	bnx2x_cl45_write(bp, phy,
6819			 MDIO_PMA_DEVAD,
6820			 MDIO_PMA_REG_MISC_CTRL1, 0x0000);
6821	bnx2x_save_bcm_spirom_ver(bp, phy, port);
6822
6823	DP(NETIF_MSG_LINK,
6824		 "bnx2x_8073_8727_external_rom_boot port %x:"
6825		 "Download complete. fw version = 0x%x\n",
6826		 port, fw_ver1);
6827
6828	return rc;
6829}
6830
6831/******************************************************************/
6832/*			BCM8073 PHY SECTION			  */
6833/******************************************************************/
6834static int bnx2x_8073_is_snr_needed(struct bnx2x *bp, struct bnx2x_phy *phy)
6835{
6836	/* This is only required for 8073A1, version 102 only */
6837	u16 val;
6838
6839	/* Read 8073 HW revision*/
6840	bnx2x_cl45_read(bp, phy,
6841			MDIO_PMA_DEVAD,
6842			MDIO_PMA_REG_8073_CHIP_REV, &val);
6843
6844	if (val != 1) {
6845		/* No need to workaround in 8073 A1 */
6846		return 0;
6847	}
6848
6849	bnx2x_cl45_read(bp, phy,
6850			MDIO_PMA_DEVAD,
6851			MDIO_PMA_REG_ROM_VER2, &val);
6852
6853	/* SNR should be applied only for version 0x102 */
6854	if (val != 0x102)
6855		return 0;
6856
6857	return 1;
6858}
6859
6860static int bnx2x_8073_xaui_wa(struct bnx2x *bp, struct bnx2x_phy *phy)
6861{
6862	u16 val, cnt, cnt1 ;
6863
6864	bnx2x_cl45_read(bp, phy,
6865			MDIO_PMA_DEVAD,
6866			MDIO_PMA_REG_8073_CHIP_REV, &val);
6867
6868	if (val > 0) {
6869		/* No need to workaround in 8073 A1 */
6870		return 0;
6871	}
6872	/* XAUI workaround in 8073 A0: */
6873
6874	/*
6875	 * After loading the boot ROM and restarting Autoneg, poll
6876	 * Dev1, Reg $C820:
6877	 */
6878
6879	for (cnt = 0; cnt < 1000; cnt++) {
6880		bnx2x_cl45_read(bp, phy,
6881				MDIO_PMA_DEVAD,
6882				MDIO_PMA_REG_8073_SPEED_LINK_STATUS,
6883				&val);
6884		  /*
6885		   * If bit [14] = 0 or bit [13] = 0, continue on with
6886		   * system initialization (XAUI work-around not required, as
6887		   * these bits indicate 2.5G or 1G link up).
6888		   */
6889		if (!(val & (1<<14)) || !(val & (1<<13))) {
6890			DP(NETIF_MSG_LINK, "XAUI work-around not required\n");
6891			return 0;
6892		} else if (!(val & (1<<15))) {
6893			DP(NETIF_MSG_LINK, "bit 15 went off\n");
6894			/*
6895			 * If bit 15 is 0, then poll Dev1, Reg $C841 until it's
6896			 * MSB (bit15) goes to 1 (indicating that the XAUI
6897			 * workaround has completed), then continue on with
6898			 * system initialization.
6899			 */
6900			for (cnt1 = 0; cnt1 < 1000; cnt1++) {
6901				bnx2x_cl45_read(bp, phy,
6902					MDIO_PMA_DEVAD,
6903					MDIO_PMA_REG_8073_XAUI_WA, &val);
6904				if (val & (1<<15)) {
6905					DP(NETIF_MSG_LINK,
6906					  "XAUI workaround has completed\n");
6907					return 0;
6908				 }
6909				 msleep(3);
6910			}
6911			break;
6912		}
6913		msleep(3);
6914	}
6915	DP(NETIF_MSG_LINK, "Warning: XAUI work-around timeout !!!\n");
6916	return -EINVAL;
6917}
6918
6919static void bnx2x_807x_force_10G(struct bnx2x *bp, struct bnx2x_phy *phy)
6920{
6921	/* Force KR or KX */
6922	bnx2x_cl45_write(bp, phy,
6923			 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x2040);
6924	bnx2x_cl45_write(bp, phy,
6925			 MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, 0x000b);
6926	bnx2x_cl45_write(bp, phy,
6927			 MDIO_PMA_DEVAD, MDIO_PMA_REG_BCM_CTRL, 0x0000);
6928	bnx2x_cl45_write(bp, phy,
6929			 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x0000);
6930}
6931
6932static void bnx2x_8073_set_pause_cl37(struct link_params *params,
6933				      struct bnx2x_phy *phy,
6934				      struct link_vars *vars)
6935{
6936	u16 cl37_val;
6937	struct bnx2x *bp = params->bp;
6938	bnx2x_cl45_read(bp, phy,
6939			MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, &cl37_val);
6940
6941	cl37_val &= ~MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
6942	/* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
6943	bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
6944	if ((vars->ieee_fc &
6945	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) ==
6946	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) {
6947		cl37_val |=  MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC;
6948	}
6949	if ((vars->ieee_fc &
6950	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
6951	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
6952		cl37_val |=  MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
6953	}
6954	if ((vars->ieee_fc &
6955	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
6956	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
6957		cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
6958	}
6959	DP(NETIF_MSG_LINK,
6960		 "Ext phy AN advertize cl37 0x%x\n", cl37_val);
6961
6962	bnx2x_cl45_write(bp, phy,
6963			 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, cl37_val);
6964	msleep(500);
6965}
6966
6967static int bnx2x_8073_config_init(struct bnx2x_phy *phy,
6968				  struct link_params *params,
6969				  struct link_vars *vars)
6970{
6971	struct bnx2x *bp = params->bp;
6972	u16 val = 0, tmp1;
6973	u8 gpio_port;
6974	DP(NETIF_MSG_LINK, "Init 8073\n");
6975
6976	if (CHIP_IS_E2(bp))
6977		gpio_port = BP_PATH(bp);
6978	else
6979		gpio_port = params->port;
6980	/* Restore normal power mode*/
6981	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
6982		       MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port);
6983
6984	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
6985		       MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port);
6986
6987	/* enable LASI */
6988	bnx2x_cl45_write(bp, phy,
6989			 MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL, (1<<2));
6990	bnx2x_cl45_write(bp, phy,
6991			 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL,  0x0004);
6992
6993	bnx2x_8073_set_pause_cl37(params, phy, vars);
6994
6995	bnx2x_cl45_read(bp, phy,
6996			MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &tmp1);
6997
6998	bnx2x_cl45_read(bp, phy,
6999			MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &tmp1);
7000
7001	DP(NETIF_MSG_LINK, "Before rom RX_ALARM(port1): 0x%x\n", tmp1);
7002
7003	/* Swap polarity if required - Must be done only in non-1G mode */
7004	if (params->lane_config & PORT_HW_CFG_SWAP_PHY_POLARITY_ENABLED) {
7005		/* Configure the 8073 to swap _P and _N of the KR lines */
7006		DP(NETIF_MSG_LINK, "Swapping polarity for the 8073\n");
7007		/* 10G Rx/Tx and 1G Tx signal polarity swap */
7008		bnx2x_cl45_read(bp, phy,
7009				MDIO_PMA_DEVAD,
7010				MDIO_PMA_REG_8073_OPT_DIGITAL_CTRL, &val);
7011		bnx2x_cl45_write(bp, phy,
7012				 MDIO_PMA_DEVAD,
7013				 MDIO_PMA_REG_8073_OPT_DIGITAL_CTRL,
7014				 (val | (3<<9)));
7015	}
7016
7017
7018	/* Enable CL37 BAM */
7019	if (REG_RD(bp, params->shmem_base +
7020			 offsetof(struct shmem_region, dev_info.
7021				  port_hw_config[params->port].default_cfg)) &
7022	    PORT_HW_CFG_ENABLE_BAM_ON_KR_ENABLED) {
7023
7024		bnx2x_cl45_read(bp, phy,
7025				MDIO_AN_DEVAD,
7026				MDIO_AN_REG_8073_BAM, &val);
7027		bnx2x_cl45_write(bp, phy,
7028				 MDIO_AN_DEVAD,
7029				 MDIO_AN_REG_8073_BAM, val | 1);
7030		DP(NETIF_MSG_LINK, "Enable CL37 BAM on KR\n");
7031	}
7032	if (params->loopback_mode == LOOPBACK_EXT) {
7033		bnx2x_807x_force_10G(bp, phy);
7034		DP(NETIF_MSG_LINK, "Forced speed 10G on 807X\n");
7035		return 0;
7036	} else {
7037		bnx2x_cl45_write(bp, phy,
7038				 MDIO_PMA_DEVAD, MDIO_PMA_REG_BCM_CTRL, 0x0002);
7039	}
7040	if (phy->req_line_speed != SPEED_AUTO_NEG) {
7041		if (phy->req_line_speed == SPEED_10000) {
7042			val = (1<<7);
7043		} else if (phy->req_line_speed ==  SPEED_2500) {
7044			val = (1<<5);
7045			/*
7046			 * Note that 2.5G works only when used with 1G
7047			 * advertisement
7048			 */
7049		} else
7050			val = (1<<5);
7051	} else {
7052		val = 0;
7053		if (phy->speed_cap_mask &
7054			PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
7055			val |= (1<<7);
7056
7057		/* Note that 2.5G works only when used with 1G advertisement */
7058		if (phy->speed_cap_mask &
7059			(PORT_HW_CFG_SPEED_CAPABILITY_D0_1G |
7060			 PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))
7061			val |= (1<<5);
7062		DP(NETIF_MSG_LINK, "807x autoneg val = 0x%x\n", val);
7063	}
7064
7065	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV, val);
7066	bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8073_2_5G, &tmp1);
7067
7068	if (((phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G) &&
7069	     (phy->req_line_speed == SPEED_AUTO_NEG)) ||
7070	    (phy->req_line_speed == SPEED_2500)) {
7071		u16 phy_ver;
7072		/* Allow 2.5G for A1 and above */
7073		bnx2x_cl45_read(bp, phy,
7074				MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_CHIP_REV,
7075				&phy_ver);
7076		DP(NETIF_MSG_LINK, "Add 2.5G\n");
7077		if (phy_ver > 0)
7078			tmp1 |= 1;
7079		else
7080			tmp1 &= 0xfffe;
7081	} else {
7082		DP(NETIF_MSG_LINK, "Disable 2.5G\n");
7083		tmp1 &= 0xfffe;
7084	}
7085
7086	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8073_2_5G, tmp1);
7087	/* Add support for CL37 (passive mode) II */
7088
7089	bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, &tmp1);
7090	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD,
7091			 (tmp1 | ((phy->req_duplex == DUPLEX_FULL) ?
7092				  0x20 : 0x40)));
7093
7094	/* Add support for CL37 (passive mode) III */
7095	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1000);
7096
7097	/*
7098	 * The SNR will improve about 2db by changing BW and FEE main
7099	 * tap. Rest commands are executed after link is up
7100	 * Change FFE main cursor to 5 in EDC register
7101	 */
7102	if (bnx2x_8073_is_snr_needed(bp, phy))
7103		bnx2x_cl45_write(bp, phy,
7104				 MDIO_PMA_DEVAD, MDIO_PMA_REG_EDC_FFE_MAIN,
7105				 0xFB0C);
7106
7107	/* Enable FEC (Forware Error Correction) Request in the AN */
7108	bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV2, &tmp1);
7109	tmp1 |= (1<<15);
7110	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV2, tmp1);
7111
7112	bnx2x_ext_phy_set_pause(params, phy, vars);
7113
7114	/* Restart autoneg */
7115	msleep(500);
7116	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x1200);
7117	DP(NETIF_MSG_LINK, "807x Autoneg Restart: Advertise 1G=%x, 10G=%x\n",
7118		   ((val & (1<<5)) > 0), ((val & (1<<7)) > 0));
7119	return 0;
7120}
7121
7122static u8 bnx2x_8073_read_status(struct bnx2x_phy *phy,
7123				 struct link_params *params,
7124				 struct link_vars *vars)
7125{
7126	struct bnx2x *bp = params->bp;
7127	u8 link_up = 0;
7128	u16 val1, val2;
7129	u16 link_status = 0;
7130	u16 an1000_status = 0;
7131
7132	bnx2x_cl45_read(bp, phy,
7133			MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val1);
7134
7135	DP(NETIF_MSG_LINK, "8703 LASI status 0x%x\n", val1);
7136
7137	/* clear the interrupt LASI status register */
7138	bnx2x_cl45_read(bp, phy,
7139			MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &val2);
7140	bnx2x_cl45_read(bp, phy,
7141			MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &val1);
7142	DP(NETIF_MSG_LINK, "807x PCS status 0x%x->0x%x\n", val2, val1);
7143	/* Clear MSG-OUT */
7144	bnx2x_cl45_read(bp, phy,
7145			MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &val1);
7146
7147	/* Check the LASI */
7148	bnx2x_cl45_read(bp, phy,
7149			MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &val2);
7150
7151	DP(NETIF_MSG_LINK, "KR 0x9003 0x%x\n", val2);
7152
7153	/* Check the link status */
7154	bnx2x_cl45_read(bp, phy,
7155			MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &val2);
7156	DP(NETIF_MSG_LINK, "KR PCS status 0x%x\n", val2);
7157
7158	bnx2x_cl45_read(bp, phy,
7159			MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val2);
7160	bnx2x_cl45_read(bp, phy,
7161			MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val1);
7162	link_up = ((val1 & 4) == 4);
7163	DP(NETIF_MSG_LINK, "PMA_REG_STATUS=0x%x\n", val1);
7164
7165	if (link_up &&
7166	     ((phy->req_line_speed != SPEED_10000))) {
7167		if (bnx2x_8073_xaui_wa(bp, phy) != 0)
7168			return 0;
7169	}
7170	bnx2x_cl45_read(bp, phy,
7171			MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &an1000_status);
7172	bnx2x_cl45_read(bp, phy,
7173			MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &an1000_status);
7174
7175	/* Check the link status on 1.1.2 */
7176	bnx2x_cl45_read(bp, phy,
7177			MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val2);
7178	bnx2x_cl45_read(bp, phy,
7179			MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val1);
7180	DP(NETIF_MSG_LINK, "KR PMA status 0x%x->0x%x,"
7181		   "an_link_status=0x%x\n", val2, val1, an1000_status);
7182
7183	link_up = (((val1 & 4) == 4) || (an1000_status & (1<<1)));
7184	if (link_up && bnx2x_8073_is_snr_needed(bp, phy)) {
7185		/*
7186		 * The SNR will improve about 2dbby changing the BW and FEE main
7187		 * tap. The 1st write to change FFE main tap is set before
7188		 * restart AN. Change PLL Bandwidth in EDC register
7189		 */
7190		bnx2x_cl45_write(bp, phy,
7191				 MDIO_PMA_DEVAD, MDIO_PMA_REG_PLL_BANDWIDTH,
7192				 0x26BC);
7193
7194		/* Change CDR Bandwidth in EDC register */
7195		bnx2x_cl45_write(bp, phy,
7196				 MDIO_PMA_DEVAD, MDIO_PMA_REG_CDR_BANDWIDTH,
7197				 0x0333);
7198	}
7199	bnx2x_cl45_read(bp, phy,
7200			MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_SPEED_LINK_STATUS,
7201			&link_status);
7202
7203	/* Bits 0..2 --> speed detected, bits 13..15--> link is down */
7204	if ((link_status & (1<<2)) && (!(link_status & (1<<15)))) {
7205		link_up = 1;
7206		vars->line_speed = SPEED_10000;
7207		DP(NETIF_MSG_LINK, "port %x: External link up in 10G\n",
7208			   params->port);
7209	} else if ((link_status & (1<<1)) && (!(link_status & (1<<14)))) {
7210		link_up = 1;
7211		vars->line_speed = SPEED_2500;
7212		DP(NETIF_MSG_LINK, "port %x: External link up in 2.5G\n",
7213			   params->port);
7214	} else if ((link_status & (1<<0)) && (!(link_status & (1<<13)))) {
7215		link_up = 1;
7216		vars->line_speed = SPEED_1000;
7217		DP(NETIF_MSG_LINK, "port %x: External link up in 1G\n",
7218			   params->port);
7219	} else {
7220		link_up = 0;
7221		DP(NETIF_MSG_LINK, "port %x: External link is down\n",
7222			   params->port);
7223	}
7224
7225	if (link_up) {
7226		/* Swap polarity if required */
7227		if (params->lane_config &
7228		    PORT_HW_CFG_SWAP_PHY_POLARITY_ENABLED) {
7229			/* Configure the 8073 to swap P and N of the KR lines */
7230			bnx2x_cl45_read(bp, phy,
7231					MDIO_XS_DEVAD,
7232					MDIO_XS_REG_8073_RX_CTRL_PCIE, &val1);
7233			/*
7234			 * Set bit 3 to invert Rx in 1G mode and clear this bit
7235			 * when it`s in 10G mode.
7236			 */
7237			if (vars->line_speed == SPEED_1000) {
7238				DP(NETIF_MSG_LINK, "Swapping 1G polarity for"
7239					      "the 8073\n");
7240				val1 |= (1<<3);
7241			} else
7242				val1 &= ~(1<<3);
7243
7244			bnx2x_cl45_write(bp, phy,
7245					 MDIO_XS_DEVAD,
7246					 MDIO_XS_REG_8073_RX_CTRL_PCIE,
7247					 val1);
7248		}
7249		bnx2x_ext_phy_10G_an_resolve(bp, phy, vars);
7250		bnx2x_8073_resolve_fc(phy, params, vars);
7251		vars->duplex = DUPLEX_FULL;
7252	}
7253	return link_up;
7254}
7255
7256static void bnx2x_8073_link_reset(struct bnx2x_phy *phy,
7257				  struct link_params *params)
7258{
7259	struct bnx2x *bp = params->bp;
7260	u8 gpio_port;
7261	if (CHIP_IS_E2(bp))
7262		gpio_port = BP_PATH(bp);
7263	else
7264		gpio_port = params->port;
7265	DP(NETIF_MSG_LINK, "Setting 8073 port %d into low power mode\n",
7266	   gpio_port);
7267	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
7268		       MISC_REGISTERS_GPIO_OUTPUT_LOW,
7269		       gpio_port);
7270}
7271
7272/******************************************************************/
7273/*			BCM8705 PHY SECTION			  */
7274/******************************************************************/
7275static int bnx2x_8705_config_init(struct bnx2x_phy *phy,
7276				  struct link_params *params,
7277				  struct link_vars *vars)
7278{
7279	struct bnx2x *bp = params->bp;
7280	DP(NETIF_MSG_LINK, "init 8705\n");
7281	/* Restore normal power mode*/
7282	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
7283		       MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
7284	/* HW reset */
7285	bnx2x_ext_phy_hw_reset(bp, params->port);
7286	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0xa040);
7287	bnx2x_wait_reset_complete(bp, phy, params);
7288
7289	bnx2x_cl45_write(bp, phy,
7290			 MDIO_PMA_DEVAD, MDIO_PMA_REG_MISC_CTRL, 0x8288);
7291	bnx2x_cl45_write(bp, phy,
7292			 MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, 0x7fbf);
7293	bnx2x_cl45_write(bp, phy,
7294			 MDIO_PMA_DEVAD, MDIO_PMA_REG_CMU_PLL_BYPASS, 0x0100);
7295	bnx2x_cl45_write(bp, phy,
7296			 MDIO_WIS_DEVAD, MDIO_WIS_REG_LASI_CNTL, 0x1);
7297	/* BCM8705 doesn't have microcode, hence the 0 */
7298	bnx2x_save_spirom_version(bp, params->port, params->shmem_base, 0);
7299	return 0;
7300}
7301
7302static u8 bnx2x_8705_read_status(struct bnx2x_phy *phy,
7303				 struct link_params *params,
7304				 struct link_vars *vars)
7305{
7306	u8 link_up = 0;
7307	u16 val1, rx_sd;
7308	struct bnx2x *bp = params->bp;
7309	DP(NETIF_MSG_LINK, "read status 8705\n");
7310	bnx2x_cl45_read(bp, phy,
7311		      MDIO_WIS_DEVAD, MDIO_WIS_REG_LASI_STATUS, &val1);
7312	DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1);
7313
7314	bnx2x_cl45_read(bp, phy,
7315		      MDIO_WIS_DEVAD, MDIO_WIS_REG_LASI_STATUS, &val1);
7316	DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1);
7317
7318	bnx2x_cl45_read(bp, phy,
7319		      MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_SD, &rx_sd);
7320
7321	bnx2x_cl45_read(bp, phy,
7322		      MDIO_PMA_DEVAD, 0xc809, &val1);
7323	bnx2x_cl45_read(bp, phy,
7324		      MDIO_PMA_DEVAD, 0xc809, &val1);
7325
7326	DP(NETIF_MSG_LINK, "8705 1.c809 val=0x%x\n", val1);
7327	link_up = ((rx_sd & 0x1) && (val1 & (1<<9)) && ((val1 & (1<<8)) == 0));
7328	if (link_up) {
7329		vars->line_speed = SPEED_10000;
7330		bnx2x_ext_phy_resolve_fc(phy, params, vars);
7331	}
7332	return link_up;
7333}
7334
7335/******************************************************************/
7336/*			SFP+ module Section			  */
7337/******************************************************************/
7338static void bnx2x_set_disable_pmd_transmit(struct link_params *params,
7339					   struct bnx2x_phy *phy,
7340					   u8 pmd_dis)
7341{
7342	struct bnx2x *bp = params->bp;
7343	/*
7344	 * Disable transmitter only for bootcodes which can enable it afterwards
7345	 * (for D3 link)
7346	 */
7347	if (pmd_dis) {
7348		if (params->feature_config_flags &
7349		     FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED)
7350			DP(NETIF_MSG_LINK, "Disabling PMD transmitter\n");
7351		else {
7352			DP(NETIF_MSG_LINK, "NOT disabling PMD transmitter\n");
7353			return;
7354		}
7355	} else
7356		DP(NETIF_MSG_LINK, "Enabling PMD transmitter\n");
7357	bnx2x_cl45_write(bp, phy,
7358			 MDIO_PMA_DEVAD,
7359			 MDIO_PMA_REG_TX_DISABLE, pmd_dis);
7360}
7361
7362static u8 bnx2x_get_gpio_port(struct link_params *params)
7363{
7364	u8 gpio_port;
7365	u32 swap_val, swap_override;
7366	struct bnx2x *bp = params->bp;
7367	if (CHIP_IS_E2(bp))
7368		gpio_port = BP_PATH(bp);
7369	else
7370		gpio_port = params->port;
7371	swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
7372	swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
7373	return gpio_port ^ (swap_val && swap_override);
7374}
7375
7376static void bnx2x_sfp_e1e2_set_transmitter(struct link_params *params,
7377					   struct bnx2x_phy *phy,
7378					   u8 tx_en)
7379{
7380	u16 val;
7381	u8 port = params->port;
7382	struct bnx2x *bp = params->bp;
7383	u32 tx_en_mode;
7384
7385	/* Disable/Enable transmitter ( TX laser of the SFP+ module.)*/
7386	tx_en_mode = REG_RD(bp, params->shmem_base +
7387			    offsetof(struct shmem_region,
7388				     dev_info.port_hw_config[port].sfp_ctrl)) &
7389		PORT_HW_CFG_TX_LASER_MASK;
7390	DP(NETIF_MSG_LINK, "Setting transmitter tx_en=%x for port %x "
7391			   "mode = %x\n", tx_en, port, tx_en_mode);
7392	switch (tx_en_mode) {
7393	case PORT_HW_CFG_TX_LASER_MDIO:
7394
7395		bnx2x_cl45_read(bp, phy,
7396				MDIO_PMA_DEVAD,
7397				MDIO_PMA_REG_PHY_IDENTIFIER,
7398				&val);
7399
7400		if (tx_en)
7401			val &= ~(1<<15);
7402		else
7403			val |= (1<<15);
7404
7405		bnx2x_cl45_write(bp, phy,
7406				 MDIO_PMA_DEVAD,
7407				 MDIO_PMA_REG_PHY_IDENTIFIER,
7408				 val);
7409	break;
7410	case PORT_HW_CFG_TX_LASER_GPIO0:
7411	case PORT_HW_CFG_TX_LASER_GPIO1:
7412	case PORT_HW_CFG_TX_LASER_GPIO2:
7413	case PORT_HW_CFG_TX_LASER_GPIO3:
7414	{
7415		u16 gpio_pin;
7416		u8 gpio_port, gpio_mode;
7417		if (tx_en)
7418			gpio_mode = MISC_REGISTERS_GPIO_OUTPUT_HIGH;
7419		else
7420			gpio_mode = MISC_REGISTERS_GPIO_OUTPUT_LOW;
7421
7422		gpio_pin = tx_en_mode - PORT_HW_CFG_TX_LASER_GPIO0;
7423		gpio_port = bnx2x_get_gpio_port(params);
7424		bnx2x_set_gpio(bp, gpio_pin, gpio_mode, gpio_port);
7425		break;
7426	}
7427	default:
7428		DP(NETIF_MSG_LINK, "Invalid TX_LASER_MDIO 0x%x\n", tx_en_mode);
7429		break;
7430	}
7431}
7432
7433static void bnx2x_sfp_set_transmitter(struct link_params *params,
7434				      struct bnx2x_phy *phy,
7435				      u8 tx_en)
7436{
7437	struct bnx2x *bp = params->bp;
7438	DP(NETIF_MSG_LINK, "Setting SFP+ transmitter to %d\n", tx_en);
7439	if (CHIP_IS_E3(bp))
7440		bnx2x_sfp_e3_set_transmitter(params, phy, tx_en);
7441	else
7442		bnx2x_sfp_e1e2_set_transmitter(params, phy, tx_en);
7443}
7444
7445static int bnx2x_8726_read_sfp_module_eeprom(struct bnx2x_phy *phy,
7446					     struct link_params *params,
7447					     u16 addr, u8 byte_cnt, u8 *o_buf)
7448{
7449	struct bnx2x *bp = params->bp;
7450	u16 val = 0;
7451	u16 i;
7452	if (byte_cnt > 16) {
7453		DP(NETIF_MSG_LINK,
7454		   "Reading from eeprom is limited to 0xf\n");
7455		return -EINVAL;
7456	}
7457	/* Set the read command byte count */
7458	bnx2x_cl45_write(bp, phy,
7459			 MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_BYTE_CNT,
7460			 (byte_cnt | 0xa000));
7461
7462	/* Set the read command address */
7463	bnx2x_cl45_write(bp, phy,
7464			 MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_MEM_ADDR,
7465			 addr);
7466
7467	/* Activate read command */
7468	bnx2x_cl45_write(bp, phy,
7469			 MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
7470			 0x2c0f);
7471
7472	/* Wait up to 500us for command complete status */
7473	for (i = 0; i < 100; i++) {
7474		bnx2x_cl45_read(bp, phy,
7475				MDIO_PMA_DEVAD,
7476				MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
7477		if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
7478		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE)
7479			break;
7480		udelay(5);
7481	}
7482
7483	if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) !=
7484		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE) {
7485		DP(NETIF_MSG_LINK,
7486			 "Got bad status 0x%x when reading from SFP+ EEPROM\n",
7487			 (val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK));
7488		return -EINVAL;
7489	}
7490
7491	/* Read the buffer */
7492	for (i = 0; i < byte_cnt; i++) {
7493		bnx2x_cl45_read(bp, phy,
7494				MDIO_PMA_DEVAD,
7495				MDIO_PMA_REG_8726_TWO_WIRE_DATA_BUF + i, &val);
7496		o_buf[i] = (u8)(val & MDIO_PMA_REG_8726_TWO_WIRE_DATA_MASK);
7497	}
7498
7499	for (i = 0; i < 100; i++) {
7500		bnx2x_cl45_read(bp, phy,
7501				MDIO_PMA_DEVAD,
7502				MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
7503		if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
7504		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE)
7505			return 0;
7506		msleep(1);
7507	}
7508	return -EINVAL;
7509}
7510
7511static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,
7512						 struct link_params *params,
7513						 u16 addr, u8 byte_cnt,
7514						 u8 *o_buf)
7515{
7516	int rc = 0;
7517	u8 i, j = 0, cnt = 0;
7518	u32 data_array[4];
7519	u16 addr32;
7520	struct bnx2x *bp = params->bp;
7521	/*DP(NETIF_MSG_LINK, "bnx2x_direct_read_sfp_module_eeprom:"
7522					" addr %d, cnt %d\n",
7523					addr, byte_cnt);*/
7524	if (byte_cnt > 16) {
7525		DP(NETIF_MSG_LINK,
7526		   "Reading from eeprom is limited to 16 bytes\n");
7527		return -EINVAL;
7528	}
7529
7530	/* 4 byte aligned address */
7531	addr32 = addr & (~0x3);
7532	do {
7533		rc = bnx2x_bsc_read(params, phy, 0xa0, addr32, 0, byte_cnt,
7534				    data_array);
7535	} while ((rc != 0) && (++cnt < I2C_WA_RETRY_CNT));
7536
7537	if (rc == 0) {
7538		for (i = (addr - addr32); i < byte_cnt + (addr - addr32); i++) {
7539			o_buf[j] = *((u8 *)data_array + i);
7540			j++;
7541		}
7542	}
7543
7544	return rc;
7545}
7546
7547static int bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy,
7548					     struct link_params *params,
7549					     u16 addr, u8 byte_cnt, u8 *o_buf)
7550{
7551	struct bnx2x *bp = params->bp;
7552	u16 val, i;
7553
7554	if (byte_cnt > 16) {
7555		DP(NETIF_MSG_LINK,
7556		   "Reading from eeprom is limited to 0xf\n");
7557		return -EINVAL;
7558	}
7559
7560	/* Need to read from 1.8000 to clear it */
7561	bnx2x_cl45_read(bp, phy,
7562			MDIO_PMA_DEVAD,
7563			MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
7564			&val);
7565
7566	/* Set the read command byte count */
7567	bnx2x_cl45_write(bp, phy,
7568			 MDIO_PMA_DEVAD,
7569			 MDIO_PMA_REG_SFP_TWO_WIRE_BYTE_CNT,
7570			 ((byte_cnt < 2) ? 2 : byte_cnt));
7571
7572	/* Set the read command address */
7573	bnx2x_cl45_write(bp, phy,
7574			 MDIO_PMA_DEVAD,
7575			 MDIO_PMA_REG_SFP_TWO_WIRE_MEM_ADDR,
7576			 addr);
7577	/* Set the destination address */
7578	bnx2x_cl45_write(bp, phy,
7579			 MDIO_PMA_DEVAD,
7580			 0x8004,
7581			 MDIO_PMA_REG_8727_TWO_WIRE_DATA_BUF);
7582
7583	/* Activate read command */
7584	bnx2x_cl45_write(bp, phy,
7585			 MDIO_PMA_DEVAD,
7586			 MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
7587			 0x8002);
7588	/*
7589	 * Wait appropriate time for two-wire command to finish before
7590	 * polling the status register
7591	 */
7592	msleep(1);
7593
7594	/* Wait up to 500us for command complete status */
7595	for (i = 0; i < 100; i++) {
7596		bnx2x_cl45_read(bp, phy,
7597				MDIO_PMA_DEVAD,
7598				MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
7599		if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
7600		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE)
7601			break;
7602		udelay(5);
7603	}
7604
7605	if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) !=
7606		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE) {
7607		DP(NETIF_MSG_LINK,
7608			 "Got bad status 0x%x when reading from SFP+ EEPROM\n",
7609			 (val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK));
7610		return -EFAULT;
7611	}
7612
7613	/* Read the buffer */
7614	for (i = 0; i < byte_cnt; i++) {
7615		bnx2x_cl45_read(bp, phy,
7616				MDIO_PMA_DEVAD,
7617				MDIO_PMA_REG_8727_TWO_WIRE_DATA_BUF + i, &val);
7618		o_buf[i] = (u8)(val & MDIO_PMA_REG_8727_TWO_WIRE_DATA_MASK);
7619	}
7620
7621	for (i = 0; i < 100; i++) {
7622		bnx2x_cl45_read(bp, phy,
7623				MDIO_PMA_DEVAD,
7624				MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
7625		if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
7626		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE)
7627			return 0;
7628		msleep(1);
7629	}
7630
7631	return -EINVAL;
7632}
7633
7634int bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
7635				 struct link_params *params, u16 addr,
7636				 u8 byte_cnt, u8 *o_buf)
7637{
7638	int rc = -EINVAL;
7639	switch (phy->type) {
7640	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
7641		rc = bnx2x_8726_read_sfp_module_eeprom(phy, params, addr,
7642						       byte_cnt, o_buf);
7643	break;
7644	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
7645	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
7646		rc = bnx2x_8727_read_sfp_module_eeprom(phy, params, addr,
7647						       byte_cnt, o_buf);
7648	break;
7649	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
7650		rc = bnx2x_warpcore_read_sfp_module_eeprom(phy, params, addr,
7651							   byte_cnt, o_buf);
7652	break;
7653	}
7654	return rc;
7655}
7656
7657static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
7658			      struct link_params *params,
7659			      u16 *edc_mode)
7660{
7661	struct bnx2x *bp = params->bp;
7662	u32 sync_offset = 0, phy_idx, media_types;
7663	u8 val, check_limiting_mode = 0;
7664	*edc_mode = EDC_MODE_LIMITING;
7665
7666	phy->media_type = ETH_PHY_UNSPECIFIED;
7667	/* First check for copper cable */
7668	if (bnx2x_read_sfp_module_eeprom(phy,
7669					 params,
7670					 SFP_EEPROM_CON_TYPE_ADDR,
7671					 1,
7672					 &val) != 0) {
7673		DP(NETIF_MSG_LINK, "Failed to read from SFP+ module EEPROM\n");
7674		return -EINVAL;
7675	}
7676
7677	switch (val) {
7678	case SFP_EEPROM_CON_TYPE_VAL_COPPER:
7679	{
7680		u8 copper_module_type;
7681		phy->media_type = ETH_PHY_DA_TWINAX;
7682		/*
7683		 * Check if its active cable (includes SFP+ module)
7684		 * of passive cable
7685		 */
7686		if (bnx2x_read_sfp_module_eeprom(phy,
7687					       params,
7688					       SFP_EEPROM_FC_TX_TECH_ADDR,
7689					       1,
7690					       &copper_module_type) != 0) {
7691			DP(NETIF_MSG_LINK,
7692				"Failed to read copper-cable-type"
7693				" from SFP+ EEPROM\n");
7694			return -EINVAL;
7695		}
7696
7697		if (copper_module_type &
7698		    SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_ACTIVE) {
7699			DP(NETIF_MSG_LINK, "Active Copper cable detected\n");
7700			check_limiting_mode = 1;
7701		} else if (copper_module_type &
7702			SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE) {
7703				DP(NETIF_MSG_LINK,
7704				   "Passive Copper cable detected\n");
7705				*edc_mode =
7706				      EDC_MODE_PASSIVE_DAC;
7707		} else {
7708			DP(NETIF_MSG_LINK,
7709			   "Unknown copper-cable-type 0x%x !!!\n",
7710			   copper_module_type);
7711			return -EINVAL;
7712		}
7713		break;
7714	}
7715	case SFP_EEPROM_CON_TYPE_VAL_LC:
7716		phy->media_type = ETH_PHY_SFP_FIBER;
7717		DP(NETIF_MSG_LINK, "Optic module detected\n");
7718		check_limiting_mode = 1;
7719		break;
7720	default:
7721		DP(NETIF_MSG_LINK, "Unable to determine module type 0x%x !!!\n",
7722			 val);
7723		return -EINVAL;
7724	}
7725	sync_offset = params->shmem_base +
7726		offsetof(struct shmem_region,
7727			 dev_info.port_hw_config[params->port].media_type);
7728	media_types = REG_RD(bp, sync_offset);
7729	/* Update media type for non-PMF sync */
7730	for (phy_idx = INT_PHY; phy_idx < MAX_PHYS; phy_idx++) {
7731		if (&(params->phy[phy_idx]) == phy) {
7732			media_types &= ~(PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK <<
7733				(PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT * phy_idx));
7734			media_types |= ((phy->media_type &
7735					PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK) <<
7736				(PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT * phy_idx));
7737			break;
7738		}
7739	}
7740	REG_WR(bp, sync_offset, media_types);
7741	if (check_limiting_mode) {
7742		u8 options[SFP_EEPROM_OPTIONS_SIZE];
7743		if (bnx2x_read_sfp_module_eeprom(phy,
7744						 params,
7745						 SFP_EEPROM_OPTIONS_ADDR,
7746						 SFP_EEPROM_OPTIONS_SIZE,
7747						 options) != 0) {
7748			DP(NETIF_MSG_LINK,
7749			   "Failed to read Option field from module EEPROM\n");
7750			return -EINVAL;
7751		}
7752		if ((options[0] & SFP_EEPROM_OPTIONS_LINEAR_RX_OUT_MASK))
7753			*edc_mode = EDC_MODE_LINEAR;
7754		else
7755			*edc_mode = EDC_MODE_LIMITING;
7756	}
7757	DP(NETIF_MSG_LINK, "EDC mode is set to 0x%x\n", *edc_mode);
7758	return 0;
7759}
7760/*
7761 * This function read the relevant field from the module (SFP+), and verify it
7762 * is compliant with this board
7763 */
7764static int bnx2x_verify_sfp_module(struct bnx2x_phy *phy,
7765				   struct link_params *params)
7766{
7767	struct bnx2x *bp = params->bp;
7768	u32 val, cmd;
7769	u32 fw_resp, fw_cmd_param;
7770	char vendor_name[SFP_EEPROM_VENDOR_NAME_SIZE+1];
7771	char vendor_pn[SFP_EEPROM_PART_NO_SIZE+1];
7772	phy->flags &= ~FLAGS_SFP_NOT_APPROVED;
7773	val = REG_RD(bp, params->shmem_base +
7774			 offsetof(struct shmem_region, dev_info.
7775				  port_feature_config[params->port].config));
7776	if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
7777	    PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_NO_ENFORCEMENT) {
7778		DP(NETIF_MSG_LINK, "NOT enforcing module verification\n");
7779		return 0;
7780	}
7781
7782	if (params->feature_config_flags &
7783	    FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY) {
7784		/* Use specific phy request */
7785		cmd = DRV_MSG_CODE_VRFY_SPECIFIC_PHY_OPT_MDL;
7786	} else if (params->feature_config_flags &
7787		   FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY) {
7788		/* Use first phy request only in case of non-dual media*/
7789		if (DUAL_MEDIA(params)) {
7790			DP(NETIF_MSG_LINK,
7791			   "FW does not support OPT MDL verification\n");
7792			return -EINVAL;
7793		}
7794		cmd = DRV_MSG_CODE_VRFY_FIRST_PHY_OPT_MDL;
7795	} else {
7796		/* No support in OPT MDL detection */
7797		DP(NETIF_MSG_LINK,
7798		   "FW does not support OPT MDL verification\n");
7799		return -EINVAL;
7800	}
7801
7802	fw_cmd_param = FW_PARAM_SET(phy->addr, phy->type, phy->mdio_ctrl);
7803	fw_resp = bnx2x_fw_command(bp, cmd, fw_cmd_param);
7804	if (fw_resp == FW_MSG_CODE_VRFY_OPT_MDL_SUCCESS) {
7805		DP(NETIF_MSG_LINK, "Approved module\n");
7806		return 0;
7807	}
7808
7809	/* format the warning message */
7810	if (bnx2x_read_sfp_module_eeprom(phy,
7811					 params,
7812					 SFP_EEPROM_VENDOR_NAME_ADDR,
7813					 SFP_EEPROM_VENDOR_NAME_SIZE,
7814					 (u8 *)vendor_name))
7815		vendor_name[0] = '\0';
7816	else
7817		vendor_name[SFP_EEPROM_VENDOR_NAME_SIZE] = '\0';
7818	if (bnx2x_read_sfp_module_eeprom(phy,
7819					 params,
7820					 SFP_EEPROM_PART_NO_ADDR,
7821					 SFP_EEPROM_PART_NO_SIZE,
7822					 (u8 *)vendor_pn))
7823		vendor_pn[0] = '\0';
7824	else
7825		vendor_pn[SFP_EEPROM_PART_NO_SIZE] = '\0';
7826
7827	netdev_err(bp->dev,  "Warning: Unqualified SFP+ module detected,"
7828			      " Port %d from %s part number %s\n",
7829			 params->port, vendor_name, vendor_pn);
7830	phy->flags |= FLAGS_SFP_NOT_APPROVED;
7831	return -EINVAL;
7832}
7833
7834static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
7835						 struct link_params *params)
7836
7837{
7838	u8 val;
7839	struct bnx2x *bp = params->bp;
7840	u16 timeout;
7841	/*
7842	 * Initialization time after hot-plug may take up to 300ms for
7843	 * some phys type ( e.g. JDSU )
7844	 */
7845
7846	for (timeout = 0; timeout < 60; timeout++) {
7847		if (bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val)
7848		    == 0) {
7849			DP(NETIF_MSG_LINK,
7850			   "SFP+ module initialization took %d ms\n",
7851			   timeout * 5);
7852			return 0;
7853		}
7854		msleep(5);
7855	}
7856	return -EINVAL;
7857}
7858
7859static void bnx2x_8727_power_module(struct bnx2x *bp,
7860				    struct bnx2x_phy *phy,
7861				    u8 is_power_up) {
7862	/* Make sure GPIOs are not using for LED mode */
7863	u16 val;
7864	/*
7865	 * In the GPIO register, bit 4 is use to determine if the GPIOs are
7866	 * operating as INPUT or as OUTPUT. Bit 1 is for input, and 0 for
7867	 * output
7868	 * Bits 0-1 determine the GPIOs value for OUTPUT in case bit 4 val is 0
7869	 * Bits 8-9 determine the GPIOs value for INPUT in case bit 4 val is 1
7870	 * where the 1st bit is the over-current(only input), and 2nd bit is
7871	 * for power( only output )
7872	 *
7873	 * In case of NOC feature is disabled and power is up, set GPIO control
7874	 *  as input to enable listening of over-current indication
7875	 */
7876	if (phy->flags & FLAGS_NOC)
7877		return;
7878	if (is_power_up)
7879		val = (1<<4);
7880	else
7881		/*
7882		 * Set GPIO control to OUTPUT, and set the power bit
7883		 * to according to the is_power_up
7884		 */
7885		val = (1<<1);
7886
7887	bnx2x_cl45_write(bp, phy,
7888			 MDIO_PMA_DEVAD,
7889			 MDIO_PMA_REG_8727_GPIO_CTRL,
7890			 val);
7891}
7892
7893static int bnx2x_8726_set_limiting_mode(struct bnx2x *bp,
7894					struct bnx2x_phy *phy,
7895					u16 edc_mode)
7896{
7897	u16 cur_limiting_mode;
7898
7899	bnx2x_cl45_read(bp, phy,
7900			MDIO_PMA_DEVAD,
7901			MDIO_PMA_REG_ROM_VER2,
7902			&cur_limiting_mode);
7903	DP(NETIF_MSG_LINK, "Current Limiting mode is 0x%x\n",
7904		 cur_limiting_mode);
7905
7906	if (edc_mode == EDC_MODE_LIMITING) {
7907		DP(NETIF_MSG_LINK, "Setting LIMITING MODE\n");
7908		bnx2x_cl45_write(bp, phy,
7909				 MDIO_PMA_DEVAD,
7910				 MDIO_PMA_REG_ROM_VER2,
7911				 EDC_MODE_LIMITING);
7912	} else { /* LRM mode ( default )*/
7913
7914		DP(NETIF_MSG_LINK, "Setting LRM MODE\n");
7915
7916		/*
7917		 * Changing to LRM mode takes quite few seconds. So do it only
7918		 * if current mode is limiting (default is LRM)
7919		 */
7920		if (cur_limiting_mode != EDC_MODE_LIMITING)
7921			return 0;
7922
7923		bnx2x_cl45_write(bp, phy,
7924				 MDIO_PMA_DEVAD,
7925				 MDIO_PMA_REG_LRM_MODE,
7926				 0);
7927		bnx2x_cl45_write(bp, phy,
7928				 MDIO_PMA_DEVAD,
7929				 MDIO_PMA_REG_ROM_VER2,
7930				 0x128);
7931		bnx2x_cl45_write(bp, phy,
7932				 MDIO_PMA_DEVAD,
7933				 MDIO_PMA_REG_MISC_CTRL0,
7934				 0x4008);
7935		bnx2x_cl45_write(bp, phy,
7936				 MDIO_PMA_DEVAD,
7937				 MDIO_PMA_REG_LRM_MODE,
7938				 0xaaaa);
7939	}
7940	return 0;
7941}
7942
7943static int bnx2x_8727_set_limiting_mode(struct bnx2x *bp,
7944					struct bnx2x_phy *phy,
7945					u16 edc_mode)
7946{
7947	u16 phy_identifier;
7948	u16 rom_ver2_val;
7949	bnx2x_cl45_read(bp, phy,
7950			MDIO_PMA_DEVAD,
7951			MDIO_PMA_REG_PHY_IDENTIFIER,
7952			&phy_identifier);
7953
7954	bnx2x_cl45_write(bp, phy,
7955			 MDIO_PMA_DEVAD,
7956			 MDIO_PMA_REG_PHY_IDENTIFIER,
7957			 (phy_identifier & ~(1<<9)));
7958
7959	bnx2x_cl45_read(bp, phy,
7960			MDIO_PMA_DEVAD,
7961			MDIO_PMA_REG_ROM_VER2,
7962			&rom_ver2_val);
7963	/* Keep the MSB 8-bits, and set the LSB 8-bits with the edc_mode */
7964	bnx2x_cl45_write(bp, phy,
7965			 MDIO_PMA_DEVAD,
7966			 MDIO_PMA_REG_ROM_VER2,
7967			 (rom_ver2_val & 0xff00) | (edc_mode & 0x00ff));
7968
7969	bnx2x_cl45_write(bp, phy,
7970			 MDIO_PMA_DEVAD,
7971			 MDIO_PMA_REG_PHY_IDENTIFIER,
7972			 (phy_identifier | (1<<9)));
7973
7974	return 0;
7975}
7976
7977static void bnx2x_8727_specific_func(struct bnx2x_phy *phy,
7978				     struct link_params *params,
7979				     u32 action)
7980{
7981	struct bnx2x *bp = params->bp;
7982
7983	switch (action) {
7984	case DISABLE_TX:
7985		bnx2x_sfp_set_transmitter(params, phy, 0);
7986		break;
7987	case ENABLE_TX:
7988		if (!(phy->flags & FLAGS_SFP_NOT_APPROVED))
7989			bnx2x_sfp_set_transmitter(params, phy, 1);
7990		break;
7991	default:
7992		DP(NETIF_MSG_LINK, "Function 0x%x not supported by 8727\n",
7993		   action);
7994		return;
7995	}
7996}
7997
7998static void bnx2x_set_e1e2_module_fault_led(struct link_params *params,
7999					   u8 gpio_mode)
8000{
8001	struct bnx2x *bp = params->bp;
8002
8003	u32 fault_led_gpio = REG_RD(bp, params->shmem_base +
8004			    offsetof(struct shmem_region,
8005			dev_info.port_hw_config[params->port].sfp_ctrl)) &
8006		PORT_HW_CFG_FAULT_MODULE_LED_MASK;
8007	switch (fault_led_gpio) {
8008	case PORT_HW_CFG_FAULT_MODULE_LED_DISABLED:
8009		return;
8010	case PORT_HW_CFG_FAULT_MODULE_LED_GPIO0:
8011	case PORT_HW_CFG_FAULT_MODULE_LED_GPIO1:
8012	case PORT_HW_CFG_FAULT_MODULE_LED_GPIO2:
8013	case PORT_HW_CFG_FAULT_MODULE_LED_GPIO3:
8014	{
8015		u8 gpio_port = bnx2x_get_gpio_port(params);
8016		u16 gpio_pin = fault_led_gpio -
8017			PORT_HW_CFG_FAULT_MODULE_LED_GPIO0;
8018		DP(NETIF_MSG_LINK, "Set fault module-detected led "
8019				   "pin %x port %x mode %x\n",
8020			       gpio_pin, gpio_port, gpio_mode);
8021		bnx2x_set_gpio(bp, gpio_pin, gpio_mode, gpio_port);
8022	}
8023	break;
8024	default:
8025		DP(NETIF_MSG_LINK, "Error: Invalid fault led mode 0x%x\n",
8026			       fault_led_gpio);
8027	}
8028}
8029
8030static void bnx2x_set_e3_module_fault_led(struct link_params *params,
8031					  u8 gpio_mode)
8032{
8033	u32 pin_cfg;
8034	u8 port = params->port;
8035	struct bnx2x *bp = params->bp;
8036	pin_cfg = (REG_RD(bp, params->shmem_base +
8037			 offsetof(struct shmem_region,
8038				  dev_info.port_hw_config[port].e3_sfp_ctrl)) &
8039		PORT_HW_CFG_E3_FAULT_MDL_LED_MASK) >>
8040		PORT_HW_CFG_E3_FAULT_MDL_LED_SHIFT;
8041	DP(NETIF_MSG_LINK, "Setting Fault LED to %d using pin cfg %d\n",
8042		       gpio_mode, pin_cfg);
8043	bnx2x_set_cfg_pin(bp, pin_cfg, gpio_mode);
8044}
8045
8046static void bnx2x_set_sfp_module_fault_led(struct link_params *params,
8047					   u8 gpio_mode)
8048{
8049	struct bnx2x *bp = params->bp;
8050	DP(NETIF_MSG_LINK, "Setting SFP+ module fault LED to %d\n", gpio_mode);
8051	if (CHIP_IS_E3(bp)) {
8052		/*
8053		 * Low ==> if SFP+ module is supported otherwise
8054		 * High ==> if SFP+ module is not on the approved vendor list
8055		 */
8056		bnx2x_set_e3_module_fault_led(params, gpio_mode);
8057	} else
8058		bnx2x_set_e1e2_module_fault_led(params, gpio_mode);
8059}
8060
8061static void bnx2x_warpcore_power_module(struct link_params *params,
8062					struct bnx2x_phy *phy,
8063					u8 power)
8064{
8065	u32 pin_cfg;
8066	struct bnx2x *bp = params->bp;
8067
8068	pin_cfg = (REG_RD(bp, params->shmem_base +
8069			  offsetof(struct shmem_region,
8070			dev_info.port_hw_config[params->port].e3_sfp_ctrl)) &
8071			PORT_HW_CFG_E3_PWR_DIS_MASK) >>
8072			PORT_HW_CFG_E3_PWR_DIS_SHIFT;
8073
8074	if (pin_cfg == PIN_CFG_NA)
8075		return;
8076	DP(NETIF_MSG_LINK, "Setting SFP+ module power to %d using pin cfg %d\n",
8077		       power, pin_cfg);
8078	/*
8079	 * Low ==> corresponding SFP+ module is powered
8080	 * high ==> the SFP+ module is powered down
8081	 */
8082	bnx2x_set_cfg_pin(bp, pin_cfg, power ^ 1);
8083}
8084
8085static void bnx2x_warpcore_hw_reset(struct bnx2x_phy *phy,
8086				    struct link_params *params)
8087{
8088	bnx2x_warpcore_power_module(params, phy, 0);
8089}
8090
8091static void bnx2x_power_sfp_module(struct link_params *params,
8092				   struct bnx2x_phy *phy,
8093				   u8 power)
8094{
8095	struct bnx2x *bp = params->bp;
8096	DP(NETIF_MSG_LINK, "Setting SFP+ power to %x\n", power);
8097
8098	switch (phy->type) {
8099	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
8100	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
8101		bnx2x_8727_power_module(params->bp, phy, power);
8102		break;
8103	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
8104		bnx2x_warpcore_power_module(params, phy, power);
8105		break;
8106	default:
8107		break;
8108	}
8109}
8110static void bnx2x_warpcore_set_limiting_mode(struct link_params *params,
8111					     struct bnx2x_phy *phy,
8112					     u16 edc_mode)
8113{
8114	u16 val = 0;
8115	u16 mode = MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_DEFAULT;
8116	struct bnx2x *bp = params->bp;
8117
8118	u8 lane = bnx2x_get_warpcore_lane(phy, params);
8119	/* This is a global register which controls all lanes */
8120	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
8121			MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE, &val);
8122	val &= ~(0xf << (lane << 2));
8123
8124	switch (edc_mode) {
8125	case EDC_MODE_LINEAR:
8126	case EDC_MODE_LIMITING:
8127		mode = MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_DEFAULT;
8128		break;
8129	case EDC_MODE_PASSIVE_DAC:
8130		mode = MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE_SFP_DAC;
8131		break;
8132	default:
8133		break;
8134	}
8135
8136	val |= (mode << (lane << 2));
8137	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
8138			 MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE, val);
8139	/* A must read */
8140	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
8141			MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE, &val);
8142
8143	/* Restart microcode to re-read the new mode */
8144	bnx2x_warpcore_reset_lane(bp, phy, 1);
8145	bnx2x_warpcore_reset_lane(bp, phy, 0);
8146
8147}
8148
8149static void bnx2x_set_limiting_mode(struct link_params *params,
8150				    struct bnx2x_phy *phy,
8151				    u16 edc_mode)
8152{
8153	switch (phy->type) {
8154	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
8155		bnx2x_8726_set_limiting_mode(params->bp, phy, edc_mode);
8156		break;
8157	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
8158	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
8159		bnx2x_8727_set_limiting_mode(params->bp, phy, edc_mode);
8160		break;
8161	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
8162		bnx2x_warpcore_set_limiting_mode(params, phy, edc_mode);
8163		break;
8164	}
8165}
8166
8167int bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
8168			       struct link_params *params)
8169{
8170	struct bnx2x *bp = params->bp;
8171	u16 edc_mode;
8172	int rc = 0;
8173
8174	u32 val = REG_RD(bp, params->shmem_base +
8175			     offsetof(struct shmem_region, dev_info.
8176				     port_feature_config[params->port].config));
8177
8178	DP(NETIF_MSG_LINK, "SFP+ module plugged in/out detected on port %d\n",
8179		 params->port);
8180	/* Power up module */
8181	bnx2x_power_sfp_module(params, phy, 1);
8182	if (bnx2x_get_edc_mode(phy, params, &edc_mode) != 0) {
8183		DP(NETIF_MSG_LINK, "Failed to get valid module type\n");
8184		return -EINVAL;
8185	} else if (bnx2x_verify_sfp_module(phy, params) != 0) {
8186		/* check SFP+ module compatibility */
8187		DP(NETIF_MSG_LINK, "Module verification failed!!\n");
8188		rc = -EINVAL;
8189		/* Turn on fault module-detected led */
8190		bnx2x_set_sfp_module_fault_led(params,
8191					       MISC_REGISTERS_GPIO_HIGH);
8192
8193		/* Check if need to power down the SFP+ module */
8194		if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
8195		     PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_POWER_DOWN) {
8196			DP(NETIF_MSG_LINK, "Shutdown SFP+ module!!\n");
8197			bnx2x_power_sfp_module(params, phy, 0);
8198			return rc;
8199		}
8200	} else {
8201		/* Turn off fault module-detected led */
8202		bnx2x_set_sfp_module_fault_led(params, MISC_REGISTERS_GPIO_LOW);
8203	}
8204
8205	/*
8206	 * Check and set limiting mode / LRM mode on 8726. On 8727 it
8207	 * is done automatically
8208	 */
8209	bnx2x_set_limiting_mode(params, phy, edc_mode);
8210
8211	/*
8212	 * Enable transmit for this module if the module is approved, or
8213	 * if unapproved modules should also enable the Tx laser
8214	 */
8215	if (rc == 0 ||
8216	    (val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) !=
8217	    PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
8218		bnx2x_sfp_set_transmitter(params, phy, 1);
8219	else
8220		bnx2x_sfp_set_transmitter(params, phy, 0);
8221
8222	return rc;
8223}
8224
8225void bnx2x_handle_module_detect_int(struct link_params *params)
8226{
8227	struct bnx2x *bp = params->bp;
8228	struct bnx2x_phy *phy;
8229	u32 gpio_val;
8230	u8 gpio_num, gpio_port;
8231	if (CHIP_IS_E3(bp))
8232		phy = &params->phy[INT_PHY];
8233	else
8234		phy = &params->phy[EXT_PHY1];
8235
8236	if (bnx2x_get_mod_abs_int_cfg(bp, params->chip_id, params->shmem_base,
8237				      params->port, &gpio_num, &gpio_port) ==
8238	    -EINVAL) {
8239		DP(NETIF_MSG_LINK, "Failed to get MOD_ABS interrupt config\n");
8240		return;
8241	}
8242
8243	/* Set valid module led off */
8244	bnx2x_set_sfp_module_fault_led(params, MISC_REGISTERS_GPIO_HIGH);
8245
8246	/* Get current gpio val reflecting module plugged in / out*/
8247	gpio_val = bnx2x_get_gpio(bp, gpio_num, gpio_port);
8248
8249	/* Call the handling function in case module is detected */
8250	if (gpio_val == 0) {
8251		bnx2x_power_sfp_module(params, phy, 1);
8252		bnx2x_set_gpio_int(bp, gpio_num,
8253				   MISC_REGISTERS_GPIO_INT_OUTPUT_CLR,
8254				   gpio_port);
8255		if (bnx2x_wait_for_sfp_module_initialized(phy, params) == 0)
8256			bnx2x_sfp_module_detection(phy, params);
8257		else
8258			DP(NETIF_MSG_LINK, "SFP+ module is not initialized\n");
8259	} else {
8260		u32 val = REG_RD(bp, params->shmem_base +
8261				 offsetof(struct shmem_region, dev_info.
8262					  port_feature_config[params->port].
8263					  config));
8264		bnx2x_set_gpio_int(bp, gpio_num,
8265				   MISC_REGISTERS_GPIO_INT_OUTPUT_SET,
8266				   gpio_port);
8267		/*
8268		 * Module was plugged out.
8269		 * Disable transmit for this module
8270		 */
8271		phy->media_type = ETH_PHY_NOT_PRESENT;
8272		if (((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
8273		     PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER) ||
8274		    CHIP_IS_E3(bp))
8275			bnx2x_sfp_set_transmitter(params, phy, 0);
8276	}
8277}
8278
8279/******************************************************************/
8280/*		Used by 8706 and 8727                             */
8281/******************************************************************/
8282static void bnx2x_sfp_mask_fault(struct bnx2x *bp,
8283				 struct bnx2x_phy *phy,
8284				 u16 alarm_status_offset,
8285				 u16 alarm_ctrl_offset)
8286{
8287	u16 alarm_status, val;
8288	bnx2x_cl45_read(bp, phy,
8289			MDIO_PMA_DEVAD, alarm_status_offset,
8290			&alarm_status);
8291	bnx2x_cl45_read(bp, phy,
8292			MDIO_PMA_DEVAD, alarm_status_offset,
8293			&alarm_status);
8294	/* Mask or enable the fault event. */
8295	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, alarm_ctrl_offset, &val);
8296	if (alarm_status & (1<<0))
8297		val &= ~(1<<0);
8298	else
8299		val |= (1<<0);
8300	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, alarm_ctrl_offset, val);
8301}
8302/******************************************************************/
8303/*		common BCM8706/BCM8726 PHY SECTION		  */
8304/******************************************************************/
8305static u8 bnx2x_8706_8726_read_status(struct bnx2x_phy *phy,
8306				      struct link_params *params,
8307				      struct link_vars *vars)
8308{
8309	u8 link_up = 0;
8310	u16 val1, val2, rx_sd, pcs_status;
8311	struct bnx2x *bp = params->bp;
8312	DP(NETIF_MSG_LINK, "XGXS 8706/8726\n");
8313	/* Clear RX Alarm*/
8314	bnx2x_cl45_read(bp, phy,
8315			MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &val2);
8316
8317	bnx2x_sfp_mask_fault(bp, phy, MDIO_PMA_LASI_TXSTAT,
8318			     MDIO_PMA_LASI_TXCTRL);
8319
8320	/* clear LASI indication*/
8321	bnx2x_cl45_read(bp, phy,
8322			MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val1);
8323	bnx2x_cl45_read(bp, phy,
8324			MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val2);
8325	DP(NETIF_MSG_LINK, "8706/8726 LASI status 0x%x--> 0x%x\n", val1, val2);
8326
8327	bnx2x_cl45_read(bp, phy,
8328			MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_SD, &rx_sd);
8329	bnx2x_cl45_read(bp, phy,
8330			MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &pcs_status);
8331	bnx2x_cl45_read(bp, phy,
8332			MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &val2);
8333	bnx2x_cl45_read(bp, phy,
8334			MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &val2);
8335
8336	DP(NETIF_MSG_LINK, "8706/8726 rx_sd 0x%x pcs_status 0x%x 1Gbps"
8337			" link_status 0x%x\n", rx_sd, pcs_status, val2);
8338	/*
8339	 * link is up if both bit 0 of pmd_rx_sd and bit 0 of pcs_status
8340	 * are set, or if the autoneg bit 1 is set
8341	 */
8342	link_up = ((rx_sd & pcs_status & 0x1) || (val2 & (1<<1)));
8343	if (link_up) {
8344		if (val2 & (1<<1))
8345			vars->line_speed = SPEED_1000;
8346		else
8347			vars->line_speed = SPEED_10000;
8348		bnx2x_ext_phy_resolve_fc(phy, params, vars);
8349		vars->duplex = DUPLEX_FULL;
8350	}
8351
8352	/* Capture 10G link fault. Read twice to clear stale value. */
8353	if (vars->line_speed == SPEED_10000) {
8354		bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
8355			    MDIO_PMA_LASI_TXSTAT, &val1);
8356		bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
8357			    MDIO_PMA_LASI_TXSTAT, &val1);
8358		if (val1 & (1<<0))
8359			vars->fault_detected = 1;
8360	}
8361
8362	return link_up;
8363}
8364
8365/******************************************************************/
8366/*			BCM8706 PHY SECTION			  */
8367/******************************************************************/
8368static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy,
8369				 struct link_params *params,
8370				 struct link_vars *vars)
8371{
8372	u32 tx_en_mode;
8373	u16 cnt, val, tmp1;
8374	struct bnx2x *bp = params->bp;
8375
8376	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
8377		       MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
8378	/* HW reset */
8379	bnx2x_ext_phy_hw_reset(bp, params->port);
8380	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0xa040);
8381	bnx2x_wait_reset_complete(bp, phy, params);
8382
8383	/* Wait until fw is loaded */
8384	for (cnt = 0; cnt < 100; cnt++) {
8385		bnx2x_cl45_read(bp, phy,
8386				MDIO_PMA_DEVAD, MDIO_PMA_REG_ROM_VER1, &val);
8387		if (val)
8388			break;
8389		msleep(10);
8390	}
8391	DP(NETIF_MSG_LINK, "XGXS 8706 is initialized after %d ms\n", cnt);
8392	if ((params->feature_config_flags &
8393	     FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
8394		u8 i;
8395		u16 reg;
8396		for (i = 0; i < 4; i++) {
8397			reg = MDIO_XS_8706_REG_BANK_RX0 +
8398				i*(MDIO_XS_8706_REG_BANK_RX1 -
8399				   MDIO_XS_8706_REG_BANK_RX0);
8400			bnx2x_cl45_read(bp, phy, MDIO_XS_DEVAD, reg, &val);
8401			/* Clear first 3 bits of the control */
8402			val &= ~0x7;
8403			/* Set control bits according to configuration */
8404			val |= (phy->rx_preemphasis[i] & 0x7);
8405			DP(NETIF_MSG_LINK, "Setting RX Equalizer to BCM8706"
8406				   " reg 0x%x <-- val 0x%x\n", reg, val);
8407			bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, reg, val);
8408		}
8409	}
8410	/* Force speed */
8411	if (phy->req_line_speed == SPEED_10000) {
8412		DP(NETIF_MSG_LINK, "XGXS 8706 force 10Gbps\n");
8413
8414		bnx2x_cl45_write(bp, phy,
8415				 MDIO_PMA_DEVAD,
8416				 MDIO_PMA_REG_DIGITAL_CTRL, 0x400);
8417		bnx2x_cl45_write(bp, phy,
8418				 MDIO_PMA_DEVAD, MDIO_PMA_LASI_TXCTRL,
8419				 0);
8420		/* Arm LASI for link and Tx fault. */
8421		bnx2x_cl45_write(bp, phy,
8422				 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 3);
8423	} else {
8424		/* Force 1Gbps using autoneg with 1G advertisement */
8425
8426		/* Allow CL37 through CL73 */
8427		DP(NETIF_MSG_LINK, "XGXS 8706 AutoNeg\n");
8428		bnx2x_cl45_write(bp, phy,
8429				 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_CL73, 0x040c);
8430
8431		/* Enable Full-Duplex advertisement on CL37 */
8432		bnx2x_cl45_write(bp, phy,
8433				 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LP, 0x0020);
8434		/* Enable CL37 AN */
8435		bnx2x_cl45_write(bp, phy,
8436				 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1000);
8437		/* 1G support */
8438		bnx2x_cl45_write(bp, phy,
8439				 MDIO_AN_DEVAD, MDIO_AN_REG_ADV, (1<<5));
8440
8441		/* Enable clause 73 AN */
8442		bnx2x_cl45_write(bp, phy,
8443				 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x1200);
8444		bnx2x_cl45_write(bp, phy,
8445				 MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
8446				 0x0400);
8447		bnx2x_cl45_write(bp, phy,
8448				 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL,
8449				 0x0004);
8450	}
8451	bnx2x_save_bcm_spirom_ver(bp, phy, params->port);
8452
8453	/*
8454	 * If TX Laser is controlled by GPIO_0, do not let PHY go into low
8455	 * power mode, if TX Laser is disabled
8456	 */
8457
8458	tx_en_mode = REG_RD(bp, params->shmem_base +
8459			    offsetof(struct shmem_region,
8460				dev_info.port_hw_config[params->port].sfp_ctrl))
8461			& PORT_HW_CFG_TX_LASER_MASK;
8462
8463	if (tx_en_mode == PORT_HW_CFG_TX_LASER_GPIO0) {
8464		DP(NETIF_MSG_LINK, "Enabling TXONOFF_PWRDN_DIS\n");
8465		bnx2x_cl45_read(bp, phy,
8466			MDIO_PMA_DEVAD, MDIO_PMA_REG_DIGITAL_CTRL, &tmp1);
8467		tmp1 |= 0x1;
8468		bnx2x_cl45_write(bp, phy,
8469			MDIO_PMA_DEVAD, MDIO_PMA_REG_DIGITAL_CTRL, tmp1);
8470	}
8471
8472	return 0;
8473}
8474
8475static int bnx2x_8706_read_status(struct bnx2x_phy *phy,
8476				  struct link_params *params,
8477				  struct link_vars *vars)
8478{
8479	return bnx2x_8706_8726_read_status(phy, params, vars);
8480}
8481
8482/******************************************************************/
8483/*			BCM8726 PHY SECTION			  */
8484/******************************************************************/
8485static void bnx2x_8726_config_loopback(struct bnx2x_phy *phy,
8486				       struct link_params *params)
8487{
8488	struct bnx2x *bp = params->bp;
8489	DP(NETIF_MSG_LINK, "PMA/PMD ext_phy_loopback: 8726\n");
8490	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x0001);
8491}
8492
8493static void bnx2x_8726_external_rom_boot(struct bnx2x_phy *phy,
8494					 struct link_params *params)
8495{
8496	struct bnx2x *bp = params->bp;
8497	/* Need to wait 100ms after reset */
8498	msleep(100);
8499
8500	/* Micro controller re-boot */
8501	bnx2x_cl45_write(bp, phy,
8502			 MDIO_PMA_DEVAD, MDIO_PMA_REG_GEN_CTRL, 0x018B);
8503
8504	/* Set soft reset */
8505	bnx2x_cl45_write(bp, phy,
8506			 MDIO_PMA_DEVAD,
8507			 MDIO_PMA_REG_GEN_CTRL,
8508			 MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
8509
8510	bnx2x_cl45_write(bp, phy,
8511			 MDIO_PMA_DEVAD,
8512			 MDIO_PMA_REG_MISC_CTRL1, 0x0001);
8513
8514	bnx2x_cl45_write(bp, phy,
8515			 MDIO_PMA_DEVAD,
8516			 MDIO_PMA_REG_GEN_CTRL,
8517			 MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
8518
8519	/* wait for 150ms for microcode load */
8520	msleep(150);
8521
8522	/* Disable serial boot control, tristates pins SS_N, SCK, MOSI, MISO */
8523	bnx2x_cl45_write(bp, phy,
8524			 MDIO_PMA_DEVAD,
8525			 MDIO_PMA_REG_MISC_CTRL1, 0x0000);
8526
8527	msleep(200);
8528	bnx2x_save_bcm_spirom_ver(bp, phy, params->port);
8529}
8530
8531static u8 bnx2x_8726_read_status(struct bnx2x_phy *phy,
8532				 struct link_params *params,
8533				 struct link_vars *vars)
8534{
8535	struct bnx2x *bp = params->bp;
8536	u16 val1;
8537	u8 link_up = bnx2x_8706_8726_read_status(phy, params, vars);
8538	if (link_up) {
8539		bnx2x_cl45_read(bp, phy,
8540				MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER,
8541				&val1);
8542		if (val1 & (1<<15)) {
8543			DP(NETIF_MSG_LINK, "Tx is disabled\n");
8544			link_up = 0;
8545			vars->line_speed = 0;
8546		}
8547	}
8548	return link_up;
8549}
8550
8551
8552static int bnx2x_8726_config_init(struct bnx2x_phy *phy,
8553				  struct link_params *params,
8554				  struct link_vars *vars)
8555{
8556	struct bnx2x *bp = params->bp;
8557	DP(NETIF_MSG_LINK, "Initializing BCM8726\n");
8558
8559	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
8560	bnx2x_wait_reset_complete(bp, phy, params);
8561
8562	bnx2x_8726_external_rom_boot(phy, params);
8563
8564	/*
8565	 * Need to call module detected on initialization since the module
8566	 * detection triggered by actual module insertion might occur before
8567	 * driver is loaded, and when driver is loaded, it reset all
8568	 * registers, including the transmitter
8569	 */
8570	bnx2x_sfp_module_detection(phy, params);
8571
8572	if (phy->req_line_speed == SPEED_1000) {
8573		DP(NETIF_MSG_LINK, "Setting 1G force\n");
8574		bnx2x_cl45_write(bp, phy,
8575				 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x40);
8576		bnx2x_cl45_write(bp, phy,
8577				 MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, 0xD);
8578		bnx2x_cl45_write(bp, phy,
8579				 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0x5);
8580		bnx2x_cl45_write(bp, phy,
8581				 MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
8582				 0x400);
8583	} else if ((phy->req_line_speed == SPEED_AUTO_NEG) &&
8584		   (phy->speed_cap_mask &
8585		      PORT_HW_CFG_SPEED_CAPABILITY_D0_1G) &&
8586		   ((phy->speed_cap_mask &
8587		      PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) !=
8588		    PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) {
8589		DP(NETIF_MSG_LINK, "Setting 1G clause37\n");
8590		/* Set Flow control */
8591		bnx2x_ext_phy_set_pause(params, phy, vars);
8592		bnx2x_cl45_write(bp, phy,
8593				 MDIO_AN_DEVAD, MDIO_AN_REG_ADV, 0x20);
8594		bnx2x_cl45_write(bp, phy,
8595				 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_CL73, 0x040c);
8596		bnx2x_cl45_write(bp, phy,
8597				 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, 0x0020);
8598		bnx2x_cl45_write(bp, phy,
8599				 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1000);
8600		bnx2x_cl45_write(bp, phy,
8601				MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x1200);
8602		/*
8603		 * Enable RX-ALARM control to receive interrupt for 1G speed
8604		 * change
8605		 */
8606		bnx2x_cl45_write(bp, phy,
8607				 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0x4);
8608		bnx2x_cl45_write(bp, phy,
8609				 MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
8610				 0x400);
8611
8612	} else { /* Default 10G. Set only LASI control */
8613		bnx2x_cl45_write(bp, phy,
8614				 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 1);
8615	}
8616
8617	/* Set TX PreEmphasis if needed */
8618	if ((params->feature_config_flags &
8619	     FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
8620		DP(NETIF_MSG_LINK,
8621		   "Setting TX_CTRL1 0x%x, TX_CTRL2 0x%x\n",
8622			 phy->tx_preemphasis[0],
8623			 phy->tx_preemphasis[1]);
8624		bnx2x_cl45_write(bp, phy,
8625				 MDIO_PMA_DEVAD,
8626				 MDIO_PMA_REG_8726_TX_CTRL1,
8627				 phy->tx_preemphasis[0]);
8628
8629		bnx2x_cl45_write(bp, phy,
8630				 MDIO_PMA_DEVAD,
8631				 MDIO_PMA_REG_8726_TX_CTRL2,
8632				 phy->tx_preemphasis[1]);
8633	}
8634
8635	return 0;
8636
8637}
8638
8639static void bnx2x_8726_link_reset(struct bnx2x_phy *phy,
8640				  struct link_params *params)
8641{
8642	struct bnx2x *bp = params->bp;
8643	DP(NETIF_MSG_LINK, "bnx2x_8726_link_reset port %d\n", params->port);
8644	/* Set serial boot control for external load */
8645	bnx2x_cl45_write(bp, phy,
8646			 MDIO_PMA_DEVAD,
8647			 MDIO_PMA_REG_GEN_CTRL, 0x0001);
8648}
8649
8650/******************************************************************/
8651/*			BCM8727 PHY SECTION			  */
8652/******************************************************************/
8653
8654static void bnx2x_8727_set_link_led(struct bnx2x_phy *phy,
8655				    struct link_params *params, u8 mode)
8656{
8657	struct bnx2x *bp = params->bp;
8658	u16 led_mode_bitmask = 0;
8659	u16 gpio_pins_bitmask = 0;
8660	u16 val;
8661	/* Only NOC flavor requires to set the LED specifically */
8662	if (!(phy->flags & FLAGS_NOC))
8663		return;
8664	switch (mode) {
8665	case LED_MODE_FRONT_PANEL_OFF:
8666	case LED_MODE_OFF:
8667		led_mode_bitmask = 0;
8668		gpio_pins_bitmask = 0x03;
8669		break;
8670	case LED_MODE_ON:
8671		led_mode_bitmask = 0;
8672		gpio_pins_bitmask = 0x02;
8673		break;
8674	case LED_MODE_OPER:
8675		led_mode_bitmask = 0x60;
8676		gpio_pins_bitmask = 0x11;
8677		break;
8678	}
8679	bnx2x_cl45_read(bp, phy,
8680			MDIO_PMA_DEVAD,
8681			MDIO_PMA_REG_8727_PCS_OPT_CTRL,
8682			&val);
8683	val &= 0xff8f;
8684	val |= led_mode_bitmask;
8685	bnx2x_cl45_write(bp, phy,
8686			 MDIO_PMA_DEVAD,
8687			 MDIO_PMA_REG_8727_PCS_OPT_CTRL,
8688			 val);
8689	bnx2x_cl45_read(bp, phy,
8690			MDIO_PMA_DEVAD,
8691			MDIO_PMA_REG_8727_GPIO_CTRL,
8692			&val);
8693	val &= 0xffe0;
8694	val |= gpio_pins_bitmask;
8695	bnx2x_cl45_write(bp, phy,
8696			 MDIO_PMA_DEVAD,
8697			 MDIO_PMA_REG_8727_GPIO_CTRL,
8698			 val);
8699}
8700static void bnx2x_8727_hw_reset(struct bnx2x_phy *phy,
8701				struct link_params *params) {
8702	u32 swap_val, swap_override;
8703	u8 port;
8704	/*
8705	 * The PHY reset is controlled by GPIO 1. Fake the port number
8706	 * to cancel the swap done in set_gpio()
8707	 */
8708	struct bnx2x *bp = params->bp;
8709	swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
8710	swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
8711	port = (swap_val && swap_override) ^ 1;
8712	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
8713		       MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
8714}
8715
8716static int bnx2x_8727_config_init(struct bnx2x_phy *phy,
8717				  struct link_params *params,
8718				  struct link_vars *vars)
8719{
8720	u32 tx_en_mode;
8721	u16 tmp1, val, mod_abs, tmp2;
8722	u16 rx_alarm_ctrl_val;
8723	u16 lasi_ctrl_val;
8724	struct bnx2x *bp = params->bp;
8725	/* Enable PMD link, MOD_ABS_FLT, and 1G link alarm */
8726
8727	bnx2x_wait_reset_complete(bp, phy, params);
8728	rx_alarm_ctrl_val = (1<<2) | (1<<5) ;
8729	/* Should be 0x6 to enable XS on Tx side. */
8730	lasi_ctrl_val = 0x0006;
8731
8732	DP(NETIF_MSG_LINK, "Initializing BCM8727\n");
8733	/* enable LASI */
8734	bnx2x_cl45_write(bp, phy,
8735			 MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
8736			 rx_alarm_ctrl_val);
8737	bnx2x_cl45_write(bp, phy,
8738			 MDIO_PMA_DEVAD, MDIO_PMA_LASI_TXCTRL,
8739			 0);
8740	bnx2x_cl45_write(bp, phy,
8741			 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, lasi_ctrl_val);
8742
8743	/*
8744	 * Initially configure MOD_ABS to interrupt when module is
8745	 * presence( bit 8)
8746	 */
8747	bnx2x_cl45_read(bp, phy,
8748			MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, &mod_abs);
8749	/*
8750	 * Set EDC off by setting OPTXLOS signal input to low (bit 9).
8751	 * When the EDC is off it locks onto a reference clock and avoids
8752	 * becoming 'lost'
8753	 */
8754	mod_abs &= ~(1<<8);
8755	if (!(phy->flags & FLAGS_NOC))
8756		mod_abs &= ~(1<<9);
8757	bnx2x_cl45_write(bp, phy,
8758			 MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
8759
8760
8761	/* Enable/Disable PHY transmitter output */
8762	bnx2x_set_disable_pmd_transmit(params, phy, 0);
8763
8764	/* Make MOD_ABS give interrupt on change */
8765	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_PCS_OPT_CTRL,
8766			&val);
8767	val |= (1<<12);
8768	if (phy->flags & FLAGS_NOC)
8769		val |= (3<<5);
8770
8771	/*
8772	 * Set 8727 GPIOs to input to allow reading from the 8727 GPIO0
8773	 * status which reflect SFP+ module over-current
8774	 */
8775	if (!(phy->flags & FLAGS_NOC))
8776		val &= 0xff8f; /* Reset bits 4-6 */
8777	bnx2x_cl45_write(bp, phy,
8778			 MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_PCS_OPT_CTRL, val);
8779
8780	bnx2x_8727_power_module(bp, phy, 1);
8781
8782	bnx2x_cl45_read(bp, phy,
8783			MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &tmp1);
8784
8785	bnx2x_cl45_read(bp, phy,
8786			MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT, &tmp1);
8787
8788	/* Set option 1G speed */
8789	if (phy->req_line_speed == SPEED_1000) {
8790		DP(NETIF_MSG_LINK, "Setting 1G force\n");
8791		bnx2x_cl45_write(bp, phy,
8792				 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x40);
8793		bnx2x_cl45_write(bp, phy,
8794				 MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, 0xD);
8795		bnx2x_cl45_read(bp, phy,
8796				MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, &tmp1);
8797		DP(NETIF_MSG_LINK, "1.7 = 0x%x\n", tmp1);
8798		/*
8799		 * Power down the XAUI until link is up in case of dual-media
8800		 * and 1G
8801		 */
8802		if (DUAL_MEDIA(params)) {
8803			bnx2x_cl45_read(bp, phy,
8804					MDIO_PMA_DEVAD,
8805					MDIO_PMA_REG_8727_PCS_GP, &val);
8806			val |= (3<<10);
8807			bnx2x_cl45_write(bp, phy,
8808					 MDIO_PMA_DEVAD,
8809					 MDIO_PMA_REG_8727_PCS_GP, val);
8810		}
8811	} else if ((phy->req_line_speed == SPEED_AUTO_NEG) &&
8812		   ((phy->speed_cap_mask &
8813		     PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) &&
8814		   ((phy->speed_cap_mask &
8815		      PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) !=
8816		   PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) {
8817
8818		DP(NETIF_MSG_LINK, "Setting 1G clause37\n");
8819		bnx2x_cl45_write(bp, phy,
8820				 MDIO_AN_DEVAD, MDIO_AN_REG_8727_MISC_CTRL, 0);
8821		bnx2x_cl45_write(bp, phy,
8822				 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1300);
8823	} else {
8824		/*
8825		 * Since the 8727 has only single reset pin, need to set the 10G
8826		 * registers although it is default
8827		 */
8828		bnx2x_cl45_write(bp, phy,
8829				 MDIO_AN_DEVAD, MDIO_AN_REG_8727_MISC_CTRL,
8830				 0x0020);
8831		bnx2x_cl45_write(bp, phy,
8832				 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x0100);
8833		bnx2x_cl45_write(bp, phy,
8834				 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x2040);
8835		bnx2x_cl45_write(bp, phy,
8836				 MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2,
8837				 0x0008);
8838	}
8839
8840	/*
8841	 * Set 2-wire transfer rate of SFP+ module EEPROM
8842	 * to 100Khz since some DACs(direct attached cables) do
8843	 * not work at 400Khz.
8844	 */
8845	bnx2x_cl45_write(bp, phy,
8846			 MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_TWO_WIRE_SLAVE_ADDR,
8847			 0xa001);
8848
8849	/* Set TX PreEmphasis if needed */
8850	if ((params->feature_config_flags &
8851	     FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
8852		DP(NETIF_MSG_LINK, "Setting TX_CTRL1 0x%x, TX_CTRL2 0x%x\n",
8853			   phy->tx_preemphasis[0],
8854			   phy->tx_preemphasis[1]);
8855		bnx2x_cl45_write(bp, phy,
8856				 MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_TX_CTRL1,
8857				 phy->tx_preemphasis[0]);
8858
8859		bnx2x_cl45_write(bp, phy,
8860				 MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_TX_CTRL2,
8861				 phy->tx_preemphasis[1]);
8862	}
8863
8864	/*
8865	 * If TX Laser is controlled by GPIO_0, do not let PHY go into low
8866	 * power mode, if TX Laser is disabled
8867	 */
8868	tx_en_mode = REG_RD(bp, params->shmem_base +
8869			    offsetof(struct shmem_region,
8870				dev_info.port_hw_config[params->port].sfp_ctrl))
8871			& PORT_HW_CFG_TX_LASER_MASK;
8872
8873	if (tx_en_mode == PORT_HW_CFG_TX_LASER_GPIO0) {
8874
8875		DP(NETIF_MSG_LINK, "Enabling TXONOFF_PWRDN_DIS\n");
8876		bnx2x_cl45_read(bp, phy,
8877			MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_OPT_CFG_REG, &tmp2);
8878		tmp2 |= 0x1000;
8879		tmp2 &= 0xFFEF;
8880		bnx2x_cl45_write(bp, phy,
8881			MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_OPT_CFG_REG, tmp2);
8882	}
8883
8884	return 0;
8885}
8886
8887static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
8888				      struct link_params *params)
8889{
8890	struct bnx2x *bp = params->bp;
8891	u16 mod_abs, rx_alarm_status;
8892	u32 val = REG_RD(bp, params->shmem_base +
8893			     offsetof(struct shmem_region, dev_info.
8894				      port_feature_config[params->port].
8895				      config));
8896	bnx2x_cl45_read(bp, phy,
8897			MDIO_PMA_DEVAD,
8898			MDIO_PMA_REG_PHY_IDENTIFIER, &mod_abs);
8899	if (mod_abs & (1<<8)) {
8900
8901		/* Module is absent */
8902		DP(NETIF_MSG_LINK,
8903		   "MOD_ABS indication show module is absent\n");
8904		phy->media_type = ETH_PHY_NOT_PRESENT;
8905		/*
8906		 * 1. Set mod_abs to detect next module
8907		 *    presence event
8908		 * 2. Set EDC off by setting OPTXLOS signal input to low
8909		 *    (bit 9).
8910		 *    When the EDC is off it locks onto a reference clock and
8911		 *    avoids becoming 'lost'.
8912		 */
8913		mod_abs &= ~(1<<8);
8914		if (!(phy->flags & FLAGS_NOC))
8915			mod_abs &= ~(1<<9);
8916		bnx2x_cl45_write(bp, phy,
8917				 MDIO_PMA_DEVAD,
8918				 MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
8919
8920		/*
8921		 * Clear RX alarm since it stays up as long as
8922		 * the mod_abs wasn't changed
8923		 */
8924		bnx2x_cl45_read(bp, phy,
8925				MDIO_PMA_DEVAD,
8926				MDIO_PMA_LASI_RXSTAT, &rx_alarm_status);
8927
8928	} else {
8929		/* Module is present */
8930		DP(NETIF_MSG_LINK,
8931		   "MOD_ABS indication show module is present\n");
8932		/*
8933		 * First disable transmitter, and if the module is ok, the
8934		 * module_detection will enable it
8935		 * 1. Set mod_abs to detect next module absent event ( bit 8)
8936		 * 2. Restore the default polarity of the OPRXLOS signal and
8937		 * this signal will then correctly indicate the presence or
8938		 * absence of the Rx signal. (bit 9)
8939		 */
8940		mod_abs |= (1<<8);
8941		if (!(phy->flags & FLAGS_NOC))
8942			mod_abs |= (1<<9);
8943		bnx2x_cl45_write(bp, phy,
8944				 MDIO_PMA_DEVAD,
8945				 MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
8946
8947		/*
8948		 * Clear RX alarm since it stays up as long as the mod_abs
8949		 * wasn't changed. This is need to be done before calling the
8950		 * module detection, otherwise it will clear* the link update
8951		 * alarm
8952		 */
8953		bnx2x_cl45_read(bp, phy,
8954				MDIO_PMA_DEVAD,
8955				MDIO_PMA_LASI_RXSTAT, &rx_alarm_status);
8956
8957
8958		if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
8959		    PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
8960			bnx2x_sfp_set_transmitter(params, phy, 0);
8961
8962		if (bnx2x_wait_for_sfp_module_initialized(phy, params) == 0)
8963			bnx2x_sfp_module_detection(phy, params);
8964		else
8965			DP(NETIF_MSG_LINK, "SFP+ module is not initialized\n");
8966	}
8967
8968	DP(NETIF_MSG_LINK, "8727 RX_ALARM_STATUS 0x%x\n",
8969		   rx_alarm_status);
8970	/* No need to check link status in case of module plugged in/out */
8971}
8972
8973static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
8974				 struct link_params *params,
8975				 struct link_vars *vars)
8976
8977{
8978	struct bnx2x *bp = params->bp;
8979	u8 link_up = 0, oc_port = params->port;
8980	u16 link_status = 0;
8981	u16 rx_alarm_status, lasi_ctrl, val1;
8982
8983	/* If PHY is not initialized, do not check link status */
8984	bnx2x_cl45_read(bp, phy,
8985			MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL,
8986			&lasi_ctrl);
8987	if (!lasi_ctrl)
8988		return 0;
8989
8990	/* Check the LASI on Rx */
8991	bnx2x_cl45_read(bp, phy,
8992			MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXSTAT,
8993			&rx_alarm_status);
8994	vars->line_speed = 0;
8995	DP(NETIF_MSG_LINK, "8727 RX_ALARM_STATUS  0x%x\n", rx_alarm_status);
8996
8997	bnx2x_sfp_mask_fault(bp, phy, MDIO_PMA_LASI_TXSTAT,
8998			     MDIO_PMA_LASI_TXCTRL);
8999
9000	bnx2x_cl45_read(bp, phy,
9001			MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val1);
9002
9003	DP(NETIF_MSG_LINK, "8727 LASI status 0x%x\n", val1);
9004
9005	/* Clear MSG-OUT */
9006	bnx2x_cl45_read(bp, phy,
9007			MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &val1);
9008
9009	/*
9010	 * If a module is present and there is need to check
9011	 * for over current
9012	 */
9013	if (!(phy->flags & FLAGS_NOC) && !(rx_alarm_status & (1<<5))) {
9014		/* Check over-current using 8727 GPIO0 input*/
9015		bnx2x_cl45_read(bp, phy,
9016				MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_GPIO_CTRL,
9017				&val1);
9018
9019		if ((val1 & (1<<8)) == 0) {
9020			if (!CHIP_IS_E1x(bp))
9021				oc_port = BP_PATH(bp) + (params->port << 1);
9022			DP(NETIF_MSG_LINK,
9023			   "8727 Power fault has been detected on port %d\n",
9024			   oc_port);
9025			netdev_err(bp->dev, "Error:  Power fault on Port %d has"
9026					    " been detected and the power to "
9027					    "that SFP+ module has been removed"
9028					    " to prevent failure of the card."
9029					    " Please remove the SFP+ module and"
9030					    " restart the system to clear this"
9031					    " error.\n",
9032			 oc_port);
9033			/* Disable all RX_ALARMs except for mod_abs */
9034			bnx2x_cl45_write(bp, phy,
9035					 MDIO_PMA_DEVAD,
9036					 MDIO_PMA_LASI_RXCTRL, (1<<5));
9037
9038			bnx2x_cl45_read(bp, phy,
9039					MDIO_PMA_DEVAD,
9040					MDIO_PMA_REG_PHY_IDENTIFIER, &val1);
9041			/* Wait for module_absent_event */
9042			val1 |= (1<<8);
9043			bnx2x_cl45_write(bp, phy,
9044					 MDIO_PMA_DEVAD,
9045					 MDIO_PMA_REG_PHY_IDENTIFIER, val1);
9046			/* Clear RX alarm */
9047			bnx2x_cl45_read(bp, phy,
9048				MDIO_PMA_DEVAD,
9049				MDIO_PMA_LASI_RXSTAT, &rx_alarm_status);
9050			return 0;
9051		}
9052	} /* Over current check */
9053
9054	/* When module absent bit is set, check module */
9055	if (rx_alarm_status & (1<<5)) {
9056		bnx2x_8727_handle_mod_abs(phy, params);
9057		/* Enable all mod_abs and link detection bits */
9058		bnx2x_cl45_write(bp, phy,
9059				 MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
9060				 ((1<<5) | (1<<2)));
9061	}
9062	DP(NETIF_MSG_LINK, "Enabling 8727 TX laser if SFP is approved\n");
9063	bnx2x_8727_specific_func(phy, params, ENABLE_TX);
9064	/* If transmitter is disabled, ignore false link up indication */
9065	bnx2x_cl45_read(bp, phy,
9066			MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, &val1);
9067	if (val1 & (1<<15)) {
9068		DP(NETIF_MSG_LINK, "Tx is disabled\n");
9069		return 0;
9070	}
9071
9072	bnx2x_cl45_read(bp, phy,
9073			MDIO_PMA_DEVAD,
9074			MDIO_PMA_REG_8073_SPEED_LINK_STATUS, &link_status);
9075
9076	/*
9077	 * Bits 0..2 --> speed detected,
9078	 * Bits 13..15--> link is down
9079	 */
9080	if ((link_status & (1<<2)) && (!(link_status & (1<<15)))) {
9081		link_up = 1;
9082		vars->line_speed = SPEED_10000;
9083		DP(NETIF_MSG_LINK, "port %x: External link up in 10G\n",
9084			   params->port);
9085	} else if ((link_status & (1<<0)) && (!(link_status & (1<<13)))) {
9086		link_up = 1;
9087		vars->line_speed = SPEED_1000;
9088		DP(NETIF_MSG_LINK, "port %x: External link up in 1G\n",
9089			   params->port);
9090	} else {
9091		link_up = 0;
9092		DP(NETIF_MSG_LINK, "port %x: External link is down\n",
9093			   params->port);
9094	}
9095
9096	/* Capture 10G link fault. */
9097	if (vars->line_speed == SPEED_10000) {
9098		bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
9099			    MDIO_PMA_LASI_TXSTAT, &val1);
9100
9101		bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
9102			    MDIO_PMA_LASI_TXSTAT, &val1);
9103
9104		if (val1 & (1<<0)) {
9105			vars->fault_detected = 1;
9106		}
9107	}
9108
9109	if (link_up) {
9110		bnx2x_ext_phy_resolve_fc(phy, params, vars);
9111		vars->duplex = DUPLEX_FULL;
9112		DP(NETIF_MSG_LINK, "duplex = 0x%x\n", vars->duplex);
9113	}
9114
9115	if ((DUAL_MEDIA(params)) &&
9116	    (phy->req_line_speed == SPEED_1000)) {
9117		bnx2x_cl45_read(bp, phy,
9118				MDIO_PMA_DEVAD,
9119				MDIO_PMA_REG_8727_PCS_GP, &val1);
9120		/*
9121		 * In case of dual-media board and 1G, power up the XAUI side,
9122		 * otherwise power it down. For 10G it is done automatically
9123		 */
9124		if (link_up)
9125			val1 &= ~(3<<10);
9126		else
9127			val1 |= (3<<10);
9128		bnx2x_cl45_write(bp, phy,
9129				 MDIO_PMA_DEVAD,
9130				 MDIO_PMA_REG_8727_PCS_GP, val1);
9131	}
9132	return link_up;
9133}
9134
9135static void bnx2x_8727_link_reset(struct bnx2x_phy *phy,
9136				  struct link_params *params)
9137{
9138	struct bnx2x *bp = params->bp;
9139
9140	/* Enable/Disable PHY transmitter output */
9141	bnx2x_set_disable_pmd_transmit(params, phy, 1);
9142
9143	/* Disable Transmitter */
9144	bnx2x_sfp_set_transmitter(params, phy, 0);
9145	/* Clear LASI */
9146	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0);
9147
9148}
9149
9150/******************************************************************/
9151/*		BCM8481/BCM84823/BCM84833 PHY SECTION	          */
9152/******************************************************************/
9153static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
9154					   struct link_params *params)
9155{
9156	u16 val, fw_ver1, fw_ver2, cnt;
9157	u8 port;
9158	struct bnx2x *bp = params->bp;
9159
9160	port = params->port;
9161
9162	/* For the 32 bits registers in 848xx, access via MDIO2ARM interface.*/
9163	/* (1) set register 0xc200_0014(SPI_BRIDGE_CTRL_2) to 0x03000000 */
9164	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0014);
9165	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200);
9166	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81B, 0x0000);
9167	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81C, 0x0300);
9168	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x0009);
9169
9170	for (cnt = 0; cnt < 100; cnt++) {
9171		bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
9172		if (val & 1)
9173			break;
9174		udelay(5);
9175	}
9176	if (cnt == 100) {
9177		DP(NETIF_MSG_LINK, "Unable to read 848xx phy fw version(1)\n");
9178		bnx2x_save_spirom_version(bp, port, 0,
9179					  phy->ver_addr);
9180		return;
9181	}
9182
9183
9184	/* 2) read register 0xc200_0000 (SPI_FW_STATUS) */
9185	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0000);
9186	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200);
9187	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x000A);
9188	for (cnt = 0; cnt < 100; cnt++) {
9189		bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
9190		if (val & 1)
9191			break;
9192		udelay(5);
9193	}
9194	if (cnt == 100) {
9195		DP(NETIF_MSG_LINK, "Unable to read 848xx phy fw version(2)\n");
9196		bnx2x_save_spirom_version(bp, port, 0,
9197					  phy->ver_addr);
9198		return;
9199	}
9200
9201	/* lower 16 bits of the register SPI_FW_STATUS */
9202	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81B, &fw_ver1);
9203	/* upper 16 bits of register SPI_FW_STATUS */
9204	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81C, &fw_ver2);
9205
9206	bnx2x_save_spirom_version(bp, port, (fw_ver2<<16) | fw_ver1,
9207				  phy->ver_addr);
9208}
9209
9210static void bnx2x_848xx_set_led(struct bnx2x *bp,
9211				struct bnx2x_phy *phy)
9212{
9213	u16 val;
9214
9215	/* PHYC_CTL_LED_CTL */
9216	bnx2x_cl45_read(bp, phy,
9217			MDIO_PMA_DEVAD,
9218			MDIO_PMA_REG_8481_LINK_SIGNAL, &val);
9219	val &= 0xFE00;
9220	val |= 0x0092;
9221
9222	bnx2x_cl45_write(bp, phy,
9223			 MDIO_PMA_DEVAD,
9224			 MDIO_PMA_REG_8481_LINK_SIGNAL, val);
9225
9226	bnx2x_cl45_write(bp, phy,
9227			 MDIO_PMA_DEVAD,
9228			 MDIO_PMA_REG_8481_LED1_MASK,
9229			 0x80);
9230
9231	bnx2x_cl45_write(bp, phy,
9232			 MDIO_PMA_DEVAD,
9233			 MDIO_PMA_REG_8481_LED2_MASK,
9234			 0x18);
9235
9236	/* Select activity source by Tx and Rx, as suggested by PHY AE */
9237	bnx2x_cl45_write(bp, phy,
9238			 MDIO_PMA_DEVAD,
9239			 MDIO_PMA_REG_8481_LED3_MASK,
9240			 0x0006);
9241
9242	/* Select the closest activity blink rate to that in 10/100/1000 */
9243	bnx2x_cl45_write(bp, phy,
9244			MDIO_PMA_DEVAD,
9245			MDIO_PMA_REG_8481_LED3_BLINK,
9246			0);
9247
9248	bnx2x_cl45_read(bp, phy,
9249			MDIO_PMA_DEVAD,
9250			MDIO_PMA_REG_84823_CTL_LED_CTL_1, &val);
9251	val |= MDIO_PMA_REG_84823_LED3_STRETCH_EN; /* stretch_en for LED3*/
9252
9253	bnx2x_cl45_write(bp, phy,
9254			 MDIO_PMA_DEVAD,
9255			 MDIO_PMA_REG_84823_CTL_LED_CTL_1, val);
9256
9257	/* 'Interrupt Mask' */
9258	bnx2x_cl45_write(bp, phy,
9259			 MDIO_AN_DEVAD,
9260			 0xFFFB, 0xFFFD);
9261}
9262
9263static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
9264				       struct link_params *params,
9265				       struct link_vars *vars)
9266{
9267	struct bnx2x *bp = params->bp;
9268	u16 autoneg_val, an_1000_val, an_10_100_val;
9269	u16 tmp_req_line_speed;
9270
9271	tmp_req_line_speed = phy->req_line_speed;
9272	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
9273		if (phy->req_line_speed == SPEED_10000)
9274			phy->req_line_speed = SPEED_AUTO_NEG;
9275
9276	/*
9277	 * This phy uses the NIG latch mechanism since link indication
9278	 * arrives through its LED4 and not via its LASI signal, so we
9279	 * get steady signal instead of clear on read
9280	 */
9281	bnx2x_bits_en(bp, NIG_REG_LATCH_BC_0 + params->port*4,
9282		      1 << NIG_LATCH_BC_ENABLE_MI_INT);
9283
9284	bnx2x_cl45_write(bp, phy,
9285			 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x0000);
9286
9287	bnx2x_848xx_set_led(bp, phy);
9288
9289	/* set 1000 speed advertisement */
9290	bnx2x_cl45_read(bp, phy,
9291			MDIO_AN_DEVAD, MDIO_AN_REG_8481_1000T_CTRL,
9292			&an_1000_val);
9293
9294	bnx2x_ext_phy_set_pause(params, phy, vars);
9295	bnx2x_cl45_read(bp, phy,
9296			MDIO_AN_DEVAD,
9297			MDIO_AN_REG_8481_LEGACY_AN_ADV,
9298			&an_10_100_val);
9299	bnx2x_cl45_read(bp, phy,
9300			MDIO_AN_DEVAD, MDIO_AN_REG_8481_LEGACY_MII_CTRL,
9301			&autoneg_val);
9302	/* Disable forced speed */
9303	autoneg_val &= ~((1<<6) | (1<<8) | (1<<9) | (1<<12) | (1<<13));
9304	an_10_100_val &= ~((1<<5) | (1<<6) | (1<<7) | (1<<8));
9305
9306	if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
9307	     (phy->speed_cap_mask &
9308	     PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
9309	    (phy->req_line_speed == SPEED_1000)) {
9310		an_1000_val |= (1<<8);
9311		autoneg_val |= (1<<9 | 1<<12);
9312		if (phy->req_duplex == DUPLEX_FULL)
9313			an_1000_val |= (1<<9);
9314		DP(NETIF_MSG_LINK, "Advertising 1G\n");
9315	} else
9316		an_1000_val &= ~((1<<8) | (1<<9));
9317
9318	bnx2x_cl45_write(bp, phy,
9319			 MDIO_AN_DEVAD, MDIO_AN_REG_8481_1000T_CTRL,
9320			 an_1000_val);
9321
9322	/* set 100 speed advertisement */
9323	if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
9324	     (phy->speed_cap_mask &
9325	      (PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL |
9326	       PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)) &&
9327	     (phy->supported &
9328	      (SUPPORTED_100baseT_Half |
9329	       SUPPORTED_100baseT_Full)))) {
9330		an_10_100_val |= (1<<7);
9331		/* Enable autoneg and restart autoneg for legacy speeds */
9332		autoneg_val |= (1<<9 | 1<<12);
9333
9334		if (phy->req_duplex == DUPLEX_FULL)
9335			an_10_100_val |= (1<<8);
9336		DP(NETIF_MSG_LINK, "Advertising 100M\n");
9337	}
9338	/* set 10 speed advertisement */
9339	if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
9340	     (phy->speed_cap_mask &
9341	      (PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL |
9342	       PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)) &&
9343	     (phy->supported &
9344	      (SUPPORTED_10baseT_Half |
9345	       SUPPORTED_10baseT_Full)))) {
9346		an_10_100_val |= (1<<5);
9347		autoneg_val |= (1<<9 | 1<<12);
9348		if (phy->req_duplex == DUPLEX_FULL)
9349			an_10_100_val |= (1<<6);
9350		DP(NETIF_MSG_LINK, "Advertising 10M\n");
9351	}
9352
9353	/* Only 10/100 are allowed to work in FORCE mode */
9354	if ((phy->req_line_speed == SPEED_100) &&
9355	    (phy->supported &
9356	     (SUPPORTED_100baseT_Half |
9357	      SUPPORTED_100baseT_Full))) {
9358		autoneg_val |= (1<<13);
9359		/* Enabled AUTO-MDIX when autoneg is disabled */
9360		bnx2x_cl45_write(bp, phy,
9361				 MDIO_AN_DEVAD, MDIO_AN_REG_8481_AUX_CTRL,
9362				 (1<<15 | 1<<9 | 7<<0));
9363		DP(NETIF_MSG_LINK, "Setting 100M force\n");
9364	}
9365	if ((phy->req_line_speed == SPEED_10) &&
9366	    (phy->supported &
9367	     (SUPPORTED_10baseT_Half |
9368	      SUPPORTED_10baseT_Full))) {
9369		/* Enabled AUTO-MDIX when autoneg is disabled */
9370		bnx2x_cl45_write(bp, phy,
9371				 MDIO_AN_DEVAD, MDIO_AN_REG_8481_AUX_CTRL,
9372				 (1<<15 | 1<<9 | 7<<0));
9373		DP(NETIF_MSG_LINK, "Setting 10M force\n");
9374	}
9375
9376	bnx2x_cl45_write(bp, phy,
9377			 MDIO_AN_DEVAD, MDIO_AN_REG_8481_LEGACY_AN_ADV,
9378			 an_10_100_val);
9379
9380	if (phy->req_duplex == DUPLEX_FULL)
9381		autoneg_val |= (1<<8);
9382
9383	/*
9384	 * Always write this if this is not 84833.
9385	 * For 84833, write it only when it's a forced speed.
9386	 */
9387	if ((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
9388		((autoneg_val & (1<<12)) == 0))
9389		bnx2x_cl45_write(bp, phy,
9390			 MDIO_AN_DEVAD,
9391			 MDIO_AN_REG_8481_LEGACY_MII_CTRL, autoneg_val);
9392
9393	if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
9394	    (phy->speed_cap_mask &
9395	     PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) ||
9396		(phy->req_line_speed == SPEED_10000)) {
9397			DP(NETIF_MSG_LINK, "Advertising 10G\n");
9398			/* Restart autoneg for 10G*/
9399
9400			bnx2x_cl45_write(bp, phy,
9401				 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL,
9402				 0x3200);
9403	} else
9404		bnx2x_cl45_write(bp, phy,
9405				 MDIO_AN_DEVAD,
9406				 MDIO_AN_REG_8481_10GBASE_T_AN_CTRL,
9407				 1);
9408
9409	/* Save spirom version */
9410	bnx2x_save_848xx_spirom_version(phy, params);
9411
9412	phy->req_line_speed = tmp_req_line_speed;
9413
9414	return 0;
9415}
9416
9417static int bnx2x_8481_config_init(struct bnx2x_phy *phy,
9418				  struct link_params *params,
9419				  struct link_vars *vars)
9420{
9421	struct bnx2x *bp = params->bp;
9422	/* Restore normal power mode*/
9423	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
9424		       MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
9425
9426	/* HW reset */
9427	bnx2x_ext_phy_hw_reset(bp, params->port);
9428	bnx2x_wait_reset_complete(bp, phy, params);
9429
9430	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
9431	return bnx2x_848xx_cmn_config_init(phy, params, vars);
9432}
9433
9434
9435#define PHY84833_HDSHK_WAIT 300
9436static int bnx2x_84833_pair_swap_cfg(struct bnx2x_phy *phy,
9437				   struct link_params *params,
9438				   struct link_vars *vars)
9439{
9440	u32 idx;
9441	u32 pair_swap;
9442	u16 val;
9443	u16 data;
9444	struct bnx2x *bp = params->bp;
9445	/* Do pair swap */
9446
9447	/* Check for configuration. */
9448	pair_swap = REG_RD(bp, params->shmem_base +
9449			   offsetof(struct shmem_region,
9450			dev_info.port_hw_config[params->port].xgbt_phy_cfg)) &
9451		PORT_HW_CFG_RJ45_PAIR_SWAP_MASK;
9452
9453	if (pair_swap == 0)
9454		return 0;
9455
9456	data = (u16)pair_swap;
9457
9458	/* Write CMD_OPEN_OVERRIDE to STATUS reg */
9459	bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
9460			MDIO_84833_TOP_CFG_SCRATCH_REG2,
9461			PHY84833_CMD_OPEN_OVERRIDE);
9462	for (idx = 0; idx < PHY84833_HDSHK_WAIT; idx++) {
9463		bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
9464				MDIO_84833_TOP_CFG_SCRATCH_REG2, &val);
9465		if (val == PHY84833_CMD_OPEN_FOR_CMDS)
9466			break;
9467		msleep(1);
9468	}
9469	if (idx >= PHY84833_HDSHK_WAIT) {
9470		DP(NETIF_MSG_LINK, "Pairswap: FW not ready.\n");
9471		return -EINVAL;
9472	}
9473
9474	bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
9475			MDIO_84833_TOP_CFG_SCRATCH_REG4,
9476			data);
9477	/* Issue pair swap command */
9478	bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
9479			MDIO_84833_TOP_CFG_SCRATCH_REG0,
9480			PHY84833_DIAG_CMD_PAIR_SWAP_CHANGE);
9481	for (idx = 0; idx < PHY84833_HDSHK_WAIT; idx++) {
9482		bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
9483				MDIO_84833_TOP_CFG_SCRATCH_REG2, &val);
9484		if ((val == PHY84833_CMD_COMPLETE_PASS) ||
9485			(val == PHY84833_CMD_COMPLETE_ERROR))
9486			break;
9487		msleep(1);
9488	}
9489	if ((idx >= PHY84833_HDSHK_WAIT) ||
9490		(val == PHY84833_CMD_COMPLETE_ERROR)) {
9491		DP(NETIF_MSG_LINK, "Pairswap: override failed.\n");
9492		return -EINVAL;
9493	}
9494	bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
9495			MDIO_84833_TOP_CFG_SCRATCH_REG2,
9496			PHY84833_CMD_CLEAR_COMPLETE);
9497	DP(NETIF_MSG_LINK, "Pairswap OK, val=0x%x\n", data);
9498	return 0;
9499}
9500
9501
9502static u8 bnx2x_84833_get_reset_gpios(struct bnx2x *bp,
9503				      u32 shmem_base_path[],
9504				      u32 chip_id)
9505{
9506	u32 reset_pin[2];
9507	u32 idx;
9508	u8 reset_gpios;
9509	if (CHIP_IS_E3(bp)) {
9510		/* Assume that these will be GPIOs, not EPIOs. */
9511		for (idx = 0; idx < 2; idx++) {
9512			/* Map config param to register bit. */
9513			reset_pin[idx] = REG_RD(bp, shmem_base_path[idx] +
9514				offsetof(struct shmem_region,
9515				dev_info.port_hw_config[0].e3_cmn_pin_cfg));
9516			reset_pin[idx] = (reset_pin[idx] &
9517				PORT_HW_CFG_E3_PHY_RESET_MASK) >>
9518				PORT_HW_CFG_E3_PHY_RESET_SHIFT;
9519			reset_pin[idx] -= PIN_CFG_GPIO0_P0;
9520			reset_pin[idx] = (1 << reset_pin[idx]);
9521		}
9522		reset_gpios = (u8)(reset_pin[0] | reset_pin[1]);
9523	} else {
9524		/* E2, look from diff place of shmem. */
9525		for (idx = 0; idx < 2; idx++) {
9526			reset_pin[idx] = REG_RD(bp, shmem_base_path[idx] +
9527				offsetof(struct shmem_region,
9528				dev_info.port_hw_config[0].default_cfg));
9529			reset_pin[idx] &= PORT_HW_CFG_EXT_PHY_GPIO_RST_MASK;
9530			reset_pin[idx] -= PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P0;
9531			reset_pin[idx] >>= PORT_HW_CFG_EXT_PHY_GPIO_RST_SHIFT;
9532			reset_pin[idx] = (1 << reset_pin[idx]);
9533		}
9534		reset_gpios = (u8)(reset_pin[0] | reset_pin[1]);
9535	}
9536
9537	return reset_gpios;
9538}
9539
9540static int bnx2x_84833_hw_reset_phy(struct bnx2x_phy *phy,
9541				struct link_params *params)
9542{
9543	struct bnx2x *bp = params->bp;
9544	u8 reset_gpios;
9545	u32 other_shmem_base_addr = REG_RD(bp, params->shmem2_base +
9546				offsetof(struct shmem2_region,
9547				other_shmem_base_addr));
9548
9549	u32 shmem_base_path[2];
9550	shmem_base_path[0] = params->shmem_base;
9551	shmem_base_path[1] = other_shmem_base_addr;
9552
9553	reset_gpios = bnx2x_84833_get_reset_gpios(bp, shmem_base_path,
9554						  params->chip_id);
9555
9556	bnx2x_set_mult_gpio(bp, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_LOW);
9557	udelay(10);
9558	DP(NETIF_MSG_LINK, "84833 hw reset on pin values 0x%x\n",
9559		reset_gpios);
9560
9561	return 0;
9562}
9563
9564static int bnx2x_84833_common_init_phy(struct bnx2x *bp,
9565						u32 shmem_base_path[],
9566						u32 chip_id)
9567{
9568	u8 reset_gpios;
9569
9570	reset_gpios = bnx2x_84833_get_reset_gpios(bp, shmem_base_path, chip_id);
9571
9572	bnx2x_set_mult_gpio(bp, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_LOW);
9573	udelay(10);
9574	bnx2x_set_mult_gpio(bp, reset_gpios, MISC_REGISTERS_GPIO_OUTPUT_HIGH);
9575	msleep(800);
9576	DP(NETIF_MSG_LINK, "84833 reset pulse on pin values 0x%x\n",
9577		reset_gpios);
9578
9579	return 0;
9580}
9581
9582#define PHY84833_CONSTANT_LATENCY 1193
9583static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
9584				   struct link_params *params,
9585				   struct link_vars *vars)
9586{
9587	struct bnx2x *bp = params->bp;
9588	u8 port, initialize = 1;
9589	u16 val;
9590	u16 temp;
9591	u32 actual_phy_selection, cms_enable, idx;
9592	int rc = 0;
9593
9594	msleep(1);
9595
9596	if (!(CHIP_IS_E1(bp)))
9597		port = BP_PATH(bp);
9598	else
9599		port = params->port;
9600
9601	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823) {
9602		bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
9603			       MISC_REGISTERS_GPIO_OUTPUT_HIGH,
9604			       port);
9605	} else {
9606		/* MDIO reset */
9607		bnx2x_cl45_write(bp, phy,
9608				MDIO_PMA_DEVAD,
9609				MDIO_PMA_REG_CTRL, 0x8000);
9610		/* Bring PHY out of super isolate mode */
9611		bnx2x_cl45_read(bp, phy,
9612				MDIO_CTL_DEVAD,
9613				MDIO_84833_TOP_CFG_XGPHY_STRAP1, &val);
9614		val &= ~MDIO_84833_SUPER_ISOLATE;
9615		bnx2x_cl45_write(bp, phy,
9616				MDIO_CTL_DEVAD,
9617				MDIO_84833_TOP_CFG_XGPHY_STRAP1, val);
9618	}
9619
9620	bnx2x_wait_reset_complete(bp, phy, params);
9621
9622	/* Wait for GPHY to come out of reset */
9623	msleep(50);
9624
9625	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
9626		bnx2x_84833_pair_swap_cfg(phy, params, vars);
9627
9628	/*
9629	 * BCM84823 requires that XGXS links up first @ 10G for normal behavior
9630	 */
9631	temp = vars->line_speed;
9632	vars->line_speed = SPEED_10000;
9633	bnx2x_set_autoneg(&params->phy[INT_PHY], params, vars, 0);
9634	bnx2x_program_serdes(&params->phy[INT_PHY], params, vars);
9635	vars->line_speed = temp;
9636
9637	/* Set dual-media configuration according to configuration */
9638
9639	bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
9640			MDIO_CTL_REG_84823_MEDIA, &val);
9641	val &= ~(MDIO_CTL_REG_84823_MEDIA_MAC_MASK |
9642		 MDIO_CTL_REG_84823_MEDIA_LINE_MASK |
9643		 MDIO_CTL_REG_84823_MEDIA_COPPER_CORE_DOWN |
9644		 MDIO_CTL_REG_84823_MEDIA_PRIORITY_MASK |
9645		 MDIO_CTL_REG_84823_MEDIA_FIBER_1G);
9646
9647	if (CHIP_IS_E3(bp)) {
9648		val &= ~(MDIO_CTL_REG_84823_MEDIA_MAC_MASK |
9649			 MDIO_CTL_REG_84823_MEDIA_LINE_MASK);
9650	} else {
9651		val |= (MDIO_CTL_REG_84823_CTRL_MAC_XFI |
9652			MDIO_CTL_REG_84823_MEDIA_LINE_XAUI_L);
9653	}
9654
9655	actual_phy_selection = bnx2x_phy_selection(params);
9656
9657	switch (actual_phy_selection) {
9658	case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT:
9659		/* Do nothing. Essentially this is like the priority copper */
9660		break;
9661	case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
9662		val |= MDIO_CTL_REG_84823_MEDIA_PRIORITY_COPPER;
9663		break;
9664	case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
9665		val |= MDIO_CTL_REG_84823_MEDIA_PRIORITY_FIBER;
9666		break;
9667	case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY:
9668		/* Do nothing here. The first PHY won't be initialized at all */
9669		break;
9670	case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY:
9671		val |= MDIO_CTL_REG_84823_MEDIA_COPPER_CORE_DOWN;
9672		initialize = 0;
9673		break;
9674	}
9675	if (params->phy[EXT_PHY2].req_line_speed == SPEED_1000)
9676		val |= MDIO_CTL_REG_84823_MEDIA_FIBER_1G;
9677
9678	bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
9679			 MDIO_CTL_REG_84823_MEDIA, val);
9680	DP(NETIF_MSG_LINK, "Multi_phy config = 0x%x, Media control = 0x%x\n",
9681		   params->multi_phy_config, val);
9682
9683	/* AutogrEEEn */
9684	if (params->feature_config_flags &
9685		FEATURE_CONFIG_AUTOGREEEN_ENABLED) {
9686		/* Ensure that f/w is ready */
9687		for (idx = 0; idx < PHY84833_HDSHK_WAIT; idx++) {
9688			bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
9689					MDIO_84833_TOP_CFG_SCRATCH_REG2, &val);
9690			if (val == PHY84833_CMD_OPEN_FOR_CMDS)
9691				break;
9692			usleep_range(1000, 1000);
9693		}
9694		if (idx >= PHY84833_HDSHK_WAIT) {
9695			DP(NETIF_MSG_LINK, "AutogrEEEn: FW not ready.\n");
9696			return -EINVAL;
9697		}
9698
9699		/* Select EEE mode */
9700		bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
9701				MDIO_84833_TOP_CFG_SCRATCH_REG3,
9702				0x2);
9703
9704		/* Set Idle and Latency */
9705		bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
9706				MDIO_84833_TOP_CFG_SCRATCH_REG4,
9707				PHY84833_CONSTANT_LATENCY + 1);
9708
9709		bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
9710				MDIO_84833_TOP_CFG_DATA3_REG,
9711				PHY84833_CONSTANT_LATENCY + 1);
9712
9713		bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
9714				MDIO_84833_TOP_CFG_DATA4_REG,
9715				PHY84833_CONSTANT_LATENCY);
9716
9717		/* Send EEE instruction to command register */
9718		bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
9719				MDIO_84833_TOP_CFG_SCRATCH_REG0,
9720				PHY84833_DIAG_CMD_SET_EEE_MODE);
9721
9722		/* Ensure that the command has completed */
9723		for (idx = 0; idx < PHY84833_HDSHK_WAIT; idx++) {
9724			bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
9725					MDIO_84833_TOP_CFG_SCRATCH_REG2, &val);
9726			if ((val == PHY84833_CMD_COMPLETE_PASS) ||
9727				(val == PHY84833_CMD_COMPLETE_ERROR))
9728				break;
9729			usleep_range(1000, 1000);
9730		}
9731		if ((idx >= PHY84833_HDSHK_WAIT) ||
9732			(val == PHY84833_CMD_COMPLETE_ERROR)) {
9733			DP(NETIF_MSG_LINK, "AutogrEEEn: command failed.\n");
9734			return -EINVAL;
9735		}
9736
9737		/* Reset command handler */
9738		bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
9739			    MDIO_84833_TOP_CFG_SCRATCH_REG2,
9740			    PHY84833_CMD_CLEAR_COMPLETE);
9741	}
9742
9743	if (initialize)
9744		rc = bnx2x_848xx_cmn_config_init(phy, params, vars);
9745	else
9746		bnx2x_save_848xx_spirom_version(phy, params);
9747	/* 84833 PHY has a better feature and doesn't need to support this. */
9748	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823) {
9749		cms_enable = REG_RD(bp, params->shmem_base +
9750			offsetof(struct shmem_region,
9751			dev_info.port_hw_config[params->port].default_cfg)) &
9752			PORT_HW_CFG_ENABLE_CMS_MASK;
9753
9754		bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
9755				MDIO_CTL_REG_84823_USER_CTRL_REG, &val);
9756		if (cms_enable)
9757			val |= MDIO_CTL_REG_84823_USER_CTRL_CMS;
9758		else
9759			val &= ~MDIO_CTL_REG_84823_USER_CTRL_CMS;
9760		bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
9761				 MDIO_CTL_REG_84823_USER_CTRL_REG, val);
9762	}
9763
9764	return rc;
9765}
9766
9767static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
9768				  struct link_params *params,
9769				  struct link_vars *vars)
9770{
9771	struct bnx2x *bp = params->bp;
9772	u16 val, val1, val2;
9773	u8 link_up = 0;
9774
9775
9776	/* Check 10G-BaseT link status */
9777	/* Check PMD signal ok */
9778	bnx2x_cl45_read(bp, phy,
9779			MDIO_AN_DEVAD, 0xFFFA, &val1);
9780	bnx2x_cl45_read(bp, phy,
9781			MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_PMD_SIGNAL,
9782			&val2);
9783	DP(NETIF_MSG_LINK, "BCM848xx: PMD_SIGNAL 1.a811 = 0x%x\n", val2);
9784
9785	/* Check link 10G */
9786	if (val2 & (1<<11)) {
9787		vars->line_speed = SPEED_10000;
9788		vars->duplex = DUPLEX_FULL;
9789		link_up = 1;
9790		bnx2x_ext_phy_10G_an_resolve(bp, phy, vars);
9791	} else { /* Check Legacy speed link */
9792		u16 legacy_status, legacy_speed;
9793
9794		/* Enable expansion register 0x42 (Operation mode status) */
9795		bnx2x_cl45_write(bp, phy,
9796				 MDIO_AN_DEVAD,
9797				 MDIO_AN_REG_8481_EXPANSION_REG_ACCESS, 0xf42);
9798
9799		/* Get legacy speed operation status */
9800		bnx2x_cl45_read(bp, phy,
9801				MDIO_AN_DEVAD,
9802				MDIO_AN_REG_8481_EXPANSION_REG_RD_RW,
9803				&legacy_status);
9804
9805		DP(NETIF_MSG_LINK, "Legacy speed status = 0x%x\n",
9806		   legacy_status);
9807		link_up = ((legacy_status & (1<<11)) == (1<<11));
9808		if (link_up) {
9809			legacy_speed = (legacy_status & (3<<9));
9810			if (legacy_speed == (0<<9))
9811				vars->line_speed = SPEED_10;
9812			else if (legacy_speed == (1<<9))
9813				vars->line_speed = SPEED_100;
9814			else if (legacy_speed == (2<<9))
9815				vars->line_speed = SPEED_1000;
9816			else /* Should not happen */
9817				vars->line_speed = 0;
9818
9819			if (legacy_status & (1<<8))
9820				vars->duplex = DUPLEX_FULL;
9821			else
9822				vars->duplex = DUPLEX_HALF;
9823
9824			DP(NETIF_MSG_LINK,
9825			   "Link is up in %dMbps, is_duplex_full= %d\n",
9826			   vars->line_speed,
9827			   (vars->duplex == DUPLEX_FULL));
9828			/* Check legacy speed AN resolution */
9829			bnx2x_cl45_read(bp, phy,
9830					MDIO_AN_DEVAD,
9831					MDIO_AN_REG_8481_LEGACY_MII_STATUS,
9832					&val);
9833			if (val & (1<<5))
9834				vars->link_status |=
9835					LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
9836			bnx2x_cl45_read(bp, phy,
9837					MDIO_AN_DEVAD,
9838					MDIO_AN_REG_8481_LEGACY_AN_EXPANSION,
9839					&val);
9840			if ((val & (1<<0)) == 0)
9841				vars->link_status |=
9842					LINK_STATUS_PARALLEL_DETECTION_USED;
9843		}
9844	}
9845	if (link_up) {
9846		DP(NETIF_MSG_LINK, "BCM84823: link speed is %d\n",
9847			   vars->line_speed);
9848		bnx2x_ext_phy_resolve_fc(phy, params, vars);
9849	}
9850
9851	return link_up;
9852}
9853
9854
9855static int bnx2x_848xx_format_ver(u32 raw_ver, u8 *str, u16 *len)
9856{
9857	int status = 0;
9858	u32 spirom_ver;
9859	spirom_ver = ((raw_ver & 0xF80) >> 7) << 16 | (raw_ver & 0x7F);
9860	status = bnx2x_format_ver(spirom_ver, str, len);
9861	return status;
9862}
9863
9864static void bnx2x_8481_hw_reset(struct bnx2x_phy *phy,
9865				struct link_params *params)
9866{
9867	bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1,
9868		       MISC_REGISTERS_GPIO_OUTPUT_LOW, 0);
9869	bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1,
9870		       MISC_REGISTERS_GPIO_OUTPUT_LOW, 1);
9871}
9872
9873static void bnx2x_8481_link_reset(struct bnx2x_phy *phy,
9874					struct link_params *params)
9875{
9876	bnx2x_cl45_write(params->bp, phy,
9877			 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x0000);
9878	bnx2x_cl45_write(params->bp, phy,
9879			 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1);
9880}
9881
9882static void bnx2x_848x3_link_reset(struct bnx2x_phy *phy,
9883				   struct link_params *params)
9884{
9885	struct bnx2x *bp = params->bp;
9886	u8 port;
9887	u16 val16;
9888
9889	if (!(CHIP_IS_E1(bp)))
9890		port = BP_PATH(bp);
9891	else
9892		port = params->port;
9893
9894	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823) {
9895		bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
9896			       MISC_REGISTERS_GPIO_OUTPUT_LOW,
9897			       port);
9898	} else {
9899		bnx2x_cl45_read(bp, phy,
9900				MDIO_CTL_DEVAD,
9901				0x400f, &val16);
9902		bnx2x_cl45_write(bp, phy,
9903				MDIO_PMA_DEVAD,
9904				MDIO_PMA_REG_CTRL, 0x800);
9905	}
9906}
9907
9908static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
9909				     struct link_params *params, u8 mode)
9910{
9911	struct bnx2x *bp = params->bp;
9912	u16 val;
9913	u8 port;
9914
9915	if (!(CHIP_IS_E1(bp)))
9916		port = BP_PATH(bp);
9917	else
9918		port = params->port;
9919
9920	switch (mode) {
9921	case LED_MODE_OFF:
9922
9923		DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE OFF\n", port);
9924
9925		if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
9926		    SHARED_HW_CFG_LED_EXTPHY1) {
9927
9928			/* Set LED masks */
9929			bnx2x_cl45_write(bp, phy,
9930					MDIO_PMA_DEVAD,
9931					MDIO_PMA_REG_8481_LED1_MASK,
9932					0x0);
9933
9934			bnx2x_cl45_write(bp, phy,
9935					MDIO_PMA_DEVAD,
9936					MDIO_PMA_REG_8481_LED2_MASK,
9937					0x0);
9938
9939			bnx2x_cl45_write(bp, phy,
9940					MDIO_PMA_DEVAD,
9941					MDIO_PMA_REG_8481_LED3_MASK,
9942					0x0);
9943
9944			bnx2x_cl45_write(bp, phy,
9945					MDIO_PMA_DEVAD,
9946					MDIO_PMA_REG_8481_LED5_MASK,
9947					0x0);
9948
9949		} else {
9950			bnx2x_cl45_write(bp, phy,
9951					 MDIO_PMA_DEVAD,
9952					 MDIO_PMA_REG_8481_LED1_MASK,
9953					 0x0);
9954		}
9955		break;
9956	case LED_MODE_FRONT_PANEL_OFF:
9957
9958		DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE FRONT PANEL OFF\n",
9959		   port);
9960
9961		if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
9962		    SHARED_HW_CFG_LED_EXTPHY1) {
9963
9964			/* Set LED masks */
9965			bnx2x_cl45_write(bp, phy,
9966					 MDIO_PMA_DEVAD,
9967					 MDIO_PMA_REG_8481_LED1_MASK,
9968					 0x0);
9969
9970			bnx2x_cl45_write(bp, phy,
9971					 MDIO_PMA_DEVAD,
9972					 MDIO_PMA_REG_8481_LED2_MASK,
9973					 0x0);
9974
9975			bnx2x_cl45_write(bp, phy,
9976					 MDIO_PMA_DEVAD,
9977					 MDIO_PMA_REG_8481_LED3_MASK,
9978					 0x0);
9979
9980			bnx2x_cl45_write(bp, phy,
9981					 MDIO_PMA_DEVAD,
9982					 MDIO_PMA_REG_8481_LED5_MASK,
9983					 0x20);
9984
9985		} else {
9986			bnx2x_cl45_write(bp, phy,
9987					 MDIO_PMA_DEVAD,
9988					 MDIO_PMA_REG_8481_LED1_MASK,
9989					 0x0);
9990		}
9991		break;
9992	case LED_MODE_ON:
9993
9994		DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE ON\n", port);
9995
9996		if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
9997		    SHARED_HW_CFG_LED_EXTPHY1) {
9998			/* Set control reg */
9999			bnx2x_cl45_read(bp, phy,
10000					MDIO_PMA_DEVAD,
10001					MDIO_PMA_REG_8481_LINK_SIGNAL,
10002					&val);
10003			val &= 0x8000;
10004			val |= 0x2492;
10005
10006			bnx2x_cl45_write(bp, phy,
10007					 MDIO_PMA_DEVAD,
10008					 MDIO_PMA_REG_8481_LINK_SIGNAL,
10009					 val);
10010
10011			/* Set LED masks */
10012			bnx2x_cl45_write(bp, phy,
10013					 MDIO_PMA_DEVAD,
10014					 MDIO_PMA_REG_8481_LED1_MASK,
10015					 0x0);
10016
10017			bnx2x_cl45_write(bp, phy,
10018					 MDIO_PMA_DEVAD,
10019					 MDIO_PMA_REG_8481_LED2_MASK,
10020					 0x20);
10021
10022			bnx2x_cl45_write(bp, phy,
10023					 MDIO_PMA_DEVAD,
10024					 MDIO_PMA_REG_8481_LED3_MASK,
10025					 0x20);
10026
10027			bnx2x_cl45_write(bp, phy,
10028					 MDIO_PMA_DEVAD,
10029					 MDIO_PMA_REG_8481_LED5_MASK,
10030					 0x0);
10031		} else {
10032			bnx2x_cl45_write(bp, phy,
10033					 MDIO_PMA_DEVAD,
10034					 MDIO_PMA_REG_8481_LED1_MASK,
10035					 0x20);
10036		}
10037		break;
10038
10039	case LED_MODE_OPER:
10040
10041		DP(NETIF_MSG_LINK, "Port 0x%x: LED MODE OPER\n", port);
10042
10043		if ((params->hw_led_mode << SHARED_HW_CFG_LED_MODE_SHIFT) ==
10044		    SHARED_HW_CFG_LED_EXTPHY1) {
10045
10046			/* Set control reg */
10047			bnx2x_cl45_read(bp, phy,
10048					MDIO_PMA_DEVAD,
10049					MDIO_PMA_REG_8481_LINK_SIGNAL,
10050					&val);
10051
10052			if (!((val &
10053			       MDIO_PMA_REG_8481_LINK_SIGNAL_LED4_ENABLE_MASK)
10054			  >> MDIO_PMA_REG_8481_LINK_SIGNAL_LED4_ENABLE_SHIFT)) {
10055				DP(NETIF_MSG_LINK, "Setting LINK_SIGNAL\n");
10056				bnx2x_cl45_write(bp, phy,
10057						 MDIO_PMA_DEVAD,
10058						 MDIO_PMA_REG_8481_LINK_SIGNAL,
10059						 0xa492);
10060			}
10061
10062			/* Set LED masks */
10063			bnx2x_cl45_write(bp, phy,
10064					 MDIO_PMA_DEVAD,
10065					 MDIO_PMA_REG_8481_LED1_MASK,
10066					 0x10);
10067
10068			bnx2x_cl45_write(bp, phy,
10069					 MDIO_PMA_DEVAD,
10070					 MDIO_PMA_REG_8481_LED2_MASK,
10071					 0x80);
10072
10073			bnx2x_cl45_write(bp, phy,
10074					 MDIO_PMA_DEVAD,
10075					 MDIO_PMA_REG_8481_LED3_MASK,
10076					 0x98);
10077
10078			bnx2x_cl45_write(bp, phy,
10079					 MDIO_PMA_DEVAD,
10080					 MDIO_PMA_REG_8481_LED5_MASK,
10081					 0x40);
10082
10083		} else {
10084			bnx2x_cl45_write(bp, phy,
10085					 MDIO_PMA_DEVAD,
10086					 MDIO_PMA_REG_8481_LED1_MASK,
10087					 0x80);
10088
10089			/* Tell LED3 to blink on source */
10090			bnx2x_cl45_read(bp, phy,
10091					MDIO_PMA_DEVAD,
10092					MDIO_PMA_REG_8481_LINK_SIGNAL,
10093					&val);
10094			val &= ~(7<<6);
10095			val |= (1<<6); /* A83B[8:6]= 1 */
10096			bnx2x_cl45_write(bp, phy,
10097					 MDIO_PMA_DEVAD,
10098					 MDIO_PMA_REG_8481_LINK_SIGNAL,
10099					 val);
10100		}
10101		break;
10102	}
10103
10104	/*
10105	 * This is a workaround for E3+84833 until autoneg
10106	 * restart is fixed in f/w
10107	 */
10108	if (CHIP_IS_E3(bp)) {
10109		bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
10110				MDIO_WC_REG_GP2_STATUS_GP_2_1, &val);
10111	}
10112}
10113
10114/******************************************************************/
10115/*			54618SE PHY SECTION			  */
10116/******************************************************************/
10117static int bnx2x_54618se_config_init(struct bnx2x_phy *phy,
10118					       struct link_params *params,
10119					       struct link_vars *vars)
10120{
10121	struct bnx2x *bp = params->bp;
10122	u8 port;
10123	u16 autoneg_val, an_1000_val, an_10_100_val, fc_val, temp;
10124	u32 cfg_pin;
10125
10126	DP(NETIF_MSG_LINK, "54618SE cfg init\n");
10127	usleep_range(1000, 1000);
10128
10129	/* This works with E3 only, no need to check the chip
10130	   before determining the port. */
10131	port = params->port;
10132
10133	cfg_pin = (REG_RD(bp, params->shmem_base +
10134			offsetof(struct shmem_region,
10135			dev_info.port_hw_config[port].e3_cmn_pin_cfg)) &
10136			PORT_HW_CFG_E3_PHY_RESET_MASK) >>
10137			PORT_HW_CFG_E3_PHY_RESET_SHIFT;
10138
10139	/* Drive pin high to bring the GPHY out of reset. */
10140	bnx2x_set_cfg_pin(bp, cfg_pin, 1);
10141
10142	/* wait for GPHY to reset */
10143	msleep(50);
10144
10145	/* reset phy */
10146	bnx2x_cl22_write(bp, phy,
10147			 MDIO_PMA_REG_CTRL, 0x8000);
10148	bnx2x_wait_reset_complete(bp, phy, params);
10149
10150	/*wait for GPHY to reset */
10151	msleep(50);
10152
10153	/* Configure LED4: set to INTR (0x6). */
10154	/* Accessing shadow register 0xe. */
10155	bnx2x_cl22_write(bp, phy,
10156			MDIO_REG_GPHY_SHADOW,
10157			MDIO_REG_GPHY_SHADOW_LED_SEL2);
10158	bnx2x_cl22_read(bp, phy,
10159			MDIO_REG_GPHY_SHADOW,
10160			&temp);
10161	temp &= ~(0xf << 4);
10162	temp |= (0x6 << 4);
10163	bnx2x_cl22_write(bp, phy,
10164			MDIO_REG_GPHY_SHADOW,
10165			MDIO_REG_GPHY_SHADOW_WR_ENA | temp);
10166	/* Configure INTR based on link status change. */
10167	bnx2x_cl22_write(bp, phy,
10168			MDIO_REG_INTR_MASK,
10169			~MDIO_REG_INTR_MASK_LINK_STATUS);
10170
10171	/* Flip the signal detect polarity (set 0x1c.0x1e[8]). */
10172	bnx2x_cl22_write(bp, phy,
10173			MDIO_REG_GPHY_SHADOW,
10174			MDIO_REG_GPHY_SHADOW_AUTO_DET_MED);
10175	bnx2x_cl22_read(bp, phy,
10176			MDIO_REG_GPHY_SHADOW,
10177			&temp);
10178	temp |= MDIO_REG_GPHY_SHADOW_INVERT_FIB_SD;
10179	bnx2x_cl22_write(bp, phy,
10180			MDIO_REG_GPHY_SHADOW,
10181			MDIO_REG_GPHY_SHADOW_WR_ENA | temp);
10182
10183	/* Set up fc */
10184	/* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
10185	bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
10186	fc_val = 0;
10187	if ((vars->ieee_fc & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
10188			MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC)
10189		fc_val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
10190
10191	if ((vars->ieee_fc & MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
10192			MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH)
10193		fc_val |= MDIO_AN_REG_ADV_PAUSE_PAUSE;
10194
10195	/* read all advertisement */
10196	bnx2x_cl22_read(bp, phy,
10197			0x09,
10198			&an_1000_val);
10199
10200	bnx2x_cl22_read(bp, phy,
10201			0x04,
10202			&an_10_100_val);
10203
10204	bnx2x_cl22_read(bp, phy,
10205			MDIO_PMA_REG_CTRL,
10206			&autoneg_val);
10207
10208	/* Disable forced speed */
10209	autoneg_val &= ~((1<<6) | (1<<8) | (1<<9) | (1<<12) | (1<<13));
10210	an_10_100_val &= ~((1<<5) | (1<<6) | (1<<7) | (1<<8) | (1<<10) |
10211			   (1<<11));
10212
10213	if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
10214			(phy->speed_cap_mask &
10215			PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
10216			(phy->req_line_speed == SPEED_1000)) {
10217		an_1000_val |= (1<<8);
10218		autoneg_val |= (1<<9 | 1<<12);
10219		if (phy->req_duplex == DUPLEX_FULL)
10220			an_1000_val |= (1<<9);
10221		DP(NETIF_MSG_LINK, "Advertising 1G\n");
10222	} else
10223		an_1000_val &= ~((1<<8) | (1<<9));
10224
10225	bnx2x_cl22_write(bp, phy,
10226			0x09,
10227			an_1000_val);
10228	bnx2x_cl22_read(bp, phy,
10229			0x09,
10230			&an_1000_val);
10231
10232	/* set 100 speed advertisement */
10233	if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
10234			(phy->speed_cap_mask &
10235			(PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL |
10236			PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)))) {
10237		an_10_100_val |= (1<<7);
10238		/* Enable autoneg and restart autoneg for legacy speeds */
10239		autoneg_val |= (1<<9 | 1<<12);
10240
10241		if (phy->req_duplex == DUPLEX_FULL)
10242			an_10_100_val |= (1<<8);
10243		DP(NETIF_MSG_LINK, "Advertising 100M\n");
10244	}
10245
10246	/* set 10 speed advertisement */
10247	if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
10248			(phy->speed_cap_mask &
10249			(PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL |
10250			PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)))) {
10251		an_10_100_val |= (1<<5);
10252		autoneg_val |= (1<<9 | 1<<12);
10253		if (phy->req_duplex == DUPLEX_FULL)
10254			an_10_100_val |= (1<<6);
10255		DP(NETIF_MSG_LINK, "Advertising 10M\n");
10256	}
10257
10258	/* Only 10/100 are allowed to work in FORCE mode */
10259	if (phy->req_line_speed == SPEED_100) {
10260		autoneg_val |= (1<<13);
10261		/* Enabled AUTO-MDIX when autoneg is disabled */
10262		bnx2x_cl22_write(bp, phy,
10263				0x18,
10264				(1<<15 | 1<<9 | 7<<0));
10265		DP(NETIF_MSG_LINK, "Setting 100M force\n");
10266	}
10267	if (phy->req_line_speed == SPEED_10) {
10268		/* Enabled AUTO-MDIX when autoneg is disabled */
10269		bnx2x_cl22_write(bp, phy,
10270				0x18,
10271				(1<<15 | 1<<9 | 7<<0));
10272		DP(NETIF_MSG_LINK, "Setting 10M force\n");
10273	}
10274
10275	/* Check if we should turn on Auto-GrEEEn */
10276	bnx2x_cl22_read(bp, phy, MDIO_REG_GPHY_PHYID_LSB, &temp);
10277	if (temp == MDIO_REG_GPHY_ID_54618SE) {
10278		if (params->feature_config_flags &
10279		    FEATURE_CONFIG_AUTOGREEEN_ENABLED) {
10280			temp = 6;
10281			DP(NETIF_MSG_LINK, "Enabling Auto-GrEEEn\n");
10282		} else {
10283			temp = 0;
10284			DP(NETIF_MSG_LINK, "Disabling Auto-GrEEEn\n");
10285		}
10286		bnx2x_cl22_write(bp, phy,
10287				 MDIO_REG_GPHY_CL45_ADDR_REG, MDIO_AN_DEVAD);
10288		bnx2x_cl22_write(bp, phy,
10289				 MDIO_REG_GPHY_CL45_DATA_REG,
10290				 MDIO_REG_GPHY_EEE_ADV);
10291		bnx2x_cl22_write(bp, phy,
10292				 MDIO_REG_GPHY_CL45_ADDR_REG,
10293				 (0x1 << 14) | MDIO_AN_DEVAD);
10294		bnx2x_cl22_write(bp, phy,
10295				 MDIO_REG_GPHY_CL45_DATA_REG,
10296				 temp);
10297	}
10298
10299	bnx2x_cl22_write(bp, phy,
10300			0x04,
10301			an_10_100_val | fc_val);
10302
10303	if (phy->req_duplex == DUPLEX_FULL)
10304		autoneg_val |= (1<<8);
10305
10306	bnx2x_cl22_write(bp, phy,
10307			MDIO_PMA_REG_CTRL, autoneg_val);
10308
10309	return 0;
10310}
10311
10312static void bnx2x_54618se_set_link_led(struct bnx2x_phy *phy,
10313				       struct link_params *params, u8 mode)
10314{
10315	struct bnx2x *bp = params->bp;
10316	DP(NETIF_MSG_LINK, "54618SE set link led (mode=%x)\n", mode);
10317	switch (mode) {
10318	case LED_MODE_FRONT_PANEL_OFF:
10319	case LED_MODE_OFF:
10320	case LED_MODE_OPER:
10321	case LED_MODE_ON:
10322	default:
10323		break;
10324	}
10325	return;
10326}
10327
10328static void bnx2x_54618se_link_reset(struct bnx2x_phy *phy,
10329				     struct link_params *params)
10330{
10331	struct bnx2x *bp = params->bp;
10332	u32 cfg_pin;
10333	u8 port;
10334
10335	/*
10336	 * In case of no EPIO routed to reset the GPHY, put it
10337	 * in low power mode.
10338	 */
10339	bnx2x_cl22_write(bp, phy, MDIO_PMA_REG_CTRL, 0x800);
10340	/*
10341	 * This works with E3 only, no need to check the chip
10342	 * before determining the port.
10343	 */
10344	port = params->port;
10345	cfg_pin = (REG_RD(bp, params->shmem_base +
10346			offsetof(struct shmem_region,
10347			dev_info.port_hw_config[port].e3_cmn_pin_cfg)) &
10348			PORT_HW_CFG_E3_PHY_RESET_MASK) >>
10349			PORT_HW_CFG_E3_PHY_RESET_SHIFT;
10350
10351	/* Drive pin low to put GPHY in reset. */
10352	bnx2x_set_cfg_pin(bp, cfg_pin, 0);
10353}
10354
10355static u8 bnx2x_54618se_read_status(struct bnx2x_phy *phy,
10356				    struct link_params *params,
10357				    struct link_vars *vars)
10358{
10359	struct bnx2x *bp = params->bp;
10360	u16 val;
10361	u8 link_up = 0;
10362	u16 legacy_status, legacy_speed;
10363
10364	/* Get speed operation status */
10365	bnx2x_cl22_read(bp, phy,
10366			0x19,
10367			&legacy_status);
10368	DP(NETIF_MSG_LINK, "54618SE read_status: 0x%x\n", legacy_status);
10369
10370	/* Read status to clear the PHY interrupt. */
10371	bnx2x_cl22_read(bp, phy,
10372			MDIO_REG_INTR_STATUS,
10373			&val);
10374
10375	link_up = ((legacy_status & (1<<2)) == (1<<2));
10376
10377	if (link_up) {
10378		legacy_speed = (legacy_status & (7<<8));
10379		if (legacy_speed == (7<<8)) {
10380			vars->line_speed = SPEED_1000;
10381			vars->duplex = DUPLEX_FULL;
10382		} else if (legacy_speed == (6<<8)) {
10383			vars->line_speed = SPEED_1000;
10384			vars->duplex = DUPLEX_HALF;
10385		} else if (legacy_speed == (5<<8)) {
10386			vars->line_speed = SPEED_100;
10387			vars->duplex = DUPLEX_FULL;
10388		}
10389		/* Omitting 100Base-T4 for now */
10390		else if (legacy_speed == (3<<8)) {
10391			vars->line_speed = SPEED_100;
10392			vars->duplex = DUPLEX_HALF;
10393		} else if (legacy_speed == (2<<8)) {
10394			vars->line_speed = SPEED_10;
10395			vars->duplex = DUPLEX_FULL;
10396		} else if (legacy_speed == (1<<8)) {
10397			vars->line_speed = SPEED_10;
10398			vars->duplex = DUPLEX_HALF;
10399		} else /* Should not happen */
10400			vars->line_speed = 0;
10401
10402		DP(NETIF_MSG_LINK,
10403		   "Link is up in %dMbps, is_duplex_full= %d\n",
10404		   vars->line_speed,
10405		   (vars->duplex == DUPLEX_FULL));
10406
10407		/* Check legacy speed AN resolution */
10408		bnx2x_cl22_read(bp, phy,
10409				0x01,
10410				&val);
10411		if (val & (1<<5))
10412			vars->link_status |=
10413				LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
10414		bnx2x_cl22_read(bp, phy,
10415				0x06,
10416				&val);
10417		if ((val & (1<<0)) == 0)
10418			vars->link_status |=
10419				LINK_STATUS_PARALLEL_DETECTION_USED;
10420
10421		DP(NETIF_MSG_LINK, "BCM54618SE: link speed is %d\n",
10422			   vars->line_speed);
10423
10424		/* Report whether EEE is resolved. */
10425		bnx2x_cl22_read(bp, phy, MDIO_REG_GPHY_PHYID_LSB, &val);
10426		if (val == MDIO_REG_GPHY_ID_54618SE) {
10427			if (vars->link_status &
10428			    LINK_STATUS_AUTO_NEGOTIATE_COMPLETE)
10429				val = 0;
10430			else {
10431				bnx2x_cl22_write(bp, phy,
10432					MDIO_REG_GPHY_CL45_ADDR_REG,
10433					MDIO_AN_DEVAD);
10434				bnx2x_cl22_write(bp, phy,
10435					MDIO_REG_GPHY_CL45_DATA_REG,
10436					MDIO_REG_GPHY_EEE_RESOLVED);
10437				bnx2x_cl22_write(bp, phy,
10438					MDIO_REG_GPHY_CL45_ADDR_REG,
10439					(0x1 << 14) | MDIO_AN_DEVAD);
10440				bnx2x_cl22_read(bp, phy,
10441					MDIO_REG_GPHY_CL45_DATA_REG,
10442					&val);
10443			}
10444			DP(NETIF_MSG_LINK, "EEE resolution: 0x%x\n", val);
10445		}
10446
10447		bnx2x_ext_phy_resolve_fc(phy, params, vars);
10448	}
10449	return link_up;
10450}
10451
10452static void bnx2x_54618se_config_loopback(struct bnx2x_phy *phy,
10453					  struct link_params *params)
10454{
10455	struct bnx2x *bp = params->bp;
10456	u16 val;
10457	u32 umac_base = params->port ? GRCBASE_UMAC1 : GRCBASE_UMAC0;
10458
10459	DP(NETIF_MSG_LINK, "2PMA/PMD ext_phy_loopback: 54618se\n");
10460
10461	/* Enable master/slave manual mmode and set to master */
10462	/* mii write 9 [bits set 11 12] */
10463	bnx2x_cl22_write(bp, phy, 0x09, 3<<11);
10464
10465	/* forced 1G and disable autoneg */
10466	/* set val [mii read 0] */
10467	/* set val [expr $val & [bits clear 6 12 13]] */
10468	/* set val [expr $val | [bits set 6 8]] */
10469	/* mii write 0 $val */
10470	bnx2x_cl22_read(bp, phy, 0x00, &val);
10471	val &= ~((1<<6) | (1<<12) | (1<<13));
10472	val |= (1<<6) | (1<<8);
10473	bnx2x_cl22_write(bp, phy, 0x00, val);
10474
10475	/* Set external loopback and Tx using 6dB coding */
10476	/* mii write 0x18 7 */
10477	/* set val [mii read 0x18] */
10478	/* mii write 0x18 [expr $val | [bits set 10 15]] */
10479	bnx2x_cl22_write(bp, phy, 0x18, 7);
10480	bnx2x_cl22_read(bp, phy, 0x18, &val);
10481	bnx2x_cl22_write(bp, phy, 0x18, val | (1<<10) | (1<<15));
10482
10483	/* This register opens the gate for the UMAC despite its name */
10484	REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + params->port*4, 1);
10485
10486	/*
10487	 * Maximum Frame Length (RW). Defines a 14-Bit maximum frame
10488	 * length used by the MAC receive logic to check frames.
10489	 */
10490	REG_WR(bp, umac_base + UMAC_REG_MAXFR, 0x2710);
10491}
10492
10493/******************************************************************/
10494/*			SFX7101 PHY SECTION			  */
10495/******************************************************************/
10496static void bnx2x_7101_config_loopback(struct bnx2x_phy *phy,
10497				       struct link_params *params)
10498{
10499	struct bnx2x *bp = params->bp;
10500	/* SFX7101_XGXS_TEST1 */
10501	bnx2x_cl45_write(bp, phy,
10502			 MDIO_XS_DEVAD, MDIO_XS_SFX7101_XGXS_TEST1, 0x100);
10503}
10504
10505static int bnx2x_7101_config_init(struct bnx2x_phy *phy,
10506				  struct link_params *params,
10507				  struct link_vars *vars)
10508{
10509	u16 fw_ver1, fw_ver2, val;
10510	struct bnx2x *bp = params->bp;
10511	DP(NETIF_MSG_LINK, "Setting the SFX7101 LASI indication\n");
10512
10513	/* Restore normal power mode*/
10514	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
10515		       MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
10516	/* HW reset */
10517	bnx2x_ext_phy_hw_reset(bp, params->port);
10518	bnx2x_wait_reset_complete(bp, phy, params);
10519
10520	bnx2x_cl45_write(bp, phy,
10521			 MDIO_PMA_DEVAD, MDIO_PMA_LASI_CTRL, 0x1);
10522	DP(NETIF_MSG_LINK, "Setting the SFX7101 LED to blink on traffic\n");
10523	bnx2x_cl45_write(bp, phy,
10524			 MDIO_PMA_DEVAD, MDIO_PMA_REG_7107_LED_CNTL, (1<<3));
10525
10526	bnx2x_ext_phy_set_pause(params, phy, vars);
10527	/* Restart autoneg */
10528	bnx2x_cl45_read(bp, phy,
10529			MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, &val);
10530	val |= 0x200;
10531	bnx2x_cl45_write(bp, phy,
10532			 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, val);
10533
10534	/* Save spirom version */
10535	bnx2x_cl45_read(bp, phy,
10536			MDIO_PMA_DEVAD, MDIO_PMA_REG_7101_VER1, &fw_ver1);
10537
10538	bnx2x_cl45_read(bp, phy,
10539			MDIO_PMA_DEVAD, MDIO_PMA_REG_7101_VER2, &fw_ver2);
10540	bnx2x_save_spirom_version(bp, params->port,
10541				  (u32)(fw_ver1<<16 | fw_ver2), phy->ver_addr);
10542	return 0;
10543}
10544
10545static u8 bnx2x_7101_read_status(struct bnx2x_phy *phy,
10546				 struct link_params *params,
10547				 struct link_vars *vars)
10548{
10549	struct bnx2x *bp = params->bp;
10550	u8 link_up;
10551	u16 val1, val2;
10552	bnx2x_cl45_read(bp, phy,
10553			MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val2);
10554	bnx2x_cl45_read(bp, phy,
10555			MDIO_PMA_DEVAD, MDIO_PMA_LASI_STAT, &val1);
10556	DP(NETIF_MSG_LINK, "10G-base-T LASI status 0x%x->0x%x\n",
10557		   val2, val1);
10558	bnx2x_cl45_read(bp, phy,
10559			MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val2);
10560	bnx2x_cl45_read(bp, phy,
10561			MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val1);
10562	DP(NETIF_MSG_LINK, "10G-base-T PMA status 0x%x->0x%x\n",
10563		   val2, val1);
10564	link_up = ((val1 & 4) == 4);
10565	/* if link is up print the AN outcome of the SFX7101 PHY */
10566	if (link_up) {
10567		bnx2x_cl45_read(bp, phy,
10568				MDIO_AN_DEVAD, MDIO_AN_REG_MASTER_STATUS,
10569				&val2);
10570		vars->line_speed = SPEED_10000;
10571		vars->duplex = DUPLEX_FULL;
10572		DP(NETIF_MSG_LINK, "SFX7101 AN status 0x%x->Master=%x\n",
10573			   val2, (val2 & (1<<14)));
10574		bnx2x_ext_phy_10G_an_resolve(bp, phy, vars);
10575		bnx2x_ext_phy_resolve_fc(phy, params, vars);
10576	}
10577	return link_up;
10578}
10579
10580static int bnx2x_7101_format_ver(u32 spirom_ver, u8 *str, u16 *len)
10581{
10582	if (*len < 5)
10583		return -EINVAL;
10584	str[0] = (spirom_ver & 0xFF);
10585	str[1] = (spirom_ver & 0xFF00) >> 8;
10586	str[2] = (spirom_ver & 0xFF0000) >> 16;
10587	str[3] = (spirom_ver & 0xFF000000) >> 24;
10588	str[4] = '\0';
10589	*len -= 5;
10590	return 0;
10591}
10592
10593void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, struct bnx2x_phy *phy)
10594{
10595	u16 val, cnt;
10596
10597	bnx2x_cl45_read(bp, phy,
10598			MDIO_PMA_DEVAD,
10599			MDIO_PMA_REG_7101_RESET, &val);
10600
10601	for (cnt = 0; cnt < 10; cnt++) {
10602		msleep(50);
10603		/* Writes a self-clearing reset */
10604		bnx2x_cl45_write(bp, phy,
10605				 MDIO_PMA_DEVAD,
10606				 MDIO_PMA_REG_7101_RESET,
10607				 (val | (1<<15)));
10608		/* Wait for clear */
10609		bnx2x_cl45_read(bp, phy,
10610				MDIO_PMA_DEVAD,
10611				MDIO_PMA_REG_7101_RESET, &val);
10612
10613		if ((val & (1<<15)) == 0)
10614			break;
10615	}
10616}
10617
10618static void bnx2x_7101_hw_reset(struct bnx2x_phy *phy,
10619				struct link_params *params) {
10620	/* Low power mode is controlled by GPIO 2 */
10621	bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_2,
10622		       MISC_REGISTERS_GPIO_OUTPUT_LOW, params->port);
10623	/* The PHY reset is controlled by GPIO 1 */
10624	bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1,
10625		       MISC_REGISTERS_GPIO_OUTPUT_LOW, params->port);
10626}
10627
10628static void bnx2x_7101_set_link_led(struct bnx2x_phy *phy,
10629				    struct link_params *params, u8 mode)
10630{
10631	u16 val = 0;
10632	struct bnx2x *bp = params->bp;
10633	switch (mode) {
10634	case LED_MODE_FRONT_PANEL_OFF:
10635	case LED_MODE_OFF:
10636		val = 2;
10637		break;
10638	case LED_MODE_ON:
10639		val = 1;
10640		break;
10641	case LED_MODE_OPER:
10642		val = 0;
10643		break;
10644	}
10645	bnx2x_cl45_write(bp, phy,
10646			 MDIO_PMA_DEVAD,
10647			 MDIO_PMA_REG_7107_LINK_LED_CNTL,
10648			 val);
10649}
10650
10651/******************************************************************/
10652/*			STATIC PHY DECLARATION			  */
10653/******************************************************************/
10654
10655static struct bnx2x_phy phy_null = {
10656	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN,
10657	.addr		= 0,
10658	.def_md_devad	= 0,
10659	.flags		= FLAGS_INIT_XGXS_FIRST,
10660	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
10661	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
10662	.mdio_ctrl	= 0,
10663	.supported	= 0,
10664	.media_type	= ETH_PHY_NOT_PRESENT,
10665	.ver_addr	= 0,
10666	.req_flow_ctrl	= 0,
10667	.req_line_speed	= 0,
10668	.speed_cap_mask	= 0,
10669	.req_duplex	= 0,
10670	.rsrv		= 0,
10671	.config_init	= (config_init_t)NULL,
10672	.read_status	= (read_status_t)NULL,
10673	.link_reset	= (link_reset_t)NULL,
10674	.config_loopback = (config_loopback_t)NULL,
10675	.format_fw_ver	= (format_fw_ver_t)NULL,
10676	.hw_reset	= (hw_reset_t)NULL,
10677	.set_link_led	= (set_link_led_t)NULL,
10678	.phy_specific_func = (phy_specific_func_t)NULL
10679};
10680
10681static struct bnx2x_phy phy_serdes = {
10682	.type		= PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT,
10683	.addr		= 0xff,
10684	.def_md_devad	= 0,
10685	.flags		= 0,
10686	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
10687	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
10688	.mdio_ctrl	= 0,
10689	.supported	= (SUPPORTED_10baseT_Half |
10690			   SUPPORTED_10baseT_Full |
10691			   SUPPORTED_100baseT_Half |
10692			   SUPPORTED_100baseT_Full |
10693			   SUPPORTED_1000baseT_Full |
10694			   SUPPORTED_2500baseX_Full |
10695			   SUPPORTED_TP |
10696			   SUPPORTED_Autoneg |
10697			   SUPPORTED_Pause |
10698			   SUPPORTED_Asym_Pause),
10699	.media_type	= ETH_PHY_BASE_T,
10700	.ver_addr	= 0,
10701	.req_flow_ctrl	= 0,
10702	.req_line_speed	= 0,
10703	.speed_cap_mask	= 0,
10704	.req_duplex	= 0,
10705	.rsrv		= 0,
10706	.config_init	= (config_init_t)bnx2x_xgxs_config_init,
10707	.read_status	= (read_status_t)bnx2x_link_settings_status,
10708	.link_reset	= (link_reset_t)bnx2x_int_link_reset,
10709	.config_loopback = (config_loopback_t)NULL,
10710	.format_fw_ver	= (format_fw_ver_t)NULL,
10711	.hw_reset	= (hw_reset_t)NULL,
10712	.set_link_led	= (set_link_led_t)NULL,
10713	.phy_specific_func = (phy_specific_func_t)NULL
10714};
10715
10716static struct bnx2x_phy phy_xgxs = {
10717	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
10718	.addr		= 0xff,
10719	.def_md_devad	= 0,
10720	.flags		= 0,
10721	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
10722	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
10723	.mdio_ctrl	= 0,
10724	.supported	= (SUPPORTED_10baseT_Half |
10725			   SUPPORTED_10baseT_Full |
10726			   SUPPORTED_100baseT_Half |
10727			   SUPPORTED_100baseT_Full |
10728			   SUPPORTED_1000baseT_Full |
10729			   SUPPORTED_2500baseX_Full |
10730			   SUPPORTED_10000baseT_Full |
10731			   SUPPORTED_FIBRE |
10732			   SUPPORTED_Autoneg |
10733			   SUPPORTED_Pause |
10734			   SUPPORTED_Asym_Pause),
10735	.media_type	= ETH_PHY_CX4,
10736	.ver_addr	= 0,
10737	.req_flow_ctrl	= 0,
10738	.req_line_speed	= 0,
10739	.speed_cap_mask	= 0,
10740	.req_duplex	= 0,
10741	.rsrv		= 0,
10742	.config_init	= (config_init_t)bnx2x_xgxs_config_init,
10743	.read_status	= (read_status_t)bnx2x_link_settings_status,
10744	.link_reset	= (link_reset_t)bnx2x_int_link_reset,
10745	.config_loopback = (config_loopback_t)bnx2x_set_xgxs_loopback,
10746	.format_fw_ver	= (format_fw_ver_t)NULL,
10747	.hw_reset	= (hw_reset_t)NULL,
10748	.set_link_led	= (set_link_led_t)NULL,
10749	.phy_specific_func = (phy_specific_func_t)NULL
10750};
10751static struct bnx2x_phy phy_warpcore = {
10752	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
10753	.addr		= 0xff,
10754	.def_md_devad	= 0,
10755	.flags		= FLAGS_HW_LOCK_REQUIRED,
10756	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
10757	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
10758	.mdio_ctrl	= 0,
10759	.supported	= (SUPPORTED_10baseT_Half |
10760			     SUPPORTED_10baseT_Full |
10761			     SUPPORTED_100baseT_Half |
10762			     SUPPORTED_100baseT_Full |
10763			     SUPPORTED_1000baseT_Full |
10764			     SUPPORTED_10000baseT_Full |
10765			     SUPPORTED_20000baseKR2_Full |
10766			     SUPPORTED_20000baseMLD2_Full |
10767			     SUPPORTED_FIBRE |
10768			     SUPPORTED_Autoneg |
10769			     SUPPORTED_Pause |
10770			     SUPPORTED_Asym_Pause),
10771	.media_type	= ETH_PHY_UNSPECIFIED,
10772	.ver_addr	= 0,
10773	.req_flow_ctrl	= 0,
10774	.req_line_speed	= 0,
10775	.speed_cap_mask	= 0,
10776	/* req_duplex = */0,
10777	/* rsrv = */0,
10778	.config_init	= (config_init_t)bnx2x_warpcore_config_init,
10779	.read_status	= (read_status_t)bnx2x_warpcore_read_status,
10780	.link_reset	= (link_reset_t)bnx2x_warpcore_link_reset,
10781	.config_loopback = (config_loopback_t)bnx2x_set_warpcore_loopback,
10782	.format_fw_ver	= (format_fw_ver_t)NULL,
10783	.hw_reset	= (hw_reset_t)bnx2x_warpcore_hw_reset,
10784	.set_link_led	= (set_link_led_t)NULL,
10785	.phy_specific_func = (phy_specific_func_t)NULL
10786};
10787
10788
10789static struct bnx2x_phy phy_7101 = {
10790	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
10791	.addr		= 0xff,
10792	.def_md_devad	= 0,
10793	.flags		= FLAGS_FAN_FAILURE_DET_REQ,
10794	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
10795	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
10796	.mdio_ctrl	= 0,
10797	.supported	= (SUPPORTED_10000baseT_Full |
10798			   SUPPORTED_TP |
10799			   SUPPORTED_Autoneg |
10800			   SUPPORTED_Pause |
10801			   SUPPORTED_Asym_Pause),
10802	.media_type	= ETH_PHY_BASE_T,
10803	.ver_addr	= 0,
10804	.req_flow_ctrl	= 0,
10805	.req_line_speed	= 0,
10806	.speed_cap_mask	= 0,
10807	.req_duplex	= 0,
10808	.rsrv		= 0,
10809	.config_init	= (config_init_t)bnx2x_7101_config_init,
10810	.read_status	= (read_status_t)bnx2x_7101_read_status,
10811	.link_reset	= (link_reset_t)bnx2x_common_ext_link_reset,
10812	.config_loopback = (config_loopback_t)bnx2x_7101_config_loopback,
10813	.format_fw_ver	= (format_fw_ver_t)bnx2x_7101_format_ver,
10814	.hw_reset	= (hw_reset_t)bnx2x_7101_hw_reset,
10815	.set_link_led	= (set_link_led_t)bnx2x_7101_set_link_led,
10816	.phy_specific_func = (phy_specific_func_t)NULL
10817};
10818static struct bnx2x_phy phy_8073 = {
10819	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
10820	.addr		= 0xff,
10821	.def_md_devad	= 0,
10822	.flags		= FLAGS_HW_LOCK_REQUIRED,
10823	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
10824	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
10825	.mdio_ctrl	= 0,
10826	.supported	= (SUPPORTED_10000baseT_Full |
10827			   SUPPORTED_2500baseX_Full |
10828			   SUPPORTED_1000baseT_Full |
10829			   SUPPORTED_FIBRE |
10830			   SUPPORTED_Autoneg |
10831			   SUPPORTED_Pause |
10832			   SUPPORTED_Asym_Pause),
10833	.media_type	= ETH_PHY_KR,
10834	.ver_addr	= 0,
10835	.req_flow_ctrl	= 0,
10836	.req_line_speed	= 0,
10837	.speed_cap_mask	= 0,
10838	.req_duplex	= 0,
10839	.rsrv		= 0,
10840	.config_init	= (config_init_t)bnx2x_8073_config_init,
10841	.read_status	= (read_status_t)bnx2x_8073_read_status,
10842	.link_reset	= (link_reset_t)bnx2x_8073_link_reset,
10843	.config_loopback = (config_loopback_t)NULL,
10844	.format_fw_ver	= (format_fw_ver_t)bnx2x_format_ver,
10845	.hw_reset	= (hw_reset_t)NULL,
10846	.set_link_led	= (set_link_led_t)NULL,
10847	.phy_specific_func = (phy_specific_func_t)NULL
10848};
10849static struct bnx2x_phy phy_8705 = {
10850	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705,
10851	.addr		= 0xff,
10852	.def_md_devad	= 0,
10853	.flags		= FLAGS_INIT_XGXS_FIRST,
10854	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
10855	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
10856	.mdio_ctrl	= 0,
10857	.supported	= (SUPPORTED_10000baseT_Full |
10858			   SUPPORTED_FIBRE |
10859			   SUPPORTED_Pause |
10860			   SUPPORTED_Asym_Pause),
10861	.media_type	= ETH_PHY_XFP_FIBER,
10862	.ver_addr	= 0,
10863	.req_flow_ctrl	= 0,
10864	.req_line_speed	= 0,
10865	.speed_cap_mask	= 0,
10866	.req_duplex	= 0,
10867	.rsrv		= 0,
10868	.config_init	= (config_init_t)bnx2x_8705_config_init,
10869	.read_status	= (read_status_t)bnx2x_8705_read_status,
10870	.link_reset	= (link_reset_t)bnx2x_common_ext_link_reset,
10871	.config_loopback = (config_loopback_t)NULL,
10872	.format_fw_ver	= (format_fw_ver_t)bnx2x_null_format_ver,
10873	.hw_reset	= (hw_reset_t)NULL,
10874	.set_link_led	= (set_link_led_t)NULL,
10875	.phy_specific_func = (phy_specific_func_t)NULL
10876};
10877static struct bnx2x_phy phy_8706 = {
10878	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706,
10879	.addr		= 0xff,
10880	.def_md_devad	= 0,
10881	.flags		= FLAGS_INIT_XGXS_FIRST,
10882	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
10883	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
10884	.mdio_ctrl	= 0,
10885	.supported	= (SUPPORTED_10000baseT_Full |
10886			   SUPPORTED_1000baseT_Full |
10887			   SUPPORTED_FIBRE |
10888			   SUPPORTED_Pause |
10889			   SUPPORTED_Asym_Pause),
10890	.media_type	= ETH_PHY_SFP_FIBER,
10891	.ver_addr	= 0,
10892	.req_flow_ctrl	= 0,
10893	.req_line_speed	= 0,
10894	.speed_cap_mask	= 0,
10895	.req_duplex	= 0,
10896	.rsrv		= 0,
10897	.config_init	= (config_init_t)bnx2x_8706_config_init,
10898	.read_status	= (read_status_t)bnx2x_8706_read_status,
10899	.link_reset	= (link_reset_t)bnx2x_common_ext_link_reset,
10900	.config_loopback = (config_loopback_t)NULL,
10901	.format_fw_ver	= (format_fw_ver_t)bnx2x_format_ver,
10902	.hw_reset	= (hw_reset_t)NULL,
10903	.set_link_led	= (set_link_led_t)NULL,
10904	.phy_specific_func = (phy_specific_func_t)NULL
10905};
10906
10907static struct bnx2x_phy phy_8726 = {
10908	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
10909	.addr		= 0xff,
10910	.def_md_devad	= 0,
10911	.flags		= (FLAGS_HW_LOCK_REQUIRED |
10912			   FLAGS_INIT_XGXS_FIRST),
10913	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
10914	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
10915	.mdio_ctrl	= 0,
10916	.supported	= (SUPPORTED_10000baseT_Full |
10917			   SUPPORTED_1000baseT_Full |
10918			   SUPPORTED_Autoneg |
10919			   SUPPORTED_FIBRE |
10920			   SUPPORTED_Pause |
10921			   SUPPORTED_Asym_Pause),
10922	.media_type	= ETH_PHY_NOT_PRESENT,
10923	.ver_addr	= 0,
10924	.req_flow_ctrl	= 0,
10925	.req_line_speed	= 0,
10926	.speed_cap_mask	= 0,
10927	.req_duplex	= 0,
10928	.rsrv		= 0,
10929	.config_init	= (config_init_t)bnx2x_8726_config_init,
10930	.read_status	= (read_status_t)bnx2x_8726_read_status,
10931	.link_reset	= (link_reset_t)bnx2x_8726_link_reset,
10932	.config_loopback = (config_loopback_t)bnx2x_8726_config_loopback,
10933	.format_fw_ver	= (format_fw_ver_t)bnx2x_format_ver,
10934	.hw_reset	= (hw_reset_t)NULL,
10935	.set_link_led	= (set_link_led_t)NULL,
10936	.phy_specific_func = (phy_specific_func_t)NULL
10937};
10938
10939static struct bnx2x_phy phy_8727 = {
10940	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
10941	.addr		= 0xff,
10942	.def_md_devad	= 0,
10943	.flags		= FLAGS_FAN_FAILURE_DET_REQ,
10944	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
10945	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
10946	.mdio_ctrl	= 0,
10947	.supported	= (SUPPORTED_10000baseT_Full |
10948			   SUPPORTED_1000baseT_Full |
10949			   SUPPORTED_FIBRE |
10950			   SUPPORTED_Pause |
10951			   SUPPORTED_Asym_Pause),
10952	.media_type	= ETH_PHY_NOT_PRESENT,
10953	.ver_addr	= 0,
10954	.req_flow_ctrl	= 0,
10955	.req_line_speed	= 0,
10956	.speed_cap_mask	= 0,
10957	.req_duplex	= 0,
10958	.rsrv		= 0,
10959	.config_init	= (config_init_t)bnx2x_8727_config_init,
10960	.read_status	= (read_status_t)bnx2x_8727_read_status,
10961	.link_reset	= (link_reset_t)bnx2x_8727_link_reset,
10962	.config_loopback = (config_loopback_t)NULL,
10963	.format_fw_ver	= (format_fw_ver_t)bnx2x_format_ver,
10964	.hw_reset	= (hw_reset_t)bnx2x_8727_hw_reset,
10965	.set_link_led	= (set_link_led_t)bnx2x_8727_set_link_led,
10966	.phy_specific_func = (phy_specific_func_t)bnx2x_8727_specific_func
10967};
10968static struct bnx2x_phy phy_8481 = {
10969	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
10970	.addr		= 0xff,
10971	.def_md_devad	= 0,
10972	.flags		= FLAGS_FAN_FAILURE_DET_REQ |
10973			  FLAGS_REARM_LATCH_SIGNAL,
10974	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
10975	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
10976	.mdio_ctrl	= 0,
10977	.supported	= (SUPPORTED_10baseT_Half |
10978			   SUPPORTED_10baseT_Full |
10979			   SUPPORTED_100baseT_Half |
10980			   SUPPORTED_100baseT_Full |
10981			   SUPPORTED_1000baseT_Full |
10982			   SUPPORTED_10000baseT_Full |
10983			   SUPPORTED_TP |
10984			   SUPPORTED_Autoneg |
10985			   SUPPORTED_Pause |
10986			   SUPPORTED_Asym_Pause),
10987	.media_type	= ETH_PHY_BASE_T,
10988	.ver_addr	= 0,
10989	.req_flow_ctrl	= 0,
10990	.req_line_speed	= 0,
10991	.speed_cap_mask	= 0,
10992	.req_duplex	= 0,
10993	.rsrv		= 0,
10994	.config_init	= (config_init_t)bnx2x_8481_config_init,
10995	.read_status	= (read_status_t)bnx2x_848xx_read_status,
10996	.link_reset	= (link_reset_t)bnx2x_8481_link_reset,
10997	.config_loopback = (config_loopback_t)NULL,
10998	.format_fw_ver	= (format_fw_ver_t)bnx2x_848xx_format_ver,
10999	.hw_reset	= (hw_reset_t)bnx2x_8481_hw_reset,
11000	.set_link_led	= (set_link_led_t)bnx2x_848xx_set_link_led,
11001	.phy_specific_func = (phy_specific_func_t)NULL
11002};
11003
11004static struct bnx2x_phy phy_84823 = {
11005	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823,
11006	.addr		= 0xff,
11007	.def_md_devad	= 0,
11008	.flags		= FLAGS_FAN_FAILURE_DET_REQ |
11009			  FLAGS_REARM_LATCH_SIGNAL,
11010	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
11011	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
11012	.mdio_ctrl	= 0,
11013	.supported	= (SUPPORTED_10baseT_Half |
11014			   SUPPORTED_10baseT_Full |
11015			   SUPPORTED_100baseT_Half |
11016			   SUPPORTED_100baseT_Full |
11017			   SUPPORTED_1000baseT_Full |
11018			   SUPPORTED_10000baseT_Full |
11019			   SUPPORTED_TP |
11020			   SUPPORTED_Autoneg |
11021			   SUPPORTED_Pause |
11022			   SUPPORTED_Asym_Pause),
11023	.media_type	= ETH_PHY_BASE_T,
11024	.ver_addr	= 0,
11025	.req_flow_ctrl	= 0,
11026	.req_line_speed	= 0,
11027	.speed_cap_mask	= 0,
11028	.req_duplex	= 0,
11029	.rsrv		= 0,
11030	.config_init	= (config_init_t)bnx2x_848x3_config_init,
11031	.read_status	= (read_status_t)bnx2x_848xx_read_status,
11032	.link_reset	= (link_reset_t)bnx2x_848x3_link_reset,
11033	.config_loopback = (config_loopback_t)NULL,
11034	.format_fw_ver	= (format_fw_ver_t)bnx2x_848xx_format_ver,
11035	.hw_reset	= (hw_reset_t)NULL,
11036	.set_link_led	= (set_link_led_t)bnx2x_848xx_set_link_led,
11037	.phy_specific_func = (phy_specific_func_t)NULL
11038};
11039
11040static struct bnx2x_phy phy_84833 = {
11041	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833,
11042	.addr		= 0xff,
11043	.def_md_devad	= 0,
11044	.flags		= FLAGS_FAN_FAILURE_DET_REQ |
11045			    FLAGS_REARM_LATCH_SIGNAL,
11046	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
11047	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
11048	.mdio_ctrl	= 0,
11049	.supported	= (SUPPORTED_100baseT_Half |
11050			   SUPPORTED_100baseT_Full |
11051			   SUPPORTED_1000baseT_Full |
11052			   SUPPORTED_10000baseT_Full |
11053			   SUPPORTED_TP |
11054			   SUPPORTED_Autoneg |
11055			   SUPPORTED_Pause |
11056			   SUPPORTED_Asym_Pause),
11057	.media_type	= ETH_PHY_BASE_T,
11058	.ver_addr	= 0,
11059	.req_flow_ctrl	= 0,
11060	.req_line_speed	= 0,
11061	.speed_cap_mask	= 0,
11062	.req_duplex	= 0,
11063	.rsrv		= 0,
11064	.config_init	= (config_init_t)bnx2x_848x3_config_init,
11065	.read_status	= (read_status_t)bnx2x_848xx_read_status,
11066	.link_reset	= (link_reset_t)bnx2x_848x3_link_reset,
11067	.config_loopback = (config_loopback_t)NULL,
11068	.format_fw_ver	= (format_fw_ver_t)bnx2x_848xx_format_ver,
11069	.hw_reset	= (hw_reset_t)bnx2x_84833_hw_reset_phy,
11070	.set_link_led	= (set_link_led_t)bnx2x_848xx_set_link_led,
11071	.phy_specific_func = (phy_specific_func_t)NULL
11072};
11073
11074static struct bnx2x_phy phy_54618se = {
11075	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE,
11076	.addr		= 0xff,
11077	.def_md_devad	= 0,
11078	.flags		= FLAGS_INIT_XGXS_FIRST,
11079	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
11080	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
11081	.mdio_ctrl	= 0,
11082	.supported	= (SUPPORTED_10baseT_Half |
11083			   SUPPORTED_10baseT_Full |
11084			   SUPPORTED_100baseT_Half |
11085			   SUPPORTED_100baseT_Full |
11086			   SUPPORTED_1000baseT_Full |
11087			   SUPPORTED_TP |
11088			   SUPPORTED_Autoneg |
11089			   SUPPORTED_Pause |
11090			   SUPPORTED_Asym_Pause),
11091	.media_type	= ETH_PHY_BASE_T,
11092	.ver_addr	= 0,
11093	.req_flow_ctrl	= 0,
11094	.req_line_speed	= 0,
11095	.speed_cap_mask	= 0,
11096	/* req_duplex = */0,
11097	/* rsrv = */0,
11098	.config_init	= (config_init_t)bnx2x_54618se_config_init,
11099	.read_status	= (read_status_t)bnx2x_54618se_read_status,
11100	.link_reset	= (link_reset_t)bnx2x_54618se_link_reset,
11101	.config_loopback = (config_loopback_t)bnx2x_54618se_config_loopback,
11102	.format_fw_ver	= (format_fw_ver_t)NULL,
11103	.hw_reset	= (hw_reset_t)NULL,
11104	.set_link_led	= (set_link_led_t)bnx2x_54618se_set_link_led,
11105	.phy_specific_func = (phy_specific_func_t)NULL
11106};
11107/*****************************************************************/
11108/*                                                               */
11109/* Populate the phy according. Main function: bnx2x_populate_phy   */
11110/*                                                               */
11111/*****************************************************************/
11112
11113static void bnx2x_populate_preemphasis(struct bnx2x *bp, u32 shmem_base,
11114				     struct bnx2x_phy *phy, u8 port,
11115				     u8 phy_index)
11116{
11117	/* Get the 4 lanes xgxs config rx and tx */
11118	u32 rx = 0, tx = 0, i;
11119	for (i = 0; i < 2; i++) {
11120		/*
11121		 * INT_PHY and EXT_PHY1 share the same value location in the
11122		 * shmem. When num_phys is greater than 1, than this value
11123		 * applies only to EXT_PHY1
11124		 */
11125		if (phy_index == INT_PHY || phy_index == EXT_PHY1) {
11126			rx = REG_RD(bp, shmem_base +
11127				    offsetof(struct shmem_region,
11128			  dev_info.port_hw_config[port].xgxs_config_rx[i<<1]));
11129
11130			tx = REG_RD(bp, shmem_base +
11131				    offsetof(struct shmem_region,
11132			  dev_info.port_hw_config[port].xgxs_config_tx[i<<1]));
11133		} else {
11134			rx = REG_RD(bp, shmem_base +
11135				    offsetof(struct shmem_region,
11136			 dev_info.port_hw_config[port].xgxs_config2_rx[i<<1]));
11137
11138			tx = REG_RD(bp, shmem_base +
11139				    offsetof(struct shmem_region,
11140			 dev_info.port_hw_config[port].xgxs_config2_rx[i<<1]));
11141		}
11142
11143		phy->rx_preemphasis[i << 1] = ((rx>>16) & 0xffff);
11144		phy->rx_preemphasis[(i << 1) + 1] = (rx & 0xffff);
11145
11146		phy->tx_preemphasis[i << 1] = ((tx>>16) & 0xffff);
11147		phy->tx_preemphasis[(i << 1) + 1] = (tx & 0xffff);
11148	}
11149}
11150
11151static u32 bnx2x_get_ext_phy_config(struct bnx2x *bp, u32 shmem_base,
11152				    u8 phy_index, u8 port)
11153{
11154	u32 ext_phy_config = 0;
11155	switch (phy_index) {
11156	case EXT_PHY1:
11157		ext_phy_config = REG_RD(bp, shmem_base +
11158					      offsetof(struct shmem_region,
11159			dev_info.port_hw_config[port].external_phy_config));
11160		break;
11161	case EXT_PHY2:
11162		ext_phy_config = REG_RD(bp, shmem_base +
11163					      offsetof(struct shmem_region,
11164			dev_info.port_hw_config[port].external_phy_config2));
11165		break;
11166	default:
11167		DP(NETIF_MSG_LINK, "Invalid phy_index %d\n", phy_index);
11168		return -EINVAL;
11169	}
11170
11171	return ext_phy_config;
11172}
11173static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
11174				  struct bnx2x_phy *phy)
11175{
11176	u32 phy_addr;
11177	u32 chip_id;
11178	u32 switch_cfg = (REG_RD(bp, shmem_base +
11179				       offsetof(struct shmem_region,
11180			dev_info.port_feature_config[port].link_config)) &
11181			  PORT_FEATURE_CONNECTED_SWITCH_MASK);
11182	chip_id = REG_RD(bp, MISC_REG_CHIP_NUM) << 16;
11183	DP(NETIF_MSG_LINK, ":chip_id = 0x%x\n", chip_id);
11184	if (USES_WARPCORE(bp)) {
11185		u32 serdes_net_if;
11186		phy_addr = REG_RD(bp,
11187				  MISC_REG_WC0_CTRL_PHY_ADDR);
11188		*phy = phy_warpcore;
11189		if (REG_RD(bp, MISC_REG_PORT4MODE_EN_OVWR) == 0x3)
11190			phy->flags |= FLAGS_4_PORT_MODE;
11191		else
11192			phy->flags &= ~FLAGS_4_PORT_MODE;
11193			/* Check Dual mode */
11194		serdes_net_if = (REG_RD(bp, shmem_base +
11195					offsetof(struct shmem_region, dev_info.
11196					port_hw_config[port].default_cfg)) &
11197				 PORT_HW_CFG_NET_SERDES_IF_MASK);
11198		/*
11199		 * Set the appropriate supported and flags indications per
11200		 * interface type of the chip
11201		 */
11202		switch (serdes_net_if) {
11203		case PORT_HW_CFG_NET_SERDES_IF_SGMII:
11204			phy->supported &= (SUPPORTED_10baseT_Half |
11205					   SUPPORTED_10baseT_Full |
11206					   SUPPORTED_100baseT_Half |
11207					   SUPPORTED_100baseT_Full |
11208					   SUPPORTED_1000baseT_Full |
11209					   SUPPORTED_FIBRE |
11210					   SUPPORTED_Autoneg |
11211					   SUPPORTED_Pause |
11212					   SUPPORTED_Asym_Pause);
11213			phy->media_type = ETH_PHY_BASE_T;
11214			break;
11215		case PORT_HW_CFG_NET_SERDES_IF_XFI:
11216			phy->media_type = ETH_PHY_XFP_FIBER;
11217			break;
11218		case PORT_HW_CFG_NET_SERDES_IF_SFI:
11219			phy->supported &= (SUPPORTED_1000baseT_Full |
11220					   SUPPORTED_10000baseT_Full |
11221					   SUPPORTED_FIBRE |
11222					   SUPPORTED_Pause |
11223					   SUPPORTED_Asym_Pause);
11224			phy->media_type = ETH_PHY_SFP_FIBER;
11225			break;
11226		case PORT_HW_CFG_NET_SERDES_IF_KR:
11227			phy->media_type = ETH_PHY_KR;
11228			phy->supported &= (SUPPORTED_1000baseT_Full |
11229					   SUPPORTED_10000baseT_Full |
11230					   SUPPORTED_FIBRE |
11231					   SUPPORTED_Autoneg |
11232					   SUPPORTED_Pause |
11233					   SUPPORTED_Asym_Pause);
11234			break;
11235		case PORT_HW_CFG_NET_SERDES_IF_DXGXS:
11236			phy->media_type = ETH_PHY_KR;
11237			phy->flags |= FLAGS_WC_DUAL_MODE;
11238			phy->supported &= (SUPPORTED_20000baseMLD2_Full |
11239					   SUPPORTED_FIBRE |
11240					   SUPPORTED_Pause |
11241					   SUPPORTED_Asym_Pause);
11242			break;
11243		case PORT_HW_CFG_NET_SERDES_IF_KR2:
11244			phy->media_type = ETH_PHY_KR;
11245			phy->flags |= FLAGS_WC_DUAL_MODE;
11246			phy->supported &= (SUPPORTED_20000baseKR2_Full |
11247					   SUPPORTED_FIBRE |
11248					   SUPPORTED_Pause |
11249					   SUPPORTED_Asym_Pause);
11250			break;
11251		default:
11252			DP(NETIF_MSG_LINK, "Unknown WC interface type 0x%x\n",
11253				       serdes_net_if);
11254			break;
11255		}
11256
11257		/*
11258		 * Enable MDC/MDIO work-around for E3 A0 since free running MDC
11259		 * was not set as expected. For B0, ECO will be enabled so there
11260		 * won't be an issue there
11261		 */
11262		if (CHIP_REV(bp) == CHIP_REV_Ax)
11263			phy->flags |= FLAGS_MDC_MDIO_WA;
11264		else
11265			phy->flags |= FLAGS_MDC_MDIO_WA_B0;
11266	} else {
11267		switch (switch_cfg) {
11268		case SWITCH_CFG_1G:
11269			phy_addr = REG_RD(bp,
11270					  NIG_REG_SERDES0_CTRL_PHY_ADDR +
11271					  port * 0x10);
11272			*phy = phy_serdes;
11273			break;
11274		case SWITCH_CFG_10G:
11275			phy_addr = REG_RD(bp,
11276					  NIG_REG_XGXS0_CTRL_PHY_ADDR +
11277					  port * 0x18);
11278			*phy = phy_xgxs;
11279			break;
11280		default:
11281			DP(NETIF_MSG_LINK, "Invalid switch_cfg\n");
11282			return -EINVAL;
11283		}
11284	}
11285	phy->addr = (u8)phy_addr;
11286	phy->mdio_ctrl = bnx2x_get_emac_base(bp,
11287					    SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH,
11288					    port);
11289	if (CHIP_IS_E2(bp))
11290		phy->def_md_devad = E2_DEFAULT_PHY_DEV_ADDR;
11291	else
11292		phy->def_md_devad = DEFAULT_PHY_DEV_ADDR;
11293
11294	DP(NETIF_MSG_LINK, "Internal phy port=%d, addr=0x%x, mdio_ctl=0x%x\n",
11295		   port, phy->addr, phy->mdio_ctrl);
11296
11297	bnx2x_populate_preemphasis(bp, shmem_base, phy, port, INT_PHY);
11298	return 0;
11299}
11300
11301static int bnx2x_populate_ext_phy(struct bnx2x *bp,
11302				  u8 phy_index,
11303				  u32 shmem_base,
11304				  u32 shmem2_base,
11305				  u8 port,
11306				  struct bnx2x_phy *phy)
11307{
11308	u32 ext_phy_config, phy_type, config2;
11309	u32 mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH;
11310	ext_phy_config = bnx2x_get_ext_phy_config(bp, shmem_base,
11311						  phy_index, port);
11312	phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
11313	/* Select the phy type */
11314	switch (phy_type) {
11315	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
11316		mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_SWAPPED;
11317		*phy = phy_8073;
11318		break;
11319	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
11320		*phy = phy_8705;
11321		break;
11322	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
11323		*phy = phy_8706;
11324		break;
11325	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
11326		mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1;
11327		*phy = phy_8726;
11328		break;
11329	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC:
11330		/* BCM8727_NOC => BCM8727 no over current */
11331		mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1;
11332		*phy = phy_8727;
11333		phy->flags |= FLAGS_NOC;
11334		break;
11335	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
11336	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
11337		mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1;
11338		*phy = phy_8727;
11339		break;
11340	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
11341		*phy = phy_8481;
11342		break;
11343	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
11344		*phy = phy_84823;
11345		break;
11346	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833:
11347		*phy = phy_84833;
11348		break;
11349	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54616:
11350	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE:
11351		*phy = phy_54618se;
11352		break;
11353	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
11354		*phy = phy_7101;
11355		break;
11356	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
11357		*phy = phy_null;
11358		return -EINVAL;
11359	default:
11360		*phy = phy_null;
11361		return 0;
11362	}
11363
11364	phy->addr = XGXS_EXT_PHY_ADDR(ext_phy_config);
11365	bnx2x_populate_preemphasis(bp, shmem_base, phy, port, phy_index);
11366
11367	/*
11368	 * The shmem address of the phy version is located on different
11369	 * structures. In case this structure is too old, do not set
11370	 * the address
11371	 */
11372	config2 = REG_RD(bp, shmem_base + offsetof(struct shmem_region,
11373					dev_info.shared_hw_config.config2));
11374	if (phy_index == EXT_PHY1) {
11375		phy->ver_addr = shmem_base + offsetof(struct shmem_region,
11376				port_mb[port].ext_phy_fw_version);
11377
11378		/* Check specific mdc mdio settings */
11379		if (config2 & SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK)
11380			mdc_mdio_access = config2 &
11381			SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK;
11382	} else {
11383		u32 size = REG_RD(bp, shmem2_base);
11384
11385		if (size >
11386		    offsetof(struct shmem2_region, ext_phy_fw_version2)) {
11387			phy->ver_addr = shmem2_base +
11388			    offsetof(struct shmem2_region,
11389				     ext_phy_fw_version2[port]);
11390		}
11391		/* Check specific mdc mdio settings */
11392		if (config2 & SHARED_HW_CFG_MDC_MDIO_ACCESS2_MASK)
11393			mdc_mdio_access = (config2 &
11394			SHARED_HW_CFG_MDC_MDIO_ACCESS2_MASK) >>
11395			(SHARED_HW_CFG_MDC_MDIO_ACCESS2_SHIFT -
11396			 SHARED_HW_CFG_MDC_MDIO_ACCESS1_SHIFT);
11397	}
11398	phy->mdio_ctrl = bnx2x_get_emac_base(bp, mdc_mdio_access, port);
11399
11400	/*
11401	 * In case mdc/mdio_access of the external phy is different than the
11402	 * mdc/mdio access of the XGXS, a HW lock must be taken in each access
11403	 * to prevent one port interfere with another port's CL45 operations.
11404	 */
11405	if (mdc_mdio_access != SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH)
11406		phy->flags |= FLAGS_HW_LOCK_REQUIRED;
11407	DP(NETIF_MSG_LINK, "phy_type 0x%x port %d found in index %d\n",
11408		   phy_type, port, phy_index);
11409	DP(NETIF_MSG_LINK, "             addr=0x%x, mdio_ctl=0x%x\n",
11410		   phy->addr, phy->mdio_ctrl);
11411	return 0;
11412}
11413
11414static int bnx2x_populate_phy(struct bnx2x *bp, u8 phy_index, u32 shmem_base,
11415			      u32 shmem2_base, u8 port, struct bnx2x_phy *phy)
11416{
11417	int status = 0;
11418	phy->type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN;
11419	if (phy_index == INT_PHY)
11420		return bnx2x_populate_int_phy(bp, shmem_base, port, phy);
11421	status = bnx2x_populate_ext_phy(bp, phy_index, shmem_base, shmem2_base,
11422					port, phy);
11423	return status;
11424}
11425
11426static void bnx2x_phy_def_cfg(struct link_params *params,
11427			      struct bnx2x_phy *phy,
11428			      u8 phy_index)
11429{
11430	struct bnx2x *bp = params->bp;
11431	u32 link_config;
11432	/* Populate the default phy configuration for MF mode */
11433	if (phy_index == EXT_PHY2) {
11434		link_config = REG_RD(bp, params->shmem_base +
11435				     offsetof(struct shmem_region, dev_info.
11436			port_feature_config[params->port].link_config2));
11437		phy->speed_cap_mask = REG_RD(bp, params->shmem_base +
11438					     offsetof(struct shmem_region,
11439						      dev_info.
11440			port_hw_config[params->port].speed_capability_mask2));
11441	} else {
11442		link_config = REG_RD(bp, params->shmem_base +
11443				     offsetof(struct shmem_region, dev_info.
11444				port_feature_config[params->port].link_config));
11445		phy->speed_cap_mask = REG_RD(bp, params->shmem_base +
11446					     offsetof(struct shmem_region,
11447						      dev_info.
11448			port_hw_config[params->port].speed_capability_mask));
11449	}
11450	DP(NETIF_MSG_LINK,
11451	   "Default config phy idx %x cfg 0x%x speed_cap_mask 0x%x\n",
11452	   phy_index, link_config, phy->speed_cap_mask);
11453
11454	phy->req_duplex = DUPLEX_FULL;
11455	switch (link_config  & PORT_FEATURE_LINK_SPEED_MASK) {
11456	case PORT_FEATURE_LINK_SPEED_10M_HALF:
11457		phy->req_duplex = DUPLEX_HALF;
11458	case PORT_FEATURE_LINK_SPEED_10M_FULL:
11459		phy->req_line_speed = SPEED_10;
11460		break;
11461	case PORT_FEATURE_LINK_SPEED_100M_HALF:
11462		phy->req_duplex = DUPLEX_HALF;
11463	case PORT_FEATURE_LINK_SPEED_100M_FULL:
11464		phy->req_line_speed = SPEED_100;
11465		break;
11466	case PORT_FEATURE_LINK_SPEED_1G:
11467		phy->req_line_speed = SPEED_1000;
11468		break;
11469	case PORT_FEATURE_LINK_SPEED_2_5G:
11470		phy->req_line_speed = SPEED_2500;
11471		break;
11472	case PORT_FEATURE_LINK_SPEED_10G_CX4:
11473		phy->req_line_speed = SPEED_10000;
11474		break;
11475	default:
11476		phy->req_line_speed = SPEED_AUTO_NEG;
11477		break;
11478	}
11479
11480	switch (link_config  & PORT_FEATURE_FLOW_CONTROL_MASK) {
11481	case PORT_FEATURE_FLOW_CONTROL_AUTO:
11482		phy->req_flow_ctrl = BNX2X_FLOW_CTRL_AUTO;
11483		break;
11484	case PORT_FEATURE_FLOW_CONTROL_TX:
11485		phy->req_flow_ctrl = BNX2X_FLOW_CTRL_TX;
11486		break;
11487	case PORT_FEATURE_FLOW_CONTROL_RX:
11488		phy->req_flow_ctrl = BNX2X_FLOW_CTRL_RX;
11489		break;
11490	case PORT_FEATURE_FLOW_CONTROL_BOTH:
11491		phy->req_flow_ctrl = BNX2X_FLOW_CTRL_BOTH;
11492		break;
11493	default:
11494		phy->req_flow_ctrl = BNX2X_FLOW_CTRL_NONE;
11495		break;
11496	}
11497}
11498
11499u32 bnx2x_phy_selection(struct link_params *params)
11500{
11501	u32 phy_config_swapped, prio_cfg;
11502	u32 return_cfg = PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT;
11503
11504	phy_config_swapped = params->multi_phy_config &
11505		PORT_HW_CFG_PHY_SWAPPED_ENABLED;
11506
11507	prio_cfg = params->multi_phy_config &
11508			PORT_HW_CFG_PHY_SELECTION_MASK;
11509
11510	if (phy_config_swapped) {
11511		switch (prio_cfg) {
11512		case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
11513		     return_cfg = PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY;
11514		     break;
11515		case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
11516		     return_cfg = PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY;
11517		     break;
11518		case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY:
11519		     return_cfg = PORT_HW_CFG_PHY_SELECTION_FIRST_PHY;
11520		     break;
11521		case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY:
11522		     return_cfg = PORT_HW_CFG_PHY_SELECTION_SECOND_PHY;
11523		     break;
11524		}
11525	} else
11526		return_cfg = prio_cfg;
11527
11528	return return_cfg;
11529}
11530
11531
11532int bnx2x_phy_probe(struct link_params *params)
11533{
11534	u8 phy_index, actual_phy_idx, link_cfg_idx;
11535	u32 phy_config_swapped, sync_offset, media_types;
11536	struct bnx2x *bp = params->bp;
11537	struct bnx2x_phy *phy;
11538	params->num_phys = 0;
11539	DP(NETIF_MSG_LINK, "Begin phy probe\n");
11540	phy_config_swapped = params->multi_phy_config &
11541		PORT_HW_CFG_PHY_SWAPPED_ENABLED;
11542
11543	for (phy_index = INT_PHY; phy_index < MAX_PHYS;
11544	      phy_index++) {
11545		link_cfg_idx = LINK_CONFIG_IDX(phy_index);
11546		actual_phy_idx = phy_index;
11547		if (phy_config_swapped) {
11548			if (phy_index == EXT_PHY1)
11549				actual_phy_idx = EXT_PHY2;
11550			else if (phy_index == EXT_PHY2)
11551				actual_phy_idx = EXT_PHY1;
11552		}
11553		DP(NETIF_MSG_LINK, "phy_config_swapped %x, phy_index %x,"
11554			       " actual_phy_idx %x\n", phy_config_swapped,
11555			   phy_index, actual_phy_idx);
11556		phy = &params->phy[actual_phy_idx];
11557		if (bnx2x_populate_phy(bp, phy_index, params->shmem_base,
11558				       params->shmem2_base, params->port,
11559				       phy) != 0) {
11560			params->num_phys = 0;
11561			DP(NETIF_MSG_LINK, "phy probe failed in phy index %d\n",
11562				   phy_index);
11563			for (phy_index = INT_PHY;
11564			      phy_index < MAX_PHYS;
11565			      phy_index++)
11566				*phy = phy_null;
11567			return -EINVAL;
11568		}
11569		if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)
11570			break;
11571
11572		sync_offset = params->shmem_base +
11573			offsetof(struct shmem_region,
11574			dev_info.port_hw_config[params->port].media_type);
11575		media_types = REG_RD(bp, sync_offset);
11576
11577		/*
11578		 * Update media type for non-PMF sync only for the first time
11579		 * In case the media type changes afterwards, it will be updated
11580		 * using the update_status function
11581		 */
11582		if ((media_types & (PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK <<
11583				    (PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT *
11584				     actual_phy_idx))) == 0) {
11585			media_types |= ((phy->media_type &
11586					PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK) <<
11587				(PORT_HW_CFG_MEDIA_TYPE_PHY1_SHIFT *
11588				 actual_phy_idx));
11589		}
11590		REG_WR(bp, sync_offset, media_types);
11591
11592		bnx2x_phy_def_cfg(params, phy, phy_index);
11593		params->num_phys++;
11594	}
11595
11596	DP(NETIF_MSG_LINK, "End phy probe. #phys found %x\n", params->num_phys);
11597	return 0;
11598}
11599
11600void bnx2x_init_bmac_loopback(struct link_params *params,
11601			      struct link_vars *vars)
11602{
11603	struct bnx2x *bp = params->bp;
11604		vars->link_up = 1;
11605		vars->line_speed = SPEED_10000;
11606		vars->duplex = DUPLEX_FULL;
11607		vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
11608		vars->mac_type = MAC_TYPE_BMAC;
11609
11610		vars->phy_flags = PHY_XGXS_FLAG;
11611
11612		bnx2x_xgxs_deassert(params);
11613
11614		/* set bmac loopback */
11615		bnx2x_bmac_enable(params, vars, 1);
11616
11617		REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
11618}
11619
11620void bnx2x_init_emac_loopback(struct link_params *params,
11621			      struct link_vars *vars)
11622{
11623	struct bnx2x *bp = params->bp;
11624		vars->link_up = 1;
11625		vars->line_speed = SPEED_1000;
11626		vars->duplex = DUPLEX_FULL;
11627		vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
11628		vars->mac_type = MAC_TYPE_EMAC;
11629
11630		vars->phy_flags = PHY_XGXS_FLAG;
11631
11632		bnx2x_xgxs_deassert(params);
11633		/* set bmac loopback */
11634		bnx2x_emac_enable(params, vars, 1);
11635		bnx2x_emac_program(params, vars);
11636		REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
11637}
11638
11639void bnx2x_init_xmac_loopback(struct link_params *params,
11640			      struct link_vars *vars)
11641{
11642	struct bnx2x *bp = params->bp;
11643	vars->link_up = 1;
11644	if (!params->req_line_speed[0])
11645		vars->line_speed = SPEED_10000;
11646	else
11647		vars->line_speed = params->req_line_speed[0];
11648	vars->duplex = DUPLEX_FULL;
11649	vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
11650	vars->mac_type = MAC_TYPE_XMAC;
11651	vars->phy_flags = PHY_XGXS_FLAG;
11652	/*
11653	 * Set WC to loopback mode since link is required to provide clock
11654	 * to the XMAC in 20G mode
11655	 */
11656	bnx2x_set_aer_mmd(params, &params->phy[0]);
11657	bnx2x_warpcore_reset_lane(bp, &params->phy[0], 0);
11658	params->phy[INT_PHY].config_loopback(
11659			&params->phy[INT_PHY],
11660			params);
11661
11662	bnx2x_xmac_enable(params, vars, 1);
11663	REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
11664}
11665
11666void bnx2x_init_umac_loopback(struct link_params *params,
11667			      struct link_vars *vars)
11668{
11669	struct bnx2x *bp = params->bp;
11670	vars->link_up = 1;
11671	vars->line_speed = SPEED_1000;
11672	vars->duplex = DUPLEX_FULL;
11673	vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
11674	vars->mac_type = MAC_TYPE_UMAC;
11675	vars->phy_flags = PHY_XGXS_FLAG;
11676	bnx2x_umac_enable(params, vars, 1);
11677
11678	REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
11679}
11680
11681void bnx2x_init_xgxs_loopback(struct link_params *params,
11682			      struct link_vars *vars)
11683{
11684	struct bnx2x *bp = params->bp;
11685		vars->link_up = 1;
11686		vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
11687		vars->duplex = DUPLEX_FULL;
11688	if (params->req_line_speed[0] == SPEED_1000)
11689			vars->line_speed = SPEED_1000;
11690	else
11691			vars->line_speed = SPEED_10000;
11692
11693	if (!USES_WARPCORE(bp))
11694		bnx2x_xgxs_deassert(params);
11695	bnx2x_link_initialize(params, vars);
11696
11697	if (params->req_line_speed[0] == SPEED_1000) {
11698		if (USES_WARPCORE(bp))
11699			bnx2x_umac_enable(params, vars, 0);
11700		else {
11701			bnx2x_emac_program(params, vars);
11702			bnx2x_emac_enable(params, vars, 0);
11703		}
11704	} else {
11705		if (USES_WARPCORE(bp))
11706			bnx2x_xmac_enable(params, vars, 0);
11707		else
11708			bnx2x_bmac_enable(params, vars, 0);
11709	}
11710
11711		if (params->loopback_mode == LOOPBACK_XGXS) {
11712			/* set 10G XGXS loopback */
11713			params->phy[INT_PHY].config_loopback(
11714				&params->phy[INT_PHY],
11715				params);
11716
11717		} else {
11718			/* set external phy loopback */
11719			u8 phy_index;
11720			for (phy_index = EXT_PHY1;
11721			      phy_index < params->num_phys; phy_index++) {
11722				if (params->phy[phy_index].config_loopback)
11723					params->phy[phy_index].config_loopback(
11724						&params->phy[phy_index],
11725						params);
11726			}
11727		}
11728		REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
11729
11730	bnx2x_set_led(params, vars, LED_MODE_OPER, vars->line_speed);
11731}
11732
11733int bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
11734{
11735	struct bnx2x *bp = params->bp;
11736	DP(NETIF_MSG_LINK, "Phy Initialization started\n");
11737	DP(NETIF_MSG_LINK, "(1) req_speed %d, req_flowctrl %d\n",
11738		   params->req_line_speed[0], params->req_flow_ctrl[0]);
11739	DP(NETIF_MSG_LINK, "(2) req_speed %d, req_flowctrl %d\n",
11740		   params->req_line_speed[1], params->req_flow_ctrl[1]);
11741	vars->link_status = 0;
11742	vars->phy_link_up = 0;
11743	vars->link_up = 0;
11744	vars->line_speed = 0;
11745	vars->duplex = DUPLEX_FULL;
11746	vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
11747	vars->mac_type = MAC_TYPE_NONE;
11748	vars->phy_flags = 0;
11749
11750	/* disable attentions */
11751	bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + params->port*4,
11752		       (NIG_MASK_XGXS0_LINK_STATUS |
11753			NIG_MASK_XGXS0_LINK10G |
11754			NIG_MASK_SERDES0_LINK_STATUS |
11755			NIG_MASK_MI_INT));
11756
11757	bnx2x_emac_init(params, vars);
11758
11759	if (params->num_phys == 0) {
11760		DP(NETIF_MSG_LINK, "No phy found for initialization !!\n");
11761		return -EINVAL;
11762	}
11763	set_phy_vars(params, vars);
11764
11765	DP(NETIF_MSG_LINK, "Num of phys on board: %d\n", params->num_phys);
11766	switch (params->loopback_mode) {
11767	case LOOPBACK_BMAC:
11768		bnx2x_init_bmac_loopback(params, vars);
11769		break;
11770	case LOOPBACK_EMAC:
11771		bnx2x_init_emac_loopback(params, vars);
11772		break;
11773	case LOOPBACK_XMAC:
11774		bnx2x_init_xmac_loopback(params, vars);
11775		break;
11776	case LOOPBACK_UMAC:
11777		bnx2x_init_umac_loopback(params, vars);
11778		break;
11779	case LOOPBACK_XGXS:
11780	case LOOPBACK_EXT_PHY:
11781		bnx2x_init_xgxs_loopback(params, vars);
11782		break;
11783	default:
11784		if (!CHIP_IS_E3(bp)) {
11785			if (params->switch_cfg == SWITCH_CFG_10G)
11786				bnx2x_xgxs_deassert(params);
11787			else
11788				bnx2x_serdes_deassert(bp, params->port);
11789		}
11790		bnx2x_link_initialize(params, vars);
11791		msleep(30);
11792		bnx2x_link_int_enable(params);
11793		break;
11794	}
11795	return 0;
11796}
11797
11798int bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
11799		     u8 reset_ext_phy)
11800{
11801	struct bnx2x *bp = params->bp;
11802	u8 phy_index, port = params->port, clear_latch_ind = 0;
11803	DP(NETIF_MSG_LINK, "Resetting the link of port %d\n", port);
11804	/* disable attentions */
11805	vars->link_status = 0;
11806	bnx2x_update_mng(params, vars->link_status);
11807	bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
11808		       (NIG_MASK_XGXS0_LINK_STATUS |
11809			NIG_MASK_XGXS0_LINK10G |
11810			NIG_MASK_SERDES0_LINK_STATUS |
11811			NIG_MASK_MI_INT));
11812
11813	/* activate nig drain */
11814	REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
11815
11816	/* disable nig egress interface */
11817	if (!CHIP_IS_E3(bp)) {
11818		REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0);
11819		REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0);
11820	}
11821
11822	/* Stop BigMac rx */
11823	if (!CHIP_IS_E3(bp))
11824		bnx2x_bmac_rx_disable(bp, port);
11825	else {
11826		bnx2x_xmac_disable(params);
11827		bnx2x_umac_disable(params);
11828	}
11829	/* disable emac */
11830	if (!CHIP_IS_E3(bp))
11831		REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
11832
11833	msleep(10);
11834	/* The PHY reset is controlled by GPIO 1
11835	 * Hold it as vars low
11836	 */
11837	 /* clear link led */
11838	bnx2x_set_led(params, vars, LED_MODE_OFF, 0);
11839
11840	if (reset_ext_phy) {
11841		bnx2x_set_mdio_clk(bp, params->chip_id, port);
11842		for (phy_index = EXT_PHY1; phy_index < params->num_phys;
11843		      phy_index++) {
11844			if (params->phy[phy_index].link_reset) {
11845				bnx2x_set_aer_mmd(params,
11846						  &params->phy[phy_index]);
11847				params->phy[phy_index].link_reset(
11848					&params->phy[phy_index],
11849					params);
11850			}
11851			if (params->phy[phy_index].flags &
11852			    FLAGS_REARM_LATCH_SIGNAL)
11853				clear_latch_ind = 1;
11854		}
11855	}
11856
11857	if (clear_latch_ind) {
11858		/* Clear latching indication */
11859		bnx2x_rearm_latch_signal(bp, port, 0);
11860		bnx2x_bits_dis(bp, NIG_REG_LATCH_BC_0 + port*4,
11861			       1 << NIG_LATCH_BC_ENABLE_MI_INT);
11862	}
11863	if (params->phy[INT_PHY].link_reset)
11864		params->phy[INT_PHY].link_reset(
11865			&params->phy[INT_PHY], params);
11866
11867	/* disable nig ingress interface */
11868	if (!CHIP_IS_E3(bp)) {
11869		/* reset BigMac */
11870		REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
11871		       (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
11872		REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0);
11873		REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0);
11874	} else {
11875		u32 xmac_base = (params->port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
11876		bnx2x_set_xumac_nig(params, 0, 0);
11877		if (REG_RD(bp, MISC_REG_RESET_REG_2) &
11878		    MISC_REGISTERS_RESET_REG_2_XMAC)
11879			REG_WR(bp, xmac_base + XMAC_REG_CTRL,
11880			       XMAC_CTRL_REG_SOFT_RESET);
11881	}
11882	vars->link_up = 0;
11883	vars->phy_flags = 0;
11884	return 0;
11885}
11886
11887/****************************************************************************/
11888/*				Common function				    */
11889/****************************************************************************/
11890static int bnx2x_8073_common_init_phy(struct bnx2x *bp,
11891				      u32 shmem_base_path[],
11892				      u32 shmem2_base_path[], u8 phy_index,
11893				      u32 chip_id)
11894{
11895	struct bnx2x_phy phy[PORT_MAX];
11896	struct bnx2x_phy *phy_blk[PORT_MAX];
11897	u16 val;
11898	s8 port = 0;
11899	s8 port_of_path = 0;
11900	u32 swap_val, swap_override;
11901	swap_val = REG_RD(bp,  NIG_REG_PORT_SWAP);
11902	swap_override = REG_RD(bp,  NIG_REG_STRAP_OVERRIDE);
11903	port ^= (swap_val && swap_override);
11904	bnx2x_ext_phy_hw_reset(bp, port);
11905	/* PART1 - Reset both phys */
11906	for (port = PORT_MAX - 1; port >= PORT_0; port--) {
11907		u32 shmem_base, shmem2_base;
11908		/* In E2, same phy is using for port0 of the two paths */
11909		if (CHIP_IS_E1x(bp)) {
11910			shmem_base = shmem_base_path[0];
11911			shmem2_base = shmem2_base_path[0];
11912			port_of_path = port;
11913		} else {
11914			shmem_base = shmem_base_path[port];
11915			shmem2_base = shmem2_base_path[port];
11916			port_of_path = 0;
11917		}
11918
11919		/* Extract the ext phy address for the port */
11920		if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
11921				       port_of_path, &phy[port]) !=
11922		    0) {
11923			DP(NETIF_MSG_LINK, "populate_phy failed\n");
11924			return -EINVAL;
11925		}
11926		/* disable attentions */
11927		bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 +
11928			       port_of_path*4,
11929			       (NIG_MASK_XGXS0_LINK_STATUS |
11930				NIG_MASK_XGXS0_LINK10G |
11931				NIG_MASK_SERDES0_LINK_STATUS |
11932				NIG_MASK_MI_INT));
11933
11934		/* Need to take the phy out of low power mode in order
11935			to write to access its registers */
11936		bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
11937			       MISC_REGISTERS_GPIO_OUTPUT_HIGH,
11938			       port);
11939
11940		/* Reset the phy */
11941		bnx2x_cl45_write(bp, &phy[port],
11942				 MDIO_PMA_DEVAD,
11943				 MDIO_PMA_REG_CTRL,
11944				 1<<15);
11945	}
11946
11947	/* Add delay of 150ms after reset */
11948	msleep(150);
11949
11950	if (phy[PORT_0].addr & 0x1) {
11951		phy_blk[PORT_0] = &(phy[PORT_1]);
11952		phy_blk[PORT_1] = &(phy[PORT_0]);
11953	} else {
11954		phy_blk[PORT_0] = &(phy[PORT_0]);
11955		phy_blk[PORT_1] = &(phy[PORT_1]);
11956	}
11957
11958	/* PART2 - Download firmware to both phys */
11959	for (port = PORT_MAX - 1; port >= PORT_0; port--) {
11960		if (CHIP_IS_E1x(bp))
11961			port_of_path = port;
11962		else
11963			port_of_path = 0;
11964
11965		DP(NETIF_MSG_LINK, "Loading spirom for phy address 0x%x\n",
11966			   phy_blk[port]->addr);
11967		if (bnx2x_8073_8727_external_rom_boot(bp, phy_blk[port],
11968						      port_of_path))
11969			return -EINVAL;
11970
11971		/* Only set bit 10 = 1 (Tx power down) */
11972		bnx2x_cl45_read(bp, phy_blk[port],
11973				MDIO_PMA_DEVAD,
11974				MDIO_PMA_REG_TX_POWER_DOWN, &val);
11975
11976		/* Phase1 of TX_POWER_DOWN reset */
11977		bnx2x_cl45_write(bp, phy_blk[port],
11978				 MDIO_PMA_DEVAD,
11979				 MDIO_PMA_REG_TX_POWER_DOWN,
11980				 (val | 1<<10));
11981	}
11982
11983	/*
11984	 * Toggle Transmitter: Power down and then up with 600ms delay
11985	 * between
11986	 */
11987	msleep(600);
11988
11989	/* PART3 - complete TX_POWER_DOWN process, and set GPIO2 back to low */
11990	for (port = PORT_MAX - 1; port >= PORT_0; port--) {
11991		/* Phase2 of POWER_DOWN_RESET */
11992		/* Release bit 10 (Release Tx power down) */
11993		bnx2x_cl45_read(bp, phy_blk[port],
11994				MDIO_PMA_DEVAD,
11995				MDIO_PMA_REG_TX_POWER_DOWN, &val);
11996
11997		bnx2x_cl45_write(bp, phy_blk[port],
11998				MDIO_PMA_DEVAD,
11999				MDIO_PMA_REG_TX_POWER_DOWN, (val & (~(1<<10))));
12000		msleep(15);
12001
12002		/* Read modify write the SPI-ROM version select register */
12003		bnx2x_cl45_read(bp, phy_blk[port],
12004				MDIO_PMA_DEVAD,
12005				MDIO_PMA_REG_EDC_FFE_MAIN, &val);
12006		bnx2x_cl45_write(bp, phy_blk[port],
12007				 MDIO_PMA_DEVAD,
12008				 MDIO_PMA_REG_EDC_FFE_MAIN, (val | (1<<12)));
12009
12010		/* set GPIO2 back to LOW */
12011		bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
12012			       MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
12013	}
12014	return 0;
12015}
12016static int bnx2x_8726_common_init_phy(struct bnx2x *bp,
12017				      u32 shmem_base_path[],
12018				      u32 shmem2_base_path[], u8 phy_index,
12019				      u32 chip_id)
12020{
12021	u32 val;
12022	s8 port;
12023	struct bnx2x_phy phy;
12024	/* Use port1 because of the static port-swap */
12025	/* Enable the module detection interrupt */
12026	val = REG_RD(bp, MISC_REG_GPIO_EVENT_EN);
12027	val |= ((1<<MISC_REGISTERS_GPIO_3)|
12028		(1<<(MISC_REGISTERS_GPIO_3 + MISC_REGISTERS_GPIO_PORT_SHIFT)));
12029	REG_WR(bp, MISC_REG_GPIO_EVENT_EN, val);
12030
12031	bnx2x_ext_phy_hw_reset(bp, 0);
12032	msleep(5);
12033	for (port = 0; port < PORT_MAX; port++) {
12034		u32 shmem_base, shmem2_base;
12035
12036		/* In E2, same phy is using for port0 of the two paths */
12037		if (CHIP_IS_E1x(bp)) {
12038			shmem_base = shmem_base_path[0];
12039			shmem2_base = shmem2_base_path[0];
12040		} else {
12041			shmem_base = shmem_base_path[port];
12042			shmem2_base = shmem2_base_path[port];
12043		}
12044		/* Extract the ext phy address for the port */
12045		if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
12046				       port, &phy) !=
12047		    0) {
12048			DP(NETIF_MSG_LINK, "populate phy failed\n");
12049			return -EINVAL;
12050		}
12051
12052		/* Reset phy*/
12053		bnx2x_cl45_write(bp, &phy,
12054				 MDIO_PMA_DEVAD, MDIO_PMA_REG_GEN_CTRL, 0x0001);
12055
12056
12057		/* Set fault module detected LED on */
12058		bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
12059			       MISC_REGISTERS_GPIO_HIGH,
12060			       port);
12061	}
12062
12063	return 0;
12064}
12065static void bnx2x_get_ext_phy_reset_gpio(struct bnx2x *bp, u32 shmem_base,
12066					 u8 *io_gpio, u8 *io_port)
12067{
12068
12069	u32 phy_gpio_reset = REG_RD(bp, shmem_base +
12070					  offsetof(struct shmem_region,
12071				dev_info.port_hw_config[PORT_0].default_cfg));
12072	switch (phy_gpio_reset) {
12073	case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P0:
12074		*io_gpio = 0;
12075		*io_port = 0;
12076		break;
12077	case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P0:
12078		*io_gpio = 1;
12079		*io_port = 0;
12080		break;
12081	case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P0:
12082		*io_gpio = 2;
12083		*io_port = 0;
12084		break;
12085	case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P0:
12086		*io_gpio = 3;
12087		*io_port = 0;
12088		break;
12089	case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P1:
12090		*io_gpio = 0;
12091		*io_port = 1;
12092		break;
12093	case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P1:
12094		*io_gpio = 1;
12095		*io_port = 1;
12096		break;
12097	case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P1:
12098		*io_gpio = 2;
12099		*io_port = 1;
12100		break;
12101	case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P1:
12102		*io_gpio = 3;
12103		*io_port = 1;
12104		break;
12105	default:
12106		/* Don't override the io_gpio and io_port */
12107		break;
12108	}
12109}
12110
12111static int bnx2x_8727_common_init_phy(struct bnx2x *bp,
12112				      u32 shmem_base_path[],
12113				      u32 shmem2_base_path[], u8 phy_index,
12114				      u32 chip_id)
12115{
12116	s8 port, reset_gpio;
12117	u32 swap_val, swap_override;
12118	struct bnx2x_phy phy[PORT_MAX];
12119	struct bnx2x_phy *phy_blk[PORT_MAX];
12120	s8 port_of_path;
12121	swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
12122	swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
12123
12124	reset_gpio = MISC_REGISTERS_GPIO_1;
12125	port = 1;
12126
12127	/*
12128	 * Retrieve the reset gpio/port which control the reset.
12129	 * Default is GPIO1, PORT1
12130	 */
12131	bnx2x_get_ext_phy_reset_gpio(bp, shmem_base_path[0],
12132				     (u8 *)&reset_gpio, (u8 *)&port);
12133
12134	/* Calculate the port based on port swap */
12135	port ^= (swap_val && swap_override);
12136
12137	/* Initiate PHY reset*/
12138	bnx2x_set_gpio(bp, reset_gpio, MISC_REGISTERS_GPIO_OUTPUT_LOW,
12139		       port);
12140	msleep(1);
12141	bnx2x_set_gpio(bp, reset_gpio, MISC_REGISTERS_GPIO_OUTPUT_HIGH,
12142		       port);
12143
12144	msleep(5);
12145
12146	/* PART1 - Reset both phys */
12147	for (port = PORT_MAX - 1; port >= PORT_0; port--) {
12148		u32 shmem_base, shmem2_base;
12149
12150		/* In E2, same phy is using for port0 of the two paths */
12151		if (CHIP_IS_E1x(bp)) {
12152			shmem_base = shmem_base_path[0];
12153			shmem2_base = shmem2_base_path[0];
12154			port_of_path = port;
12155		} else {
12156			shmem_base = shmem_base_path[port];
12157			shmem2_base = shmem2_base_path[port];
12158			port_of_path = 0;
12159		}
12160
12161		/* Extract the ext phy address for the port */
12162		if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
12163				       port_of_path, &phy[port]) !=
12164				       0) {
12165			DP(NETIF_MSG_LINK, "populate phy failed\n");
12166			return -EINVAL;
12167		}
12168		/* disable attentions */
12169		bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 +
12170			       port_of_path*4,
12171			       (NIG_MASK_XGXS0_LINK_STATUS |
12172				NIG_MASK_XGXS0_LINK10G |
12173				NIG_MASK_SERDES0_LINK_STATUS |
12174				NIG_MASK_MI_INT));
12175
12176
12177		/* Reset the phy */
12178		bnx2x_cl45_write(bp, &phy[port],
12179				 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
12180	}
12181
12182	/* Add delay of 150ms after reset */
12183	msleep(150);
12184	if (phy[PORT_0].addr & 0x1) {
12185		phy_blk[PORT_0] = &(phy[PORT_1]);
12186		phy_blk[PORT_1] = &(phy[PORT_0]);
12187	} else {
12188		phy_blk[PORT_0] = &(phy[PORT_0]);
12189		phy_blk[PORT_1] = &(phy[PORT_1]);
12190	}
12191	/* PART2 - Download firmware to both phys */
12192	for (port = PORT_MAX - 1; port >= PORT_0; port--) {
12193		if (CHIP_IS_E1x(bp))
12194			port_of_path = port;
12195		else
12196			port_of_path = 0;
12197		DP(NETIF_MSG_LINK, "Loading spirom for phy address 0x%x\n",
12198			   phy_blk[port]->addr);
12199		if (bnx2x_8073_8727_external_rom_boot(bp, phy_blk[port],
12200						      port_of_path))
12201			return -EINVAL;
12202		/* Disable PHY transmitter output */
12203		bnx2x_cl45_write(bp, phy_blk[port],
12204				 MDIO_PMA_DEVAD,
12205				 MDIO_PMA_REG_TX_DISABLE, 1);
12206
12207	}
12208	return 0;
12209}
12210
12211static int bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
12212				     u32 shmem2_base_path[], u8 phy_index,
12213				     u32 ext_phy_type, u32 chip_id)
12214{
12215	int rc = 0;
12216
12217	switch (ext_phy_type) {
12218	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
12219		rc = bnx2x_8073_common_init_phy(bp, shmem_base_path,
12220						shmem2_base_path,
12221						phy_index, chip_id);
12222		break;
12223	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722:
12224	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
12225	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC:
12226		rc = bnx2x_8727_common_init_phy(bp, shmem_base_path,
12227						shmem2_base_path,
12228						phy_index, chip_id);
12229		break;
12230
12231	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
12232		/*
12233		 * GPIO1 affects both ports, so there's need to pull
12234		 * it for single port alone
12235		 */
12236		rc = bnx2x_8726_common_init_phy(bp, shmem_base_path,
12237						shmem2_base_path,
12238						phy_index, chip_id);
12239		break;
12240	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833:
12241		/*
12242		 * GPIO3's are linked, and so both need to be toggled
12243		 * to obtain required 2us pulse.
12244		 */
12245		rc = bnx2x_84833_common_init_phy(bp, shmem_base_path, chip_id);
12246		break;
12247	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
12248		rc = -EINVAL;
12249		break;
12250	default:
12251		DP(NETIF_MSG_LINK,
12252			   "ext_phy 0x%x common init not required\n",
12253			   ext_phy_type);
12254		break;
12255	}
12256
12257	if (rc != 0)
12258		netdev_err(bp->dev,  "Warning: PHY was not initialized,"
12259				      " Port %d\n",
12260			 0);
12261	return rc;
12262}
12263
12264int bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[],
12265			  u32 shmem2_base_path[], u32 chip_id)
12266{
12267	int rc = 0;
12268	u32 phy_ver, val;
12269	u8 phy_index = 0;
12270	u32 ext_phy_type, ext_phy_config;
12271	bnx2x_set_mdio_clk(bp, chip_id, PORT_0);
12272	bnx2x_set_mdio_clk(bp, chip_id, PORT_1);
12273	DP(NETIF_MSG_LINK, "Begin common phy init\n");
12274	if (CHIP_IS_E3(bp)) {
12275		/* Enable EPIO */
12276		val = REG_RD(bp, MISC_REG_GEN_PURP_HWG);
12277		REG_WR(bp, MISC_REG_GEN_PURP_HWG, val | 1);
12278	}
12279	/* Check if common init was already done */
12280	phy_ver = REG_RD(bp, shmem_base_path[0] +
12281			 offsetof(struct shmem_region,
12282				  port_mb[PORT_0].ext_phy_fw_version));
12283	if (phy_ver) {
12284		DP(NETIF_MSG_LINK, "Not doing common init; phy ver is 0x%x\n",
12285			       phy_ver);
12286		return 0;
12287	}
12288
12289	/* Read the ext_phy_type for arbitrary port(0) */
12290	for (phy_index = EXT_PHY1; phy_index < MAX_PHYS;
12291	      phy_index++) {
12292		ext_phy_config = bnx2x_get_ext_phy_config(bp,
12293							  shmem_base_path[0],
12294							  phy_index, 0);
12295		ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
12296		rc |= bnx2x_ext_phy_common_init(bp, shmem_base_path,
12297						shmem2_base_path,
12298						phy_index, ext_phy_type,
12299						chip_id);
12300	}
12301	return rc;
12302}
12303
12304static void bnx2x_check_over_curr(struct link_params *params,
12305				  struct link_vars *vars)
12306{
12307	struct bnx2x *bp = params->bp;
12308	u32 cfg_pin;
12309	u8 port = params->port;
12310	u32 pin_val;
12311
12312	cfg_pin = (REG_RD(bp, params->shmem_base +
12313			  offsetof(struct shmem_region,
12314			       dev_info.port_hw_config[port].e3_cmn_pin_cfg1)) &
12315		   PORT_HW_CFG_E3_OVER_CURRENT_MASK) >>
12316		PORT_HW_CFG_E3_OVER_CURRENT_SHIFT;
12317
12318	/* Ignore check if no external input PIN available */
12319	if (bnx2x_get_cfg_pin(bp, cfg_pin, &pin_val) != 0)
12320		return;
12321
12322	if (!pin_val) {
12323		if ((vars->phy_flags & PHY_OVER_CURRENT_FLAG) == 0) {
12324			netdev_err(bp->dev, "Error:  Power fault on Port %d has"
12325					    " been detected and the power to "
12326					    "that SFP+ module has been removed"
12327					    " to prevent failure of the card."
12328					    " Please remove the SFP+ module and"
12329					    " restart the system to clear this"
12330					    " error.\n",
12331			 params->port);
12332			vars->phy_flags |= PHY_OVER_CURRENT_FLAG;
12333		}
12334	} else
12335		vars->phy_flags &= ~PHY_OVER_CURRENT_FLAG;
12336}
12337
12338static void bnx2x_analyze_link_error(struct link_params *params,
12339				     struct link_vars *vars, u32 lss_status)
12340{
12341	struct bnx2x *bp = params->bp;
12342	/* Compare new value with previous value */
12343	u8 led_mode;
12344	u32 half_open_conn = (vars->phy_flags & PHY_HALF_OPEN_CONN_FLAG) > 0;
12345
12346	if ((lss_status ^ half_open_conn) == 0)
12347		return;
12348
12349	/* If values differ */
12350	DP(NETIF_MSG_LINK, "Link changed:%x %x->%x\n", vars->link_up,
12351		       half_open_conn, lss_status);
12352
12353	/*
12354	 * a. Update shmem->link_status accordingly
12355	 * b. Update link_vars->link_up
12356	 */
12357	if (lss_status) {
12358		DP(NETIF_MSG_LINK, "Remote Fault detected !!!\n");
12359		vars->link_status &= ~LINK_STATUS_LINK_UP;
12360		vars->link_up = 0;
12361		vars->phy_flags |= PHY_HALF_OPEN_CONN_FLAG;
12362		/*
12363		 * Set LED mode to off since the PHY doesn't know about these
12364		 * errors
12365		 */
12366		led_mode = LED_MODE_OFF;
12367	} else {
12368		DP(NETIF_MSG_LINK, "Remote Fault cleared\n");
12369		vars->link_status |= LINK_STATUS_LINK_UP;
12370		vars->link_up = 1;
12371		vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG;
12372		led_mode = LED_MODE_OPER;
12373	}
12374	/* Update the LED according to the link state */
12375	bnx2x_set_led(params, vars, led_mode, SPEED_10000);
12376
12377	/* Update link status in the shared memory */
12378	bnx2x_update_mng(params, vars->link_status);
12379
12380	/* C. Trigger General Attention */
12381	vars->periodic_flags |= PERIODIC_FLAGS_LINK_EVENT;
12382	bnx2x_notify_link_changed(bp);
12383}
12384
12385/******************************************************************************
12386* Description:
12387*	This function checks for half opened connection change indication.
12388*	When such change occurs, it calls the bnx2x_analyze_link_error
12389*	to check if Remote Fault is set or cleared. Reception of remote fault
12390*	status message in the MAC indicates that the peer's MAC has detected
12391*	a fault, for example, due to break in the TX side of fiber.
12392*
12393******************************************************************************/
12394static void bnx2x_check_half_open_conn(struct link_params *params,
12395				       struct link_vars *vars)
12396{
12397	struct bnx2x *bp = params->bp;
12398	u32 lss_status = 0;
12399	u32 mac_base;
12400	/* In case link status is physically up @ 10G do */
12401	if ((vars->phy_flags & PHY_PHYSICAL_LINK_FLAG) == 0)
12402		return;
12403
12404	if (CHIP_IS_E3(bp) &&
12405	    (REG_RD(bp, MISC_REG_RESET_REG_2) &
12406	      (MISC_REGISTERS_RESET_REG_2_XMAC))) {
12407		/* Check E3 XMAC */
12408		/*
12409		 * Note that link speed cannot be queried here, since it may be
12410		 * zero while link is down. In case UMAC is active, LSS will
12411		 * simply not be set
12412		 */
12413		mac_base = (params->port) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
12414
12415		/* Clear stick bits (Requires rising edge) */
12416		REG_WR(bp, mac_base + XMAC_REG_CLEAR_RX_LSS_STATUS, 0);
12417		REG_WR(bp, mac_base + XMAC_REG_CLEAR_RX_LSS_STATUS,
12418		       XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_LOCAL_FAULT_STATUS |
12419		       XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_REMOTE_FAULT_STATUS);
12420		if (REG_RD(bp, mac_base + XMAC_REG_RX_LSS_STATUS))
12421			lss_status = 1;
12422
12423		bnx2x_analyze_link_error(params, vars, lss_status);
12424	} else if (REG_RD(bp, MISC_REG_RESET_REG_2) &
12425		   (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port)) {
12426		/* Check E1X / E2 BMAC */
12427		u32 lss_status_reg;
12428		u32 wb_data[2];
12429		mac_base = params->port ? NIG_REG_INGRESS_BMAC1_MEM :
12430			NIG_REG_INGRESS_BMAC0_MEM;
12431		/*  Read BIGMAC_REGISTER_RX_LSS_STATUS */
12432		if (CHIP_IS_E2(bp))
12433			lss_status_reg = BIGMAC2_REGISTER_RX_LSS_STAT;
12434		else
12435			lss_status_reg = BIGMAC_REGISTER_RX_LSS_STATUS;
12436
12437		REG_RD_DMAE(bp, mac_base + lss_status_reg, wb_data, 2);
12438		lss_status = (wb_data[0] > 0);
12439
12440		bnx2x_analyze_link_error(params, vars, lss_status);
12441	}
12442}
12443
12444void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
12445{
12446	struct bnx2x *bp = params->bp;
12447	u16 phy_idx;
12448	for (phy_idx = INT_PHY; phy_idx < MAX_PHYS; phy_idx++) {
12449		if (params->phy[phy_idx].flags & FLAGS_TX_ERROR_CHECK) {
12450			bnx2x_set_aer_mmd(params, &params->phy[phy_idx]);
12451			bnx2x_check_half_open_conn(params, vars);
12452			break;
12453		}
12454	}
12455
12456	if (CHIP_IS_E3(bp)) {
12457		struct bnx2x_phy *phy = &params->phy[INT_PHY];
12458		bnx2x_set_aer_mmd(params, phy);
12459		bnx2x_check_over_curr(params, vars);
12460		bnx2x_warpcore_config_runtime(phy, params, vars);
12461	}
12462
12463}
12464
12465u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base)
12466{
12467	u8 phy_index;
12468	struct bnx2x_phy phy;
12469	for (phy_index = INT_PHY; phy_index < MAX_PHYS;
12470	      phy_index++) {
12471		if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
12472				       0, &phy) != 0) {
12473			DP(NETIF_MSG_LINK, "populate phy failed\n");
12474			return 0;
12475		}
12476
12477		if (phy.flags & FLAGS_HW_LOCK_REQUIRED)
12478			return 1;
12479	}
12480	return 0;
12481}
12482
12483u8 bnx2x_fan_failure_det_req(struct bnx2x *bp,
12484			     u32 shmem_base,
12485			     u32 shmem2_base,
12486			     u8 port)
12487{
12488	u8 phy_index, fan_failure_det_req = 0;
12489	struct bnx2x_phy phy;
12490	for (phy_index = EXT_PHY1; phy_index < MAX_PHYS;
12491	      phy_index++) {
12492		if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
12493				       port, &phy)
12494		    != 0) {
12495			DP(NETIF_MSG_LINK, "populate phy failed\n");
12496			return 0;
12497		}
12498		fan_failure_det_req |= (phy.flags &
12499					FLAGS_FAN_FAILURE_DET_REQ);
12500	}
12501	return fan_failure_det_req;
12502}
12503
12504void bnx2x_hw_reset_phy(struct link_params *params)
12505{
12506	u8 phy_index;
12507	struct bnx2x *bp = params->bp;
12508	bnx2x_update_mng(params, 0);
12509	bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + params->port*4,
12510		       (NIG_MASK_XGXS0_LINK_STATUS |
12511			NIG_MASK_XGXS0_LINK10G |
12512			NIG_MASK_SERDES0_LINK_STATUS |
12513			NIG_MASK_MI_INT));
12514
12515	for (phy_index = INT_PHY; phy_index < MAX_PHYS;
12516	      phy_index++) {
12517		if (params->phy[phy_index].hw_reset) {
12518			params->phy[phy_index].hw_reset(
12519				&params->phy[phy_index],
12520				params);
12521			params->phy[phy_index] = phy_null;
12522		}
12523	}
12524}
12525
12526void bnx2x_init_mod_abs_int(struct bnx2x *bp, struct link_vars *vars,
12527			    u32 chip_id, u32 shmem_base, u32 shmem2_base,
12528			    u8 port)
12529{
12530	u8 gpio_num = 0xff, gpio_port = 0xff, phy_index;
12531	u32 val;
12532	u32 offset, aeu_mask, swap_val, swap_override, sync_offset;
12533	if (CHIP_IS_E3(bp)) {
12534		if (bnx2x_get_mod_abs_int_cfg(bp, chip_id,
12535					      shmem_base,
12536					      port,
12537					      &gpio_num,
12538					      &gpio_port) != 0)
12539			return;
12540	} else {
12541		struct bnx2x_phy phy;
12542		for (phy_index = EXT_PHY1; phy_index < MAX_PHYS;
12543		      phy_index++) {
12544			if (bnx2x_populate_phy(bp, phy_index, shmem_base,
12545					       shmem2_base, port, &phy)
12546			    != 0) {
12547				DP(NETIF_MSG_LINK, "populate phy failed\n");
12548				return;
12549			}
12550			if (phy.type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) {
12551				gpio_num = MISC_REGISTERS_GPIO_3;
12552				gpio_port = port;
12553				break;
12554			}
12555		}
12556	}
12557
12558	if (gpio_num == 0xff)
12559		return;
12560
12561	/* Set GPIO3 to trigger SFP+ module insertion/removal */
12562	bnx2x_set_gpio(bp, gpio_num, MISC_REGISTERS_GPIO_INPUT_HI_Z, gpio_port);
12563
12564	swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
12565	swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
12566	gpio_port ^= (swap_val && swap_override);
12567
12568	vars->aeu_int_mask = AEU_INPUTS_ATTN_BITS_GPIO0_FUNCTION_0 <<
12569		(gpio_num + (gpio_port << 2));
12570
12571	sync_offset = shmem_base +
12572		offsetof(struct shmem_region,
12573			 dev_info.port_hw_config[port].aeu_int_mask);
12574	REG_WR(bp, sync_offset, vars->aeu_int_mask);
12575
12576	DP(NETIF_MSG_LINK, "Setting MOD_ABS (GPIO%d_P%d) AEU to 0x%x\n",
12577		       gpio_num, gpio_port, vars->aeu_int_mask);
12578
12579	if (port == 0)
12580		offset = MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0;
12581	else
12582		offset = MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0;
12583
12584	/* Open appropriate AEU for interrupts */
12585	aeu_mask = REG_RD(bp, offset);
12586	aeu_mask |= vars->aeu_int_mask;
12587	REG_WR(bp, offset, aeu_mask);
12588
12589	/* Enable the GPIO to trigger interrupt */
12590	val = REG_RD(bp, MISC_REG_GPIO_EVENT_EN);
12591	val |= 1 << (gpio_num + (gpio_port << 2));
12592	REG_WR(bp, MISC_REG_GPIO_EVENT_EN, val);
12593}
12594