]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[e1000e] Basic 82579 support
authorDaniel Hokka Zakrisson <daniel@hozac.com>
Fri, 6 Apr 2012 08:13:04 +0000 (10:13 +0200)
committerMichael Brown <mcb30@ipxe.org>
Tue, 10 Apr 2012 12:47:19 +0000 (13:47 +0100)
Add support for 82579-based chips such as those found on Sandy Bridge
motherboards.  Based on d3738bb8203acf8552c3ec8b3447133fc0938ddd in
Linux.

Signed-off-by: Daniel Hokka Zakrisson <daniel@hozac.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/drivers/net/e1000e/e1000e.h
src/drivers/net/e1000e/e1000e_defines.h
src/drivers/net/e1000e/e1000e_hw.h
src/drivers/net/e1000e/e1000e_ich8lan.c
src/drivers/net/e1000e/e1000e_ich8lan.h
src/drivers/net/e1000e/e1000e_main.c
src/drivers/net/e1000e/e1000e_phy.c

index bc8e7b08328c52e7dd6b177b551efd2ae701302b..0e537932c6ad09cac7c3a7a3ea4ffa113212d794 100644 (file)
@@ -143,6 +143,7 @@ enum e1000_boards {
        board_ich9lan,
        board_ich10lan,
        board_pchlan,
+       board_pch2lan,
        board_82583,
 };
 
@@ -300,6 +301,7 @@ extern void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw,
 extern void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw);
 extern void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw);
 extern void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw);
+extern s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable);
 
 extern s32 e1000e_check_for_copper_link(struct e1000_hw *hw);
 extern s32 e1000e_check_for_fiber_link(struct e1000_hw *hw);
index da135d918bffb16c96005f4d8f55beac8efd0cb5..8cfc6ed8286e557fea78fe643936cf7cbd0cc537 100644 (file)
@@ -675,6 +675,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE       0x00000001
 #define E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE       0x00000008
 #define E1000_EXTCNF_CTRL_SWFLAG                 0x00000020
+#define E1000_EXTCNF_CTRL_GATE_PHY_CFG           0x00000080
 #define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK   0x00FF0000
 #define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT          16
 #define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK   0x0FFF0000
@@ -1261,6 +1262,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #define BME1000_E_PHY_ID_R2  0x01410CB1
 #define I82577_E_PHY_ID 0x01540050
 #define I82578_E_PHY_ID 0x004DD040
+#define I82579_E_PHY_ID      0x01540090
 #define M88_VENDOR           0x0141
 
 /* M88E1000 Specific Registers */
index 03ed35c92761808ac2f6c785b5cc293bc29ebf82..336af30d4efb5e94a5294a5e22748484b5580202 100644 (file)
@@ -85,6 +85,8 @@ struct e1000_hw;
 #define E1000_DEV_ID_PCH_M_HV_LC              0x10EB
 #define E1000_DEV_ID_PCH_D_HV_DM              0x10EF
 #define E1000_DEV_ID_PCH_D_HV_DC              0x10F0
+#define E1000_DEV_ID_PCH2_LV_LM               0x1502
+#define E1000_DEV_ID_PCH2_LV_V                0x1503
 #define E1000_REVISION_0 0
 #define E1000_REVISION_1 1
 #define E1000_REVISION_2 2
@@ -109,6 +111,7 @@ enum e1000_mac_type {
        e1000_ich9lan,
        e1000_ich10lan,
        e1000_pchlan,
+       e1000_pch2lan,
        e1000_num_macs  /* List is 1-based, so subtract 1 for true count. */
 };
 
