diff --git a/packages/base/any/kernels/3.16+deb8/patches/driver-support-intel-igb-bcm5461X-phy.patch b/packages/base/any/kernels/3.16+deb8/patches/driver-support-intel-igb-bcm5461X-phy.patch new file mode 100644 index 00000000..e258426c --- /dev/null +++ b/packages/base/any/kernels/3.16+deb8/patches/driver-support-intel-igb-bcm5461X-phy.patch @@ -0,0 +1,280 @@ ++ 0x75diff -urpN a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c +--- a/drivers/net/ethernet/intel/igb/e1000_82575.c 2016-03-02 10:31:21.000000000 +0000 ++++ b/drivers/net/ethernet/intel/igb/e1000_82575.c 2016-09-15 19:55:02.680725611 +0000 +@@ -179,8 +179,11 @@ static s32 igb_init_phy_params_82575(str + ctrl_ext = rd32(E1000_CTRL_EXT); + + if (igb_sgmii_active_82575(hw)) { +- phy->ops.reset = igb_phy_hw_reset_sgmii_82575; +- ctrl_ext |= E1000_CTRL_I2C_ENA; ++ if(phy->type == e1000_phy_bcm5461s) ++ phy->ops.reset = igb_phy_hw_reset; ++ else ++ phy->ops.reset = igb_phy_hw_reset_sgmii_82575; ++ ctrl_ext |= E1000_CTRL_I2C_ENA; + } else { + phy->ops.reset = igb_phy_hw_reset; + ctrl_ext &= ~E1000_CTRL_I2C_ENA; +@@ -286,6 +289,19 @@ static s32 igb_init_phy_params_82575(str + 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_phy_info = igb_get_phy_info_5461s; ++ 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; +@@ -827,9 +843,9 @@ static s32 igb_get_phy_id_82575(struct e + break; + case e1000_82580: + case e1000_i350: +- case e1000_i354: + case e1000_i210: + case e1000_i211: ++ case e1000_i354: + mdic = rd32(E1000_MDICNFG); + mdic &= E1000_MDICNFG_PHY_MASK; + phy->addr = mdic >> E1000_MDICNFG_PHY_SHIFT; +@@ -840,6 +856,17 @@ static s32 igb_get_phy_id_82575(struct e + break; + } + 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; + } + +@@ -1220,6 +1247,9 @@ static s32 igb_get_cfg_done_82575(struct + (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; + } + +@@ -1552,6 +1582,7 @@ static s32 igb_setup_copper_link_82575(s + 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); +@@ -1595,6 +1626,10 @@ static s32 igb_setup_copper_link_82575(s + 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 -urpN a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h +--- a/drivers/net/ethernet/intel/igb/e1000_defines.h 2016-03-02 10:31:21.000000000 +0000 ++++ b/drivers/net/ethernet/intel/igb/e1000_defines.h 2016-09-15 19:55:27.068726140 +0000 +@@ -860,6 +860,8 @@ + #define M88_VENDOR 0x0141 + #define I210_I_PHY_ID 0x01410C00 + #define M88E1543_E_PHY_ID 0x01410EA0 ++#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 -urpN a/drivers/net/ethernet/intel/igb/e1000_hw.h b/drivers/net/ethernet/intel/igb/e1000_hw.h +--- a/drivers/net/ethernet/intel/igb/e1000_hw.h 2016-03-02 10:31:21.000000000 +0000 ++++ b/drivers/net/ethernet/intel/igb/e1000_hw.h 2016-09-15 19:55:44.584726520 +0000 +@@ -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 -urpN a/drivers/net/ethernet/intel/igb/e1000_phy.c b/drivers/net/ethernet/intel/igb/e1000_phy.c +--- a/drivers/net/ethernet/intel/igb/e1000_phy.c 2016-03-02 10:31:21.000000000 +0000 ++++ b/drivers/net/ethernet/intel/igb/e1000_phy.c 2016-09-15 20:07:34.964741935 +0000 +@@ -148,6 +148,14 @@ s32 igb_read_phy_reg_mdic(struct e1000_h + * 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)); +@@ -204,6 +212,14 @@ s32 igb_write_phy_reg_mdic(struct e1000_ + * 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) | +@@ -1115,11 +1131,13 @@ s32 igb_setup_copper_link(struct e1000_h + * depending on user settings. + */ + hw_dbg("Forcing Speed and Duplex\n"); +- ret_val = hw->phy.ops.force_speed_duplex(hw); +- if (ret_val) { ++ 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; +- } ++ } ++ } + } + + /* Check link status. Wait up to 100 microseconds for link to become +@@ -2509,3 +2527,67 @@ static s32 igb_set_master_slave_mode(str + + 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 -urpN a/drivers/net/ethernet/intel/igb/e1000_phy.h b/drivers/net/ethernet/intel/igb/e1000_phy.h +--- a/drivers/net/ethernet/intel/igb/e1000_phy.h 2016-03-02 10:31:21.000000000 +0000 ++++ b/drivers/net/ethernet/intel/igb/e1000_phy.h 2016-09-15 19:41:43.584708271 +0000 +@@ -61,6 +61,8 @@ s32 igb_phy_has_link(struct e1000_hw *h + 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_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data); + s32 igb_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data); + s32 igb_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data); +diff -urpN a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c +--- a/drivers/net/ethernet/intel/igb/igb_main.c 2016-03-02 10:31:21.000000000 +0000 ++++ b/drivers/net/ethernet/intel/igb/igb_main.c 2016-09-15 19:56:53.276728011 +0000 +@@ -108,6 +108,7 @@ static const struct pci_device_id igb_pc + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_COPPER), board_82575 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_FIBER_SERDES), board_82575 }, + { PCI_VDEVICE(INTEL, E1000_DEV_ID_82575GB_QUAD_COPPER), board_82575 }, ++ { PCI_VDEVICE(INTEL, E1000_DEV_ID_I354_SGMII), board_82575 }, + /* required last entry */ + {0, } + }; +@@ -7198,11 +7199,19 @@ static int igb_mii_ioctl(struct net_devi + 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; + } diff --git a/packages/base/any/kernels/3.16+deb8/patches/series b/packages/base/any/kernels/3.16+deb8/patches/series index 64f03b31..a3d4952f 100644 --- a/packages/base/any/kernels/3.16+deb8/patches/series +++ b/packages/base/any/kernels/3.16+deb8/patches/series @@ -11,3 +11,6 @@ driver-hwmon-pmbus-add-dps460-support.patch driver-hwmon-pmbus-ucd9200-mlnx.patch driver-arista-piix4-mux-patch.patch 3.16-fs-overlayfs.patch +driver-support-intel-igb-bcm5461X-phy.patch + +