diff options
Diffstat (limited to 'target/linux')
| -rw-r--r-- | target/linux/ramips/patches-3.8/0132-NET-ramips-fix-mdio-bus-support.patch | 222 | 
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 000000000..eb7badfd5 --- /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 | 
