diff options
-rw-r--r-- | cpu/ppc4xx/miiphy.c | 196 |
1 files changed, 80 insertions, 116 deletions
diff --git a/cpu/ppc4xx/miiphy.c b/cpu/ppc4xx/miiphy.c index 3978773..c882720 100644 --- a/cpu/ppc4xx/miiphy.c +++ b/cpu/ppc4xx/miiphy.c @@ -29,6 +29,11 @@ | +-----------------------------------------------------------------------------*/ +/* define DEBUG for debugging output (obviously ;-)) */ +#if 0 +#define DEBUG +#endif + #include <common.h> #include <asm/processor.h> #include <asm/io.h> @@ -38,7 +43,10 @@ #include <405_mal.h> #include <miiphy.h> -#undef ET_DEBUG +#if !defined(CONFIG_PHY_CLK_FREQ) +#define CONFIG_PHY_CLK_FREQ 0 +#endif + /***********************************************************/ /* Dump out to the screen PHY regs */ /***********************************************************/ @@ -164,9 +172,21 @@ int phy_setup_aneg (char *devname, unsigned char addr) /***********************************************************/ /* read a phy reg and return the value with a rc */ /***********************************************************/ +/* AMCC_TODO: + * Find out of the choice for the emac for MDIO is from the bridges, + * i.e. ZMII or RGMII as approporiate. If the bridges are not used + * to determine the emac for MDIO, then is the SDR0_ETH_CFG[MDIO_SEL] + * used? If so, then this routine below does not apply to the 460EX/GT. + * + * sr: Currently on 460EX only EMAC0 works with MDIO, so we always + * return EMAC0 offset here + */ unsigned int miiphy_getemac_offset (void) { -#if (defined(CONFIG_440) && !defined(CONFIG_440SP) && !defined(CONFIG_440SPE)) && defined(CONFIG_NET_MULTI) +#if (defined(CONFIG_440) && \ + !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \ + !defined(CONFIG_460EX) && !defined(CONFIG_460GT)) && \ + defined(CONFIG_NET_MULTI) unsigned long zmii; unsigned long eoffset; @@ -217,153 +237,97 @@ unsigned int miiphy_getemac_offset (void) #endif } -int emac4xx_miiphy_read (char *devname, unsigned char addr, unsigned char reg, - unsigned short *value) +static int emac_miiphy_wait(u32 emac_reg) { - unsigned long sta_reg; /* STA scratch area */ - unsigned long i; - unsigned long emac_reg; + u32 sta_reg; + int i; - emac_reg = miiphy_getemac_offset (); - /* see if it is ready for 1000 nsec */ + /* wait for completion */ i = 0; - - /* see if it is ready for sec */ - while ((in_be32((void *)EMAC_STACR + emac_reg) & EMAC_STACR_OC) == - EMAC_STACR_OC_MASK) { - udelay (7); - if (i > 5) { -#ifdef ET_DEBUG - sta_reg = in_be32((void *)EMAC_STACR + emac_reg); - printf ("read : EMAC_STACR=0x%0x\n", sta_reg); /* test-only */ - printf ("read err 1\n"); -#endif + do { + sta_reg = in_be32((void *)EMAC_STACR + emac_reg); + if (i++ > 5) { + debug("%s [%d]: Timeout! EMAC_STACR=0x%0x\n", __func__, + __LINE__, sta_reg); return -1; } - i++; - } + udelay(10); + } while ((sta_reg & EMAC_STACR_OC) == EMAC_STACR_OC_MASK); + + return 0; +} + +static int emac_miiphy_command(u8 addr, u8 reg, int cmd, u16 value) +{ + u32 emac_reg; + u32 sta_reg; + + emac_reg = miiphy_getemac_offset(); + + /* wait for completion */ + if (emac_miiphy_wait(emac_reg) != 0) + return -1; + sta_reg = reg; /* reg address */ + /* set clock (50Mhz) and read flags */ #if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_460EX) || defined(CONFIG_460GT) || \ 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; + sta_reg = (sta_reg & ~EMAC_STACR_OP_MASK) | cmd; #else - sta_reg |= EMAC_STACR_READ; + sta_reg |= cmd; #endif #else - sta_reg = (sta_reg | EMAC_STACR_READ) & ~EMAC_STACR_CLK_100MHZ; + sta_reg = (sta_reg | cmd) & ~EMAC_STACR_CLK_100MHZ; #endif -#if defined(CONFIG_PHY_CLK_FREQ) && !defined(CONFIG_440GX) && \ - !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \ - !defined(CONFIG_440EPX) && !defined(CONFIG_440GRX) && \ - !defined(CONFIG_405EX) + /* Some boards (mainly 405EP based) define the PHY clock freqency fixed */ sta_reg = sta_reg | CONFIG_PHY_CLK_FREQ; -#endif - sta_reg = sta_reg | (addr << 5); /* Phy address */ + sta_reg = sta_reg | ((u32)addr << 5); /* Phy address */ sta_reg = sta_reg | EMAC_STACR_OC_MASK; /* new IBM emac v4 */ + if (cmd == EMAC_STACR_WRITE) + memcpy(&sta_reg, &value, 2); /* put in data */ + out_be32((void *)EMAC_STACR + emac_reg, sta_reg); -#ifdef ET_DEBUG - printf ("a2: write: EMAC_STACR=0x%0x\n", sta_reg); /* test-only */ -#endif + debug("%s [%d]: sta_reg=%08x\n", __func__, __LINE__, sta_reg); - sta_reg = in_be32((void *)EMAC_STACR + emac_reg); -#ifdef ET_DEBUG - 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) { - udelay (7); - if (i > 5) - return -1; + /* wait for completion */ + if (emac_miiphy_wait(emac_reg) != 0) + return -1; - i++; - sta_reg = in_be32((void *)EMAC_STACR + emac_reg); -#ifdef ET_DEBUG - printf ("a22: read : EMAC_STACR=0x%0x\n", sta_reg); /* test-only */ -#endif - } + debug("%s [%d]: sta_reg=%08x\n", __func__, __LINE__, sta_reg); if ((sta_reg & EMAC_STACR_PHYE) != 0) return -1; - *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_read (char *devname, unsigned char addr, unsigned char reg, + unsigned short *value) { - unsigned long sta_reg; /* STA scratch area */ - unsigned long i; + unsigned long sta_reg; unsigned long emac_reg; emac_reg = miiphy_getemac_offset (); - /* 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) { - if (i > 5) - return -1; - - udelay (7); - i++; - } - sta_reg = 0; - sta_reg = reg; /* reg address */ - /* set clock (50Mhz) and read flags */ -#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; -#else - sta_reg |= EMAC_STACR_WRITE; -#endif -#else - sta_reg = (sta_reg | EMAC_STACR_WRITE) & ~EMAC_STACR_CLK_100MHZ; -#endif - -#if defined(CONFIG_PHY_CLK_FREQ) && !defined(CONFIG_440GX) && \ - !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \ - !defined(CONFIG_440EPX) && !defined(CONFIG_440GRX) && \ - !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 */ - memcpy (&sta_reg, &value, 2); /* put in data */ - out_be32((void *)EMAC_STACR + emac_reg, sta_reg); + if (emac_miiphy_command(addr, reg, EMAC_STACR_READ, 0) != 0) + return -1; - /* wait for completion */ - 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 */ -#endif - while ((sta_reg & EMAC_STACR_OC) == EMAC_STACR_OC_MASK) { - udelay (7); - if (i > 5) - return -1; - - i++; - sta_reg = in_be32((void *)EMAC_STACR + emac_reg); -#ifdef ET_DEBUG - printf ("a32: read : EMAC_STACR=0x%0x\n", sta_reg); /* test-only */ -#endif - } - - if ((sta_reg & EMAC_STACR_PHYE) != 0) - return -1; + *value = *(u16 *)(&sta_reg); return 0; +} -} /* phy_write */ +/***********************************************************/ +/* 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) +{ + return emac_miiphy_command(addr, reg, EMAC_STACR_WRITE, value); +} |