PPC4xx: Add Ethernet 1000BASE-X support for PPC4xx
PATCH 2/2 PPC4xx: Add Ethernet 1000BASE-X support for PPC4xx
This patch adds a new switch: "CONFIG_PHY_DYNAMIC_ANEG". When this symbol is defined, the PHY will advertise it's capabilities for autonegotiation based on the capabilities shown in the PHY's status registers, including 1000BASE-X. When "CONFIG_PHY_DYNAMIC_ANEG" is not defined, the PHY will advertise hard-coded capabilities, as before.
Signed-off-by Larry Johnson <[email protected]>
---
cpu/ppc4xx/miiphy.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 80 insertions(+), 5 deletions(-)
cpu/ppc4xx/miiphy.c +80 -5
@@ -66,9 +66,82 @@ void miiphy_dump (char *devname, unsigned char addr)/***********************************************************/ int phy_setup_aneg (char *devname,unsigned char addr) { -unsigned short ctl, adv; +u16 bmcr; + +#if defined(CONFIG_PHY_DYNAMIC_ANEG ) +/* +* Set up advertisement based on capablilities reported by the PHY. +* This should work for both copper and fiber. +*/ +u16 bmsr; +#if defined(CONFIG_PHY_GIGE ) +u16 exsr =0x0000 ; +#endif + +miiphy_read (devname, addr,PHY_BMSR , &bmsr); + +#if defined(CONFIG_PHY_GIGE ) +if (bmsr &PHY_BMSR_EXT_STAT ) { +miiphy_read (devname, addr,PHY_EXSR , &exsr); + } + +if (exsr & (PHY_EXSR_1000XF |PHY_EXSR_1000XH )) { +/* 1000BASE-X */ +u16 anar =0x0000 ; + +if (exsr &PHY_EXSR_1000XF ) { + anar |=PHY_X_ANLPAR_FD ; + } +if (exsr &PHY_EXSR_1000XH ) { + anar |=PHY_X_ANLPAR_HD ; + } +miiphy_write (devname, addr,PHY_ANAR , anar); + } else +#endif + { +u16 anar, btcr; + +miiphy_read (devname, addr,PHY_ANAR , &anar); + anar &= ~(0x5000 |PHY_ANLPAR_T4 |PHY_ANLPAR_TXFD | +PHY_ANLPAR_TX |PHY_ANLPAR_10FD |PHY_ANLPAR_10 ); + +miiphy_read (devname, addr,PHY_1000BTCR , &btcr); + btcr &= ~(0x00FF |PHY_1000BTCR_1000FD |PHY_1000BTCR_1000HD ); + +if (bmsr &PHY_BMSR_100T4 ) { + anar |=PHY_ANLPAR_T4 ; + } +if (bmsr &PHY_BMSR_100TXF ) { + anar |=PHY_ANLPAR_TXFD ; + } +if (bmsr &PHY_BMSR_100TXH ) { + anar |=PHY_ANLPAR_TX ; + } +if (bmsr &PHY_BMSR_10TF ) { + anar |=PHY_ANLPAR_10FD ; + } +if (bmsr &PHY_BMSR_10TH ) { + anar |=PHY_ANLPAR_10 ; + } +miiphy_write (devname, addr,PHY_ANAR , anar); + +#if defined(CONFIG_PHY_GIGE ) +if (exsr &PHY_EXSR_1000TF ) { + btcr |=PHY_1000BTCR_1000FD ; + } +if (exsr &PHY_EXSR_1000TH ) { + btcr |=PHY_1000BTCR_1000HD ; + } +miiphy_write (devname, addr,PHY_1000BTCR , btcr); +#endif + } + +#else /* defined(CONFIG_PHY_DYNAMIC_ANEG) */ +/* +* Set up standard advertisement +*/ +u16 adv; -/* Setup standard advertise */ miiphy_read (devname, addr,PHY_ANAR , &adv); adv |= (PHY_ANLPAR_ACK | PHY_ANLPAR_RF | PHY_ANLPAR_T4 | PHY_ANLPAR_TXFD | PHY_ANLPAR_TX | PHY_ANLPAR_10FD |
@@ -79,10 +152,12 @@ int phy_setup_aneg (char *devname, unsigned char addr) adv |= (0x0300 );miiphy_write (devname, addr,PHY_1000BTCR , adv); +#endif /* defined(CONFIG_PHY_DYNAMIC_ANEG) */ +/* Start/Restart aneg */ -miiphy_read (devname, addr,PHY_BMCR , &ctl); - ctl |= (PHY_BMCR_AUTON |PHY_BMCR_RST_NEG ); -miiphy_write (devname, addr,PHY_BMCR , ctl); +miiphy_read (devname, addr,PHY_BMCR , &bmcr); + bmcr |= (PHY_BMCR_AUTON |PHY_BMCR_RST_NEG ); +miiphy_write (devname, addr,PHY_BMCR , bmcr);return 0 ; }