aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bnx2x/bnx2x_link.c
diff options
context:
space:
mode:
authorYaniv Rosner <yaniv.rosner@broadcom.com>2010-09-07 07:41:07 -0400
committerDavid S. Miller <davem@davemloft.net>2010-09-07 16:15:40 -0400
commitc18aa15d08a2d1a5c7624a21747b1b03c2c1dcfd (patch)
tree35407386797909073baafe68fdca35b71d5df0e5 /drivers/net/bnx2x/bnx2x_link.c
parentd90d96baf0cc044bcdedc9ee9e925b5937865673 (diff)
bnx2x: Apply logic changes for the new scheme
Make the needed changes for the new scheme especially around PHY initialization, and link detection. - The get_emac_base function was changed to enable setting different MAC access setting for each PHY based of external configuration. - As a part of the dual-media preparation, the save_spirom_version was modified to accept a PHY specific version address to be saved in the shmem. This will enable to save more than single spirom version in different locations. - The test_link function was changed also as a preparation for the dual-media upcoming changes - Duplicate initialization logic was removed from the link_setting_status and link_initialize functions 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/bnx2x_link.c')
-rw-r--r--drivers/net/bnx2x/bnx2x_link.c331
1 files changed, 154 insertions, 177 deletions
diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c
index 72ac8dcf6e20..fcf99bf62fa1 100644
--- a/drivers/net/bnx2x/bnx2x_link.c
+++ b/drivers/net/bnx2x/bnx2x_link.c
@@ -195,24 +195,6 @@ static void bnx2x_set_serdes_access(struct bnx2x *bp, u8 port)
195 REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_ST + port*0x10, 0); 195 REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_ST + port*0x10, 0);
196} 196}
197 197
198static void bnx2x_set_phy_mdio(struct link_params *params, u8 phy_flags)
199{
200 struct bnx2x *bp = params->bp;
201
202 if (phy_flags & PHY_XGXS_FLAG) {
203 REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST +
204 params->port*0x18, 0);
205 REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + params->port*0x18,
206 DEFAULT_PHY_DEV_ADDR);
207 } else {
208 bnx2x_set_serdes_access(bp, params->port);
209
210 REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_DEVAD +
211 params->port*0x10,
212 DEFAULT_PHY_DEV_ADDR);
213 }
214}
215
216static u32 bnx2x_bits_en(struct bnx2x *bp, u32 reg, u32 bits) 198static u32 bnx2x_bits_en(struct bnx2x *bp, u32 reg, u32 bits)
217{ 199{
218 u32 val = REG_RD(bp, reg); 200 u32 val = REG_RD(bp, reg);
@@ -528,31 +510,46 @@ static u8 bnx2x_bmac_enable(struct link_params *params, struct link_vars *vars,
528 return 0; 510 return 0;
529} 511}
530 512
531static void bnx2x_phy_deassert(struct link_params *params, u8 phy_flags) 513static void bnx2x_serdes_deassert(struct bnx2x *bp, u8 port)
532{ 514{
533 struct bnx2x *bp = params->bp;
534 u32 val; 515 u32 val;
535 516
536 if (phy_flags & PHY_XGXS_FLAG) { 517 DP(NETIF_MSG_LINK, "bnx2x_serdes_deassert\n");
537 DP(NETIF_MSG_LINK, "bnx2x_phy_deassert:XGXS\n");
538 val = XGXS_RESET_BITS;
539 518
540 } else { /* SerDes */ 519 val = SERDES_RESET_BITS << (port*16);
541 DP(NETIF_MSG_LINK, "bnx2x_phy_deassert:SerDes\n");
542 val = SERDES_RESET_BITS;
543 }
544
545 val = val << (params->port*16);
546 520
547 /* reset and unreset the SerDes/XGXS */ 521 /* reset and unreset the SerDes/XGXS */
548 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, 522 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val);
549 val);
550 udelay(500); 523 udelay(500);
551 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, 524 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val);
552 val); 525
553 bnx2x_set_phy_mdio(params, phy_flags); 526 bnx2x_set_serdes_access(bp, port);
527
528 REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_DEVAD +
529 port*0x10,
530 DEFAULT_PHY_DEV_ADDR);
554} 531}
555 532
533static void bnx2x_xgxs_deassert(struct link_params *params)
534{
535 struct bnx2x *bp = params->bp;
536 u8 port;
537 u32 val;
538 DP(NETIF_MSG_LINK, "bnx2x_xgxs_deassert\n");
539 port = params->port;
540
541 val = XGXS_RESET_BITS << (port*16);
542
543 /* reset and unreset the SerDes/XGXS */
544 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val);
545 udelay(500);
546 REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val);
547
548 REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST +
549 port*0x18, 0);
550 REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
551 params->phy[INT_PHY].def_md_devad);
552}
556void bnx2x_link_status_update(struct link_params *params, 553void bnx2x_link_status_update(struct link_params *params,
557 struct link_vars *vars) 554 struct link_vars *vars)
558{ 555{
@@ -799,25 +796,32 @@ static u8 bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl,
799 return 0; 796 return 0;
800} 797}
801 798
802static u32 bnx2x_get_emac_base(struct bnx2x *bp, u32 ext_phy_type, u8 port) 799static u32 bnx2x_get_emac_base(struct bnx2x *bp,
800 u32 mdc_mdio_access, u8 port)
803{ 801{
804 u32 emac_base; 802 u32 emac_base = 0;
805 803 switch (mdc_mdio_access) {
806 switch (ext_phy_type) { 804 case SHARED_HW_CFG_MDC_MDIO_ACCESS1_PHY_TYPE:
807 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: 805 break;
808 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726: 806 case SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC0:
809 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727: 807 if (REG_RD(bp, NIG_REG_PORT_SWAP))
810 /* All MDC/MDIO is directed through single EMAC */ 808 emac_base = GRCBASE_EMAC1;
809 else
810 emac_base = GRCBASE_EMAC0;
811 break;
812 case SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1:
811 if (REG_RD(bp, NIG_REG_PORT_SWAP)) 813 if (REG_RD(bp, NIG_REG_PORT_SWAP))
812 emac_base = GRCBASE_EMAC0; 814 emac_base = GRCBASE_EMAC0;
813 else 815 else
814 emac_base = GRCBASE_EMAC1; 816 emac_base = GRCBASE_EMAC1;
815 break; 817 break;
816 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073: 818 case SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH:
819 emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
820 break;
821 case SHARED_HW_CFG_MDC_MDIO_ACCESS1_SWAPPED:
817 emac_base = (port) ? GRCBASE_EMAC0 : GRCBASE_EMAC1; 822 emac_base = (port) ? GRCBASE_EMAC0 : GRCBASE_EMAC1;
818 break; 823 break;
819 default: 824 default:
820 emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
821 break; 825 break;
822 } 826 }
823 return emac_base; 827 return emac_base;
@@ -1147,7 +1151,7 @@ static void bnx2x_set_parallel_detection(struct bnx2x_phy *phy,
1147 control2); 1151 control2);
1148 1152
1149 if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) && 1153 if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
1150 (params->speed_cap_mask & 1154 (phy->speed_cap_mask &
1151 PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) { 1155 PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) {
1152 DP(NETIF_MSG_LINK, "XGXS\n"); 1156 DP(NETIF_MSG_LINK, "XGXS\n");
1153 1157
@@ -1777,7 +1781,7 @@ static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
1777 struct bnx2x *bp = params->bp; 1781 struct bnx2x *bp = params->bp;
1778 u16 new_line_speed , gp_status; 1782 u16 new_line_speed , gp_status;
1779 u8 rc = 0; 1783 u8 rc = 0;
1780 u32 ext_phy_type; 1784
1781 /* Read gp_status */ 1785 /* Read gp_status */
1782 CL45_RD_OVER_CL22(bp, phy, 1786 CL45_RD_OVER_CL22(bp, phy,
1783 MDIO_REG_BANK_GP_STATUS, 1787 MDIO_REG_BANK_GP_STATUS,
@@ -1885,30 +1889,7 @@ static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
1885 } 1889 }
1886 1890
1887 vars->line_speed = new_line_speed; 1891 vars->line_speed = new_line_speed;
1888 vars->link_status |= LINK_STATUS_SERDES_LINK;
1889 ext_phy_type = params->phy[EXT_PHY1].type;
1890 if ((params->req_line_speed == SPEED_AUTO_NEG) &&
1891 ((ext_phy_type ==
1892 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) ||
1893 (ext_phy_type ==
1894 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) ||
1895 (ext_phy_type ==
1896 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706) ||
1897 (ext_phy_type ==
1898 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726))) {
1899 vars->autoneg = AUTO_NEG_ENABLED;
1900
1901 if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) {
1902 vars->autoneg |= AUTO_NEG_COMPLETE;
1903 vars->link_status |=
1904 LINK_STATUS_AUTO_NEGOTIATE_COMPLETE;
1905 }
1906 1892
1907 vars->autoneg |= AUTO_NEG_PARALLEL_DETECTION_USED;
1908 vars->link_status |=
1909 LINK_STATUS_PARALLEL_DETECTION_USED;
1910
1911 }
1912 1893
1913 } else { /* link_down */ 1894 } else { /* link_down */
1914 DP(NETIF_MSG_LINK, "phy link down\n"); 1895 DP(NETIF_MSG_LINK, "phy link down\n");
@@ -1917,14 +1898,12 @@ static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
1917 1898
1918 vars->duplex = DUPLEX_FULL; 1899 vars->duplex = DUPLEX_FULL;
1919 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; 1900 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
1920 vars->autoneg = AUTO_NEG_DISABLED;
1921 vars->mac_type = MAC_TYPE_NONE; 1901 vars->mac_type = MAC_TYPE_NONE;
1922 1902
1923 if ((params->req_line_speed == SPEED_AUTO_NEG) && 1903 if ((phy->req_line_speed == SPEED_AUTO_NEG) &&
1924 (SINGLE_MEDIA_DIRECT(params))) { 1904 SINGLE_MEDIA_DIRECT(params)) {
1925 /* Check signal is detected */ 1905 /* Check signal is detected */
1926 bnx2x_check_fallback_to_cl37(&params->phy[INT_PHY], 1906 bnx2x_check_fallback_to_cl37(phy, params);
1927 params);
1928 } 1907 }
1929 } 1908 }
1930 1909
@@ -2078,6 +2057,7 @@ static u8 bnx2x_init_xgxs(struct bnx2x_phy *phy,
2078 2057
2079 return rc; 2058 return rc;
2080} 2059}
2060
2081/*****************************************************************************/ 2061/*****************************************************************************/
2082/* External Phy section */ 2062/* External Phy section */
2083/*****************************************************************************/ 2063/*****************************************************************************/
@@ -2091,19 +2071,18 @@ void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port)
2091} 2071}
2092 2072
2093static void bnx2x_save_spirom_version(struct bnx2x *bp, u8 port, 2073static void bnx2x_save_spirom_version(struct bnx2x *bp, u8 port,
2094 u32 shmem_base, u32 spirom_ver) 2074 u32 spirom_ver, u32 ver_addr)
2095{ 2075{
2096 DP(NETIF_MSG_LINK, "FW version 0x%x:0x%x for port %d\n", 2076 DP(NETIF_MSG_LINK, "FW version 0x%x:0x%x for port %d\n",
2097 (u16)(spirom_ver>>16), (u16)spirom_ver, port); 2077 (u16)(spirom_ver>>16), (u16)spirom_ver, port);
2098 REG_WR(bp, shmem_base + 2078
2099 offsetof(struct shmem_region, 2079 if (ver_addr)
2100 port_mb[port].ext_phy_fw_version), 2080 REG_WR(bp, ver_addr, spirom_ver);
2101 spirom_ver);
2102} 2081}
2103 2082
2104static void bnx2x_save_bcm_spirom_ver(struct bnx2x *bp, u8 port, 2083static void bnx2x_save_bcm_spirom_ver(struct bnx2x *bp,
2105 struct bnx2x_phy *phy, 2084 struct bnx2x_phy *phy,
2106 u32 shmem_base) 2085 u8 port)
2107{ 2086{
2108 u16 fw_ver1, fw_ver2; 2087 u16 fw_ver1, fw_ver2;
2109 2088
@@ -2111,13 +2090,12 @@ static void bnx2x_save_bcm_spirom_ver(struct bnx2x *bp, u8 port,
2111 MDIO_PMA_REG_ROM_VER1, &fw_ver1); 2090 MDIO_PMA_REG_ROM_VER1, &fw_ver1);
2112 bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 2091 bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
2113 MDIO_PMA_REG_ROM_VER2, &fw_ver2); 2092 MDIO_PMA_REG_ROM_VER2, &fw_ver2);
2114 bnx2x_save_spirom_version(bp, port, shmem_base, 2093 bnx2x_save_spirom_version(bp, port, (u32)(fw_ver1<<16 | fw_ver2),
2115 (u32)(fw_ver1<<16 | fw_ver2)); 2094 phy->ver_addr);
2116} 2095}
2117 2096
2118static void bnx2x_save_8481_spirom_version(struct bnx2x_phy *phy, 2097static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
2119 struct link_params *params, 2098 struct link_params *params)
2120 u32 shmem_base)
2121{ 2099{
2122 u16 val, fw_ver1, fw_ver2, cnt; 2100 u16 val, fw_ver1, fw_ver2, cnt;
2123 struct bnx2x *bp = params->bp; 2101 struct bnx2x *bp = params->bp;
@@ -2137,9 +2115,9 @@ static void bnx2x_save_8481_spirom_version(struct bnx2x_phy *phy,
2137 udelay(5); 2115 udelay(5);
2138 } 2116 }
2139 if (cnt == 100) { 2117 if (cnt == 100) {
2140 DP(NETIF_MSG_LINK, "Unable to read 8481 phy fw version(1)\n"); 2118 DP(NETIF_MSG_LINK, "Unable to read 848xx phy fw version(1)\n");
2141 bnx2x_save_spirom_version(bp, params->port, 2119 bnx2x_save_spirom_version(bp, params->port, 0,
2142 shmem_base, 0); 2120 phy->ver_addr);
2143 return; 2121 return;
2144 } 2122 }
2145 2123
@@ -2169,7 +2147,6 @@ static void bnx2x_save_8481_spirom_version(struct bnx2x_phy *phy,
2169 bnx2x_save_spirom_version(bp, params->port, (fw_ver2<<16) | fw_ver1, 2147 bnx2x_save_spirom_version(bp, params->port, (fw_ver2<<16) | fw_ver1,
2170 phy->ver_addr); 2148 phy->ver_addr);
2171} 2149}
2172
2173static u8 bnx2x_8073_is_snr_needed(struct bnx2x *bp, struct bnx2x_phy *phy) 2150static u8 bnx2x_8073_is_snr_needed(struct bnx2x *bp, struct bnx2x_phy *phy)
2174{ 2151{
2175 /* This is only required for 8073A1, version 102 only */ 2152 /* This is only required for 8073A1, version 102 only */
@@ -2250,7 +2227,7 @@ static u8 bnx2x_8073_xaui_wa(struct bnx2x *bp, struct bnx2x_phy *phy)
2250 2227
2251static void bnx2x_8073_8727_external_rom_boot(struct bnx2x *bp, 2228static void bnx2x_8073_8727_external_rom_boot(struct bnx2x *bp,
2252 struct bnx2x_phy *phy, 2229 struct bnx2x_phy *phy,
2253 u8 port, u32 shmem_base) 2230 u8 port)
2254{ 2231{
2255 /* Boot port from external ROM */ 2232 /* Boot port from external ROM */
2256 /* EDC grst */ 2233 /* EDC grst */
@@ -2288,7 +2265,7 @@ static void bnx2x_8073_8727_external_rom_boot(struct bnx2x *bp,
2288 bnx2x_cl45_write(bp, phy, 2265 bnx2x_cl45_write(bp, phy,
2289 MDIO_PMA_DEVAD, 2266 MDIO_PMA_DEVAD,
2290 MDIO_PMA_REG_MISC_CTRL1, 0x0000); 2267 MDIO_PMA_REG_MISC_CTRL1, 0x0000);
2291 bnx2x_save_bcm_spirom_ver(bp, port, phy, shmem_base); 2268 bnx2x_save_bcm_spirom_ver(bp, phy, port);
2292} 2269}
2293 2270
2294static void bnx2x_8726_external_rom_boot(struct bnx2x_phy *phy, 2271static void bnx2x_8726_external_rom_boot(struct bnx2x_phy *phy,
@@ -2326,9 +2303,7 @@ static void bnx2x_8726_external_rom_boot(struct bnx2x_phy *phy,
2326 MDIO_PMA_REG_MISC_CTRL1, 0x0000); 2303 MDIO_PMA_REG_MISC_CTRL1, 0x0000);
2327 2304
2328 msleep(200); 2305 msleep(200);
2329 bnx2x_save_bcm_spirom_ver(bp, params->port, 2306 bnx2x_save_bcm_spirom_ver(bp, phy, params->port);
2330 phy,
2331 params->shmem_base);
2332} 2307}
2333 2308
2334static void bnx2x_sfp_set_transmitter(struct bnx2x *bp, 2309static void bnx2x_sfp_set_transmitter(struct bnx2x *bp,
@@ -3055,7 +3030,7 @@ static void bnx2x_set_preemphasis(struct bnx2x_phy *phy,
3055 } 3030 }
3056} 3031}
3057 3032
3058static void bnx2x_8481_set_led(struct bnx2x *bp, 3033static void bnx2x_848xx_set_led(struct bnx2x *bp,
3059 struct bnx2x_phy *phy) 3034 struct bnx2x_phy *phy)
3060{ 3035{
3061 u16 val; 3036 u16 val;
@@ -3195,7 +3170,6 @@ static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy,
3195 /* HW reset */ 3170 /* HW reset */
3196 bnx2x_ext_phy_hw_reset(bp, params->port); 3171 bnx2x_ext_phy_hw_reset(bp, params->port);
3197 bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0xa040); 3172 bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0xa040);
3198
3199 bnx2x_wait_reset_complete(bp, phy); 3173 bnx2x_wait_reset_complete(bp, phy);
3200 3174
3201 /* Wait until fw is loaded */ 3175 /* Wait until fw is loaded */
@@ -3262,7 +3236,7 @@ static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy,
3262 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 3236 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL,
3263 0x0004); 3237 0x0004);
3264 } 3238 }
3265 bnx2x_save_bcm_spirom_ver(bp, params->port, phy, params->shmem_base); 3239 bnx2x_save_bcm_spirom_ver(bp, phy, params->port);
3266 return 0; 3240 return 0;
3267} 3241}
3268 3242
@@ -3512,6 +3486,7 @@ static u8 bnx2x_8073_config_init(struct bnx2x_phy *phy,
3512 return 0; 3486 return 0;
3513} 3487}
3514 3488
3489
3515static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy, 3490static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy,
3516 struct link_params *params, 3491 struct link_params *params,
3517 struct link_vars *vars) 3492 struct link_vars *vars)
@@ -3690,7 +3665,7 @@ static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
3690 3665
3691 bnx2x_cl45_write(bp, phy, 3666 bnx2x_cl45_write(bp, phy,
3692 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x0000); 3667 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x0000);
3693 bnx2x_8481_set_led(bp, phy); 3668 bnx2x_848xx_set_led(bp, phy);
3694 /* set 1000 speed advertisement */ 3669 /* set 1000 speed advertisement */
3695 bnx2x_cl45_read(bp, phy, 3670 bnx2x_cl45_read(bp, phy,
3696 MDIO_AN_DEVAD, MDIO_AN_REG_8481_1000T_CTRL, 3671 MDIO_AN_DEVAD, MDIO_AN_REG_8481_1000T_CTRL,
@@ -3795,7 +3770,7 @@ static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
3795 1); 3770 1);
3796 } 3771 }
3797 /* Save spirom version */ 3772 /* Save spirom version */
3798 bnx2x_save_8481_spirom_version(phy, params, params->shmem_base); 3773 bnx2x_save_848xx_spirom_version(phy, params);
3799 3774
3800 return 0; 3775 return 0;
3801} 3776}
@@ -3935,6 +3910,7 @@ static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
3935 module plugged in/out */ 3910 module plugged in/out */
3936} 3911}
3937 3912
3913
3938static u8 bnx2x_8705_read_status(struct bnx2x_phy *phy, 3914static u8 bnx2x_8705_read_status(struct bnx2x_phy *phy,
3939 struct link_params *params, 3915 struct link_params *params,
3940 struct link_vars *vars) 3916 struct link_vars *vars)
@@ -4011,7 +3987,6 @@ static u8 bnx2x_8706_8726_read_status(struct bnx2x_phy *phy,
4011 } 3987 }
4012 return link_up; 3988 return link_up;
4013} 3989}
4014
4015static u8 bnx2x_8706_read_status(struct bnx2x_phy *phy, 3990static u8 bnx2x_8706_read_status(struct bnx2x_phy *phy,
4016 struct link_params *params, 3991 struct link_params *params,
4017 struct link_vars *vars) 3992 struct link_vars *vars)
@@ -4038,6 +4013,7 @@ static u8 bnx2x_8726_read_status(struct bnx2x_phy *phy,
4038 } 4013 }
4039 return link_up; 4014 return link_up;
4040} 4015}
4016
4041static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy, 4017static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
4042 struct link_params *params, 4018 struct link_params *params,
4043 struct link_vars *vars) 4019 struct link_vars *vars)
@@ -4183,7 +4159,6 @@ static void bnx2x_8073_resolve_fc(struct bnx2x_phy *phy,
4183 pause_result); 4159 pause_result);
4184 } 4160 }
4185} 4161}
4186
4187static u8 bnx2x_8073_read_status(struct bnx2x_phy *phy, 4162static u8 bnx2x_8073_read_status(struct bnx2x_phy *phy,
4188 struct link_params *params, 4163 struct link_params *params,
4189 struct link_vars *vars) 4164 struct link_vars *vars)
@@ -4415,6 +4390,7 @@ static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
4415 4390
4416 return link_up; 4391 return link_up;
4417} 4392}
4393
4418static void bnx2x_link_int_enable(struct link_params *params) 4394static void bnx2x_link_int_enable(struct link_params *params)
4419{ 4395{
4420 u8 port = params->port; 4396 u8 port = params->port;
@@ -4616,7 +4592,6 @@ static u8 bnx2x_null_format_ver(u32 spirom_ver, u8 *str, u16 *len)
4616 (*len)--; 4592 (*len)--;
4617 return 0; 4593 return 0;
4618} 4594}
4619
4620u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded, 4595u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
4621 u8 *version, u16 len) 4596 u8 *version, u16 len)
4622{ 4597{
@@ -4706,6 +4681,7 @@ static void bnx2x_7101_config_loopback(struct bnx2x_phy *phy,
4706 bnx2x_cl45_write(bp, phy, 4681 bnx2x_cl45_write(bp, phy,
4707 MDIO_XS_DEVAD, MDIO_XS_SFX7101_XGXS_TEST1, 0x100); 4682 MDIO_XS_DEVAD, MDIO_XS_SFX7101_XGXS_TEST1, 0x100);
4708} 4683}
4684
4709/* 4685/*
4710 *------------------------------------------------------------------------ 4686 *------------------------------------------------------------------------
4711 * bnx2x_override_led_value - 4687 * bnx2x_override_led_value -
@@ -4892,7 +4868,7 @@ u8 bnx2x_set_led(struct link_params *params, u8 mode, u32 speed)
4892u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars) 4868u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars)
4893{ 4869{
4894 struct bnx2x *bp = params->bp; 4870 struct bnx2x *bp = params->bp;
4895 u16 gp_status = 0; 4871 u16 gp_status = 0, phy_index = 0;
4896 4872
4897 CL45_RD_OVER_CL22(bp, &params->phy[INT_PHY], 4873 CL45_RD_OVER_CL22(bp, &params->phy[INT_PHY],
4898 MDIO_REG_BANK_GP_STATUS, 4874 MDIO_REG_BANK_GP_STATUS,
@@ -4902,86 +4878,59 @@ u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars)
4902 if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) { 4878 if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {
4903 u8 ext_phy_link_up = 1; 4879 u8 ext_phy_link_up = 1;
4904 struct link_vars temp_vars; 4880 struct link_vars temp_vars;
4905 if (params->phy[EXT_PHY1].read_status) 4881 for (phy_index = EXT_PHY1; phy_index < params->num_phys;
4906 ext_phy_link_up &= 4882 phy_index++) {
4907 params->phy[EXT_PHY1].read_status( 4883 if (params->phy[phy_index].read_status)
4908 &params->phy[EXT_PHY1], 4884 ext_phy_link_up &=
4885 params->phy[phy_index].read_status(
4886 &params->phy[phy_index],
4909 params, &temp_vars); 4887 params, &temp_vars);
4888 }
4910 if (ext_phy_link_up) 4889 if (ext_phy_link_up)
4911 return 0; 4890 return 0;
4912 } 4891 }
4913
4914 return -ESRCH; 4892 return -ESRCH;
4915} 4893}
4916 4894
4917static u8 bnx2x_link_initialize(struct link_params *params, 4895static u8 bnx2x_link_initialize(struct link_params *params,
4918 struct link_vars *vars) 4896 struct link_vars *vars)
4919{ 4897{
4920 struct bnx2x *bp = params->bp;
4921 u8 rc = 0; 4898 u8 rc = 0;
4922 u8 phy_index, non_ext_phy; 4899 u8 phy_index, non_ext_phy;
4923 struct bnx2x_phy *ext_phy = &params->phy[EXT_PHY1]; 4900 struct bnx2x *bp = params->bp;
4924 struct bnx2x_phy *int_phy = &params->phy[INT_PHY]; 4901 /**
4925 /* Activate the external PHY */ 4902 * In case of external phy existence, the line speed would be the
4926 4903 * line speed linked up by the external phy. In case it is direct
4927 bnx2x_set_aer_mmd(params, int_phy); 4904 * only, then the line_speed during initialization will be
4928 4905 * equal to the req_line_speed
4929 if (vars->phy_flags & PHY_XGXS_FLAG) 4906 */
4930 bnx2x_set_master_ln(params, int_phy); 4907 vars->line_speed = params->phy[INT_PHY].req_line_speed;
4931
4932 rc = bnx2x_reset_unicore(params, int_phy,
4933 int_phy->type ==
4934 PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT);
4935 /* reset the SerDes and wait for reset bit return low */
4936 if (rc != 0)
4937 return rc;
4938
4939 bnx2x_set_aer_mmd(params, int_phy);
4940
4941 /* setting the masterLn_def again after the reset */
4942 if (vars->phy_flags & PHY_XGXS_FLAG) {
4943 bnx2x_set_master_ln(params, int_phy);
4944 bnx2x_set_swap_lanes(params, int_phy);
4945 }
4946 4908
4947 if (vars->phy_flags & PHY_XGXS_FLAG) { 4909 /**
4948 if ((params->req_line_speed && 4910 * Initialize the internal phy in case this is a direct board
4949 ((params->req_line_speed == SPEED_100) || 4911 * (no external phys), or this board has external phy which requires
4950 (params->req_line_speed == SPEED_10))) || 4912 * to first.
4951 (!params->req_line_speed && 4913 */
4952 (params->speed_cap_mask >=
4953 PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) &&
4954 (params->speed_cap_mask <
4955 PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
4956 )) {
4957 vars->phy_flags |= PHY_SGMII_FLAG;
4958 } else {
4959 vars->phy_flags &= ~PHY_SGMII_FLAG;
4960 }
4961 }
4962 /* In case of external phy existance, the line speed would be the
4963 line speed linked up by the external phy. In case it is direct only,
4964 then the line_speed during initialization will be equal to the
4965 req_line_speed*/
4966 vars->line_speed = params->req_line_speed;
4967 4914
4968 bnx2x_calc_ieee_aneg_adv(int_phy, params, &vars->ieee_fc); 4915 if (params->phy[INT_PHY].config_init)
4916 params->phy[INT_PHY].config_init(
4917 &params->phy[INT_PHY],
4918 params, vars);
4969 4919
4970 /* init ext phy and enable link state int */ 4920 /* init ext phy and enable link state int */
4971 non_ext_phy = ((ext_phy->type == 4921 non_ext_phy = (SINGLE_MEDIA_DIRECT(params) ||
4972 PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) ||
4973 (params->loopback_mode == LOOPBACK_XGXS_10)); 4922 (params->loopback_mode == LOOPBACK_XGXS_10));
4974 4923
4975 if (non_ext_phy || 4924 if (non_ext_phy ||
4976 (ext_phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) || 4925 (params->phy[EXT_PHY1].flags & FLAGS_INIT_XGXS_FIRST) ||
4977 (ext_phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706) ||
4978 (ext_phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) ||
4979 (params->loopback_mode == LOOPBACK_EXT_PHY)) { 4926 (params->loopback_mode == LOOPBACK_EXT_PHY)) {
4927 struct bnx2x_phy *phy = &params->phy[INT_PHY];
4980 if (vars->line_speed == SPEED_AUTO_NEG) 4928 if (vars->line_speed == SPEED_AUTO_NEG)
4981 bnx2x_set_parallel_detection(int_phy, params); 4929 bnx2x_set_parallel_detection(phy, params);
4982 bnx2x_init_internal_phy(int_phy, params, vars); 4930 bnx2x_init_internal_phy(phy, params, vars);
4983 } 4931 }
4984 4932
4933 /* Init external phy*/
4985 if (!non_ext_phy) 4934 if (!non_ext_phy)
4986 for (phy_index = EXT_PHY1; phy_index < params->num_phys; 4935 for (phy_index = EXT_PHY1; phy_index < params->num_phys;
4987 phy_index++) { 4936 phy_index++) {
@@ -4997,7 +4946,6 @@ static u8 bnx2x_link_initialize(struct link_params *params,
4997 NIG_STATUS_XGXS0_LINK_STATUS | 4946 NIG_STATUS_XGXS0_LINK_STATUS |
4998 NIG_STATUS_SERDES0_LINK_STATUS | 4947 NIG_STATUS_SERDES0_LINK_STATUS |
4999 NIG_MASK_MI_INT)); 4948 NIG_MASK_MI_INT));
5000
5001 return rc; 4949 return rc;
5002} 4950}
5003 4951
@@ -5122,7 +5070,7 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
5122 5070
5123 vars->phy_flags = PHY_XGXS_FLAG; 5071 vars->phy_flags = PHY_XGXS_FLAG;
5124 5072
5125 bnx2x_phy_deassert(params, vars->phy_flags); 5073 bnx2x_xgxs_deassert(params);
5126 5074
5127 /* set bmac loopback */ 5075 /* set bmac loopback */
5128 bnx2x_bmac_enable(params, vars, 1); 5076 bnx2x_bmac_enable(params, vars, 1);
@@ -5140,7 +5088,7 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
5140 5088
5141 vars->phy_flags = PHY_XGXS_FLAG; 5089 vars->phy_flags = PHY_XGXS_FLAG;
5142 5090
5143 bnx2x_phy_deassert(params, vars->phy_flags); 5091 bnx2x_xgxs_deassert(params);
5144 /* set bmac loopback */ 5092 /* set bmac loopback */
5145 bnx2x_emac_enable(params, vars, 1); 5093 bnx2x_emac_enable(params, vars, 1);
5146 bnx2x_emac_program(params, vars); 5094 bnx2x_emac_program(params, vars);
@@ -5161,7 +5109,7 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
5161 NIG_REG_XGXS0_CTRL_PHY_ADDR+ 5109 NIG_REG_XGXS0_CTRL_PHY_ADDR+
5162 params->port*0x18); 5110 params->port*0x18);
5163 5111
5164 bnx2x_phy_deassert(params, vars->phy_flags); 5112 bnx2x_xgxs_deassert(params);
5165 bnx2x_link_initialize(params, vars); 5113 bnx2x_link_initialize(params, vars);
5166 5114
5167 vars->mac_type = MAC_TYPE_BMAC; 5115 vars->mac_type = MAC_TYPE_BMAC;
@@ -5194,8 +5142,9 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
5194 /* No loopback */ 5142 /* No loopback */
5195 { 5143 {
5196 if (params->switch_cfg == SWITCH_CFG_10G) 5144 if (params->switch_cfg == SWITCH_CFG_10G)
5197 vars->phy_flags = PHY_XGXS_FLAG; 5145 bnx2x_xgxs_deassert(params);
5198 bnx2x_phy_deassert(params, vars->phy_flags); 5146 else
5147 bnx2x_serdes_deassert(bp, params->port);
5199 bnx2x_link_initialize(params, vars); 5148 bnx2x_link_initialize(params, vars);
5200 msleep(30); 5149 msleep(30);
5201 bnx2x_link_int_enable(params); 5150 bnx2x_link_int_enable(params);
@@ -5282,9 +5231,7 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
5282 u8 reset_ext_phy) 5231 u8 reset_ext_phy)
5283{ 5232{
5284 struct bnx2x *bp = params->bp; 5233 struct bnx2x *bp = params->bp;
5285
5286 u8 phy_index, port = params->port; 5234 u8 phy_index, port = params->port;
5287
5288 DP(NETIF_MSG_LINK, "Resetting the link of port %d\n", port); 5235 DP(NETIF_MSG_LINK, "Resetting the link of port %d\n", port);
5289 /* disable attentions */ 5236 /* disable attentions */
5290 vars->link_status = 0; 5237 vars->link_status = 0;
@@ -5340,7 +5287,6 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
5340 return 0; 5287 return 0;
5341} 5288}
5342 5289
5343
5344static u8 bnx2x_update_link_down(struct link_params *params, 5290static u8 bnx2x_update_link_down(struct link_params *params,
5345 struct link_vars *vars) 5291 struct link_vars *vars)
5346{ 5292{
@@ -6078,7 +6024,7 @@ static u8 bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
6078 } 6024 }
6079 phy->addr = (u8)phy_addr; 6025 phy->addr = (u8)phy_addr;
6080 phy->mdio_ctrl = bnx2x_get_emac_base(bp, 6026 phy->mdio_ctrl = bnx2x_get_emac_base(bp,
6081 phy->type, 6027 SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH,
6082 port); 6028 port);
6083 phy->def_md_devad = DEFAULT_PHY_DEV_ADDR; 6029 phy->def_md_devad = DEFAULT_PHY_DEV_ADDR;
6084 6030
@@ -6095,14 +6041,15 @@ static u8 bnx2x_populate_ext_phy(struct bnx2x *bp,
6095 u8 port, 6041 u8 port,
6096 struct bnx2x_phy *phy) 6042 struct bnx2x_phy *phy)
6097{ 6043{
6098 u32 ext_phy_config, phy_type; 6044 u32 ext_phy_config, phy_type, config2;
6099 6045 u32 mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH;
6100 ext_phy_config = bnx2x_get_ext_phy_config(bp, shmem_base, 6046 ext_phy_config = bnx2x_get_ext_phy_config(bp, shmem_base,
6101 phy_index, port); 6047 phy_index, port);
6102 phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config); 6048 phy_type = XGXS_EXT_PHY_TYPE(ext_phy_config);
6103 /* Select the phy type */ 6049 /* Select the phy type */
6104 switch (phy_type) { 6050 switch (phy_type) {
6105 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073: 6051 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
6052 mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_SWAPPED;
6106 *phy = phy_8073; 6053 *phy = phy_8073;
6107 break; 6054 break;
6108 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705: 6055 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
@@ -6112,14 +6059,17 @@ static u8 bnx2x_populate_ext_phy(struct bnx2x *bp,
6112 *phy = phy_8706; 6059 *phy = phy_8706;
6113 break; 6060 break;
6114 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726: 6061 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
6062 mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1;
6115 *phy = phy_8726; 6063 *phy = phy_8726;
6116 break; 6064 break;
6117 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC: 6065 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC:
6118 /* BCM8727_NOC => BCM8727 no over current */ 6066 /* BCM8727_NOC => BCM8727 no over current */
6067 mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1;
6119 *phy = phy_8727; 6068 *phy = phy_8727;
6120 phy->flags |= FLAGS_NOC; 6069 phy->flags |= FLAGS_NOC;
6121 break; 6070 break;
6122 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727: 6071 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
6072 mdc_mdio_access = SHARED_HW_CFG_MDC_MDIO_ACCESS1_EMAC1;
6123 *phy = phy_8727; 6073 *phy = phy_8727;
6124 break; 6074 break;
6125 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481: 6075 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481:
@@ -6141,8 +6091,36 @@ static u8 bnx2x_populate_ext_phy(struct bnx2x *bp,
6141 6091
6142 phy->addr = XGXS_EXT_PHY_ADDR(ext_phy_config); 6092 phy->addr = XGXS_EXT_PHY_ADDR(ext_phy_config);
6143 bnx2x_populate_preemphasis(bp, shmem_base, phy, port, phy_index); 6093 bnx2x_populate_preemphasis(bp, shmem_base, phy, port, phy_index);
6144 phy->mdio_ctrl = bnx2x_get_emac_base(bp, phy->type, port);
6145 6094
6095 /**
6096 * The shmem address of the phy version is located on different
6097 * structures. In case this structure is too old, do not set
6098 * the address
6099 */
6100 config2 = REG_RD(bp, shmem_base + offsetof(struct shmem_region,
6101 dev_info.shared_hw_config.config2));
6102
6103 phy->ver_addr = shmem_base + offsetof(struct shmem_region,
6104 port_mb[port].ext_phy_fw_version);
6105
6106 /* Check specific mdc mdio settings */
6107 if (config2 & SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK)
6108 mdc_mdio_access = config2 &
6109 SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK;
6110
6111 phy->mdio_ctrl = bnx2x_get_emac_base(bp, mdc_mdio_access, port);
6112
6113 /**
6114 * In case mdc/mdio_access of the external phy is different than the
6115 * mdc/mdio access of the XGXS, a HW lock must be taken in each access
6116 * to prevent one port interfere with another port's CL45 operations.
6117 */
6118 if (mdc_mdio_access != SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH)
6119 phy->flags |= FLAGS_HW_LOCK_REQUIRED;
6120 DP(NETIF_MSG_LINK, "phy_type 0x%x port %d found in index %d\n",
6121 phy_type, port, phy_index);
6122 DP(NETIF_MSG_LINK, " addr=0x%x, mdio_ctl=0x%x\n",
6123 phy->addr, phy->mdio_ctrl);
6146 return 0; 6124 return 0;
6147} 6125}
6148 6126
@@ -6262,7 +6240,6 @@ u32 bnx2x_supported_attr(struct link_params *params, u8 phy_idx)
6262 return 0; 6240 return 0;
6263} 6241}
6264 6242
6265
6266static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base) 6243static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base)
6267{ 6244{
6268 struct bnx2x_phy phy[PORT_MAX]; 6245 struct bnx2x_phy phy[PORT_MAX];
@@ -6314,7 +6291,7 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base)
6314 u16 fw_ver1; 6291 u16 fw_ver1;
6315 6292
6316 bnx2x_8073_8727_external_rom_boot(bp, phy_blk[port], 6293 bnx2x_8073_8727_external_rom_boot(bp, phy_blk[port],
6317 port, shmem_base); 6294 port);
6318 6295
6319 bnx2x_cl45_read(bp, phy_blk[port], 6296 bnx2x_cl45_read(bp, phy_blk[port],
6320 MDIO_PMA_DEVAD, 6297 MDIO_PMA_DEVAD,
@@ -6427,7 +6404,7 @@ static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp, u32 shmem_base)
6427 u16 fw_ver1; 6404 u16 fw_ver1;
6428 6405
6429 bnx2x_8073_8727_external_rom_boot(bp, phy_blk[port], 6406 bnx2x_8073_8727_external_rom_boot(bp, phy_blk[port],
6430 port, shmem_base); 6407 port);
6431 bnx2x_cl45_read(bp, phy_blk[port], 6408 bnx2x_cl45_read(bp, phy_blk[port],
6432 MDIO_PMA_DEVAD, 6409 MDIO_PMA_DEVAD,
6433 MDIO_PMA_REG_ROM_VER1, &fw_ver1); 6410 MDIO_PMA_REG_ROM_VER1, &fw_ver1);