[U-Boot-Users] [PATCH] PPC4xx: Add Ethernet 1000BASE-X support for PPC4xx

Larry Johnson lrj at arlinx.com
Mon Oct 29 18:00:56 CET 2007


This patch adds a new switch: "CONFIG_PHY_DYNAMIC_ANEG".  When this symbol
is defined, the PHY will advertise it's capabilities for autonegotiation
based on the capabilities shown in the PHY's status registers, including
1000BASE-X.  When "CONFIG_PHY_DYNAMIC_ANEG" is not defined, the PHY will
advertise hard-coded capabilities, as before.

Signed-off-by: Larry Johnson <lrj at acm.org>
---
diff --git a/common/miiphyutil.c b/common/miiphyutil.c
index c69501f..39e3c20 100644
--- a/common/miiphyutil.c
+++ b/common/miiphyutil.c
@@ -36,7 +36,6 @@
 #include <net.h>

 /* local debug macro */
-#define MII_DEBUG
 #undef MII_DEBUG

 #undef debug
@@ -49,10 +48,10 @@
 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);
+	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;
@@ -62,21 +61,21 @@ static struct mii_dev *current_mii;
  *
  * Initialize global data. Need to be called before any other miiphy routine.
  */
-void miiphy_init()
+void miiphy_init ()
 {
-		INIT_LIST_HEAD(&mii_devs);
-		current_mii = NULL;
+	INIT_LIST_HEAD (&mii_devs);
+	current_mii = NULL;
 }

 /*****************************************************************************
  *
  * 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))
+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;
@@ -84,63 +83,64 @@ void miiphy_register(char *name,
 	unsigned int name_len;

 	/* 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);
+	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);
+	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);
+	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);
+	memset (new_dev, 0, sizeof (struct mii_dev) + name_len);

 	/* initalize mii_dev struct fields */
-	INIT_LIST_HEAD(&new_dev->link);
+	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);
+	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);
+	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);
+	list_add_tail (&new_dev->link, &mii_devs);

 	if (!current_mii)
 		current_mii = new_dev;
 }

-int miiphy_set_current_dev(char *devname)
+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);
+	list_for_each (entry, &mii_devs) {
+		dev = list_entry (entry, struct mii_dev, link);

-		if (strcmp(devname, dev->name) == 0) {
+		if (strcmp (devname, dev->name) == 0) {
 			current_mii = dev;
 			return 0;
 		}
 	}

-	printf("No such device: %s\n", devname);
+	printf ("No such device: %s\n", devname);
 	return 1;
 }

