mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-19 21:58:04 +00:00
ramips: fix MDIO/PHY handling
Signed-off-by: Gabor Juhos <juhosg@openwrt.org> SVN-Revision: 36271
This commit is contained in:
parent
30e5bae84a
commit
78ee80f2e8
@ -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
|
Loading…
Reference in New Issue
Block a user