aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/forcedeth.c
diff options
context:
space:
mode:
authorAyaz Abdulla <aabdulla@nvidia.com>2006-08-24 15:43:42 -0400
committerJeff Garzik <jeff@garzik.org>2006-09-06 10:57:37 -0400
commitedf7e5ec99c2e24cea3951f7961958fc7edbfdd1 (patch)
tree1862fb28066e7f8728f7bc325349e1efc5885ab6 /drivers/net/forcedeth.c
parent3784fd7316d336f2ba79b6c7c8168d08eff8a714 (diff)
[PATCH] forcedeth: errata for marvell phys
This patch addresses an errata found on certain marvell phys concerning the reset of the BMCR phy register during phy reset. Signed-Off-By: Ayaz Abdulla <aabdulla@nvidia.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/forcedeth.c')
-rw-r--r--drivers/net/forcedeth.c73
1 files changed, 56 insertions, 17 deletions
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 8c8f7cf0e952..74ed8bb266ec 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -543,6 +543,9 @@ union ring_type {
543#define PHYID1_OUI_SHFT 6 543#define PHYID1_OUI_SHFT 6
544#define PHYID2_OUI_MASK 0xfc00 544#define PHYID2_OUI_MASK 0xfc00
545#define PHYID2_OUI_SHFT 10 545#define PHYID2_OUI_SHFT 10
546#define PHYID2_MODEL_MASK 0x03f0
547#define PHY_MODEL_MARVELL_E3016 0x220
548#define PHY_MARVELL_E3016_INITMASK 0x0300
546#define PHY_INIT1 0x0f000 549#define PHY_INIT1 0x0f000
547#define PHY_INIT2 0x0e00 550#define PHY_INIT2 0x0e00
548#define PHY_INIT3 0x01000 551#define PHY_INIT3 0x01000
@@ -701,6 +704,7 @@ struct fe_priv {
701 int phyaddr; 704 int phyaddr;
702 int wolenabled; 705 int wolenabled;
703 unsigned int phy_oui; 706 unsigned int phy_oui;
707 unsigned int phy_model;
704 u16 gigabit; 708 u16 gigabit;
705 int intr_test; 709 int intr_test;
706 710
@@ -1027,14 +1031,13 @@ static int mii_rw(struct net_device *dev, int addr, int miireg, int value)
1027 return retval; 1031 return retval;
1028} 1032}
1029 1033
1030static int phy_reset(struct net_device *dev) 1034static int phy_reset(struct net_device *dev, u32 bmcr_setup)
1031{ 1035{
1032 struct fe_priv *np = netdev_priv(dev); 1036 struct fe_priv *np = netdev_priv(dev);
1033 u32 miicontrol; 1037 u32 miicontrol;
1034 unsigned int tries = 0; 1038 unsigned int tries = 0;
1035 1039
1036 miicontrol = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ); 1040 miicontrol = BMCR_RESET | bmcr_setup;
1037 miicontrol |= BMCR_RESET;
1038 if (mii_rw(dev, np->phyaddr, MII_BMCR, miicontrol)) { 1041 if (mii_rw(dev, np->phyaddr, MII_BMCR, miicontrol)) {
1039 return -1; 1042 return -1;
1040 } 1043 }
@@ -1059,6 +1062,16 @@ static int phy_init(struct net_device *dev)
1059 u8 __iomem *base = get_hwbase(dev); 1062 u8 __iomem *base = get_hwbase(dev);
1060 u32 phyinterface, phy_reserved, mii_status, mii_control, mii_control_1000,reg; 1063 u32 phyinterface, phy_reserved, mii_status, mii_control, mii_control_1000,reg;
1061 1064
1065 /* phy errata for E3016 phy */
1066 if (np->phy_model == PHY_MODEL_MARVELL_E3016) {
1067 reg = mii_rw(dev, np->phyaddr, MII_NCONFIG, MII_READ);
1068 reg &= ~PHY_MARVELL_E3016_INITMASK;
1069 if (mii_rw(dev, np->phyaddr, MII_NCONFIG, reg)) {
1070 printk(KERN_INFO "%s: phy write to errata reg failed.\n", pci_name(np->pci_dev));
1071 return PHY_ERROR;
1072 }
1073 }
1074
1062 /* set advertise register */ 1075 /* set advertise register */
1063 reg = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ); 1076 reg = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
1064 reg |= (ADVERTISE_10HALF|ADVERTISE_10FULL|ADVERTISE_100HALF|ADVERTISE_100FULL|ADVERTISE_PAUSE_ASYM|ADVERTISE_PAUSE_CAP); 1077 reg |= (ADVERTISE_10HALF|ADVERTISE_10FULL|ADVERTISE_100HALF|ADVERTISE_100FULL|ADVERTISE_PAUSE_ASYM|ADVERTISE_PAUSE_CAP);
@@ -1089,8 +1102,13 @@ static int phy_init(struct net_device *dev)
1089 else 1102 else
1090 np->gigabit = 0; 1103 np->gigabit = 0;
1091 1104
1092 /* reset the phy */ 1105 mii_control = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
1093 if (phy_reset(dev)) { 1106 mii_control |= BMCR_ANENABLE;
1107
1108 /* reset the phy
1109 * (certain phys need bmcr to be setup with reset)
1110 */
1111 if (phy_reset(dev, mii_control)) {
1094 printk(KERN_INFO "%s: phy reset failed\n", pci_name(np->pci_dev)); 1112 printk(KERN_INFO "%s: phy reset failed\n", pci_name(np->pci_dev));
1095 return PHY_ERROR; 1113 return PHY_ERROR;
1096 } 1114 }
@@ -3158,9 +3176,18 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
3158 if (netif_running(dev)) 3176 if (netif_running(dev))
3159 printk(KERN_INFO "%s: link down.\n", dev->name); 3177 printk(KERN_INFO "%s: link down.\n", dev->name);
3160 bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ); 3178 bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
3161 bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART); 3179 if (np->phy_model == PHY_MODEL_MARVELL_E3016) {
3162 mii_rw(dev, np->phyaddr, MII_BMCR, bmcr); 3180 bmcr |= BMCR_ANENABLE;
3163 3181 /* reset the phy in order for settings to stick,
3182 * and cause autoneg to start */
3183 if (phy_reset(dev, bmcr)) {
3184 printk(KERN_INFO "%s: phy reset failed\n", dev->name);
3185 return -EINVAL;
3186 }
3187 } else {
3188 bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
3189 mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
3190 }
3164 } else { 3191 } else {
3165 int adv, bmcr; 3192 int adv, bmcr;
3166 3193
@@ -3200,17 +3227,19 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
3200 bmcr |= BMCR_FULLDPLX; 3227 bmcr |= BMCR_FULLDPLX;
3201 if (np->fixed_mode & (ADVERTISE_100HALF|ADVERTISE_100FULL)) 3228 if (np->fixed_mode & (ADVERTISE_100HALF|ADVERTISE_100FULL))
3202 bmcr |= BMCR_SPEED100; 3229 bmcr |= BMCR_SPEED100;
3203 mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
3204 if (np->phy_oui == PHY_OUI_MARVELL) { 3230 if (np->phy_oui == PHY_OUI_MARVELL) {
3205 /* reset the phy */ 3231 /* reset the phy in order for forced mode settings to stick */
3206 if (phy_reset(dev)) { 3232 if (phy_reset(dev, bmcr)) {
3207 printk(KERN_INFO "%s: phy reset failed\n", dev->name); 3233 printk(KERN_INFO "%s: phy reset failed\n", dev->name);
3208 return -EINVAL; 3234 return -EINVAL;
3209 } 3235 }
3210 } else if (netif_running(dev)) { 3236 } else {
3211 /* Wait a bit and then reconfigure the nic. */ 3237 mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
3212 udelay(10); 3238 if (netif_running(dev)) {
3213 nv_linkchange(dev); 3239 /* Wait a bit and then reconfigure the nic. */
3240 udelay(10);
3241 nv_linkchange(dev);
3242 }
3214 } 3243 }
3215 } 3244 }
3216 3245
@@ -3267,8 +3296,17 @@ static int nv_nway_reset(struct net_device *dev)
3267 } 3296 }
3268 3297
3269 bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ); 3298 bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
3270 bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART); 3299 if (np->phy_model == PHY_MODEL_MARVELL_E3016) {
3271 mii_rw(dev, np->phyaddr, MII_BMCR, bmcr); 3300 bmcr |= BMCR_ANENABLE;
3301 /* reset the phy in order for settings to stick*/
3302 if (phy_reset(dev, bmcr)) {
3303 printk(KERN_INFO "%s: phy reset failed\n", dev->name);
3304 return -EINVAL;
3305 }
3306 } else {
3307 bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
3308 mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
3309 }
3272 3310
3273 if (netif_running(dev)) { 3311 if (netif_running(dev)) {
3274 nv_start_rx(dev); 3312 nv_start_rx(dev);
@@ -4488,6 +4526,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
4488 if (id2 < 0 || id2 == 0xffff) 4526 if (id2 < 0 || id2 == 0xffff)
4489 continue; 4527 continue;
4490 4528
4529 np->phy_model = id2 & PHYID2_MODEL_MASK;
4491 id1 = (id1 & PHYID1_OUI_MASK) << PHYID1_OUI_SHFT; 4530 id1 = (id1 & PHYID1_OUI_MASK) << PHYID1_OUI_SHFT;
4492 id2 = (id2 & PHYID2_OUI_MASK) >> PHYID2_OUI_SHFT; 4531 id2 = (id2 & PHYID2_OUI_MASK) >> PHYID2_OUI_SHFT;
4493 dprintk(KERN_DEBUG "%s: open: Found PHY %04x:%04x at address %d.\n", 4532 dprintk(KERN_DEBUG "%s: open: Found PHY %04x:%04x at address %d.\n",