diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2010-06-28 20:24:40 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2010-06-28 20:24:40 +0000 |
commit | 0a207b8443a33c9ee222d51495e916ff221072bf (patch) | |
tree | 69a6d324d02fc2ac2221da2d8e342f22ab959f90 | |
parent | aacf328674add35b5309e38c851ac0586c995ca6 (diff) |
Initial 82578 support from Mike Belopuhov.
ok claudio@
-rw-r--r-- | sys/dev/pci/if_em.c | 4 | ||||
-rw-r--r-- | sys/dev/pci/if_em_hw.c | 73 | ||||
-rw-r--r-- | sys/dev/pci/if_em_hw.h | 9 |
3 files changed, 74 insertions, 12 deletions
diff --git a/sys/dev/pci/if_em.c b/sys/dev/pci/if_em.c index 2c13e27faf0..58bbb633025 100644 --- a/sys/dev/pci/if_em.c +++ b/sys/dev/pci/if_em.c @@ -31,7 +31,7 @@ POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ -/* $OpenBSD: if_em.c,v 1.239 2010/06/27 20:13:04 jsg Exp $ */ +/* $OpenBSD: if_em.c,v 1.240 2010/06/28 20:24:39 jsg Exp $ */ /* $FreeBSD: if_em.c,v 1.46 2004/09/29 18:28:28 mlaier Exp $ */ #include <dev/pci/if_em.h> @@ -133,6 +133,8 @@ const struct pci_matchid em_devices[] = { { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82576_SERDES_QUAD }, { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82577LC }, { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82577LM }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82578DC }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82578DM }, { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ICH8_82567V_3 }, { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ICH8_IFE }, { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ICH8_IFE_G }, diff --git a/sys/dev/pci/if_em_hw.c b/sys/dev/pci/if_em_hw.c index 68113cfbf69..72abebe9b73 100644 --- a/sys/dev/pci/if_em_hw.c +++ b/sys/dev/pci/if_em_hw.c @@ -31,7 +31,7 @@ *******************************************************************************/ -/* $OpenBSD: if_em_hw.c,v 1.51 2010/06/27 20:13:04 jsg Exp $ */ +/* $OpenBSD: if_em_hw.c,v 1.52 2010/06/28 20:24:39 jsg Exp $ */ /* * if_em_hw.c Shared functions for accessing and configuring the MAC */ @@ -165,7 +165,6 @@ static int32_t em_configure_kmrn_for_10_100(struct em_hw *, uint16_t); static int32_t em_configure_kmrn_for_1000(struct em_hw *); static int32_t em_set_pciex_completion_timeout(struct em_hw *hw); int32_t em_hv_phy_workarounds_ich8lan(struct em_hw *); -void em_initialize_hw_bits_ich8lan(struct em_hw *); int32_t em_configure_k1_ich8lan(struct em_hw *, boolean_t); /* IGP cable length table */ @@ -236,6 +235,9 @@ em_set_phy_type(struct em_hw *hw) case I82577_E_PHY_ID: hw->phy_type = em_phy_82577; break; + case I82578_E_PHY_ID: + hw->phy_type = em_phy_82578; + break; case BME1000_E_PHY_ID: if (hw->phy_revision == 1) { hw->phy_type = em_phy_bm; @@ -518,6 +520,8 @@ em_set_mac_type(struct em_hw *hw) break; case E1000_DEV_ID_PCH_M_HV_LC: case E1000_DEV_ID_PCH_M_HV_LM: + case E1000_DEV_ID_PCH_D_HV_DC: + case E1000_DEV_ID_PCH_D_HV_DM: hw->mac_type = em_pchlan; break; case E1000_DEV_ID_EP80579_LAN_1: @@ -1414,8 +1418,9 @@ em_setup_link(struct em_hw *hw) E1000_WRITE_REG(hw, FCAL, FLOW_CONTROL_ADDRESS_LOW); } E1000_WRITE_REG(hw, FCTTV, hw->fc_pause_time); - - if (hw->phy_type == em_phy_82577) { + + if (hw->phy_type == em_phy_82577 || + hw->phy_type == em_phy_82578) { em_write_phy_reg(hw, PHY_REG(BM_PORT_CTRL_PAGE, 27), hw->fc_pause_time); } @@ -1980,6 +1985,10 @@ em_copper_link_mgp_setup(struct em_hw *hw) if (hw->phy_reset_disable) return E1000_SUCCESS; + /* disable lplu d0 during driver init */ + if (hw->mac_type == em_pchlan) + ret_val = em_set_lplu_state_pchlan(hw, FALSE); + /* Enable CRS on TX. This must be set for half-duplex operation. */ ret_val = em_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); if (ret_val) @@ -2096,6 +2105,20 @@ em_copper_link_mgp_setup(struct em_hw *hw) if (ret_val) return ret_val; } + if (hw->phy_type == em_phy_82578) { + ret_val = em_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, + &phy_data); + if (ret_val) + return ret_val; + + /* 82578 PHY - set the downshift count to 1x. */ + phy_data |= I82578_EPSCR_DOWNSHIFT_ENABLE; + phy_data &= ~I82578_EPSCR_DOWNSHIFT_COUNTER_MASK; + ret_val = em_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, + phy_data); + if (ret_val) + return ret_val; + } /* SW Reset the PHY so all changes take effect */ ret_val = em_phy_reset(hw); if (ret_val) { @@ -2326,7 +2349,8 @@ em_setup_copper_link(struct em_hw *hw) return ret_val; } else if (hw->phy_type == em_phy_m88 || hw->phy_type == em_phy_bm || - hw->phy_type == em_phy_oem) { + hw->phy_type == em_phy_oem || + hw->phy_type == em_phy_82578) { ret_val = em_copper_link_mgp_setup(hw); if (ret_val) return ret_val; @@ -2692,7 +2716,8 @@ em_phy_force_speed_duplex(struct em_hw *hw) if ((hw->phy_type == em_phy_m88) || (hw->phy_type == em_phy_gg82563) || (hw->phy_type == em_phy_bm) || - (hw->phy_type == em_phy_oem)) { + (hw->phy_type == em_phy_oem || + (hw->phy_type == em_phy_82578))) { ret_val = em_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); if (ret_val) @@ -4526,6 +4551,8 @@ em_match_gig_phy(struct em_hw *hw) match = TRUE; if (hw->phy_id == I82577_E_PHY_ID) match = TRUE; + if (hw->phy_id == I82578_E_PHY_ID) + match = TRUE; break; case em_icp_xxxx: if (hw->phy_id == M88E1141_E_PHY_ID) @@ -6796,7 +6823,8 @@ em_get_cable_length(struct em_hw *hw, uint16_t *min_length, /* Use old method for Phy older than IGP */ if (hw->phy_type == em_phy_m88 || - hw->phy_type == em_phy_oem) { + hw->phy_type == em_phy_oem || + hw->phy_type == em_phy_82578) { ret_val = em_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); @@ -6999,7 +7027,8 @@ em_check_downshift(struct em_hw *hw) IGP01E1000_PLHR_SS_DOWNGRADE) ? 1 : 0; } else if ((hw->phy_type == em_phy_m88) || (hw->phy_type == em_phy_gg82563) || - (hw->phy_type == em_phy_oem)) { + (hw->phy_type == em_phy_oem) || + (hw->phy_type == em_phy_82578)) { ret_val = em_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); if (ret_val) @@ -9126,7 +9155,8 @@ em_hv_phy_workarounds_ich8lan(struct em_hw *hw) } if (((hw->phy_type == em_phy_82577) && - ((hw->phy_revision == 1) || (hw->phy_revision == 2)))) { + ((hw->phy_revision == 1) || (hw->phy_revision == 2))) || + ((hw->phy_type == em_phy_82578) && (hw->phy_revision == 1))) { /* Disable generation of early preamble */ ret_val = em_write_phy_reg(hw, PHY_REG(769, 25), 0x4431); if (ret_val) @@ -9138,6 +9168,31 @@ em_hv_phy_workarounds_ich8lan(struct em_hw *hw) goto out; } + if (hw->phy_type == em_phy_82578) { + if (hw->revision_id < 3) { + /* PHY config */ + ret_val = em_write_phy_reg(hw, (1 << 6) | 0x29, + 0x66C0); + if (ret_val) + goto out; + + /* PHY config */ + ret_val = em_write_phy_reg(hw, (1 << 6) | 0x1E, + 0xFFFF); + if (ret_val) + goto out; + } + + /* + * Return registers to default by doing a soft reset then + * writing 0x3140 to the control register. + */ + if (hw->phy_revision < 2) { + em_phy_reset(hw); + ret_val = em_write_phy_reg(hw, PHY_CTRL, 0x3140); + } + } + if ((hw->revision_id == 2) && (hw->phy_type == em_phy_82577) && ((hw->phy_revision == 2) || (hw->phy_revision == 3))) { diff --git a/sys/dev/pci/if_em_hw.h b/sys/dev/pci/if_em_hw.h index 74808fc2124..28dc1146276 100644 --- a/sys/dev/pci/if_em_hw.h +++ b/sys/dev/pci/if_em_hw.h @@ -31,7 +31,7 @@ *******************************************************************************/ -/* $OpenBSD: if_em_hw.h,v 1.41 2010/06/27 20:13:04 jsg Exp $ */ +/* $OpenBSD: if_em_hw.h,v 1.42 2010/06/28 20:24:39 jsg Exp $ */ /* $FreeBSD: if_em_hw.h,v 1.15 2005/05/26 23:32:02 tackerman Exp $ */ /* if_em_hw.h @@ -237,6 +237,7 @@ typedef enum { em_phy_bm, /* phy used in i82574L, ICH10 and some ICH9 */ em_phy_oem, em_phy_82577, + em_phy_82578, em_phy_undefined = 0xFF } em_phy_type; @@ -2776,7 +2777,7 @@ struct em_host_command_info { GG82563_REG(194, 25) /* Link Partner Advertised Next page */ #define GG82563_PHY_KMRN_MISC \ GG82563_REG(194, 26) /* Misc. */ - + /* I82577 Specific Registers */ #define I82577_PHY_ADDR_REG 16 #define I82577_PHY_CFG_REG 22 @@ -3010,6 +3011,10 @@ struct em_host_command_info { #define M88E1000_EPSCR_TX_TIME_CTRL 0x0002 /* Add Delay */ #define M88E1000_EPSCR_RX_TIME_CTRL 0x0080 /* Add Delay */ +/* I82578 specific */ +#define I82578_EPSCR_DOWNSHIFT_ENABLE 0x0020 +#define I82578_EPSCR_DOWNSHIFT_COUNTER_MASK 0x001C + /* IGP01E1000 Specific Port Config Register - R/W */ #define IGP01E1000_PSCFR_AUTO_MDIX_PAR_DETECT 0x0010 #define IGP01E1000_PSCFR_PRE_EN 0x0020 |