diff options
Diffstat (limited to 'drivers/net/ibm_newemac/phy.c')
-rw-r--r-- | drivers/net/ibm_newemac/phy.c | 188 |
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; |