[U-Boot-Users] [PATCH 3/9] 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 lrj@acm.org --- cpu/ppc4xx/miiphy.c | 143 +++++++++++++++++++++++++++++++++++--------------- 1 files changed, 100 insertions(+), 43 deletions(-)
diff --git a/cpu/ppc4xx/miiphy.c b/cpu/ppc4xx/miiphy.c index 98ba0a7..97ec023 100644 --- a/cpu/ppc4xx/miiphy.c +++ b/cpu/ppc4xx/miiphy.c @@ -27,19 +27,6 @@ | | Author: Mark Wisner | - | Change Activity- - | - | Date Description of Change BY - | --------- --------------------- --- - | 05-May-99 Created MKW - | 01-Jul-99 Changed clock setting of sta_reg from 66Mhz to 50Mhz to - | better match OPB speed. Also modified delay times. JWB - | 29-Jul-99 Added Full duplex support MKW - | 24-Aug-99 Removed printf from dp83843_duplex() JWB - | 19-Jul-00 Ported to esd cpci405 sr - | 23-Dec-03 Ported from miiphy.c to 440GX Travis Sawyer TBS - | travis.sawyer@sandburst.com - | +-----------------------------------------------------------------------------*/
#include <common.h> @@ -61,7 +48,6 @@ void miiphy_dump (char *devname, unsigned char addr) unsigned long i; unsigned short data;
- for (i = 0; i < 0x1A; i++) { if (miiphy_read (devname, addr, i, &data)) { printf ("read error for reg %lx\n", i); @@ -76,15 +62,87 @@ void miiphy_dump (char *devname, unsigned char addr) } /* end for loop */ } /* end dump */
- /***********************************************************/ /* (Re)start autonegotiation */ /***********************************************************/ 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 | @@ -95,15 +153,16 @@ 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; }
- /***********************************************************/ /* read a phy reg and return the value with a rc */ /***********************************************************/ @@ -156,21 +215,20 @@ unsigned int miiphy_getemac_offset (void) #endif }
- -int emac4xx_miiphy_read (char *devname, unsigned char addr, - unsigned char reg, unsigned short *value) +int emac4xx_miiphy_read (char *devname, unsigned char addr, unsigned char reg, + unsigned short *value) { unsigned long sta_reg; /* STA scratch area */ unsigned long i; unsigned long emac_reg;
- emac_reg = miiphy_getemac_offset (); /* see if it is ready for 1000 nsec */ i = 0;
/* see if it is ready for sec */ - while ((in_be32((void *)EMAC_STACR + emac_reg) & EMAC_STACR_OC) == EMAC_STACR_OC_MASK) { + while ((in_be32((void *)EMAC_STACR + emac_reg) & EMAC_STACR_OC) == + EMAC_STACR_OC_MASK) { udelay (7); if (i > 5) { #ifdef ET_DEBUG @@ -187,10 +245,10 @@ int emac4xx_miiphy_read (char *devname, unsigned char addr, #if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ defined(CONFIG_405EX) -#if defined(CONFIG_IBM_EMAC4_V4) /* EMAC4 V4 changed bit setting */ - sta_reg = (sta_reg & ~EMAC_STACR_OP_MASK) | EMAC_STACR_READ; +#if defined(CONFIG_IBM_EMAC4_V4) /* EMAC4 V4 changed bit setting */ + sta_reg = (sta_reg & ~EMAC_STACR_OP_MASK) | EMAC_STACR_READ; #else - sta_reg |= EMAC_STACR_READ; + sta_reg |= EMAC_STACR_READ; #endif #else sta_reg = (sta_reg | EMAC_STACR_READ) & ~EMAC_STACR_CLK_100MHZ; @@ -211,7 +269,7 @@ int emac4xx_miiphy_read (char *devname, unsigned char addr,
sta_reg = in_be32((void *)EMAC_STACR + emac_reg); #ifdef ET_DEBUG - printf ("a21: read : EMAC_STACR=0x%0x\n", sta_reg); /* test-only */ + printf ("a21: read : EMAC_STACR=0x%0x\n", sta_reg); /* test-only */ #endif i = 0; while ((sta_reg & EMAC_STACR_OC) == EMAC_STACR_OC_MASK) { @@ -229,19 +287,17 @@ int emac4xx_miiphy_read (char *devname, unsigned char addr, return -1; }
- *value = *(short *) (&sta_reg); + *value = *(short *)(&sta_reg); return 0;
- } /* phy_read */
- /***********************************************************/ /* write a phy reg and return the value with a rc */ /***********************************************************/
-int emac4xx_miiphy_write (char *devname, unsigned char addr, - unsigned char reg, unsigned short value) +int emac4xx_miiphy_write (char *devname, unsigned char addr, unsigned char reg, + unsigned short value) { unsigned long sta_reg; /* STA scratch area */ unsigned long i; @@ -251,7 +307,8 @@ int emac4xx_miiphy_write (char *devname, unsigned char addr, /* see if it is ready for 1000 nsec */ i = 0;
- while ((in_be32((void *)EMAC_STACR + emac_reg) & EMAC_STACR_OC) == EMAC_STACR_OC_MASK) { + while ((in_be32((void *)EMAC_STACR + emac_reg) & EMAC_STACR_OC) == + EMAC_STACR_OC_MASK) { if (i > 5) return -1; udelay (7); @@ -263,10 +320,10 @@ int emac4xx_miiphy_write (char *devname, unsigned char addr, #if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ defined(CONFIG_405EX) -#if defined(CONFIG_IBM_EMAC4_V4) /* EMAC4 V4 changed bit setting */ - sta_reg = (sta_reg & ~EMAC_STACR_OP_MASK) | EMAC_STACR_WRITE; +#if defined(CONFIG_IBM_EMAC4_V4) /* EMAC4 V4 changed bit setting */ + sta_reg = (sta_reg & ~EMAC_STACR_OP_MASK) | EMAC_STACR_WRITE; #else - sta_reg |= EMAC_STACR_WRITE; + sta_reg |= EMAC_STACR_WRITE; #endif #else sta_reg = (sta_reg | EMAC_STACR_WRITE) & ~EMAC_STACR_CLK_100MHZ; @@ -278,8 +335,8 @@ int emac4xx_miiphy_write (char *devname, unsigned char addr, !defined(CONFIG_405EX) sta_reg = sta_reg | CONFIG_PHY_CLK_FREQ; /* Set clock frequency (PLB freq. dependend) */ #endif - sta_reg = sta_reg | ((unsigned long) addr << 5);/* Phy address */ - sta_reg = sta_reg | EMAC_STACR_OC_MASK; /* new IBM emac v4 */ + sta_reg = sta_reg | ((unsigned long)addr << 5); /* Phy address */ + sta_reg = sta_reg | EMAC_STACR_OC_MASK; /* new IBM emac v4 */ memcpy (&sta_reg, &value, 2); /* put in data */
out_be32((void *)EMAC_STACR + emac_reg, sta_reg); @@ -288,7 +345,7 @@ int emac4xx_miiphy_write (char *devname, unsigned char addr, i = 0; sta_reg = in_be32((void *)EMAC_STACR + emac_reg); #ifdef ET_DEBUG - printf ("a31: read : EMAC_STACR=0x%0x\n", sta_reg); /* test-only */ + printf ("a31: read : EMAC_STACR=0x%0x\n", sta_reg); /* test-only */ #endif while ((sta_reg & EMAC_STACR_OC) == EMAC_STACR_OC_MASK) { udelay (7); @@ -305,4 +362,4 @@ int emac4xx_miiphy_write (char *devname, unsigned char addr, return -1; return 0;
-} /* phy_write */ +} /* phy_write */

On Saturday 22 December 2007, Larry Johnson wrote:
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.
Sorry for the late review, but I have still some remarks. Please see below.
Signed-off-by: Larry Johnson lrj@acm.org
cpu/ppc4xx/miiphy.c | 143 +++++++++++++++++++++++++++++++++++--------------- 1 files changed, 100 insertions(+), 43 deletions(-)
diff --git a/cpu/ppc4xx/miiphy.c b/cpu/ppc4xx/miiphy.c index 98ba0a7..97ec023 100644 --- a/cpu/ppc4xx/miiphy.c +++ b/cpu/ppc4xx/miiphy.c @@ -27,19 +27,6 @@
| Author: Mark Wisner
- | Change Activity-
- |
- | Date Description of Change BY
- | --------- --------------------- ---
- | 05-May-99 Created MKW
- | 01-Jul-99 Changed clock setting of sta_reg from 66Mhz to 50Mhz to
- | better match OPB speed. Also modified delay times. JWB
- | 29-Jul-99 Added Full duplex support MKW
- | 24-Aug-99 Removed printf from dp83843_duplex() JWB
- | 19-Jul-00 Ported to esd cpci405 sr
- | 23-Dec-03 Ported from miiphy.c to 440GX Travis Sawyer TBS
- | travis.sawyer@sandburst.com
- |
+-------------------------------------------------------------------------- ---*/
#include <common.h> @@ -61,7 +48,6 @@ void miiphy_dump (char *devname, unsigned char addr) unsigned long i; unsigned short data;
- for (i = 0; i < 0x1A; i++) { if (miiphy_read (devname, addr, i, &data)) { printf ("read error for reg %lx\n", i);
@@ -76,15 +62,87 @@ void miiphy_dump (char *devname, unsigned char addr) } /* end for loop */ } /* end dump */
/***********************************************************/ /* (Re)start autonegotiation */ /***********************************************************/ 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);
- }
No parantheses (braces ?) for one line statements please.
- 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;
}
Again, please check the complete source for such on lined statements and remove those braces.
Thanks.
Best regards, Stefan
===================================================================== DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: +49-8142-66989-0 Fax: +49-8142-66989-80 Email: office@denx.de =====================================================================
participants (2)
-
Larry Johnson
-
Stefan Roese