@@ -146,6 +149,7 @@ enum e1000_phy_type {
        e1000_phy_bm,
        e1000_phy_82578,
        e1000_phy_82577,
+       e1000_phy_82579,
 };
 
 enum e1000_bus_type {
index 7b9a49b98f1ed9585308730efbd67994efd19968..d438ff1e9487157b0a565f6856ef80b42a16f015 100644 (file)
@@ -206,7 +206,7 @@ static s32 e1000e_init_phy_params_pchlan(struct e1000_hw *hw)
        e1000e_get_phy_id(hw);
        phy->type = e1000e_get_phy_type_from_id(phy->id);
 
-       if (phy->type == e1000_phy_82577) {
+       if (phy->type == e1000_phy_82577 || phy->type == e1000_phy_82579) {
                phy->ops.check_polarity = e1000e_check_polarity_82577;
 #if 0
                phy->ops.force_speed_duplex =
@@ -449,6 +449,7 @@ static s32 e1000e_init_mac_params_ich8lan(struct e1000_hw *hw)
                mac->ops.led_off = e1000e_led_off_ich8lan;
                break;
        case e1000_pchlan:
+       case e1000_pch2lan:
                /* ID LED init */
                mac->ops.id_led_init = e1000e_id_led_init_pchlan;
                /* setup LED */
@@ -467,6 +468,14 @@ static s32 e1000e_init_mac_params_ich8lan(struct e1000_hw *hw)
        if (mac->type == e1000_ich8lan)
                e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, true);
 
+       /* Disable PHY configuration by hardware, config by software */
+       if (mac->type == e1000_pch2lan) {
+               u32 extcnf_ctrl = er32(EXTCNF_CTRL);
+
+               extcnf_ctrl |= E1000_EXTCNF_CTRL_GATE_PHY_CFG;
+               ew32(EXTCNF_CTRL, extcnf_ctrl);
+       }
+
 
        return E1000_SUCCESS;
 }
@@ -577,6 +586,7 @@ void e1000e_init_function_pointers_ich8lan(struct e1000_hw *hw)
                hw->phy.ops.init_params = e1000e_init_phy_params_ich8lan;
                break;
        case e1000_pchlan:
+       case e1000_pch2lan:
                hw->phy.ops.init_params = e1000e_init_phy_params_pchlan;
                break;
        default:
@@ -765,7 +775,8 @@ static s32 e1000e_sw_lcd_config_ich8lan(struct e1000_hw *hw)
                /* Check if SW needs to configure the PHY */
                if ((hw->device_id == E1000_DEV_ID_ICH8_IGP_M_AMT) ||
                    (hw->device_id == E1000_DEV_ID_ICH8_IGP_M) ||
-                   (hw->mac.type == e1000_pchlan))
+                   (hw->mac.type == e1000_pchlan) ||
+                   (hw->mac.type == e1000_pch2lan))
                        sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;
                else
                        sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG;
@@ -777,13 +788,15 @@ static s32 e1000e_sw_lcd_config_ich8lan(struct e1000_hw *hw)
                /* Wait for basic configuration completes before proceeding */
                e1000e_lan_init_done_ich8lan(hw);
 
-               /*
-                * Make sure HW does not configure LCD from PHY
-                * extended configuration before SW configuration
-                */
-               data = er32(EXTCNF_CTRL);
-               if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)
-                       goto out;
+               if (hw->mac.type != e1000_pch2lan) {
+                       /*
+                        * Make sure HW does not configure LCD from PHY
+                        * extended configuration before SW configuration
+                        */
+                       data = er32(EXTCNF_CTRL);
+                       if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)
+                               goto out;
+               }
 
                cnf_size = er32(EXTCNF_SIZE);
                cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK;
@@ -795,7 +808,8 @@ static s32 e1000e_sw_lcd_config_ich8lan(struct e1000_hw *hw)
                cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;
 
                if (!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) &&
