diff options
Diffstat (limited to 'drivers/eepro100.c')
-rw-r--r-- | drivers/eepro100.c | 118 |
1 files changed, 100 insertions, 18 deletions
diff --git a/drivers/eepro100.c b/drivers/eepro100.c index 0054e87..04c17f6 100644 --- a/drivers/eepro100.c +++ b/drivers/eepro100.c @@ -26,6 +26,7 @@ #include <net.h> #include <asm/io.h> #include <pci.h> +#include <miiphy.h> #undef DEBUG @@ -271,49 +272,124 @@ static inline void OUTL (struct eth_device *dev, int command, u_long addr) *(volatile u32 *) ((addr + dev->iobase)) = cpu_to_le32 (command); } -#if defined (CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) +#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) static inline int INL (struct eth_device *dev, u_long addr) { return le32_to_cpu (*(volatile u32 *) (addr + dev->iobase)); } -int miiphy_read (unsigned char addr, - unsigned char reg, - unsigned short *value) +static int get_phyreg (struct eth_device *dev, unsigned char addr, + unsigned char reg, unsigned short *value) { - int cmd = (2 << 26) | ((addr & 0x1f) << 21) | ((reg & 0x1f) << 16); - - struct eth_device *dev = eth_get_dev (); + int cmd; + int timeout = 50; + /* read requested data */ + cmd = (2 << 26) | ((addr & 0x1f) << 21) | ((reg & 0x1f) << 16); OUTL (dev, cmd, SCBCtrlMDI); do { + udelay(1000); cmd = INL (dev, SCBCtrlMDI); - } while (!(cmd & (1 << 28))); + } while (!(cmd & (1 << 28)) && (--timeout)); + + if (timeout == 0) + return -1; *value = (unsigned short) (cmd & 0xffff); return 0; } -int miiphy_write (unsigned char addr, - unsigned char reg, - unsigned short value) +static int set_phyreg (struct eth_device *dev, unsigned char addr, + unsigned char reg, unsigned short value) { - int cmd = (1 << 26) | ((addr & 0x1f) << 21) | ((reg & 0x1f) << 16); - - struct eth_device *dev = eth_get_dev (); + int cmd; + int timeout = 50; + /* write requested data */ + cmd = (1 << 26) | ((addr & 0x1f) << 21) | ((reg & 0x1f) << 16); OUTL (dev, cmd | value, SCBCtrlMDI); - while (!(INL (dev, SCBCtrlMDI) & (1 << 28))); + while (!(INL (dev, SCBCtrlMDI) & (1 << 28)) && (--timeout)) + udelay(1000); + + if (timeout == 0) + return -1; return 0; } -#endif /* (CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) */ - /* Wait for the chip get the command. - */ +/* Check if given phyaddr is valid, i.e. there is a PHY connected. + * Do this by checking model value field from ID2 register. + */ +static struct eth_device* verify_phyaddr (char *devname, unsigned char addr) +{ + struct eth_device *dev; + unsigned short value; + unsigned char model; + + dev = eth_get_dev_by_name(devname); + if (dev == NULL) { + printf("%s: no such device\n", devname); + return NULL; + } + + /* read id2 register */ + if (get_phyreg(dev, addr, PHY_PHYIDR2, &value) != 0) { + printf("%s: mii read timeout!\n", devname); + return NULL; + } + + /* get model */ + model = (unsigned char)((value >> 4) & 0x003f); + + if (model == 0) { + printf("%s: no PHY at address %d\n", devname, addr); + return NULL; + } + + return dev; +} + +static int eepro100_miiphy_read (char *devname, unsigned char addr, + unsigned char reg, unsigned short *value) +{ + struct eth_device *dev; + + dev = verify_phyaddr(devname, addr); + if (dev == NULL) + return -1; + + if (get_phyreg(dev, addr, reg, value) != 0) { + printf("%s: mii read timeout!\n", devname); + return -1; + } + + return 0; +} + +static int eepro100_miiphy_write (char *devname, unsigned char addr, + unsigned char reg, unsigned short value) +{ + struct eth_device *dev; + + dev = verify_phyaddr(devname, addr); + if (dev == NULL) + return -1; + + if (set_phyreg(dev, addr, reg, value) != 0) { + printf("%s: mii write timeout!\n", devname); + return -1; + } + + return 0; +} + +#endif /* defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) */ + +/* Wait for the chip get the command. +*/ static int wait_for_eepro100 (struct eth_device *dev) { int i; @@ -386,6 +462,12 @@ int eepro100_initialize (bd_t * bis) eth_register (dev); +#if defined (CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) + /* register mii command access routines */ + miiphy_register(dev->name, + eepro100_miiphy_read, eepro100_miiphy_write); +#endif + card_number++; /* Set the latency timer for value. |