diff options
-rw-r--r-- | drivers/net/mxc_fec.c | 150 |
1 files changed, 95 insertions, 55 deletions
diff --git a/drivers/net/mxc_fec.c b/drivers/net/mxc_fec.c index 60a0f0a..76c6d5c 100644 --- a/drivers/net/mxc_fec.c +++ b/drivers/net/mxc_fec.c @@ -78,9 +78,7 @@ #if defined(CONFIG_MX6Q) || defined(CONFIG_MX6DL) extern int mx6_rgmii_rework(char *devname, int phy_addr); -#endif -#if defined(CONFIG_MX6Q_ARM2) || defined(CONFIG_MX6Q_SABRESD) || \ - defined(CONFIG_MX6DL_SABRESD) + #define PHY_MIPSCR_LINK_UP (0x1 << 10) #define PHY_MIPSCR_SPEED_MASK (0x3 << 14) #define PHY_MIPSCR_1000M (0x2 << 14) @@ -104,6 +102,27 @@ extern int mx6_rgmii_rework(char *devname, int phy_addr); #define FEC_MII_TICK CONFIG_FEC_TICKET #endif +/* define phy ID */ +#define PHY_OUID_MASK 0x1FFFFF8 +#define PHY_OUID_GET(high_bits, low_bits) \ + ((high_bits << 19) | (low_bits << 3)) +#define PHY_ATHEROS_OUID_GET(valh, vall) \ + PHY_OUID_GET((valh & 0x3F), vall) +#define PHY_MICREL_OUID_GET(valh, vall) \ + PHY_OUID_GET((valh >> 10), vall) +#define PHY_AR8031_OUID PHY_OUID_GET(0x34, 0x4D) +#define PHY_AR8033_OUID PHY_OUID_GET(0x34, 0x4D) +#define PHY_KSZ9021_OUID PHY_OUID_GET(0x5, 0x22) + +/* Get phy ID */ +static unsigned int fec_phy_ouid; +#define phy_is_ksz9021() (((fec_phy_ouid & PHY_OUID_MASK) == PHY_KSZ9021_OUID) \ + ? 1 : 0) +#define phy_is_ar8031() (((fec_phy_ouid & PHY_OUID_MASK) == PHY_AR8031_OUID) \ + ? 1 : 0) +#define phy_is_ar8033() (((fec_phy_ouid & PHY_OUID_MASK) == PHY_AR8033_OUID) \ + ? 1 : 0) + DECLARE_GLOBAL_DATA_PTR; #if defined(CONFIG_MII_GASKET) @@ -195,6 +214,26 @@ static void mxc_fec_phy_powerup(char *devname, int phy_addr) mxc_fec_mii_write(devname, phy_addr, PHY_BMCR, (value & ~PHY_BMCR_POWD)); } +static void mxc_get_phy_ouid(char *devname, int phy_addr) +{ + unsigned short value1, value2; + + mxc_fec_mii_read(devname, phy_addr, PHY_PHYIDR1, &value1); + mxc_fec_mii_read(devname, phy_addr, PHY_PHYIDR2, &value2); + + fec_phy_ouid = PHY_ATHEROS_OUID_GET(value2, value1); + if (phy_is_ar8031()) + return; + else if (phy_is_ar8033()) + return; + + fec_phy_ouid = PHY_MICREL_OUID_GET(value2, value1); + if (phy_is_ksz9021()) + return; + + fec_phy_ouid = 0xFFFFFFFF; +} + static inline int __fec_mii_read(volatile fec_t *fecp, unsigned char addr, unsigned char reg, unsigned short *value) { @@ -368,56 +407,56 @@ static void setFecDuplexSpeed(volatile fec_t *fecp, unsigned char addr, } else { printf("FEC: Link is down %x\n", val); } -/* for AR8031 PHY */ -#if defined(CONFIG_MX6Q_ARM2) || defined(CONFIG_MX6Q_SABRESD) || \ - defined(CONFIG_MX6DL_SABRESD) - ret = __fec_mii_read(fecp, addr, PHY_MIPSCR, &val); - if (ret) - dup_spd = _100BASET | (FULL << 16); - else { - if ((val & PHY_MIPSCR_SPEED_MASK) == PHY_MIPSCR_1000M) - dup_spd = _1000BASET; - else if ((val & PHY_MIPSCR_SPEED_MASK) == PHY_MIPSCR_100M) - dup_spd = _100BASET; - else - dup_spd = _10BASET; - - if (val & PHY_MIPSCR_FULL_DUPLEX) - dup_spd |= (FULL << 16); - else - dup_spd |= (HALF << 16); - } -#elif defined(CONFIG_PHY_MICREL_KSZ9021) - ret = __fec_mii_read(fecp, addr, 0x1f, &val); - if (ret) - dup_spd = _100BASET | (FULL << 16); - else { - if (val & (1 << 6)) - dup_spd = _1000BASET; - else if (val & (1 << 5)) - dup_spd = _100BASET; - else - dup_spd = _10BASET; - if (val & (1 << 3)) - dup_spd |= (FULL << 16); - else - dup_spd |= (HALF << 16); - } -#else - ret = __fec_mii_read(fecp, addr, PHY_BMSR, &val); - if (ret) - dup_spd = _100BASET | (FULL << 16); - else { - if (val & (PHY_BMSR_100TXF | PHY_BMSR_100TXH | PHY_BMSR_100T4)) - dup_spd = _100BASET; - else - dup_spd = _10BASET; - if (val & (PHY_BMSR_100TXF | PHY_BMSR_10TF)) - dup_spd |= (FULL << 16); - else - dup_spd |= (HALF << 16); + + /* for Atheros PHY */ + if (phy_is_ar8031() || phy_is_ar8033()) { + ret = __fec_mii_read(fecp, addr, PHY_MIPSCR, &val); + if (ret) + dup_spd = _100BASET | (FULL << 16); + else { + if ((val & PHY_MIPSCR_SPEED_MASK) == PHY_MIPSCR_1000M) + dup_spd = _1000BASET; + else if ((val & PHY_MIPSCR_SPEED_MASK) == PHY_MIPSCR_100M) + dup_spd = _100BASET; + else + dup_spd = _10BASET; + + if (val & PHY_MIPSCR_FULL_DUPLEX) + dup_spd |= (FULL << 16); + else + dup_spd |= (HALF << 16); + } + } else if (phy_is_ksz9021()) { /* for Micrel phy */ + ret = __fec_mii_read(fecp, addr, 0x1f, &val); + if (ret) + dup_spd = _100BASET | (FULL << 16); + else { + if (val & (1 << 6)) + dup_spd = _1000BASET; + else if (val & (1 << 5)) + dup_spd = _100BASET; + else + dup_spd = _10BASET; + if (val & (1 << 3)) + dup_spd |= (FULL << 16); + else + dup_spd |= (HALF << 16); + } + } else { /* for SMSC and other unknow phys */ + ret = __fec_mii_read(fecp, addr, PHY_BMSR, &val); + if (ret) + dup_spd = _100BASET | (FULL << 16); + else { + if (val & (PHY_BMSR_100TXF | PHY_BMSR_100TXH | PHY_BMSR_100T4)) + dup_spd = _100BASET; + else + dup_spd = _10BASET; + if (val & (PHY_BMSR_100TXF | PHY_BMSR_10TF)) + dup_spd |= (FULL << 16); + else + dup_spd |= (HALF << 16); + } } -#endif } if ((dup_spd >> 16) == FULL) { @@ -838,9 +877,6 @@ static void fec_mii_phy_init(struct eth_device *dev) #if defined (CONFIG_CMD_MII) || defined (CONFIG_MII) || \ defined (CONFIG_DISCOVER_PHY) mxc_fec_mii_init(fecp); -#if defined(CONFIG_MX6Q) || defined(CONFIG_MX6DL) - mx6_rgmii_rework(dev->name, info->phy_addr); -#endif mxc_fec_phy_powerup(dev->name, info->phy_addr); #endif @@ -861,6 +897,10 @@ int fec_init(struct eth_device *dev, bd_t *bd) if (info->phy_addr < 0 || info->phy_addr > 0x1F) info->phy_addr = mxc_fec_mii_discover_phy(dev); #endif +#if defined(CONFIG_MX6Q) || defined(CONFIG_MX6DL) + mx6_rgmii_rework(dev->name, info->phy_addr); +#endif + mxc_get_phy_ouid(dev->name, info->phy_addr); setFecDuplexSpeed(fecp, (uchar)info->phy_addr, info->dup_spd); #else #ifndef CONFIG_DISCOVER_PHY |