-                   (hw->mac.type == e1000_pchlan)) {
+                   (hw->mac.type == e1000_pchlan ||
+                    hw->mac.type == e1000_pch2lan)) {
                        /*
                         * HW configures the SMBus address and LEDs when the
                         * OEM and LCD Write Enable bits are set in the NVM.
@@ -1006,16 +1020,18 @@ s32 e1000e_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state)
        u32 mac_reg;
        u16 oem_reg;
 
-       if (hw->mac.type != e1000_pchlan)
+       if (hw->mac.type != e1000_pchlan && hw->mac.type != e1000_pch2lan)
                return ret_val;
 
        ret_val = hw->phy.ops.acquire(hw);
        if (ret_val)
                return ret_val;
 
-       mac_reg = er32(EXTCNF_CTRL);
-       if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)
-               goto out;
+       if (hw->mac.type != e1000_pch2lan) {
+               mac_reg = er32(EXTCNF_CTRL);
+               if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)
+                       goto out;
+       }
 
        mac_reg = er32(FEXTNVM);
        if (!(mac_reg & E1000_FEXTNVM_SW_CONFIG_ICH8M))
@@ -2573,7 +2589,7 @@ static s32 e1000e_reset_hw_ich8lan(struct e1000_hw *hw)
                }
        }
        /* Dummy read to clear the phy wakeup bit after lcd reset */
-       if (hw->mac.type == e1000_pchlan)
+       if (hw->mac.type == e1000_pchlan || hw->mac.type == e1000_pch2lan)
                e1e_rphy(hw, BM_WUC, &reg);
 
        ret_val = e1000e_sw_lcd_config_ich8lan(hw);
@@ -2791,6 +2807,7 @@ static s32 e1000e_setup_link_ich8lan(struct e1000_hw *hw)
 
        ew32(FCTTV, hw->fc.pause_time);
        if ((hw->phy.type == e1000_phy_82578) ||
+           (hw->phy.type == e1000_phy_82579) ||
            (hw->phy.type == e1000_phy_82577)) {
                ret_val = e1e_wphy(hw,
                                             PHY_REG(BM_PORT_CTRL_PAGE, 27),
@@ -2859,6 +2876,7 @@ static s32 e1000e_setup_copper_link_ich8lan(struct e1000_hw *hw)
                        goto out;
                break;
        case e1000_phy_82577:
+       case e1000_phy_82579:
                ret_val = e1000e_copper_link_setup_82577(hw);
                if (ret_val)
                        goto out;
@@ -3388,6 +3406,7 @@ static void e1000e_clear_hw_cntrs_ich8lan(struct e1000_hw *hw __unused)
 
        /* Clear PHY statistics registers */
        if ((hw->phy.type == e1000_phy_82578) ||
+           (hw->phy.type == e1000_phy_82579) ||
            (hw->phy.type == e1000_phy_82577)) {
                e1e_rphy(hw, HV_SCC_UPPER, &phy_data);
                e1e_rphy(hw, HV_SCC_LOWER, &phy_data);
@@ -3434,6 +3453,8 @@ static struct pci_device_id e1000e_ich8lan_nics[] = {
      PCI_ROM(0x8086, 0x10EB, "E1000_DEV_ID_PCH_M_HV_LC", "E1000_DEV_ID_PCH_M_HV_LC", board_pchlan),
      PCI_ROM(0x8086, 0x10EF, "E1000_DEV_ID_PCH_D_HV_DM", "E1000_DEV_ID_PCH_D_HV_DM", board_pchlan),
      PCI_ROM(0x8086, 0x10F0, "E1000_DEV_ID_PCH_D_HV_DC", "E1000_DEV_ID_PCH_D_HV_DC", board_pchlan),
+     PCI_ROM(0x8086, 0x1502, "E1000_DEV_ID_PCH2_LV_LM", "E1000_DEV_ID_PCH2_LV_LM", board_pch2lan),
+     PCI_ROM(0x8086, 0x1503, "E1000_DEV_ID_PCH2_LV_V", "E1000_DEV_ID_PCH2_LV_V", board_pch2lan),
 };
 
 struct pci_driver e1000e_ich8lan_driver __pci_driver = {
index af3447829288a54f0d8969fff19c9cb42ab2b721..8b145d92062a537a9ef860f143cf3d4a33d4e81c 100644 (file)
@@ -146,6 +146,9 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #define HV_SMB_ADDR_PEC_EN     0x0200
 #define HV_SMB_ADDR_VALID      0x0080
 
+/* PHY Power Management Control */
+#define HV_PM_CTRL             PHY_REG(770, 17)
+
 /* Strapping Option Register - RO */
 #define E1000_STRAP                     0x0000C
 #define E1000_STRAP_SMBUS_ADDRESS_MASK  0x00FE0000
index 352e3c45e3f67f2f9d3d85a1f4f71b365bc46b15..69a5bc20a605de5c75b4d17ba9fe11c57fa631b9 100644 (file)
@@ -279,6 +279,22 @@ static struct e1000_info e1000_pch_info = {
        .get_variants           = e1000e_get_variants_ich8lan,
 };
 
+static struct e1000_info e1000_pch2_info = {
+       .mac                    = e1000_pch2lan,
+       .flags                  = FLAG_IS_ICH
+                                 | FLAG_HAS_WOL
+                                 | FLAG_RX_CSUM_ENABLED
+                                 | FLAG_HAS_CTRLEXT_ON_LOAD
+                                 | FLAG_HAS_AMT
+                                 | FLAG_HAS_FLASH
+                                 | FLAG_HAS_JUMBO_FRAMES
+                                 | FLAG_APME_IN_WUC,
+       .pba                    = 26,
+       .max_hw_frame_size      = DEFAULT_JUMBO,
+       .init_ops               = e1000e_init_function_pointers_ich8lan,
+       .get_variants           = e1000e_get_variants_ich8lan,
+};
+
 static const struct e1000_info *e1000_info_tbl[] = {
        [board_82571]           = &e1000_82571_info,
        [board_82572]           = &e1000_82572_info,
@@ -290,6 +306,7 @@ static const struct e1000_info *e1000_info_tbl[] = {
        [board_ich9lan]         = &e1000_ich9_info,
        [board_ich10lan]        = &e1000_ich10_info,
        [board_pchlan]          = &e1000_pch_info,
+       [board_pch2lan]         = &e1000_pch2_info,
 };
 
 /* Low-level support routines */
index 337be7371df37405c3c9e7c96ffd0ad0ca71dd41..133109dc8cf4355222a7b5e3c6dfdf3e2e844daa 100644 (file)
@@ -2332,6 +2332,9 @@ enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id)
        case I82577_E_PHY_ID:
                phy_type = e1000_phy_82577;
                break;
+       case I82579_E_PHY_ID:
+               phy_type = e1000_phy_82579;
+               break;
        default:
                phy_type = e1000_phy_unknown;
                break;