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 ¶ms->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 ¶ms->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, ®_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, ®_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 ®_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 ®_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, ®_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, ®_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 = ¶ms->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 ¶ms->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 = ¶ms->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 ¶ms->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 ¶ms->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(¶ms->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 = ¶ms->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 ¶ms->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, ¶ms->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 = ¶ms->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 ¶ms->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 ¶ms->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 ¶ms->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 = ¶ms->phy[INT_PHY]; 8233 else 8234 phy = ¶ms->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(¶ms->phy[INT_PHY], params, vars, 0); 9634 bnx2x_program_serdes(¶ms->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 = ¶ms->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, ¶ms->phy[0]); 11657 bnx2x_warpcore_reset_lane(bp, ¶ms->phy[0], 0); 11658 params->phy[INT_PHY].config_loopback( 11659 ¶ms->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 ¶ms->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 ¶ms->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 ¶ms->phy[phy_index]); 11847 params->phy[phy_index].link_reset( 11848 ¶ms->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 ¶ms->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, ¶ms->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 = ¶ms->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 ¶ms->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