]> Pileus Git - ~andy/linux/commitdiff
bnx2x: Change MDIO clock settings
authorYaniv Rosner <yanivr@broadcom.com>
Tue, 27 Nov 2012 03:46:30 +0000 (03:46 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 28 Nov 2012 15:59:21 +0000 (10:59 -0500)
When drivers works on top of an old bootcode, it is theoretically subjected to
MDC/MDIO failures since the MDIO clock is set in the beginning of each sequence,
rather than per CL45 command. On rare cases an old bootcodes may change that in
the middle, so to address that, the MDIO clock is set for each CL45 access.
In addition, setting the MDIO clock is now done per EMAC base, and
not per port number, since a specific port can potentially use both EMACs for
different PHY accesses.

Signed-off-by: Yaniv Rosner <yanivr@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c

index 525a9bc30cb3f26004d4784872f566c1e7f94849..a1a3ff43f66dc952d40529cde077ea478429c49a 100644 (file)
@@ -1246,6 +1246,7 @@ struct drv_func_mb {
        #define DRV_MSG_CODE_VRFY_AFEX_SUPPORTED        0xa2000000
        #define REQ_BC_VER_4_VRFY_AFEX_SUPPORTED        0x00070002
        #define REQ_BC_VER_4_SFP_TX_DISABLE_SUPPORTED   0x00070014
+       #define REQ_BC_VER_4_MT_SUPPORTED               0x00070201
        #define REQ_BC_VER_4_PFC_STATS_SUPPORTED        0x00070201
        #define REQ_BC_VER_4_FCOE_FEATURES              0x00070209
 
index eb44b230676e3684f746a70d613f5f234c667d56..e054921d45d8a3b44fa890813e606015ae51922a 100644 (file)
@@ -1441,30 +1441,47 @@ void bnx2x_pfc_statistic(struct link_params *params, struct link_vars *vars,
 /******************************************************************/
 /*                     MAC/PBF section                           */
 /******************************************************************/
-static void bnx2x_set_mdio_clk(struct bnx2x *bp, u32 chip_id, u8 port)
+static void bnx2x_set_mdio_clk(struct bnx2x *bp, u32 chip_id,
+                              u32 emac_base)
 {
-       u32 mode, emac_base;
+       u32 new_mode, cur_mode;
+       u32 clc_cnt;
        /* Set clause 45 mode, slow down the MDIO clock to 2.5MHz
         * (a value of 49==0x31) and make sure that the AUTO poll is off
         */
+       cur_mode = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE);
 
-       if (CHIP_IS_E2(bp))
-               emac_base = GRCBASE_EMAC0;
-       else
-               emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
-       mode = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE);
-       mode &= ~(EMAC_MDIO_MODE_AUTO_POLL |
-                 EMAC_MDIO_MODE_CLOCK_CNT);
        if (USES_WARPCORE(bp))
-               mode |= (74L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT);
+               clc_cnt = 74L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT;
        else
-               mode |= (49L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT);
+               clc_cnt = 49L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT;
 
-       mode |= (EMAC_MDIO_MODE_CLAUSE_45);
-       REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE, mode);
+       if (((cur_mode & EMAC_MDIO_MODE_CLOCK_CNT) == clc_cnt) &&
+           (cur_mode & (EMAC_MDIO_MODE_CLAUSE_45)))
+               return;
+
+       new_mode = cur_mode &
+               ~(EMAC_MDIO_MODE_AUTO_POLL | EMAC_MDIO_MODE_CLOCK_CNT);
+       new_mode |= clc_cnt;
+       new_mode |= (EMAC_MDIO_MODE_CLAUSE_45);
 
+       DP(NETIF_MSG_LINK, "Changing emac_mode from 0x%x to 0x%x\n",
+          cur_mode, new_mode);
+       REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE, new_mode);
        udelay(40);
 }
+
+static void bnx2x_set_mdio_emac_per_phy(struct bnx2x *bp,
+                                       struct link_params *params)
+{
+       u8 phy_index;
+       /* Set mdio clock per phy */
+       for (phy_index = INT_PHY; phy_index < params->num_phys;
+             phy_index++)
+               bnx2x_set_mdio_clk(bp, params->chip_id,
+                                  params->phy[phy_index].mdio_ctrl);
+}
+
 static u8 bnx2x_is_4_port_mode(struct bnx2x *bp)
 {
        u32 port4mode_ovwr_val;
@@ -1509,7 +1526,8 @@ static void bnx2x_emac_init(struct link_params *params,
                }
                timeout--;
        } while (val & EMAC_MODE_RESET);
-       bnx2x_set_mdio_clk(bp, params->chip_id, port);
+
+       bnx2x_set_mdio_emac_per_phy(bp, params);
        /* Set mac address */
        val = ((params->mac_addr[0] << 8) |
                params->mac_addr[1]);
@@ -2683,6 +2701,13 @@ static int bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
        u32 val;
        u16 i;
        int rc = 0;
+       u32 chip_id;
+       if (phy->flags & FLAGS_MDC_MDIO_WA_G) {
+               chip_id = (REG_RD(bp, MISC_REG_CHIP_NUM) << 16) |
+                         ((REG_RD(bp, MISC_REG_CHIP_REV) & 0xf) << 12);
+               bnx2x_set_mdio_clk(bp, chip_id, phy->mdio_ctrl);
+       }
+
        if (phy->flags & FLAGS_MDC_MDIO_WA_B0)
                bnx2x_bits_en(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS,
                              EMAC_MDIO_STATUS_10MB);
@@ -2751,6 +2776,13 @@ static int bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
        u32 tmp;
        u8 i;
        int rc = 0;
