summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjuhosg <juhosg@3c298f89-4303-0410-b956-a3cf2f4a3e73>2013-04-08 11:12:01 +0000
committerjuhosg <juhosg@3c298f89-4303-0410-b956-a3cf2f4a3e73>2013-04-08 11:12:01 +0000
commitac2214d6d1db2ba55091f031769ec8d8eb2f441d (patch)
treec8f519c29fa63e6d2629321c231ff682a37c9d56
parentc9e4dfb65d5f7458c9e4caccb778bd0d1cd8f355 (diff)
ramips: fix MDIO/PHY handling
Signed-off-by: Gabor Juhos <juhosg@openwrt.org> git-svn-id: svn://svn.openwrt.org/openwrt/trunk@36271 3c298f89-4303-0410-b956-a3cf2f4a3e73
-rw-r--r--target/linux/ramips/patches-3.8/0132-NET-ramips-fix-mdio-bus-support.patch222
1 files changed, 222 insertions, 0 deletions
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
index 0000000000..eb7badfd52
--- /dev/null
+++ b/target/linux/ramips/patches-3.8/0132-NET-ramips-fix-mdio-bus-support.patch
@@ -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