diff options
Diffstat (limited to 'drivers/net/fec_mpc52xx_phy.c')
-rw-r--r-- | drivers/net/fec_mpc52xx_phy.c | 55 |
1 files changed, 22 insertions, 33 deletions
diff --git a/drivers/net/fec_mpc52xx_phy.c b/drivers/net/fec_mpc52xx_phy.c index 08e18bcb970f..45dd9bdc5d62 100644 --- a/drivers/net/fec_mpc52xx_phy.c +++ b/drivers/net/fec_mpc52xx_phy.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * Driver for the MPC5200 Fast Ethernet Controller - MDIO bus driver | 2 | * Driver for the MPC5200 Fast Ethernet Controller - MDIO bus driver |
3 | * | 3 | * |
4 | * Copyright (C) 2007 Domen Puncer, Telargo, Inc. | 4 | * Copyright (C) 2007 Domen Puncer, Telargo, Inc. |
5 | * Copyright (C) 2008 Wolfram Sang, Pengutronix | ||
5 | * | 6 | * |
6 | * This file is licensed under the terms of the GNU General Public License | 7 | * This file is licensed under the terms of the GNU General Public License |
7 | * version 2. This program is licensed "as is" without any warranty of any | 8 | * version 2. This program is licensed "as is" without any warranty of any |
@@ -21,58 +22,45 @@ struct mpc52xx_fec_mdio_priv { | |||
21 | struct mpc52xx_fec __iomem *regs; | 22 | struct mpc52xx_fec __iomem *regs; |
22 | }; | 23 | }; |
23 | 24 | ||
24 | static int mpc52xx_fec_mdio_read(struct mii_bus *bus, int phy_id, int reg) | 25 | static int mpc52xx_fec_mdio_transfer(struct mii_bus *bus, int phy_id, |
26 | int reg, u32 value) | ||
25 | { | 27 | { |
26 | struct mpc52xx_fec_mdio_priv *priv = bus->priv; | 28 | struct mpc52xx_fec_mdio_priv *priv = bus->priv; |
27 | struct mpc52xx_fec __iomem *fec; | 29 | struct mpc52xx_fec __iomem *fec; |
28 | int tries = 100; | 30 | int tries = 100; |
29 | u32 request = FEC_MII_READ_FRAME; | 31 | |
32 | value |= (phy_id << FEC_MII_DATA_PA_SHIFT) & FEC_MII_DATA_PA_MSK; | ||
33 | value |= (reg << FEC_MII_DATA_RA_SHIFT) & FEC_MII_DATA_RA_MSK; | ||
30 | 34 | ||
31 | fec = priv->regs; | 35 | fec = priv->regs; |
32 | out_be32(&fec->ievent, FEC_IEVENT_MII); | 36 | out_be32(&fec->ievent, FEC_IEVENT_MII); |
33 | 37 | out_be32(&priv->regs->mii_data, value); | |
34 | request |= (phy_id << FEC_MII_DATA_PA_SHIFT) & FEC_MII_DATA_PA_MSK; | ||
35 | request |= (reg << FEC_MII_DATA_RA_SHIFT) & FEC_MII_DATA_RA_MSK; | ||
36 | |||
37 | out_be32(&priv->regs->mii_data, request); | ||
38 | 38 | ||
39 | /* wait for it to finish, this takes about 23 us on lite5200b */ | 39 | /* wait for it to finish, this takes about 23 us on lite5200b */ |
40 | while (!(in_be32(&fec->ievent) & FEC_IEVENT_MII) && --tries) | 40 | while (!(in_be32(&fec->ievent) & FEC_IEVENT_MII) && --tries) |
41 | udelay(5); | 41 | udelay(5); |
42 | 42 | ||
43 | if (tries == 0) | 43 | if (!tries) |
44 | return -ETIMEDOUT; | 44 | return -ETIMEDOUT; |
45 | 45 | ||
46 | return in_be32(&priv->regs->mii_data) & FEC_MII_DATA_DATAMSK; | 46 | return value & FEC_MII_DATA_OP_RD ? |
47 | in_be32(&priv->regs->mii_data) & FEC_MII_DATA_DATAMSK : 0; | ||
47 | } | 48 | } |
48 | 49 | ||
49 | static int mpc52xx_fec_mdio_write(struct mii_bus *bus, int phy_id, int reg, u16 data) | 50 | static int mpc52xx_fec_mdio_read(struct mii_bus *bus, int phy_id, int reg) |
50 | { | 51 | { |
51 | struct mpc52xx_fec_mdio_priv *priv = bus->priv; | 52 | return mpc52xx_fec_mdio_transfer(bus, phy_id, reg, FEC_MII_READ_FRAME); |
52 | struct mpc52xx_fec __iomem *fec; | 53 | } |
53 | u32 value = data; | ||
54 | int tries = 100; | ||
55 | |||
56 | fec = priv->regs; | ||
57 | out_be32(&fec->ievent, FEC_IEVENT_MII); | ||
58 | |||
59 | value |= FEC_MII_WRITE_FRAME; | ||
60 | value |= (phy_id << FEC_MII_DATA_PA_SHIFT) & FEC_MII_DATA_PA_MSK; | ||
61 | value |= (reg << FEC_MII_DATA_RA_SHIFT) & FEC_MII_DATA_RA_MSK; | ||
62 | |||
63 | out_be32(&priv->regs->mii_data, value); | ||
64 | |||
65 | /* wait for request to finish */ | ||
66 | while (!(in_be32(&fec->ievent) & FEC_IEVENT_MII) && --tries) | ||
67 | udelay(5); | ||
68 | |||
69 | if (tries == 0) | ||
70 | return -ETIMEDOUT; | ||
71 | 54 | ||
72 | return 0; | 55 | static int mpc52xx_fec_mdio_write(struct mii_bus *bus, int phy_id, int reg, |
56 | u16 data) | ||
57 | { | ||
58 | return mpc52xx_fec_mdio_transfer(bus, phy_id, reg, | ||
59 | data | FEC_MII_WRITE_FRAME); | ||
73 | } | 60 | } |
74 | 61 | ||
75 | static int mpc52xx_fec_mdio_probe(struct of_device *of, const struct of_device_id *match) | 62 | static int mpc52xx_fec_mdio_probe(struct of_device *of, |
63 | const struct of_device_id *match) | ||
76 | { | 64 | { |
77 | struct device *dev = &of->dev; | 65 | struct device *dev = &of->dev; |
78 | struct device_node *np = of->node; | 66 | struct device_node *np = of->node; |
@@ -131,7 +119,8 @@ static int mpc52xx_fec_mdio_probe(struct of_device *of, const struct of_device_i | |||
131 | dev_set_drvdata(dev, bus); | 119 | dev_set_drvdata(dev, bus); |
132 | 120 | ||
133 | /* set MII speed */ | 121 | /* set MII speed */ |
134 | out_be32(&priv->regs->mii_speed, ((mpc52xx_find_ipb_freq(of->node) >> 20) / 5) << 1); | 122 | out_be32(&priv->regs->mii_speed, |
123 | ((mpc52xx_find_ipb_freq(of->node) >> 20) / 5) << 1); | ||
135 | 124 | ||
136 | /* enable MII interrupt */ | 125 | /* enable MII interrupt */ |
137 | out_be32(&priv->regs->imask, in_be32(&priv->regs->imask) | FEC_IMASK_MII); | 126 | out_be32(&priv->regs->imask, in_be32(&priv->regs->imask) | FEC_IMASK_MII); |