aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bnx2x
diff options
context:
space:
mode:
authorYaniv Rosner <yaniv.rosner@broadcom.com>2010-09-07 07:40:54 -0400
committerDavid S. Miller <davem@davemloft.net>2010-09-07 16:13:36 -0400
commitb7737c9be9d3e894d1a4375c52f5f47789475f26 (patch)
treebbc561c7f7104aa14638503948fbcb3ad6546225 /drivers/net/bnx2x
parente10bc84d0e96adff7569161e7d825074a119be36 (diff)
bnx2x: Split PHY functions
Move the code into PHY oriented functions, and for that a new structure is defines for each PHY which contain PHY properties and its own functions. This also enables to encapsulate all PHY specific operations into the PHY functions. During initialization, the PHYs will be probed by the "bnx2x_phy_probe" function to detect which PHYs exist on-board, and configure them accordingly. Note that the ext_phy_reset implementation was incorporated in the ext_phy_init since it is actually part of the PHY initialization procedure. Signed-off-by: Yaniv Rosner <yanivr@broadcom.com> Signed-off-by: Eilon Greenstein <eilong@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bnx2x')
-rw-r--r--drivers/net/bnx2x/bnx2x_ethtool.c35
-rw-r--r--drivers/net/bnx2x/bnx2x_link.c1864
-rw-r--r--drivers/net/bnx2x/bnx2x_link.h109
-rw-r--r--drivers/net/bnx2x/bnx2x_main.c270
4 files changed, 1425 insertions, 853 deletions
diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c
index 2c7e0ab6ccf8..becfd9eb8905 100644
--- a/drivers/net/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/bnx2x/bnx2x_ethtool.c
@@ -52,39 +52,14 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
52 cmd->duplex = -1; 52 cmd->duplex = -1;
53 } 53 }
54 54
55 if (bp->link_params.switch_cfg == SWITCH_CFG_10G) { 55 if (bp->link_params.num_phys > 0) {
56 u32 ext_phy_type = 56 if (bp->link_params.phy[bp->link_params.num_phys - 1].
57 XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config); 57 supported & SUPPORTED_FIBRE)
58
59 switch (ext_phy_type) {
60 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
61 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
62 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
63 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
64 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
65 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
66 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
67 cmd->port = PORT_FIBRE; 58 cmd->port = PORT_FIBRE;
68 break; 59 else
69
70 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
71 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
72 cmd->port = PORT_TP; 60 cmd->port = PORT_TP;
73 break;
74
75 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
76 BNX2X_ERR("XGXS PHY Failure detected 0x%x\n",
77 bp->link_params.ext_phy_config);
78 break;
79
80 default:
81 DP(NETIF_MSG_LINK, "BAD XGXS ext_phy_config 0x%x\n",
82 bp->link_params.ext_phy_config);
83 break;
84 }
85 } else 61 } else
86 cmd->port = PORT_TP; 62 DP(NETIF_MSG_LINK, "No media found\n");
87
88 cmd->phy_address = bp->mdio.prtad; 63 cmd->phy_address = bp->mdio.prtad;
89 cmd->transceiver = XCVR_INTERNAL; 64 cmd->transceiver = XCVR_INTERNAL;
90 65
diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c
index e6bc70ff8432..c1540727cdbf 100644
--- a/drivers/net/bnx2x/bnx2x_link.c
+++ b/drivers/net/bnx2x/bnx2x_link.c
@@ -1776,16 +1776,20 @@ static void bnx2x_check_fallback_to_cl37(struct bnx2x_phy *phy,
1776 bnx2x_restart_autoneg(phy, params, 0); 1776 bnx2x_restart_autoneg(phy, params, 0);
1777 DP(NETIF_MSG_LINK, "Disabling CL73, and restarting CL37 autoneg\n"); 1777 DP(NETIF_MSG_LINK, "Disabling CL73, and restarting CL37 autoneg\n");
1778} 1778}
1779static u8 bnx2x_link_settings_status(struct link_params *params, 1779static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
1780 struct link_vars *vars, 1780 struct link_params *params,
1781 u32 gp_status, 1781 struct link_vars *vars)
1782 u8 ext_phy_link_up)
1783{ 1782{
1784 struct bnx2x *bp = params->bp; 1783 struct bnx2x *bp = params->bp;
1785 u16 new_line_speed; 1784 u16 new_line_speed , gp_status;
1786 u8 rc = 0; 1785 u8 rc = 0;
1787 u32 ext_phy_type; 1786 u32 ext_phy_type;
1788 vars->link_status = 0; 1787 /* Read gp_status */
1788 CL45_RD_OVER_CL22(bp, phy,
1789 MDIO_REG_BANK_GP_STATUS,
1790 MDIO_GP_STATUS_TOP_AN_STATUS1,
1791 &gp_status);
1792
1789 if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) { 1793 if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {
1790 DP(NETIF_MSG_LINK, "phy link up gp_status=0x%x\n", 1794 DP(NETIF_MSG_LINK, "phy link up gp_status=0x%x\n",
1791 gp_status); 1795 gp_status);
@@ -1881,23 +1885,6 @@ static u8 bnx2x_link_settings_status(struct link_params *params,
1881 return -EINVAL; 1885 return -EINVAL;
1882 } 1886 }
1883 1887
1884 /* Upon link speed change set the NIG into drain mode.
1885 Comes to deals with possible FIFO glitch due to clk change
1886 when speed is decreased without link down indicator */
1887 if (new_line_speed != vars->line_speed) {
1888 if (!SINGLE_MEDIA_DIRECT(params) &&
1889 ext_phy_link_up) {
1890 DP(NETIF_MSG_LINK, "Internal link speed %d is"
1891 " different than the external"
1892 " link speed %d\n", new_line_speed,
1893 vars->line_speed);
1894 vars->phy_link_up = 0;
1895 return 0;
1896 }
1897 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
1898 + params->port*4, 0);
1899 msleep(1);
1900 }
1901 vars->line_speed = new_line_speed; 1888 vars->line_speed = new_line_speed;
1902 vars->link_status |= LINK_STATUS_SERDES_LINK; 1889 vars->link_status |= LINK_STATUS_SERDES_LINK;
1903 ext_phy_type = params->phy[EXT_PHY1].type; 1890 ext_phy_type = params->phy[EXT_PHY1].type;
@@ -2001,7 +1988,7 @@ static void bnx2x_set_gmii_tx_driver(struct link_params *params)
2001} 1988}
2002 1989
2003static u8 bnx2x_emac_program(struct link_params *params, 1990static u8 bnx2x_emac_program(struct link_params *params,
2004 u32 line_speed, u32 duplex) 1991 struct link_vars *vars)
2005{ 1992{
2006 struct bnx2x *bp = params->bp; 1993 struct bnx2x *bp = params->bp;
2007 u8 port = params->port; 1994 u8 port = params->port;
@@ -2013,7 +2000,7 @@ static u8 bnx2x_emac_program(struct link_params *params,
2013 (EMAC_MODE_25G_MODE | 2000 (EMAC_MODE_25G_MODE |
2014 EMAC_MODE_PORT_MII_10M | 2001 EMAC_MODE_PORT_MII_10M |
2015 EMAC_MODE_HALF_DUPLEX)); 2002 EMAC_MODE_HALF_DUPLEX));
2016 switch (line_speed) { 2003 switch (vars->line_speed) {
2017 case SPEED_10: 2004 case SPEED_10:
2018 mode |= EMAC_MODE_PORT_MII_10M; 2005 mode |= EMAC_MODE_PORT_MII_10M;
2019 break; 2006 break;
@@ -2032,21 +2019,74 @@ static u8 bnx2x_emac_program(struct link_params *params,
2032 2019
2033 default: 2020 default:
2034 /* 10G not valid for EMAC */ 2021 /* 10G not valid for EMAC */
2035 DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n", line_speed); 2022 DP(NETIF_MSG_LINK, "Invalid line_speed 0x%x\n",
2023 vars->line_speed);
2036 return -EINVAL; 2024 return -EINVAL;
2037 } 2025 }
2038 2026
2039 if (duplex == DUPLEX_HALF) 2027 if (vars->duplex == DUPLEX_HALF)
2040 mode |= EMAC_MODE_HALF_DUPLEX; 2028 mode |= EMAC_MODE_HALF_DUPLEX;
2041 bnx2x_bits_en(bp, 2029 bnx2x_bits_en(bp,
2042 GRCBASE_EMAC0 + port*0x400 + EMAC_REG_EMAC_MODE, 2030 GRCBASE_EMAC0 + port*0x400 + EMAC_REG_EMAC_MODE,
2043 mode); 2031 mode);
2044 2032
2045 bnx2x_set_led(params, LED_MODE_OPER, line_speed); 2033 bnx2x_set_led(params, LED_MODE_OPER, vars->line_speed);
2046 return 0; 2034 return 0;
2047} 2035}
2048 2036
2037static u8 bnx2x_init_serdes(struct bnx2x_phy *phy,
2038 struct link_params *params,
2039 struct link_vars *vars)
2040{
2041 u8 rc;
2042 vars->phy_flags |= PHY_SGMII_FLAG;
2043 bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
2044 bnx2x_set_aer_mmd(params, phy);
2045 rc = bnx2x_reset_unicore(params, phy, 1);
2046 /* reset the SerDes and wait for reset bit return low */
2047 if (rc != 0)
2048 return rc;
2049 bnx2x_set_aer_mmd(params, phy);
2050
2051 return rc;
2052}
2049 2053
2054static u8 bnx2x_init_xgxs(struct bnx2x_phy *phy,
2055 struct link_params *params,
2056 struct link_vars *vars)
2057{
2058 u8 rc;
2059 vars->phy_flags = PHY_XGXS_FLAG;
2060 if ((phy->req_line_speed &&
2061 ((phy->req_line_speed == SPEED_100) ||
2062 (phy->req_line_speed == SPEED_10))) ||
2063 (!phy->req_line_speed &&
2064 (phy->speed_cap_mask >=
2065 PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) &&
2066 (phy->speed_cap_mask <
2067 PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
2068 ))
2069 vars->phy_flags |= PHY_SGMII_FLAG;
2070 else
2071 vars->phy_flags &= ~PHY_SGMII_FLAG;
2072
2073 bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc);
2074 bnx2x_set_aer_mmd(params, phy);
2075 bnx2x_set_master_ln(params, phy);
2076
2077 rc = bnx2x_reset_unicore(params, phy, 0);
2078 /* reset the SerDes and wait for reset bit return low */
2079 if (rc != 0)
2080 return rc;
2081
2082 bnx2x_set_aer_mmd(params, phy);
2083
2084 /* setting the masterLn_def again after the reset */
2085 bnx2x_set_master_ln(params, phy);
2086 bnx2x_set_swap_lanes(params, phy);
2087
2088 return rc;
2089}
2050/*****************************************************************************/ 2090/*****************************************************************************/
2051/* External Phy section */ 2091/* External Phy section */
2052/*****************************************************************************/ 2092/*****************************************************************************/
@@ -2059,127 +2099,6 @@ void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port)
2059 MISC_REGISTERS_GPIO_OUTPUT_HIGH, port); 2099 MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
2060} 2100}
2061 2101
2062static void bnx2x_ext_phy_reset(struct bnx2x_phy *phy,
2063 struct link_params *params,
2064 struct link_vars *vars)
2065{
2066 struct bnx2x *bp = params->bp;
2067 DP(NETIF_MSG_LINK, "Port %x: bnx2x_ext_phy_reset\n", params->port);
2068 /* The PHY reset is controled by GPIO 1
2069 * Give it 1ms of reset pulse
2070 */
2071 switch (phy->type) {
2072 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
2073 DP(NETIF_MSG_LINK, "XGXS Direct\n");
2074 break;
2075
2076 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
2077 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
2078 DP(NETIF_MSG_LINK, "XGXS 8705/8706\n");
2079
2080 /* Restore normal power mode*/
2081 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
2082 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
2083 params->port);
2084
2085 /* HW reset */
2086 bnx2x_ext_phy_hw_reset(bp, params->port);
2087
2088 bnx2x_cl45_write(bp, phy,
2089 MDIO_PMA_DEVAD,
2090 MDIO_PMA_REG_CTRL, 0xa040);
2091 break;
2092
2093 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
2094 break;
2095
2096 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
2097
2098 /* Restore normal power mode*/
2099 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
2100 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
2101 params->port);
2102
2103 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
2104 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
2105 params->port);
2106
2107 bnx2x_cl45_write(bp, phy,
2108 MDIO_PMA_DEVAD,
2109 MDIO_PMA_REG_CTRL,
2110 1<<15);
2111 break;
2112
2113 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
2114 DP(NETIF_MSG_LINK, "XGXS 8072\n");
2115
2116 /* Unset Low Power Mode and SW reset */
2117 /* Restore normal power mode*/
2118 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
2119 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
2120 params->port);
2121
2122 bnx2x_cl45_write(bp, phy,
2123 MDIO_PMA_DEVAD,
2124 MDIO_PMA_REG_CTRL,
2125 1<<15);
2126 break;
2127
2128 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
2129 DP(NETIF_MSG_LINK, "XGXS 8073\n");
2130
2131 /* Restore normal power mode*/
2132 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
2133 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
2134 params->port);
2135
2136 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
2137 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
2138 params->port);
2139 break;
2140
2141 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
2142 DP(NETIF_MSG_LINK, "XGXS SFX7101\n");
2143
2144 /* Restore normal power mode*/
2145 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
2146 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
2147 params->port);
2148
2149 /* HW reset */
2150 bnx2x_ext_phy_hw_reset(bp, params->port);
2151 break;
2152
2153 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
2154 /* Restore normal power mode*/
2155 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
2156 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
2157 params->port);
2158
2159 /* HW reset */
2160 bnx2x_ext_phy_hw_reset(bp, params->port);
2161
2162 bnx2x_cl45_write(bp, phy,
2163 MDIO_PMA_DEVAD,
2164 MDIO_PMA_REG_CTRL,
2165 1<<15);
2166 break;
2167 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
2168 msleep(1);
2169 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
2170 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
2171 params->port);
2172 break;
2173 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
2174 DP(NETIF_MSG_LINK, "XGXS PHY Failure detected\n");
2175 break;
2176 default:
2177 DP(NETIF_MSG_LINK, "BAD phy type 0x%x\n",
2178 phy->type);
2179 break;
2180 }
2181}
2182
2183static void bnx2x_save_spirom_version(struct bnx2x *bp, u8 port, 2102static void bnx2x_save_spirom_version(struct bnx2x *bp, u8 port,
2184 u32 shmem_base, u32 spirom_ver) 2103 u32 shmem_base, u32 spirom_ver)
2185{ 2104{
@@ -2498,11 +2417,13 @@ static void bnx2x_8726_external_rom_boot(struct bnx2x_phy *phy,
2498 2417
2499static void bnx2x_sfp_set_transmitter(struct bnx2x *bp, 2418static void bnx2x_sfp_set_transmitter(struct bnx2x *bp,
2500 struct bnx2x_phy *phy, 2419 struct bnx2x_phy *phy,
2420 u8 port,
2501 u8 tx_en) 2421 u8 tx_en)
2502{ 2422{
2503 u16 val; 2423 u16 val;
2504 2424
2505 DP(NETIF_MSG_LINK, "Setting transmitter tx_en=%x\n", tx_en); 2425 DP(NETIF_MSG_LINK, "Setting transmitter tx_en=%x for port %x\n",
2426 tx_en, port);
2506 /* Disable/Enable transmitter ( TX laser of the SFP+ module.)*/ 2427 /* Disable/Enable transmitter ( TX laser of the SFP+ module.)*/
2507 bnx2x_cl45_read(bp, phy, 2428 bnx2x_cl45_read(bp, phy,
2508 MDIO_PMA_DEVAD, 2429 MDIO_PMA_DEVAD,
@@ -2946,9 +2867,10 @@ static void bnx2x_8727_power_module(struct bnx2x *bp,
2946 * In case of NOC feature is disabled and power is up, set GPIO control 2867 * In case of NOC feature is disabled and power is up, set GPIO control
2947 * as input to enable listening of over-current indication 2868 * as input to enable listening of over-current indication
2948 */ 2869 */
2949 2870 if (phy->flags & FLAGS_NOC)
2950 if (!(params->feature_config_flags & 2871 return;
2951 FEATURE_CONFIG_BCM8727_NOC) && is_power_up) 2872 if (!(phy->flags &
2873 FLAGS_NOC) && is_power_up)
2952 val = (1<<4); 2874 val = (1<<4);
2953 else 2875 else
2954 /* 2876 /*
@@ -3022,9 +2944,9 @@ static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
3022 if (rc == 0 || 2944 if (rc == 0 ||
3023 (val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) != 2945 (val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) !=
3024 PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER) 2946 PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
3025 bnx2x_sfp_set_transmitter(bp, phy, 1); 2947 bnx2x_sfp_set_transmitter(bp, phy, params->port, 1);
3026 else 2948 else
3027 bnx2x_sfp_set_transmitter(bp, phy, 0); 2949 bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
3028 2950
3029 return rc; 2951 return rc;
3030} 2952}
@@ -3068,7 +2990,7 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
3068 /* Disable transmit for this module */ 2990 /* Disable transmit for this module */
3069 if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) == 2991 if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
3070 PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER) 2992 PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
3071 bnx2x_sfp_set_transmitter(bp, phy, 0); 2993 bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
3072 } 2994 }
3073} 2995}
3074 2996
@@ -3233,7 +3155,7 @@ static void bnx2x_set_preemphasis(struct bnx2x_phy *phy,
3233 CL45_WR_OVER_CL22(bp, phy, 3155 CL45_WR_OVER_CL22(bp, phy,
3234 bank, 3156 bank,
3235 MDIO_RX0_RX_EQ_BOOST, 3157 MDIO_RX0_RX_EQ_BOOST,
3236 params->xgxs_config_rx[i]); 3158 phy->rx_preemphasis[i]);
3237 } 3159 }
3238 3160
3239 for (bank = MDIO_REG_BANK_TX0, i = 0; bank <= MDIO_REG_BANK_TX3; 3161 for (bank = MDIO_REG_BANK_TX0, i = 0; bank <= MDIO_REG_BANK_TX3;
@@ -3241,7 +3163,7 @@ static void bnx2x_set_preemphasis(struct bnx2x_phy *phy,
3241 CL45_WR_OVER_CL22(bp, phy, 3163 CL45_WR_OVER_CL22(bp, phy,
3242 bank, 3164 bank,
3243 MDIO_TX0_TX_DRIVER, 3165 MDIO_TX0_TX_DRIVER,
3244 params->xgxs_config_tx[i]); 3166 phy->tx_preemphasis[i]);
3245 } 3167 }
3246} 3168}
3247 3169
@@ -3331,24 +3253,10 @@ static void bnx2x_init_internal_phy(struct bnx2x_phy *phy,
3331 } 3253 }
3332} 3254}
3333 3255
3334static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars) 3256static u16 bnx2x_wait_reset_complete(struct bnx2x *bp,
3257 struct bnx2x_phy *phy)
3335{ 3258{
3336 struct bnx2x *bp = params->bp; 3259 u16 cnt, ctrl;
3337 u16 cnt;
3338 u16 ctrl = 0;
3339 u16 val = 0;
3340 u8 rc = 0;
3341 struct bnx2x_phy *phy = &params->phy[EXT_PHY1];
3342 if (vars->phy_flags & PHY_XGXS_FLAG) {
3343 /* Make sure that the soft reset is off (expect for the 8072:
3344 * due to the lock, it will be done inside the specific
3345 * handling)
3346 */
3347 if ((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
3348 (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) &&
3349 (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN) &&
3350 (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) &&
3351 (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073)) {
3352 /* Wait for soft reset to get cleared upto 1 sec */ 3260 /* Wait for soft reset to get cleared upto 1 sec */
3353 for (cnt = 0; cnt < 1000; cnt++) { 3261 for (cnt = 0; cnt < 1000; cnt++) {
3354 bnx2x_cl45_read(bp, phy, 3262 bnx2x_cl45_read(bp, phy,
@@ -3360,13 +3268,22 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
3360 } 3268 }
3361 DP(NETIF_MSG_LINK, "control reg 0x%x (after %d ms)\n", 3269 DP(NETIF_MSG_LINK, "control reg 0x%x (after %d ms)\n",
3362 ctrl, cnt); 3270 ctrl, cnt);
3363 } 3271 return 0;
3364 3272}
3365 switch (phy->type) {
3366 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
3367 break;
3368 3273
3369 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705: 3274static u8 bnx2x_8705_config_init(struct bnx2x_phy *phy,
3275 struct link_params *params,
3276 struct link_vars *vars)
3277{
3278 struct bnx2x *bp = params->bp;
3279 DP(NETIF_MSG_LINK, "init 8705\n");
3280 /* Restore normal power mode*/
3281 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
3282 MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
3283 /* HW reset */
3284 bnx2x_ext_phy_hw_reset(bp, params->port);
3285 bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0xa040);
3286 bnx2x_wait_reset_complete(bp, phy);
3370 DP(NETIF_MSG_LINK, "XGXS 8705\n"); 3287 DP(NETIF_MSG_LINK, "XGXS 8705\n");
3371 3288
3372 bnx2x_cl45_write(bp, phy, 3289 bnx2x_cl45_write(bp, phy,
@@ -3388,9 +3305,23 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
3388 /* BCM8705 doesn't have microcode, hence the 0 */ 3305 /* BCM8705 doesn't have microcode, hence the 0 */
3389 bnx2x_save_spirom_version(bp, params->port, 3306 bnx2x_save_spirom_version(bp, params->port,
3390 params->shmem_base, 0); 3307 params->shmem_base, 0);
3391 break;
3392 3308
3393 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: 3309 return 0;
3310}
3311
3312static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy,
3313 struct link_params *params,
3314 struct link_vars *vars)
3315{
3316 u16 cnt, val;
3317 struct bnx2x *bp = params->bp;
3318 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
3319 MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
3320 /* HW reset */
3321 bnx2x_ext_phy_hw_reset(bp, params->port);
3322 bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0xa040);
3323
3324 bnx2x_wait_reset_complete(bp, phy);
3394 /* Wait until fw is loaded */ 3325 /* Wait until fw is loaded */
3395 for (cnt = 0; cnt < 100; cnt++) { 3326 for (cnt = 0; cnt < 100; cnt++) {
3396 bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 3327 bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
@@ -3416,7 +3347,7 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
3416 val &= ~0x7; 3347 val &= ~0x7;
3417 /* Set control bits according to 3348 /* Set control bits according to
3418 configuation */ 3349 configuation */
3419 val |= (params->xgxs_config_rx[i] & 3350 val |= (phy->rx_preemphasis[i] &
3420 0x7); 3351 0x7);
3421 DP(NETIF_MSG_LINK, "Setting RX" 3352 DP(NETIF_MSG_LINK, "Setting RX"
3422 "Equalizer to BCM8706 reg 0x%x" 3353 "Equalizer to BCM8706 reg 0x%x"
@@ -3479,8 +3410,26 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
3479 bnx2x_save_bcm_spirom_ver(bp, params->port, 3410 bnx2x_save_bcm_spirom_ver(bp, params->port,
3480 phy, 3411 phy,
3481 params->shmem_base); 3412 params->shmem_base);
3482 break; 3413 return 0;
3483 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726: 3414}
3415
3416static u8 bnx2x_8726_config_init(struct bnx2x_phy *phy,
3417 struct link_params *params,
3418 struct link_vars *vars)
3419{
3420 struct bnx2x *bp = params->bp;
3421 DP(NETIF_MSG_LINK, "Initializing BCM8726\n");
3422 /* Restore normal power mode*/
3423 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
3424 MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
3425
3426 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
3427 MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
3428
3429 bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
3430 bnx2x_wait_reset_complete(bp, phy);
3431
3432 bnx2x_wait_reset_complete(bp, phy);
3484 DP(NETIF_MSG_LINK, "Initializing BCM8726\n"); 3433 DP(NETIF_MSG_LINK, "Initializing BCM8726\n");
3485 bnx2x_8726_external_rom_boot(phy, params); 3434 bnx2x_8726_external_rom_boot(phy, params);
3486 3435
@@ -3538,21 +3487,39 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
3538 FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) { 3487 FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
3539 DP(NETIF_MSG_LINK, "Setting TX_CTRL1 0x%x," 3488 DP(NETIF_MSG_LINK, "Setting TX_CTRL1 0x%x,"
3540 "TX_CTRL2 0x%x\n", 3489 "TX_CTRL2 0x%x\n",
3541 params->xgxs_config_tx[0], 3490 phy->tx_preemphasis[0],
3542 params->xgxs_config_tx[1]); 3491 phy->tx_preemphasis[1]);
3543 bnx2x_cl45_write(bp, phy, 3492 bnx2x_cl45_write(bp, phy,
3544 MDIO_PMA_DEVAD, 3493 MDIO_PMA_DEVAD,
3545 MDIO_PMA_REG_8726_TX_CTRL1, 3494 MDIO_PMA_REG_8726_TX_CTRL1,
3546 params->xgxs_config_tx[0]); 3495 phy->tx_preemphasis[0]);
3547 3496
3548 bnx2x_cl45_write(bp, phy, 3497 bnx2x_cl45_write(bp, phy,
3549 MDIO_PMA_DEVAD, 3498 MDIO_PMA_DEVAD,
3550 MDIO_PMA_REG_8726_TX_CTRL2, 3499 MDIO_PMA_REG_8726_TX_CTRL2,
3551 params->xgxs_config_tx[1]); 3500 phy->tx_preemphasis[1]);
3552 } 3501 }
3553 break; 3502 return 0;
3554 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: 3503
3555 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073: 3504}
3505
3506static u8 bnx2x_8072_8073_config_init(struct bnx2x_phy *phy,
3507 struct link_params *params,
3508 struct link_vars *vars)
3509{
3510 struct bnx2x *bp = params->bp;
3511 u16 val = 0;
3512 u8 gpio_port;
3513 DP(NETIF_MSG_LINK, "Init 8073\n");
3514
3515 gpio_port = params->port;
3516 /* Restore normal power mode*/
3517 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
3518 MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port);
3519
3520 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
3521 MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port);
3522
3556 { 3523 {
3557 u16 tmp1; 3524 u16 tmp1;
3558 u16 rx_alarm_ctrl_val; 3525 u16 rx_alarm_ctrl_val;
@@ -3606,7 +3573,7 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
3606 bnx2x_807x_force_10G(bp, phy); 3573 bnx2x_807x_force_10G(bp, phy);
3607 DP(NETIF_MSG_LINK, 3574 DP(NETIF_MSG_LINK,
3608 "Forced speed 10G on 807X\n"); 3575 "Forced speed 10G on 807X\n");
3609 break; 3576 return 0;
3610 } else { 3577 } else {
3611 bnx2x_cl45_write(bp, phy, 3578 bnx2x_cl45_write(bp, phy,
3612 MDIO_PMA_DEVAD, 3579 MDIO_PMA_DEVAD,
@@ -3728,21 +3695,25 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
3728 "Advertise 1G=%x, 10G=%x\n", 3695 "Advertise 1G=%x, 10G=%x\n",
3729 ((val & (1<<5)) > 0), 3696 ((val & (1<<5)) > 0),
3730 ((val & (1<<7)) > 0)); 3697 ((val & (1<<7)) > 0));
3731 break; 3698 return 0;
3732 } 3699 }
3700}
3733 3701
3734 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727: 3702static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy,
3735 { 3703 struct link_params *params,
3736 u16 tmp1; 3704 struct link_vars *vars)
3737 u16 rx_alarm_ctrl_val; 3705{
3738 u16 lasi_ctrl_val; 3706 u16 tmp1, val, mod_abs;
3707 u16 rx_alarm_ctrl_val;
3708 u16 lasi_ctrl_val;
3709 struct bnx2x *bp = params->bp;
3710 /* Enable PMD link, MOD_ABS_FLT, and 1G link alarm */
3739 3711
3740 /* Enable PMD link, MOD_ABS_FLT, and 1G link alarm */ 3712 /* Enable PMD link, MOD_ABS_FLT, and 1G link alarm */
3741 3713
3742 u16 mod_abs;
3743 rx_alarm_ctrl_val = (1<<2) | (1<<5) ; 3714 rx_alarm_ctrl_val = (1<<2) | (1<<5) ;
3744 lasi_ctrl_val = 0x0004; 3715 lasi_ctrl_val = 0x0004;
3745 3716 bnx2x_wait_reset_complete(bp, phy);
3746 DP(NETIF_MSG_LINK, "Initializing BCM8727\n"); 3717 DP(NETIF_MSG_LINK, "Initializing BCM8727\n");
3747 /* enable LASI */ 3718 /* enable LASI */
3748 bnx2x_cl45_write(bp, phy, 3719 bnx2x_cl45_write(bp, phy,
@@ -3861,28 +3832,39 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
3861 FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) { 3832 FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) {
3862 DP(NETIF_MSG_LINK, "Setting TX_CTRL1 0x%x," 3833 DP(NETIF_MSG_LINK, "Setting TX_CTRL1 0x%x,"
3863 "TX_CTRL2 0x%x\n", 3834 "TX_CTRL2 0x%x\n",
3864 params->xgxs_config_tx[0], 3835 phy->tx_preemphasis[0],
3865 params->xgxs_config_tx[1]); 3836 phy->tx_preemphasis[1]);
3866 bnx2x_cl45_write(bp, phy, 3837 bnx2x_cl45_write(bp, phy,
3867 MDIO_PMA_DEVAD, 3838 MDIO_PMA_DEVAD,
3868 MDIO_PMA_REG_8727_TX_CTRL1, 3839 MDIO_PMA_REG_8727_TX_CTRL1,
3869 params->xgxs_config_tx[0]); 3840 phy->tx_preemphasis[0]);
3870 3841
3871 bnx2x_cl45_write(bp, phy, 3842 bnx2x_cl45_write(bp, phy,
3872 MDIO_PMA_DEVAD, 3843 MDIO_PMA_DEVAD,
3873 MDIO_PMA_REG_8727_TX_CTRL2, 3844 MDIO_PMA_REG_8727_TX_CTRL2,
3874 params->xgxs_config_tx[1]); 3845 phy->tx_preemphasis[1]);
3875 } 3846 }
3876 3847
3877 break; 3848 return 0;
3878 } 3849}
3850
3851static u8 bnx2x_7101_config_init(struct bnx2x_phy *phy,
3852 struct link_params *params,
3853 struct link_vars *vars)
3854{
3855 u16 fw_ver1, fw_ver2, val;
3856 struct bnx2x *bp = params->bp;
3857 DP(NETIF_MSG_LINK, "Setting the SFX7101 LASI indication\n");
3858
3859 /* Restore normal power mode*/
3860 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
3861 MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
3862 /* HW reset */
3863 bnx2x_ext_phy_hw_reset(bp, params->port);
3879 3864
3880 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
3881 {
3882 u16 fw_ver1, fw_ver2;
3883 DP(NETIF_MSG_LINK, 3865 DP(NETIF_MSG_LINK,
3884 "Setting the SFX7101 LASI indication\n"); 3866 "Setting the SFX7101 LASI indication\n");
3885 3867 bnx2x_wait_reset_complete(bp, phy);
3886 bnx2x_cl45_write(bp, phy, 3868 bnx2x_cl45_write(bp, phy,
3887 MDIO_PMA_DEVAD, 3869 MDIO_PMA_DEVAD,
3888 MDIO_PMA_REG_LASI_CTRL, 0x1); 3870 MDIO_PMA_REG_LASI_CTRL, 0x1);
@@ -3912,10 +3894,14 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
3912 bnx2x_save_spirom_version(params->bp, params->port, 3894 bnx2x_save_spirom_version(params->bp, params->port,
3913 params->shmem_base, 3895 params->shmem_base,
3914 (u32)(fw_ver1<<16 | fw_ver2)); 3896 (u32)(fw_ver1<<16 | fw_ver2));
3915 break; 3897 return 0;
3916 } 3898}
3917 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481: 3899
3918 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823: 3900static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
3901 struct link_params *params,
3902 struct link_vars *vars)
3903{
3904 struct bnx2x *bp = params->bp;
3919 { 3905 {
3920 /* This phy uses the NIG latch mechanism since link 3906 /* This phy uses the NIG latch mechanism since link
3921 indication arrives through its LED4 and not via 3907 indication arrives through its LED4 and not via
@@ -3924,6 +3910,7 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
3924 u16 autoneg_val, an_1000_val, an_10_100_val, temp; 3910 u16 autoneg_val, an_1000_val, an_10_100_val, temp;
3925 temp = vars->line_speed; 3911 temp = vars->line_speed;
3926 vars->line_speed = SPEED_10000; 3912 vars->line_speed = SPEED_10000;
3913 bnx2x_wait_reset_complete(bp, phy);
3927 bnx2x_set_autoneg(phy, params, vars, 0); 3914 bnx2x_set_autoneg(phy, params, vars, 0);
3928 bnx2x_program_serdes(phy, params, vars); 3915 bnx2x_program_serdes(phy, params, vars);
3929 vars->line_speed = temp; 3916 vars->line_speed = temp;
@@ -4052,24 +4039,49 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
4052 /* Save spirom version */ 4039 /* Save spirom version */
4053 bnx2x_save_8481_spirom_version(phy, params, 4040 bnx2x_save_8481_spirom_version(phy, params,
4054 params->shmem_base); 4041 params->shmem_base);
4055 break; 4042 return 0;
4056 } 4043 }
4057 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE: 4044}
4058 DP(NETIF_MSG_LINK,
4059 "XGXS PHY Failure detected 0x%x\n",
4060 phy->type);
4061 rc = -EINVAL;
4062 break;
4063 4045
4064 default: 4046static u8 bnx2x_848x3_config_init(struct bnx2x_phy *phy,
4065 DP(NETIF_MSG_LINK, "BAD SerDes ext_phy_config 0x%x\n", 4047 struct link_params *params,
4066 phy->type); 4048 struct link_vars *vars)
4067 break; 4049{
4068 } 4050 struct bnx2x *bp = params->bp;
4069 } 4051 u16 temp;
4070 return rc; 4052 msleep(1);
4053 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
4054 MISC_REGISTERS_GPIO_OUTPUT_HIGH,
4055 params->port);
4056 msleep(200); /* 100 is not enough */
4057
4058 /**
4059 * BCM84823 requires that XGXS links up first @ 10G for normal
4060 * behavior
4061 */
4062 temp = vars->line_speed;
4063 vars->line_speed = SPEED_10000;
4064 bnx2x_set_autoneg(phy, params, vars, 0);
4065 bnx2x_program_serdes(phy, params, vars);
4066 vars->line_speed = temp;
4067 return bnx2x_848xx_cmn_config_init(phy, params, vars);
4071} 4068}
4072 4069
4070static u8 bnx2x_8481_config_init(struct bnx2x_phy *phy,
4071 struct link_params *params,
4072 struct link_vars *vars)
4073{
4074 struct bnx2x *bp = params->bp;
4075 /* Restore normal power mode*/
4076 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
4077 MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
4078
4079 /* HW reset */
4080 bnx2x_ext_phy_hw_reset(bp, params->port);
4081
4082 bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
4083 return bnx2x_848xx_cmn_config_init(phy, params, vars);
4084}
4073static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy, 4085static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
4074 struct link_params *params) 4086 struct link_params *params)
4075{ 4087{
@@ -4134,7 +4146,7 @@ static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
4134 4146
4135 if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) == 4147 if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
4136 PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER) 4148 PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
4137 bnx2x_sfp_set_transmitter(bp, phy, 0); 4149 bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
4138 4150
4139 if (bnx2x_wait_for_sfp_module_initialized(phy, params) == 0) 4151 if (bnx2x_wait_for_sfp_module_initialized(phy, params) == 0)
4140 bnx2x_sfp_module_detection(phy, params); 4152 bnx2x_sfp_module_detection(phy, params);
@@ -4148,25 +4160,13 @@ static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
4148 module plugged in/out */ 4160 module plugged in/out */
4149} 4161}
4150 4162
4151 4163static u8 bnx2x_8705_read_status(struct bnx2x_phy *phy,
4152static u8 bnx2x_ext_phy_is_link_up(struct bnx2x_phy *phy,
4153 struct link_params *params, 4164 struct link_params *params,
4154 struct link_vars *vars, 4165 struct link_vars *vars)
4155 u8 is_mi_int)
4156{ 4166{
4157 struct bnx2x *bp = params->bp;
4158 u16 val1 = 0, val2;
4159 u16 rx_sd, pcs_status;
4160 u8 ext_phy_link_up = 0; 4167 u8 ext_phy_link_up = 0;
4161 4168 u16 val1, rx_sd;
4162 if (vars->phy_flags & PHY_XGXS_FLAG) { 4169 struct bnx2x *bp = params->bp;
4163 switch (phy->type) {
4164 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
4165 DP(NETIF_MSG_LINK, "XGXS Direct\n");
4166 ext_phy_link_up = 1;
4167 break;
4168
4169 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
4170 DP(NETIF_MSG_LINK, "XGXS 8705\n"); 4170 DP(NETIF_MSG_LINK, "XGXS 8705\n");
4171 bnx2x_cl45_read(bp, phy, 4171 bnx2x_cl45_read(bp, phy,
4172 MDIO_WIS_DEVAD, 4172 MDIO_WIS_DEVAD,
@@ -4194,10 +4194,16 @@ static u8 bnx2x_ext_phy_is_link_up(struct bnx2x_phy *phy,
4194 ((val1 & (1<<8)) == 0)); 4194 ((val1 & (1<<8)) == 0));
4195 if (ext_phy_link_up) 4195 if (ext_phy_link_up)
4196 vars->line_speed = SPEED_10000; 4196 vars->line_speed = SPEED_10000;
4197 break; 4197 return ext_phy_link_up;
4198}
4198 4199
4199 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: 4200static u8 bnx2x_8706_8726_read_status(struct bnx2x_phy *phy,
4200 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726: 4201 struct link_params *params,
4202 struct link_vars *vars)
4203{
4204 u8 link_up = 0;
4205 u16 val1, val2, rx_sd, pcs_status;
4206 struct bnx2x *bp = params->bp;
4201 DP(NETIF_MSG_LINK, "XGXS 8706/8726\n"); 4207 DP(NETIF_MSG_LINK, "XGXS 8706/8726\n");
4202 /* Clear RX Alarm*/ 4208 /* Clear RX Alarm*/
4203 bnx2x_cl45_read(bp, phy, 4209 bnx2x_cl45_read(bp, phy,
@@ -4233,35 +4239,54 @@ static u8 bnx2x_ext_phy_is_link_up(struct bnx2x_phy *phy,
4233 * bit 0 of pcs_status are set, or if the autoneg bit 4239 * bit 0 of pcs_status are set, or if the autoneg bit
4234 1 is set 4240 1 is set
4235 */ 4241 */
4236 ext_phy_link_up = ((rx_sd & pcs_status & 0x1) || 4242 link_up = ((rx_sd & pcs_status & 0x1) ||
4237 (val2 & (1<<1))); 4243 (val2 & (1<<1)));
4238 if (ext_phy_link_up) { 4244 if (link_up) {
4239 if (phy->type ==
4240 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) {
4241 /* If transmitter is disabled,
4242 ignore false link up indication */
4243 bnx2x_cl45_read(bp, phy,
4244 MDIO_PMA_DEVAD,
4245 MDIO_PMA_REG_PHY_IDENTIFIER,
4246 &val1);
4247 if (val1 & (1<<15)) {
4248 DP(NETIF_MSG_LINK, "Tx is "
4249 "disabled\n");
4250 ext_phy_link_up = 0;
4251 break;
4252 }
4253 }
4254 if (val2 & (1<<1)) 4245 if (val2 & (1<<1))
4255 vars->line_speed = SPEED_1000; 4246 vars->line_speed = SPEED_1000;
4256 else 4247 else
4257 vars->line_speed = SPEED_10000; 4248 vars->line_speed = SPEED_10000;
4249 bnx2x_ext_phy_resolve_fc(phy, params, vars);
4250 return link_up;
4258 } 4251 }
4259 break; 4252 return 0;
4253}
4260 4254
4261 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727: 4255static u8 bnx2x_8706_read_status(struct bnx2x_phy *phy,
4262 { 4256 struct link_params *params,
4257 struct link_vars *vars)
4258{
4259 return bnx2x_8706_8726_read_status(phy, params, vars);
4260}
4261
4262static u8 bnx2x_8726_read_status(struct bnx2x_phy *phy,
4263 struct link_params *params,
4264 struct link_vars *vars)
4265{
4266 struct bnx2x *bp = params->bp;
4267 u16 val1;
4268 u8 link_up = bnx2x_8706_8726_read_status(phy, params, vars);
4269 if (link_up) {
4270 bnx2x_cl45_read(bp, phy,
4271 MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER,
4272 &val1);
4273 if (val1 & (1<<15)) {
4274 DP(NETIF_MSG_LINK, "Tx is disabled\n");
4275 link_up = 0;
4276 vars->line_speed = 0;
4277 }
4278 }
4279 return link_up;
4280}
4281static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
4282 struct link_params *params,
4283 struct link_vars *vars)
4284
4285{
4286 struct bnx2x *bp = params->bp;
4287 u8 ext_phy_link_up = 0;
4263 u16 link_status = 0; 4288 u16 link_status = 0;
4264 u16 rx_alarm_status; 4289 u16 rx_alarm_status, val1;
4265 /* Check the LASI */ 4290 /* Check the LASI */
4266 bnx2x_cl45_read(bp, phy, 4291 bnx2x_cl45_read(bp, phy,
4267 MDIO_PMA_DEVAD, 4292 MDIO_PMA_DEVAD,
@@ -4288,8 +4313,7 @@ static u8 bnx2x_ext_phy_is_link_up(struct bnx2x_phy *phy,
4288 * If a module is present and there is need to check 4313 * If a module is present and there is need to check
4289 * for over current 4314 * for over current
4290 */ 4315 */
4291 if (!(params->feature_config_flags & 4316 if (!(phy->flags & FLAGS_NOC) &&
4292 FEATURE_CONFIG_BCM8727_NOC) &&
4293 !(rx_alarm_status & (1<<5))) { 4317 !(rx_alarm_status & (1<<5))) {
4294 /* Check over-current using 8727 GPIO0 input*/ 4318 /* Check over-current using 8727 GPIO0 input*/
4295 bnx2x_cl45_read(bp, phy, 4319 bnx2x_cl45_read(bp, phy,
@@ -4328,7 +4352,7 @@ static u8 bnx2x_ext_phy_is_link_up(struct bnx2x_phy *phy,
4328 MDIO_PMA_DEVAD, 4352 MDIO_PMA_DEVAD,
4329 MDIO_PMA_REG_RX_ALARM, 4353 MDIO_PMA_REG_RX_ALARM,
4330 &rx_alarm_status); 4354 &rx_alarm_status);
4331 break; 4355 return ext_phy_link_up;
4332 } 4356 }
4333 } /* Over current check */ 4357 } /* Over current check */
4334 4358
@@ -4351,7 +4375,7 @@ static u8 bnx2x_ext_phy_is_link_up(struct bnx2x_phy *phy,
4351 if (val1 & (1<<15)) { 4375 if (val1 & (1<<15)) {
4352 DP(NETIF_MSG_LINK, "Tx is disabled\n"); 4376 DP(NETIF_MSG_LINK, "Tx is disabled\n");
4353 ext_phy_link_up = 0; 4377 ext_phy_link_up = 0;
4354 break; 4378 return ext_phy_link_up;
4355 } 4379 }
4356 4380
4357 bnx2x_cl45_read(bp, phy, 4381 bnx2x_cl45_read(bp, phy,
@@ -4378,12 +4402,16 @@ static u8 bnx2x_ext_phy_is_link_up(struct bnx2x_phy *phy,
4378 "port %x: External link" 4402 "port %x: External link"
4379 " is down\n", params->port); 4403 " is down\n", params->port);
4380 } 4404 }
4381 break; 4405 return ext_phy_link_up;
4382 }
4383 4406
4384 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: 4407}
4385 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073: 4408static u8 bnx2x_8073_read_status(struct bnx2x_phy *phy,
4386 { 4409 struct link_params *params,
4410 struct link_vars *vars)
4411{
4412 struct bnx2x *bp = params->bp;
4413 u8 ext_phy_link_up = 0;
4414 u16 val1, val2;
4387 u16 link_status = 0; 4415 u16 link_status = 0;
4388 u16 an1000_status = 0; 4416 u16 an1000_status = 0;
4389 4417
@@ -4456,7 +4484,7 @@ static u8 bnx2x_ext_phy_is_link_up(struct bnx2x_phy *phy,
4456 if (bnx2x_8073_xaui_wa(bp, phy) 4484 if (bnx2x_8073_xaui_wa(bp, phy)
4457 != 0) { 4485 != 0) {
4458 ext_phy_link_up = 0; 4486 ext_phy_link_up = 0;
4459 break; 4487 return ext_phy_link_up;
4460 } 4488 }
4461 } 4489 }
4462 bnx2x_cl45_read(bp, phy, 4490 bnx2x_cl45_read(bp, phy,
@@ -4561,9 +4589,16 @@ static u8 bnx2x_ext_phy_is_link_up(struct bnx2x_phy *phy,
4561 } 4589 }
4562 } 4590 }
4563 4591
4564 break; 4592 return ext_phy_link_up;
4565 } 4593}
4566 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101: 4594
4595static u8 bnx2x_7101_read_status(struct bnx2x_phy *phy,
4596 struct link_params *params,
4597 struct link_vars *vars)
4598{
4599 struct bnx2x *bp = params->bp;
4600 u8 ext_phy_link_up;
4601 u16 val1, val2;
4567 bnx2x_cl45_read(bp, phy, 4602 bnx2x_cl45_read(bp, phy,
4568 MDIO_PMA_DEVAD, 4603 MDIO_PMA_DEVAD,
4569 MDIO_PMA_REG_LASI_STATUS, &val2); 4604 MDIO_PMA_REG_LASI_STATUS, &val2);
@@ -4597,9 +4632,17 @@ static u8 bnx2x_ext_phy_is_link_up(struct bnx2x_phy *phy,
4597 val2, 4632 val2,
4598 (val2 & (1<<14))); 4633 (val2 & (1<<14)));
4599 } 4634 }
4600 break; 4635 return ext_phy_link_up;
4601 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481: 4636}
4602 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823: 4637
4638static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
4639 struct link_params *params,
4640 struct link_vars *vars)
4641{
4642 struct bnx2x *bp = params->bp;
4643 u16 val1, val2;
4644 u8 ext_phy_link_up = 0;
4645
4603 /* Check 10G-BaseT link status */ 4646 /* Check 10G-BaseT link status */
4604 /* Check PMD signal ok */ 4647 /* Check PMD signal ok */
4605 bnx2x_cl45_read(bp, phy, 4648 bnx2x_cl45_read(bp, phy,
@@ -4661,26 +4704,9 @@ static u8 bnx2x_ext_phy_is_link_up(struct bnx2x_phy *phy,
4661 (vars->duplex == DUPLEX_FULL)); 4704 (vars->duplex == DUPLEX_FULL));
4662 } 4705 }
4663 } 4706 }
4664 break; 4707 return ext_phy_link_up;
4665 default:
4666 DP(NETIF_MSG_LINK,
4667 "BAD SerDes ext_phy_config 0x%x\n",
4668 phy->type);
4669 ext_phy_link_up = 0;
4670 break;
4671 }
4672 }
4673
4674 /* Set SGMII mode for external phy */
4675 if (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) {
4676 if (vars->line_speed < SPEED_1000)
4677 vars->phy_flags |= PHY_SGMII_FLAG;
4678 else
4679 vars->phy_flags &= ~PHY_SGMII_FLAG;
4680 }
4681
4682 return ext_phy_link_up;
4683} 4708}
4709
4684static void bnx2x_link_int_enable(struct link_params *params) 4710static void bnx2x_link_int_enable(struct link_params *params)
4685{ 4711{
4686 u8 port = params->port; 4712 u8 port = params->port;
@@ -4825,13 +4851,26 @@ static void bnx2x_link_int_ack(struct link_params *params,
4825 } 4851 }
4826} 4852}
4827 4853
4828static u8 bnx2x_format_ver(u32 num, u8 *str, u16 len) 4854static u8 bnx2x_7101_format_ver(u32 spirom_ver, u8 *str, u16 *len)
4855{
4856 if (*len < 5)
4857 return -EINVAL;
4858 str[0] = (spirom_ver & 0xFF);
4859 str[1] = (spirom_ver & 0xFF00) >> 8;
4860 str[2] = (spirom_ver & 0xFF0000) >> 16;
4861 str[3] = (spirom_ver & 0xFF000000) >> 24;
4862 str[4] = '\0';
4863 *len -= 5;
4864 return 0;
4865}
4866
4867static u8 bnx2x_format_ver(u32 num, u8 *str, u16 *len)
4829{ 4868{
4830 u8 *str_ptr = str; 4869 u8 *str_ptr = str;
4831 u32 mask = 0xf0000000; 4870 u32 mask = 0xf0000000;
4832 u8 shift = 8*4; 4871 u8 shift = 8*4;
4833 u8 digit; 4872 u8 digit;
4834 if (len < 10) { 4873 if (*len < 10) {
4835 /* Need more than 10chars for this format */ 4874 /* Need more than 10chars for this format */
4836 *str_ptr = '\0'; 4875 *str_ptr = '\0';
4837 return -EINVAL; 4876 return -EINVAL;
@@ -4855,65 +4894,41 @@ static u8 bnx2x_format_ver(u32 num, u8 *str, u16 len)
4855 return 0; 4894 return 0;
4856} 4895}
4857 4896
4897static u8 bnx2x_848xx_format_ver(u32 raw_ver, u8 *str, u16 *len)
4898{
4899 u8 status = 0;
4900 u32 spirom_ver;
4901 spirom_ver = ((raw_ver & 0xF80) >> 7) << 16 | (raw_ver & 0x7F);
4902 status = bnx2x_format_ver(spirom_ver, str, len);
4903 return status;
4904}
4905
4906static u8 bnx2x_null_format_ver(u32 spirom_ver, u8 *str, u16 *len)
4907{
4908 str[0] = '\0';
4909 (*len)--;
4910 return 0;
4911}
4912
4858u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded, 4913u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
4859 u8 *version, u16 len) 4914 u8 *version, u16 len)
4860{ 4915{
4861 struct bnx2x *bp; 4916 struct bnx2x *bp;
4862 u32 ext_phy_type = 0;
4863 u32 spirom_ver = 0; 4917 u32 spirom_ver = 0;
4864 u8 status; 4918 u8 status = 0;
4865 4919 u8 *ver_p = version;
4866 if (version == NULL || params == NULL) 4920 if (version == NULL || params == NULL)
4867 return -EINVAL; 4921 return -EINVAL;
4868 bp = params->bp; 4922 bp = params->bp;
4869 4923
4870 spirom_ver = REG_RD(bp, params->shmem_base + 4924 /* Extract first external phy*/
4871 offsetof(struct shmem_region, 4925 version[0] = '\0';
4872 port_mb[params->port].ext_phy_fw_version)); 4926 spirom_ver = REG_RD(bp, params->phy[EXT_PHY1].ver_addr);
4873
4874 status = 0;
4875 /* reset the returned value to zero */
4876 ext_phy_type = params->phy[EXT_PHY1].type;
4877 switch (ext_phy_type) {
4878 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
4879
4880 if (len < 5)
4881 return -EINVAL;
4882
4883 version[0] = (spirom_ver & 0xFF);
4884 version[1] = (spirom_ver & 0xFF00) >> 8;
4885 version[2] = (spirom_ver & 0xFF0000) >> 16;
4886 version[3] = (spirom_ver & 0xFF000000) >> 24;
4887 version[4] = '\0';
4888 4927
4889 break; 4928 if (params->phy[EXT_PHY1].format_fw_ver)
4890 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: 4929 status |= params->phy[EXT_PHY1].format_fw_ver(spirom_ver,
4891 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073: 4930 ver_p,
4892 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727: 4931 &len);
4893 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
4894 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
4895 status = bnx2x_format_ver(spirom_ver, version, len);
4896 break;
4897 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
4898 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
4899 spirom_ver = ((spirom_ver & 0xF80) >> 7) << 16 |
4900 (spirom_ver & 0x7F);
4901 status = bnx2x_format_ver(spirom_ver, version, len);
4902 break;
4903 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
4904 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
4905 version[0] = '\0';
4906 break;
4907
4908 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
4909 DP(NETIF_MSG_LINK, "bnx2x_get_ext_phy_fw_version:"
4910 " type is FAILURE!\n");
4911 status = -EINVAL;
4912 break;
4913
4914 default:
4915 break;
4916 }
4917 return status; 4932 return status;
4918} 4933}
4919 4934
@@ -4969,47 +4984,21 @@ static void bnx2x_set_xgxs_loopback(struct bnx2x_phy *phy,
4969 } 4984 }
4970} 4985}
4971 4986
4972static void bnx2x_ext_phy_loopback(struct bnx2x_phy *phy, 4987static void bnx2x_8726_config_loopback(struct bnx2x_phy *phy,
4973 struct link_params *params) 4988 struct link_params *params)
4974{ 4989{
4975 struct bnx2x *bp = params->bp; 4990 struct bnx2x *bp = params->bp;
4991 DP(NETIF_MSG_LINK, "PMA/PMD ext_phy_loopback: 8726\n");
4992 bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x0001);
4993}
4976 4994
4977 if (params->switch_cfg == SWITCH_CFG_10G) { 4995static void bnx2x_7101_config_loopback(struct bnx2x_phy *phy,
4978 4996 struct link_params *params)
4979 /* CL37 Autoneg Enabled */ 4997{
4980 switch (phy->type) { 4998 struct bnx2x *bp = params->bp;
4981 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT: 4999 /* SFX7101_XGXS_TEST1 */
4982 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN: 5000 bnx2x_cl45_write(bp, phy,
4983 DP(NETIF_MSG_LINK, 5001 MDIO_XS_DEVAD, MDIO_XS_SFX7101_XGXS_TEST1, 0x100);
4984 "ext_phy_loopback: We should not get here\n");
4985 break;
4986 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
4987 DP(NETIF_MSG_LINK, "ext_phy_loopback: 8705\n");
4988 break;
4989 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
4990 DP(NETIF_MSG_LINK, "ext_phy_loopback: 8706\n");
4991 break;
4992 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
4993 DP(NETIF_MSG_LINK, "PMA/PMD ext_phy_loopback: 8726\n");
4994 bnx2x_cl45_write(bp, phy,
4995 MDIO_PMA_DEVAD,
4996 MDIO_PMA_REG_CTRL,
4997 0x0001);
4998 break;
4999 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
5000 /* SFX7101_XGXS_TEST1 */
5001 bnx2x_cl45_write(bp, phy,
5002 MDIO_XS_DEVAD,
5003 MDIO_XS_SFX7101_XGXS_TEST1,
5004 0x100);
5005 DP(NETIF_MSG_LINK,
5006 "ext_phy_loopback: set ext phy loopback\n");
5007 break;
5008 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
5009
5010 break;
5011 } /* switch external PHY type */
5012 }
5013} 5002}
5014/* 5003/*
5015 *------------------------------------------------------------------------ 5004 *------------------------------------------------------------------------
@@ -5204,9 +5193,17 @@ u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars)
5204 MDIO_GP_STATUS_TOP_AN_STATUS1, 5193 MDIO_GP_STATUS_TOP_AN_STATUS1,
5205 &gp_status); 5194 &gp_status);
5206 /* link is up only if both local phy and external phy are up */ 5195 /* link is up only if both local phy and external phy are up */
5207 if ((gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) && 5196 if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {
5208 bnx2x_ext_phy_is_link_up(&params->phy[EXT_PHY1], params, vars, 1)) 5197 u8 ext_phy_link_up = 1;
5209 return 0; 5198 struct link_vars temp_vars;
5199 if (params->phy[EXT_PHY1].read_status)
5200 ext_phy_link_up &=
5201 params->phy[EXT_PHY1].read_status(
5202 &params->phy[EXT_PHY1],
5203 params, &temp_vars);
5204 if (ext_phy_link_up)
5205 return 0;
5206 }
5210 5207
5211 return -ESRCH; 5208 return -ESRCH;
5212} 5209}
@@ -5217,11 +5214,10 @@ static u8 bnx2x_link_initialize(struct link_params *params,
5217 struct bnx2x *bp = params->bp; 5214 struct bnx2x *bp = params->bp;
5218 u8 port = params->port; 5215 u8 port = params->port;
5219 u8 rc = 0; 5216 u8 rc = 0;
5220 u8 non_ext_phy; 5217 u8 phy_index, non_ext_phy;
5221 struct bnx2x_phy *ext_phy = &params->phy[EXT_PHY1]; 5218 struct bnx2x_phy *ext_phy = &params->phy[EXT_PHY1];
5222 struct bnx2x_phy *int_phy = &params->phy[INT_PHY]; 5219 struct bnx2x_phy *int_phy = &params->phy[INT_PHY];
5223 /* Activate the external PHY */ 5220 /* Activate the external PHY */
5224 bnx2x_ext_phy_reset(ext_phy, params, vars);
5225 5221
5226 bnx2x_set_aer_mmd(params, int_phy); 5222 bnx2x_set_aer_mmd(params, int_phy);
5227 5223
@@ -5282,7 +5278,12 @@ static u8 bnx2x_link_initialize(struct link_params *params,
5282 } 5278 }
5283 5279
5284 if (!non_ext_phy) 5280 if (!non_ext_phy)
5285 rc |= bnx2x_ext_phy_init(params, vars); 5281 for (phy_index = EXT_PHY1; phy_index < params->num_phys;
5282 phy_index++) {
5283 params->phy[phy_index].config_init(
5284 &params->phy[phy_index],
5285 params, vars);
5286 }
5286 5287
5287 bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4, 5288 bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
5288 (NIG_STATUS_XGXS0_LINK10G | 5289 (NIG_STATUS_XGXS0_LINK10G |
@@ -5292,6 +5293,35 @@ static u8 bnx2x_link_initialize(struct link_params *params,
5292 return rc; 5293 return rc;
5293} 5294}
5294 5295
5296static void set_phy_vars(struct link_params *params)
5297{
5298 struct bnx2x *bp = params->bp;
5299 u8 actual_phy_idx, phy_index;
5300
5301 for (phy_index = INT_PHY; phy_index < params->num_phys;
5302 phy_index++) {
5303
5304 actual_phy_idx = phy_index;
5305 params->phy[actual_phy_idx].req_flow_ctrl =
5306 params->req_flow_ctrl;
5307
5308 params->phy[actual_phy_idx].req_line_speed =
5309 params->req_line_speed;
5310
5311 params->phy[actual_phy_idx].speed_cap_mask =
5312 params->speed_cap_mask;
5313
5314 params->phy[actual_phy_idx].req_duplex =
5315 params->req_duplex;
5316
5317 DP(NETIF_MSG_LINK, "req_flow_ctrl %x, req_line_speed %x,"
5318 " speed_cap_mask %x\n",
5319 params->phy[actual_phy_idx].req_flow_ctrl,
5320 params->phy[actual_phy_idx].req_line_speed,
5321 params->phy[actual_phy_idx].speed_cap_mask);
5322 }
5323}
5324
5295u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars) 5325u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
5296{ 5326{
5297 struct bnx2x *bp = params->bp; 5327 struct bnx2x *bp = params->bp;
@@ -5307,29 +5337,7 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
5307 vars->duplex = DUPLEX_FULL; 5337 vars->duplex = DUPLEX_FULL;
5308 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; 5338 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
5309 vars->mac_type = MAC_TYPE_NONE; 5339 vars->mac_type = MAC_TYPE_NONE;
5310 5340 vars->phy_flags = 0;
5311 if (params->switch_cfg == SWITCH_CFG_1G) {
5312 params->phy[INT_PHY].type =
5313 PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT;
5314 vars->phy_flags = PHY_SERDES_FLAG;
5315 } else {
5316 params->phy[INT_PHY].type =
5317 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT;
5318 vars->phy_flags = PHY_XGXS_FLAG;
5319 }
5320 params->phy[INT_PHY].mdio_ctrl =
5321 bnx2x_get_emac_base(bp,
5322 params->phy[INT_PHY].type, params->port);
5323 if (XGXS_EXT_PHY_TYPE(params->ext_phy_config) !=
5324 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) {
5325 params->phy[EXT_PHY1].type =
5326 XGXS_EXT_PHY_TYPE(params->ext_phy_config);
5327 params->phy[EXT_PHY1].addr =
5328 XGXS_EXT_PHY_ADDR(params->ext_phy_config);
5329 params->phy[EXT_PHY1].mdio_ctrl =
5330 bnx2x_get_emac_base(bp, params->phy[EXT_PHY1].type,
5331 params->port);
5332 }
5333 5341
5334 /* disable attentions */ 5342 /* disable attentions */
5335 bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + params->port*4, 5343 bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + params->port*4,
@@ -5340,6 +5348,13 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
5340 5348
5341 bnx2x_emac_init(params, vars); 5349 bnx2x_emac_init(params, vars);
5342 5350
5351 if (params->num_phys == 0) {
5352 DP(NETIF_MSG_LINK, "No phy found for initialization !!\n");
5353 return -EINVAL;
5354 }
5355 set_phy_vars(params);
5356
5357 DP(NETIF_MSG_LINK, "Num of phys on board: %d\n", params->num_phys);
5343 if (CHIP_REV_IS_FPGA(bp)) { 5358 if (CHIP_REV_IS_FPGA(bp)) {
5344 5359
5345 vars->link_up = 1; 5360 vars->link_up = 1;
@@ -5420,8 +5435,7 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
5420 bnx2x_phy_deassert(params, vars->phy_flags); 5435 bnx2x_phy_deassert(params, vars->phy_flags);
5421 /* set bmac loopback */ 5436 /* set bmac loopback */
5422 bnx2x_emac_enable(params, vars, 1); 5437 bnx2x_emac_enable(params, vars, 1);
5423 bnx2x_emac_program(params, vars->line_speed, 5438 bnx2x_emac_program(params, vars);
5424 vars->duplex);
5425 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + 5439 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
5426 params->port*4, 0); 5440 params->port*4, 0);
5427 5441
@@ -5438,8 +5452,7 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
5438 val = REG_RD(bp, 5452 val = REG_RD(bp,
5439 NIG_REG_XGXS0_CTRL_PHY_ADDR+ 5453 NIG_REG_XGXS0_CTRL_PHY_ADDR+
5440 params->port*0x18); 5454 params->port*0x18);
5441 params->phy_addr = (u8)val; 5455
5442 params->phy[INT_PHY].addr = (u8)val;
5443 bnx2x_phy_deassert(params, vars->phy_flags); 5456 bnx2x_phy_deassert(params, vars->phy_flags);
5444 bnx2x_link_initialize(params, vars); 5457 bnx2x_link_initialize(params, vars);
5445 5458
@@ -5449,12 +5462,20 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
5449 5462
5450 if (params->loopback_mode == LOOPBACK_XGXS_10) { 5463 if (params->loopback_mode == LOOPBACK_XGXS_10) {
5451 /* set 10G XGXS loopback */ 5464 /* set 10G XGXS loopback */
5452 bnx2x_set_xgxs_loopback(&params->phy[INT_PHY], 5465 params->phy[INT_PHY].config_loopback(
5453 params, 1); 5466 &params->phy[INT_PHY],
5467 params);
5468
5454 } else { 5469 } else {
5455 /* set external phy loopback */ 5470 /* set external phy loopback */
5456 bnx2x_ext_phy_loopback(&params->phy[INT_PHY], 5471 u8 phy_index;
5472 for (phy_index = EXT_PHY1;
5473 phy_index < params->num_phys; phy_index++) {
5474 if (params->phy[phy_index].config_loopback)
5475 params->phy[phy_index].config_loopback(
5476 &params->phy[phy_index],
5457 params); 5477 params);
5478 }
5458 } 5479 }
5459 5480
5460 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + 5481 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
@@ -5464,37 +5485,9 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
5464 } else 5485 } else
5465 /* No loopback */ 5486 /* No loopback */
5466 { 5487 {
5488 if (params->switch_cfg == SWITCH_CFG_10G)
5489 vars->phy_flags = PHY_XGXS_FLAG;
5467 bnx2x_phy_deassert(params, vars->phy_flags); 5490 bnx2x_phy_deassert(params, vars->phy_flags);
5468 switch (params->switch_cfg) {
5469 case SWITCH_CFG_1G:
5470 vars->phy_flags |= PHY_SERDES_FLAG;
5471 if ((params->ext_phy_config &
5472 PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK) ==
5473 PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482) {
5474 vars->phy_flags |= PHY_SGMII_FLAG;
5475 }
5476
5477 val = REG_RD(bp,
5478 NIG_REG_SERDES0_CTRL_PHY_ADDR+
5479 params->port*0x10);
5480
5481 params->phy_addr = (u8)val;
5482
5483 break;
5484 case SWITCH_CFG_10G:
5485 vars->phy_flags |= PHY_XGXS_FLAG;
5486 val = REG_RD(bp,
5487 NIG_REG_XGXS0_CTRL_PHY_ADDR+
5488 params->port*0x18);
5489 params->phy_addr = (u8)val;
5490
5491 break;
5492 default:
5493 DP(NETIF_MSG_LINK, "Invalid switch_cfg\n");
5494 return -EINVAL;
5495 }
5496 DP(NETIF_MSG_LINK, "Phy address = 0x%x\n", params->phy_addr);
5497 params->phy[INT_PHY].addr = params->phy_addr;
5498 bnx2x_link_initialize(params, vars); 5491 bnx2x_link_initialize(params, vars);
5499 msleep(30); 5492 msleep(30);
5500 bnx2x_link_int_enable(params); 5493 bnx2x_link_int_enable(params);
@@ -5503,14 +5496,78 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
5503} 5496}
5504 5497
5505 5498
5506static void bnx2x_8726_reset_phy(struct bnx2x *bp, 5499static void bnx2x_8726_link_reset(struct bnx2x_phy *phy,
5507 struct bnx2x_phy *phy) 5500 struct link_params *params)
5508{ 5501{
5509 DP(NETIF_MSG_LINK, "bnx2x_8726_reset_phy\n"); 5502 struct bnx2x *bp = params->bp;
5503 DP(NETIF_MSG_LINK, "bnx2x_8726_link_reset port %d\n", params->port);
5510 /* Set serial boot control for external load */ 5504 /* Set serial boot control for external load */
5511 bnx2x_cl45_write(bp, phy, 5505 bnx2x_cl45_write(bp, phy,
5512 MDIO_PMA_DEVAD, 5506 MDIO_PMA_DEVAD,
5513 MDIO_PMA_REG_GEN_CTRL, 0x0001); 5507 MDIO_PMA_REG_GEN_CTRL, 0x0001);
5508}
5509
5510static void bnx2x_8727_link_reset(struct bnx2x_phy *phy,
5511 struct link_params *params)
5512{
5513 struct bnx2x *bp = params->bp;
5514 /* Disable Transmitter */
5515 bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
5516}
5517static void bnx2x_8073_link_reset(struct bnx2x_phy *phy,
5518 struct link_params *params)
5519{
5520 struct bnx2x *bp = params->bp;
5521 u8 gpio_port;
5522 gpio_port = params->port;
5523 DP(NETIF_MSG_LINK, "Setting 8073 port %d into low power mode\n",
5524 gpio_port);
5525 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
5526 MISC_REGISTERS_GPIO_OUTPUT_LOW,
5527 gpio_port);
5528}
5529static void bnx2x_8481_link_reset(struct bnx2x_phy *phy,
5530 struct link_params *params)
5531{
5532 bnx2x_cl45_write(params->bp, phy,
5533 MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x0000);
5534 bnx2x_cl45_write(params->bp, phy,
5535 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1);
5536}
5537
5538static void bnx2x_848x3_link_reset(struct bnx2x_phy *phy,
5539 struct link_params *params)
5540{
5541 struct bnx2x *bp = params->bp;
5542 u8 port = params->port;
5543 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
5544 MISC_REGISTERS_GPIO_OUTPUT_LOW,
5545 port);
5546}
5547
5548static void bnx2x_common_ext_link_reset(struct bnx2x_phy *phy,
5549 struct link_params *params)
5550{
5551 struct bnx2x *bp = params->bp;
5552 u8 gpio_port;
5553 /* HW reset */
5554 gpio_port = params->port;
5555 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
5556 MISC_REGISTERS_GPIO_OUTPUT_LOW,
5557 gpio_port);
5558 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
5559 MISC_REGISTERS_GPIO_OUTPUT_LOW,
5560 gpio_port);
5561 DP(NETIF_MSG_LINK, "reset external PHY\n");
5562}
5563
5564static void bnx2x_int_link_reset(struct bnx2x_phy *phy,
5565 struct link_params *params)
5566{
5567 /* reset the SerDes/XGXS */
5568 REG_WR(params->bp, GRCBASE_MISC +
5569 MISC_REGISTERS_RESET_REG_3_CLEAR,
5570 (0x1ff << (params->port*16)));
5514} 5571}
5515 5572
5516u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars, 5573u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
@@ -5518,12 +5575,8 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
5518{ 5575{
5519 struct bnx2x *bp = params->bp; 5576 struct bnx2x *bp = params->bp;
5520 5577
5521 u8 port = params->port; 5578 u8 phy_index, port = params->port;
5522 5579
5523 u32 val = REG_RD(bp, params->shmem_base +
5524 offsetof(struct shmem_region, dev_info.
5525 port_feature_config[params->port].
5526 config));
5527 DP(NETIF_MSG_LINK, "Resetting the link of port %d\n", port); 5580 DP(NETIF_MSG_LINK, "Resetting the link of port %d\n", port);
5528 /* disable attentions */ 5581 /* disable attentions */
5529 vars->link_status = 0; 5582 vars->link_status = 0;
@@ -5554,57 +5607,18 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
5554 /* clear link led */ 5607 /* clear link led */
5555 bnx2x_set_led(params, LED_MODE_OFF, 0); 5608 bnx2x_set_led(params, LED_MODE_OFF, 0);
5556 if (reset_ext_phy) { 5609 if (reset_ext_phy) {
5557 struct bnx2x_phy *phy = &params->phy[EXT_PHY1]; 5610 for (phy_index = EXT_PHY1; phy_index < params->num_phys;
5558 switch (phy->type) { 5611 phy_index++) {
5559 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT: 5612 if (params->phy[phy_index].link_reset)
5560 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: 5613 params->phy[phy_index].link_reset(
5561 break; 5614 &params->phy[phy_index],
5562 5615 params);
5563 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
5564 {
5565
5566 /* Disable Transmitter */
5567 if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
5568 PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
5569 bnx2x_sfp_set_transmitter(bp, phy, 0);
5570 break;
5571 }
5572 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
5573 DP(NETIF_MSG_LINK, "Setting 8073 port %d into "
5574 "low power mode\n",
5575 port);
5576 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
5577 MISC_REGISTERS_GPIO_OUTPUT_LOW,
5578 port);
5579 break;
5580 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
5581 {
5582 /* Set soft reset */
5583 bnx2x_8726_reset_phy(bp, phy);
5584 break;
5585 }
5586 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
5587 {
5588 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
5589 MISC_REGISTERS_GPIO_OUTPUT_LOW,
5590 params->port);
5591 break;
5592 }
5593 default:
5594 /* HW reset */
5595 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
5596 MISC_REGISTERS_GPIO_OUTPUT_LOW,
5597 port);
5598 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
5599 MISC_REGISTERS_GPIO_OUTPUT_LOW,
5600 port);
5601 DP(NETIF_MSG_LINK, "reset external PHY\n");
5602 } 5616 }
5603 } 5617 }
5604 /* reset the SerDes/XGXS */
5605 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR,
5606 (0x1ff << (port*16)));
5607 5618
5619 if (params->phy[INT_PHY].link_reset)
5620 params->phy[INT_PHY].link_reset(
5621 &params->phy[INT_PHY], params);
5608 /* reset BigMac */ 5622 /* reset BigMac */
5609 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, 5623 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
5610 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)); 5624 (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
@@ -5654,7 +5668,7 @@ static u8 bnx2x_update_link_down(struct link_params *params,
5654 5668
5655static u8 bnx2x_update_link_up(struct link_params *params, 5669static u8 bnx2x_update_link_up(struct link_params *params,
5656 struct link_vars *vars, 5670 struct link_vars *vars,
5657 u8 link_10g, u32 gp_status) 5671 u8 link_10g)
5658{ 5672{
5659 struct bnx2x *bp = params->bp; 5673 struct bnx2x *bp = params->bp;
5660 u8 port = params->port; 5674 u8 port = params->port;
@@ -5665,8 +5679,7 @@ static u8 bnx2x_update_link_up(struct link_params *params,
5665 bnx2x_bmac_enable(params, vars, 0); 5679 bnx2x_bmac_enable(params, vars, 0);
5666 bnx2x_set_led(params, LED_MODE_OPER, SPEED_10000); 5680 bnx2x_set_led(params, LED_MODE_OPER, SPEED_10000);
5667 } else { 5681 } else {
5668 rc = bnx2x_emac_program(params, vars->line_speed, 5682 rc = bnx2x_emac_program(params, vars);
5669 vars->duplex);
5670 5683
5671 bnx2x_emac_enable(params, vars, 0); 5684 bnx2x_emac_enable(params, vars, 0);
5672 5685
@@ -5689,28 +5702,39 @@ static u8 bnx2x_update_link_up(struct link_params *params,
5689 msleep(20); 5702 msleep(20);
5690 return rc; 5703 return rc;
5691} 5704}
5692/* This function should called upon link interrupt */ 5705/**
5693/* In case vars->link_up, driver needs to 5706 * The bnx2x_link_update function should be called upon link
5694 1. Update the pbf 5707 * interrupt.
5695 2. Disable drain 5708 * Link is considered up as follows:
5696 3. Update the shared memory 5709 * - DIRECT_SINGLE_MEDIA - Only XGXS link (internal link) needs
5697 4. Indicate link up 5710 * to be up
5698 5. Set LEDs 5711 * - SINGLE_MEDIA - The link between the 577xx and the external
5699 Otherwise, 5712 * phy (XGXS) need to up as well as the external link of the
5700 1. Update shared memory 5713 * phy (PHY_EXT1)
5701 2. Reset BigMac 5714 * - DUAL_MEDIA - The link between the 577xx and the first
5702 3. Report link down 5715 * external phy needs to be up, and at least one of the 2
5703 4. Unset LEDs 5716 * external phy link must be up.
5704*/ 5717*/
5705u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars) 5718u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
5706{ 5719{
5707 struct bnx2x *bp = params->bp; 5720 struct bnx2x *bp = params->bp;
5721 struct link_vars phy_vars[MAX_PHYS];
5708 u8 port = params->port; 5722 u8 port = params->port;
5709 u16 gp_status; 5723 u8 link_10g, phy_index;
5710 u8 link_10g; 5724 u8 ext_phy_link_up = 0, cur_link_up, rc = 0;
5711 u8 ext_phy_link_up, rc = 0;
5712 struct bnx2x_phy *int_phy = &params->phy[INT_PHY];
5713 u8 is_mi_int = 0; 5725 u8 is_mi_int = 0;
5726 u16 ext_phy_line_speed = 0, prev_line_speed = vars->line_speed;
5727 u8 active_external_phy = INT_PHY;
5728 vars->link_status = 0;
5729 for (phy_index = INT_PHY; phy_index < params->num_phys;
5730 phy_index++) {
5731 phy_vars[phy_index].flow_ctrl = 0;
5732 phy_vars[phy_index].link_status = 0;
5733 phy_vars[phy_index].line_speed = 0;
5734 phy_vars[phy_index].duplex = DUPLEX_FULL;
5735 phy_vars[phy_index].phy_link_up = 0;
5736 phy_vars[phy_index].link_up = 0;
5737 }
5714 5738
5715 DP(NETIF_MSG_LINK, "port %x, XGXS?%x, int_status 0x%x\n", 5739 DP(NETIF_MSG_LINK, "port %x, XGXS?%x, int_status 0x%x\n",
5716 port, (vars->phy_flags & PHY_XGXS_FLAG), 5740 port, (vars->phy_flags & PHY_XGXS_FLAG),
@@ -5731,21 +5755,94 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
5731 /* disable emac */ 5755 /* disable emac */
5732 REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0); 5756 REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
5733 5757
5734 /* Check external link change only for non-direct */ 5758 /**
5735 ext_phy_link_up = bnx2x_ext_phy_is_link_up(&params->phy[EXT_PHY1], 5759 * Step 1:
5736 params, vars, 5760 * Check external link change only for external phys, and apply
5737 is_mi_int); 5761 * priority selection between them in case the link on both phys
5762 * is up. Note that the instead of the common vars, a temporary
5763 * vars argument is used since each phy may have different link/
5764 * speed/duplex result
5765 */
5766 for (phy_index = EXT_PHY1; phy_index < params->num_phys;
5767 phy_index++) {
5768 struct bnx2x_phy *phy = &params->phy[phy_index];
5769 if (!phy->read_status)
5770 continue;
5771 /* Read link status and params of this ext phy */
5772 cur_link_up = phy->read_status(phy, params,
5773 &phy_vars[phy_index]);
5774 if (cur_link_up) {
5775 DP(NETIF_MSG_LINK, "phy in index %d link is up\n",
5776 phy_index);
5777 } else {
5778 DP(NETIF_MSG_LINK, "phy in index %d link is down\n",
5779 phy_index);
5780 continue;
5781 }
5738 5782
5739 /* Read gp_status */ 5783 if (!ext_phy_link_up) {
5740 CL45_RD_OVER_CL22(bp, int_phy, 5784 ext_phy_link_up = 1;
5741 MDIO_REG_BANK_GP_STATUS, 5785 active_external_phy = phy_index;
5742 MDIO_GP_STATUS_TOP_AN_STATUS1, 5786 }
5743 &gp_status); 5787 }
5788 prev_line_speed = vars->line_speed;
5789 /**
5790 * Step 2:
5791 * Read the status of the internal phy. In case of
5792 * DIRECT_SINGLE_MEDIA board, this link is the external link,
5793 * otherwise this is the link between the 577xx and the first
5794 * external phy
5795 */
5796 if (params->phy[INT_PHY].read_status)
5797 params->phy[INT_PHY].read_status(
5798 &params->phy[INT_PHY],
5799 params, vars);
5800 /**
5801 * The INT_PHY flow control reside in the vars. This include the
5802 * case where the speed or flow control are not set to AUTO.
5803 * Otherwise, the active external phy flow control result is set
5804 * to the vars. The ext_phy_line_speed is needed to check if the
5805 * speed is different between the internal phy and external phy.
5806 * This case may be result of intermediate link speed change.
5807 */
5808 if (active_external_phy > INT_PHY) {
5809 vars->flow_ctrl = phy_vars[active_external_phy].flow_ctrl;
5810 /**
5811 * Link speed is taken from the XGXS. AN and FC result from
5812 * the external phy.
5813 */
5814 vars->link_status |= phy_vars[active_external_phy].link_status;
5815 ext_phy_line_speed = phy_vars[active_external_phy].line_speed;
5816 vars->duplex = phy_vars[active_external_phy].duplex;
5817 if (params->phy[active_external_phy].supported &
5818 SUPPORTED_FIBRE)
5819 vars->link_status |= LINK_STATUS_SERDES_LINK;
5820 DP(NETIF_MSG_LINK, "Active external phy selected: %x\n",
5821 active_external_phy);
5822 }
5823 DP(NETIF_MSG_LINK, "vars->flow_ctrl = 0x%x, vars->link_status = 0x%x,"
5824 " ext_phy_line_speed = %d\n", vars->flow_ctrl,
5825 vars->link_status, ext_phy_line_speed);
5826 /**
5827 * Upon link speed change set the NIG into drain mode. Comes to
5828 * deals with possible FIFO glitch due to clk change when speed
5829 * is decreased without link down indicator
5830 */
5744 5831
5745 rc = bnx2x_link_settings_status(params, vars, gp_status, 5832 if (vars->phy_link_up) {
5746 ext_phy_link_up); 5833 if (!(SINGLE_MEDIA_DIRECT(params)) && ext_phy_link_up &&
5747 if (rc != 0) 5834 (ext_phy_line_speed != vars->line_speed)) {
5748 return rc; 5835 DP(NETIF_MSG_LINK, "Internal link speed %d is"
5836 " different than the external"
5837 " link speed %d\n", vars->line_speed,
5838 ext_phy_line_speed);
5839 vars->phy_link_up = 0;
5840 } else if (prev_line_speed != vars->line_speed) {
5841 REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
5842 + params->port*4, 0);
5843 msleep(1);
5844 }
5845 }
5749 5846
5750 /* anything 10 and over uses the bmac */ 5847 /* anything 10 and over uses the bmac */
5751 link_10g = ((vars->line_speed == SPEED_10000) || 5848 link_10g = ((vars->line_speed == SPEED_10000) ||
@@ -5757,31 +5854,469 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
5757 5854
5758 bnx2x_link_int_ack(params, vars, link_10g, is_mi_int); 5855 bnx2x_link_int_ack(params, vars, link_10g, is_mi_int);
5759 5856
5760 /* In case external phy link is up, and internal link is down 5857 /**
5761 ( not initialized yet probably after link initialization, it needs 5858 * In case external phy link is up, and internal link is down
5762 to be initialized. 5859 * (not initialized yet probably after link initialization, it
5763 Note that after link down-up as result of cable plug, 5860 * needs to be initialized.
5764 the xgxs link would probably become up again without the need to 5861 * Note that after link down-up as result of cable plug, the xgxs
5765 initialize it*/ 5862 * link would probably become up again without the need
5766 5863 * initialize it
5767 if ((int_phy->type != PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT) && 5864 */
5768 (int_phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) && 5865 if (!(SINGLE_MEDIA_DIRECT(params))) {
5769 (int_phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706) && 5866 DP(NETIF_MSG_LINK, "ext_phy_link_up = %d, int_link_up = %d,"
5770 (int_phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) && 5867 " init_preceding = %d\n", ext_phy_link_up,
5771 (int_phy->type && !vars->phy_link_up)) 5868 vars->phy_link_up,
5772 bnx2x_init_internal_phy(int_phy, params, vars); 5869 params->phy[EXT_PHY1].flags &
5773 5870 FLAGS_INIT_XGXS_FIRST);
5774 /* link is up only if both local phy and external phy are up */ 5871 if (!(params->phy[EXT_PHY1].flags &
5775 vars->link_up = (ext_phy_link_up && vars->phy_link_up); 5872 FLAGS_INIT_XGXS_FIRST)
5873 && ext_phy_link_up && !vars->phy_link_up) {
5874 vars->line_speed = ext_phy_line_speed;
5875 if (vars->line_speed < SPEED_1000)
5876 vars->phy_flags |= PHY_SGMII_FLAG;
5877 else
5878 vars->phy_flags &= ~PHY_SGMII_FLAG;
5879 bnx2x_init_internal_phy(&params->phy[INT_PHY],
5880 params,
5881 vars);
5882 }
5883 }
5884 /**
5885 * Link is up only if both local phy and external phy (in case of
5886 * non-direct board) are up
5887 */
5888 vars->link_up = (vars->phy_link_up &&
5889 (ext_phy_link_up ||
5890 SINGLE_MEDIA_DIRECT(params)));
5776 5891
5777 if (vars->link_up) 5892 if (vars->link_up)
5778 rc = bnx2x_update_link_up(params, vars, link_10g, gp_status); 5893 rc = bnx2x_update_link_up(params, vars, link_10g);
5779 else 5894 else
5780 rc = bnx2x_update_link_down(params, vars); 5895 rc = bnx2x_update_link_down(params, vars);
5781 5896
5782 return rc; 5897 return rc;
5783} 5898}
5784 5899
5900static void bnx2x_8481_hw_reset(struct bnx2x_phy *phy,
5901 struct link_params *params)
5902{
5903 bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1,
5904 MISC_REGISTERS_GPIO_OUTPUT_LOW, 0);
5905 bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1,
5906 MISC_REGISTERS_GPIO_OUTPUT_LOW, 1);
5907}
5908
5909static void bnx2x_8727_hw_reset(struct bnx2x_phy *phy,
5910 struct link_params *params) {
5911 u32 swap_val, swap_override;
5912 u8 port;
5913 /**
5914 * The PHY reset is controlled by GPIO 1. Fake the port number
5915 * to cancel the swap done in set_gpio()
5916 */
5917 struct bnx2x *bp = params->bp;
5918 swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
5919 swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
5920 port = (swap_val && swap_override) ^ 1;
5921 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
5922 MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
5923}
5924
5925static void bnx2x_7101_hw_reset(struct bnx2x_phy *phy,
5926 struct link_params *params) {
5927 /* Low power mode is controlled by GPIO 2 */
5928 bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_2,
5929 MISC_REGISTERS_GPIO_OUTPUT_LOW, params->port);
5930 /* The PHY reset is controlled by GPIO 1 */
5931 bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1,
5932 MISC_REGISTERS_GPIO_OUTPUT_LOW, params->port);
5933}
5934/******************************************************************/
5935/* STATIC PHY DECLARATION */
5936/******************************************************************/
5937
5938static struct bnx2x_phy phy_null = {
5939 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN,
5940 .addr = 0,
5941 .flags = FLAGS_INIT_XGXS_FIRST,
5942 .def_md_devad = 0,
5943 .reserved = 0,
5944 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
5945 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
5946 .mdio_ctrl = 0,
5947 .supported = 0,
5948 .media_type = ETH_PHY_NOT_PRESENT,
5949 .ver_addr = 0,
5950 .req_flow_ctrl = 0,
5951 .req_line_speed = 0,
5952 .speed_cap_mask = 0,
5953 .req_duplex = 0,
5954 .rsrv = 0,
5955 .config_init = (config_init_t)NULL,
5956 .read_status = (read_status_t)NULL,
5957 .link_reset = (link_reset_t)NULL,
5958 .config_loopback = (config_loopback_t)NULL,
5959 .format_fw_ver = (format_fw_ver_t)NULL,
5960 .hw_reset = (hw_reset_t)NULL,
5961 .set_link_led = (set_link_led_t)NULL
5962};
5963
5964static struct bnx2x_phy phy_serdes = {
5965 .type = PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT,
5966 .addr = 0xff,
5967 .flags = 0,
5968 .def_md_devad = 0,
5969 .reserved = 0,
5970 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
5971 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
5972 .mdio_ctrl = 0,
5973 .supported = (SUPPORTED_10baseT_Half |
5974 SUPPORTED_10baseT_Full |
5975 SUPPORTED_100baseT_Half |
5976 SUPPORTED_100baseT_Full |
5977 SUPPORTED_1000baseT_Full |
5978 SUPPORTED_2500baseX_Full |
5979 SUPPORTED_TP |
5980 SUPPORTED_Autoneg |
5981 SUPPORTED_Pause |
5982 SUPPORTED_Asym_Pause),
5983 .media_type = ETH_PHY_UNSPECIFIED,
5984 .ver_addr = 0,
5985 .req_flow_ctrl = 0,
5986 .req_line_speed = 0,
5987 .speed_cap_mask = 0,
5988 .req_duplex = 0,
5989 .rsrv = 0,
5990 .config_init = (config_init_t)bnx2x_init_serdes,
5991 .read_status = (read_status_t)bnx2x_link_settings_status,
5992 .link_reset = (link_reset_t)bnx2x_int_link_reset,
5993 .config_loopback = (config_loopback_t)NULL,
5994 .format_fw_ver = (format_fw_ver_t)NULL,
5995 .hw_reset = (hw_reset_t)NULL,
5996 .set_link_led = (set_link_led_t)NULL
5997};
5998
5999static struct bnx2x_phy phy_xgxs = {
6000 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
6001 .addr = 0xff,
6002 .flags = 0,
6003 .def_md_devad = 0,
6004 .reserved = 0,
6005 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6006 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6007 .mdio_ctrl = 0,
6008 .supported = (SUPPORTED_10baseT_Half |
6009 SUPPORTED_10baseT_Full |
6010 SUPPORTED_100baseT_Half |
6011 SUPPORTED_100baseT_Full |
6012 SUPPORTED_1000baseT_Full |
6013 SUPPORTED_2500baseX_Full |
6014 SUPPORTED_10000baseT_Full |
6015 SUPPORTED_FIBRE |
6016 SUPPORTED_Autoneg |
6017 SUPPORTED_Pause |
6018 SUPPORTED_Asym_Pause),
6019 .media_type = ETH_PHY_UNSPECIFIED,
6020 .ver_addr = 0,
6021 .req_flow_ctrl = 0,
6022 .req_line_speed = 0,
6023 .speed_cap_mask = 0,
6024 .req_duplex = 0,
6025 .rsrv = 0,
6026 .config_init = (config_init_t)bnx2x_init_xgxs,
6027 .read_status = (read_status_t)bnx2x_link_settings_status,
6028 .link_reset = (link_reset_t)bnx2x_int_link_reset,
6029 .config_loopback = (config_loopback_t)bnx2x_set_xgxs_loopback,
6030 .format_fw_ver = (format_fw_ver_t)NULL,
6031 .hw_reset = (hw_reset_t)NULL,
6032 .set_link_led = (set_link_led_t)NULL
6033};
6034
6035static struct bnx2x_phy phy_7101 = {
6036 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
6037 .addr = 0xff,
6038 .flags = FLAGS_FAN_FAILURE_DET_REQ,
6039 .def_md_devad = 0,
6040 .reserved = 0,
6041 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6042 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6043 .mdio_ctrl = 0,
6044 .supported = (SUPPORTED_10000baseT_Full |
6045 SUPPORTED_TP |
6046 SUPPORTED_Autoneg |
6047 SUPPORTED_Pause |
6048 SUPPORTED_Asym_Pause),
6049 .media_type = ETH_PHY_BASE_T,
6050 .ver_addr = 0,
6051 .req_flow_ctrl = 0,
6052 .req_line_speed = 0,
6053 .speed_cap_mask = 0,
6054 .req_duplex = 0,
6055 .rsrv = 0,
6056 .config_init = (config_init_t)bnx2x_7101_config_init,
6057 .read_status = (read_status_t)bnx2x_7101_read_status,
6058 .link_reset = (link_reset_t)bnx2x_common_ext_link_reset,
6059 .config_loopback = (config_loopback_t)bnx2x_7101_config_loopback,
6060 .format_fw_ver = (format_fw_ver_t)bnx2x_7101_format_ver,
6061 .hw_reset = (hw_reset_t)bnx2x_7101_hw_reset,
6062 .set_link_led = (set_link_led_t)NULL
6063};
6064static struct bnx2x_phy phy_8073 = {
6065 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
6066 .addr = 0xff,
6067 .flags = FLAGS_HW_LOCK_REQUIRED,
6068 .def_md_devad = 0,
6069 .reserved = 0,
6070 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6071 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6072 .mdio_ctrl = 0,
6073 .supported = (SUPPORTED_10000baseT_Full |
6074 SUPPORTED_2500baseX_Full |
6075 SUPPORTED_1000baseT_Full |
6076 SUPPORTED_FIBRE |
6077 SUPPORTED_Autoneg |
6078 SUPPORTED_Pause |
6079 SUPPORTED_Asym_Pause),
6080 .media_type = ETH_PHY_UNSPECIFIED,
6081 .ver_addr = 0,
6082 .req_flow_ctrl = 0,
6083 .req_line_speed = 0,
6084 .speed_cap_mask = 0,
6085 .req_duplex = 0,
6086 .rsrv = 0,
6087 .config_init = (config_init_t)bnx2x_8072_8073_config_init,
6088 .read_status = (read_status_t)bnx2x_8073_read_status,
6089 .link_reset = (link_reset_t)bnx2x_8073_link_reset,
6090 .config_loopback = (config_loopback_t)NULL,
6091 .format_fw_ver = (format_fw_ver_t)bnx2x_format_ver,
6092 .hw_reset = (hw_reset_t)NULL,
6093 .set_link_led = (set_link_led_t)NULL
6094};
6095static struct bnx2x_phy phy_8705 = {
6096 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705,
6097 .addr = 0xff,
6098 .flags = FLAGS_INIT_XGXS_FIRST,
6099 .def_md_devad = 0,
6100 .reserved = 0,
6101 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6102 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6103 .mdio_ctrl = 0,
6104 .supported = (SUPPORTED_10000baseT_Full |
6105 SUPPORTED_FIBRE |
6106 SUPPORTED_Pause |
6107 SUPPORTED_Asym_Pause),
6108 .media_type = ETH_PHY_XFP_FIBER,
6109 .ver_addr = 0,
6110 .req_flow_ctrl = 0,
6111 .req_line_speed = 0,
6112 .speed_cap_mask = 0,
6113 .req_duplex = 0,
6114 .rsrv = 0,
6115 .config_init = (config_init_t)bnx2x_8705_config_init,
6116 .read_status = (read_status_t)bnx2x_8705_read_status,
6117 .link_reset = (link_reset_t)bnx2x_common_ext_link_reset,
6118 .config_loopback = (config_loopback_t)NULL,
6119 .format_fw_ver = (format_fw_ver_t)bnx2x_null_format_ver,
6120 .hw_reset = (hw_reset_t)NULL,
6121 .set_link_led = (set_link_led_t)NULL
6122};
6123static struct bnx2x_phy phy_8706 = {
6124 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706,
6125 .addr = 0xff,
6126 .flags = FLAGS_INIT_XGXS_FIRST,
6127 .def_md_devad = 0,
6128 .reserved = 0,
6129 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6130 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6131 .mdio_ctrl = 0,
6132 .supported = (SUPPORTED_10000baseT_Full |
6133 SUPPORTED_1000baseT_Full |
6134 SUPPORTED_FIBRE |
6135 SUPPORTED_Pause |
6136 SUPPORTED_Asym_Pause),
6137 .media_type = ETH_PHY_SFP_FIBER,
6138 .ver_addr = 0,
6139 .req_flow_ctrl = 0,
6140 .req_line_speed = 0,
6141 .speed_cap_mask = 0,
6142 .req_duplex = 0,
6143 .rsrv = 0,
6144 .config_init = (config_init_t)bnx2x_8706_config_init,
6145 .read_status = (read_status_t)bnx2x_8706_read_status,
6146 .link_reset = (link_reset_t)bnx2x_common_ext_link_reset,
6147 .config_loopback = (config_loopback_t)NULL,
6148 .format_fw_ver = (format_fw_ver_t)bnx2x_format_ver,
6149 .hw_reset = (hw_reset_t)NULL,
6150 .set_link_led = (set_link_led_t)NULL
6151};
6152
6153static struct bnx2x_phy phy_8726 = {
6154 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
6155 .addr = 0xff,
6156 .flags = (FLAGS_HW_LOCK_REQUIRED |
6157 FLAGS_INIT_XGXS_FIRST),
6158 .def_md_devad = 0,
6159 .reserved = 0,
6160 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6161 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6162 .mdio_ctrl = 0,
6163 .supported = (SUPPORTED_10000baseT_Full |
6164 SUPPORTED_1000baseT_Full |
6165 SUPPORTED_Autoneg |
6166 SUPPORTED_FIBRE |
6167 SUPPORTED_Pause |
6168 SUPPORTED_Asym_Pause),
6169 .media_type = ETH_PHY_SFP_FIBER,
6170 .ver_addr = 0,
6171 .req_flow_ctrl = 0,
6172 .req_line_speed = 0,
6173 .speed_cap_mask = 0,
6174 .req_duplex = 0,
6175 .rsrv = 0,
6176 .config_init = (config_init_t)bnx2x_8726_config_init,
6177 .read_status = (read_status_t)bnx2x_8726_read_status,
6178 .link_reset = (link_reset_t)bnx2x_8726_link_reset,
6179 .config_loopback = (config_loopback_t)bnx2x_8726_config_loopback,
6180 .format_fw_ver = (format_fw_ver_t)bnx2x_format_ver,
6181 .hw_reset = (hw_reset_t)NULL,
6182 .set_link_led = (set_link_led_t)NULL
6183};
6184
6185static struct bnx2x_phy phy_8727 = {
6186 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
6187 .addr = 0xff,
6188 .flags = FLAGS_FAN_FAILURE_DET_REQ,
6189 .def_md_devad = 0,
6190 .reserved = 0,
6191 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6192 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6193 .mdio_ctrl = 0,
6194 .supported = (SUPPORTED_10000baseT_Full |
6195 SUPPORTED_1000baseT_Full |
6196 SUPPORTED_Autoneg |
6197 SUPPORTED_FIBRE |
6198 SUPPORTED_Pause |
6199 SUPPORTED_Asym_Pause),
6200 .media_type = ETH_PHY_SFP_FIBER,
6201 .ver_addr = 0,
6202 .req_flow_ctrl = 0,
6203 .req_line_speed = 0,
6204 .speed_cap_mask = 0,
6205 .req_duplex = 0,
6206 .rsrv = 0,
6207 .config_init = (config_init_t)bnx2x_8727_config_init,
6208 .read_status = (read_status_t)bnx2x_8727_read_status,
6209 .link_reset = (link_reset_t)bnx2x_8727_link_reset,
6210 .config_loopback = (config_loopback_t)NULL,
6211 .format_fw_ver = (format_fw_ver_t)bnx2x_format_ver,
6212 .hw_reset = (hw_reset_t)bnx2x_8727_hw_reset,
6213 .set_link_led = (set_link_led_t)NULL
6214};
6215static struct bnx2x_phy phy_8481 = {
6216 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
6217 .addr = 0xff,
6218 .flags = FLAGS_FAN_FAILURE_DET_REQ,
6219 .def_md_devad = 0,
6220 .reserved = 0,
6221 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6222 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6223 .mdio_ctrl = 0,
6224 .supported = (SUPPORTED_10baseT_Half |
6225 SUPPORTED_10baseT_Full |
6226 SUPPORTED_100baseT_Half |
6227 SUPPORTED_100baseT_Full |
6228 SUPPORTED_1000baseT_Full |
6229 SUPPORTED_10000baseT_Full |
6230 SUPPORTED_TP |
6231 SUPPORTED_Autoneg |
6232 SUPPORTED_Pause |
6233 SUPPORTED_Asym_Pause),
6234 .media_type = ETH_PHY_BASE_T,
6235 .ver_addr = 0,
6236 .req_flow_ctrl = 0,
6237 .req_line_speed = 0,
6238 .speed_cap_mask = 0,
6239 .req_duplex = 0,
6240 .rsrv = 0,
6241 .config_init = (config_init_t)bnx2x_8481_config_init,
6242 .read_status = (read_status_t)bnx2x_848xx_read_status,
6243 .link_reset = (link_reset_t)bnx2x_8481_link_reset,
6244 .config_loopback = (config_loopback_t)NULL,
6245 .format_fw_ver = (format_fw_ver_t)bnx2x_848xx_format_ver,
6246 .hw_reset = (hw_reset_t)bnx2x_8481_hw_reset,
6247 .set_link_led = (set_link_led_t)NULL
6248};
6249
6250static struct bnx2x_phy phy_84823 = {
6251 .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823,
6252 .addr = 0xff,
6253 .flags = FLAGS_FAN_FAILURE_DET_REQ,
6254 .def_md_devad = 0,
6255 .reserved = 0,
6256 .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6257 .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
6258 .mdio_ctrl = 0,
6259 .supported = (SUPPORTED_10baseT_Half |
6260 SUPPORTED_10baseT_Full |
6261 SUPPORTED_100baseT_Half |
6262 SUPPORTED_100baseT_Full |
6263 SUPPORTED_1000baseT_Full |
6264 SUPPORTED_10000baseT_Full |
6265 SUPPORTED_TP |
6266 SUPPORTED_Autoneg |
6267 SUPPORTED_Pause |
6268 SUPPORTED_Asym_Pause),
6269 .media_type = ETH_PHY_BASE_T,
6270 .ver_addr = 0,
6271 .req_flow_ctrl = 0,
6272 .req_line_speed = 0,
6273 .speed_cap_mask = 0,
6274 .req_duplex = 0,
6275 .rsrv = 0,
6276 .config_init = (config_init_t)bnx2x_848x3_config_init,
6277 .read_status = (read_status_t)bnx2x_848xx_read_status,
6278 .link_reset = (link_reset_t)bnx2x_848x3_link_reset,
6279 .config_loopback = (config_loopback_t)NULL,
6280 .format_fw_ver = (format_fw_ver_t)bnx2x_848xx_format_ver,
6281 .hw_reset = (hw_reset_t)NULL,
6282 .set_link_led = (set_link_led_t)NULL
6283};
6284
6285/*****************************************************************/
6286/* */
6287/* Populate the phy according. Main function: bnx2x_populate_phy */
6288/* */
6289/*****************************************************************/
6290
6291static void bnx2x_populate_preemphasis(struct bnx2x *bp, u32 shmem_base,
6292 struct bnx2x_phy *phy, u8 port,
6293 u8 phy_index)
6294{
6295 /* Get the 4 lanes xgxs config rx and tx */
6296 u32 rx = 0, tx = 0, i;
6297 for (i = 0; i < 2; i++) {
6298 /**
6299 * INT_PHY and EXT_PHY1 share the same value location in the
6300 * shmem. When num_phys is greater than 1, than this value
6301 * applies only to EXT_PHY1
6302 */
6303
6304 rx = REG_RD(bp, shmem_base +
6305 offsetof(struct shmem_region,
6306 dev_info.port_hw_config[port].xgxs_config_rx[i<<1]));
6307
6308 tx = REG_RD(bp, shmem_base +
6309 offsetof(struct shmem_region,
6310 dev_info.port_hw_config[port].xgxs_config_tx[i<<1]));
6311
6312 phy->rx_preemphasis[i << 1] = ((rx>>16) & 0xffff);
6313 phy->rx_preemphasis[(i << 1) + 1] = (rx & 0xffff);
6314
6315 phy->tx_preemphasis[i << 1] = ((tx>>16) & 0xffff);
6316 phy->tx_preemphasis[(i << 1) + 1] = (tx & 0xffff);
6317 }
6318}
6319
5785static u32 bnx2x_get_ext_phy_config(struct bnx2x *bp, u32 shmem_base, 6320static u32 bnx2x_get_ext_phy_config(struct bnx2x *bp, u32 shmem_base,
5786 u8 phy_index, u8 port) 6321 u8 phy_index, u8 port)
5787{ 6322{
@@ -5799,6 +6334,45 @@ static u32 bnx2x_get_ext_phy_config(struct bnx2x *bp, u32 shmem_base,
5799 6334
5800 return ext_phy_config; 6335 return ext_phy_config;
5801} 6336}
6337static u8 bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
6338 struct bnx2x_phy *phy)
6339{
6340 u32 phy_addr;
6341 u32 chip_id;
6342 u32 switch_cfg = (REG_RD(bp, shmem_base +
6343 offsetof(struct shmem_region,
6344 dev_info.port_feature_config[port].link_config)) &
6345 PORT_FEATURE_CONNECTED_SWITCH_MASK);
6346 chip_id = REG_RD(bp, MISC_REG_CHIP_NUM) << 16;
6347 switch (switch_cfg) {
6348 case SWITCH_CFG_1G:
6349 phy_addr = REG_RD(bp,
6350 NIG_REG_SERDES0_CTRL_PHY_ADDR +
6351 port * 0x10);
6352 *phy = phy_serdes;
6353 break;
6354 case SWITCH_CFG_10G:
6355 phy_addr = REG_RD(bp,
6356 NIG_REG_XGXS0_CTRL_PHY_ADDR +
6357 port * 0x18);
6358 *phy = phy_xgxs;
6359 break;
6360 default:
6361 DP(NETIF_MSG_LINK, "Invalid switch_cfg\n");
6362 return -EINVAL;
6363 }
6364 phy->addr = (u8)phy_addr;
6365 phy->mdio_ctrl = bnx2x_get_emac_base(bp,
6366 phy->type,
6367 port);
6368 phy->def_md_devad = DEFAULT_PHY_DEV_ADDR;
6369
6370 DP(NETIF_MSG_LINK, "Internal phy port=%d, addr=0x%x, mdio_ctl=0x%x\n",
6371 port, phy->addr, phy->mdio_ctrl);
6372
6373 bnx2x_populate_preemphasis(bp, shmem_base, phy, port, INT_PHY);
6374 return 0;
6375}
5802 6376
5803static u8 bnx2x_populate_ext_phy(struct bnx2x *bp, 6377static u8 bnx2x_populate_ext_phy(struct bnx2x *bp,
5804 u8 phy_index, 6378 u8 phy_index,
@@ -5806,12 +6380,52 @@ static u8 bnx2x_populate_ext_phy(struct bnx2x *bp,
5806 u8 port, 6380 u8 port,
5807 struct bnx2x_phy *phy) 6381 struct bnx2x_phy *phy)
5808{ 6382{
5809 u32 ext_phy_config; 6383 u32 ext_phy_config, phy_type;
5810 6384
5811 ext_phy_config = bnx2x_get_ext_phy_config(bp, shmem_base, 6385 ext_phy_config = bnx2x_get_ext_phy_config(bp, shmem_base,
5812 phy_index, port); 6386 phy_index, port);
5813 phy->type = XGXS_EXT_PHY_TYPE(ext_phy_config); 6387 phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
6388 /* Select the phy type */
6389 switch (phy_type) {
6390 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
6391 *phy = phy_8073;
6392 break;
6393 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
6394 *phy = phy_8705;
6395 break;
6396 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
6397 *phy = phy_8706;
6398 break;
6399 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
6400 *phy = phy_8726;
6401 break;
6402 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC:
6403 /* BCM8727_NOC => BCM8727 no over current */
6404 *phy = phy_8727;
6405 phy->flags |= FLAGS_NOC;
6406 break;
6407 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
6408 *phy = phy_8727;
6409 break;
6410 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
6411 *phy = phy_8481;
6412 break;
6413 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
6414 *phy = phy_84823;
6415 break;
6416 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
6417 *phy = phy_7101;
6418 break;
6419 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
6420 *phy = phy_null;
6421 return -EINVAL;
6422 default:
6423 *phy = phy_null;
6424 return 0;
6425 }
6426
5814 phy->addr = XGXS_EXT_PHY_ADDR(ext_phy_config); 6427 phy->addr = XGXS_EXT_PHY_ADDR(ext_phy_config);
6428 bnx2x_populate_preemphasis(bp, shmem_base, phy, port, phy_index);
5815 phy->mdio_ctrl = bnx2x_get_emac_base(bp, phy->type, port); 6429 phy->mdio_ctrl = bnx2x_get_emac_base(bp, phy->type, port);
5816 return 0; 6430 return 0;
5817} 6431}
@@ -5820,11 +6434,119 @@ static u8 bnx2x_populate_phy(struct bnx2x *bp, u8 phy_index, u32 shmem_base,
5820 u8 port, struct bnx2x_phy *phy) 6434 u8 port, struct bnx2x_phy *phy)
5821{ 6435{
5822 u8 status = 0; 6436 u8 status = 0;
6437 phy->type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN;
6438 if (phy_index == INT_PHY)
6439 return bnx2x_populate_int_phy(bp, shmem_base, port, phy);
5823 status = bnx2x_populate_ext_phy(bp, phy_index, shmem_base, 6440 status = bnx2x_populate_ext_phy(bp, phy_index, shmem_base,
5824 port, phy); 6441 port, phy);
5825 return status; 6442 return status;
5826} 6443}
5827 6444
6445static void bnx2x_phy_def_cfg(struct link_params *params,
6446 struct bnx2x_phy *phy,
6447 u8 actual_phy_idx)
6448{
6449 struct bnx2x *bp = params->bp;
6450 u32 link_config;
6451 /* Populate the default phy configuration for MF mode */
6452 link_config = REG_RD(bp, params->shmem_base +
6453 offsetof(struct shmem_region, dev_info.
6454 port_feature_config[params->port].link_config));
6455 phy->speed_cap_mask = REG_RD(bp, params->shmem_base +
6456 offsetof(struct shmem_region, dev_info.
6457 port_hw_config[params->port].speed_capability_mask));
6458
6459 phy->req_duplex = DUPLEX_FULL;
6460 switch (link_config & PORT_FEATURE_LINK_SPEED_MASK) {
6461 case PORT_FEATURE_LINK_SPEED_10M_HALF:
6462 phy->req_duplex = DUPLEX_HALF;
6463 case PORT_FEATURE_LINK_SPEED_10M_FULL:
6464 phy->req_line_speed = SPEED_10;
6465 break;
6466 case PORT_FEATURE_LINK_SPEED_100M_HALF:
6467 phy->req_duplex = DUPLEX_HALF;
6468 case PORT_FEATURE_LINK_SPEED_100M_FULL:
6469 phy->req_line_speed = SPEED_100;
6470 break;
6471 case PORT_FEATURE_LINK_SPEED_1G:
6472 phy->req_line_speed = SPEED_1000;
6473 break;
6474 case PORT_FEATURE_LINK_SPEED_2_5G:
6475 phy->req_line_speed = SPEED_2500;
6476 break;
6477 case PORT_FEATURE_LINK_SPEED_10G_CX4:
6478 phy->req_line_speed = SPEED_10000;
6479 break;
6480 default:
6481 phy->req_line_speed = SPEED_AUTO_NEG;
6482 break;
6483 }
6484
6485 switch (link_config & PORT_FEATURE_FLOW_CONTROL_MASK) {
6486 case PORT_FEATURE_FLOW_CONTROL_AUTO:
6487 phy->req_flow_ctrl = BNX2X_FLOW_CTRL_AUTO;
6488 break;
6489 case PORT_FEATURE_FLOW_CONTROL_TX:
6490 phy->req_flow_ctrl = BNX2X_FLOW_CTRL_TX;
6491 break;
6492 case PORT_FEATURE_FLOW_CONTROL_RX:
6493 phy->req_flow_ctrl = BNX2X_FLOW_CTRL_RX;
6494 break;
6495 case PORT_FEATURE_FLOW_CONTROL_BOTH:
6496 phy->req_flow_ctrl = BNX2X_FLOW_CTRL_BOTH;
6497 break;
6498 default:
6499 phy->req_flow_ctrl = BNX2X_FLOW_CTRL_NONE;
6500 break;
6501 }
6502}
6503
6504u8 bnx2x_phy_probe(struct link_params *params)
6505{
6506 u8 phy_index, actual_phy_idx, link_cfg_idx;
6507
6508 struct bnx2x *bp = params->bp;
6509 struct bnx2x_phy *phy;
6510 params->num_phys = 0;
6511 DP(NETIF_MSG_LINK, "Begin phy probe\n");
6512
6513 for (phy_index = INT_PHY; phy_index < MAX_PHYS;
6514 phy_index++) {
6515 link_cfg_idx = LINK_CONFIG_IDX(phy_index);
6516 actual_phy_idx = phy_index;
6517
6518 phy = &params->phy[actual_phy_idx];
6519 if (bnx2x_populate_phy(bp, phy_index, params->shmem_base,
6520 params->port,
6521 phy) != 0) {
6522 params->num_phys = 0;
6523 DP(NETIF_MSG_LINK, "phy probe failed in phy index %d\n",
6524 phy_index);
6525 for (phy_index = INT_PHY;
6526 phy_index < MAX_PHYS;
6527 phy_index++)
6528 *phy = phy_null;
6529 return -EINVAL;
6530 }
6531 if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)
6532 break;
6533
6534 bnx2x_phy_def_cfg(params, phy, actual_phy_idx);
6535 params->num_phys++;
6536 }
6537
6538 DP(NETIF_MSG_LINK, "End phy probe. #phys found %x\n", params->num_phys);
6539 return 0;
6540}
6541
6542u32 bnx2x_supported_attr(struct link_params *params, u8 phy_idx)
6543{
6544 if (phy_idx < params->num_phys)
6545 return params->phy[phy_idx].supported;
6546 return 0;
6547}
6548
6549
5828static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base) 6550static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base)
5829{ 6551{
5830 struct bnx2x_phy phy[PORT_MAX]; 6552 struct bnx2x_phy phy[PORT_MAX];
diff --git a/drivers/net/bnx2x/bnx2x_link.h b/drivers/net/bnx2x/bnx2x_link.h
index 9bfe7fa452bc..9717cb1fbad0 100644
--- a/drivers/net/bnx2x/bnx2x_link.h
+++ b/drivers/net/bnx2x/bnx2x_link.h
@@ -46,6 +46,15 @@
46#define SFP_EEPROM_PART_NO_ADDR 0x28 46#define SFP_EEPROM_PART_NO_ADDR 0x28
47#define SFP_EEPROM_PART_NO_SIZE 16 47#define SFP_EEPROM_PART_NO_SIZE 16
48#define PWR_FLT_ERR_MSG_LEN 250 48#define PWR_FLT_ERR_MSG_LEN 250
49
50#define XGXS_EXT_PHY_TYPE(ext_phy_config) \
51 ((ext_phy_config) & PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK)
52#define XGXS_EXT_PHY_ADDR(ext_phy_config) \
53 (((ext_phy_config) & PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> \
54 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT)
55#define SERDES_EXT_PHY_TYPE(ext_phy_config) \
56 ((ext_phy_config) & PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK)
57
49/* Single Media Direct board is the plain 577xx board with CX4/RJ45 jacks */ 58/* Single Media Direct board is the plain 577xx board with CX4/RJ45 jacks */
50#define SINGLE_MEDIA_DIRECT(params) (params->num_phys == 1) 59#define SINGLE_MEDIA_DIRECT(params) (params->num_phys == 1)
51/* Single Media board contains single external phy */ 60/* Single Media board contains single external phy */
@@ -58,6 +67,10 @@
58 67
59#define MAX_PHYS 2 68#define MAX_PHYS 2
60 69
70/* Same configuration is shared between the XGXS and the first external phy */
71#define LINK_CONFIG_SIZE (MAX_PHYS - 1)
72#define LINK_CONFIG_IDX(_phy_idx) ((_phy_idx == INT_PHY) ? \
73 0 : (_phy_idx - 1))
61/***********************************************************/ 74/***********************************************************/
62/* bnx2x_phy struct */ 75/* bnx2x_phy struct */
63/* Defines the required arguments and function per phy */ 76/* Defines the required arguments and function per phy */
@@ -66,13 +79,88 @@ struct link_vars;
66struct link_params; 79struct link_params;
67struct bnx2x_phy; 80struct bnx2x_phy;
68 81
82typedef u8 (*config_init_t)(struct bnx2x_phy *phy, struct link_params *params,
83 struct link_vars *vars);
84typedef u8 (*read_status_t)(struct bnx2x_phy *phy, struct link_params *params,
85 struct link_vars *vars);
86typedef void (*link_reset_t)(struct bnx2x_phy *phy,
87 struct link_params *params);
88typedef void (*config_loopback_t)(struct bnx2x_phy *phy,
89 struct link_params *params);
90typedef u8 (*format_fw_ver_t)(u32 raw, u8 *str, u16 *len);
91typedef void (*hw_reset_t)(struct bnx2x_phy *phy, struct link_params *params);
92typedef void (*set_link_led_t)(struct bnx2x_phy *phy,
93 struct link_params *params, u8 mode);
94
69struct bnx2x_phy { 95struct bnx2x_phy {
70 u32 type; 96 u32 type;
71 97
72 /* Loaded during init */ 98 /* Loaded during init */
73 u8 addr; 99 u8 addr;
74 100
101 u8 flags;
102 /* Require HW lock */
103#define FLAGS_HW_LOCK_REQUIRED (1<<0)
104 /* No Over-Current detection */
105#define FLAGS_NOC (1<<1)
106 /* Fan failure detection required */
107#define FLAGS_FAN_FAILURE_DET_REQ (1<<2)
108 /* Initialize first the XGXS and only then the phy itself */
109#define FLAGS_INIT_XGXS_FIRST (1<<3)
110
111 u8 def_md_devad;
112 u8 reserved;
113 /* preemphasis values for the rx side */
114 u16 rx_preemphasis[4];
115
116 /* preemphasis values for the tx side */
117 u16 tx_preemphasis[4];
118
119 /* EMAC address for access MDIO */
75 u32 mdio_ctrl; 120 u32 mdio_ctrl;
121
122 u32 supported;
123
124 u32 media_type;
125#define ETH_PHY_UNSPECIFIED 0x0
126#define ETH_PHY_SFP_FIBER 0x1
127#define ETH_PHY_XFP_FIBER 0x2
128#define ETH_PHY_DA_TWINAX 0x3
129#define ETH_PHY_BASE_T 0x4
130#define ETH_PHY_NOT_PRESENT 0xff
131
132 /* The address in which version is located*/
133 u32 ver_addr;
134
135 u16 req_flow_ctrl;
136
137 u16 req_line_speed;
138
139 u32 speed_cap_mask;
140
141 u16 req_duplex;
142 u16 rsrv;
143 /* Called per phy/port init, and it configures LASI, speed, autoneg,
144 duplex, flow control negotiation, etc. */
145 config_init_t config_init;
146
147 /* Called due to interrupt. It determines the link, speed */
148 read_status_t read_status;
149
150 /* Called when driver is unloading. Should reset the phy */
151 link_reset_t link_reset;
152
153 /* Set the loopback configuration for the phy */
154 config_loopback_t config_loopback;
155
156 /* Format the given raw number into str up to len */
157 format_fw_ver_t format_fw_ver;
158
159 /* Reset the phy (both ports) */
160 hw_reset_t hw_reset;
161
162 /* Set link led mode (on/off/oper)*/
163 set_link_led_t set_link_led;
76}; 164};
77 165
78/* Inputs parameters to the CLC */ 166/* Inputs parameters to the CLC */
@@ -106,38 +194,23 @@ struct link_params {
106#define SWITCH_CFG_10G PORT_FEATURE_CON_SWITCH_10G_SWITCH 194#define SWITCH_CFG_10G PORT_FEATURE_CON_SWITCH_10G_SWITCH
107#define SWITCH_CFG_AUTO_DETECT PORT_FEATURE_CON_SWITCH_AUTO_DETECT 195#define SWITCH_CFG_AUTO_DETECT PORT_FEATURE_CON_SWITCH_AUTO_DETECT
108 196
109 u16 hw_led_mode; /* part of the hw_config read from the shmem */
110
111 /* phy_addr populated by the phy_init function */
112 u8 phy_addr;
113 /*u8 reserved1;*/
114
115 u32 lane_config; 197 u32 lane_config;
116 u32 ext_phy_config;
117#define XGXS_EXT_PHY_TYPE(ext_phy_config) \
118 ((ext_phy_config) & PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK)
119#define XGXS_EXT_PHY_ADDR(ext_phy_config) \
120 (((ext_phy_config) & PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> \
121 PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT)
122#define SERDES_EXT_PHY_TYPE(ext_phy_config) \
123 ((ext_phy_config) & PORT_HW_CFG_SERDES_EXT_PHY_TYPE_MASK)
124 198
125 /* Phy register parameter */ 199 /* Phy register parameter */
126 u32 chip_id; 200 u32 chip_id;
127 201
128 u16 xgxs_config_rx[4]; /* preemphasis values for the rx side */
129 u16 xgxs_config_tx[4]; /* preemphasis values for the tx side */
130
131 u32 feature_config_flags; 202 u32 feature_config_flags;
132#define FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED (1<<0) 203#define FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED (1<<0)
133#define FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY (1<<2) 204#define FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY (1<<2)
134#define FEATURE_CONFIG_BCM8727_NOC (1<<3)
135 /* Will be populated during common init */ 205 /* Will be populated during common init */
136 struct bnx2x_phy phy[MAX_PHYS]; 206 struct bnx2x_phy phy[MAX_PHYS];
137 207
138 /* Will be populated during common init */ 208 /* Will be populated during common init */
139 u8 num_phys; 209 u8 num_phys;
140 210
211 u8 rsrv;
212 u16 hw_led_mode; /* part of the hw_config read from the shmem */
213
141 /* Device pointer passed to all callback functions */ 214 /* Device pointer passed to all callback functions */
142 struct bnx2x *bp; 215 struct bnx2x *bp;
143}; 216};
diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c
index 174ed8b4587e..1ecff37bab18 100644
--- a/drivers/net/bnx2x/bnx2x_main.c
+++ b/drivers/net/bnx2x/bnx2x_main.c
@@ -1960,12 +1960,16 @@ static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted)
1960static inline void bnx2x_fan_failure(struct bnx2x *bp) 1960static inline void bnx2x_fan_failure(struct bnx2x *bp)
1961{ 1961{
1962 int port = BP_PORT(bp); 1962 int port = BP_PORT(bp);
1963 1963 u32 ext_phy_config;
1964 /* mark the failure */ 1964 /* mark the failure */
1965 bp->link_params.ext_phy_config &= ~PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK; 1965 ext_phy_config =
1966 bp->link_params.ext_phy_config |= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE; 1966 SHMEM_RD(bp,
1967 dev_info.port_hw_config[port].external_phy_config);
1968
1969 ext_phy_config &= ~PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK;
1970 ext_phy_config |= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE;
1967 SHMEM_WR(bp, dev_info.port_hw_config[port].external_phy_config, 1971 SHMEM_WR(bp, dev_info.port_hw_config[port].external_phy_config,
1968 bp->link_params.ext_phy_config); 1972 ext_phy_config);
1969 1973
1970 /* log the failure */ 1974 /* log the failure */
1971 netdev_err(bp->dev, "Fan Failure on Network Controller has caused" 1975 netdev_err(bp->dev, "Fan Failure on Network Controller has caused"
@@ -1991,7 +1995,7 @@ static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn)
1991 BNX2X_ERR("SPIO5 hw attention\n"); 1995 BNX2X_ERR("SPIO5 hw attention\n");
1992 1996
1993 /* Fan failure attention */ 1997 /* Fan failure attention */
1994 switch (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config)) { 1998 switch (bp->link_params.phy[EXT_PHY1].type) {
1995 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101: 1999 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
1996 /* Low power mode is controlled by GPIO 2 */ 2000 /* Low power mode is controlled by GPIO 2 */
1997 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2, 2001 bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
@@ -4140,7 +4144,7 @@ static int bnx2x_init_common(struct bnx2x *bp)
4140 return -EBUSY; 4144 return -EBUSY;
4141 } 4145 }
4142 4146
4143 switch (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config)) { 4147 switch (bp->link_params.phy[EXT_PHY1].type) {
4144 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: 4148 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
4145 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073: 4149 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
4146 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726: 4150 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
@@ -4299,7 +4303,7 @@ static int bnx2x_init_port(struct bnx2x *bp)
4299 bnx2x_init_block(bp, MCP_BLOCK, init_stage); 4303 bnx2x_init_block(bp, MCP_BLOCK, init_stage);
4300 bnx2x_init_block(bp, DMAE_BLOCK, init_stage); 4304 bnx2x_init_block(bp, DMAE_BLOCK, init_stage);
4301 4305
4302 switch (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config)) { 4306 switch (bp->link_params.phy[EXT_PHY1].type) {
4303 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726: 4307 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
4304 { 4308 {
4305 u32 swap_val, swap_override, aeu_gpio_mask, offset; 4309 u32 swap_val, swap_override, aeu_gpio_mask, offset;
@@ -4480,7 +4484,7 @@ static int bnx2x_init_func(struct bnx2x *bp)
4480 /* Reset PCIE errors for debug */ 4484 /* Reset PCIE errors for debug */
4481 REG_WR(bp, 0x2114, 0xffffffff); 4485 REG_WR(bp, 0x2114, 0xffffffff);
4482 REG_WR(bp, 0x2120, 0xffffffff); 4486 REG_WR(bp, 0x2120, 0xffffffff);
4483 4487 bnx2x_phy_probe(&bp->link_params);
4484 return 0; 4488 return 0;
4485} 4489}
4486 4490
@@ -6065,194 +6069,32 @@ static void __devinit bnx2x_link_settings_supported(struct bnx2x *bp,
6065 u32 switch_cfg) 6069 u32 switch_cfg)
6066{ 6070{
6067 int port = BP_PORT(bp); 6071 int port = BP_PORT(bp);
6068 u32 ext_phy_type; 6072 bp->port.supported = 0;
6069 6073 switch (bp->link_params.num_phys) {
6070 switch (switch_cfg) { 6074 case 1:
6071 case SWITCH_CFG_1G: 6075 bp->port.supported = bp->link_params.phy[INT_PHY].supported;
6072 BNX2X_DEV_INFO("switch_cfg 0x%x (1G)\n", switch_cfg);
6073
6074 ext_phy_type =
6075 SERDES_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
6076 switch (ext_phy_type) {
6077 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT:
6078 BNX2X_DEV_INFO("ext_phy_type 0x%x (Direct)\n",
6079 ext_phy_type);
6080
6081 bp->port.supported |= (SUPPORTED_10baseT_Half |
6082 SUPPORTED_10baseT_Full |
6083 SUPPORTED_100baseT_Half |
6084 SUPPORTED_100baseT_Full |
6085 SUPPORTED_1000baseT_Full |
6086 SUPPORTED_2500baseX_Full |
6087 SUPPORTED_TP |
6088 SUPPORTED_FIBRE |
6089 SUPPORTED_Autoneg |
6090 SUPPORTED_Pause |
6091 SUPPORTED_Asym_Pause);
6092 break; 6076 break;
6093 6077 case 2:
6094 case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482: 6078 bp->port.supported = bp->link_params.phy[EXT_PHY1].supported;
6095 BNX2X_DEV_INFO("ext_phy_type 0x%x (5482)\n",
6096 ext_phy_type);
6097
6098 bp->port.supported |= (SUPPORTED_10baseT_Half |
6099 SUPPORTED_10baseT_Full |
6100 SUPPORTED_100baseT_Half |
6101 SUPPORTED_100baseT_Full |
6102 SUPPORTED_1000baseT_Full |
6103 SUPPORTED_TP |
6104 SUPPORTED_FIBRE |
6105 SUPPORTED_Autoneg |
6106 SUPPORTED_Pause |
6107 SUPPORTED_Asym_Pause);
6108 break; 6079 break;
6080 }
6109 6081
6110 default: 6082 if (!(bp->port.supported)) {
6111 BNX2X_ERR("NVRAM config error. " 6083 BNX2X_ERR("NVRAM config error. BAD phy config."
6112 "BAD SerDes ext_phy_config 0x%x\n", 6084 "PHY1 config 0x%x\n",
6113 bp->link_params.ext_phy_config); 6085 SHMEM_RD(bp,
6086 dev_info.port_hw_config[port].external_phy_config));
6114 return; 6087 return;
6115 } 6088 }
6116 6089
6090 switch (switch_cfg) {
6091 case SWITCH_CFG_1G:
6117 bp->port.phy_addr = REG_RD(bp, NIG_REG_SERDES0_CTRL_PHY_ADDR + 6092 bp->port.phy_addr = REG_RD(bp, NIG_REG_SERDES0_CTRL_PHY_ADDR +
6118 port*0x10); 6093 port*0x10);
6119 BNX2X_DEV_INFO("phy_addr 0x%x\n", bp->port.phy_addr); 6094 BNX2X_DEV_INFO("phy_addr 0x%x\n", bp->port.phy_addr);
6120 break; 6095 break;
6121 6096
6122 case SWITCH_CFG_10G: 6097 case SWITCH_CFG_10G:
6123 BNX2X_DEV_INFO("switch_cfg 0x%x (10G)\n", switch_cfg);
6124
6125 ext_phy_type =
6126 XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
6127 switch (ext_phy_type) {
6128 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
6129 BNX2X_DEV_INFO("ext_phy_type 0x%x (Direct)\n",
6130 ext_phy_type);
6131
6132 bp->port.supported |= (SUPPORTED_10baseT_Half |
6133 SUPPORTED_10baseT_Full |
6134 SUPPORTED_100baseT_Half |
6135 SUPPORTED_100baseT_Full |
6136 SUPPORTED_1000baseT_Full |
6137 SUPPORTED_2500baseX_Full |
6138 SUPPORTED_10000baseT_Full |
6139 SUPPORTED_TP |
6140 SUPPORTED_FIBRE |
6141 SUPPORTED_Autoneg |
6142 SUPPORTED_Pause |
6143 SUPPORTED_Asym_Pause);
6144 break;
6145
6146 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
6147 BNX2X_DEV_INFO("ext_phy_type 0x%x (8072)\n",
6148 ext_phy_type);
6149
6150 bp->port.supported |= (SUPPORTED_10000baseT_Full |
6151 SUPPORTED_1000baseT_Full |
6152 SUPPORTED_FIBRE |
6153 SUPPORTED_Autoneg |
6154 SUPPORTED_Pause |
6155 SUPPORTED_Asym_Pause);
6156 break;
6157
6158 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
6159 BNX2X_DEV_INFO("ext_phy_type 0x%x (8073)\n",
6160 ext_phy_type);
6161
6162 bp->port.supported |= (SUPPORTED_10000baseT_Full |
6163 SUPPORTED_2500baseX_Full |
6164 SUPPORTED_1000baseT_Full |
6165 SUPPORTED_FIBRE |
6166 SUPPORTED_Autoneg |
6167 SUPPORTED_Pause |
6168 SUPPORTED_Asym_Pause);
6169 break;
6170
6171 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
6172 BNX2X_DEV_INFO("ext_phy_type 0x%x (8705)\n",
6173 ext_phy_type);
6174
6175 bp->port.supported |= (SUPPORTED_10000baseT_Full |
6176 SUPPORTED_FIBRE |
6177 SUPPORTED_Pause |
6178 SUPPORTED_Asym_Pause);
6179 break;
6180
6181 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
6182 BNX2X_DEV_INFO("ext_phy_type 0x%x (8706)\n",
6183 ext_phy_type);
6184
6185 bp->port.supported |= (SUPPORTED_10000baseT_Full |
6186 SUPPORTED_1000baseT_Full |
6187 SUPPORTED_FIBRE |
6188 SUPPORTED_Pause |
6189 SUPPORTED_Asym_Pause);
6190 break;
6191
6192 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
6193 BNX2X_DEV_INFO("ext_phy_type 0x%x (8726)\n",
6194 ext_phy_type);
6195
6196 bp->port.supported |= (SUPPORTED_10000baseT_Full |
6197 SUPPORTED_1000baseT_Full |
6198 SUPPORTED_Autoneg |
6199 SUPPORTED_FIBRE |
6200 SUPPORTED_Pause |
6201 SUPPORTED_Asym_Pause);
6202 break;
6203
6204 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
6205 BNX2X_DEV_INFO("ext_phy_type 0x%x (8727)\n",
6206 ext_phy_type);
6207
6208 bp->port.supported |= (SUPPORTED_10000baseT_Full |
6209 SUPPORTED_1000baseT_Full |
6210 SUPPORTED_Autoneg |
6211 SUPPORTED_FIBRE |
6212 SUPPORTED_Pause |
6213 SUPPORTED_Asym_Pause);
6214 break;
6215
6216 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
6217 BNX2X_DEV_INFO("ext_phy_type 0x%x (SFX7101)\n",
6218 ext_phy_type);
6219
6220 bp->port.supported |= (SUPPORTED_10000baseT_Full |
6221 SUPPORTED_TP |
6222 SUPPORTED_Autoneg |
6223 SUPPORTED_Pause |
6224 SUPPORTED_Asym_Pause);
6225 break;
6226
6227 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
6228 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
6229 BNX2X_DEV_INFO("ext_phy_type 0x%x (BCM848xx)\n",
6230 ext_phy_type);
6231
6232 bp->port.supported |= (SUPPORTED_10baseT_Half |
6233 SUPPORTED_10baseT_Full |
6234 SUPPORTED_100baseT_Half |
6235 SUPPORTED_100baseT_Full |
6236 SUPPORTED_1000baseT_Full |
6237 SUPPORTED_10000baseT_Full |
6238 SUPPORTED_TP |
6239 SUPPORTED_Autoneg |
6240 SUPPORTED_Pause |
6241 SUPPORTED_Asym_Pause);
6242 break;
6243
6244 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE:
6245 BNX2X_ERR("XGXS PHY Failure detected 0x%x\n",
6246 bp->link_params.ext_phy_config);
6247 break;
6248
6249 default:
6250 BNX2X_ERR("NVRAM config error. "
6251 "BAD XGXS ext_phy_config 0x%x\n",
6252 bp->link_params.ext_phy_config);
6253 return;
6254 }
6255
6256 bp->port.phy_addr = REG_RD(bp, NIG_REG_XGXS0_CTRL_PHY_ADDR + 6098 bp->port.phy_addr = REG_RD(bp, NIG_REG_XGXS0_CTRL_PHY_ADDR +
6257 port*0x18); 6099 port*0x18);
6258 BNX2X_DEV_INFO("phy_addr 0x%x\n", bp->port.phy_addr); 6100 BNX2X_DEV_INFO("phy_addr 0x%x\n", bp->port.phy_addr);
@@ -6264,8 +6106,6 @@ static void __devinit bnx2x_link_settings_supported(struct bnx2x *bp,
6264 bp->port.link_config); 6106 bp->port.link_config);
6265 return; 6107 return;
6266 } 6108 }
6267 bp->link_params.phy_addr = bp->port.phy_addr;
6268
6269 /* mask what we support according to speed_cap_mask */ 6109 /* mask what we support according to speed_cap_mask */
6270 if (!(bp->link_params.speed_cap_mask & 6110 if (!(bp->link_params.speed_cap_mask &
6271 PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)) 6111 PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF))
@@ -6309,25 +6149,10 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
6309 bp->link_params.req_line_speed = SPEED_AUTO_NEG; 6149 bp->link_params.req_line_speed = SPEED_AUTO_NEG;
6310 bp->port.advertising = bp->port.supported; 6150 bp->port.advertising = bp->port.supported;
6311 } else { 6151 } else {
6312 u32 ext_phy_type =
6313 XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config);
6314
6315 if ((ext_phy_type ==
6316 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) ||
6317 (ext_phy_type ==
6318 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706)) {
6319 /* force 10G, no AN */ 6152 /* force 10G, no AN */
6320 bp->link_params.req_line_speed = SPEED_10000; 6153 bp->link_params.req_line_speed = SPEED_10000;
6321 bp->port.advertising = 6154 bp->port.advertising = (ADVERTISED_10000baseT_Full |
6322 (ADVERTISED_10000baseT_Full |
6323 ADVERTISED_FIBRE); 6155 ADVERTISED_FIBRE);
6324 break;
6325 }
6326 BNX2X_ERR("NVRAM config error. "
6327 "Invalid link_config 0x%x"
6328 " Autoneg not supported\n",
6329 bp->port.link_config);
6330 return;
6331 } 6156 }
6332 break; 6157 break;
6333 6158
@@ -6475,27 +6300,13 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
6475 int port = BP_PORT(bp); 6300 int port = BP_PORT(bp);
6476 u32 val, val2; 6301 u32 val, val2;
6477 u32 config; 6302 u32 config;
6478 u16 i; 6303 u32 ext_phy_type, ext_phy_config;;
6479 u32 ext_phy_type;
6480 6304
6481 bp->link_params.bp = bp; 6305 bp->link_params.bp = bp;
6482 bp->link_params.port = port; 6306 bp->link_params.port = port;
6483 6307
6484 bp->link_params.lane_config = 6308 bp->link_params.lane_config =
6485 SHMEM_RD(bp, dev_info.port_hw_config[port].lane_config); 6309 SHMEM_RD(bp, dev_info.port_hw_config[port].lane_config);
6486 bp->link_params.ext_phy_config =
6487 SHMEM_RD(bp,
6488 dev_info.port_hw_config[port].external_phy_config);
6489 /* BCM8727_NOC => BCM8727 no over current */
6490 if (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config) ==
6491 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC) {
6492 bp->link_params.ext_phy_config &=
6493 ~PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK;
6494 bp->link_params.ext_phy_config |=
6495 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727;
6496 bp->link_params.feature_config_flags |=
6497 FEATURE_CONFIG_BCM8727_NOC;
6498 }
6499 6310
6500 bp->link_params.speed_cap_mask = 6311 bp->link_params.speed_cap_mask =
6501 SHMEM_RD(bp, 6312 SHMEM_RD(bp,
@@ -6504,18 +6315,6 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
6504 bp->port.link_config = 6315 bp->port.link_config =
6505 SHMEM_RD(bp, dev_info.port_feature_config[port].link_config); 6316 SHMEM_RD(bp, dev_info.port_feature_config[port].link_config);
6506 6317
6507 /* Get the 4 lanes xgxs config rx and tx */
6508 for (i = 0; i < 2; i++) {
6509 val = SHMEM_RD(bp,
6510 dev_info.port_hw_config[port].xgxs_config_rx[i<<1]);
6511 bp->link_params.xgxs_config_rx[i << 1] = ((val>>16) & 0xffff);
6512 bp->link_params.xgxs_config_rx[(i << 1) + 1] = (val & 0xffff);
6513
6514 val = SHMEM_RD(bp,
6515 dev_info.port_hw_config[port].xgxs_config_tx[i<<1]);
6516 bp->link_params.xgxs_config_tx[i << 1] = ((val>>16) & 0xffff);
6517 bp->link_params.xgxs_config_tx[(i << 1) + 1] = (val & 0xffff);
6518 }
6519 6318
6520 /* If the device is capable of WoL, set the default state according 6319 /* If the device is capable of WoL, set the default state according
6521 * to the HW 6320 * to the HW
@@ -6524,14 +6323,14 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
6524 bp->wol = (!(bp->flags & NO_WOL_FLAG) && 6323 bp->wol = (!(bp->flags & NO_WOL_FLAG) &&
6525 (config & PORT_FEATURE_WOL_ENABLED)); 6324 (config & PORT_FEATURE_WOL_ENABLED));
6526 6325
6527 BNX2X_DEV_INFO("lane_config 0x%08x ext_phy_config 0x%08x" 6326 BNX2X_DEV_INFO("lane_config 0x%08x"
6528 " speed_cap_mask 0x%08x link_config 0x%08x\n", 6327 " speed_cap_mask 0x%08x link_config 0x%08x\n",
6529 bp->link_params.lane_config, 6328 bp->link_params.lane_config,
6530 bp->link_params.ext_phy_config,
6531 bp->link_params.speed_cap_mask, bp->port.link_config); 6329 bp->link_params.speed_cap_mask, bp->port.link_config);
6532 6330
6533 bp->link_params.switch_cfg |= (bp->port.link_config & 6331 bp->link_params.switch_cfg |= (bp->port.link_config &
6534 PORT_FEATURE_CONNECTED_SWITCH_MASK); 6332 PORT_FEATURE_CONNECTED_SWITCH_MASK);
6333 bnx2x_phy_probe(&bp->link_params);
6535 bnx2x_link_settings_supported(bp, bp->link_params.switch_cfg); 6334 bnx2x_link_settings_supported(bp, bp->link_params.switch_cfg);
6536 6335
6537 bnx2x_link_settings_requested(bp); 6336 bnx2x_link_settings_requested(bp);
@@ -6540,14 +6339,17 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
6540 * If connected directly, work with the internal PHY, otherwise, work 6339 * If connected directly, work with the internal PHY, otherwise, work
6541 * with the external PHY 6340 * with the external PHY
6542 */ 6341 */
6543 ext_phy_type = XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config); 6342 ext_phy_config =
6343 SHMEM_RD(bp,
6344 dev_info.port_hw_config[port].external_phy_config);
6345 ext_phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
6544 if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) 6346 if (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)
6545 bp->mdio.prtad = bp->link_params.phy_addr; 6347 bp->mdio.prtad = bp->port.phy_addr;
6546 6348
6547 else if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) && 6349 else if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) &&
6548 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN)) 6350 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN))
6549 bp->mdio.prtad = 6351 bp->mdio.prtad =
6550 XGXS_EXT_PHY_ADDR(bp->link_params.ext_phy_config); 6352 XGXS_EXT_PHY_ADDR(ext_phy_config);
6551 6353
6552 val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_upper); 6354 val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_upper);
6553 val = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_lower); 6355 val = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_lower);