From: Gabor Juhos Date: Mon, 8 Apr 2013 11:12:01 +0000 (+0000) Subject: ramips: fix MDIO/PHY handling X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=78ee80f2e86d9fd167a26256115c8cb9f5f58d53;p=openwrt%2Fstaging%2Fldir.git ramips: fix MDIO/PHY handling Signed-off-by: Gabor Juhos SVN-Revision: 36271 --- 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 + #include + #include ++#include + + #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