diff options
-rw-r--r-- | drivers/net/sungem.c | 4 | ||||
-rw-r--r-- | drivers/net/sungem_phy.c | 69 | ||||
-rw-r--r-- | drivers/net/sungem_phy.h | 3 |
3 files changed, 56 insertions, 20 deletions
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 1f5655655c40..2608e7a3d214 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 0fca414d3657..d3ddb41d6e5c 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 822cb58174ea..430544496c52 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 |