imx6: drop 4.1 support
[openwrt.git] / target / linux / imx6 / patches-4.1 / 204-net-igb-register-mii_bus-for-SerDes-w-external-phy.patch
diff --git a/target/linux/imx6/patches-4.1/204-net-igb-register-mii_bus-for-SerDes-w-external-phy.patch b/target/linux/imx6/patches-4.1/204-net-igb-register-mii_bus-for-SerDes-w-external-phy.patch
deleted file mode 100644 (file)
index 01768e8..0000000
+++ /dev/null
@@ -1,308 +0,0 @@
-From 03855caf93f7332a3f320228ba1a0e7baae8a749 Mon Sep 17 00:00:00 2001
-From: Tim Harvey <tharvey@gateworks.com>
-Date: Thu, 15 May 2014 12:36:23 -0700
-Subject: [PATCH] net: igb: register mii_bus for SerDes w/ external phy
-
-If an i210 is configured for 1000BASE-BX link_mode and has an external phy
-specified, then register an mii bus using the external phy address as
-a mask.
-
-An i210 hooked to an external standard phy will be configured with a link_mo
-of SGMII in which case phy ops will be configured and used internall in the
-igb driver for link status. However, in certain cases one might be using a
-backplane SerDes connection to something that talks on the mdio bus but is
-not a standard phy, such as a switch. In this case by registering an mdio
-bus a phy driver can manage the device.
-
-Signed-off-by: Tim Harvey <tharvey@gateworks.com>
----
- drivers/net/ethernet/intel/igb/e1000_82575.c |  15 +++
- drivers/net/ethernet/intel/igb/e1000_hw.h    |   7 ++
- drivers/net/ethernet/intel/igb/igb_main.c    | 168 ++++++++++++++++++++++++++-
- 3 files changed, 185 insertions(+), 5 deletions(-)
-
---- a/drivers/net/ethernet/intel/igb/e1000_82575.c
-+++ b/drivers/net/ethernet/intel/igb/e1000_82575.c
-@@ -598,13 +598,25 @@ static s32 igb_get_invariants_82575(stru
-       switch (link_mode) {
-       case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX:
-               hw->phy.media_type = e1000_media_type_internal_serdes;
-+              if (igb_sgmii_uses_mdio_82575(hw)) {
-+                      u32 mdicnfg = rd32(E1000_MDICNFG);
-+                      mdicnfg &= E1000_MDICNFG_PHY_MASK;
-+                      hw->phy.addr = mdicnfg >> E1000_MDICNFG_PHY_SHIFT;
-+                      hw_dbg("1000BASE_KX w/ external MDIO device at 0x%x\n",
-+                             hw->phy.addr);
-+              } else {
-+                      hw_dbg("1000BASE_KX");
-+              }
-               break;
-       case E1000_CTRL_EXT_LINK_MODE_SGMII:
-               /* Get phy control interface type set (MDIO vs. I2C)*/
-               if (igb_sgmii_uses_mdio_82575(hw)) {
-                       hw->phy.media_type = e1000_media_type_copper;
-                       dev_spec->sgmii_active = true;
-+                      hw_dbg("SGMII with external MDIO PHY");
-                       break;
-+              } else {
-+                      hw_dbg("SGMII with external I2C PHY");
-               }
-               /* fall through for I2C based SGMII */
-       case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES:
-@@ -621,8 +633,11 @@ static s32 igb_get_invariants_82575(stru
-                               hw->phy.media_type = e1000_media_type_copper;
-                               dev_spec->sgmii_active = true;
-                       }
-+                      hw_dbg("SERDES with external SFP");
-                       break;
-+              } else {
-+                      hw_dbg("SERDES");
-               }
-               /* do not change link mode for 100BaseFX */
---- a/drivers/net/ethernet/intel/igb/e1000_hw.h
-+++ b/drivers/net/ethernet/intel/igb/e1000_hw.h
-@@ -27,6 +27,7 @@
- #include <linux/delay.h>
- #include <linux/io.h>
- #include <linux/netdevice.h>
-+#include <linux/phy.h>
- #include "e1000_regs.h"
- #include "e1000_defines.h"
-@@ -543,6 +544,12 @@ struct e1000_hw {
-       struct e1000_mbx_info mbx;
-       struct e1000_host_mng_dhcp_cookie mng_cookie;
-+#ifdef CONFIG_PHYLIB
-+      /* Phylib and MDIO interface */
-+      struct mii_bus *mii_bus;
-+      struct phy_device *phy_dev;
-+      phy_interface_t phy_interface;
-+#endif
-       union {
-               struct e1000_dev_spec_82575     _82575;
-       } dev_spec;
---- a/drivers/net/ethernet/intel/igb/igb_main.c
-+++ b/drivers/net/ethernet/intel/igb/igb_main.c
-@@ -41,6 +41,7 @@
- #include <linux/if_vlan.h>
- #include <linux/pci.h>
- #include <linux/pci-aspm.h>
-+#include <linux/phy.h>
- #include <linux/delay.h>
- #include <linux/interrupt.h>
- #include <linux/ip.h>
-@@ -2234,6 +2235,126 @@ static s32 igb_init_i2c(struct igb_adapt
-       return status;
- }
-+
-+#ifdef CONFIG_PHYLIB
-+/*
-+ * MMIO/PHYdev support
-+ */
-+
-+static int igb_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
-+{
-+      struct e1000_hw *hw = bus->priv;
-+      u16 out;
-+      int err;
-+
-+      err = igb_read_reg_gs40g(hw, mii_id, regnum, &out);
-+      if (err)
-+              return err;
-+      return out;
-+}
-+
-+static int igb_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
-+                               u16 val)
-+{
-+      struct e1000_hw *hw = bus->priv;
-+
-+      return igb_write_reg_gs40g(hw, mii_id, regnum, val);
-+}
-+
-+static int igb_enet_mdio_reset(struct mii_bus *bus)
-+{
-+      udelay(300);
-+      return 0;
-+}
-+
-+static void igb_enet_mii_link(struct net_device *netdev)
-+{
-+}
-+
-+/* Probe the mdio bus for phys and connect them */
-+static int igb_enet_mii_probe(struct net_device *netdev)
-+{
-+      struct igb_adapter *adapter = netdev_priv(netdev);
-+      struct e1000_hw *hw = &adapter->hw;
-+      struct phy_device *phy_dev = NULL;
-+      int phy_id;
-+
-+      /* check for attached phy */
-+      for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) {
-+              if (hw->mii_bus->phy_map[phy_id]) {
-+                      phy_dev = hw->mii_bus->phy_map[phy_id];
-+                      break;
-+              }
-+      }
-+      if (!phy_dev) {
-+              netdev_err(netdev, "no PHY found\n");
-+              return -ENODEV;
-+      }
-+
-+      hw->phy_interface = PHY_INTERFACE_MODE_RGMII;
-+      phy_dev = phy_connect(netdev, dev_name(&phy_dev->dev),
-+                            igb_enet_mii_link, hw->phy_interface);
-+      if (IS_ERR(phy_dev)) {
-+              netdev_err(netdev, "could not attach to PHY\n");
-+              return PTR_ERR(phy_dev);
-+      }
-+
-+      hw->phy_dev = phy_dev;
-+      netdev_info(netdev, "igb PHY driver [%s] (mii_bus:phy_addr=%s)\n",
-+              hw->phy_dev->drv->name, dev_name(&hw->phy_dev->dev));
-+
-+      return 0;
-+}
-+
-+/* Create and register mdio bus */
-+static int igb_enet_mii_init(struct pci_dev *pdev)
-+{
-+      struct mii_bus *mii_bus;
-+      struct net_device *netdev = pci_get_drvdata(pdev);
-+      struct igb_adapter *adapter = netdev_priv(netdev);
-+      struct e1000_hw *hw = &adapter->hw;
-+      int err;
-+
-+      mii_bus = mdiobus_alloc();
-+      if (mii_bus == NULL) {
-+              err = -ENOMEM;
-+              goto err_out;
-+      }
-+
-+      mii_bus->name = "igb_enet_mii_bus";
-+      mii_bus->read = igb_enet_mdio_read;
-+      mii_bus->write = igb_enet_mdio_write;
-+      mii_bus->reset = igb_enet_mdio_reset;
-+      snprintf(mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
-+               pci_name(pdev), hw->device_id + 1);
-+      mii_bus->priv = hw;
-+      mii_bus->parent = &pdev->dev;
-+      mii_bus->phy_mask = ~(1 << hw->phy.addr);
-+
-+      err = mdiobus_register(mii_bus);
-+      if (err) {
-+              printk(KERN_ERR "failed to register mii_bus: %d\n", err);
-+              goto err_out_free_mdiobus;
-+      }
-+      hw->mii_bus = mii_bus;
-+
-+      return 0;
-+
-+err_out_free_mdiobus:
-+      mdiobus_free(mii_bus);
-+err_out:
-+      return err;
-+}
-+
-+static void igb_enet_mii_remove(struct e1000_hw *hw)
-+{
-+      if (hw->mii_bus) {
-+              mdiobus_unregister(hw->mii_bus);
-+              mdiobus_free(hw->mii_bus);
-+      }
-+}
-+#endif /* CONFIG_PHYLIB */
-+
- /**
-  *  igb_probe - Device Initialization Routine
-  *  @pdev: PCI device information struct
-@@ -2656,6 +2777,13 @@ static int igb_probe(struct pci_dev *pde
-               }
-       }
-       pm_runtime_put_noidle(&pdev->dev);
-+
-+#ifdef CONFIG_PHYLIB
-+      /* create and register the mdio bus if using ext phy */
-+      if (rd32(E1000_MDICNFG) & E1000_MDICNFG_EXT_MDIO)
-+              igb_enet_mii_init(pdev);
-+#endif
-+
-       return 0;
- err_register:
-@@ -2799,6 +2927,10 @@ static void igb_remove(struct pci_dev *p
-       struct e1000_hw *hw = &adapter->hw;
-       pm_runtime_get_noresume(&pdev->dev);
-+#ifdef CONFIG_PHYLIB
-+      if (rd32(E1000_MDICNFG) & E1000_MDICNFG_EXT_MDIO)
-+              igb_enet_mii_remove(hw);
-+#endif
- #ifdef CONFIG_IGB_HWMON
-       igb_sysfs_exit(adapter);
- #endif
-@@ -3112,6 +3244,12 @@ static int __igb_open(struct net_device
-       if (!resuming)
-               pm_runtime_put(&pdev->dev);
-+#ifdef CONFIG_PHYLIB
-+      /* Probe and connect to PHY if using ext phy */
-+      if (rd32(E1000_MDICNFG) & E1000_MDICNFG_EXT_MDIO)
-+              igb_enet_mii_probe(netdev);
-+#endif
-+
-       /* start the watchdog. */
-       hw->mac.get_link_status = 1;
-       schedule_work(&adapter->watchdog_task);
-@@ -7146,21 +7284,41 @@ void igb_alloc_rx_buffers(struct igb_rin
- static int igb_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
- {
-       struct igb_adapter *adapter = netdev_priv(netdev);
-+      struct e1000_hw *hw = &adapter->hw;
-       struct mii_ioctl_data *data = if_mii(ifr);
--      if (adapter->hw.phy.media_type != e1000_media_type_copper)
-+      if (adapter->hw.phy.media_type != e1000_media_type_copper &&
-+          !(rd32(E1000_MDICNFG) & E1000_MDICNFG_EXT_MDIO))
-               return -EOPNOTSUPP;
-       switch (cmd) {
-       case SIOCGMIIPHY:
--              data->phy_id = adapter->hw.phy.addr;
-+              data->phy_id = hw->phy.addr;
-               break;
-       case SIOCGMIIREG:
--              if (igb_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
--                                   &data->val_out))
--                      return -EIO;
-+              if (hw->mac.type == e1000_i210 || hw->mac.type == e1000_i211) {
-+                      if (igb_read_reg_gs40g(&adapter->hw, data->phy_id,
-+                                             data->reg_num & 0x1F,
-+                                             &data->val_out))
-+                              return -EIO;
-+              } else {
-+                      if (igb_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
-+                                           &data->val_out))
-+                              return -EIO;
-+              }
-               break;
-       case SIOCSMIIREG:
-+              if (hw->mac.type == e1000_i210 || hw->mac.type == e1000_i211) {
-+                      if (igb_write_reg_gs40g(hw, data->phy_id,
-+                                              data->reg_num & 0x1F,
-+                                              data->val_in))
-+                              return -EIO;
-+              } else {
-+                      if (igb_write_phy_reg(hw, data->reg_num & 0x1F,
-+                                            data->val_in))
-+                              return -EIO;
-+              }
-+              break;
-       default:
-               return -EOPNOTSUPP;
-       }