-/* $OpenBSD: rgephyreg.h,v 1.6 2014/11/24 00:13:42 brad Exp $ */
+/* $OpenBSD: rgephyreg.h,v 1.7 2015/06/04 18:33:41 dms Exp $ */
/*
* Copyright (c) 2003
* Bill Paul <wpaul@windriver.com>. All rights reserved.
#define RGEPHY_ANER_LPNP 0x0008 /* Link partner can next page */
#define RGEPHY_ANER_NP 0x0004 /* Local PHY can next page */
#define RGEPHY_ANER_RX 0x0002 /* Next page received */
+
#define RGEPHY_ANER_LPAN 0x0001 /* Link partner autoneg capable */
#define RGEPHY_MII_NEXTP 0x07 /* Next page */
#define RGEPHY_SR_JABBER 0x0001 /* Jabber */
#define RGEPHY_SR_SPEED(X) ((X) & RGEPHY_SR_SPEED_MASK)
+#define RGEPHY_LC 0x18 /* PHY LED Control Register */
+#define RGEPHY_LC_P2 0x1A /* PHY LED Control Register, Page 2 */
+#define RGEPHY_LC_DISABLE 0x8000 /* disable leds */
+/* Led pusle strething */
+#define RGEPHY_LC_PULSE_1_3S 0x7000
+#define RGEPHY_LC_PULSE_670MS 0x6000
+#define RGEPHY_LC_PULSE_340MS 0x5000
+#define RGEPHY_LC_PULSE_170MS 0x4000
+#define RGEPHY_LC_PULSE_84MS 0x3000
+#define RGEPHY_LC_PULSE_42MS 0x2000
+#define RGEPHY_LC_PULSE_21MS 0x1000
+#define RGEPHY_LC_PULSE_0MS 0x0000
+#define RGEPHY_LC_LINK 0x0008 /* Link and speed indicated by combination of leds */
+#define RGEPHY_LC_DUPLEX 0x0004
+#define RGEPHY_LC_RX 0x0002
+#define RGEPHY_LC_TX 0x0001
+
+#define RGEPHY_PS 0x1F /* Page Select Register */
+#define RGEPHY_PS_PAGE_0 0x0000
+#define RGEPHY_PS_PAGE_1 0x0001
+#define RGEPHY_PS_PAGE_2 0x0002
+#define RGEPHY_PS_PAGE_3 0x0003
+#define RGEPHY_PS_PAGE_4 0x0004
+
#endif /* _DEV_RGEPHY_MIIREG_H_ */
*******************************************************************************/
-/* $OpenBSD: if_em_hw.c,v 1.84 2015/05/12 02:33:39 jsg Exp $ */
+/* $OpenBSD: if_em_hw.c,v 1.85 2015/06/04 18:33:41 dms Exp $ */
/*
* if_em_hw.c Shared functions for accessing and configuring the MAC
*/
#include <dev/pci/if_em_hw.h>
#include <dev/pci/if_em_soc.h>
+#include <dev/mii/rgephyreg.h>
+
#define STATIC
static int32_t em_swfw_sync_acquire(struct em_hw *, uint16_t);
case I350_I_PHY_ID:
hw->phy_type = em_phy_82580;
break;
+ case RTL8211_E_PHY_ID:
+ hw->phy_type = em_phy_rtl8211;
+ break;
case BME1000_E_PHY_ID:
if (hw->phy_revision == 1) {
hw->phy_type = em_phy_bm;
hw->icp_xxxx_port_num = 0;
break;
case E1000_DEV_ID_EP80579_LAN_2:
+ case E1000_DEV_ID_EP80579_LAN_4:
hw->mac_type = em_icp_xxxx;
hw->icp_xxxx_port_num = 1;
break;
case E1000_DEV_ID_EP80579_LAN_3:
+ case E1000_DEV_ID_EP80579_LAN_5:
hw->mac_type = em_icp_xxxx;
hw->icp_xxxx_port_num = 2;
break;
+ case E1000_DEV_ID_EP80579_LAN_6:
+ hw->mac_type = em_icp_xxxx;
+ hw->icp_xxxx_port_num = 3;
+ break;
default:
/* Should never have loaded on this device */
return -E1000_ERR_MAC_TYPE;
case E1000_DEV_ID_EP80579_LAN_1:
case E1000_DEV_ID_EP80579_LAN_2:
case E1000_DEV_ID_EP80579_LAN_3:
- hw->media_type = em_media_type_oem;
+ case E1000_DEV_ID_EP80579_LAN_4:
+ case E1000_DEV_ID_EP80579_LAN_5:
+ case E1000_DEV_ID_EP80579_LAN_6:
+ hw->media_type = em_media_type_copper;
break;
default:
switch (hw->mac_type) {
return ret_val;
}
+static int32_t
+em_copper_link_rtl8211_setup(struct em_hw *hw)
+{
+ int32_t ret_val;
+ uint16_t phy_data;
+
+ DEBUGFUNC("em_copper_link_rtl8211_setup: begin");
+
+ if (!hw) {
+ return -1;
+ }
+ /* SW Reset the PHY so all changes take effect */
+ em_phy_hw_reset(hw);
+
+ /* Enable CRS on TX. This must be set for half-duplex operation. */
+ phy_data = 0;
+
+ ret_val = em_read_phy_reg_ex(hw, RGEPHY_CR, &phy_data);
+ if (ret_val) {
+ printf("Unable to read RGEPHY_CR register\n");
+ return ret_val;
+ }
+ DEBUGOUT3("RTL8211: Rx phy_id=%X addr=%X SPEC_CTRL=%X\n", hw->phy_id,
+ hw->phy_addr, phy_data);
+ phy_data |= RGEPHY_CR_ASSERT_CRS;
+
+ ret_val = em_write_phy_reg_ex(hw, RGEPHY_CR, phy_data);
+ if (ret_val) {
+ printf("Unable to write RGEPHY_CR register\n");
+ return ret_val;
+ }
+
+ phy_data = 0; /* LED Control Register 0x18 */
+ ret_val = em_read_phy_reg_ex(hw, RGEPHY_LC, &phy_data);
+ if (ret_val) {
+ printf("Unable to read RGEPHY_LC register\n");
+ return ret_val;
+ }
+
+ phy_data &= 0x80FF; /* bit-15=0 disable, clear bit 8-10 */
+ ret_val = em_write_phy_reg_ex(hw, RGEPHY_LC, phy_data);
+ if (ret_val) {
+ printf("Unable to write RGEPHY_CR register\n");
+ return ret_val;
+ }
+ /* LED Control and Definition Register 0x11, PHY spec status reg */
+ phy_data = 0;
+ ret_val = em_read_phy_reg_ex(hw, RGEPHY_SR, &phy_data);
+ if (ret_val) {
+ printf("Unable to read RGEPHY_SRregister\n");
+ return ret_val;
+ }
+
+ phy_data |= 0x0010; /* LED active Low */
+ ret_val = em_write_phy_reg_ex(hw, RGEPHY_SR, phy_data);
+ if (ret_val) {
+ printf("Unable to write RGEPHY_SR register\n");
+ return ret_val;
+ }
+
+ phy_data = 0;
+ ret_val = em_read_phy_reg_ex(hw, RGEPHY_SR, &phy_data);
+ if (ret_val) {
+ printf("Unable to read RGEPHY_SR register\n");
+ return ret_val;
+ }
+
+ /* Switch to Page2 */
+ phy_data = RGEPHY_PS_PAGE_2;
+ ret_val = em_write_phy_reg_ex(hw, RGEPHY_PS, phy_data);
+ if (ret_val) {
+ printf("Unable to write PHY RGEPHY_PS register\n");
+ return ret_val;
+ }
+
+ phy_data = 0x0000;
+ ret_val = em_write_phy_reg_ex(hw, RGEPHY_LC_P2, phy_data);
+ if (ret_val) {
+ printf("Unable to write RGEPHY_LC_P2 register\n");
+ return ret_val;
+ }
+ usec_delay(5);
+
+
+ /* LED Configuration Control Reg for setting for 0x1A Register */
+ phy_data = 0;
+ ret_val = em_read_phy_reg_ex(hw, RGEPHY_LC_P2, &phy_data);
+ if (ret_val) {
+ printf("Unable to read RGEPHY_LC_P2 register\n");
+ return ret_val;
+ }
+
+ phy_data &= 0xF000;
+ phy_data |= 0x0F24;
+ ret_val = em_write_phy_reg_ex(hw, RGEPHY_LC_P2, phy_data);
+ if (ret_val) {
+ printf("Unable to write RGEPHY_LC_P2 register\n");
+ return ret_val;
+ }
+ phy_data = 0;
+ ret_val= em_read_phy_reg_ex(hw, RGEPHY_LC_P2, &phy_data);
+ if (ret_val) {
+ printf("Unable to read RGEPHY_LC_P2 register\n");
+ return ret_val;
+ }
+ DEBUGOUT1("RTL8211:ReadBack for check, LED_CFG->data=%X\n", phy_data);
+
+
+ /* After setting Page2, go back to Page 0 */
+ phy_data = 0;
+ ret_val = em_write_phy_reg_ex(hw, RGEPHY_PS, phy_data);
+ if (ret_val) {
+ printf("Unable to write PHY RGEPHY_PS register\n");
+ return ret_val;
+ }
+
+ /* pulse streching= 42-84ms, blink rate=84mm */
+ phy_data = 0x140 | RGEPHY_LC_PULSE_42MS | RGEPHY_LC_LINK |
+ RGEPHY_LC_DUPLEX | RGEPHY_LC_RX;
+
+ ret_val = em_write_phy_reg_ex(hw, RGEPHY_LC, phy_data);
+ if (ret_val) {
+ printf("Unable to write RGEPHY_LC register\n");
+ return ret_val;
+ }
+ return E1000_SUCCESS;
+}
+
/******************************************************************************
* Setup auto-negotiation and flow control advertisements,
* and then perform auto-negotiation.
ret_val = em_copper_link_82580_setup(hw);
if (ret_val)
return ret_val;
+ } else if (hw->phy_type == em_phy_rtl8211) {
+ ret_val = em_copper_link_rtl8211_setup(hw);
+ if (ret_val)
+ return ret_val;
}
if (hw->autoneg) {
/*
/* Need to reset the PHY or these changes will be ignored */
mii_ctrl_reg |= MII_CR_RESET;
+ }
+ else if (hw->phy_type == em_phy_rtl8211) {
+ ret_val = em_read_phy_reg_ex(hw, RGEPHY_CR, &phy_data);
+ if(ret_val) {
+ printf("Unable to read RGEPHY_CR register\n"
+ );
+ return ret_val;
+ }
+
+ /*
+ * Clear Auto-Crossover to force MDI manually. RTL8211 requires
+ * MDI forced whenever speed are duplex are forced.
+ */
+
+ phy_data |= RGEPHY_CR_MDI_MASK; // enable MDIX
+ ret_val = em_write_phy_reg_ex(hw, RGEPHY_CR, phy_data);
+ if(ret_val) {
+ printf("Unable to write RGEPHY_CR register\n");
+ return ret_val;
+ }
+ mii_ctrl_reg |= MII_CR_RESET;
+
}
/* Disable MDI-X support for 10/100 */
else if (hw->phy_type == em_phy_ife) {
if (ret_val)
return ret_val;
}
+ } else if (hw->phy_type == em_phy_rtl8211) {
+ /*
+ * In addition, because of the s/w reset above, we need to enable
+ * CRX on TX. This must be set for both full and half duplex
+ * operation.
+ */
+
+ ret_val = em_read_phy_reg_ex(hw, RGEPHY_CR, &phy_data);
+ if(ret_val) {
+ printf("Unable to read RGEPHY_CR register\n");
+ return ret_val;
+ }
+
+ phy_data &= ~RGEPHY_CR_ASSERT_CRS;
+ ret_val = em_write_phy_reg_ex(hw, RGEPHY_CR, phy_data);
+ if(ret_val) {
+ printf("Unable to write RGEPHY_CR register\n");
+ return ret_val;
+ }
} else if (hw->phy_type == em_phy_gg82563) {
/*
* The TX_CLK of the Extended PHY Specific Control Register
* MAC. Otherwise, we need to force speed/duplex on the MAC
* to the current PHY speed/duplex settings.
*/
- if (hw->mac_type >= em_82544 && hw->mac_type != em_icp_xxxx)
+ if (hw->mac_type >= em_82544 && hw->mac_type != em_icp_xxxx) {
em_config_collision_dist(hw);
- else {
+ } else {
ret_val = em_config_mac_to_phy(hw);
if (ret_val) {
DEBUGOUT("Error configuring MAC to PHY"
case em_icp_xxxx:
if (hw->phy_id == M88E1141_E_PHY_ID)
match = TRUE;
+ if (hw->phy_id == RTL8211_E_PHY_ID)
+ match = TRUE;
break;
default:
DEBUGOUT1("Invalid MAC type %d\n", hw->mac_type);
return -E1000_ERR_PHY;
break;
}
+ } else if (hw->phy_type == em_phy_rtl8211) {
+ /* no cable length info on RTL8211, fake */
+ *min_length = 0;
+ *max_length = em_igp_cable_length_50;
} else if (hw->phy_type == em_phy_gg82563) {
ret_val = em_read_phy_reg(hw, GG82563_PHY_DSP_DISTANCE,
&phy_data);
{
uint32_t manc = 0;
uint32_t fwsm = 0;
+ DEBUGFUNC("em_check_phy_reset_block\n");
+
if (IS_ICH8(hw->mac_type)) {
fwsm = E1000_READ_REG(hw, FWSM);
return (fwsm & E1000_FWSM_RSPCIPHY) ? E1000_SUCCESS :