[PATCH 5/5] gianfar: don't hard code the TBIPA MDIO address

Paul Gortmaker paul.gortmaker at windriver.com
Fri Apr 11 03:52:02 EST 2008


Currently the MDIO address for the gianfar Ten Bit
Interface is hard coded to be 0x1f, which can conflit
with some boards if they happen to put a PHY there.

Previous discussions indicated that the proper approach
here would be to dynamically allocate it, based on
picking the highest MDIO address that is not in use
by a PHY.

Signed-off-by: Paul Gortmaker <paul.gortmaker at windriver.com>
---
 drivers/net/gianfar.c       |   20 ++++++++++++++++----
 drivers/net/gianfar.h       |    1 -
 drivers/net/gianfar_mii.c   |   11 ++++++++++-
 include/linux/fsl_devices.h |    1 +
 4 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 9173784..684c97b 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -123,6 +123,7 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id);
 static irqreturn_t gfar_interrupt(int irq, void *dev_id);
 static void adjust_link(struct net_device *dev);
 static void init_registers(struct net_device *dev);
+static void gfar_set_tbipa(struct net_device *dev);
 static int init_phy(struct net_device *dev);
 static int gfar_probe(struct platform_device *pdev);
 static int gfar_remove(struct platform_device *pdev);
@@ -469,6 +470,8 @@ static int init_phy(struct net_device *dev)
 	priv->mii_bus = phydev->bus;
 	priv->phydev = phydev;
 
+	gfar_set_tbipa(dev);
+
 	if (interface == PHY_INTERFACE_MODE_SGMII)
 		gfar_configure_serdes(dev);
 
@@ -479,19 +482,20 @@ static void gfar_configure_serdes(struct net_device *dev)
 {
 	struct gfar_private *priv = netdev_priv(dev);
 	struct mii_bus *bus = priv->mii_bus;
+	struct gianfar_mdio_data *mdata = (struct gianfar_mdio_data *)bus->priv;
 
 	/* Initialise TBI i/f to communicate with serdes (lynx phy) */
 
 	/* Single clk mode, mii mode off(for aerdes communication) */
-	gfar_mdio_write(bus, TBIPA_VALUE, MII_TBICON, TBICON_CLK_SELECT);
+	gfar_mdio_write(bus, mdata->tbi_pa, MII_TBICON, TBICON_CLK_SELECT);
 
 	/* Supported pause and full-duplex, no half-duplex */
-	gfar_mdio_write(bus, TBIPA_VALUE, MII_ADVERTISE,
+	gfar_mdio_write(bus, mdata->tbi_pa, MII_ADVERTISE,
 			ADVERTISE_1000XFULL | ADVERTISE_1000XPAUSE |
 			ADVERTISE_1000XPSE_ASYM);
 
 	/* ANEG enable, restart ANEG, full duplex mode, speed[1] set */
-	gfar_mdio_write(bus, TBIPA_VALUE, MII_BMCR, BMCR_ANENABLE |
+	gfar_mdio_write(bus, mdata->tbi_pa, MII_BMCR, BMCR_ANENABLE |
 			BMCR_ANRESTART | BMCR_FULLDPLX | BMCR_SPEED1000);
 }
 
@@ -539,8 +543,16 @@ static void init_registers(struct net_device *dev)
 	/* Initialize the Minimum Frame Length Register */
 	gfar_write(&priv->regs->minflr, MINFLR_INIT_SETTINGS);
 
+}
+
+static void gfar_set_tbipa(struct net_device *dev)
+{
+	struct gfar_private *priv = netdev_priv(dev);
+	struct mii_bus *bus = priv->mii_bus;
+	struct gianfar_mdio_data *mdata = (struct gianfar_mdio_data *)bus->priv;
+
 	/* Assign the TBI an address which won't conflict with the PHYs */
-	gfar_write(&priv->regs->tbipa, TBIPA_VALUE);
+	gfar_write(&priv->regs->tbipa, mdata->tbi_pa);
 }
 
 
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index 46cd773..771aa5e 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -130,7 +130,6 @@ extern const char gfar_driver_version[];
 #define DEFAULT_RXCOUNT	16
 #define DEFAULT_RXTIME	4
 
-#define TBIPA_VALUE		0x1f
 #define MIIMCFG_INIT_VALUE	0x00000007
 #define MIIMCFG_RESET           0x80000000
 #define MIIMIND_BUSY            0x00000001
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c
index 806df3f..41ff8c4 100644
--- a/drivers/net/gianfar_mii.c
+++ b/drivers/net/gianfar_mii.c
@@ -160,7 +160,7 @@ int gfar_mdio_probe(struct device *dev)
 	struct gfar_mii __iomem *regs;
 	struct mii_bus *new_bus;
 	struct resource *r;
-	int err = 0;
+	int i, err = 0;
 
 	if (NULL == dev)
 		return -EINVAL;
@@ -209,6 +209,15 @@ int gfar_mdio_probe(struct device *dev)
 		goto bus_register_fail;
 	}
 
+	/* mdiobus_register has populated the phy_map, so we now know
+ 	   which doghouses have wild dogs living in them.  Search
+	   backwards for the 1st vacant one for the Ten Bit Interface */
+	for (i = PHY_MAX_ADDR - 1; i >= 0; i--)
+		if (new_bus->phy_map[i] == NULL) break;
+
+	printk(KERN_INFO "Gianfar MDIO: using ID 0x%x for TBIPA\n", i);
+	pdata->tbi_pa = i;
+
 	return 0;
 
 bus_register_fail:
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index 4b304b6..285bd80 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -60,6 +60,7 @@ struct gianfar_mdio_data {
 	/* board specific information */
 	struct	gfar_mii __iomem *regs;
 	int	irq[32];
+	int	tbi_pa;
 };
 
 /* Flags related to gianfar device features */
-- 
1.5.4.3




More information about the Linuxppc-dev mailing list