From 63ff004c4fcad9f690bf44dbd15d568bb47aac2d Mon Sep 17 00:00:00 2001 From: Marian Balakowicz Date: Fri, 28 Oct 2005 22:30:33 +0200 Subject: Add support for multiple PHYs. --- drivers/eepro100.c | 118 +++++++++++++++++++++++++++++++++++++++++++-------- drivers/ns7520_eth.c | 18 ++++++-- drivers/tsec.c | 24 ++++++++--- 3 files changed, 133 insertions(+), 27 deletions(-) (limited to 'drivers') 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 #include #include +#include #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. diff --git a/drivers/ns7520_eth.c b/drivers/ns7520_eth.c index bcdc27f..a5a20df 100644 --- a/drivers/ns7520_eth.c +++ b/drivers/ns7520_eth.c @@ -767,8 +767,8 @@ enum mii_status { /** * Read a 16-bit value from an MII register. */ -extern int miiphy_read(unsigned char const addr, unsigned char const reg, - unsigned short *const value) +extern int ns7520_miiphy_read(char *devname, unsigned char const addr, + unsigned char const reg, unsigned short *const value) { int ret = MII_STATUS_FAILURE; @@ -813,8 +813,8 @@ extern int miiphy_read(unsigned char const addr, unsigned char const reg, /** * Write a 16-bit value to an MII register. */ -extern int miiphy_write(unsigned char const addr, unsigned char const reg, - unsigned short const value) +extern int ns7520_miiphy_write(char *devname, unsigned char const addr, + unsigned char const reg, unsigned short const value) { int ret = MII_STATUS_FAILURE; @@ -847,3 +847,13 @@ extern int miiphy_write(unsigned char const addr, unsigned char const reg, } #endif /* defined(CONFIG_MII) */ #endif /* CONFIG_DRIVER_NS7520_ETHERNET */ + +int ns7520_miiphy_initialize(bd_t *bis) +{ +#if defined(CONFIG_DRIVER_NS7520_ETHERNET) +#if defined(CONFIG_MII) + miiphy_register("ns7520phy", ns7520_miiphy_read, ns7520_miiphy_write); +#endif +#endif + return 0; +} diff --git a/drivers/tsec.c b/drivers/tsec.c index 069a42f..f860dae 100644 --- a/drivers/tsec.c +++ b/drivers/tsec.c @@ -21,8 +21,9 @@ #if defined(CONFIG_TSEC_ENET) #include "tsec.h" +#include "miiphy.h" -#define TX_BUF_CNT 2 +#define TX_BUF_CNT 2 static uint rxIdx; /* index of the current RX buffer */ static uint txIdx; /* index of the current TX buffer */ @@ -120,6 +121,10 @@ struct phy_info * get_phy_info(struct eth_device *dev); void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd); static void adjust_link(struct eth_device *dev); static void relocate_cmds(void); +static int tsec_miiphy_write(char *devname, unsigned char addr, + unsigned char reg, unsigned short value); +static int tsec_miiphy_read(char *devname, unsigned char addr, + unsigned char reg, unsigned short *value); /* Initialize device structure. Returns success if PHY * initialization succeeded (i.e. if it recognizes the PHY) @@ -169,6 +174,11 @@ int tsec_initialize(bd_t *bis, int index, char *devname) priv->regs->maccfg1 |= MACCFG1_SOFT_RESET; priv->regs->maccfg1 &= ~(MACCFG1_SOFT_RESET); +#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) \ + && !defined(BITBANGMII) + miiphy_register(dev->name, tsec_miiphy_read, tsec_miiphy_write); +#endif + /* Try to initialize PHY here, and return */ return init_phy(dev); } @@ -1058,7 +1068,8 @@ static void relocate_cmds(void) } -#ifndef CONFIG_BITBANGMII +#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) \ + && !defined(BITBANGMII) struct tsec_private * get_priv_for_phy(unsigned char phyaddr) { @@ -1078,7 +1089,8 @@ struct tsec_private * get_priv_for_phy(unsigned char phyaddr) * Returns: * 0 on success */ -int miiphy_read(unsigned char addr, unsigned char reg, unsigned short *value) +static int tsec_miiphy_read(char *devname, unsigned char addr, + unsigned char reg, unsigned short *value) { unsigned short ret; struct tsec_private *priv = get_priv_for_phy(addr); @@ -1100,7 +1112,8 @@ int miiphy_read(unsigned char addr, unsigned char reg, unsigned short *value) * Returns: * 0 on success */ -int miiphy_write(unsigned char addr, unsigned char reg, unsigned short value) +static int tsec_miiphy_write(char *devname, unsigned char addr, + unsigned char reg, unsigned short value) { struct tsec_private *priv = get_priv_for_phy(addr); @@ -1114,6 +1127,7 @@ int miiphy_write(unsigned char addr, unsigned char reg, unsigned short value) return 0; } -#endif /* CONFIG_BITBANGMII */ +#endif /* defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) + && !defined(BITBANGMII) */ #endif /* CONFIG_TSEC_ENET */ -- cgit v1.1