diff options
Diffstat (limited to 'drivers/net/bnx2x')
-rw-r--r-- | drivers/net/bnx2x/bnx2x_ethtool.c | 35 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_link.c | 1864 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_link.h | 109 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_main.c | 270 |
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 | } |
1779 | static u8 bnx2x_link_settings_status(struct link_params *params, | 1779 | static 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 | ||
2003 | static u8 bnx2x_emac_program(struct link_params *params, | 1990 | static 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 | ||
2037 | static 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 | ||
2054 | static 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 | ||
2062 | static 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 | |||
2183 | static void bnx2x_save_spirom_version(struct bnx2x *bp, u8 port, | 2102 | static 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 | ||
2499 | static void bnx2x_sfp_set_transmitter(struct bnx2x *bp, | 2418 | static 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 | ||
3334 | static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars) | 3256 | static 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 = ¶ms->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: | 3274 | static 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 | |||
3312 | static 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 | |||
3416 | static 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 | |||
3506 | static 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: | 3702 | static 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 | |||
3851 | static 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: | 3900 | static 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: | 4046 | static 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 | ||
4070 | static 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 | } | ||
4073 | static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy, | 4085 | static 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 | 4163 | static u8 bnx2x_8705_read_status(struct bnx2x_phy *phy, | |
4152 | static 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: | 4200 | static 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: | 4255 | static 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 | |||
4262 | static 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 | } | ||
4281 | static 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: | 4408 | static 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 | |
4595 | static 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 | |
4638 | static 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 | |||
4684 | static void bnx2x_link_int_enable(struct link_params *params) | 4710 | static 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 | ||
4828 | static u8 bnx2x_format_ver(u32 num, u8 *str, u16 len) | 4854 | static 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 | |||
4867 | static 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 | ||
4897 | static 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 | |||
4906 | static u8 bnx2x_null_format_ver(u32 spirom_ver, u8 *str, u16 *len) | ||
4907 | { | ||
4908 | str[0] = '\0'; | ||
4909 | (*len)--; | ||
4910 | return 0; | ||
4911 | } | ||
4912 | |||
4858 | u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded, | 4913 | u8 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 | ||
4972 | static void bnx2x_ext_phy_loopback(struct bnx2x_phy *phy, | 4987 | static 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) { | 4995 | static 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(¶ms->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 | ¶ms->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 = ¶ms->phy[EXT_PHY1]; | 5218 | struct bnx2x_phy *ext_phy = ¶ms->phy[EXT_PHY1]; |
5222 | struct bnx2x_phy *int_phy = ¶ms->phy[INT_PHY]; | 5219 | struct bnx2x_phy *int_phy = ¶ms->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 | ¶ms->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 | ||
5296 | static 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 | |||
5295 | u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars) | 5325 | u8 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(¶ms->phy[INT_PHY], | 5465 | params->phy[INT_PHY].config_loopback( |
5453 | params, 1); | 5466 | ¶ms->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(¶ms->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 | ¶ms->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 | ||
5506 | static void bnx2x_8726_reset_phy(struct bnx2x *bp, | 5499 | static 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 | |||
5510 | static 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 | } | ||
5517 | static 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 | } | ||
5529 | static 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 | |||
5538 | static 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 | |||
5548 | static 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 | |||
5564 | static 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 | ||
5516 | u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars, | 5573 | u8 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 = ¶ms->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 | ¶ms->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 | ¶ms->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 | ||
5655 | static u8 bnx2x_update_link_up(struct link_params *params, | 5669 | static 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 | */ |
5705 | u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars) | 5718 | u8 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 = ¶ms->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(¶ms->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 = ¶ms->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 | ¶ms->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(¶ms->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 | ||
5900 | static 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 | |||
5909 | static 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 | |||
5925 | static 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 | |||
5938 | static 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 | |||
5964 | static 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 | |||
5999 | static 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 | |||
6035 | static 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 | }; | ||
6064 | static 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 | }; | ||
6095 | static 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 | }; | ||
6123 | static 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 | |||
6153 | static 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 | |||
6185 | static 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 | }; | ||
6215 | static 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 | |||
6250 | static 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 | |||
6291 | static 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 | |||
5785 | static u32 bnx2x_get_ext_phy_config(struct bnx2x *bp, u32 shmem_base, | 6320 | static 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 | } |
6337 | static 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 | ||
5803 | static u8 bnx2x_populate_ext_phy(struct bnx2x *bp, | 6377 | static 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 | ||
6445 | static 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 | |||
6504 | u8 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 = ¶ms->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 | |||
6542 | u32 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 | |||
5828 | static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base) | 6550 | static 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; | |||
66 | struct link_params; | 79 | struct link_params; |
67 | struct bnx2x_phy; | 80 | struct bnx2x_phy; |
68 | 81 | ||
82 | typedef u8 (*config_init_t)(struct bnx2x_phy *phy, struct link_params *params, | ||
83 | struct link_vars *vars); | ||
84 | typedef u8 (*read_status_t)(struct bnx2x_phy *phy, struct link_params *params, | ||
85 | struct link_vars *vars); | ||
86 | typedef void (*link_reset_t)(struct bnx2x_phy *phy, | ||
87 | struct link_params *params); | ||
88 | typedef void (*config_loopback_t)(struct bnx2x_phy *phy, | ||
89 | struct link_params *params); | ||
90 | typedef u8 (*format_fw_ver_t)(u32 raw, u8 *str, u16 *len); | ||
91 | typedef void (*hw_reset_t)(struct bnx2x_phy *phy, struct link_params *params); | ||
92 | typedef void (*set_link_led_t)(struct bnx2x_phy *phy, | ||
93 | struct link_params *params, u8 mode); | ||
94 | |||
69 | struct bnx2x_phy { | 95 | struct 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) | |||
1960 | static inline void bnx2x_fan_failure(struct bnx2x *bp) | 1960 | static 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); |