diff options
Diffstat (limited to 'drivers/net/fec_mpc52xx_phy.c')
-rw-r--r-- | drivers/net/fec_mpc52xx_phy.c | 60 |
1 files changed, 23 insertions, 37 deletions
diff --git a/drivers/net/fec_mpc52xx_phy.c b/drivers/net/fec_mpc52xx_phy.c index 08e18bcb970f..dd9bfa42ac34 100644 --- a/drivers/net/fec_mpc52xx_phy.c +++ b/drivers/net/fec_mpc52xx_phy.c @@ -2,6 +2,7 @@ * Driver for the MPC5200 Fast Ethernet Controller - MDIO bus driver * * Copyright (C) 2007 Domen Puncer, Telargo, Inc. + * Copyright (C) 2008 Wolfram Sang, Pengutronix * * This file is licensed under the terms of the GNU General Public License * version 2. This program is licensed "as is" without any warranty of any @@ -21,58 +22,45 @@ struct mpc52xx_fec_mdio_priv { struct mpc52xx_fec __iomem *regs; }; -static int mpc52xx_fec_mdio_read(struct mii_bus *bus, int phy_id, int reg) +static int mpc52xx_fec_mdio_transfer(struct mii_bus *bus, int phy_id, + int reg, u32 value) { struct mpc52xx_fec_mdio_priv *priv = bus->priv; struct mpc52xx_fec __iomem *fec; int tries = 100; - u32 request = FEC_MII_READ_FRAME; + + value |= (phy_id << FEC_MII_DATA_PA_SHIFT) & FEC_MII_DATA_PA_MSK; + value |= (reg << FEC_MII_DATA_RA_SHIFT) & FEC_MII_DATA_RA_MSK; fec = priv->regs; out_be32(&fec->ievent, FEC_IEVENT_MII); - - request |= (phy_id << FEC_MII_DATA_PA_SHIFT) & FEC_MII_DATA_PA_MSK; - request |= (reg << FEC_MII_DATA_RA_SHIFT) & FEC_MII_DATA_RA_MSK; - - out_be32(&priv->regs->mii_data, request); + out_be32(&priv->regs->mii_data, value); /* wait for it to finish, this takes about 23 us on lite5200b */ while (!(in_be32(&fec->ievent) & FEC_IEVENT_MII) && --tries) udelay(5); - if (tries == 0) + if (!tries) return -ETIMEDOUT; - return in_be32(&priv->regs->mii_data) & FEC_MII_DATA_DATAMSK; + return value & FEC_MII_DATA_OP_RD ? + in_be32(&priv->regs->mii_data) & FEC_MII_DATA_DATAMSK : 0; } -static int mpc52xx_fec_mdio_write(struct mii_bus *bus, int phy_id, int reg, u16 data) +static int mpc52xx_fec_mdio_read(struct mii_bus *bus, int phy_id, int reg) { - struct mpc52xx_fec_mdio_priv *priv = bus->priv; - struct mpc52xx_fec __iomem *fec; - u32 value = data; - int tries = 100; - - fec = priv->regs; - out_be32(&fec->ievent, FEC_IEVENT_MII); - - value |= FEC_MII_WRITE_FRAME; - value |= (phy_id << FEC_MII_DATA_PA_SHIFT) & FEC_MII_DATA_PA_MSK; - value |= (reg << FEC_MII_DATA_RA_SHIFT) & FEC_MII_DATA_RA_MSK; - - out_be32(&priv->regs->mii_data, value); - - /* wait for request to finish */ - while (!(in_be32(&fec->ievent) & FEC_IEVENT_MII) && --tries) - udelay(5); - - if (tries == 0) - return -ETIMEDOUT; + return mpc52xx_fec_mdio_transfer(bus, phy_id, reg, FEC_MII_READ_FRAME); +} - return 0; +static int mpc52xx_fec_mdio_write(struct mii_bus *bus, int phy_id, int reg, + u16 data) +{ + return mpc52xx_fec_mdio_transfer(bus, phy_id, reg, + data | FEC_MII_WRITE_FRAME); } -static int mpc52xx_fec_mdio_probe(struct of_device *of, const struct of_device_id *match) +static int mpc52xx_fec_mdio_probe(struct of_device *of, + const struct of_device_id *match) { struct device *dev = &of->dev; struct device_node *np = of->node; @@ -131,10 +119,8 @@ static int mpc52xx_fec_mdio_probe(struct of_device *of, const struct of_device_i dev_set_drvdata(dev, bus); /* set MII speed */ - out_be32(&priv->regs->mii_speed, ((mpc52xx_find_ipb_freq(of->node) >> 20) / 5) << 1); - - /* enable MII interrupt */ - out_be32(&priv->regs->imask, in_be32(&priv->regs->imask) | FEC_IMASK_MII); + out_be32(&priv->regs->mii_speed, + ((mpc52xx_find_ipb_freq(of->node) >> 20) / 5) << 1); err = mdiobus_register(bus); if (err) @@ -167,7 +153,7 @@ static int mpc52xx_fec_mdio_remove(struct of_device *of) iounmap(priv->regs); for (i=0; i<PHY_MAX_ADDR; i++) - if (bus->irq[i]) + if (bus->irq[i] != PHY_POLL) irq_dispose_mapping(bus->irq[i]); kfree(priv); kfree(bus->irq); |