Add support for multiple PHYs.
diff --git a/common/cmd_mii.c b/common/cmd_mii.c
index f93232c..48a4e77 100644
--- a/common/cmd_mii.c
+++ b/common/cmd_mii.c
@@ -41,19 +41,21 @@
 uint last_reg;
 
 /*
- * MII read/write
+ * MII device/info/read/write
  *
  * Syntax:
- *  mii read {addr} {reg}
- *  mii write {addr} {reg} {data}
+ *  mii device {devname}
+ *  mii info   {addr}
+ *  mii read   {addr} {reg}
+ *  mii write  {addr} {reg} {data}
  */
-
 int do_mii (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 {
 	char		op;
 	unsigned char	addr, reg;
 	unsigned short	data;
 	int		rcode = 0;
+	char		*devname;
 
 #if defined(CONFIG_8xx) || defined(CONFIG_MCF52x2)
 	mii_init ();
@@ -78,8 +80,11 @@
 			data = simple_strtoul (argv[4], NULL, 16);
 	}
 
+	/* use current device */
+	devname = miiphy_get_current_dev();
+
 	/*
-	 * check info/read/write.
+	 * check device/read/write/list.
 	 */
 	if (op == 'i') {
 		unsigned char j, start, end;
@@ -91,34 +96,43 @@
 		 * Look for any and all PHYs.  Valid addresses are 0..31.
 		 */
 		if (argc >= 3) {
-			start = addrlo; end = addrhi + 1;
+			start = addr; end = addr + 1;
 		} else {
-			start = 0; end = 32;
+			start = 0; end = 31;
 		}
 
 		for (j = start; j < end; j++) {
-			if (miiphy_info (j, &oui, &model, &rev) == 0) {
+			if (miiphy_info (devname, j, &oui, &model, &rev) == 0) {
 				printf ("PHY 0x%02X: "
 					"OUI = 0x%04X, "
 					"Model = 0x%02X, "
 					"Rev = 0x%02X, "
 					"%3dbaseT, %s\n",
 					j, oui, model, rev,
-					miiphy_speed (j),
-					miiphy_duplex (j) == FULL ? "FDX" : "HDX");
+					miiphy_speed (devname, j),
+					(miiphy_duplex (devname, j) == FULL)
+						? "FDX" : "HDX");
+			} else {
+				puts ("Error reading info from the PHY\n");
 			}
 		}
 	} else if (op == 'r') {
-		if (miiphy_read (addr, reg, &data) != 0) {
+		if (miiphy_read (devname, addr, reg, &data) != 0) {
 			puts ("Error reading from the PHY\n");
 			rcode = 1;
+		} else {
+			printf ("%04X\n", data & 0x0000FFFF);
 		}
-		printf ("%04X\n", data & 0x0000FFFF);
 	} else if (op == 'w') {
-		if (miiphy_write (addr, reg, data) != 0) {
+		if (miiphy_write (devname, addr, reg, data) != 0) {
 			puts ("Error writing to the PHY\n");
 			rcode = 1;
 		}
+	} else if (op == 'd') {
+		if (argc == 2)
+			miiphy_listdev ();
+		else
+			miiphy_set_current_dev (argv[2]);
 	} else {
 		printf ("Usage:\n%s\n", cmdtp->usage);
 		return 1;
@@ -140,9 +154,11 @@
 U_BOOT_CMD(
 	mii,	5,	1,	do_mii,
 	"mii     - MII utility commands\n",
-	"info  <addr>              - display MII PHY info\n"
-	"mii read  <addr> <reg>        - read  MII PHY <addr> register <reg>\n"
-	"mii write <addr> <reg> <data> - write MII PHY <addr> register <reg>\n"
+	"device                     - list available devices\n"
+	"mii device <devname>           - set current device\n"
+	"mii info   <addr>              - display MII PHY info\n"
+	"mii read   <addr> <reg>        - read  MII PHY <addr> register <reg>\n"
+	"mii write  <addr> <reg> <data> - write MII PHY <addr> register <reg>\n"
 );
 
 #else /* ! CONFIG_TERSE_MII ================================================= */
@@ -386,7 +402,7 @@
 	return 0;
 }
 
-uint last_op;
+char last_op[2];
 uint last_data;
 uint last_addr_lo;
 uint last_addr_hi;
@@ -412,11 +428,12 @@
 /* ---------------------------------------------------------------- */
 int do_mii (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 {
-	char		op;
+	char		op[2];
 	unsigned char	addrlo, addrhi, reglo, reghi;
 	unsigned char	addr, reg;
 	unsigned short	data;
 	int		rcode = 0;
+	char		*devname;
 
 #ifdef CONFIG_8xx
 	mii_init ();
@@ -426,7 +443,8 @@
 	 * We use the last specified parameters, unless new ones are
 	 * entered.
 	 */
-	op     = last_op;
+	op[0] = last_op[0];
+	op[1] = last_op[1];
 	addrlo = last_addr_lo;
 	addrhi = last_addr_hi;
 	reglo  = last_reg_lo;
@@ -434,7 +452,12 @@
 	data   = last_data;
 
 	if ((flag & CMD_FLAG_REPEAT) == 0) {
-		op = argv[1][0];
+		op[0] = argv[1][0];
+		if (strlen(argv[1]) > 1)
+			op[1] = argv[1][1];
+		else
+			op[1] = '\0';
+
 		if (argc >= 3)
 			extract_range(argv[2], &addrlo, &addrhi);
 		if (argc >= 4)
@@ -443,10 +466,13 @@
 			data = simple_strtoul (argv[4], NULL, 16);
 	}
 
+	/* use current device */
+	devname = miiphy_get_current_dev();
+
 	/*
 	 * check info/read/write.
 	 */
-	if (op == 'i') {
+	if (op[0] == 'i') {
 		unsigned char j, start, end;
 		unsigned int oui;
 		unsigned char model;
@@ -462,22 +488,25 @@
 		}
 
 		for (j = start; j <= end; j++) {
-			if (miiphy_info (j, &oui, &model, &rev) == 0) {
+			if (miiphy_info (devname, j, &oui, &model, &rev) == 0) {
 				printf("PHY 0x%02X: "
 					"OUI = 0x%04X, "
 					"Model = 0x%02X, "
 					"Rev = 0x%02X, "
 					"%3dbaseT, %s\n",
 					j, oui, model, rev,
-					miiphy_speed (j),
-					miiphy_duplex (j) == FULL ? "FDX" : "HDX");
+					miiphy_speed (devname, j),
+					(miiphy_duplex (devname, j) == FULL)
+						? "FDX" : "HDX");
+			} else {
+				puts ("Error reading info from the PHY\n");
 			}
 		}
-	} else if (op == 'r') {
+	} else if (op[0] == 'r') {
 		for (addr = addrlo; addr <= addrhi; addr++) {
 			for (reg = reglo; reg <= reghi; reg++) {
 				data = 0xffff;
-				if (miiphy_read (addr, reg, &data) != 0) {
+				if (miiphy_read (devname, addr, reg, &data) != 0) {
 					printf(
 					"Error reading from the PHY addr=%02x reg=%02x\n",
 						addr, reg);
@@ -492,17 +521,17 @@
 			if ((addrlo != addrhi) && (reglo != reghi))
 				printf("\n");
 		}
-	} else if (op == 'w') {
+	} else if (op[0] == 'w') {
 		for (addr = addrlo; addr <= addrhi; addr++) {
 			for (reg = reglo; reg <= reghi; reg++) {
-				if (miiphy_write (addr, reg, data) != 0) {
+				if (miiphy_write (devname, addr, reg, data) != 0) {
 					printf("Error writing to the PHY addr=%02x reg=%02x\n",
 						addr, reg);
 					rcode = 1;
 				}
 			}
 		}
-	} else if (op == 'd') {
+	} else if (strncmp(op, "du", 2) == 0) {
 		ushort regs[6];
 		int ok = 1;
 		if ((reglo > 5) || (reghi > 5)) {
@@ -512,8 +541,8 @@
 			return 1;
 		}
 		for (addr = addrlo; addr <= addrhi; addr++) {
-			for (reg = 0; reg < 6; reg++) {
-				if (miiphy_read(addr, reg, &regs[reg]) != 0) {
+			for (reg = reglo; reg < reghi + 1; reg++) {
+				if (miiphy_read(devname, addr, reg, &regs[reg]) != 0) {
 					ok = 0;
 					printf(
 					"Error reading from the PHY addr=%02x reg=%02x\n",
@@ -525,6 +554,11 @@
 				MII_dump_0_to_5(regs, reglo, reghi);
 			printf("\n");
 		}
+	} else if (strncmp(op, "de", 2) == 0) {
+		if (argc == 2)
+			miiphy_listdev ();
+		else
+			miiphy_set_current_dev (argv[2]);
 	} else {
 		printf("Usage:\n%s\n", cmdtp->usage);
 		return 1;
@@ -533,7 +567,8 @@
 	/*
 	 * Save the parameters for repeats.
 	 */
-	last_op      = op;
+	last_op[0] = op[0];
+	last_op[1] = op[1];
 	last_addr_lo = addrlo;
 	last_addr_hi = addrhi;
 	last_reg_lo  = reglo;
@@ -548,10 +583,12 @@
 U_BOOT_CMD(
 	mii,	5,	1,	do_mii,
 	"mii     - MII utility commands\n",
-	"info  <addr>              - display MII PHY info\n"
-	"mii read  <addr> <reg>        - read  MII PHY <addr> register <reg>\n"
-	"mii write <addr> <reg> <data> - write MII PHY <addr> register <reg>\n"
-	"mii dump  <addr> <reg>        - pretty-print <addr> <reg> (0-5 only)\n"
+	"device                     - list available devices\n"
+	"mii device <devname>           - set current device\n"
+	"mii info   <addr>              - display MII PHY info\n"
+	"mii read   <addr> <reg>        - read  MII PHY <addr> register <reg>\n"
+	"mii write  <addr> <reg> <data> - write MII PHY <addr> register <reg>\n"
+	"mii dump   <addr> <reg>        - pretty-print <addr> <reg> (0-5 only)\n"
 	"Addr and/or reg may be ranges, e.g. 2-7.\n"
 );
 
diff --git a/common/miiphybb.c b/common/miiphybb.c
index b6af88f..adb697c 100644
--- a/common/miiphybb.c
+++ b/common/miiphybb.c
@@ -121,7 +121,8 @@
  * Returns:
  *   0 on success
  */
-int miiphy_read (unsigned char addr, unsigned char reg, unsigned short *value)
+int bb_miiphy_read (char *devname, unsigned char addr,
+		unsigned char reg, unsigned short *value)
 {
 	short rdreg;		/* register working value */
 	int j;			/* counter */
@@ -188,7 +189,8 @@
  * Returns:
  *   0 on success
  */
-int miiphy_write (unsigned char addr, unsigned char reg, unsigned short value)
+int bb_miiphy_write (char *devname, unsigned char addr,
+		unsigned char reg, unsigned short value)
 {
 	int j;			/* counter */
 #ifndef CONFIG_EP8248
diff --git a/common/miiphyutil.c b/common/miiphyutil.c
index 13b9c65..d67c8b5 100644
--- a/common/miiphyutil.c
+++ b/common/miiphyutil.c
@@ -30,6 +30,215 @@
 #include <miiphy.h>
 
 #if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
+#include <asm/types.h>
+#include <linux/list.h>
+#include <malloc.h>
+#include <net.h>
+
+/* local debug macro */
+#define MII_DEBUG
+#undef MII_DEBUG
+
+#undef debug
+#ifdef MII_DEBUG
+#define debug(fmt,args...)	printf (fmt ,##args)
+#else
+#define debug(fmt,args...)
+#endif /* MII_DEBUG */
+
+struct mii_dev {
+	struct list_head link;
+	char *name;
+	int (* read)(char *devname, unsigned char addr,
+			unsigned char reg, unsigned short *value);
+	int (* write)(char *devname, unsigned char addr,
+			unsigned char reg, unsigned short value);
+};
+
+static struct list_head mii_devs;
+static struct mii_dev *current_mii;
+
+/*****************************************************************************
+ *
+ * Register read and write MII access routines for the device <name>.
+ */
+void miiphy_register(char *name,
+		int (* read)(char *devname, unsigned char addr,
+			unsigned char reg, unsigned short *value),
+		int (* write)(char *devname, unsigned char addr,
+			unsigned char reg, unsigned short value))
+{
+	struct list_head *entry;
+	struct mii_dev *new_dev;
+	struct mii_dev *miidev;
+	static int head_initialized = 0;
+	unsigned int name_len;
+
+	if (head_initialized == 0) {
+		INIT_LIST_HEAD(&mii_devs);
+		current_mii = NULL;
+		head_initialized = 1;
+	}
+
+	/* check if we have unique name */
+	list_for_each(entry, &mii_devs) {
+		miidev = list_entry(entry, struct mii_dev, link);
+		if (strcmp(miidev->name, name) == 0) {
+			printf("miiphy_register: non unique device name '%s'\n",
+					name);
+			return;
+		}
+	}
+
+	/* allocate memory */
+	name_len = strlen(name);
+	new_dev = (struct mii_dev *)malloc(sizeof(struct mii_dev) + name_len + 1);
+
+	if(new_dev == NULL) {
+		printf("miiphy_register: cannot allocate memory for '%s'\n",
+				name);
+		return;
+	}
+	memset(new_dev, 0, sizeof(struct mii_dev) + name_len);
+
+	/* initalize mii_dev struct fields */
+	INIT_LIST_HEAD(&new_dev->link);
+	new_dev->read = read;
+	new_dev->write = write;
+	new_dev->name = (char *)(new_dev + 1);
+	strncpy(new_dev->name, name, name_len);
+	new_dev->name[name_len] = '\0';
+
+	debug("miiphy_register: added '%s', read=0x%08lx, write=0x%08lx\n",
+			new_dev->name, new_dev->read, new_dev->write);
+
+	/* add it to the list */
+	list_add_tail(&new_dev->link, &mii_devs);
+
+	if (!current_mii)
+		current_mii = new_dev;
+}
+
+int miiphy_set_current_dev(char *devname)
+{
+	struct list_head *entry;
+	struct mii_dev *dev;
+
+	list_for_each(entry, &mii_devs) {
+		dev = list_entry(entry, struct mii_dev, link);
+
+		if (strcmp(devname, dev->name) == 0) {
+			current_mii = dev;
+			return 0;
+		}
+	}
+
+	printf("No such device: %s\n", devname);
+	return 1;
+}
+
+char *miiphy_get_current_dev()
+{
+	if (current_mii)
+		return current_mii->name;
+
+	return NULL;
+}
+
+/*****************************************************************************
+ *
+ * Read to variable <value> from the PHY attached to device <devname>,
+ * use PHY address <addr> and register <reg>.
+ *
+ * Returns:
+ *   0 on success
+ */
+int miiphy_read(char *devname, unsigned char addr, unsigned char reg,
+		unsigned short *value)
+{
+	struct list_head *entry;
+	struct mii_dev *dev;
+	int found_dev = 0;
+	int read_ret = 0;
+
+	if (!devname) {
+		printf("NULL device name!\n");
+		return 1;
+	}
+
+	list_for_each(entry, &mii_devs) {
+		dev = list_entry(entry, struct mii_dev, link);
+
+		if (strcmp(devname, dev->name) == 0) {
+			found_dev = 1;
+			read_ret = dev->read(devname, addr, reg, value);
+			break;
+		}
+	}
+
+	if (found_dev == 0)
+		printf("No such device: %s\n", devname);
+
+	return ((found_dev) ? read_ret : 1);
+}
+
+/*****************************************************************************
+ *
+ * Write <value> to the PHY attached to device <devname>,
+ * use PHY address <addr> and register <reg>.
+ *
+ * Returns:
+ *   0 on success
+ */
+int miiphy_write(char *devname, unsigned char addr, unsigned char reg,
+		unsigned short value)
+{
+	struct list_head *entry;
+	struct mii_dev *dev;
+	int found_dev = 0;
+	int write_ret = 0;
+
+	if (!devname) {
+		printf("NULL device name!\n");
+		return 1;
+	}
+
+	list_for_each(entry, &mii_devs) {
+		dev = list_entry(entry, struct mii_dev, link);
+
+		if (strcmp(devname, dev->name) == 0) {
+			found_dev = 1;
+			write_ret = dev->write(devname, addr, reg, value);
+			break;
+		}
+	}
+
+	if (found_dev == 0)
+		printf("No such device: %s\n", devname);
+
+	return ((found_dev) ? write_ret : 1);
+}
+
+/*****************************************************************************
+ *
+ * Print out list of registered MII capable devices.
+ */
+void miiphy_listdev(void)
+{
+	struct list_head *entry;
+	struct mii_dev *dev;
+
+	puts("MII devices: ");
+	list_for_each(entry, &mii_devs) {
+		dev = list_entry(entry, struct mii_dev, link);
+		printf("'%s' ", dev->name);
+	}
+	puts("\n");
+
+	if (current_mii)
+		printf("Current device: '%s'\n", current_mii->name);
+}
+
 
 /*****************************************************************************
  *
@@ -42,14 +251,15 @@
  * Returns:
  *   0 on success
  */
-int miiphy_info (unsigned char addr,
+int miiphy_info (char *devname,
+		 unsigned char addr,
 		 unsigned int *oui,
 		 unsigned char *model, unsigned char *rev)
 {
 	unsigned int reg = 0;
 	unsigned short tmp;
 
-	if (miiphy_read (addr, PHY_PHYIDR2, &tmp) != 0) {
+	if (miiphy_read (devname, addr, PHY_PHYIDR2, &tmp) != 0) {
 #ifdef DEBUG
 		puts ("PHY ID register 2 read failed\n");
 #endif
@@ -65,7 +275,7 @@
 		return (-1);
 	}
 
-	if (miiphy_read (addr, PHY_PHYIDR1, &tmp) != 0) {
+	if (miiphy_read (devname, addr, PHY_PHYIDR1, &tmp) != 0) {
 #ifdef DEBUG
 		puts ("PHY ID register 1 read failed\n");
 #endif
@@ -88,18 +298,18 @@
  * Returns:
  *   0 on success
  */
-int miiphy_reset (unsigned char addr)
+int miiphy_reset (char *devname, unsigned char addr)
 {
 	unsigned short reg;
 	int loop_cnt;
 
-	if (miiphy_read (addr, PHY_BMCR, &reg) != 0) {
+	if (miiphy_read (devname, addr, PHY_BMCR, &reg) != 0) {
 #ifdef DEBUG
 		printf ("PHY status read failed\n");
 #endif
 		return (-1);
 	}
-	if (miiphy_write (addr, PHY_BMCR, reg | 0x8000) != 0) {
+	if (miiphy_write (devname, addr, PHY_BMCR, reg | 0x8000) != 0) {
 #ifdef DEBUG
 		puts ("PHY reset failed\n");
 #endif
@@ -116,7 +326,7 @@
 	loop_cnt = 0;
 	reg = 0x8000;
 	while (((reg & 0x8000) != 0) && (loop_cnt++ < 1000000)) {
-		if (miiphy_read (addr, PHY_BMCR, &reg) != 0) {
+		if (miiphy_read (devname, addr, PHY_BMCR, &reg) != 0) {
 #     ifdef DEBUG
 			puts ("PHY status read failed\n");
 #     endif
@@ -137,12 +347,12 @@
  *
  * Determine the ethernet speed (10/100).
  */
-int miiphy_speed (unsigned char addr)
+int miiphy_speed (char *devname, unsigned char addr)
 {
 	unsigned short reg;
 
 #if defined(CONFIG_PHY_GIGE)
-	if (miiphy_read (addr, PHY_1000BTSR, &reg)) {
+	if (miiphy_read (devname, addr, PHY_1000BTSR, &reg)) {
 		printf ("PHY 1000BT Status read failed\n");
 	} else {
 		if (reg != 0xFFFF) {
@@ -154,14 +364,14 @@
 #endif /* CONFIG_PHY_GIGE */
 
 	/* Check Basic Management Control Register first. */
-	if (miiphy_read (addr, PHY_BMCR, &reg)) {
+	if (miiphy_read (devname, addr, PHY_BMCR, &reg)) {
 		puts ("PHY speed read failed, assuming 10bT\n");
 		return (_10BASET);
 	}
 	/* Check if auto-negotiation is on. */
 	if ((reg & PHY_BMCR_AUTON) != 0) {
 		/* Get auto-negotiation results. */
-		if (miiphy_read (addr, PHY_ANLPAR, &reg)) {
+		if (miiphy_read (devname, addr, PHY_ANLPAR, &reg)) {
 			puts ("PHY AN speed read failed, assuming 10bT\n");
 			return (_10BASET);
 		}
@@ -185,12 +395,12 @@
  *
  * Determine full/half duplex.
  */
-int miiphy_duplex (unsigned char addr)
+int miiphy_duplex (char *devname, unsigned char addr)
 {
 	unsigned short reg;
 
 #if defined(CONFIG_PHY_GIGE)
-	if (miiphy_read (addr, PHY_1000BTSR, &reg)) {
+	if (miiphy_read (devname, addr, PHY_1000BTSR, &reg)) {
 		printf ("PHY 1000BT Status read failed\n");
 	} else {
 		if ( (reg != 0xFFFF) &&
@@ -205,14 +415,14 @@
 #endif /* CONFIG_PHY_GIGE */
 
 	/* Check Basic Management Control Register first. */
-	if (miiphy_read (addr, PHY_BMCR, &reg)) {
+	if (miiphy_read (devname, addr, PHY_BMCR, &reg)) {
 		puts ("PHY duplex read failed, assuming half duplex\n");
 		return (HALF);
 	}
 	/* Check if auto-negotiation is on. */
 	if ((reg & PHY_BMCR_AUTON) != 0) {
 		/* Get auto-negotiation results. */
-		if (miiphy_read (addr, PHY_ANLPAR, &reg)) {
+		if (miiphy_read (devname, addr, PHY_ANLPAR, &reg)) {
 			puts ("PHY AN duplex read failed, assuming half duplex\n");
 			return (HALF);
 		}
@@ -237,13 +447,13 @@
  *
  * Determine link status
  */
-int miiphy_link (unsigned char addr)
+int miiphy_link (char *devname, unsigned char addr)
 {
 	unsigned short reg;
 
 	/* dummy read; needed to latch some phys */
-	(void)miiphy_read(addr, PHY_BMSR, &reg);
-	if (miiphy_read (addr, PHY_BMSR, &reg)) {
+	(void)miiphy_read(devname, addr, PHY_BMSR, &reg);
+	if (miiphy_read (devname, addr, PHY_BMSR, &reg)) {
 		puts ("PHY_BMSR read failed, assuming no link\n");
 		return (0);
 	}