aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/sysdev/fsl_soc.c26
-rw-r--r--drivers/net/gianfar.c7
-rw-r--r--drivers/net/gianfar_mii.c21
-rw-r--r--drivers/net/gianfar_mii.h3
-rw-r--r--include/linux/fsl_devices.h3
5 files changed, 59 insertions, 1 deletions
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 01b884b25696..26ecb96f9731 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -223,6 +223,8 @@ static int gfar_mdio_of_init_one(struct device_node *np)
223 if (ret) 223 if (ret)
224 return ret; 224 return ret;
225 225
226 /* The gianfar device will try to use the same ID created below to find
227 * this bus, to coordinate register access (since they share). */
226 mdio_dev = platform_device_register_simple("fsl-gianfar_mdio", 228 mdio_dev = platform_device_register_simple("fsl-gianfar_mdio",
227 res.start&0xfffff, &res, 1); 229 res.start&0xfffff, &res, 1);
228 if (IS_ERR(mdio_dev)) 230 if (IS_ERR(mdio_dev))
@@ -394,6 +396,30 @@ static int __init gfar_of_init(void)
394 of_node_put(mdio); 396 of_node_put(mdio);
395 } 397 }
396 398
399 /* Get MDIO bus controlled by this eTSEC, if any. Normally only
400 * eTSEC 1 will control an MDIO bus, not necessarily the same
401 * bus that its PHY is on ('mdio' above), so we can't just use
402 * that. What we do is look for a gianfar mdio device that has
403 * overlapping registers with this device. That's really the
404 * whole point, to find the device sharing our registers to
405 * coordinate access with it.
406 */
407 for_each_compatible_node(mdio, NULL, "fsl,gianfar-mdio") {
408 if (of_address_to_resource(mdio, 0, &res))
409 continue;
410
411 if (res.start >= r[0].start && res.end <= r[0].end) {
412 /* Get the ID the mdio bus platform device was
413 * registered with. gfar_data.bus_id is
414 * different because it's for finding a PHY,
415 * while this is for finding a MII bus.
416 */
417 gfar_data.mdio_bus = res.start&0xfffff;
418 of_node_put(mdio);
419 break;
420 }
421 }
422
397 ret = 423 ret =
398 platform_device_add_data(gfar_dev, &gfar_data, 424 platform_device_add_data(gfar_dev, &gfar_data,
399 sizeof(struct 425 sizeof(struct
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 64b201134fdb..249541a1814b 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -586,6 +586,10 @@ static void gfar_configure_serdes(struct net_device *dev)
586 struct gfar_mii __iomem *regs = 586 struct gfar_mii __iomem *regs =
587 (void __iomem *)&priv->regs->gfar_mii_regs; 587 (void __iomem *)&priv->regs->gfar_mii_regs;
588 int tbipa = gfar_read(&priv->regs->tbipa); 588 int tbipa = gfar_read(&priv->regs->tbipa);
589 struct mii_bus *bus = gfar_get_miibus(priv);
590
591 if (bus)
592 mutex_lock(&bus->mdio_lock);
589 593
590 /* Single clk mode, mii mode off(for serdes communication) */ 594 /* Single clk mode, mii mode off(for serdes communication) */
591 gfar_local_mdio_write(regs, tbipa, MII_TBICON, TBICON_CLK_SELECT); 595 gfar_local_mdio_write(regs, tbipa, MII_TBICON, TBICON_CLK_SELECT);
@@ -596,6 +600,9 @@ static void gfar_configure_serdes(struct net_device *dev)
596 600
597 gfar_local_mdio_write(regs, tbipa, MII_BMCR, BMCR_ANENABLE | 601 gfar_local_mdio_write(regs, tbipa, MII_BMCR, BMCR_ANENABLE |
598 BMCR_ANRESTART | BMCR_FULLDPLX | BMCR_SPEED1000); 602 BMCR_ANRESTART | BMCR_FULLDPLX | BMCR_SPEED1000);
603
604 if (bus)
605 mutex_unlock(&bus->mdio_lock);
599} 606}
600 607
601static void init_registers(struct net_device *dev) 608static void init_registers(struct net_device *dev)
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c
index bf73eea98010..0e2595d24933 100644
--- a/drivers/net/gianfar_mii.c
+++ b/drivers/net/gianfar_mii.c
@@ -269,6 +269,27 @@ static struct device_driver gianfar_mdio_driver = {
269 .remove = gfar_mdio_remove, 269 .remove = gfar_mdio_remove,
270}; 270};
271 271
272static int match_mdio_bus(struct device *dev, void *data)
273{
274 const struct gfar_private *priv = data;
275 const struct platform_device *pdev = to_platform_device(dev);
276
277 return !strcmp(pdev->name, gianfar_mdio_driver.name) &&
278 pdev->id == priv->einfo->mdio_bus;
279}
280
281/* Given a gfar_priv structure, find the mii_bus controlled by this device (not
282 * necessarily the same as the bus the gfar's PHY is on), if one exists.
283 * Normally only the first gianfar controls a mii_bus. */
284struct mii_bus *gfar_get_miibus(const struct gfar_private *priv)
285{
286 /*const*/ struct device *d;
287
288 d = bus_find_device(gianfar_mdio_driver.bus, NULL, (void *)priv,
289 match_mdio_bus);
290 return d ? dev_get_drvdata(d) : NULL;
291}
292
272int __init gfar_mdio_init(void) 293int __init gfar_mdio_init(void)
273{ 294{
274 return driver_register(&gianfar_mdio_driver); 295 return driver_register(&gianfar_mdio_driver);
diff --git a/drivers/net/gianfar_mii.h b/drivers/net/gianfar_mii.h
index 2af28b16a0e2..02dc970ca1ff 100644
--- a/drivers/net/gianfar_mii.h
+++ b/drivers/net/gianfar_mii.h
@@ -18,6 +18,8 @@
18#ifndef __GIANFAR_MII_H 18#ifndef __GIANFAR_MII_H
19#define __GIANFAR_MII_H 19#define __GIANFAR_MII_H
20 20
21struct gfar_private; /* forward ref */
22
21#define MIIMIND_BUSY 0x00000001 23#define MIIMIND_BUSY 0x00000001
22#define MIIMIND_NOTVALID 0x00000004 24#define MIIMIND_NOTVALID 0x00000004
23 25
@@ -44,6 +46,7 @@ int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value);
44int gfar_local_mdio_write(struct gfar_mii __iomem *regs, int mii_id, 46int gfar_local_mdio_write(struct gfar_mii __iomem *regs, int mii_id,
45 int regnum, u16 value); 47 int regnum, u16 value);
46int gfar_local_mdio_read(struct gfar_mii __iomem *regs, int mii_id, int regnum); 48int gfar_local_mdio_read(struct gfar_mii __iomem *regs, int mii_id, int regnum);
49struct mii_bus *gfar_get_miibus(const struct gfar_private *priv);
47int __init gfar_mdio_init(void); 50int __init gfar_mdio_init(void);
48void gfar_mdio_exit(void); 51void gfar_mdio_exit(void);
49#endif /* GIANFAR_PHY_H */ 52#endif /* GIANFAR_PHY_H */
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index 4e625e0094c8..708bab58d8d0 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -49,7 +49,8 @@ struct gianfar_platform_data {
49 u32 device_flags; 49 u32 device_flags;
50 /* board specific information */ 50 /* board specific information */
51 u32 board_flags; 51 u32 board_flags;
52 char bus_id[MII_BUS_ID_SIZE]; 52 int mdio_bus; /* Bus controlled by us */
53 char bus_id[MII_BUS_ID_SIZE]; /* Bus PHY is on */
53 u32 phy_id; 54 u32 phy_id;
54 u8 mac_addr[6]; 55 u8 mac_addr[6];
55 phy_interface_t interface; 56 phy_interface_t interface;