summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorMarian Balakowicz <m8@semihalf.com>2005-10-28 22:30:33 +0200
committerMarian Balakowicz <m8@semihalf.com>2005-10-28 22:30:33 +0200
commit63ff004c4fcad9f690bf44dbd15d568bb47aac2d (patch)
tree7b64074a85da8118b6c862f14de1171b36ade0f7 /drivers
parentfe93483a0ab9dcbf7794ffbf0b029ba138380e81 (diff)
Add support for multiple PHYs.
Diffstat (limited to 'drivers')
-rw-r--r--drivers/eepro100.c118
-rw-r--r--drivers/ns7520_eth.c18
-rw-r--r--drivers/tsec.c24
3 files changed, 133 insertions, 27 deletions
diff --git a/drivers/eepro100.c b/drivers/eepro100.c
index 0054e87571f..04c17f69f6e 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.
diff --git a/drivers/ns7520_eth.c b/drivers/ns7520_eth.c
index bcdc27fa85b..a5a20dfd72e 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 069a42fe318..f860dae8b00 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 */