bnx2x: Adjust BCM8726 module detection settings
authorYaniv Rosner <yanivr@broadcom.com>
Tue, 31 May 2011 21:28:43 +0000 (21:28 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 1 Jun 2011 20:10:57 +0000 (13:10 -0700)
Move BCM8726 module detection code into a separate function to be called only once during initialization.

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/bnx2x/bnx2x_hsi.h
drivers/net/bnx2x/bnx2x_link.c
drivers/net/bnx2x/bnx2x_link.h
drivers/net/bnx2x/bnx2x_main.c
drivers/net/bnx2x/bnx2x_reg.h

index 5bfdbcc94a7c0338cfd363ef7495db66e2bece9c..c308a48c8f4b366da0b2cf83bb79696e1847a392 100644 (file)
@@ -263,7 +263,10 @@ struct port_hw_cfg {                           /* port 0: 0x12c  port 1: 0x2bc */
 #define PORT_HW_CFG_FAULT_MODULE_LED_GPIO2                   0x00000200
 #define PORT_HW_CFG_FAULT_MODULE_LED_GPIO3                   0x00000300
 #define PORT_HW_CFG_FAULT_MODULE_LED_DISABLED                0x00000400
-       u32 Reserved01[11];                                 /* 0x158 */
+
+       u32 Reserved01[10];                                 /* 0x158 */
+
+       u32 aeu_int_mask;                                       /* 0x190 */
 
        u32 media_type;                                 /* 0x194 */
 #define PORT_HW_CFG_MEDIA_TYPE_PHY0_MASK                     0x000000FF
index 81bcd6141065f0992f1a2345cd4d830eb8484dda..e44c19d86c39051a12761d5dc7b59ad8df3461be 100644 (file)
@@ -1915,8 +1915,15 @@ void bnx2x_link_status_update(struct link_params *params,
                PORT_HW_CFG_MEDIA_TYPE_PHY2_SHIFT;
        DP(NETIF_MSG_LINK, "media_types = 0x%x\n", media_types);
 
-       DP(NETIF_MSG_LINK, "link_status 0x%x  phy_link_up %x\n",
-                vars->link_status, vars->phy_link_up);
+       /* Sync AEU offset */
+       sync_offset = params->shmem_base +
+                       offsetof(struct shmem_region,
+                                dev_info.port_hw_config[port].aeu_int_mask);
+
+       vars->aeu_int_mask = REG_RD(bp, sync_offset);
+
+       DP(NETIF_MSG_LINK, "link_status 0x%x  phy_link_up %x int_mask 0x%x\n",
+                vars->link_status, vars->phy_link_up, vars->aeu_int_mask);
        DP(NETIF_MSG_LINK, "line_speed %x  duplex %x  flow_ctrl 0x%x\n",
                 vars->line_speed, vars->duplex, vars->flow_ctrl);
 }
@@ -5522,8 +5529,6 @@ static int bnx2x_8726_config_init(struct bnx2x_phy *phy,
                                  struct link_vars *vars)
 {
        struct bnx2x *bp = params->bp;
-       u32 val;
-       u32 swap_val, swap_override, aeu_gpio_mask, offset;
        DP(NETIF_MSG_LINK, "Initializing BCM8726\n");
 
        bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
@@ -5602,30 +5607,6 @@ static int bnx2x_8726_config_init(struct bnx2x_phy *phy,
                                 phy->tx_preemphasis[1]);
        }
 
-       /* Set GPIO3 to trigger SFP+ module insertion/removal */
-       bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
-                      MISC_REGISTERS_GPIO_INPUT_HI_Z, params->port);
-
-       /* The GPIO should be swapped if the swap register is set and active */
-       swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
-       swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
-
-       /* Select function upon port-swap configuration */
-       if (params->port == 0) {
-               offset = MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0;
-               aeu_gpio_mask = (swap_val && swap_override) ?
-                       AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1 :
-                       AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0;
-       } else {
-               offset = MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0;
-               aeu_gpio_mask = (swap_val && swap_override) ?
-                       AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0 :
-                       AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1;
-       }
-       val = REG_RD(bp, offset);
-       /* add GPIO3 to group */
-       val |= aeu_gpio_mask;
-       REG_WR(bp, offset, val);
        return 0;
 
 }
@@ -8521,3 +8502,66 @@ void bnx2x_hw_reset_phy(struct link_params *params)
                }
        }
 }