+       u32 chip_id;
+       if (phy->flags & FLAGS_MDC_MDIO_WA_G) {
+               chip_id = (REG_RD(bp, MISC_REG_CHIP_NUM) << 16) |
+                         ((REG_RD(bp, MISC_REG_CHIP_REV) & 0xf) << 12);
+               bnx2x_set_mdio_clk(bp, chip_id, phy->mdio_ctrl);
+       }
+
        if (phy->flags & FLAGS_MDC_MDIO_WA_B0)
                bnx2x_bits_en(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS,
                              EMAC_MDIO_STATUS_10MB);
@@ -4508,7 +4540,7 @@ static void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy,
        struct bnx2x *bp = params->bp;
        u16 val16, lane;
        bnx2x_sfp_e3_set_transmitter(params, phy, 0);
-       bnx2x_set_mdio_clk(bp, params->chip_id, params->port);
+       bnx2x_set_mdio_emac_per_phy(bp, params);
        bnx2x_set_aer_mmd(params, phy);
        /* Global register */
        bnx2x_warpcore_reset_lane(bp, phy, 1);
@@ -8600,7 +8632,7 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
 
        /* Call the handling function in case module is detected */
        if (gpio_val == 0) {
-               bnx2x_set_mdio_clk(bp, params->chip_id, params->port);
+               bnx2x_set_mdio_emac_per_phy(bp, params);
                bnx2x_set_aer_mmd(params, phy);
 
                bnx2x_power_sfp_module(params, phy, 1);
@@ -12100,6 +12132,10 @@ int bnx2x_phy_probe(struct link_params *params)
                    FEATURE_CONFIG_DISABLE_REMOTE_FAULT_DET)
                        phy->flags &= ~FLAGS_TX_ERROR_CHECK;
 
+               if (!(params->feature_config_flags &
+                     FEATURE_CONFIG_MT_SUPPORT))
+                       phy->flags |= FLAGS_MDC_MDIO_WA_G;
+
                sync_offset = params->shmem_base +
                        offsetof(struct shmem_region,
                        dev_info.port_hw_config[params->port].media_type);
@@ -12542,7 +12578,7 @@ int bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
         * Hold it as vars low
         */
         /* Clear link led */
-       bnx2x_set_mdio_clk(bp, params->chip_id, port);
+       bnx2x_set_mdio_emac_per_phy(bp, params);
        bnx2x_set_led(params, vars, LED_MODE_OFF, 0);
 
        if (reset_ext_phy) {
@@ -13019,12 +13055,12 @@ int bnx2x_pre_init_phy(struct bnx2x *bp,
 {
        int rc = 0;
        struct bnx2x_phy phy;
-       bnx2x_set_mdio_clk(bp, chip_id, PORT_0);
        if (bnx2x_populate_phy(bp, EXT_PHY1, shmem_base, shmem2_base,
                               PORT_0, &phy)) {
                DP(NETIF_MSG_LINK, "populate_phy failed\n");
                return -EINVAL;
        }
+       bnx2x_set_mdio_clk(bp, chip_id, phy.mdio_ctrl);
        switch (phy.type) {
        case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833:
                rc = bnx2x_84833_pre_init_phy(bp, &phy);
@@ -13095,8 +13131,9 @@ int bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[],
        u32 phy_ver, val;
        u8 phy_index = 0;
        u32 ext_phy_type, ext_phy_config;
-       bnx2x_set_mdio_clk(bp, chip_id, PORT_0);
-       bnx2x_set_mdio_clk(bp, chip_id, PORT_1);
+
+       bnx2x_set_mdio_clk(bp, chip_id, GRCBASE_EMAC0);
+       bnx2x_set_mdio_clk(bp, chip_id, GRCBASE_EMAC1);
        DP(NETIF_MSG_LINK, "Begin common phy init\n");
        if (CHIP_IS_E3(bp)) {
                /* Enable EPIO */
index 33940fbe52c49d92ad91b0a40ecd3439cce43f40..24246b9a0c598e399321099e7de780d52741668b 100644 (file)
@@ -156,6 +156,7 @@ struct bnx2x_phy {
 #define FLAGS_MDC_MDIO_WA_B0           (1<<10)
 #define FLAGS_TX_ERROR_CHECK           (1<<12)
 #define FLAGS_EEE                      (1<<13)
+#define FLAGS_MDC_MDIO_WA_G    (1<<15)
 
        /* preemphasis values for the rx side */
        u16 rx_preemphasis[4];
@@ -267,6 +268,8 @@ struct link_params {
 #define FEATURE_CONFIG_AUTOGREEEN_ENABLED                      (1<<9)
 #define FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED             (1<<10)
 #define FEATURE_CONFIG_DISABLE_REMOTE_FAULT_DET                (1<<11)
+#define FEATURE_CONFIG_MT_SUPPORT                      (1<<13)
+
        /* Will be populated during common init */
        struct bnx2x_phy phy[MAX_PHYS];
 
index 4f33170a18d2b1b53c9a127d874250cdd7d96fa9..79e4b7245564fddd31ef15d5283add862500c11a 100644 (file)
@@ -9921,6 +9921,11 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
        bp->link_params.feature_config_flags |=
                (val >= REQ_BC_VER_4_SFP_TX_DISABLE_SUPPORTED) ?
                FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED : 0;
+
+       bp->link_params.feature_config_flags |=
+               (val >= REQ_BC_VER_4_MT_SUPPORTED) ?
+               FEATURE_CONFIG_MT_SUPPORT : 0;
+
        bp->flags |= (val >= REQ_BC_VER_4_PFC_STATS_SUPPORTED) ?
                        BC_SUPPORTS_PFC_STATS : 0;