-char *miiphy_get_current_dev()
+char *miiphy_get_current_dev ()
 {
 	if (current_mii)
 		return current_mii->name;
@@ -156,8 +156,8 @@ char *miiphy_get_current_dev()
  * Returns:
  *   0 on success
  */
-int miiphy_read(char *devname, unsigned char addr, unsigned char reg,
-		unsigned short *value)
+int miiphy_read (char *devname, unsigned char addr, unsigned char reg,
+		 unsigned short *value)
 {
 	struct list_head *entry;
 	struct mii_dev *dev;
@@ -165,22 +165,22 @@ int miiphy_read(char *devname, unsigned char addr, unsigned char reg,
 	int read_ret = 0;

 	if (!devname) {
-		printf("NULL device name!\n");
+		printf ("NULL device name!\n");
 		return 1;
 	}

-	list_for_each(entry, &mii_devs) {
-		dev = list_entry(entry, struct mii_dev, link);
+	list_for_each (entry, &mii_devs) {
+		dev = list_entry (entry, struct mii_dev, link);

-		if (strcmp(devname, dev->name) == 0) {
+		if (strcmp (devname, dev->name) == 0) {
 			found_dev = 1;
-			read_ret = dev->read(devname, addr, reg, value);
+			read_ret = dev->read (devname, addr, reg, value);
 			break;
 		}
 	}

 	if (found_dev == 0)
-		printf("No such device: %s\n", devname);
+		printf ("No such device: %s\n", devname);

 	return ((found_dev) ? read_ret : 1);
 }
@@ -193,8 +193,8 @@ int miiphy_read(char *devname, unsigned char addr, unsigned char reg,
  * Returns:
  *   0 on success
  */
-int miiphy_write(char *devname, unsigned char addr, unsigned char reg,
-		unsigned short value)
+int miiphy_write (char *devname, unsigned char addr, unsigned char reg,
+		  unsigned short value)
 {
 	struct list_head *entry;
 	struct mii_dev *dev;
@@ -202,22 +202,22 @@ int miiphy_write(char *devname, unsigned char addr, unsigned char reg,
 	int write_ret = 0;

 	if (!devname) {
-		printf("NULL device name!\n");
+		printf ("NULL device name!\n");
 		return 1;
 	}

-	list_for_each(entry, &mii_devs) {
-		dev = list_entry(entry, struct mii_dev, link);
+	list_for_each (entry, &mii_devs) {
+		dev = list_entry (entry, struct mii_dev, link);

-		if (strcmp(devname, dev->name) == 0) {
+		if (strcmp (devname, dev->name) == 0) {
 			found_dev = 1;
-			write_ret = dev->write(devname, addr, reg, value);
+			write_ret = dev->write (devname, addr, reg, value);
 			break;
 		}
 	}

 	if (found_dev == 0)
-		printf("No such device: %s\n", devname);
+		printf ("No such device: %s\n", devname);

 	return ((found_dev) ? write_ret : 1);
 }
@@ -226,23 +226,22 @@ int miiphy_write(char *devname, unsigned char addr, unsigned char reg,
  *
  * Print out list of registered MII capable devices.
  */
-void miiphy_listdev(void)
+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 ("MII devices: ");
+	list_for_each (entry, &mii_devs) {
+		dev = list_entry (entry, struct mii_dev, link);
+		printf ("'%s' ", dev->name);
 	}
-	puts("\n");
+	puts ("\n");

 	if (current_mii)
-		printf("Current device: '%s'\n", current_mii->name);
+		printf ("Current device: '%s'\n", current_mii->name);
 }

-
 /*****************************************************************************
  *
  * Read the OUI, manufacture's model number, and revision number.
@@ -254,9 +253,7 @@ void miiphy_listdev(void)
  * Returns:
  *   0 on success
  */
-int miiphy_info (char *devname,
-		 unsigned char addr,
-		 unsigned int *oui,
+int miiphy_info (char *devname, unsigned char addr, unsigned int *oui,
 		 unsigned char *model, unsigned char *rev)
 {
 	unsigned int reg = 0;
@@ -288,13 +285,12 @@ int miiphy_info (char *devname,
 #ifdef DEBUG
 	printf ("PHY_PHYIDR[1,2] @ 0x%x = 0x%08x\n", addr, reg);
 #endif
-	*oui   =                 ( reg >> 10);
-	*model = (unsigned char) ((reg >>  4) & 0x0000003F);
-	*rev   = (unsigned char) ( reg        & 0x0000000F);
+	*oui = (reg >> 10);
+	*model = (unsigned char)((reg >> 4) & 0x0000003F);
+	*rev = (unsigned char)(reg & 0x0000000F);
 	return (0);
 }

-
 /*****************************************************************************
  *
  * Reset the PHY.
@@ -345,104 +341,150 @@ int miiphy_reset (char *devname, unsigned char addr)
 	return (0);
 }

-
 /*****************************************************************************
  *
- * Determine the ethernet speed (10/100).
+ * Determine the ethernet speed (10/100/1000).  Return 10 on error.
  */
 int miiphy_speed (char *devname, unsigned char addr)
 {
-	unsigned short reg;
+	u16 bmcr;

 #if defined(CONFIG_PHY_GIGE)
-	if (miiphy_read (devname, addr, PHY_1000BTSR, &reg)) {
-		printf ("PHY 1000BT Status read failed\n");
-	} else {
-		if (reg != 0xFFFF) {
-			if ((reg & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)) !=0) {
-				return (_1000BASET);
-			}
+	u16 btsr;
+
+#if defined(CONFIG_PHY_DYNAMIC_ANEG)
+	u16 bmsr;
+
+	/* Check for 1000BASE-X. */
+	if (miiphy_read (devname, addr, PHY_BMSR, &bmsr)) {
+		printf ("PHY status");
+		goto miiphy_read_failed;
+	}
+	if (bmsr & PHY_BMSR_EXT_STAT) {
+		u16 exsr;
+
+		if (miiphy_read (devname, addr, PHY_EXSR, &exsr)) {
+			printf ("PHY extended status");
+			goto miiphy_read_failed;
+		}
+		if (exsr & (PHY_EXSR_1000XF | PHY_EXSR_1000XH)) {
+			/* 1000BASE-X */
+			return _1000BASET;
 		}
 	}
+#endif /*  defined(CONFIG_PHY_DYNAMIC_ANEG) */
+
+	/* Check for 1000BASE-T. */
+	if (miiphy_read (devname, addr, PHY_1000BTSR, &btsr)) {
+		printf ("PHY 1000BT status");
+		goto miiphy_read_failed;
+	}
+	if (btsr != 0xFFFF &&
+	    (btsr & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD))) {
+		return _1000BASET;
+	}
 #endif /* CONFIG_PHY_GIGE */

 	/* Check Basic Management Control Register first. */
-	if (miiphy_read (devname, addr, PHY_BMCR, &reg)) {
-		puts ("PHY speed read failed, assuming 10bT\n");
-		return (_10BASET);
+	if (miiphy_read (devname, addr, PHY_BMCR, &bmcr)) {
+		printf ("PHY speed");
+		goto miiphy_read_failed;
 	}
 	/* Check if auto-negotiation is on. */
-	if ((reg & PHY_BMCR_AUTON) != 0) {
+	if (bmcr & PHY_BMCR_AUTON) {
 		/* Get auto-negotiation results. */
-		if (miiphy_read (devname, addr, PHY_ANLPAR, &reg)) {
-			puts ("PHY AN speed read failed, assuming 10bT\n");
-			return (_10BASET);
-		}
-		if ((reg & PHY_ANLPAR_100) != 0) {
-			return (_100BASET);
-		} else {
-			return (_10BASET);
+		u16 anlpar;
+
+		if (miiphy_read (devname, addr, PHY_ANLPAR, &anlpar)) {
+			printf ("PHY AN speed");
+			goto miiphy_read_failed;
 		}
+		return (anlpar & PHY_ANLPAR_100) ? _100BASET : _10BASET;
 	}
 	/* Get speed from basic control settings. */
-	else if (reg & PHY_BMCR_100MB) {
-		return (_100BASET);
-	} else {
-		return (_10BASET);
-	}
+	return (bmcr & PHY_BMCR_100MB) ? _100BASET : _10BASET;

+      miiphy_read_failed:
+	printf (" read failed, assuming 10BASE-T\n");
+	return _10BASET;
 }

-
 /*****************************************************************************
  *
- * Determine full/half duplex.
+ * Determine full/half duplex.  Return half on error.
  */
 int miiphy_duplex (char *devname, unsigned char addr)
 {
-	unsigned short reg;
+	u16 bmcr;

 #if defined(CONFIG_PHY_GIGE)
-	if (miiphy_read (devname, addr, PHY_1000BTSR, &reg)) {
-		printf ("PHY 1000BT Status read failed\n");
-	} else {
-		if ( (reg != 0xFFFF) &&
-		     (reg & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)) ) {
-			if ((reg & PHY_1000BTSR_1000FD) !=0) {
-				return (FULL);
-			} else {
-				return (HALF);
+	u16 btsr;
+
+#if defined(CONFIG_PHY_DYNAMIC_ANEG)
+	u16 bmsr;
+
+	/* Check for 1000BASE-X. */
+	if (miiphy_read (devname, addr, PHY_BMSR, &bmsr)) {
+		printf ("PHY status");
+		goto miiphy_read_failed;
+	}
+	if (bmsr & PHY_BMSR_EXT_STAT) {
+		u16 exsr;
+
+		if (miiphy_read (devname, addr, PHY_EXSR, &exsr)) {
+			printf ("PHY extended status");
+			goto miiphy_read_failed;
+		}
+		if (exsr & (PHY_EXSR_1000XF | PHY_EXSR_1000XH)) {
+			/* 1000BASE-X */
+			u16 anlpar;
+
+			if (miiphy_read (devname, addr, PHY_ANLPAR, &anlpar)) {
+				printf ("1000BASE-X PHY AN duplex");
+				goto miiphy_read_failed;
 			}
+			return (anlpar & PHY_X_ANLPAR_FD) ? FULL : HALF;
+		}
+	}
+#endif /* defined(CONFIG_PHY_DYNAMIC_ANEG) */
+
+	/* Check for 1000BASE-T. */
+	if (miiphy_read (devname, addr, PHY_1000BTSR, &btsr)) {
+		printf ("PHY 1000BT status");
+		goto miiphy_read_failed;
+	}
+	if (btsr != 0xFFFF) {
+		if (btsr & PHY_1000BTSR_1000FD) {
+			return FULL;
+		} else if (btsr & PHY_1000BTSR_1000HD) {
+			return HALF;
 		}
 	}
 #endif /* CONFIG_PHY_GIGE */

 	/* Check Basic Management Control Register first. */
-	if (miiphy_read (devname, addr, PHY_BMCR, &reg)) {
-		puts ("PHY duplex read failed, assuming half duplex\n");
-		return (HALF);
+	if (miiphy_read (devname, addr, PHY_BMCR, &bmcr)) {
+		puts ("PHY duplex");
+		goto miiphy_read_failed;
 	}
 	/* Check if auto-negotiation is on. */
-	if ((reg & PHY_BMCR_AUTON) != 0) {
+	if ((bmcr & PHY_BMCR_AUTON) != 0) {
 		/* Get auto-negotiation results. */
-		if (miiphy_read (devname, addr, PHY_ANLPAR, &reg)) {
-			puts ("PHY AN duplex read failed, assuming half duplex\n");
-			return (HALF);
-		}
+		u16 anlpar;

-		if ((reg & (PHY_ANLPAR_10FD | PHY_ANLPAR_TXFD)) != 0) {
-			return (FULL);
-		} else {
-			return (HALF);
+		if (miiphy_read (devname, addr, PHY_ANLPAR, &anlpar)) {
+			puts ("PHY AN duplex");
+			goto miiphy_read_failed;
 		}
+		return (anlpar & (PHY_ANLPAR_10FD | PHY_ANLPAR_TXFD)) ?
+		    FULL : HALF;
 	}
 	/* Get speed from basic control settings. */
-	else if (reg & PHY_BMCR_DPLX) {
-		return (FULL);
-	} else {
-		return (HALF);
-	}
+	return (bmcr & PHY_BMCR_DPLX) ? FULL : HALF;

+      miiphy_read_failed:
+	printf (" read failed, assuming half duplex\n");
+	return HALF;
 }

 #ifdef CFG_FAULT_ECHO_LINK_DOWN
@@ -455,7 +497,7 @@ int miiphy_link (char *devname, unsigned char addr)
 	unsigned short reg;

 	/* dummy read; needed to latch some phys */
-	(void)miiphy_read(devname, 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);
@@ -469,5 +511,4 @@ int miiphy_link (char *devname, unsigned char addr)
 	}
 }
 #endif
-
 #endif /* CONFIG_MII */
diff --git a/cpu/ppc4xx/miiphy.c b/cpu/ppc4xx/miiphy.c
index 6b98025..55d777f 100644
--- a/cpu/ppc4xx/miiphy.c
+++ b/cpu/ppc4xx/miiphy.c
@@ -39,6 +39,9 @@
   |  19-Jul-00	 Ported to esd cpci405					     sr
   |  23-Dec-03	 Ported from miiphy.c to 440GX Travis Sawyer		     TBS
   |		 <travis.sawyer at sandburst.com>
+  |  20-Oct-07	 Added support for autonegotiation base on reported	     lrj
+  |		 capabilities, including 1000BASE-X.  Larry Johnson
+  |		 <lrj at acm.org>
   |
   +-----------------------------------------------------------------------------*/

@@ -60,7 +63,6 @@ void miiphy_dump (char *devname, unsigned char addr)
 	unsigned long i;
 	unsigned short data;

-
 	for (i = 0; i < 0x1A; i++) {
 		if (miiphy_read (devname, addr, i, &data)) {
 			printf ("read error for reg %lx\n", i);
@@ -75,15 +77,87 @@ void miiphy_dump (char *devname, unsigned char addr)
 	}			/* end for loop */
 }				/* end dump */

-
 /***********************************************************/
 /* (Re)start autonegotiation				   */
 /***********************************************************/
 int phy_setup_aneg (char *devname, unsigned char addr)
 {
-	unsigned short ctl, adv;
+	u16 bmcr;
+
+#if defined(CONFIG_PHY_DYNAMIC_ANEG)
+	/*
+	 * Set up advertisement based on capablilities reported by the PHY.
+	 * This should work for both copper and fiber.
+	 */
+	u16 bmsr;
+#if defined(CONFIG_PHY_GIGE)
+	u16 exsr = 0x0000;
+#endif
+
+	miiphy_read (devname, addr, PHY_BMSR, &bmsr);
+
+#if defined(CONFIG_PHY_GIGE)
+	if (bmsr & PHY_BMSR_EXT_STAT) {
+		miiphy_read (devname, addr, PHY_EXSR, &exsr);
+	}
+
+	if (exsr & (PHY_EXSR_1000XF | PHY_EXSR_1000XH)) {
+		/* 1000BASE-X */
+		u16 anar = 0x0000;
+
+		if (exsr & PHY_EXSR_1000XF) {
+			anar |= PHY_X_ANLPAR_FD;
+		}
+		if (exsr & PHY_EXSR_1000XH) {
+			anar |= PHY_X_ANLPAR_HD;
+		}
+		miiphy_write (devname, addr, PHY_ANAR, anar);
+	} else
+#endif
+	{
+		u16 anar, btcr;
+
+		miiphy_read (devname, addr, PHY_ANAR, &anar);
+		anar &= ~(0x5000 | PHY_ANLPAR_T4 | PHY_ANLPAR_TXFD |
+			  PHY_ANLPAR_TX | PHY_ANLPAR_10FD | PHY_ANLPAR_10);
+
+		miiphy_read (devname, addr, PHY_1000BTCR, &btcr);
+		btcr &= ~(0x00FF | PHY_1000BTCR_1000FD | PHY_1000BTCR_1000HD);
+
+		if (bmsr & PHY_BMSR_100T4) {
+			anar |= PHY_ANLPAR_T4;
+		}
+		if (bmsr & PHY_BMSR_100TXF) {
+			anar |= PHY_ANLPAR_TXFD;
+		}
+		if (bmsr & PHY_BMSR_100TXH) {
+			anar |= PHY_ANLPAR_TX;
+		}
+		if (bmsr & PHY_BMSR_10TF) {
+			anar |= PHY_ANLPAR_10FD;
+		}
+		if (bmsr & PHY_BMSR_10TH) {
+			anar |= PHY_ANLPAR_10;
+		}
+		miiphy_write (devname, addr, PHY_ANAR, anar);
+
+#if defined(CONFIG_PHY_GIGE)
+		if (exsr & PHY_EXSR_1000TF) {
+			btcr |= PHY_1000BTCR_1000FD;
+		}
+		if (exsr & PHY_EXSR_1000TH) {
+			btcr |= PHY_1000BTCR_1000HD;
+		}
+		miiphy_write (devname, addr, PHY_1000BTCR, btcr);
+#endif
+	}
+
+#else /* defined(CONFIG_PHY_DYNAMIC_ANEG) */
+	/*
+	 * Set up standard advertisement
+	 */
+	u16 adv;

-	/* Setup standard advertise */
 	miiphy_read (devname, addr, PHY_ANAR, &adv);
 	adv |= (PHY_ANLPAR_ACK | PHY_ANLPAR_RF | PHY_ANLPAR_T4 |
 		PHY_ANLPAR_TXFD | PHY_ANLPAR_TX | PHY_ANLPAR_10FD |
@@ -94,15 +168,16 @@ int phy_setup_aneg (char *devname, unsigned char addr)
 	adv |= (0x0300);
 	miiphy_write (devname, addr, PHY_1000BTCR, adv);

+#endif /* defined(CONFIG_PHY_DYNAMIC_ANEG) */
+
 	/* Start/Restart aneg */
-	miiphy_read (devname, addr, PHY_BMCR, &ctl);
-	ctl |= (PHY_BMCR_AUTON | PHY_BMCR_RST_NEG);
-	miiphy_write (devname, addr, PHY_BMCR, ctl);
+	miiphy_read (devname, addr, PHY_BMCR, &bmcr);
+	bmcr |= (PHY_BMCR_AUTON | PHY_BMCR_RST_NEG);
+	miiphy_write (devname, addr, PHY_BMCR, bmcr);

 	return 0;
 }

-
 /***********************************************************/
 /* read a phy reg and return the value with a rc	   */
 /***********************************************************/
@@ -145,21 +220,20 @@ unsigned int miiphy_getemac_offset (void)
 #endif
 }

-
-int emac4xx_miiphy_read (char *devname, unsigned char addr,
-		unsigned char reg, unsigned short *value)
+int emac4xx_miiphy_read (char *devname, unsigned char addr, unsigned char reg,
+			 unsigned short *value)
 {
 	unsigned long sta_reg;	/* STA scratch area */
 	unsigned long i;
 	unsigned long emac_reg;

-
 	emac_reg = miiphy_getemac_offset ();
 	/* see if it is ready for 1000 nsec */
 	i = 0;

 	/* see if it is ready for  sec */
-	while ((in32 (EMAC_STACR + emac_reg) & EMAC_STACR_OC) == EMAC_STACR_OC_MASK) {
+	while ((in32 (EMAC_STACR + emac_reg) & EMAC_STACR_OC) ==
+	       EMAC_STACR_OC_MASK) {
 		udelay (7);
 		if (i > 5) {
 #ifdef ET_DEBUG
@@ -175,10 +249,10 @@ int emac4xx_miiphy_read (char *devname, unsigned char addr,
 	/* set clock (50Mhz) and read flags */
 #if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
     defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
-#if defined(CONFIG_IBM_EMAC4_V4)      /* EMAC4 V4 changed bit setting */
-		sta_reg = (sta_reg & ~EMAC_STACR_OP_MASK) | EMAC_STACR_READ;
+#if defined(CONFIG_IBM_EMAC4_V4)	/* EMAC4 V4 changed bit setting */
+	sta_reg = (sta_reg & ~EMAC_STACR_OP_MASK) | EMAC_STACR_READ;
 #else
-		sta_reg |= EMAC_STACR_READ;
+	sta_reg |= EMAC_STACR_READ;
 #endif
 #else
 	sta_reg = (sta_reg | EMAC_STACR_READ) & ~EMAC_STACR_CLK_100MHZ;
@@ -198,7 +272,7 @@ int emac4xx_miiphy_read (char *devname, unsigned char addr,

 	sta_reg = in32 (EMAC_STACR + emac_reg);
 #ifdef ET_DEBUG
-		printf ("a21: read : EMAC_STACR=0x%0x\n", sta_reg);	/* test-only */
+	printf ("a21: read : EMAC_STACR=0x%0x\n", sta_reg);	/* test-only */
 #endif
 	i = 0;
 	while ((sta_reg & EMAC_STACR_OC) == EMAC_STACR_OC_MASK) {
@@ -216,19 +290,17 @@ int emac4xx_miiphy_read (char *devname, unsigned char addr,
 		return -1;
 	}

-	*value = *(short *) (&sta_reg);
+	*value = *(short *)(&sta_reg);
 	return 0;

-
 }				/* phy_read */

-
 /***********************************************************/
 /* write a phy reg and return the value with a rc	    */
 /***********************************************************/

-int emac4xx_miiphy_write (char *devname, unsigned char addr,
-		unsigned char reg, unsigned short value)
+int emac4xx_miiphy_write (char *devname, unsigned char addr, unsigned char reg,
+			  unsigned short value)
 {
 	unsigned long sta_reg;	/* STA scratch area */
 	unsigned long i;
@@ -238,7 +310,8 @@ int emac4xx_miiphy_write (char *devname, unsigned char addr,
 	/* see if it is ready for 1000 nsec */
 	i = 0;

-	while ((in32 (EMAC_STACR + emac_reg) & EMAC_STACR_OC) == EMAC_STACR_OC_MASK) {
+	while ((in32 (EMAC_STACR + emac_reg) & EMAC_STACR_OC) ==
+	       EMAC_STACR_OC_MASK) {
 		if (i > 5)
 			return -1;
 		udelay (7);
@@ -249,10 +322,10 @@ int emac4xx_miiphy_write (char *devname, unsigned char addr,
 	/* set clock (50Mhz) and read flags */
 #if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
     defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
-#if defined(CONFIG_IBM_EMAC4_V4)      /* EMAC4 V4 changed bit setting */
-		sta_reg = (sta_reg & ~EMAC_STACR_OP_MASK) | EMAC_STACR_WRITE;
+#if defined(CONFIG_IBM_EMAC4_V4)	/* EMAC4 V4 changed bit setting */
+	sta_reg = (sta_reg & ~EMAC_STACR_OP_MASK) | EMAC_STACR_WRITE;
 #else
-		sta_reg |= EMAC_STACR_WRITE;
+	sta_reg |= EMAC_STACR_WRITE;
 #endif
 #else
 	sta_reg = (sta_reg | EMAC_STACR_WRITE) & ~EMAC_STACR_CLK_100MHZ;
@@ -263,8 +336,8 @@ int emac4xx_miiphy_write (char *devname, unsigned char addr,
     !defined(CONFIG_440EPX) && !defined(CONFIG_440GRX)
 	sta_reg = sta_reg | CONFIG_PHY_CLK_FREQ;	/* Set clock frequency (PLB freq. dependend) */
 #endif
-	sta_reg = sta_reg | ((unsigned long) addr << 5);/* Phy address */
-	sta_reg = sta_reg | EMAC_STACR_OC_MASK;		/* new IBM emac v4 */
+	sta_reg = sta_reg | ((unsigned long)addr << 5);	/* Phy address */
+	sta_reg = sta_reg | EMAC_STACR_OC_MASK;	/* new IBM emac v4 */
 	memcpy (&sta_reg, &value, 2);	/* put in data */

 	out32 (EMAC_STACR + emac_reg, sta_reg);
@@ -273,7 +346,7 @@ int emac4xx_miiphy_write (char *devname, unsigned char addr,
 	i = 0;
 	sta_reg = in32 (EMAC_STACR + emac_reg);
 #ifdef ET_DEBUG
-		printf ("a31: read : EMAC_STACR=0x%0x\n", sta_reg);	/* test-only */
+	printf ("a31: read : EMAC_STACR=0x%0x\n", sta_reg);	/* test-only */
 #endif
 	while ((sta_reg & EMAC_STACR_OC) == EMAC_STACR_OC_MASK) {
 		udelay (7);
diff --git a/include/miiphy.h b/include/miiphy.h
index 71716b0..0332e4b 100644
--- a/include/miiphy.h
+++ b/include/miiphy.h
@@ -33,6 +33,7 @@
 |  04-May-99   Created							MKW
 |  07-Jul-99   Added full duplex support				MKW
 |  08-Sep-01   Tweaks							gvb
+|  28-Oct-07   Added 1000BASE-X support.  Larry Johnson <lrj at acm.org>   lrj
 |
 +----------------------------------------------------------------------------*/
 #ifndef _miiphy_h_
@@ -40,26 +41,26 @@

 #include <net.h>

-int  miiphy_read(char *devname, unsigned char addr, unsigned char reg,
+int miiphy_read(char *devname, unsigned char addr, unsigned char reg,
 		unsigned short *value);
-int  miiphy_write(char *devname, unsigned char addr, unsigned char reg,
-		unsigned short value);
-int  miiphy_info(char *devname, unsigned char addr, unsigned int  *oui,
+int miiphy_write(char *devname, unsigned char addr, unsigned char reg,
+		 unsigned short value);
+int miiphy_info(char *devname, unsigned char addr, unsigned int *oui,
 		unsigned char *model, unsigned char *rev);
-int  miiphy_reset(char *devname, unsigned char addr);
-int  miiphy_speed(char *devname, unsigned char addr);
-int  miiphy_duplex(char *devname, unsigned char addr);
+int miiphy_reset(char *devname, unsigned char addr);
+int miiphy_speed(char *devname, unsigned char addr);
+int miiphy_duplex(char *devname, unsigned char addr);
 #ifdef CFG_FAULT_ECHO_LINK_DOWN
-int  miiphy_link(char *devname, unsigned char addr);
+int miiphy_link(char *devname, unsigned char addr);
 #endif

 void miiphy_init(void);

 void miiphy_register(char *devname,
-	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));
+		     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));

 int miiphy_set_current_dev(char *devname);
 char *miiphy_get_current_dev(void);
@@ -68,14 +69,14 @@ void miiphy_listdev(void);

 #define BB_MII_DEVNAME	"bbmii"

-int bb_miiphy_read (char *devname, 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 bb_miiphy_read(char *devname, unsigned char addr,
+		   unsigned char reg, unsigned short *value);
+int bb_miiphy_write(char *devname, unsigned char addr,
+		    unsigned char reg, unsigned short value);

 /* phy seed setup */
 #define AUTO			99
-#define _1000BASET              1000
+#define _1000BASET		1000
 #define _100BASET		100
 #define _10BASET		10
 #define HALF			22
@@ -90,9 +91,10 @@ int bb_miiphy_write (char *devname, unsigned char addr,
 #define PHY_ANLPAR		0x05
 #define PHY_ANER		0x06
 #define PHY_ANNPTR		0x07
-#define PHY_ANLPNP              0x08
-#define PHY_1000BTCR            0x09
-#define PHY_1000BTSR            0x0A
+#define PHY_ANLPNP		0x08
+#define PHY_1000BTCR		0x09
+#define PHY_1000BTSR		0x0A
+#define PHY_EXSR		0x0F
 #define PHY_PHYSTS		0x10
 #define PHY_MIPSCR		0x11
 #define PHY_MIPGSR		0x12
@@ -126,6 +128,7 @@ int bb_miiphy_write (char *devname, unsigned char addr,
 #define PHY_BMSR_100TXH		0x2000
 #define PHY_BMSR_10TF		0x1000
 #define PHY_BMSR_10TH		0x0800
+#define PHY_BMSR_EXT_STAT	0x0100
 #define PHY_BMSR_PRE_SUP	0x0040
 #define PHY_BMSR_AUTN_COMP	0x0020
 #define PHY_BMSR_RF		0x0010
@@ -138,18 +141,31 @@ int bb_miiphy_write (char *devname, unsigned char addr,
 #define PHY_ANLPAR_NP		0x8000
 #define PHY_ANLPAR_ACK		0x4000
 #define PHY_ANLPAR_RF		0x2000
+#define PHY_ANLPAR_ASYMP	0x0800
+#define PHY_ANLPAR_PAUSE	0x0400
 #define PHY_ANLPAR_T4		0x0200
 #define PHY_ANLPAR_TXFD		0x0100
 #define PHY_ANLPAR_TX		0x0080
 #define PHY_ANLPAR_10FD		0x0040
 #define PHY_ANLPAR_10		0x0020
-#define PHY_ANLPAR_100		0x0380	    /* we can run at 100 */
+#define PHY_ANLPAR_100		0x0380	/* we can run at 100 */
+/* phy ANLPAR 1000BASE-X */
+#define PHY_X_ANLPAR_NP		0x8000
+#define PHY_X_ANLPAR_ACK	0x4000
+#define PHY_X_ANLPAR_RF_MASK	0x3000
+#define PHY_X_ANLPAR_PAUSE_MASK	0x0180
+#define PHY_X_ANLPAR_HD		0x0040
+#define PHY_X_ANLPAR_FD		0x0020

 #define PHY_ANLPAR_PSB_MASK     0x001f
 #define PHY_ANLPAR_PSB_802_3    0x0001
 #define PHY_ANLPAR_PSB_802_9    0x0002

-/* PHY_1000BTSR */
+/* phy 1000BTCR */
+#define PHY_1000BTCR_1000FD     0x0200
+#define PHY_1000BTCR_1000HD     0x0100
+
+/* phy 1000BTSR */
 #define PHY_1000BTSR_MSCF       0x8000
 #define PHY_1000BTSR_MSCR       0x4000
 #define PHY_1000BTSR_LRS        0x2000
@@ -157,4 +173,10 @@ int bb_miiphy_write (char *devname, unsigned char addr,
 #define PHY_1000BTSR_1000FD     0x0800
 #define PHY_1000BTSR_1000HD     0x0400

+/* phy EXSR */
+#define PHY_EXSR_1000XF		0x8000
+#define PHY_EXSR_1000XH		0x4000
+#define PHY_EXSR_1000TF		0x2000
+#define PHY_EXSR_1000TH		0x1000
+
 #endif




More information about the U-Boot mailing list