summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/sungem.c4
-rw-r--r--drivers/net/sungem_phy.c69
-rw-r--r--drivers/net/sungem_phy.h3
3 files changed, 56 insertions, 20 deletions
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index 1f5655655c4..2608e7a3d21 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -3079,7 +3079,9 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
gp->phy_mii.dev = dev;
gp->phy_mii.mdio_read = _phy_read;
gp->phy_mii.mdio_write = _phy_write;
-
+#ifdef CONFIG_PPC_PMAC
+ gp->phy_mii.platform_data = gp->of_node;
+#endif
/* By default, we start with autoneg */
gp->want_autoneg = 1;
diff --git a/drivers/net/sungem_phy.c b/drivers/net/sungem_phy.c
index 0fca414d365..d3ddb41d6e5 100644
--- a/drivers/net/sungem_phy.c
+++ b/drivers/net/sungem_phy.c
@@ -32,6 +32,10 @@
#include <linux/ethtool.h>
#include <linux/delay.h>
+#ifdef CONFIG_PPC_PMAC
+#include <asm/prom.h>
+#endif
+
#include "sungem_phy.h"
/* Link modes of the BCM5400 PHY */
@@ -281,10 +285,12 @@ static int bcm5411_suspend(struct mii_phy* phy)
static int bcm5421_init(struct mii_phy* phy)
{
u16 data;
- int rev;
+ unsigned int id;
- rev = phy_read(phy, MII_PHYSID2) & 0x000f;
- if (rev == 0) {
+ id = (phy_read(phy, MII_PHYSID1) << 16 | phy_read(phy, MII_PHYSID2));
+
+ /* Revision 0 of 5421 needs some fixups */
+ if (id == 0x002060e0) {
/* This is borrowed from MacOS
*/
phy_write(phy, 0x18, 0x1007);
@@ -297,21 +303,28 @@ static int bcm5421_init(struct mii_phy* phy)
data = phy_read(phy, 0x15);
phy_write(phy, 0x15, data | 0x0200);
}
-#if 0
- /* This has to be verified before I enable it */
- /* Enable automatic low-power */
- phy_write(phy, 0x1c, 0x9002);
- phy_write(phy, 0x1c, 0xa821);
- phy_write(phy, 0x1c, 0x941d);
-#endif
- return 0;
-}
-static int bcm5421k2_init(struct mii_phy* phy)
-{
- /* Init code borrowed from OF */
- phy_write(phy, 4, 0x01e1);
- phy_write(phy, 9, 0x0300);
+ /* Pick up some init code from OF for K2 version */
+ if ((id & 0xfffffff0) == 0x002062e0) {
+ phy_write(phy, 4, 0x01e1);
+ phy_write(phy, 9, 0x0300);
+ }
+
+ /* Check if we can enable automatic low power */
+#ifdef CONFIG_PPC_PMAC
+ if (phy->platform_data) {
+ struct device_node *np = of_get_parent(phy->platform_data);
+ int can_low_power = 1;
+ if (np == NULL || get_property(np, "no-autolowpower", NULL))
+ can_low_power = 0;
+ if (can_low_power) {
+ /* Enable automatic low-power */
+ phy_write(phy, 0x1c, 0x9002);
+ phy_write(phy, 0x1c, 0xa821);
+ phy_write(phy, 0x1c, 0x941d);
+ }
+ }
+#endif /* CONFIG_PPC_PMAC */
return 0;
}
@@ -762,7 +775,7 @@ static struct mii_phy_def bcm5421_phy_def = {
/* Broadcom BCM 5421 built-in K2 */
static struct mii_phy_ops bcm5421k2_phy_ops = {
- .init = bcm5421k2_init,
+ .init = bcm5421_init,
.suspend = bcm5411_suspend,
.setup_aneg = bcm54xx_setup_aneg,
.setup_forced = bcm54xx_setup_forced,
@@ -779,6 +792,25 @@ static struct mii_phy_def bcm5421k2_phy_def = {
.ops = &bcm5421k2_phy_ops
};
+/* Broadcom BCM 5462 built-in Vesta */
+static struct mii_phy_ops bcm5462V_phy_ops = {
+ .init = bcm5421_init,
+ .suspend = bcm5411_suspend,
+ .setup_aneg = bcm54xx_setup_aneg,
+ .setup_forced = bcm54xx_setup_forced,
+ .poll_link = genmii_poll_link,
+ .read_link = bcm54xx_read_link,
+};
+
+static struct mii_phy_def bcm5462V_phy_def = {
+ .phy_id = 0x002060d0,
+ .phy_id_mask = 0xfffffff0,
+ .name = "BCM5462-Vesta",
+ .features = MII_GBIT_FEATURES,
+ .magic_aneg = 1,
+ .ops = &bcm5462V_phy_ops
+};
+
/* Marvell 88E1101 (Apple seem to deal with 2 different revs,
* I masked out the 8 last bits to get both, but some specs
* would be useful here) --BenH.
@@ -824,6 +856,7 @@ static struct mii_phy_def* mii_phy_table[] = {
&bcm5411_phy_def,
&bcm5421_phy_def,
&bcm5421k2_phy_def,
+ &bcm5462V_phy_def,
&marvell_phy_def,
&genmii_phy_def,
NULL
diff --git a/drivers/net/sungem_phy.h b/drivers/net/sungem_phy.h
index 822cb58174e..430544496c5 100644
--- a/drivers/net/sungem_phy.h
+++ b/drivers/net/sungem_phy.h
@@ -43,9 +43,10 @@ struct mii_phy
int pause;
/* Provided by host chip */
- struct net_device* dev;
+ struct net_device *dev;
int (*mdio_read) (struct net_device *dev, int mii_id, int reg);
void (*mdio_write) (struct net_device *dev, int mii_id, int reg, int val);
+ void *platform_data;
};
/* Pass in a struct mii_phy with dev, mdio_read and mdio_write