diff options
Diffstat (limited to 'drivers/net/ibm_emac')
-rw-r--r-- | drivers/net/ibm_emac/ibm_emac.h | 22 | ||||
-rw-r--r-- | drivers/net/ibm_emac/ibm_emac_core.c | 20 | ||||
-rw-r--r-- | drivers/net/ibm_emac/ibm_emac_mal.h | 5 | ||||
-rw-r--r-- | drivers/net/ibm_emac/ibm_emac_phy.c | 12 |
4 files changed, 47 insertions, 12 deletions
diff --git a/drivers/net/ibm_emac/ibm_emac.h b/drivers/net/ibm_emac/ibm_emac.h index 28c476f28c20..644edbff4f94 100644 --- a/drivers/net/ibm_emac/ibm_emac.h +++ b/drivers/net/ibm_emac/ibm_emac.h @@ -26,7 +26,8 @@ /* This is a simple check to prevent use of this driver on non-tested SoCs */ #if !defined(CONFIG_405GP) && !defined(CONFIG_405GPR) && !defined(CONFIG_405EP) && \ !defined(CONFIG_440GP) && !defined(CONFIG_440GX) && !defined(CONFIG_440SP) && \ - !defined(CONFIG_440EP) && !defined(CONFIG_NP405H) + !defined(CONFIG_440EP) && !defined(CONFIG_NP405H) && !defined(CONFIG_440SPE) && \ + !defined(CONFIG_440GR) #error "Unknown SoC. Please, check chip user manual and make sure EMAC defines are OK" #endif @@ -246,6 +247,25 @@ struct emac_regs { #define EMAC_STACR_PCDA_SHIFT 5 #define EMAC_STACR_PRA_MASK 0x1f +/* + * For the 440SPe, AMCC inexplicably changed the polarity of + * the "operation complete" bit in the MII control register. + */ +#if defined(CONFIG_440SPE) +static inline int emac_phy_done(u32 stacr) +{ + return !(stacr & EMAC_STACR_OC); +}; +#define EMAC_STACR_START EMAC_STACR_OC + +#else /* CONFIG_440SPE */ +static inline int emac_phy_done(u32 stacr) +{ + return stacr & EMAC_STACR_OC; +}; +#define EMAC_STACR_START 0 +#endif /* !CONFIG_440SPE */ + /* EMACx_TRTR */ #if !defined(CONFIG_IBM_EMAC4) #define EMAC_TRTR_SHIFT 27 diff --git a/drivers/net/ibm_emac/ibm_emac_core.c b/drivers/net/ibm_emac/ibm_emac_core.c index 943fbd1546ff..eb7d69478715 100644 --- a/drivers/net/ibm_emac/ibm_emac_core.c +++ b/drivers/net/ibm_emac/ibm_emac_core.c @@ -87,10 +87,11 @@ MODULE_LICENSE("GPL"); */ static u32 busy_phy_map; -#if defined(CONFIG_IBM_EMAC_PHY_RX_CLK_FIX) && (defined(CONFIG_405EP) || defined(CONFIG_440EP)) +#if defined(CONFIG_IBM_EMAC_PHY_RX_CLK_FIX) && \ + (defined(CONFIG_405EP) || defined(CONFIG_440EP) || defined(CONFIG_440GR)) /* 405EP has "EMAC to PHY Control Register" (CPC0_EPCTL) which can help us * with PHY RX clock problem. - * 440EP has more sane SDR0_MFR register implementation than 440GX, which + * 440EP/440GR has more sane SDR0_MFR register implementation than 440GX, which * also allows controlling each EMAC clock */ static inline void EMAC_RX_CLK_TX(int idx) @@ -100,7 +101,7 @@ static inline void EMAC_RX_CLK_TX(int idx) #if defined(CONFIG_405EP) mtdcr(0xf3, mfdcr(0xf3) | (1 << idx)); -#else /* CONFIG_440EP */ +#else /* CONFIG_440EP || CONFIG_440GR */ SDR_WRITE(DCRN_SDR_MFR, SDR_READ(DCRN_SDR_MFR) | (0x08000000 >> idx)); #endif @@ -546,7 +547,7 @@ static int __emac_mdio_read(struct ocp_enet_private *dev, u8 id, u8 reg) /* Wait for management interface to become idle */ n = 10; - while (!(in_be32(&p->stacr) & EMAC_STACR_OC)) { + while (!emac_phy_done(in_be32(&p->stacr))) { udelay(1); if (!--n) goto to; @@ -556,11 +557,12 @@ static int __emac_mdio_read(struct ocp_enet_private *dev, u8 id, u8 reg) out_be32(&p->stacr, EMAC_STACR_BASE(emac_opb_mhz()) | EMAC_STACR_STAC_READ | (reg & EMAC_STACR_PRA_MASK) - | ((id & EMAC_STACR_PCDA_MASK) << EMAC_STACR_PCDA_SHIFT)); + | ((id & EMAC_STACR_PCDA_MASK) << EMAC_STACR_PCDA_SHIFT) + | EMAC_STACR_START); /* Wait for read to complete */ n = 100; - while (!((r = in_be32(&p->stacr)) & EMAC_STACR_OC)) { + while (!emac_phy_done(r = in_be32(&p->stacr))) { udelay(1); if (!--n) goto to; @@ -594,7 +596,7 @@ static void __emac_mdio_write(struct ocp_enet_private *dev, u8 id, u8 reg, /* Wait for management interface to be idle */ n = 10; - while (!(in_be32(&p->stacr) & EMAC_STACR_OC)) { + while (!emac_phy_done(in_be32(&p->stacr))) { udelay(1); if (!--n) goto to; @@ -605,11 +607,11 @@ static void __emac_mdio_write(struct ocp_enet_private *dev, u8 id, u8 reg, EMAC_STACR_BASE(emac_opb_mhz()) | EMAC_STACR_STAC_WRITE | (reg & EMAC_STACR_PRA_MASK) | ((id & EMAC_STACR_PCDA_MASK) << EMAC_STACR_PCDA_SHIFT) | - (val << EMAC_STACR_PHYD_SHIFT)); + (val << EMAC_STACR_PHYD_SHIFT) | EMAC_STACR_START); /* Wait for write to complete */ n = 100; - while (!(in_be32(&p->stacr) & EMAC_STACR_OC)) { + while (!emac_phy_done(in_be32(&p->stacr))) { udelay(1); if (!--n) goto to; diff --git a/drivers/net/ibm_emac/ibm_emac_mal.h b/drivers/net/ibm_emac/ibm_emac_mal.h index 15b0bdae26ac..2a2d3b24b037 100644 --- a/drivers/net/ibm_emac/ibm_emac_mal.h +++ b/drivers/net/ibm_emac/ibm_emac_mal.h @@ -32,9 +32,10 @@ * reflect the fact that 40x and 44x have slightly different MALs. --ebs */ #if defined(CONFIG_405GP) || defined(CONFIG_405GPR) || defined(CONFIG_405EP) || \ - defined(CONFIG_440EP) || defined(CONFIG_NP405H) + defined(CONFIG_440EP) || defined(CONFIG_440GR) || defined(CONFIG_NP405H) #define MAL_VERSION 1 -#elif defined(CONFIG_440GP) || defined(CONFIG_440GX) || defined(CONFIG_440SP) +#elif defined(CONFIG_440GP) || defined(CONFIG_440GX) || defined(CONFIG_440SP) || \ + defined(CONFIG_440SPE) #define MAL_VERSION 2 #else #error "Unknown SoC, please check chip manual and choose MAL 'version'" diff --git a/drivers/net/ibm_emac/ibm_emac_phy.c b/drivers/net/ibm_emac/ibm_emac_phy.c index a27e49cfe43b..67935dd33a65 100644 --- a/drivers/net/ibm_emac/ibm_emac_phy.c +++ b/drivers/net/ibm_emac/ibm_emac_phy.c @@ -236,12 +236,16 @@ static struct mii_phy_def genmii_phy_def = { }; /* CIS8201 */ +#define MII_CIS8201_10BTCSR 0x16 +#define TENBTCSR_ECHO_DISABLE 0x2000 #define MII_CIS8201_EPCR 0x17 #define EPCR_MODE_MASK 0x3000 #define EPCR_GMII_MODE 0x0000 #define EPCR_RGMII_MODE 0x1000 #define EPCR_TBI_MODE 0x2000 #define EPCR_RTBI_MODE 0x3000 +#define MII_CIS8201_ACSR 0x1c +#define ACSR_PIN_PRIO_SELECT 0x0004 static int cis8201_init(struct mii_phy *phy) { @@ -269,6 +273,14 @@ static int cis8201_init(struct mii_phy *phy) } phy_write(phy, MII_CIS8201_EPCR, epcr); + + /* MII regs override strap pins */ + phy_write(phy, MII_CIS8201_ACSR, + phy_read(phy, MII_CIS8201_ACSR) | ACSR_PIN_PRIO_SELECT); + + /* Disable TX_EN -> CRS echo mode, otherwise 10/HDX doesn't work */ + phy_write(phy, MII_CIS8201_10BTCSR, + phy_read(phy, MII_CIS8201_10BTCSR) | TENBTCSR_ECHO_DISABLE); return 0; } |