aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/ibm_newemac/phy.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ibm_newemac/phy.c')
-rw-r--r--drivers/net/ibm_newemac/phy.c188
1 files changed, 186 insertions, 2 deletions
diff --git a/drivers/net/ibm_newemac/phy.c b/drivers/net/ibm_newemac/phy.c
index ac9d964e59e..635cb96ef64 100644
--- a/drivers/net/ibm_newemac/phy.c
+++ b/drivers/net/ibm_newemac/phy.c
@@ -52,7 +52,7 @@ int emac_mii_reset_phy(struct mii_phy *phy)
{
int val;
int limit = 10000;
-
+#ifndef CONFIG_APOLLO3G
val = phy_read(phy, MII_BMCR);
val &= ~(BMCR_ISOLATE | BMCR_ANENABLE);
val |= BMCR_RESET;
@@ -68,7 +68,7 @@ int emac_mii_reset_phy(struct mii_phy *phy)
}
if ((val & BMCR_ISOLATE) && limit > 0)
phy_write(phy, MII_BMCR, val & ~BMCR_ISOLATE);
-
+#endif /* CONFIG_APOLLO3G */
return limit <= 0;
}
@@ -359,7 +359,51 @@ static struct mii_phy_def bcm5248_phy_def = {
.name = "BCM5248 10/100 SMII Ethernet",
.ops = &generic_phy_ops
};
+#ifdef CONFIG_APOLLO3G
+static int bcm54610_init(struct mii_phy *phy)
+{
+ int regb, rega;
+
+ phy_write(phy, 0x1C, 0x2C00);
+ regb = phy_read(phy, 0x1C);
+
+ phy_write(phy, 0x1C, 0xAC8C);
+
+ phy_write(phy, 0x1C, 0x2C00);
+ rega = phy_read(phy, 0x1C);
+
+ printk(KERN_INFO "%s: before 0x%04x, after 0x%04x\n",
+ __FUNCTION__, (regb & 0xffff), (rega & 0xffff));
+
+ /* the RGMII interface is not half-duplex capable */
+ rega = phy_read(phy, 0x04);
+ phy_write(phy, 0x04, rega & ~0x00a0);
+
+ regb = phy_read(phy, 0x09);
+ phy_write(phy, 0x09, regb & ~0x0100);
+
+ printk(KERN_INFO "%s: before 0x%04x, 0x%04x; after 0x%04x, 0x%04x\n",
+ __FUNCTION__, (rega & 0xffff), (regb & 0xffff),
+ (phy_read(phy, 0x04) & 0xffff), (phy_read(phy, 0x09) & 0xffff));
+
+ return 0;
+}
+
+static struct mii_phy_ops bcm54610_phy_ops = {
+ .init = bcm54610_init,
+ .setup_aneg = genmii_setup_aneg,
+ .setup_forced = genmii_setup_forced,
+ .poll_link = genmii_poll_link,
+ .read_link = genmii_read_link
+};
+static struct mii_phy_def bcm54610_phy_def = {
+ .phy_id = 0x0143BD63,
+ .phy_id_mask = 0xffffffff,
+ .name = "BCM54610 Gigabit Ethernet",
+ .ops = &bcm54610_phy_ops
+};
+#endif
static int m88e1111_init(struct mii_phy *phy)
{
pr_debug("%s: Marvell 88E1111 Ethernet\n", __func__);
@@ -400,6 +444,111 @@ static int m88e1112_init(struct mii_phy *phy)
return 0;
}
+static int m88e1141_init(struct mii_phy *phy)
+{
+ unsigned short data;
+
+ printk(KERN_CRIT "we go to init for %d\n", phy->mode);
+ switch (phy->mode) {
+ case PHY_MODE_GMII:
+#if defined(CONFIG_M88E1141_DEBUG)
+ data = phy_read(phy, 0x00);
+ data |= 0x2000; /* Speed Select 1000Mbps */
+ phy_write(phy, 0x00, data);
+ data = phy_read(phy, 0x14);
+ data |= 0x0010; /* GMII Deafult MAC interface speed */
+ phy_write(phy, 0x14, data);
+ data = phy_read(phy, 0x1B);
+ data |= 0x8000; /* Auto Selection = Disable */
+ data |= 0x0400; /* Interrupt Polarity = Active Low */
+ data |= 0x0080; /* DTE Detect Status wait time */
+ data |= 0x000F; /* HWCFG_MODE = GMII */
+ phy_write(phy, 0x1B, data);
+ data = phy_read(phy, 0x04);
+ data |= 0x0C00; /* Async Pause + Pause */
+ data |= 0x01E0; /* 100FDX + 100HDX + 10FDX + 10HDX */
+ phy_write(phy, 0x04, data);
+ data = phy_read(phy, 0x09);
+ //data |= 0x1C00; /* Master/Slave Config */
+ data |= 0x0300; /* 1000FDX + 1000HDX */
+ phy_write(phy, 0x09, data);
+#else
+ data = phy_read(phy, 0x14);
+ data |= 0x0010; /* GMII Deafult MAC interface speed */
+ phy_write(phy, 0x14, data);
+ data = phy_read(phy, 0x1B);
+ data |= 0x000F; /* HWCFG_MODE = GMII */
+ phy_write(phy, 0x1B, data);
+#endif
+ break;
+ case PHY_MODE_RGMII:
+#if defined(CONFIG_M88E1141_DEBUG)
+ data = phy_read(phy, 0x00);
+ data |= 0x2000; /* Speed Select 1000Mbps */
+ phy_write(phy, 0x00, data);
+ data = phy_read(phy, 0x14);
+ data |= 0x0080; /* RGMII RX Timing Control */
+ data |= 0x0002; /* RGMII TX Timing Control */
+ data |= 0x0050; /* RGMII Deafult MAC interface speed */
+ phy_write(phy, 0x14, data);
+ data = phy_read(phy, 0x1B);
+ data |= 0x8000; /* Auto Selection = Disable */
+ data |= 0x0400; /* Interrupt Polarity = Active Low */
+ data |= 0x0080; /* DTE Detect Status wait time */
+ data |= 0x000B; /* HWCFG_MODE = RGMII */
+ phy_write(phy, 0x1B, data);
+ data = phy_read(phy, 0x04);
+ data |= 0x0C00; /* Async Pause + Pause */
+ data |= 0x01E0; /* 100FDX + 100HDX + 10FDX + 10HDX */
+ phy_write(phy, 0x04, data);
+ data = phy_read(phy, 0x09);
+ //data |= 0x1C00; /* Master/Slave Config */
+ data |= 0x0300; /* 1000FDX + 1000HDX */
+ phy_write(phy, 0x09, data);
+#else
+ data = phy_read(phy, 0x14);
+ data |= 0x0080; /* RGMII RX Timing Control */
+ data |= 0x0002; /* RGMII TX Timing Control */
+ data |= 0x0050; /* RGMII Deafult MAC interface speed */
+ phy_write(phy, 0x14, data);
+ data = phy_read(phy, 0x1B);
+ data |= 0x000B; /* HWCFG_MODE = RGMII */
+ phy_write(phy, 0x1B, data);
+#endif
+ break;
+ case PHY_MODE_SGMII:
+ data = phy_read(phy, 0x14);
+ data &= ~0x0080; /* CLEAR - RGMII setting */
+ data &= ~0x0002; /* CLEAR - RGMII setting */
+ data &= ~0x0070; /* CLEAR - Default MAC speed */
+ data |= 0x0070; /* GMII Deafult MAC interface speed */
+ phy_write(phy, 0x14, data);
+
+ data = phy_read(phy, 0x1B);
+ data |= 0x8000; /* Auto Selection = Disable */
+ data &= ~0x0400; /* Interrupt Polarity = Active Low */
+ data |= 0x0120; /* DTE Detect Status wait time */
+ data &= ~0x000F;/* CLEAR - HWCFG_MODE setting */
+ data |= 0x0000; /* HWCFG_MODE = SGMII */
+ phy_write(phy, 0x1B, data);
+
+ phy_write(phy, 0x10, 0x0068);
+ phy_write(phy, 0x16, 0x0001);
+ phy_write(phy, 0x00, 0x8100);
+ phy_write(phy, 0x16, 0x0000);
+ break;
+ }
+
+#if 0
+ data = phy_read(phy, 0x00);
+ data |= 0x8000; /* Reset PHY */
+ phy_write(phy, 0x00, data);
+ udelay(1000);
+#endif
+
+ return 0;
+}
+
static int et1011c_init(struct mii_phy *phy)
{
u16 reg_short;
@@ -467,12 +616,31 @@ static struct mii_phy_def m88e1112_phy_def = {
.ops = &m88e1112_phy_ops,
};
+static struct mii_phy_ops m88e1141_phy_ops = {
+ .init = m88e1141_init,
+ .setup_aneg = genmii_setup_aneg,
+ .setup_forced = genmii_setup_forced,
+ .poll_link = genmii_poll_link,
+ .read_link = genmii_read_link
+};
+
+static struct mii_phy_def m88e1141_phy_def = {
+ .phy_id = 0x01410CD0,
+ .phy_id_mask = 0x0ffffff0,
+ .name = "Marvell 88E1141 Ethernet",
+ .ops = &m88e1141_phy_ops,
+};
+
static struct mii_phy_def *mii_phy_table[] = {
&et1011c_phy_def,
&cis8201_phy_def,
&bcm5248_phy_def,
+#ifdef CONFIG_APOLLO3G
+ &bcm54610_phy_def,
+#endif
&m88e1111_phy_def,
&m88e1112_phy_def,
+ &m88e1141_phy_def,
&genmii_phy_def,
NULL
};
@@ -487,7 +655,11 @@ int emac_mii_phy_probe(struct mii_phy *phy, int address)
phy->advertising = 0;
phy->address = address;
phy->speed = SPEED_10;
+#ifndef CONFIG_APOLLO3G
phy->duplex = DUPLEX_HALF;
+#else
+ phy->duplex = DUPLEX_FULL;
+#endif
phy->pause = phy->asym_pause = 0;
/* Take PHY out of isolate mode and reset it. */
@@ -511,24 +683,36 @@ int emac_mii_phy_probe(struct mii_phy *phy, int address)
u16 bmsr = phy_read(phy, MII_BMSR);
if (bmsr & BMSR_ANEGCAPABLE)
phy->features |= SUPPORTED_Autoneg;
+#ifndef CONFIG_APOLLO3G
if (bmsr & BMSR_10HALF)
phy->features |= SUPPORTED_10baseT_Half;
+#endif
if (bmsr & BMSR_10FULL)
phy->features |= SUPPORTED_10baseT_Full;
+#ifndef CONFIG_APOLLO3G
if (bmsr & BMSR_100HALF)
phy->features |= SUPPORTED_100baseT_Half;
+#endif
if (bmsr & BMSR_100FULL)
phy->features |= SUPPORTED_100baseT_Full;
if (bmsr & BMSR_ESTATEN) {
u16 esr = phy_read(phy, MII_ESTATUS);
if (esr & ESTATUS_1000_TFULL)
phy->features |= SUPPORTED_1000baseT_Full;
+#ifndef CONFIG_APOLLO3G
if (esr & ESTATUS_1000_THALF)
phy->features |= SUPPORTED_1000baseT_Half;
+#endif
}
phy->features |= SUPPORTED_MII;
}
+#if (defined CONFIG_APM82181) /* RGMII does not support half-duplex */
+ phy->features &= ~(SUPPORTED_1000baseT_Half |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_10baseT_Half);
+#endif
+
/* Setup default advertising */
phy->advertising = phy->features;