ramips: fix MDIO/PHY handling
authorGabor Juhos <juhosg@openwrt.org>
Mon, 8 Apr 2013 11:12:01 +0000 (11:12 +0000)
committerGabor Juhos <juhosg@openwrt.org>
Mon, 8 Apr 2013 11:12:01 +0000 (11:12 +0000)
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
SVN-Revision: 36271

target/linux/ramips/patches-3.8/0132-NET-ramips-fix-mdio-bus-support.patch [new file with mode: 0644]

diff --git a/target/linux/ramips/patches-3.8/0132-NET-ramips-fix-mdio-bus-support.patch b/target/linux/ramips/patches-3.8/0132-NET-ramips-fix-mdio-bus-support.patch
new file mode 100644 (file)
index 0000000..eb7badf
--- /dev/null
@@ -0,0 +1,222 @@
+--- a/drivers/net/ethernet/ramips/ramips_main.c
++++ b/drivers/net/ethernet/ramips/ramips_main.c
+@@ -28,6 +28,7 @@
+ #include <linux/of_device.h>
+ #include <linux/clk.h>
+ #include <linux/of_net.h>
++#include <linux/of_mdio.h>
+ #include "ramips_eth.h"
+@@ -406,12 +407,25 @@ ramips_mdio_reset(struct mii_bus *bus)
+ static int
+ ramips_mdio_init(struct raeth_priv *re)
+ {
++      struct device_node *mii_np;
+       int err;
+-      int i;
++
++      mii_np = of_get_child_by_name(re->of_node, "mdio-bus");
++      if (!mii_np) {
++              dev_err(re->parent, "no %s child node found", "mdio-bus");
++              return -ENODEV;
++      }
++
++      if (!of_device_is_available(mii_np)) {
++              err = 0;
++              goto err_put_node;
++      }
+       re->mii_bus = mdiobus_alloc();
+-      if (re->mii_bus == NULL)
+-              return -ENOMEM;
++      if (re->mii_bus == NULL) {
++              err = -ENOMEM;
++              goto err_put_node;
++      }
+       re->mii_bus->name = "ramips_mdio";
+       re->mii_bus->read = ramips_mdio_read;
+@@ -422,12 +436,7 @@ ramips_mdio_init(struct raeth_priv *re)
+       re->mii_bus->parent = re->parent;
+       snprintf(re->mii_bus->id, MII_BUS_ID_SIZE, "%s", "ramips_mdio");
+-      re->mii_bus->phy_mask = 0;
+-
+-      for (i = 0; i < PHY_MAX_ADDR; i++)
+-              re->mii_irq[i] = PHY_POLL;
+-
+-      err = mdiobus_register(re->mii_bus);
++      err = of_mdiobus_register(re->mii_bus, mii_np);
+       if (err)
+               goto err_free_bus;
+@@ -435,13 +444,20 @@ ramips_mdio_init(struct raeth_priv *re)
+ err_free_bus:
+       kfree(re->mii_bus);
++err_put_node:
++      of_node_put(mii_np);
++      re->mii_bus = NULL;
+       return err;
+ }
+ static void
+ ramips_mdio_cleanup(struct raeth_priv *re)
+ {
++      if (!re->mii_bus)
++              return;
++
+       mdiobus_unregister(re->mii_bus);
++      of_node_put(re->mii_bus->dev.of_node);
+       kfree(re->mii_bus);
+ }
+@@ -474,106 +490,86 @@ ramips_phy_link_adjust(struct net_device
+ }
+ static int
+-ramips_phy_connect_multi(struct raeth_priv *re)
++ramips_phy_connect_by_node(struct raeth_priv *re, struct device_node *phy_node)
+ {
+-      struct net_device *netdev = re->netdev;
+-      struct phy_device *phydev = NULL;
+-      int phy_addr;
+-      int ret = 0;
+-
+-      for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
+-              if (!(re->phy_mask & (1 << phy_addr)))
+-                      continue;
+-
+-              if (re->mii_bus->phy_map[phy_addr] == NULL)
+-                      continue;
++      struct phy_device *phydev;
++      int phy_mode;
+-              RADEBUG("%s: PHY found at %s, uid=%08x\n",
+-                      netdev->name,
+-                      dev_name(&re->mii_bus->phy_map[phy_addr]->dev),
+-                      re->mii_bus->phy_map[phy_addr]->phy_id);
+-
+-              if (phydev == NULL)
+-                      phydev = re->mii_bus->phy_map[phy_addr];
+-      }
+-
+-      if (!phydev) {
+-              netdev_err(netdev, "no PHY found with phy_mask=%08x\n",
+-                         re->phy_mask);
+-              return -ENODEV;
++      phy_mode = of_get_phy_mode(re->of_node);
++      if (phy_mode < 0) {
++              dev_err(re->parent, "incorrect phy-mode\n");
++              return -EINVAL;
+       }
+-      re->phy_dev = phy_connect(netdev, dev_name(&phydev->dev),
+-                                ramips_phy_link_adjust, 0, re->phy_if_mode);
+-
+-      if (IS_ERR(re->phy_dev)) {
+-              netdev_err(netdev, "could not connect to PHY at %s\n",
+-                         dev_name(&phydev->dev));
++      phydev = of_phy_connect(re->netdev, phy_node, ramips_phy_link_adjust,
++                              0, phy_mode);
++      if (IS_ERR(phydev)) {
++              dev_err(re->parent, "could not connect to PHY\n");
+               return PTR_ERR(re->phy_dev);
+       }
+       phydev->supported &= PHY_GBIT_FEATURES;
+       phydev->advertising = phydev->supported;
+-      RADEBUG("%s: connected to PHY at %s [uid=%08x, driver=%s]\n",
+-              netdev->name, dev_name(&phydev->dev),
+-              phydev->phy_id, phydev->drv->name);
++      dev_info(re->parent,
++               "connected to PHY at %s [uid=%08x, driver=%s]\n",
++               dev_name(&phydev->dev), phydev->phy_id,
++               phydev->drv->name);
++      re->phy_dev = phydev;
+       re->link = 0;
+       re->speed = 0;
+       re->duplex = -1;
+       re->rx_fc = 0;
+       re->tx_fc = 0;
+-      return ret;
++      return 0;
+ }
+ static int
+-ramips_phy_connect_fixed(struct raeth_priv *re)
++ramips_phy_connect_fixed(struct raeth_priv *re, const __be32 *link, int size)
+ {
+-      if (!re->speed) {
+-              const __be32 *link;
+-              int size;
+-
+-              link = of_get_property(re->of_node,
+-                                      "ralink,fixed-link", &size);
+-              if (!link || size != (4 * sizeof(*link)))
+-                      return -ENOENT;
+-
+-              re->speed = be32_to_cpup(link++);
+-              re->duplex = be32_to_cpup(link++);
+-              re->tx_fc = be32_to_cpup(link++);
+-              re->rx_fc = be32_to_cpup(link++);
++      if (size != (4 * sizeof(*link))) {
++              dev_err(re->parent, "invalid fixed-link property\n");
++              return -EINVAL;
+       }
++      re->speed = be32_to_cpup(link++);
++      re->duplex = be32_to_cpup(link++);
++      re->tx_fc = be32_to_cpup(link++);
++      re->rx_fc = be32_to_cpup(link++);
++
+       switch (re->speed) {
+       case SPEED_10:
+       case SPEED_100:
+       case SPEED_1000:
+               break;
+       default:
+-              netdev_err(re->netdev, "invalid speed specified\n");
++              dev_err(re->parent, "invalid link speed: %d\n", re->speed);
+               return -EINVAL;
+       }
+-      pr_info("%s: using fixed link parameters\n", re->netdev->name);
++      dev_info(re->parent, "using fixed link parameters\n");
+       return 0;
+ }
+ static int
+ ramips_phy_connect(struct raeth_priv *re)
+ {
+-      const __be32 *mask;
+-
+-      mask = of_get_property(re->of_node, "ralink,phy-mask", NULL);
+-      re->phy_if_mode = of_get_phy_mode(re->of_node);
+-
+-      if (!re->phy_if_mode || !mask)
+-              return ramips_phy_connect_fixed(re);
+-
+-      re->phy_mask = be32_to_cpup(mask);
+-      return ramips_phy_connect_multi(re);
++      struct device_node *phy_node;
++      const __be32 *p32;
++      int size;
++
++      phy_node = of_parse_phandle(re->of_node, "phy-handle", 0);
++      if (phy_node)
++              return ramips_phy_connect_by_node(re, phy_node);
++
++      p32 = of_get_property(re->of_node, "ralink,fixed-link", &size);
++      if (p32)
++              return ramips_phy_connect_fixed(re, p32, size);
++      dev_err(re->parent, "unable to get connection type\n");
++      return -EINVAL;
+ }
+ static void