mirror of
https://github.com/Telecominfraproject/OpenNetworkLinux.git
synced 2025-12-25 17:27:01 +00:00
igb: Add support for bcm5461x phy
Patch provided by David Ahern @dsahern for kernel 4.11 based on 3.16-lts ONL patch.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
#
|
||||
# Automatically generated file; DO NOT EDIT.
|
||||
# Linux/x86_64 4.9.30 Kernel Configuration
|
||||
# Linux/x86 4.9.30 Kernel Configuration
|
||||
#
|
||||
CONFIG_64BIT=y
|
||||
CONFIG_X86_64=y
|
||||
@@ -1477,6 +1477,7 @@ CONFIG_VIRTIO_NET=y
|
||||
# Distributed Switch Architecture drivers
|
||||
#
|
||||
CONFIG_ETHERNET=y
|
||||
CONFIG_MDIO=y
|
||||
CONFIG_NET_VENDOR_3COM=y
|
||||
# CONFIG_PCMCIA_3C574 is not set
|
||||
# CONFIG_PCMCIA_3C589 is not set
|
||||
@@ -1557,10 +1558,12 @@ CONFIG_E100=y
|
||||
CONFIG_E1000=y
|
||||
CONFIG_E1000E=y
|
||||
CONFIG_E1000E_HWTS=y
|
||||
# CONFIG_IGB is not set
|
||||
# CONFIG_IGBVF is not set
|
||||
# CONFIG_IXGB is not set
|
||||
# CONFIG_IXGBE is not set
|
||||
CONFIG_IGB=y
|
||||
CONFIG_IGB_HWMON=y
|
||||
CONFIG_IGBVF=y
|
||||
CONFIG_IXGB=y
|
||||
CONFIG_IXGBE=y
|
||||
CONFIG_IXGBE_HWMON=y
|
||||
# CONFIG_IXGBEVF is not set
|
||||
# CONFIG_I40E is not set
|
||||
# CONFIG_I40EVF is not set
|
||||
|
||||
@@ -0,0 +1,263 @@
|
||||
From 908a37bb6749d85a7818fb8a0f684d46c858f52e Mon Sep 17 00:00:00 2001
|
||||
From: David Ahern <dsahern@gmail.com>
|
||||
Date: Thu, 11 May 2017 17:53:43 -0700
|
||||
Subject: [PATCH] igb: Add support for bcm5461x phy
|
||||
|
||||
Based on driver-support-intel-igb-bcm5461X-phy.patch from
|
||||
OpenNetworkLinux, 3.16-lts patches
|
||||
|
||||
Signed-off-by: David Ahern <dsahern@gmail.com>
|
||||
---
|
||||
drivers/net/ethernet/intel/igb/e1000_82575.c | 27 ++++++++
|
||||
drivers/net/ethernet/intel/igb/e1000_defines.h | 2 +
|
||||
drivers/net/ethernet/intel/igb/e1000_hw.h | 2 +
|
||||
drivers/net/ethernet/intel/igb/e1000_phy.c | 87 ++++++++++++++++++++++++--
|
||||
drivers/net/ethernet/intel/igb/e1000_phy.h | 2 +
|
||||
drivers/net/ethernet/intel/igb/igb_main.c | 8 +++
|
||||
6 files changed, 124 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c
|
||||
index ee443985581fe..2de38acdc187f 100644
|
||||
--- a/drivers/net/ethernet/intel/igb/e1000_82575.c
|
||||
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.c
|
||||
@@ -339,6 +339,15 @@ static s32 igb_init_phy_params_82575(struct e1000_hw *hw)
|
||||
phy->ops.set_d3_lplu_state = igb_set_d3_lplu_state_82580;
|
||||
phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_m88;
|
||||
break;
|
||||
+ case BCM5461S_PHY_ID:
|
||||
+ phy->type = e1000_phy_bcm5461s;
|
||||
+ phy->ops.check_polarity = NULL;
|
||||
+ phy->ops.get_cable_length = NULL;
|
||||
+ phy->ops.force_speed_duplex = igb_phy_force_speed_duplex_82580;
|
||||
+ break;
|
||||
+ case BCM54616_E_PHY_ID:
|
||||
+ phy->type = e1000_phy_bcm54616;
|
||||
+ break;
|
||||
default:
|
||||
ret_val = -E1000_ERR_PHY;
|
||||
goto out;
|
||||
@@ -898,6 +907,16 @@ static s32 igb_get_phy_id_82575(struct e1000_hw *hw)
|
||||
goto out;
|
||||
}
|
||||
ret_val = igb_get_phy_id(hw);
|
||||
+ if (ret_val && hw->mac.type == e1000_i354) {
|
||||
+ /* we do a special check for bcm5461s phy by setting
|
||||
+ * the phy->addr to 5 and doing the phy check again. This
|
||||
+ * call will succeed and retrieve a valid phy id if we have
|
||||
+ * the bcm5461s phy
|
||||
+ */
|
||||
+ phy->addr = 5;
|
||||
+ phy->type = e1000_phy_bcm5461s;
|
||||
+ ret_val = igb_get_phy_id(hw);
|
||||
+ }
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1285,6 +1304,9 @@ static s32 igb_get_cfg_done_82575(struct e1000_hw *hw)
|
||||
(hw->phy.type == e1000_phy_igp_3))
|
||||
igb_phy_init_script_igp3(hw);
|
||||
|
||||
+ if (hw->phy.type == e1000_phy_bcm5461s)
|
||||
+ igb_phy_init_script_5461s(hw);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1614,6 +1636,7 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw)
|
||||
case e1000_i350:
|
||||
case e1000_i210:
|
||||
case e1000_i211:
|
||||
+ case e1000_i354:
|
||||
phpm_reg = rd32(E1000_82580_PHY_POWER_MGMT);
|
||||
phpm_reg &= ~E1000_82580_PM_GO_LINKD;
|
||||
wr32(E1000_82580_PHY_POWER_MGMT, phpm_reg);
|
||||
@@ -1658,6 +1681,10 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw)
|
||||
case e1000_phy_82580:
|
||||
ret_val = igb_copper_link_setup_82580(hw);
|
||||
break;
|
||||
+ case e1000_phy_bcm54616:
|
||||
+ break;
|
||||
+ case e1000_phy_bcm5461s:
|
||||
+ break;
|
||||
default:
|
||||
ret_val = -E1000_ERR_PHY;
|
||||
break;
|
||||
diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h
|
||||
index 8aee314332a87..9c1471643c542 100644
|
||||
--- a/drivers/net/ethernet/intel/igb/e1000_defines.h
|
||||
+++ b/drivers/net/ethernet/intel/igb/e1000_defines.h
|
||||
@@ -868,6 +868,8 @@
|
||||
#define I210_I_PHY_ID 0x01410C00
|
||||
#define M88E1543_E_PHY_ID 0x01410EA0
|
||||
#define M88E1512_E_PHY_ID 0x01410DD0
|
||||
+#define BCM54616_E_PHY_ID 0x3625D10
|
||||
+#define BCM5461S_PHY_ID 0x002060C0
|
||||
|
||||
/* M88E1000 Specific Registers */
|
||||
#define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */
|
||||
diff --git a/drivers/net/ethernet/intel/igb/e1000_hw.h b/drivers/net/ethernet/intel/igb/e1000_hw.h
|
||||
index 2fb2213cd562e..2840ad95396af 100644
|
||||
--- a/drivers/net/ethernet/intel/igb/e1000_hw.h
|
||||
+++ b/drivers/net/ethernet/intel/igb/e1000_hw.h
|
||||
@@ -128,6 +128,8 @@ enum e1000_phy_type {
|
||||
e1000_phy_ife,
|
||||
e1000_phy_82580,
|
||||
e1000_phy_i210,
|
||||
+ e1000_phy_bcm54616,
|
||||
+ e1000_phy_bcm5461s,
|
||||
};
|
||||
|
||||
enum e1000_bus_type {
|
||||
diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.c b/drivers/net/ethernet/intel/igb/e1000_phy.c
|
||||
index 68812d783f33e..1a4013ca6f85e 100644
|
||||
--- a/drivers/net/ethernet/intel/igb/e1000_phy.c
|
||||
+++ b/drivers/net/ethernet/intel/igb/e1000_phy.c
|
||||
@@ -146,6 +146,13 @@ s32 igb_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
|
||||
* Control register. The MAC will take care of interfacing with the
|
||||
* PHY to retrieve the desired data.
|
||||
*/
|
||||
+ if (phy->type == e1000_phy_bcm5461s) {
|
||||
+ mdic = rd32(E1000_MDICNFG);
|
||||
+ mdic &= ~E1000_MDICNFG_PHY_MASK;
|
||||
+ mdic |= (phy->addr << E1000_MDICNFG_PHY_SHIFT);
|
||||
+ wr32(E1000_MDICNFG, mdic);
|
||||
+ }
|
||||
+
|
||||
mdic = ((offset << E1000_MDIC_REG_SHIFT) |
|
||||
(phy->addr << E1000_MDIC_PHY_SHIFT) |
|
||||
(E1000_MDIC_OP_READ));
|
||||
@@ -202,6 +209,13 @@ s32 igb_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
|
||||
* Control register. The MAC will take care of interfacing with the
|
||||
* PHY to retrieve the desired data.
|
||||
*/
|
||||
+ if (phy->type == e1000_phy_bcm5461s) {
|
||||
+ mdic = rd32(E1000_MDICNFG);
|
||||
+ mdic &= ~E1000_MDICNFG_PHY_MASK;
|
||||
+ mdic |= (phy->addr << E1000_MDICNFG_PHY_SHIFT);
|
||||
+ wr32(E1000_MDICNFG, mdic);
|
||||
+ }
|
||||
+
|
||||
mdic = (((u32)data) |
|
||||
(offset << E1000_MDIC_REG_SHIFT) |
|
||||
(phy->addr << E1000_MDIC_PHY_SHIFT) |
|
||||
@@ -1113,10 +1127,12 @@ s32 igb_setup_copper_link(struct e1000_hw *hw)
|
||||
* depending on user settings.
|
||||
*/
|
||||
hw_dbg("Forcing Speed and Duplex\n");
|
||||
- ret_val = hw->phy.ops.force_speed_duplex(hw);
|
||||
- if (ret_val) {
|
||||
- hw_dbg("Error Forcing Speed and Duplex\n");
|
||||
- goto out;
|
||||
+ if (hw->phy.ops.force_speed_duplex) {
|
||||
+ ret_val = hw->phy.ops.force_speed_duplex(hw);
|
||||
+ if (ret_val) {
|
||||
+ hw_dbg("Error Forcing Speed and Duplex\n");
|
||||
+ goto out;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2647,3 +2663,66 @@ static s32 igb_set_master_slave_mode(struct e1000_hw *hw)
|
||||
|
||||
return hw->phy.ops.write_reg(hw, PHY_1000T_CTRL, phy_data);
|
||||
}
|
||||
+
|
||||
+/**
|
||||
+ * igb_phy_init_script_5461s - Inits the BCM5461S PHY
|
||||
+ * @hw: pointer to the HW structure
|
||||
+ *
|
||||
+ * Initializes a Broadcom Gigabit PHY.
|
||||
+ **/
|
||||
+s32 igb_phy_init_script_5461s(struct e1000_hw *hw)
|
||||
+{
|
||||
+ u16 mii_reg_led = 0;
|
||||
+
|
||||
+ /* 1. Speed LED (Set the Link LED mode), Shadow 00010, 0x1C.bit2=1 */
|
||||
+ hw->phy.ops.write_reg(hw, 0x1C, 0x0800);
|
||||
+ hw->phy.ops.read_reg(hw, 0x1C, &mii_reg_led);
|
||||
+ mii_reg_led |= 0x0004;
|
||||
+ hw->phy.ops.write_reg(hw, 0x1C, mii_reg_led | 0x8000);
|
||||
+
|
||||
+ /* 2. Active LED (Set the Link LED mode), Shadow 01001, 0x1C.bit4=1, 0x10.bit5=0 */
|
||||
+ hw->phy.ops.write_reg(hw, 0x1C, 0x2400);
|
||||
+ hw->phy.ops.read_reg(hw, 0x1C, &mii_reg_led);
|
||||
+ mii_reg_led |= 0x0010;
|
||||
+ hw->phy.ops.write_reg(hw, 0x1C, mii_reg_led | 0x8000);
|
||||
+ hw->phy.ops.read_reg(hw, 0x10, &mii_reg_led);
|
||||
+ mii_reg_led &= 0xffdf;
|
||||
+ hw->phy.ops.write_reg(hw, 0x10, mii_reg_led);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * igb_get_phy_info_5461s - Retrieve 5461s PHY information
|
||||
+ * @hw: pointer to the HW structure
|
||||
+ *
|
||||
+ * Read PHY status to determine if link is up. If link is up, then
|
||||
+ * set/determine 10base-T extended distance and polarity correction. Read
|
||||
+ * PHY port status to determine MDI/MDIx and speed. Based on the speed,
|
||||
+ * determine on the cable length, local and remote receiver.
|
||||
+ **/
|
||||
+s32 igb_get_phy_info_5461s(struct e1000_hw *hw)
|
||||
+{
|
||||
+ struct e1000_phy_info *phy = &hw->phy;
|
||||
+ s32 ret_val;
|
||||
+ bool link;
|
||||
+
|
||||
+ ret_val = igb_phy_has_link(hw, 1, 0, &link);
|
||||
+ if (ret_val)
|
||||
+ goto out;
|
||||
+
|
||||
+ if (!link) {
|
||||
+ ret_val = -E1000_ERR_CONFIG;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ phy->polarity_correction = true;
|
||||
+
|
||||
+ phy->is_mdix = true;
|
||||
+ phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED;
|
||||
+ phy->local_rx = e1000_1000t_rx_status_ok;
|
||||
+ phy->remote_rx = e1000_1000t_rx_status_ok;
|
||||
+
|
||||
+out:
|
||||
+ return ret_val;
|
||||
+}
|
||||
diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.h b/drivers/net/ethernet/intel/igb/e1000_phy.h
|
||||
index 9b622b33bb5ac..3b28873060946 100644
|
||||
--- a/drivers/net/ethernet/intel/igb/e1000_phy.h
|
||||
+++ b/drivers/net/ethernet/intel/igb/e1000_phy.h
|
||||
@@ -61,6 +61,8 @@ s32 igb_phy_has_link(struct e1000_hw *hw, u32 iterations,
|
||||
void igb_power_up_phy_copper(struct e1000_hw *hw);
|
||||
void igb_power_down_phy_copper(struct e1000_hw *hw);
|
||||
s32 igb_phy_init_script_igp3(struct e1000_hw *hw);
|
||||
+s32 igb_phy_init_script_5461s(struct e1000_hw *hw);
|
||||
+s32 igb_get_phy_info_5461s(struct e1000_hw *hw);
|
||||
s32 igb_initialize_M88E1512_phy(struct e1000_hw *hw);
|
||||
s32 igb_initialize_M88E1543_phy(struct e1000_hw *hw);
|
||||
s32 igb_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data);
|
||||
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
|
||||
index be456bae81690..4689079f8bbcd 100644
|
||||
--- a/drivers/net/ethernet/intel/igb/igb_main.c
|
||||
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
|
||||
@@ -7356,11 +7356,19 @@ static int igb_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
|
||||
data->phy_id = adapter->hw.phy.addr;
|
||||
break;
|
||||
case SIOCGMIIREG:
|
||||
+ adapter->hw.phy.addr = data->phy_id;
|
||||
if (igb_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
|
||||
&data->val_out))
|
||||
return -EIO;
|
||||
break;
|
||||
case SIOCSMIIREG:
|
||||
+ if (!capable(CAP_NET_ADMIN))
|
||||
+ return -EPERM;
|
||||
+ adapter->hw.phy.addr = data->phy_id;
|
||||
+ if (igb_write_phy_reg(&adapter->hw, data->reg_num & 0x1F,
|
||||
+ data->val_in))
|
||||
+ return -EIO;
|
||||
+ break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
|
||||
driver-support-intel-igb-bcm5461-phy.patch
|
||||
|
||||
Reference in New Issue
Block a user