+
+void bnx2x_init_mod_abs_int(struct bnx2x *bp, struct link_vars *vars,
+                           u32 chip_id, u32 shmem_base, u32 shmem2_base,
+                           u8 port)
+{
+       u8 gpio_num = 0xff, gpio_port = 0xff, phy_index;
+       u32 val;
+       u32 offset, aeu_mask, swap_val, swap_override, sync_offset;
+
+       {
+               struct bnx2x_phy phy;
+               for (phy_index = EXT_PHY1; phy_index < MAX_PHYS;
+                     phy_index++) {
+                       if (bnx2x_populate_phy(bp, phy_index, shmem_base,
+                                              shmem2_base, port, &phy)
+                           != 0) {
+                               DP(NETIF_MSG_LINK, "populate phy failed\n");
+                               return;
+                       }
+                       if (phy.type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) {
+                               gpio_num = MISC_REGISTERS_GPIO_3;
+                               gpio_port = port;
+                               break;
+                       }
+               }
+       }
+
+       if (gpio_num == 0xff)
+               return;
+
+       /* Set GPIO3 to trigger SFP+ module insertion/removal */
+       bnx2x_set_gpio(bp, gpio_num, MISC_REGISTERS_GPIO_INPUT_HI_Z, gpio_port);
+
+       swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
+       swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
+       gpio_port ^= (swap_val && swap_override);
+
+       vars->aeu_int_mask = AEU_INPUTS_ATTN_BITS_GPIO0_FUNCTION_0 <<
+               (gpio_num + (gpio_port << 2));
+
+       sync_offset = shmem_base +
+               offsetof(struct shmem_region,
+                        dev_info.port_hw_config[port].aeu_int_mask);
+       REG_WR(bp, sync_offset, vars->aeu_int_mask);
+
+       DP(NETIF_MSG_LINK, "Setting MOD_ABS (GPIO%d_P%d) AEU to 0x%x\n",
+                      gpio_num, gpio_port, vars->aeu_int_mask);
+
+       if (port == 0)
+               offset = MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0;
+       else
+               offset = MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0;
+
+       /* Open appropriate AEU for interrupts */
+       aeu_mask = REG_RD(bp, offset);
+       aeu_mask |= vars->aeu_int_mask;
+       REG_WR(bp, offset, aeu_mask);
+
+       /* Enable the GPIO to trigger interrupt */
+       val = REG_RD(bp, MISC_REG_GPIO_EVENT_EN);
+       val |= 1 << (gpio_num + (gpio_port << 2));
+       REG_WR(bp, MISC_REG_GPIO_EVENT_EN, val);
+}
index 906b5117083d4a0f8b4aec68283fc04187b3ac2d..a106d8cbd69fc7bef744a7542388876ec11b6c01 100644 (file)
@@ -277,6 +277,7 @@ struct link_vars {
        u8 fault_detected;
        u8 rsrv1;
        u16 rsrv2;
+       u32 aeu_int_mask;
 };
 
 /***********************************************************/
@@ -401,4 +402,7 @@ int bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos);
 void bnx2x_pfc_statistic(struct link_params *params, struct link_vars *vars,
                                                 u32 pfc_frames_sent[2],
                                                 u32 pfc_frames_received[2]);
+void bnx2x_init_mod_abs_int(struct bnx2x *bp, struct link_vars *vars,
+                           u32 chip_id, u32 shmem_base, u32 shmem2_base,
+                           u8 port);
 #endif /* BNX2X_LINK_H */
index c6591c46ebdf298dbe80dff6c818310d09e72eeb..2e89b6cf37ae1974e6c209f6ca61630fef8eff7b 100644 (file)
@@ -4452,6 +4452,10 @@ void bnx2x_nic_init(struct bnx2x *bp, u32 load_code)
 
 #endif
 
+       /* Initialize MOD_ABS interrupts */
+       bnx2x_init_mod_abs_int(bp, &bp->link_vars, bp->common.chip_id,
+                              bp->common.shmem_base, bp->common.shmem2_base,
+                              BP_PORT(bp));
        /* ensure status block indices were read */
        rmb();
 
index 11d35250b092befae215fa8b9215ac6d938e6f20..949e8bd7318804fe30cf6f2c8fb0c51844327c35 100644 (file)
 #define AEU_INPUTS_ATTN_BITS_DMAE_HW_INTERRUPT               (1<<11)
 #define AEU_INPUTS_ATTN_BITS_DOORBELLQ_HW_INTERRUPT          (1<<13)
 #define AEU_INPUTS_ATTN_BITS_DOORBELLQ_PARITY_ERROR          (1<<12)
+#define AEU_INPUTS_ATTN_BITS_GPIO0_FUNCTION_0                (1<<2)
 #define AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0                (1<<5)
 #define AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1                (1<<9)
 #define AEU_INPUTS_ATTN_BITS_IGU_PARITY_ERROR                (1<<12)