All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v2 0/6] Universal PHY Infrastructure
@ 2011-04-05 21:59 Andy Fleming
  2011-04-05 21:59 ` [U-Boot] [PATCH v2 1/6] tsec: use IO accessors for IO accesses Andy Fleming
  2011-04-06 12:07 ` [U-Boot] [PATCH v2 0/6] Universal PHY Infrastructure Detlev Zundel
  0 siblings, 2 replies; 27+ messages in thread
From: Andy Fleming @ 2011-04-05 21:59 UTC (permalink / raw)
  To: u-boot

Or PHY Lib for U-Boot.

This sequence of patches adds infrastructure for universally-available PHY
drivers (and MDIO drivers).  It piggy-backs on the existing miiphy code, for
backwards compatibility, but it also creates a new set of APIs. This was
necessary partly to provide cleaner interfaces for more robust driver
support, and partly because one goal was to support 10G (802.3 Clause 45) MDIO
buses, which has an extra argument for addressing PHY registers.

The first three patches clear the way, and are in this sequence mostly
because the tsec changes depend on them.

Special thanks goes to Mingkai Hu, who did a substantial amount
of work up front to convert the tsec PHY code into something more usable,
which I have mostly copied for the purposes of PHY Lib.

As the subject says, these are submitted here for comment.  I hope they
will go in for the presumptive June release.

This second version cleans up all checkpatch errors that I reasonably could,
and addresses most of the comments from the first round of reviews.

I have removed the mdio command patch, as I want to rework it a bit, and it's
not currently necessary unless you want to interact with a 10G PHY from the
command line.  I should submit a new version of that, soon.

I also got Kumar to remove the tsec patches I reworked slightly from his tree, so that these can go in without conflict.


Andy Fleming (4):
  Remove instances of phy_read/write
  Create PHY Lib for U-Boot
  phylib: Add a bunch of PHY drivers from tsec
  tsec: Convert tsec to use PHY Lib

Mingkai Hu (2):
  tsec: use IO accessors for IO accesses
  tsec: arrange the code to avoid useless function declaration

 arch/powerpc/include/asm/config.h         |    7 +
 arch/powerpc/include/asm/fsl_enet.h       |   10 +
 board/freescale/mpc837xemds/mpc837xemds.c |    7 +
 board/freescale/mpc8536ds/mpc8536ds.c     |    6 +
 board/freescale/mpc8544ds/mpc8544ds.c     |   30 +
 board/freescale/mpc8572ds/mpc8572ds.c     |    6 +
 board/freescale/p1022ds/p1022ds.c         |    6 +
 board/freescale/p1_p2_rdb/p1_p2_rdb.c     |    6 +
 board/freescale/p2020ds/p2020ds.c         |    7 +
 common/Makefile                           |    1 +
 common/miiphyutil.c                       |  308 +++--
 drivers/net/Makefile                      |    2 +-
 drivers/net/dm9000x.c                     |   18 +-
 drivers/net/enc28j60.c                    |   24 +-
 drivers/net/fsl_mdio.c                    |  120 ++
 drivers/net/phy/Makefile                  |   12 +
 drivers/net/phy/atheros.c                 |   48 +
 drivers/net/phy/broadcom.c                |  286 +++++
 drivers/net/phy/davicom.c                 |   98 ++
 drivers/net/phy/lxt.c                     |   87 ++
 drivers/net/phy/marvell.c                 |  376 ++++++
 drivers/net/phy/micrel.c                  |   40 +
 drivers/net/phy/natsemi.c                 |   96 ++
 drivers/net/phy/phy.c                     |  750 +++++++++++
 drivers/net/phy/realtek.c                 |  130 ++
 drivers/net/phy/teranetics.c              |   54 +
 drivers/net/phy/vitesse.c                 |  242 ++++
 drivers/net/tsec.c                        | 1992 ++++-------------------------
 drivers/net/uli526x.c                     |   24 +-
 drivers/qe/uec.c                          |    3 -
 drivers/qe/uec_phy.c                      |  145 ++-
 include/fsl_mdio.h                        |   62 +
 include/miiphy.h                          |   67 +-
 include/phy.h                             |  500 ++++++++
 include/phylib_all_drivers.h              |   25 +
 include/tsec.h                            |  302 +----
 net/eth.c                                 |    6 +
 37 files changed, 3693 insertions(+), 2210 deletions(-)
 create mode 100644 drivers/net/fsl_mdio.c
 create mode 100644 drivers/net/phy/atheros.c
 create mode 100644 drivers/net/phy/broadcom.c
 create mode 100644 drivers/net/phy/davicom.c
 create mode 100644 drivers/net/phy/lxt.c
 create mode 100644 drivers/net/phy/marvell.c
 create mode 100644 drivers/net/phy/micrel.c
 create mode 100644 drivers/net/phy/natsemi.c
 create mode 100644 drivers/net/phy/phy.c
 create mode 100644 drivers/net/phy/realtek.c
 create mode 100644 drivers/net/phy/teranetics.c
 create mode 100644 drivers/net/phy/vitesse.c
 create mode 100644 include/fsl_mdio.h
 create mode 100644 include/phy.h
 create mode 100644 include/phylib_all_drivers.h

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [U-Boot] [PATCH v2 1/6] tsec: use IO accessors for IO accesses
  2011-04-05 21:59 [U-Boot] [PATCH v2 0/6] Universal PHY Infrastructure Andy Fleming
@ 2011-04-05 21:59 ` Andy Fleming
  2011-04-05 21:59   ` [U-Boot] [PATCH v2 2/6] tsec: arrange the code to avoid useless function declaration Andy Fleming
  2011-04-06 12:29   ` [U-Boot] [PATCH v2 1/6] tsec: use IO accessors for IO accesses Detlev Zundel
  2011-04-06 12:07 ` [U-Boot] [PATCH v2 0/6] Universal PHY Infrastructure Detlev Zundel
  1 sibling, 2 replies; 27+ messages in thread
From: Andy Fleming @ 2011-04-05 21:59 UTC (permalink / raw)
  To: u-boot

From: Mingkai Hu <Mingkai.hu@freescale.com>

Signed-off-by: Mingkai Hu <Mingkai.hu@freescale.com>
Acked-by: Andy Fleming <afleming@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
Fixed the commit message's spelling

 drivers/net/tsec.c |  242 +++++++++++++++++++++++++++-------------------------
 include/tsec.h     |    8 +-
 2 files changed, 130 insertions(+), 120 deletions(-)

diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c
index 9a91b9e..4ea9813 100644
--- a/drivers/net/tsec.c
+++ b/drivers/net/tsec.c
@@ -5,7 +5,7 @@
  * terms of the GNU Public License, Version 2, incorporated
  * herein by reference.
  *
- * Copyright 2004-2010 Freescale Semiconductor, Inc.
+ * Copyright 2004-2011 Freescale Semiconductor, Inc.
  * (C) Copyright 2003, Motorola, Inc.
  * author Andy Fleming
  *
@@ -50,7 +50,7 @@ static int tsec_recv(struct eth_device *dev);
 static int tsec_init(struct eth_device *dev, bd_t * bd);
 static int tsec_initialize(bd_t * bis, struct tsec_info_struct *tsec_info);
 static void tsec_halt(struct eth_device *dev);
-static void init_registers(volatile tsec_t * regs);
+static void init_registers(tsec_t *regs);
 static void startup_tsec(struct eth_device *dev);
 static int init_phy(struct eth_device *dev);
 void write_phy_reg(struct tsec_private *priv, uint regnum, uint value);
@@ -166,9 +166,9 @@ static int tsec_initialize(bd_t * bis, struct tsec_info_struct *tsec_info)
 	eth_register(dev);
 
 	/* Reset the MAC */
-	priv->regs->maccfg1 |= MACCFG1_SOFT_RESET;
+	setbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
 	udelay(2);  /* Soft Reset must be asserted for 3 TX clocks */
-	priv->regs->maccfg1 &= ~(MACCFG1_SOFT_RESET);
+	clrbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
 
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \
 	&& !defined(BITBANGMII)
@@ -190,16 +190,16 @@ static int tsec_init(struct eth_device *dev, bd_t * bd)
 	char tmpbuf[MAC_ADDR_LEN];
 	int i;
 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
-	volatile tsec_t *regs = priv->regs;
+	tsec_t *regs = priv->regs;
 
 	/* Make sure the controller is stopped */
 	tsec_halt(dev);
 
 	/* Init MACCFG2.  Defaults to GMII */
-	regs->maccfg2 = MACCFG2_INIT_SETTINGS;
+	out_be32(&regs->maccfg2, MACCFG2_INIT_SETTINGS);
 
 	/* Init ECNTRL */
-	regs->ecntrl = ECNTRL_INIT_SETTINGS;
+	out_be32(&regs->ecntrl, ECNTRL_INIT_SETTINGS);
 
 	/* Copy the station address into the address registers.
 	 * Backwards, because little endian MACS are dumb */
@@ -209,11 +209,11 @@ static int tsec_init(struct eth_device *dev, bd_t * bd)
 	tempval = (tmpbuf[0] << 24) | (tmpbuf[1] << 16) | (tmpbuf[2] << 8) |
 		  tmpbuf[3];
 
-	regs->macstnaddr1 = tempval;
+	out_be32(&regs->macstnaddr1, tempval);
 
 	tempval = *((uint *) (tmpbuf + 4));
 
-	regs->macstnaddr2 = tempval;
+	out_be32(&regs->macstnaddr2, tempval);
 
 	/* reset the indices to zero */
 	rxIdx = 0;
@@ -230,17 +230,18 @@ static int tsec_init(struct eth_device *dev, bd_t * bd)
 }
 
 /* Writes the given phy's reg with value, using the specified MDIO regs */
-static void tsec_local_mdio_write(volatile tsec_mdio_t *phyregs, uint addr,
+static void tsec_local_mdio_write(tsec_mdio_t *phyregs, uint addr,
 		uint reg, uint value)
 {
 	int timeout = 1000000;
 
-	phyregs->miimadd = (addr << 8) | reg;
-	phyregs->miimcon = value;
+	out_be32(&phyregs->miimadd, (addr << 8) | reg);
+	out_be32(&phyregs->miimcon, value);
 	asm("sync");
 
 	timeout = 1000000;
-	while ((phyregs->miimind & MIIMIND_BUSY) && timeout--) ;
+	while ((in_be32(&phyregs->miimind) & MIIMIND_BUSY) && timeout--)
+		;
 }
 
 
@@ -254,28 +255,28 @@ static void tsec_local_mdio_write(volatile tsec_mdio_t *phyregs, uint addr,
  * notvalid bit cleared), and the bus to cease activity (miimind
  * busy bit cleared), and then returns the value
  */
-static uint tsec_local_mdio_read(volatile tsec_mdio_t *phyregs,
-				uint phyid, uint regnum)
+static uint tsec_local_mdio_read(tsec_mdio_t *phyregs, uint phyid, uint regnum)
 {
 	uint value;
 
 	/* Put the address of the phy, and the register
 	 * number into MIIMADD */
-	phyregs->miimadd = (phyid << 8) | regnum;
+	out_be32(&phyregs->miimadd, (phyid << 8) | regnum);
 
 	/* Clear the command register, and wait */
-	phyregs->miimcom = 0;
+	out_be32(&phyregs->miimcom, 0);
 	asm("sync");
 
 	/* Initiate a read command, and wait */
-	phyregs->miimcom = MIIM_READ_COMMAND;
+	out_be32(&phyregs->miimcom, MIIM_READ_COMMAND);
 	asm("sync");
 
 	/* Wait for the the indication that the read is done */
-	while ((phyregs->miimind & (MIIMIND_NOTVALID | MIIMIND_BUSY))) ;
+	while ((in_be32(&phyregs->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY)))
+		;
 
 	/* Grab the value read from the PHY */
-	value = phyregs->miimstat;
+	value = in_be32(&phyregs->miimstat);
 
 	return value;
 }
@@ -321,18 +322,19 @@ static int init_phy(struct eth_device *dev)
 {
 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
 	struct phy_info *curphy;
-	volatile tsec_t *regs = priv->regs;
+	tsec_t *regs = priv->regs;
 
 	/* Assign a Physical address to the TBI */
-	regs->tbipa = CONFIG_SYS_TBIPA_VALUE;
+	out_be32(&regs->tbipa, CONFIG_SYS_TBIPA_VALUE);
 	asm("sync");
 
 	/* Reset MII (due to new addresses) */
-	priv->phyregs->miimcfg = MIIMCFG_RESET;
+	out_be32(&priv->phyregs->miimcfg, MIIMCFG_RESET);
 	asm("sync");
-	priv->phyregs->miimcfg = MIIMCFG_INIT_VALUE;
+	out_be32(&priv->phyregs->miimcfg, MIIMCFG_INIT_VALUE);
 	asm("sync");
-	while (priv->phyregs->miimind & MIIMIND_BUSY) ;
+	while (in_be32(&priv->phyregs->miimind) & MIIMIND_BUSY)
+		;
 
 	/* Get the cmd structure corresponding to the attached
 	 * PHY */
@@ -345,7 +347,7 @@ static int init_phy(struct eth_device *dev)
 		return 0;
 	}
 
-	if (regs->ecntrl & ECNTRL_SGMII_MODE)
+	if (in_be32(&regs->ecntrl) & ECNTRL_SGMII_MODE)
 		tsec_configure_serdes(priv);
 
 	priv->phyinfo = curphy;
@@ -838,16 +840,17 @@ static uint mii_parse_dm9161_scsr(uint mii_reg, struct tsec_private * priv)
 static uint mii_cis8204_fixled(uint mii_reg, struct tsec_private * priv)
 {
 	uint phyid;
-	volatile tsec_mdio_t *regbase = priv->phyregs;
+	tsec_mdio_t *regbase = priv->phyregs;
 	int timeout = 1000000;
 
 	for (phyid = 0; phyid < 4; phyid++) {
-		regbase->miimadd = (phyid << 8) | mii_reg;
-		regbase->miimcon = MIIM_CIS8204_SLEDCON_INIT;
+		out_be32(&regbase->miimadd, (phyid << 8) | mii_reg);
+		out_be32(&regbase->miimcon, MIIM_CIS8204_SLEDCON_INIT);
 		asm("sync");
 
 		timeout = 1000000;
-		while ((regbase->miimind & MIIMIND_BUSY) && timeout--) ;
+		while ((in_be32(&regbase->miimind) & MIIMIND_BUSY) && timeout--)
+			;
 	}
 
 	return MIIM_CIS8204_SLEDCON_INIT;
@@ -874,45 +877,45 @@ static uint mii_m88e1111s_setmode(uint mii_reg, struct tsec_private *priv)
  * those we don't care about (unless zero is bad, in which case,
  * choose a more appropriate value)
  */
-static void init_registers(volatile tsec_t * regs)
+static void init_registers(tsec_t *regs)
 {
 	/* Clear IEVENT */
-	regs->ievent = IEVENT_INIT_CLEAR;
-
-	regs->imask = IMASK_INIT_CLEAR;
-
-	regs->hash.iaddr0 = 0;
-	regs->hash.iaddr1 = 0;
-	regs->hash.iaddr2 = 0;
-	regs->hash.iaddr3 = 0;
-	regs->hash.iaddr4 = 0;
-	regs->hash.iaddr5 = 0;
-	regs->hash.iaddr6 = 0;
-	regs->hash.iaddr7 = 0;
-
-	regs->hash.gaddr0 = 0;
-	regs->hash.gaddr1 = 0;
-	regs->hash.gaddr2 = 0;
-	regs->hash.gaddr3 = 0;
-	regs->hash.gaddr4 = 0;
-	regs->hash.gaddr5 = 0;
-	regs->hash.gaddr6 = 0;
-	regs->hash.gaddr7 = 0;
-
-	regs->rctrl = 0x00000000;
+	out_be32(&regs->ievent, IEVENT_INIT_CLEAR);
+
+	out_be32(&regs->imask, IMASK_INIT_CLEAR);
+
+	out_be32(&regs->hash.iaddr0, 0);
+	out_be32(&regs->hash.iaddr1, 0);
+	out_be32(&regs->hash.iaddr2, 0);
+	out_be32(&regs->hash.iaddr3, 0);
+	out_be32(&regs->hash.iaddr4, 0);
+	out_be32(&regs->hash.iaddr5, 0);
+	out_be32(&regs->hash.iaddr6, 0);
+	out_be32(&regs->hash.iaddr7, 0);
+
+	out_be32(&regs->hash.gaddr0, 0);
+	out_be32(&regs->hash.gaddr1, 0);
+	out_be32(&regs->hash.gaddr2, 0);
+	out_be32(&regs->hash.gaddr3, 0);
+	out_be32(&regs->hash.gaddr4, 0);
+	out_be32(&regs->hash.gaddr5, 0);
+	out_be32(&regs->hash.gaddr6, 0);
+	out_be32(&regs->hash.gaddr7, 0);
+
+	out_be32(&regs->rctrl, 0x00000000);
 
 	/* Init RMON mib registers */
 	memset((void *)&(regs->rmon), 0, sizeof(rmon_mib_t));
 
-	regs->rmon.cam1 = 0xffffffff;
-	regs->rmon.cam2 = 0xffffffff;
+	out_be32(&regs->rmon.cam1, 0xffffffff);
+	out_be32(&regs->rmon.cam2, 0xffffffff);
 
-	regs->mrblr = MRBLR_INIT_SETTINGS;
+	out_be32(&regs->mrblr, MRBLR_INIT_SETTINGS);
 
-	regs->minflr = MINFLR_INIT_SETTINGS;
+	out_be32(&regs->minflr, MINFLR_INIT_SETTINGS);
 
-	regs->attr = ATTR_INIT_SETTINGS;
-	regs->attreli = ATTRELI_INIT_SETTINGS;
+	out_be32(&regs->attr, ATTR_INIT_SETTINGS);
+	out_be32(&regs->attreli, ATTRELI_INIT_SETTINGS);
 
 }
 
@@ -922,44 +925,49 @@ static void init_registers(volatile tsec_t * regs)
 static void adjust_link(struct eth_device *dev)
 {
 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
-	volatile tsec_t *regs = priv->regs;
+	tsec_t *regs = priv->regs;
+	u32 ecntrl, maccfg2;
 
-	if (priv->link) {
-		if (priv->duplexity != 0)
-			regs->maccfg2 |= MACCFG2_FULL_DUPLEX;
-		else
-			regs->maccfg2 &= ~(MACCFG2_FULL_DUPLEX);
+	if (!priv->link) {
+		printf("%s: No link.\n", dev->name);
+		return;
+	}
 
-		switch (priv->speed) {
-		case 1000:
-			regs->maccfg2 = ((regs->maccfg2 & ~(MACCFG2_IF))
-					 | MACCFG2_GMII);
-			break;
-		case 100:
-		case 10:
-			regs->maccfg2 = ((regs->maccfg2 & ~(MACCFG2_IF))
-					 | MACCFG2_MII);
+	/* clear all bits relative with interface mode */
+	ecntrl = in_be32(&regs->ecntrl);
+	ecntrl &= ~ECNTRL_R100;
 
-			/* Set R100 bit in all modes although
-			 * it is only used in RGMII mode
-			 */
-			if (priv->speed == 100)
-				regs->ecntrl |= ECNTRL_R100;
-			else
-				regs->ecntrl &= ~(ECNTRL_R100);
-			break;
-		default:
-			printf("%s: Speed was bad\n", dev->name);
-			break;
-		}
+	maccfg2 = in_be32(&regs->maccfg2);
+	maccfg2 &= ~(MACCFG2_IF | MACCFG2_FULL_DUPLEX);
 
-		printf("Speed: %d, %s duplex%s\n", priv->speed,
-		       (priv->duplexity) ? "full" : "half",
-		       (priv->flags & TSEC_FIBER) ? ", fiber mode" : "");
+	if (priv->duplexity)
+		maccfg2 |= MACCFG2_FULL_DUPLEX;
 
-	} else {
-		printf("%s: No link.\n", dev->name);
+	switch (priv->speed) {
+	case 1000:
+		maccfg2 |= MACCFG2_GMII;
+		break;
+	case 100:
+	case 10:
+		maccfg2 |= MACCFG2_MII;
+
+		/* Set R100 bit in all modes although
+		 * it is only used in RGMII mode
+		 */
+		if (priv->speed == 100)
+			ecntrl |= ECNTRL_R100;
+		break;
+	default:
+		printf("%s: Speed was bad\n", dev->name);
+		break;
 	}
+
+	out_be32(&regs->ecntrl, ecntrl);
+	out_be32(&regs->maccfg2, maccfg2);
+
+	printf("Speed: %d, %s duplex%s\n", priv->speed,
+			(priv->duplexity) ? "full" : "half",
+			(priv->flags & TSEC_FIBER) ? ", fiber mode" : "");
 }
 
 /* Set up the buffers and their descriptors, and bring up the
@@ -969,11 +977,11 @@ static void startup_tsec(struct eth_device *dev)
 {
 	int i;
 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
-	volatile tsec_t *regs = priv->regs;
+	tsec_t *regs = priv->regs;
 
 	/* Point to the buffer descriptors */
-	regs->tbase = (unsigned int)(&rtx.txbd[txIdx]);
-	regs->rbase = (unsigned int)(&rtx.rxbd[rxIdx]);
+	out_be32(&regs->tbase, (unsigned int)(&rtx.txbd[txIdx]));
+	out_be32(&regs->rbase, (unsigned int)(&rtx.rxbd[rxIdx]));
 
 	/* Initialize the Rx Buffer descriptors */
 	for (i = 0; i < PKTBUFSRX; i++) {
@@ -998,13 +1006,13 @@ static void startup_tsec(struct eth_device *dev)
 	adjust_link(dev);
 
 	/* Enable Transmit and Receive */
-	regs->maccfg1 |= (MACCFG1_RX_EN | MACCFG1_TX_EN);
+	setbits_be32(&regs->maccfg1, MACCFG1_RX_EN | MACCFG1_TX_EN);
 
 	/* Tell the DMA it is clear to go */
-	regs->dmactrl |= DMACTRL_INIT_SETTINGS;
-	regs->tstat = TSTAT_CLEAR_THALT;
-	regs->rstat = RSTAT_CLEAR_RHALT;
-	regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
+	setbits_be32(&regs->dmactrl, DMACTRL_INIT_SETTINGS);
+	out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
+	out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
+	clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
 }
 
 /* This returns the status bits of the device.	The return value
@@ -1017,7 +1025,7 @@ static int tsec_send(struct eth_device *dev, volatile void *packet, int length)
 	int i;
 	int result = 0;
 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
-	volatile tsec_t *regs = priv->regs;
+	tsec_t *regs = priv->regs;
 
 	/* Find an empty buffer descriptor */
 	for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
@@ -1033,7 +1041,7 @@ static int tsec_send(struct eth_device *dev, volatile void *packet, int length)
 	    (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT);
 
 	/* Tell the DMA to go */
-	regs->tstat = TSTAT_CLEAR_THALT;
+	out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
 
 	/* Wait for buffer to be transmitted */
 	for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
@@ -1053,7 +1061,7 @@ static int tsec_recv(struct eth_device *dev)
 {
 	int length;
 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
-	volatile tsec_t *regs = priv->regs;
+	tsec_t *regs = priv->regs;
 
 	while (!(rtx.rxbd[rxIdx].status & RXBD_EMPTY)) {
 
@@ -1076,9 +1084,9 @@ static int tsec_recv(struct eth_device *dev)
 		rxIdx = (rxIdx + 1) % PKTBUFSRX;
 	}
 
-	if (regs->ievent & IEVENT_BSY) {
-		regs->ievent = IEVENT_BSY;
-		regs->rstat = RSTAT_CLEAR_RHALT;
+	if (in_be32(&regs->ievent) & IEVENT_BSY) {
+		out_be32(&regs->ievent, IEVENT_BSY);
+		out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
 	}
 
 	return -1;
@@ -1089,15 +1097,16 @@ static int tsec_recv(struct eth_device *dev)
 static void tsec_halt(struct eth_device *dev)
 {
 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
-	volatile tsec_t *regs = priv->regs;
+	tsec_t *regs = priv->regs;
 
-	regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
-	regs->dmactrl |= (DMACTRL_GRS | DMACTRL_GTS);
+	clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
+	setbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
 
-	while ((regs->ievent & (IEVENT_GRSC | IEVENT_GTSC))
-		!= (IEVENT_GRSC | IEVENT_GTSC)) ;
+	while ((in_be32(&regs->ievent) & (IEVENT_GRSC | IEVENT_GTSC))
+			!= (IEVENT_GRSC | IEVENT_GTSC))
+		;
 
-	regs->maccfg1 &= ~(MACCFG1_TX_EN | MACCFG1_RX_EN);
+	clrbits_be32(&regs->maccfg1, MACCFG1_TX_EN | MACCFG1_RX_EN);
 
 	/* Shut down the PHY, as needed */
 	if(priv->phyinfo)
@@ -1904,13 +1913,14 @@ static void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd)
 {
 	int i;
 	uint result;
-	volatile tsec_mdio_t *phyregs = priv->phyregs;
+	tsec_mdio_t *phyregs = priv->phyregs;
 
-	phyregs->miimcfg = MIIMCFG_RESET;
+	out_be32(&phyregs->miimcfg, MIIMCFG_RESET);
 
-	phyregs->miimcfg = MIIMCFG_INIT_VALUE;
+	out_be32(&phyregs->miimcfg, MIIMCFG_INIT_VALUE);
 
-	while (phyregs->miimind & MIIMIND_BUSY) ;
+	while (in_be32(&phyregs->miimind) & MIIMIND_BUSY)
+		;
 
 	for (i = 0; cmd->mii_reg != miim_end; i++) {
 		if (cmd->mii_data == miim_read) {
diff --git a/include/tsec.h b/include/tsec.h
index d56ec2c..a066d97 100644
--- a/include/tsec.h
+++ b/include/tsec.h
@@ -7,7 +7,7 @@
  *  terms of the GNU Public License, Version 2, incorporated
  *  herein by reference.
  *
- * Copyright 2004, 2007, 2009  Freescale Semiconductor, Inc.
+ * Copyright 2004, 2007, 2009, 2011  Freescale Semiconductor, Inc.
  * (C) Copyright 2003, Motorola, Inc.
  * maintained by Xianghua Xiao (x.xiao at motorola.com)
  * author Andy Fleming
@@ -587,9 +587,9 @@ typedef struct tsec
 #define TSEC_FIBER	(1 << 3)	/* PHY uses fiber, eg 1000 Base-X */
 
 struct tsec_private {
-	volatile tsec_t *regs;
-	volatile tsec_mdio_t *phyregs;
-	volatile tsec_mdio_t *phyregs_sgmii;
+	tsec_t *regs;
+	tsec_mdio_t *phyregs;
+	tsec_mdio_t *phyregs_sgmii;
 	struct phy_info *phyinfo;
 	uint phyaddr;
 	u32 flags;
-- 
1.6.5.2.g6ff9a

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [U-Boot] [PATCH v2 2/6] tsec: arrange the code to avoid useless function declaration
  2011-04-05 21:59 ` [U-Boot] [PATCH v2 1/6] tsec: use IO accessors for IO accesses Andy Fleming
@ 2011-04-05 21:59   ` Andy Fleming
  2011-04-05 21:59     ` [U-Boot] [PATCH v2 3/6] Remove instances of phy_read/write Andy Fleming
  2011-04-06 12:31     ` [U-Boot] [PATCH v2 2/6] tsec: arrange the code to avoid useless function declaration Detlev Zundel
  2011-04-06 12:29   ` [U-Boot] [PATCH v2 1/6] tsec: use IO accessors for IO accesses Detlev Zundel
  1 sibling, 2 replies; 27+ messages in thread
From: Andy Fleming @ 2011-04-05 21:59 UTC (permalink / raw)
  To: u-boot

From: Mingkai Hu <Mingkai.hu@freescale.com>

This is merely a rearrangement.  No changes to the code, except
to remove now-useless declarations.

Signed-off-by: Mingkai Hu <Mingkai.hu@freescale.com>
Acked-by: Andy Fleming <afleming@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
Added clarification to the commit message

 drivers/net/tsec.c |  861 +++++++++++++++++++++++++---------------------------
 1 files changed, 418 insertions(+), 443 deletions(-)

diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c
index 4ea9813..1ee189d 100644
--- a/drivers/net/tsec.c
+++ b/drivers/net/tsec.c
@@ -44,31 +44,6 @@ static RTXBD rtx __attribute__ ((aligned(8)));
 #error "rtx must be 64-bit aligned"
 #endif
 
-static int tsec_send(struct eth_device *dev,
-		     volatile void *packet, int length);
-static int tsec_recv(struct eth_device *dev);
-static int tsec_init(struct eth_device *dev, bd_t * bd);
-static int tsec_initialize(bd_t * bis, struct tsec_info_struct *tsec_info);
-static void tsec_halt(struct eth_device *dev);
-static void init_registers(tsec_t *regs);
-static void startup_tsec(struct eth_device *dev);
-static int init_phy(struct eth_device *dev);
-void write_phy_reg(struct tsec_private *priv, uint regnum, uint value);
-uint read_phy_reg(struct tsec_private *priv, uint regnum);
-static struct phy_info *get_phy_info(struct eth_device *dev);
-static void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd);
-static void adjust_link(struct eth_device *dev);
-#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \
-	&& !defined(BITBANGMII)
-static int tsec_miiphy_write(const char *devname, unsigned char addr,
-			     unsigned char reg, unsigned short value);
-static int tsec_miiphy_read(const char *devname, unsigned char addr,
-			    unsigned char reg, unsigned short *value);
-#endif
-#ifdef CONFIG_MCAST_TFTP
-static int tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set);
-#endif
-
 /* Default initializations for TSEC controllers. */
 
 static struct tsec_info_struct tsec_info[] = {
@@ -95,140 +70,6 @@ static struct tsec_info_struct tsec_info[] = {
 #endif
 };
 
-/*
- * Initialize all the TSEC devices
- *
- * Returns the number of TSEC devices that were initialized
- */
-int tsec_eth_init(bd_t *bis, struct tsec_info_struct *tsecs, int num)
-{
-	int i;
-	int ret, count = 0;
-
-	for (i = 0; i < num; i++) {
-		ret = tsec_initialize(bis, &tsecs[i]);
-		if (ret > 0)
-			count += ret;
-	}
-
-	return count;
-}
-
-int tsec_standard_init(bd_t *bis)
-{
-	return tsec_eth_init(bis, tsec_info, ARRAY_SIZE(tsec_info));
-}
-
-/* Initialize device structure. Returns success if PHY
- * initialization succeeded (i.e. if it recognizes the PHY)
- */
-static int tsec_initialize(bd_t * bis, struct tsec_info_struct *tsec_info)
-{
-	struct eth_device *dev;
-	int i;
-	struct tsec_private *priv;
-
-	dev = (struct eth_device *)malloc(sizeof *dev);
-
-	if (NULL == dev)
-		return 0;
-
-	memset(dev, 0, sizeof *dev);
-
-	priv = (struct tsec_private *)malloc(sizeof(*priv));
-
-	if (NULL == priv)
-		return 0;
-
-	privlist[num_tsecs++] = priv;
-	priv->regs = tsec_info->regs;
-	priv->phyregs = tsec_info->miiregs;
-	priv->phyregs_sgmii = tsec_info->miiregs_sgmii;
-
-	priv->phyaddr = tsec_info->phyaddr;
-	priv->flags = tsec_info->flags;
-
-	sprintf(dev->name, tsec_info->devname);
-	dev->iobase = 0;
-	dev->priv = priv;
-	dev->init = tsec_init;
-	dev->halt = tsec_halt;
-	dev->send = tsec_send;
-	dev->recv = tsec_recv;
-#ifdef CONFIG_MCAST_TFTP
-	dev->mcast = tsec_mcast_addr;
-#endif
-
-	/* Tell u-boot to get the addr from the env */
-	for (i = 0; i < 6; i++)
-		dev->enetaddr[i] = 0;
-
-	eth_register(dev);
-
-	/* Reset the MAC */
-	setbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
-	udelay(2);  /* Soft Reset must be asserted for 3 TX clocks */
-	clrbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
-
-#if defined(CONFIG_MII) || defined(CONFIG_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);
-}
-
-/* Initializes data structures and registers for the controller,
- * and brings the interface up.	 Returns the link status, meaning
- * that it returns success if the link is up, failure otherwise.
- * This allows u-boot to find the first active controller.
- */
-static int tsec_init(struct eth_device *dev, bd_t * bd)
-{
-	uint tempval;
-	char tmpbuf[MAC_ADDR_LEN];
-	int i;
-	struct tsec_private *priv = (struct tsec_private *)dev->priv;
-	tsec_t *regs = priv->regs;
-
-	/* Make sure the controller is stopped */
-	tsec_halt(dev);
-
-	/* Init MACCFG2.  Defaults to GMII */
-	out_be32(&regs->maccfg2, MACCFG2_INIT_SETTINGS);
-
-	/* Init ECNTRL */
-	out_be32(&regs->ecntrl, ECNTRL_INIT_SETTINGS);
-
-	/* Copy the station address into the address registers.
-	 * Backwards, because little endian MACS are dumb */
-	for (i = 0; i < MAC_ADDR_LEN; i++) {
-		tmpbuf[MAC_ADDR_LEN - 1 - i] = dev->enetaddr[i];
-	}
-	tempval = (tmpbuf[0] << 24) | (tmpbuf[1] << 16) | (tmpbuf[2] << 8) |
-		  tmpbuf[3];
-
-	out_be32(&regs->macstnaddr1, tempval);
-
-	tempval = *((uint *) (tmpbuf + 4));
-
-	out_be32(&regs->macstnaddr2, tempval);
-
-	/* reset the indices to zero */
-	rxIdx = 0;
-	txIdx = 0;
-
-	/* Clear out (for the most part) the other registers */
-	init_registers(regs);
-
-	/* Ready the device for tx/rx */
-	startup_tsec(dev);
-
-	/* If there's no link, fail */
-	return (priv->link ? 0 : -1);
-}
-
 /* Writes the given phy's reg with value, using the specified MDIO regs */
 static void tsec_local_mdio_write(tsec_mdio_t *phyregs, uint addr,
 		uint reg, uint value)
@@ -244,7 +85,6 @@ static void tsec_local_mdio_write(tsec_mdio_t *phyregs, uint addr,
 		;
 }
 
-
 /* Provide the default behavior of writing the PHY of this ethernet device */
 #define write_phy_reg(priv, regnum, value) \
 	tsec_local_mdio_write(priv->phyregs,priv->phyaddr,regnum,value)
@@ -314,49 +154,6 @@ static void tsec_configure_serdes(struct tsec_private *priv)
 			CONFIG_TSEC_TBICR_SETTINGS);
 }
 
-/* Discover which PHY is attached to the device, and configure it
- * properly.  If the PHY is not recognized, then return 0
- * (failure).  Otherwise, return 1
- */
-static int init_phy(struct eth_device *dev)
-{
-	struct tsec_private *priv = (struct tsec_private *)dev->priv;
-	struct phy_info *curphy;
-	tsec_t *regs = priv->regs;
-
-	/* Assign a Physical address to the TBI */
-	out_be32(&regs->tbipa, CONFIG_SYS_TBIPA_VALUE);
-	asm("sync");
-
-	/* Reset MII (due to new addresses) */
-	out_be32(&priv->phyregs->miimcfg, MIIMCFG_RESET);
-	asm("sync");
-	out_be32(&priv->phyregs->miimcfg, MIIMCFG_INIT_VALUE);
-	asm("sync");
-	while (in_be32(&priv->phyregs->miimind) & MIIMIND_BUSY)
-		;
-
-	/* Get the cmd structure corresponding to the attached
-	 * PHY */
-	curphy = get_phy_info(dev);
-
-	if (curphy == NULL) {
-		priv->phyinfo = NULL;
-		printf("%s: No PHY found\n", dev->name);
-
-		return 0;
-	}
-
-	if (in_be32(&regs->ecntrl) & ECNTRL_SGMII_MODE)
-		tsec_configure_serdes(priv);
-
-	priv->phyinfo = curphy;
-
-	phy_run_commands(priv, priv->phyinfo->config);
-
-	return 1;
-}
-
 /*
  * Returns which value to write to the control register.
  * For 10/100, the value is slightly different
@@ -873,246 +670,6 @@ static uint mii_m88e1111s_setmode(uint mii_reg, struct tsec_private *priv)
 	return mii_data;
 }
 
-/* Initialized required registers to appropriate values, zeroing
- * those we don't care about (unless zero is bad, in which case,
- * choose a more appropriate value)
- */
-static void init_registers(tsec_t *regs)
-{
-	/* Clear IEVENT */
-	out_be32(&regs->ievent, IEVENT_INIT_CLEAR);
-
-	out_be32(&regs->imask, IMASK_INIT_CLEAR);
-
-	out_be32(&regs->hash.iaddr0, 0);
-	out_be32(&regs->hash.iaddr1, 0);
-	out_be32(&regs->hash.iaddr2, 0);
-	out_be32(&regs->hash.iaddr3, 0);
-	out_be32(&regs->hash.iaddr4, 0);
-	out_be32(&regs->hash.iaddr5, 0);
-	out_be32(&regs->hash.iaddr6, 0);
-	out_be32(&regs->hash.iaddr7, 0);
-
-	out_be32(&regs->hash.gaddr0, 0);
-	out_be32(&regs->hash.gaddr1, 0);
-	out_be32(&regs->hash.gaddr2, 0);
-	out_be32(&regs->hash.gaddr3, 0);
-	out_be32(&regs->hash.gaddr4, 0);
-	out_be32(&regs->hash.gaddr5, 0);
-	out_be32(&regs->hash.gaddr6, 0);
-	out_be32(&regs->hash.gaddr7, 0);
-
-	out_be32(&regs->rctrl, 0x00000000);
-
-	/* Init RMON mib registers */
-	memset((void *)&(regs->rmon), 0, sizeof(rmon_mib_t));
-
-	out_be32(&regs->rmon.cam1, 0xffffffff);
-	out_be32(&regs->rmon.cam2, 0xffffffff);
-
-	out_be32(&regs->mrblr, MRBLR_INIT_SETTINGS);
-
-	out_be32(&regs->minflr, MINFLR_INIT_SETTINGS);
-
-	out_be32(&regs->attr, ATTR_INIT_SETTINGS);
-	out_be32(&regs->attreli, ATTRELI_INIT_SETTINGS);
-
-}
-
-/* Configure maccfg2 based on negotiated speed and duplex
- * reported by PHY handling code
- */
-static void adjust_link(struct eth_device *dev)
-{
-	struct tsec_private *priv = (struct tsec_private *)dev->priv;
-	tsec_t *regs = priv->regs;
-	u32 ecntrl, maccfg2;
-
-	if (!priv->link) {
-		printf("%s: No link.\n", dev->name);
-		return;
-	}
-
-	/* clear all bits relative with interface mode */
-	ecntrl = in_be32(&regs->ecntrl);
-	ecntrl &= ~ECNTRL_R100;
-
-	maccfg2 = in_be32(&regs->maccfg2);
-	maccfg2 &= ~(MACCFG2_IF | MACCFG2_FULL_DUPLEX);
-
-	if (priv->duplexity)
-		maccfg2 |= MACCFG2_FULL_DUPLEX;
-
-	switch (priv->speed) {
-	case 1000:
-		maccfg2 |= MACCFG2_GMII;
-		break;
-	case 100:
-	case 10:
-		maccfg2 |= MACCFG2_MII;
-
-		/* Set R100 bit in all modes although
-		 * it is only used in RGMII mode
-		 */
-		if (priv->speed == 100)
-			ecntrl |= ECNTRL_R100;
-		break;
-	default:
-		printf("%s: Speed was bad\n", dev->name);
-		break;
-	}
-
-	out_be32(&regs->ecntrl, ecntrl);
-	out_be32(&regs->maccfg2, maccfg2);
-
-	printf("Speed: %d, %s duplex%s\n", priv->speed,
-			(priv->duplexity) ? "full" : "half",
-			(priv->flags & TSEC_FIBER) ? ", fiber mode" : "");
-}
-
-/* Set up the buffers and their descriptors, and bring up the
- * interface
- */
-static void startup_tsec(struct eth_device *dev)
-{
-	int i;
-	struct tsec_private *priv = (struct tsec_private *)dev->priv;
-	tsec_t *regs = priv->regs;
-
-	/* Point to the buffer descriptors */
-	out_be32(&regs->tbase, (unsigned int)(&rtx.txbd[txIdx]));
-	out_be32(&regs->rbase, (unsigned int)(&rtx.rxbd[rxIdx]));
-
-	/* Initialize the Rx Buffer descriptors */
-	for (i = 0; i < PKTBUFSRX; i++) {
-		rtx.rxbd[i].status = RXBD_EMPTY;
-		rtx.rxbd[i].length = 0;
-		rtx.rxbd[i].bufPtr = (uint) NetRxPackets[i];
-	}
-	rtx.rxbd[PKTBUFSRX - 1].status |= RXBD_WRAP;
-
-	/* Initialize the TX Buffer Descriptors */
-	for (i = 0; i < TX_BUF_CNT; i++) {
-		rtx.txbd[i].status = 0;
-		rtx.txbd[i].length = 0;
-		rtx.txbd[i].bufPtr = 0;
-	}
-	rtx.txbd[TX_BUF_CNT - 1].status |= TXBD_WRAP;
-
-	/* Start up the PHY */
-	if(priv->phyinfo)
-		phy_run_commands(priv, priv->phyinfo->startup);
-
-	adjust_link(dev);
-
-	/* Enable Transmit and Receive */
-	setbits_be32(&regs->maccfg1, MACCFG1_RX_EN | MACCFG1_TX_EN);
-
-	/* Tell the DMA it is clear to go */
-	setbits_be32(&regs->dmactrl, DMACTRL_INIT_SETTINGS);
-	out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
-	out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
-	clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
-}
-
-/* This returns the status bits of the device.	The return value
- * is never checked, and this is what the 8260 driver did, so we
- * do the same.	 Presumably, this would be zero if there were no
- * errors
- */
-static int tsec_send(struct eth_device *dev, volatile void *packet, int length)
-{
-	int i;
-	int result = 0;
-	struct tsec_private *priv = (struct tsec_private *)dev->priv;
-	tsec_t *regs = priv->regs;
-
-	/* Find an empty buffer descriptor */
-	for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
-		if (i >= TOUT_LOOP) {
-			debug("%s: tsec: tx buffers full\n", dev->name);
-			return result;
-		}
-	}
-
-	rtx.txbd[txIdx].bufPtr = (uint) packet;
-	rtx.txbd[txIdx].length = length;
-	rtx.txbd[txIdx].status |=
-	    (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT);
-
-	/* Tell the DMA to go */
-	out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
-
-	/* Wait for buffer to be transmitted */
-	for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
-		if (i >= TOUT_LOOP) {
-			debug("%s: tsec: tx error\n", dev->name);
-			return result;
-		}
-	}
-
-	txIdx = (txIdx + 1) % TX_BUF_CNT;
-	result = rtx.txbd[txIdx].status & TXBD_STATS;
-
-	return result;
-}
-
-static int tsec_recv(struct eth_device *dev)
-{
-	int length;
-	struct tsec_private *priv = (struct tsec_private *)dev->priv;
-	tsec_t *regs = priv->regs;
-
-	while (!(rtx.rxbd[rxIdx].status & RXBD_EMPTY)) {
-
-		length = rtx.rxbd[rxIdx].length;
-
-		/* Send the packet up if there were no errors */
-		if (!(rtx.rxbd[rxIdx].status & RXBD_STATS)) {
-			NetReceive(NetRxPackets[rxIdx], length - 4);
-		} else {
-			printf("Got error %x\n",
-			       (rtx.rxbd[rxIdx].status & RXBD_STATS));
-		}
-
-		rtx.rxbd[rxIdx].length = 0;
-
-		/* Set the wrap bit if this is the last element in the list */
-		rtx.rxbd[rxIdx].status =
-		    RXBD_EMPTY | (((rxIdx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0);
-
-		rxIdx = (rxIdx + 1) % PKTBUFSRX;
-	}
-
-	if (in_be32(&regs->ievent) & IEVENT_BSY) {
-		out_be32(&regs->ievent, IEVENT_BSY);
-		out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
-	}
-
-	return -1;
-
-}
-
-/* Stop the interface */
-static void tsec_halt(struct eth_device *dev)
-{
-	struct tsec_private *priv = (struct tsec_private *)dev->priv;
-	tsec_t *regs = priv->regs;
-
-	clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
-	setbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
-
-	while ((in_be32(&regs->ievent) & (IEVENT_GRSC | IEVENT_GTSC))
-			!= (IEVENT_GRSC | IEVENT_GTSC))
-		;
-
-	clrbits_be32(&regs->maccfg1, MACCFG1_TX_EN | MACCFG1_RX_EN);
-
-	/* Shut down the PHY, as needed */
-	if(priv->phyinfo)
-		phy_run_commands(priv, priv->phyinfo->shutdown);
-}
-
 static struct phy_info phy_info_M88E1149S = {
 	0x1410ca,
 	"Marvell 88E1149S",
@@ -2032,3 +1589,421 @@ tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set)
 	return 0;
 }
 #endif /* Multicast TFTP ? */
+
+/* Initialized required registers to appropriate values, zeroing
+ * those we don't care about (unless zero is bad, in which case,
+ * choose a more appropriate value)
+ */
+static void init_registers(tsec_t *regs)
+{
+	/* Clear IEVENT */
+	out_be32(&regs->ievent, IEVENT_INIT_CLEAR);
+
+	out_be32(&regs->imask, IMASK_INIT_CLEAR);
+
+	out_be32(&regs->hash.iaddr0, 0);
+	out_be32(&regs->hash.iaddr1, 0);
+	out_be32(&regs->hash.iaddr2, 0);
+	out_be32(&regs->hash.iaddr3, 0);
+	out_be32(&regs->hash.iaddr4, 0);
+	out_be32(&regs->hash.iaddr5, 0);
+	out_be32(&regs->hash.iaddr6, 0);
+	out_be32(&regs->hash.iaddr7, 0);
+
+	out_be32(&regs->hash.gaddr0, 0);
+	out_be32(&regs->hash.gaddr1, 0);
+	out_be32(&regs->hash.gaddr2, 0);
+	out_be32(&regs->hash.gaddr3, 0);
+	out_be32(&regs->hash.gaddr4, 0);
+	out_be32(&regs->hash.gaddr5, 0);
+	out_be32(&regs->hash.gaddr6, 0);
+	out_be32(&regs->hash.gaddr7, 0);
+
+	out_be32(&regs->rctrl, 0x00000000);
+
+	/* Init RMON mib registers */
+	memset((void *)&(regs->rmon), 0, sizeof(rmon_mib_t));
+
+	out_be32(&regs->rmon.cam1, 0xffffffff);
+	out_be32(&regs->rmon.cam2, 0xffffffff);
+
+	out_be32(&regs->mrblr, MRBLR_INIT_SETTINGS);
+
+	out_be32(&regs->minflr, MINFLR_INIT_SETTINGS);
+
+	out_be32(&regs->attr, ATTR_INIT_SETTINGS);
+	out_be32(&regs->attreli, ATTRELI_INIT_SETTINGS);
+
+}
+
+/* Configure maccfg2 based on negotiated speed and duplex
+ * reported by PHY handling code
+ */
+static void adjust_link(struct eth_device *dev)
+{
+	struct tsec_private *priv = (struct tsec_private *)dev->priv;
+	tsec_t *regs = priv->regs;
+	u32 ecntrl, maccfg2;
+
+	if (!priv->link) {
+		printf("%s: No link.\n", dev->name);
+		return;
+	}
+
+	/* clear all bits relative with interface mode */
+	ecntrl = in_be32(&regs->ecntrl);
+	ecntrl &= ~ECNTRL_R100;
+
+	maccfg2 = in_be32(&regs->maccfg2);
+	maccfg2 &= ~(MACCFG2_IF | MACCFG2_FULL_DUPLEX);
+
+	if (priv->duplexity)
+		maccfg2 |= MACCFG2_FULL_DUPLEX;
+
+	switch (priv->speed) {
+	case 1000:
+		maccfg2 |= MACCFG2_GMII;
+		break;
+	case 100:
+	case 10:
+		maccfg2 |= MACCFG2_MII;
+
+		/* Set R100 bit in all modes although
+		 * it is only used in RGMII mode
+		 */
+		if (priv->speed == 100)
+			ecntrl |= ECNTRL_R100;
+		break;
+	default:
+		printf("%s: Speed was bad\n", dev->name);
+		break;
+	}
+
+	out_be32(&regs->ecntrl, ecntrl);
+	out_be32(&regs->maccfg2, maccfg2);
+
+	printf("Speed: %d, %s duplex%s\n", priv->speed,
+			(priv->duplexity) ? "full" : "half",
+			(priv->flags & TSEC_FIBER) ? ", fiber mode" : "");
+}
+
+/* Set up the buffers and their descriptors, and bring up the
+ * interface
+ */
+static void startup_tsec(struct eth_device *dev)
+{
+	int i;
+	struct tsec_private *priv = (struct tsec_private *)dev->priv;
+	tsec_t *regs = priv->regs;
+
+	/* Point to the buffer descriptors */
+	out_be32(&regs->tbase, (unsigned int)(&rtx.txbd[txIdx]));
+	out_be32(&regs->rbase, (unsigned int)(&rtx.rxbd[rxIdx]));
+
+	/* Initialize the Rx Buffer descriptors */
+	for (i = 0; i < PKTBUFSRX; i++) {
+		rtx.rxbd[i].status = RXBD_EMPTY;
+		rtx.rxbd[i].length = 0;
+		rtx.rxbd[i].bufPtr = (uint) NetRxPackets[i];
+	}
+	rtx.rxbd[PKTBUFSRX - 1].status |= RXBD_WRAP;
+
+	/* Initialize the TX Buffer Descriptors */
+	for (i = 0; i < TX_BUF_CNT; i++) {
+		rtx.txbd[i].status = 0;
+		rtx.txbd[i].length = 0;
+		rtx.txbd[i].bufPtr = 0;
+	}
+	rtx.txbd[TX_BUF_CNT - 1].status |= TXBD_WRAP;
+
+	/* Start up the PHY */
+	if (priv->phyinfo)
+		phy_run_commands(priv, priv->phyinfo->startup);
+
+	adjust_link(dev);
+
+	/* Enable Transmit and Receive */
+	setbits_be32(&regs->maccfg1, MACCFG1_RX_EN | MACCFG1_TX_EN);
+
+	/* Tell the DMA it is clear to go */
+	setbits_be32(&regs->dmactrl, DMACTRL_INIT_SETTINGS);
+	out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
+	out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
+	clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
+}
+
+/* This returns the status bits of the device.	The return value
+ * is never checked, and this is what the 8260 driver did, so we
+ * do the same.	 Presumably, this would be zero if there were no
+ * errors
+ */
+static int tsec_send(struct eth_device *dev, volatile void *packet, int length)
+{
+	int i;
+	int result = 0;
+	struct tsec_private *priv = (struct tsec_private *)dev->priv;
+	tsec_t *regs = priv->regs;
+
+	/* Find an empty buffer descriptor */
+	for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
+		if (i >= TOUT_LOOP) {
+			debug("%s: tsec: tx buffers full\n", dev->name);
+			return result;
+		}
+	}
+
+	rtx.txbd[txIdx].bufPtr = (uint) packet;
+	rtx.txbd[txIdx].length = length;
+	rtx.txbd[txIdx].status |=
+	    (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT);
+
+	/* Tell the DMA to go */
+	out_be32(&regs->tstat, TSTAT_CLEAR_THALT);
+
+	/* Wait for buffer to be transmitted */
+	for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
+		if (i >= TOUT_LOOP) {
+			debug("%s: tsec: tx error\n", dev->name);
+			return result;
+		}
+	}
+
+	txIdx = (txIdx + 1) % TX_BUF_CNT;
+	result = rtx.txbd[txIdx].status & TXBD_STATS;
+
+	return result;
+}
+
+static int tsec_recv(struct eth_device *dev)
+{
+	int length;
+	struct tsec_private *priv = (struct tsec_private *)dev->priv;
+	tsec_t *regs = priv->regs;
+
+	while (!(rtx.rxbd[rxIdx].status & RXBD_EMPTY)) {
+
+		length = rtx.rxbd[rxIdx].length;
+
+		/* Send the packet up if there were no errors */
+		if (!(rtx.rxbd[rxIdx].status & RXBD_STATS)) {
+			NetReceive(NetRxPackets[rxIdx], length - 4);
+		} else {
+			printf("Got error %x\n",
+			       (rtx.rxbd[rxIdx].status & RXBD_STATS));
+		}
+
+		rtx.rxbd[rxIdx].length = 0;
+
+		/* Set the wrap bit if this is the last element in the list */
+		rtx.rxbd[rxIdx].status =
+		    RXBD_EMPTY | (((rxIdx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0);
+
+		rxIdx = (rxIdx + 1) % PKTBUFSRX;
+	}
+
+	if (in_be32(&regs->ievent) & IEVENT_BSY) {
+		out_be32(&regs->ievent, IEVENT_BSY);
+		out_be32(&regs->rstat, RSTAT_CLEAR_RHALT);
+	}
+
+	return -1;
+
+}
+
+/* Stop the interface */
+static void tsec_halt(struct eth_device *dev)
+{
+	struct tsec_private *priv = (struct tsec_private *)dev->priv;
+	tsec_t *regs = priv->regs;
+
+	clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
+	setbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);
+
+	while ((in_be32(&regs->ievent) & (IEVENT_GRSC | IEVENT_GTSC))
+			!= (IEVENT_GRSC | IEVENT_GTSC))
+		;
+
+	clrbits_be32(&regs->maccfg1, MACCFG1_TX_EN | MACCFG1_RX_EN);
+
+	/* Shut down the PHY, as needed */
+	if (priv->phyinfo)
+		phy_run_commands(priv, priv->phyinfo->shutdown);
+}
+
+/* Initializes data structures and registers for the controller,
+ * and brings the interface up.	 Returns the link status, meaning
+ * that it returns success if the link is up, failure otherwise.
+ * This allows u-boot to find the first active controller.
+ */
+static int tsec_init(struct eth_device *dev, bd_t * bd)
+{
+	uint tempval;
+	char tmpbuf[MAC_ADDR_LEN];
+	int i;
+	struct tsec_private *priv = (struct tsec_private *)dev->priv;
+	tsec_t *regs = priv->regs;
+
+	/* Make sure the controller is stopped */
+	tsec_halt(dev);
+
+	/* Init MACCFG2.  Defaults to GMII */
+	out_be32(&regs->maccfg2, MACCFG2_INIT_SETTINGS);
+
+	/* Init ECNTRL */
+	out_be32(&regs->ecntrl, ECNTRL_INIT_SETTINGS);
+
+	/* Copy the station address into the address registers.
+	 * Backwards, because little endian MACS are dumb */
+	for (i = 0; i < MAC_ADDR_LEN; i++)
+		tmpbuf[MAC_ADDR_LEN - 1 - i] = dev->enetaddr[i];
+
+	tempval = (tmpbuf[0] << 24) | (tmpbuf[1] << 16) | (tmpbuf[2] << 8) |
+		  tmpbuf[3];
+
+	out_be32(&regs->macstnaddr1, tempval);
+
+	tempval = *((uint *) (tmpbuf + 4));
+
+	out_be32(&regs->macstnaddr2, tempval);
+
+	/* reset the indices to zero */
+	rxIdx = 0;
+	txIdx = 0;
+
+	/* Clear out (for the most part) the other registers */
+	init_registers(regs);
+
+	/* Ready the device for tx/rx */
+	startup_tsec(dev);
+
+	/* If there's no link, fail */
+	return priv->link ? 0 : -1;
+}
+
+/* Discover which PHY is attached to the device, and configure it
+ * properly.  If the PHY is not recognized, then return 0
+ * (failure).  Otherwise, return 1
+ */
+static int init_phy(struct eth_device *dev)
+{
+	struct tsec_private *priv = (struct tsec_private *)dev->priv;
+	struct phy_info *curphy;
+	tsec_t *regs = priv->regs;
+
+	/* Assign a Physical address to the TBI */
+	out_be32(&regs->tbipa, CONFIG_SYS_TBIPA_VALUE);
+	asm("sync");
+
+	/* Reset MII (due to new addresses) */
+	out_be32(&priv->phyregs->miimcfg, MIIMCFG_RESET);
+	asm("sync");
+	out_be32(&priv->phyregs->miimcfg, MIIMCFG_INIT_VALUE);
+	asm("sync");
+	while (in_be32(&priv->phyregs->miimind) & MIIMIND_BUSY)
+		;
+
+	/* Get the cmd structure corresponding to the attached
+	 * PHY */
+	curphy = get_phy_info(dev);
+
+	if (curphy == NULL) {
+		priv->phyinfo = NULL;
+		printf("%s: No PHY found\n", dev->name);
+
+		return 0;
+	}
+
+	if (in_be32(&regs->ecntrl) & ECNTRL_SGMII_MODE)
+		tsec_configure_serdes(priv);
+
+	priv->phyinfo = curphy;
+
+	phy_run_commands(priv, priv->phyinfo->config);
+
+	return 1;
+}
+
+/* Initialize device structure. Returns success if PHY
+ * initialization succeeded (i.e. if it recognizes the PHY)
+ */
+static int tsec_initialize(bd_t *bis, struct tsec_info_struct *tsec_info)
+{
+	struct eth_device *dev;
+	int i;
+	struct tsec_private *priv;
+
+	dev = (struct eth_device *)malloc(sizeof *dev);
+
+	if (NULL == dev)
+		return 0;
+
+	memset(dev, 0, sizeof *dev);
+
+	priv = (struct tsec_private *)malloc(sizeof(*priv));
+
+	if (NULL == priv)
+		return 0;
+
+	privlist[num_tsecs++] = priv;
+	priv->regs = tsec_info->regs;
+	priv->phyregs = tsec_info->miiregs;
+	priv->phyregs_sgmii = tsec_info->miiregs_sgmii;
+
+	priv->phyaddr = tsec_info->phyaddr;
+	priv->flags = tsec_info->flags;
+
+	sprintf(dev->name, tsec_info->devname);
+	dev->iobase = 0;
+	dev->priv = priv;
+	dev->init = tsec_init;
+	dev->halt = tsec_halt;
+	dev->send = tsec_send;
+	dev->recv = tsec_recv;
+#ifdef CONFIG_MCAST_TFTP
+	dev->mcast = tsec_mcast_addr;
+#endif
+
+	/* Tell u-boot to get the addr from the env */
+	for (i = 0; i < 6; i++)
+		dev->enetaddr[i] = 0;
+
+	eth_register(dev);
+
+	/* Reset the MAC */
+	setbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
+	udelay(2);  /* Soft Reset must be asserted for 3 TX clocks */
+	clrbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
+
+#if defined(CONFIG_MII) || defined(CONFIG_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);
+}
+
+/*
+ * Initialize all the TSEC devices
+ *
+ * Returns the number of TSEC devices that were initialized
+ */
+int tsec_eth_init(bd_t *bis, struct tsec_info_struct *tsecs, int num)
+{
+	int i;
+	int ret, count = 0;
+
+	for (i = 0; i < num; i++) {
+		ret = tsec_initialize(bis, &tsecs[i]);
+		if (ret > 0)
+			count += ret;
+	}
+
+	return count;
+}
+
+int tsec_standard_init(bd_t *bis)
+{
+	return tsec_eth_init(bis, tsec_info, ARRAY_SIZE(tsec_info));
+}
+
-- 
1.6.5.2.g6ff9a

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [U-Boot] [PATCH v2 3/6] Remove instances of phy_read/write
  2011-04-05 21:59   ` [U-Boot] [PATCH v2 2/6] tsec: arrange the code to avoid useless function declaration Andy Fleming
@ 2011-04-05 21:59     ` Andy Fleming
  2011-04-05 21:59       ` [U-Boot] [PATCH v2 4/6] Create PHY Lib for U-Boot Andy Fleming
  2011-04-06 12:32       ` [U-Boot] [PATCH v2 3/6] Remove instances of phy_read/write Detlev Zundel
  2011-04-06 12:31     ` [U-Boot] [PATCH v2 2/6] tsec: arrange the code to avoid useless function declaration Detlev Zundel
  1 sibling, 2 replies; 27+ messages in thread
From: Andy Fleming @ 2011-04-05 21:59 UTC (permalink / raw)
  To: u-boot

There were a few files which were already using phy_read and phy_write
for their PHY function names.  It's only a few places, and the name
seems most appropriate for the high-level abstraction, so let's
rename the other versions to something more specific.

Also, uec_phy.c had a marvell_init function which I renamed to not
conflict with the one in marvell.c

Lastly, uec_phy.c was putting a space between the phy writing
function names, and the open paren, so I fixed that

Signed-off-by: Andy Fleming <afleming@freescale.com>
---
Fixed some sparse errors/warnings

 drivers/net/dm9000x.c  |   18 +++---
 drivers/net/enc28j60.c |   24 ++++----
 drivers/net/uli526x.c  |   24 ++++----
 drivers/qe/uec.c       |    3 -
 drivers/qe/uec_phy.c   |  145 ++++++++++++++++++++++++------------------------
 5 files changed, 107 insertions(+), 107 deletions(-)

diff --git a/drivers/net/dm9000x.c b/drivers/net/dm9000x.c
index 709f67a..b5c5573 100644
--- a/drivers/net/dm9000x.c
+++ b/drivers/net/dm9000x.c
@@ -110,8 +110,8 @@ static board_info_t dm9000_info;
 
 /* function declaration ------------------------------------- */
 static int dm9000_probe(void);
-static u16 phy_read(int);
-static void phy_write(int, u16);
+static u16 dm9000_phy_read(int);
+static void dm9000_phy_write(int, u16);
 static u8 DM9000_ior(int);
 static void DM9000_iow(int reg, u8 value);
 
@@ -361,7 +361,7 @@ static int dm9000_init(struct eth_device *dev, bd_t *bd)
 	DM9000_iow(DM9000_IMR, IMR_PAR);
 
 	i = 0;
-	while (!(phy_read(1) & 0x20)) {	/* autonegation complete bit */
+	while (!(dm9000_phy_read(1) & 0x20)) {	/* autonegation complete bit */
 		udelay(1000);
 		i++;
 		if (i == 10000) {
@@ -371,7 +371,7 @@ static int dm9000_init(struct eth_device *dev, bd_t *bd)
 	}
 
 	/* see what we've got */
-	lnk = phy_read(17) >> 12;
+	lnk = dm9000_phy_read(17) >> 12;
 	printf("operating at ");
 	switch (lnk) {
 	case 1:
@@ -445,7 +445,7 @@ static void dm9000_halt(struct eth_device *netdev)
 	DM9000_DBG("%s\n", __func__);
 
 	/* RESET devie */
-	phy_write(0, 0x8000);	/* PHY RESET */
+	dm9000_phy_write(0, 0x8000);	/* PHY RESET */
 	DM9000_iow(DM9000_GPR, 0x01);	/* Power-Down PHY */
 	DM9000_iow(DM9000_IMR, 0x80);	/* Disable all interrupt */
 	DM9000_iow(DM9000_RCR, 0x00);	/* Disable RX */
@@ -581,7 +581,7 @@ DM9000_iow(int reg, u8 value)
    Read a word from phyxcer
 */
 static u16
-phy_read(int reg)
+dm9000_phy_read(int reg)
 {
 	u16 val;
 
@@ -593,7 +593,7 @@ phy_read(int reg)
 	val = (DM9000_ior(DM9000_EPDRH) << 8) | DM9000_ior(DM9000_EPDRL);
 
 	/* The read data keeps on REG_0D & REG_0E */
-	DM9000_DBG("phy_read(0x%x): 0x%x\n", reg, val);
+	DM9000_DBG("dm9000_phy_read(0x%x): 0x%x\n", reg, val);
 	return val;
 }
 
@@ -601,7 +601,7 @@ phy_read(int reg)
    Write a word to phyxcer
 */
 static void
-phy_write(int reg, u16 value)
+dm9000_phy_write(int reg, u16 value)
 {
 
 	/* Fill the phyxcer register into REG_0C */
@@ -613,7 +613,7 @@ phy_write(int reg, u16 value)
 	DM9000_iow(DM9000_EPCR, 0xa);	/* Issue phyxcer write command */
 	udelay(500);			/* Wait write complete */
 	DM9000_iow(DM9000_EPCR, 0x0);	/* Clear phyxcer write command */
-	DM9000_DBG("phy_write(reg:0x%x, value:0x%x)\n", reg, value);
+	DM9000_DBG("dm9000_phy_write(reg:0x%x, value:0x%x)\n", reg, value);
 }
 
 int dm9000_initialize(bd_t *bis)
diff --git a/drivers/net/enc28j60.c b/drivers/net/enc28j60.c
index 6c161b6..d55cacd 100644
--- a/drivers/net/enc28j60.c
+++ b/drivers/net/enc28j60.c
@@ -314,7 +314,7 @@ static void enc_release_bus(enc_dev_t *enc)
 /*
  * Read PHY register
  */
-static u16 phy_read(enc_dev_t *enc, const u8 addr)
+static u16 enc_phy_read(enc_dev_t *enc, const u8 addr)
 {
 	uint64_t etime;
 	u8 status;
@@ -339,7 +339,7 @@ static u16 phy_read(enc_dev_t *enc, const u8 addr)
 /*
  * Write PHY register
  */
-static void phy_write(enc_dev_t *enc, const u8 addr, const u16 data)
+static void enc_phy_write(enc_dev_t *enc, const u8 addr, const u16 data)
 {
 	uint64_t etime;
 	u8 status;
@@ -374,7 +374,7 @@ static int enc_phy_link_wait(enc_dev_t *enc)
 
 #ifdef CONFIG_ENC_SILENTLINK
 	/* check if we have a link, then just return */
-	status = phy_read(enc, PHY_REG_PHSTAT1);
+	status = enc_phy_read(enc, PHY_REG_PHSTAT1);
 	if (status & ENC_PHSTAT1_LLSTAT)
 		return 0;
 #endif
@@ -382,10 +382,10 @@ static int enc_phy_link_wait(enc_dev_t *enc)
 	/* wait for link with 1 second timeout */
 	etime = get_ticks() + get_tbclk();
 	while (get_ticks() <= etime) {
-		status = phy_read(enc, PHY_REG_PHSTAT1);
+		status = enc_phy_read(enc, PHY_REG_PHSTAT1);
 		if (status & ENC_PHSTAT1_LLSTAT) {
 			/* now we have a link */
-			status = phy_read(enc, PHY_REG_PHSTAT2);
+			status = enc_phy_read(enc, PHY_REG_PHSTAT2);
 			duplex = (status & ENC_PHSTAT2_DPXSTAT) ? 1 : 0;
 			printf("%s: link up, 10Mbps %s-duplex\n",
 				enc->dev->name, duplex ? "full" : "half");
@@ -678,8 +678,8 @@ static int enc_setup(enc_dev_t *enc)
 	enc->bank = 0xff;	/* invalidate current bank in enc28j60 */
 
 	/* verify PHY identification */
-	phid1 = phy_read(enc, PHY_REG_PHID1);
-	phid2 = phy_read(enc, PHY_REG_PHID2) & ENC_PHID2_MASK;
+	phid1 = enc_phy_read(enc, PHY_REG_PHID1);
+	phid2 = enc_phy_read(enc, PHY_REG_PHID2) & ENC_PHID2_MASK;
 	if (phid1 != ENC_PHID1_VALUE || phid2 != ENC_PHID2_VALUE) {
 		printf("%s: failed to identify PHY. Found %04x:%04x\n",
 			enc->dev->name, phid1, phid2);
@@ -694,7 +694,7 @@ static int enc_setup(enc_dev_t *enc)
 	 * Prevent automatic loopback of data beeing transmitted by setting
 	 * ENC_PHCON2_HDLDIS
 	 */
-	phy_write(enc, PHY_REG_PHCON2, (1<<8));
+	enc_phy_write(enc, PHY_REG_PHCON2, (1<<8));
 
 	/*
 	 * LEDs configuration
@@ -702,10 +702,10 @@ static int enc_setup(enc_dev_t *enc)
 	 * LEDB: LBCFG = 0111 -> display TX & RX activity
 	 * STRCH = 1 -> LED pulses
 	 */
-	phy_write(enc, PHY_REG_PHLCON, 0x0472);
+	enc_phy_write(enc, PHY_REG_PHLCON, 0x0472);
 
 	/* Reset PDPXMD-bit => half duplex */
-	phy_write(enc, PHY_REG_PHCON1, 0);
+	enc_phy_write(enc, PHY_REG_PHCON1, 0);
 
 #ifdef CONFIG_USE_IRQ
 	/* enable interrupts */
@@ -771,7 +771,7 @@ int enc_miiphy_read(const char *devname, u8 phy_adr, u8 reg, u16 *value)
 		enc_release_bus(enc);
 		return -1;
 	}
-	*value = phy_read(enc, reg);
+	*value = enc_phy_read(enc, reg);
 	enc_release_bus(enc);
 	return 0;
 }
@@ -796,7 +796,7 @@ int enc_miiphy_write(const char *devname, u8 phy_adr, u8 reg, u16 value)
 		enc_release_bus(enc);
 		return -1;
 	}
-	phy_write(enc, reg, value);
+	enc_phy_write(enc, reg, value);
 	enc_release_bus(enc);
 	return 0;
 }
diff --git a/drivers/net/uli526x.c b/drivers/net/uli526x.c
index a4624e1..5933bdd 100644
--- a/drivers/net/uli526x.c
+++ b/drivers/net/uli526x.c
@@ -175,9 +175,9 @@ static u16 read_srom_word(long, int);
 static void uli526x_descriptor_init(struct uli526x_board_info *, unsigned long);
 static void allocate_rx_buffer(struct uli526x_board_info *);
 static void update_cr6(u32, unsigned long);
-static u16 phy_read(unsigned long, u8, u8, u32);
+static u16 uli_phy_read(unsigned long, u8, u8, u32);
 static u16 phy_readby_cr10(unsigned long, u8, u8);
-static void phy_write(unsigned long, u8, u8, u16, u32);
+static void uli_phy_write(unsigned long, u8, u8, u16, u32);
 static void phy_writeby_cr10(unsigned long, u8, u8, u16);
 static void phy_write_1bit(unsigned long, u32, u32);
 static u16 phy_read_1bit(unsigned long, u32);
@@ -349,7 +349,7 @@ static void uli526x_disable(struct eth_device *dev)
 		/* Reset & stop ULI526X board */
 		outl(ULI526X_RESET, db->ioaddr + DCR0);
 		udelay(5);
-		phy_write(db->ioaddr, db->phy_addr, 0, 0x8000, db->chip_id);
+		uli_phy_write(db->ioaddr, db->phy_addr, 0, 0x8000, db->chip_id);
 
 		/* reset the board */
 		db->cr6_data &= ~(CR6_RXSC | CR6_TXSC);	/* Disable Tx/Rx */
@@ -385,7 +385,7 @@ static void uli526x_init(struct eth_device *dev)
 	db->tx_packet_cnt = 0;
 	for (phy_tmp = 0; phy_tmp < 32; phy_tmp++) {
 		/* peer add */
-		phy_value = phy_read(db->ioaddr, phy_tmp, 3, db->chip_id);
+		phy_value = uli_phy_read(db->ioaddr, phy_tmp, 3, db->chip_id);
 		if (phy_value != 0xffff && phy_value != 0) {
 			db->phy_addr = phy_tmp;
 			break;
@@ -404,10 +404,10 @@ static void uli526x_init(struct eth_device *dev)
 
 	if (!(inl(db->ioaddr + DCR12) & 0x8)) {
 		/* Phyxcer capability setting */
-		phy_reg_reset = phy_read(db->ioaddr,
+		phy_reg_reset = uli_phy_read(db->ioaddr,
 			db->phy_addr, 0, db->chip_id);
 		phy_reg_reset = (phy_reg_reset | 0x8000);
-		phy_write(db->ioaddr, db->phy_addr, 0,
+		uli_phy_write(db->ioaddr, db->phy_addr, 0,
 			phy_reg_reset, db->chip_id);
 		udelay(500);
 
@@ -781,7 +781,8 @@ static void uli526x_set_phyxcer(struct uli526x_board_info *db)
 	u16 phy_reg;
 
 	/* Phyxcer capability setting */
-	phy_reg = phy_read(db->ioaddr, db->phy_addr, 4, db->chip_id) & ~0x01e0;
+	phy_reg = uli_phy_read(db->ioaddr,
+			db->phy_addr, 4, db->chip_id) & ~0x01e0;
 
 	if (db->media_mode & ULI526X_AUTO) {
 		/* AUTO Mode */
@@ -802,10 +803,10 @@ static void uli526x_set_phyxcer(struct uli526x_board_info *db)
 		phy_reg |= db->PHY_reg4;
 		db->media_mode |= ULI526X_AUTO;
 	}
-	phy_write(db->ioaddr, db->phy_addr, 4, phy_reg, db->chip_id);
+	uli_phy_write(db->ioaddr, db->phy_addr, 4, phy_reg, db->chip_id);
 
 	/* Restart Auto-Negotiation */
-	phy_write(db->ioaddr, db->phy_addr, 0, 0x1200, db->chip_id);
+	uli_phy_write(db->ioaddr, db->phy_addr, 0, 0x1200, db->chip_id);
 	udelay(50);
 }
 
@@ -813,7 +814,7 @@ static void uli526x_set_phyxcer(struct uli526x_board_info *db)
  *	Write a word to Phy register
  */
 
-static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset,
+static void uli_phy_write(unsigned long iobase, u8 phy_addr, u8 offset,
 	u16 phy_data, u32 chip_id)
 {
 	u16 i;
@@ -862,7 +863,8 @@ static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset,
  *	Read a word data from phy register
  */
 
-static u16 phy_read(unsigned long iobase, u8 phy_addr, u8 offset, u32 chip_id)
+static u16 uli_phy_read(unsigned long iobase, u8 phy_addr, u8 offset,
+			u32 chip_id)
 {
 	int i;
 	u16 phy_data;
diff --git a/drivers/qe/uec.c b/drivers/qe/uec.c
index 282ab23..81febd6 100644
--- a/drivers/qe/uec.c
+++ b/drivers/qe/uec.c
@@ -67,9 +67,6 @@ static uec_info_t uec_info[] = {
 
 static struct eth_device *devlist[MAXCONTROLLERS];
 
-u16 phy_read (struct uec_mii_info *mii_info, u16 regnum);
-void phy_write (struct uec_mii_info *mii_info, u16 regnum, u16 val);
-
 static int uec_mac_enable(uec_private_t *uec, comm_dir_e mode)
 {
 	uec_t		*uec_regs;
diff --git a/drivers/qe/uec_phy.c b/drivers/qe/uec_phy.c
index 55c2622..c83ca4b 100644
--- a/drivers/qe/uec_phy.c
+++ b/drivers/qe/uec_phy.c
@@ -121,8 +121,8 @@ static int gbit_config_aneg (struct uec_mii_info *mii_info);
 static int genmii_config_aneg (struct uec_mii_info *mii_info);
 static int genmii_update_link (struct uec_mii_info *mii_info);
 static int genmii_read_status (struct uec_mii_info *mii_info);
-u16 phy_read (struct uec_mii_info *mii_info, u16 regnum);
-void phy_write (struct uec_mii_info *mii_info, u16 regnum, u16 val);
+u16 uec_phy_read(struct uec_mii_info *mii_info, u16 regnum);
+void uec_phy_write(struct uec_mii_info *mii_info, u16 regnum, u16 val);
 
 /* Write value to the PHY for this device to the register at regnum, */
 /* waiting until the write is done before it returns.  All PHY */
@@ -242,7 +242,7 @@ static void config_genmii_advert (struct uec_mii_info *mii_info)
 	advertise = mii_info->advertising;
 
 	/* Setup standard advertisement */
-	adv = phy_read (mii_info, MII_ADVERTISE);
+	adv = uec_phy_read(mii_info, MII_ADVERTISE);
 	adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
 	if (advertise & ADVERTISED_10baseT_Half)
 		adv |= ADVERTISE_10HALF;
@@ -252,7 +252,7 @@ static void config_genmii_advert (struct uec_mii_info *mii_info)
 		adv |= ADVERTISE_100HALF;
 	if (advertise & ADVERTISED_100baseT_Full)
 		adv |= ADVERTISE_100FULL;
-	phy_write (mii_info, MII_ADVERTISE, adv);
+	uec_phy_write(mii_info, MII_ADVERTISE, adv);
 }
 
 static void genmii_setup_forced (struct uec_mii_info *mii_info)
@@ -260,7 +260,7 @@ static void genmii_setup_forced (struct uec_mii_info *mii_info)
 	u16 ctrl;
 	u32 features = mii_info->phyinfo->features;
 
-	ctrl = phy_read (mii_info, MII_BMCR);
+	ctrl = uec_phy_read(mii_info, MII_BMCR);
 
 	ctrl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 |
 		  BMCR_SPEED1000 | BMCR_ANENABLE);
@@ -290,7 +290,7 @@ static void genmii_setup_forced (struct uec_mii_info *mii_info)
 		break;
 	}
 
-	phy_write (mii_info, MII_BMCR, ctrl);
+	uec_phy_write(mii_info, MII_BMCR, ctrl);
 }
 
 /* Enable and Restart Autonegotiation */
@@ -298,9 +298,9 @@ static void genmii_restart_aneg (struct uec_mii_info *mii_info)
 {
 	u16 ctl;
 
-	ctl = phy_read (mii_info, MII_BMCR);
+	ctl = uec_phy_read(mii_info, MII_BMCR);
 	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
-	phy_write (mii_info, MII_BMCR, ctl);
+	uec_phy_write(mii_info, MII_BMCR, ctl);
 }
 
 static int gbit_config_aneg (struct uec_mii_info *mii_info)
@@ -313,14 +313,14 @@ static int gbit_config_aneg (struct uec_mii_info *mii_info)
 		config_genmii_advert (mii_info);
 		advertise = mii_info->advertising;
 
-		adv = phy_read (mii_info, MII_CTRL1000);
+		adv = uec_phy_read(mii_info, MII_CTRL1000);
 		adv &= ~(ADVERTISE_1000FULL |
 			 ADVERTISE_1000HALF);
 		if (advertise & SUPPORTED_1000baseT_Half)
 			adv |= ADVERTISE_1000HALF;
 		if (advertise & SUPPORTED_1000baseT_Full)
 			adv |= ADVERTISE_1000FULL;
-		phy_write (mii_info, MII_CTRL1000, adv);
+		uec_phy_write(mii_info, MII_CTRL1000, adv);
 
 		/* Start/Restart aneg */
 		genmii_restart_aneg (mii_info);
@@ -335,13 +335,13 @@ static int marvell_config_aneg (struct uec_mii_info *mii_info)
 	/* The Marvell PHY has an errata which requires
 	 * that certain registers get written in order
 	 * to restart autonegotiation */
-	phy_write (mii_info, MII_BMCR, BMCR_RESET);
+	uec_phy_write(mii_info, MII_BMCR, BMCR_RESET);
 
-	phy_write (mii_info, 0x1d, 0x1f);
-	phy_write (mii_info, 0x1e, 0x200c);
-	phy_write (mii_info, 0x1d, 0x5);
-	phy_write (mii_info, 0x1e, 0);
-	phy_write (mii_info, 0x1e, 0x100);
+	uec_phy_write(mii_info, 0x1d, 0x1f);
+	uec_phy_write(mii_info, 0x1e, 0x200c);
+	uec_phy_write(mii_info, 0x1d, 0x5);
+	uec_phy_write(mii_info, 0x1e, 0);
+	uec_phy_write(mii_info, 0x1e, 0x100);
 
 	gbit_config_aneg (mii_info);
 
@@ -373,13 +373,13 @@ static int genmii_update_link (struct uec_mii_info *mii_info)
 	u16 status;
 
 	/* Status is read once to clear old link state */
-	phy_read (mii_info, MII_BMSR);
+	uec_phy_read(mii_info, MII_BMSR);
 
 	/*
 	 * Wait if the link is up, and autonegotiation is in progress
 	 * (ie - we're capable and it's not done)
 	 */
-	status = phy_read(mii_info, MII_BMSR);
+	status = uec_phy_read(mii_info, MII_BMSR);
 	if ((status & BMSR_LSTATUS) && (status & BMSR_ANEGCAPABLE)
 	    && !(status & BMSR_ANEGCOMPLETE)) {
 		int i = 0;
@@ -395,7 +395,7 @@ static int genmii_update_link (struct uec_mii_info *mii_info)
 
 			i++;
 			udelay(1000);	/* 1 ms */
-			status = phy_read(mii_info, MII_BMSR);
+			status = uec_phy_read(mii_info, MII_BMSR);
 		}
 		mii_info->link = 1;
 	} else {
@@ -420,7 +420,7 @@ static int genmii_read_status (struct uec_mii_info *mii_info)
 		return err;
 
 	if (mii_info->autoneg) {
-		status = phy_read(mii_info, MII_STAT1000);
+		status = uec_phy_read(mii_info, MII_STAT1000);
 
 		if (status & (LPA_1000FULL | LPA_1000HALF)) {
 			mii_info->speed = SPEED_1000;
@@ -429,7 +429,7 @@ static int genmii_read_status (struct uec_mii_info *mii_info)
 			else
 				mii_info->duplex = DUPLEX_HALF;
 		} else {
-			status = phy_read(mii_info, MII_LPA);
+			status = uec_phy_read(mii_info, MII_LPA);
 
 			if (status & (LPA_10FULL | LPA_100FULL))
 				mii_info->duplex = DUPLEX_FULL;
@@ -463,25 +463,25 @@ static int bcm_init(struct uec_mii_info *mii_info)
 
 		/* Wait for aneg to complete. */
 		do
-			val = phy_read(mii_info, MII_BMSR);
+			val = uec_phy_read(mii_info, MII_BMSR);
 		while (--cnt && !(val & BMSR_ANEGCOMPLETE));
 
 		/* Set RDX clk delay. */
-		phy_write(mii_info, 0x18, 0x7 | (7 << 12));
+		uec_phy_write(mii_info, 0x18, 0x7 | (7 << 12));
 
-		val = phy_read(mii_info, 0x18);
+		val = uec_phy_read(mii_info, 0x18);
 		/* Set RDX-RXC skew. */
 		val |= (1 << 8);
 		val |= (7 | (7 << 12));
 		/* Write bits 14:0. */
 		val |= (1 << 15);
-		phy_write(mii_info, 0x18, val);
+		uec_phy_write(mii_info, 0x18, val);
 	}
 
 	 return 0;
 }
 
-static int marvell_init(struct uec_mii_info *mii_info)
+static int uec_marvell_init(struct uec_mii_info *mii_info)
 {
 	struct eth_device *edev = mii_info->dev;
 	uec_private_t *uec = edev->priv;
@@ -494,7 +494,7 @@ static int marvell_init(struct uec_mii_info *mii_info)
 	    iface == RGMII_TXID)) {
 		int temp;
 
-		temp = phy_read(mii_info, MII_M1111_PHY_EXT_CR);
+		temp = uec_phy_read(mii_info, MII_M1111_PHY_EXT_CR);
 		if (iface == RGMII_ID) {
 			temp |= MII_M1111_RX_DELAY | MII_M1111_TX_DELAY;
 		} else if (iface == RGMII_RXID) {
@@ -504,14 +504,14 @@ static int marvell_init(struct uec_mii_info *mii_info)
 			temp &= ~MII_M1111_RX_DELAY;
 			temp |= MII_M1111_TX_DELAY;
 		}
-		phy_write(mii_info, MII_M1111_PHY_EXT_CR, temp);
+		uec_phy_write(mii_info, MII_M1111_PHY_EXT_CR, temp);
 
-		temp = phy_read(mii_info, MII_M1111_PHY_EXT_SR);
+		temp = uec_phy_read(mii_info, MII_M1111_PHY_EXT_SR);
 		temp &= ~MII_M1111_HWCFG_MODE_MASK;
 		temp |= MII_M1111_HWCFG_MODE_RGMII;
-		phy_write(mii_info, MII_M1111_PHY_EXT_SR, temp);
+		uec_phy_write(mii_info, MII_M1111_PHY_EXT_SR, temp);
 
-		phy_write(mii_info, MII_BMCR, BMCR_RESET);
+		uec_phy_write(mii_info, MII_BMCR, BMCR_RESET);
 	}
 
 	return 0;
@@ -534,7 +534,7 @@ static int marvell_read_status (struct uec_mii_info *mii_info)
 	if (mii_info->autoneg && mii_info->link) {
 		int speed;
 
-		status = phy_read (mii_info, MII_M1011_PHY_SPEC_STATUS);
+		status = uec_phy_read(mii_info, MII_M1011_PHY_SPEC_STATUS);
 
 		/* Get the duplexity */
 		if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
@@ -564,7 +564,7 @@ static int marvell_read_status (struct uec_mii_info *mii_info)
 static int marvell_ack_interrupt (struct uec_mii_info *mii_info)
 {
 	/* Clear the interrupts by reading the reg */
-	phy_read (mii_info, MII_M1011_IEVENT);
+	uec_phy_read(mii_info, MII_M1011_IEVENT);
 
 	return 0;
 }
@@ -572,9 +572,10 @@ static int marvell_ack_interrupt (struct uec_mii_info *mii_info)
 static int marvell_config_intr (struct uec_mii_info *mii_info)
 {
 	if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
-		phy_write (mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
+		uec_phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
 	else
-		phy_write (mii_info, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
+		uec_phy_write(mii_info, MII_M1011_IMASK,
+				MII_M1011_IMASK_CLEAR);
 
 	return 0;
 }
@@ -582,13 +583,13 @@ static int marvell_config_intr (struct uec_mii_info *mii_info)
 static int dm9161_init (struct uec_mii_info *mii_info)
 {
 	/* Reset the PHY */
-	phy_write (mii_info, MII_BMCR, phy_read (mii_info, MII_BMCR) |
+	uec_phy_write(mii_info, MII_BMCR, uec_phy_read(mii_info, MII_BMCR) |
 		   BMCR_RESET);
 	/* PHY and MAC connect */
-	phy_write (mii_info, MII_BMCR, phy_read (mii_info, MII_BMCR) &
+	uec_phy_write(mii_info, MII_BMCR, uec_phy_read(mii_info, MII_BMCR) &
 		   ~BMCR_ISOLATE);
 
-	phy_write (mii_info, MII_DM9161_SCR, MII_DM9161_SCR_INIT);
+	uec_phy_write(mii_info, MII_DM9161_SCR, MII_DM9161_SCR_INIT);
 
 	config_genmii_advert (mii_info);
 	/* Start/restart aneg */
@@ -614,7 +615,7 @@ static int dm9161_read_status (struct uec_mii_info *mii_info)
 	/* If the link is up, read the speed and duplex
 	   If we aren't autonegotiating assume speeds are as set */
 	if (mii_info->autoneg && mii_info->link) {
-		status = phy_read (mii_info, MII_DM9161_SCSR);
+		status = uec_phy_read(mii_info, MII_DM9161_SCSR);
 		if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_100H))
 			mii_info->speed = SPEED_100;
 		else
@@ -632,7 +633,7 @@ static int dm9161_read_status (struct uec_mii_info *mii_info)
 static int dm9161_ack_interrupt (struct uec_mii_info *mii_info)
 {
 	/* Clear the interrupt by reading the reg */
-	phy_read (mii_info, MII_DM9161_INTR);
+	uec_phy_read(mii_info, MII_DM9161_INTR);
 
 	return 0;
 }
@@ -640,9 +641,9 @@ static int dm9161_ack_interrupt (struct uec_mii_info *mii_info)
 static int dm9161_config_intr (struct uec_mii_info *mii_info)
 {
 	if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
-		phy_write (mii_info, MII_DM9161_INTR, MII_DM9161_INTR_INIT);
+		uec_phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_INIT);
 	else
-		phy_write (mii_info, MII_DM9161_INTR, MII_DM9161_INTR_STOP);
+		uec_phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_STOP);
 
 	return 0;
 }
@@ -696,7 +697,7 @@ static int smsc_read_status (struct uec_mii_info *mii_info)
 	if (mii_info->autoneg && mii_info->link) {
 		int	val;
 
-		status = phy_read (mii_info, 0x1f);
+		status = uec_phy_read(mii_info, 0x1f);
 		val = (status & 0x1c) >> 2;
 
 		switch (val) {
@@ -751,7 +752,7 @@ static struct phy_info phy_info_marvell = {
 	.phy_id_mask = 0xffffff00,
 	.name = "Marvell 88E11x1",
 	.features = MII_GBIT_FEATURES,
-	.init = &marvell_init,
+	.init = &uec_marvell_init,
 	.config_aneg = &marvell_config_aneg,
 	.read_status = &marvell_read_status,
 	.ack_interrupt = &marvell_ack_interrupt,
@@ -804,12 +805,12 @@ static struct phy_info *phy_info[] = {
 	NULL
 };
 
-u16 phy_read (struct uec_mii_info *mii_info, u16 regnum)
+u16 uec_phy_read(struct uec_mii_info *mii_info, u16 regnum)
 {
 	return mii_info->mdio_read (mii_info->dev, mii_info->mii_id, regnum);
 }
 
-void phy_write (struct uec_mii_info *mii_info, u16 regnum, u16 val)
+void uec_phy_write(struct uec_mii_info *mii_info, u16 regnum, u16 val)
 {
 	mii_info->mdio_write (mii_info->dev, mii_info->mii_id, regnum, val);
 }
@@ -825,11 +826,11 @@ struct phy_info *uec_get_phy_info (struct uec_mii_info *mii_info)
 	struct phy_info *theInfo = NULL;
 
 	/* Grab the bits from PHYIR1, and put them in the upper half */
-	phy_reg = phy_read (mii_info, MII_PHYSID1);
+	phy_reg = uec_phy_read(mii_info, MII_PHYSID1);
 	phy_ID = (phy_reg & 0xffff) << 16;
 
 	/* Grab the bits from PHYIR2, and put them in the lower half */
-	phy_reg = phy_read (mii_info, MII_PHYSID2);
+	phy_reg = uec_phy_read(mii_info, MII_PHYSID2);
 	phy_ID |= (phy_reg & 0xffff);
 
 	/* loop through all the known PHY types, and find one that */
@@ -869,39 +870,39 @@ void marvell_phy_interface_mode (struct eth_device *dev,
 
 	if (type == RGMII) {
 		if (speed == 100) {
-			phy_write (mii_info, 0x00, 0x9140);
-			phy_write (mii_info, 0x1d, 0x001f);
-			phy_write (mii_info, 0x1e, 0x200c);
-			phy_write (mii_info, 0x1d, 0x0005);
-			phy_write (mii_info, 0x1e, 0x0000);
-			phy_write (mii_info, 0x1e, 0x0100);
-			phy_write (mii_info, 0x09, 0x0e00);
-			phy_write (mii_info, 0x04, 0x01e1);
-			phy_write (mii_info, 0x00, 0x9140);
-			phy_write (mii_info, 0x00, 0x1000);
+			uec_phy_write(mii_info, 0x00, 0x9140);
+			uec_phy_write(mii_info, 0x1d, 0x001f);
+			uec_phy_write(mii_info, 0x1e, 0x200c);
+			uec_phy_write(mii_info, 0x1d, 0x0005);
+			uec_phy_write(mii_info, 0x1e, 0x0000);
+			uec_phy_write(mii_info, 0x1e, 0x0100);
+			uec_phy_write(mii_info, 0x09, 0x0e00);
+			uec_phy_write(mii_info, 0x04, 0x01e1);
+			uec_phy_write(mii_info, 0x00, 0x9140);
+			uec_phy_write(mii_info, 0x00, 0x1000);
 			udelay (100000);
-			phy_write (mii_info, 0x00, 0x2900);
-			phy_write (mii_info, 0x14, 0x0cd2);
-			phy_write (mii_info, 0x00, 0xa100);
-			phy_write (mii_info, 0x09, 0x0000);
-			phy_write (mii_info, 0x1b, 0x800b);
-			phy_write (mii_info, 0x04, 0x05e1);
-			phy_write (mii_info, 0x00, 0xa100);
-			phy_write (mii_info, 0x00, 0x2100);
+			uec_phy_write(mii_info, 0x00, 0x2900);
+			uec_phy_write(mii_info, 0x14, 0x0cd2);
+			uec_phy_write(mii_info, 0x00, 0xa100);
+			uec_phy_write(mii_info, 0x09, 0x0000);
+			uec_phy_write(mii_info, 0x1b, 0x800b);
+			uec_phy_write(mii_info, 0x04, 0x05e1);
+			uec_phy_write(mii_info, 0x00, 0xa100);
+			uec_phy_write(mii_info, 0x00, 0x2100);
 			udelay (1000000);
 		} else if (speed == 10) {
-			phy_write (mii_info, 0x14, 0x8e40);
-			phy_write (mii_info, 0x1b, 0x800b);
-			phy_write (mii_info, 0x14, 0x0c82);
-			phy_write (mii_info, 0x00, 0x8100);
+			uec_phy_write(mii_info, 0x14, 0x8e40);
+			uec_phy_write(mii_info, 0x1b, 0x800b);
+			uec_phy_write(mii_info, 0x14, 0x0c82);
+			uec_phy_write(mii_info, 0x00, 0x8100);
 			udelay (1000000);
 		}
 	}
 
 	/* handle 88e1111 rev.B2 erratum 5.6 */
 	if (mii_info->autoneg) {
-		status = phy_read (mii_info, MII_BMCR);
-		phy_write (mii_info, MII_BMCR, status | BMCR_ANENABLE);
+		status = uec_phy_read(mii_info, MII_BMCR);
+		uec_phy_write(mii_info, MII_BMCR, status | BMCR_ANENABLE);
 	}
 	/* now the B2 will correctly report autoneg completion status */
 }
-- 
1.6.5.2.g6ff9a

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [U-Boot] [PATCH v2 4/6] Create PHY Lib for U-Boot
  2011-04-05 21:59     ` [U-Boot] [PATCH v2 3/6] Remove instances of phy_read/write Andy Fleming
@ 2011-04-05 21:59       ` Andy Fleming
  2011-04-05 21:59         ` [U-Boot] [PATCH v2 5/6] phylib: Add a bunch of PHY drivers from tsec Andy Fleming
                           ` (4 more replies)
  2011-04-06 12:32       ` [U-Boot] [PATCH v2 3/6] Remove instances of phy_read/write Detlev Zundel
  1 sibling, 5 replies; 27+ messages in thread
From: Andy Fleming @ 2011-04-05 21:59 UTC (permalink / raw)
  To: u-boot

Extends the mii_dev structure to participate in a full-blown MDIO and
PHY driver scheme.  The mii_dev structure and miiphy calls are modified
in such a way to allow the original mii command and miiphy
infrastructure to work as before, but also to support a new set of APIs
which allow (among other things) sharing of PHY driver code and 10G support

The mii command will continue to support normal PHY management functions
(Clause 22 of 802.3), but will not be changed to support 10G
(Clause 45).

The basic design is similar to PHY Lib from Linux, but simplified for
U-Boot's network and driver infrastructure.

We now have MDIO drivers and PHY drivers

An MDIO driver provides:
read
write
reset

A PHY driver provides:
(optionally): probe
config - initial setup, starting of auto-negotiation
startup - waiting for AN, and reading link state
shutdown - any cleanup needed

The ethernet drivers interact with the PHY Lib using these functions:
phy_connect()
phy_config()
phy_startup()
phy_shutdown()

Each PHY driver can be configured separately, or all at once using
phylib_all_drivers.h (added in the patch which adds the drivers)

In the process, cleaned up a number of whitespace issues in miiphyutil.c

Signed-off-by: Andy Fleming <afleming@freescale.com>
---
* Fixed some sparse warnings/errors
* Changed headers for new files to GPL v2+
* Removed the unexplained 500ms delay after autonegotiation

 common/Makefile          |    1 +
 common/miiphyutil.c      |  308 ++++++++++++++-------
 drivers/net/phy/Makefile |    1 +
 drivers/net/phy/phy.c    |  719 ++++++++++++++++++++++++++++++++++++++++++++++
 include/miiphy.h         |   67 ++++--
 include/phy.h            |  489 +++++++++++++++++++++++++++++++
 net/eth.c                |    6 +
 7 files changed, 1476 insertions(+), 115 deletions(-)
 create mode 100644 drivers/net/phy/phy.c
 create mode 100644 include/phy.h

diff --git a/common/Makefile b/common/Makefile
index 048df0c..00847ef 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -114,6 +114,7 @@ COBJS-$(CONFIG_CMD_MFSL) += cmd_mfsl.o
 COBJS-$(CONFIG_CMD_MG_DISK) += cmd_mgdisk.o
 COBJS-$(CONFIG_MII) += miiphyutil.o
 COBJS-$(CONFIG_CMD_MII) += miiphyutil.o
+COBJS-$(CONFIG_PHYLIB) += miiphyutil.o
 COBJS-$(CONFIG_CMD_MII) += cmd_mii.o
 COBJS-$(CONFIG_CMD_MISC) += cmd_misc.o
 COBJS-$(CONFIG_CMD_MMC) += cmd_mmc.o
diff --git a/common/miiphyutil.c b/common/miiphyutil.c
index e282096..10adb52 100644
--- a/common/miiphyutil.c
+++ b/common/miiphyutil.c
@@ -28,6 +28,7 @@
 
 #include <common.h>
 #include <miiphy.h>
+#include <phy.h>
 
 #include <asm/types.h>
 #include <linux/list.h>
@@ -39,27 +40,18 @@
 
 #undef debug
 #ifdef MII_DEBUG
-#define debug(fmt,args...)	printf (fmt ,##args)
+#define debug(fmt, args...)	printf(fmt, ##args)
 #else
-#define debug(fmt,args...)
+#define debug(fmt, args...)
 #endif /* MII_DEBUG */
 
-struct mii_dev {
-	struct list_head link;
-	const char *name;
-	int (*read) (const char *devname, unsigned char addr,
-		     unsigned char reg, unsigned short *value);
-	int (*write) (const char *devname, unsigned char addr,
-		      unsigned char reg, unsigned short value);
-};
-
 static struct list_head mii_devs;
 static struct mii_dev *current_mii;
 
 /*
  * Lookup the mii_dev struct by the registered device name.
  */
-static struct mii_dev *miiphy_get_dev_by_name(const char *devname, int quiet)
+struct mii_dev *miiphy_get_dev_by_name(const char *devname)
 {
 	struct list_head *entry;
 	struct mii_dev *dev;
@@ -75,8 +67,6 @@ static struct mii_dev *miiphy_get_dev_by_name(const char *devname, int quiet)
 			return dev;
 	}
 
-	if (!quiet)
-		printf("No such device: %s\n", devname);
 	return NULL;
 }
 
@@ -90,70 +80,193 @@ void miiphy_init(void)
 	current_mii = NULL;
 }
 
+static int legacy_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg)
+{
+	unsigned short val;
+	int ret;
+	struct legacy_mii_dev *ldev = bus->priv;
+
+	ret = ldev->read(bus->name, addr, reg, &val);
+
+	return ret ? -1 : (int)val;
+}
+
+static int legacy_miiphy_write(struct mii_dev *bus, int addr, int devad,
+				int reg, u16 val)
+{
+	struct legacy_mii_dev *ldev = bus->priv;
+
+	return ldev->write(bus->name, addr, reg, val);
+}
+
 /*****************************************************************************
  *
  * Register read and write MII access routines for the device <name>.
  */
 void miiphy_register(const char *name,
-		      int (*read) (const char *devname, unsigned char addr,
+		      int (*read)(const char *devname, unsigned char addr,
 				   unsigned char reg, unsigned short *value),
-		      int (*write) (const char *devname, unsigned char addr,
+		      int (*write)(const char *devname, unsigned char addr,
 				    unsigned char reg, unsigned short value))
 {
 	struct mii_dev *new_dev;
+	struct legacy_mii_dev *ldev;
 	unsigned int name_len;
 	char *new_name;
 
 	/* check if we have unique name */
-	new_dev = miiphy_get_dev_by_name(name, 1);
+	new_dev = miiphy_get_dev_by_name(name);
 	if (new_dev) {
 		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 = malloc(sizeof(struct mii_dev) + name_len + 1);
+	ldev = malloc(sizeof(*ldev));
 
-	if (new_dev == NULL) {
-		printf ("miiphy_register: cannot allocate memory for '%s'\n",
+	if (new_dev == NULL || ldev == 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);
-	new_dev->read = read;
-	new_dev->write = write;
+	INIT_LIST_HEAD(&new_dev->link);
+	new_dev->read = legacy_miiphy_read;
+	new_dev->write = legacy_miiphy_write;
 	new_dev->name = new_name = (char *)(new_dev + 1);
-	strncpy (new_name, name, name_len);
+	strncpy(new_name, name, name_len);
 	new_name[name_len] = '\0';
+	ldev->read = read;
+	ldev->write = write;
+	new_dev->priv = ldev;
 
-	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, ldev->read, ldev->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;
 }
 
+struct mii_dev *mdio_alloc(void)
+{
+	struct mii_dev *bus;
+
+	bus = malloc(sizeof(*bus));
+	if (!bus)
+		return bus;
+
+	memset(bus, 0, sizeof(*bus));
+
+	bus->name = malloc(MDIO_NAME_LEN);
+	if (!bus->name) {
+		printf("Could not allocate name for mii_dev\n");
+		free(bus);
+		return NULL;
+	}
+
+	memset(bus->name, 0, MDIO_NAME_LEN);
+
+	/* initalize mii_dev struct fields */
+	INIT_LIST_HEAD(&bus->link);
+
+	return bus;
+}
+
+int mdio_register(struct mii_dev *bus)
+{
+	if (!bus || !bus->name || !bus->read || !bus->write)
+		return -1;
+
+	/* check if we have unique name */
+	if (miiphy_get_dev_by_name(bus->name)) {
+		printf("mdio_register: non unique device name '%s'\n",
+			bus->name);
+		return -1;
+	}
+
+	/* add it to the list */
+	list_add_tail(&bus->link, &mii_devs);
+
+	if (!current_mii)
+		current_mii = bus;
+
+	return 0;
+}
+
+void mdio_list_devices(void)
+{
+	struct list_head *entry;
+
+	list_for_each(entry, &mii_devs) {
+		int i;
+		struct mii_dev *bus = list_entry(entry, struct mii_dev, link);
+
+		printf("%s:\n", bus->name);
+
+		for (i = 0; i < PHY_MAX_ADDR; i++) {
+			struct phy_device *phydev = bus->phymap[i];
+
+			if (phydev) {
+				printf("%d - %s", i, phydev->drv->name);
+
+				if (phydev->dev)
+					printf(" <--> %s\n", phydev->dev->name);
+				else
+					printf("\n");
+			}
+		}
+	}
+}
+
 int miiphy_set_current_dev(const char *devname)
 {
 	struct mii_dev *dev;
 
-	dev = miiphy_get_dev_by_name(devname, 0);
+	dev = miiphy_get_dev_by_name(devname);
 	if (dev) {
 		current_mii = dev;
 		return 0;
 	}
 
+	printf("No such device: %s\n", devname);
+
 	return 1;
 }
 
+struct mii_dev *mdio_get_current_dev(void)
+{
+	return current_mii;
+}
+
+struct phy_device *mdio_phydev_for_ethname(const char *ethname)
+{
+	struct list_head *entry;
+	struct mii_dev *bus;
+
+	list_for_each(entry, &mii_devs) {
+		int i;
+		bus = list_entry(entry, struct mii_dev, link);
+
+		for (i = 0; i < PHY_MAX_ADDR; i++) {
+			if ((!bus->phymap[i]) || (!bus->phymap[i]->dev))
+				continue;
+
+			if (strcmp(bus->phymap[i]->dev->name, ethname) == 0)
+				return bus->phymap[i];
+		}
+	}
+
+	printf("%s is not a known ethernet\n", ethname);
+	return NULL;
+}
+
 const char *miiphy_get_current_dev(void)
 {
 	if (current_mii)
@@ -187,13 +300,15 @@ static struct mii_dev *miiphy_get_active_dev(const char *devname)
 int miiphy_read(const char *devname, unsigned char addr, unsigned char reg,
 		 unsigned short *value)
 {
-	struct mii_dev *dev;
+	struct mii_dev *bus;
 
-	dev = miiphy_get_active_dev(devname);
-	if (dev)
-		return dev->read(devname, addr, reg, value);
+	bus = miiphy_get_active_dev(devname);
+	if (bus)
+		*value = bus->read(bus, addr, MDIO_DEVAD_NONE, reg);
+	else
+		return 1;
 
-	return 1;
+	return (*value < 0) ? 1 : 0;
 }
 
 /*****************************************************************************
@@ -207,11 +322,11 @@ int miiphy_read(const char *devname, unsigned char addr, unsigned char reg,
 int miiphy_write(const char *devname, unsigned char addr, unsigned char reg,
 		  unsigned short value)
 {
-	struct mii_dev *dev;
+	struct mii_dev *bus;
 
-	dev = miiphy_get_active_dev(devname);
-	if (dev)
-		return dev->write(devname, addr, reg, value);
+	bus = miiphy_get_active_dev(devname);
+	if (bus)
+		return bus->write(bus, addr, MDIO_DEVAD_NONE, reg, value);
 
 	return 1;
 }
@@ -220,20 +335,20 @@ int miiphy_write(const 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);
 }
 
 /*****************************************************************************
@@ -253,30 +368,30 @@ int miiphy_info(const char *devname, unsigned char addr, unsigned int *oui,
 	unsigned int reg = 0;
 	unsigned short tmp;
 
-	if (miiphy_read (devname, addr, MII_PHYSID2, &tmp) != 0) {
-		debug ("PHY ID register 2 read failed\n");
-		return (-1);
+	if (miiphy_read(devname, addr, MII_PHYSID2, &tmp) != 0) {
+		debug("PHY ID register 2 read failed\n");
+		return -1;
 	}
 	reg = tmp;
 
-	debug ("MII_PHYSID2 @ 0x%x = 0x%04x\n", addr, reg);
+	debug("MII_PHYSID2 @ 0x%x = 0x%04x\n", addr, reg);
 
 	if (reg == 0xFFFF) {
 		/* No physical device present at this address */
-		return (-1);
+		return -1;
 	}
 
-	if (miiphy_read (devname, addr, MII_PHYSID1, &tmp) != 0) {
-		debug ("PHY ID register 1 read failed\n");
-		return (-1);
+	if (miiphy_read(devname, addr, MII_PHYSID1, &tmp) != 0) {
+		debug("PHY ID register 1 read failed\n");
+		return -1;
 	}
 	reg |= tmp << 16;
-	debug ("PHY_PHYIDR[1,2] @ 0x%x = 0x%08x\n", addr, reg);
+	debug("PHY_PHYIDR[1,2] @ 0x%x = 0x%08x\n", addr, reg);
 
 	*oui = (reg >> 10);
 	*model = (unsigned char)((reg >> 4) & 0x0000003F);
 	*rev = (unsigned char)(reg & 0x0000000F);
-	return (0);
+	return 0;
 }
 
 /*****************************************************************************
@@ -290,16 +405,16 @@ int miiphy_reset(const char *devname, unsigned char addr)
 	unsigned short reg;
 	int timeout = 500;
 
-	if (miiphy_read (devname, addr, MII_BMCR, &reg) != 0) {
-		debug ("PHY status read failed\n");
-		return (-1);
+	if (miiphy_read(devname, addr, MII_BMCR, &reg) != 0) {
+		debug("PHY status read failed\n");
+		return -1;
 	}
-	if (miiphy_write (devname, addr, MII_BMCR, reg | BMCR_RESET) != 0) {
-		debug ("PHY reset failed\n");
-		return (-1);
+	if (miiphy_write(devname, addr, MII_BMCR, reg | BMCR_RESET) != 0) {
+		debug("PHY reset failed\n");
+		return -1;
 	}
 #ifdef CONFIG_PHY_RESET_DELAY
-	udelay (CONFIG_PHY_RESET_DELAY);	/* Intel LXT971A needs this */
+	udelay(CONFIG_PHY_RESET_DELAY);	/* Intel LXT971A needs this */
 #endif
 	/*
 	 * Poll the control register for the reset bit to go to 0 (it is
@@ -315,12 +430,12 @@ int miiphy_reset(const char *devname, unsigned char addr)
 		udelay(1000);
 	}
 	if ((reg & 0x8000) == 0) {
-		return (0);
+		return 0;
 	} else {
-		puts ("PHY reset timed out\n");
-		return (-1);
+		puts("PHY reset timed out\n");
+		return -1;
 	}
-	return (0);
+	return 0;
 }
 
 /*****************************************************************************
@@ -338,33 +453,32 @@ int miiphy_speed(const char *devname, unsigned char addr)
 	 * Check for 1000BASE-X.  If it is supported, then assume that the speed
 	 * is 1000.
 	 */
-	if (miiphy_is_1000base_x (devname, addr)) {
+	if (miiphy_is_1000base_x(devname, addr))
 		return _1000BASET;
-	}
+
 	/*
 	 * No 1000BASE-X, so assume 1000BASE-T/100BASE-TX/10BASE-T register set.
 	 */
 	/* Check for 1000BASE-T. */
-	if (miiphy_read (devname, addr, MII_STAT1000, &btsr)) {
-		printf ("PHY 1000BT status");
+	if (miiphy_read(devname, addr, MII_STAT1000, &btsr)) {
+		printf("PHY 1000BT status");
 		goto miiphy_read_failed;
 	}
 	if (btsr != 0xFFFF &&
-	    (btsr & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD))) {
+			(btsr & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)))
 		return _1000BASET;
-	}
 #endif /* CONFIG_PHY_GIGE */
 
 	/* Check Basic Management Control Register first. */
-	if (miiphy_read (devname, addr, MII_BMCR, &bmcr)) {
-		printf ("PHY speed");
+	if (miiphy_read(devname, addr, MII_BMCR, &bmcr)) {
+		printf("PHY speed");
 		goto miiphy_read_failed;
 	}
 	/* Check if auto-negotiation is on. */
 	if (bmcr & BMCR_ANENABLE) {
 		/* Get auto-negotiation results. */
-		if (miiphy_read (devname, addr, MII_LPA, &anlpar)) {
-			printf ("PHY AN speed");
+		if (miiphy_read(devname, addr, MII_LPA, &anlpar)) {
+			printf("PHY AN speed");
 			goto miiphy_read_failed;
 		}
 		return (anlpar & LPA_100) ? _100BASET : _10BASET;
@@ -373,7 +487,7 @@ int miiphy_speed(const char *devname, unsigned char addr)
 	return (bmcr & BMCR_SPEED100) ? _100BASET : _10BASET;
 
 miiphy_read_failed:
-	printf (" read failed, assuming 10BASE-T\n");
+	printf(" read failed, assuming 10BASE-T\n");
 	return _10BASET;
 }
 
@@ -389,10 +503,10 @@ int miiphy_duplex(const char *devname, unsigned char addr)
 	u16 btsr;
 
 	/* Check for 1000BASE-X. */
-	if (miiphy_is_1000base_x (devname, addr)) {
+	if (miiphy_is_1000base_x(devname, addr)) {
 		/* 1000BASE-X */
-		if (miiphy_read (devname, addr, MII_LPA, &anlpar)) {
-			printf ("1000BASE-X PHY AN duplex");
+		if (miiphy_read(devname, addr, MII_LPA, &anlpar)) {
+			printf("1000BASE-X PHY AN duplex");
 			goto miiphy_read_failed;
 		}
 	}
@@ -400,8 +514,8 @@ int miiphy_duplex(const char *devname, unsigned char addr)
 	 * No 1000BASE-X, so assume 1000BASE-T/100BASE-TX/10BASE-T register set.
 	 */
 	/* Check for 1000BASE-T. */
-	if (miiphy_read (devname, addr, MII_STAT1000, &btsr)) {
-		printf ("PHY 1000BT status");
+	if (miiphy_read(devname, addr, MII_STAT1000, &btsr)) {
+		printf("PHY 1000BT status");
 		goto miiphy_read_failed;
 	}
 	if (btsr != 0xFFFF) {
@@ -414,15 +528,15 @@ int miiphy_duplex(const char *devname, unsigned char addr)
 #endif /* CONFIG_PHY_GIGE */
 
 	/* Check Basic Management Control Register first. */
-	if (miiphy_read (devname, addr, MII_BMCR, &bmcr)) {
-		puts ("PHY duplex");
+	if (miiphy_read(devname, addr, MII_BMCR, &bmcr)) {
+		puts("PHY duplex");
 		goto miiphy_read_failed;
 	}
 	/* Check if auto-negotiation is on. */
 	if (bmcr & BMCR_ANENABLE) {
 		/* Get auto-negotiation results. */
-		if (miiphy_read (devname, addr, MII_LPA, &anlpar)) {
-			puts ("PHY AN duplex");
+		if (miiphy_read(devname, addr, MII_LPA, &anlpar)) {
+			puts("PHY AN duplex");
 			goto miiphy_read_failed;
 		}
 		return (anlpar & (LPA_10FULL | LPA_100FULL)) ?
@@ -432,7 +546,7 @@ int miiphy_duplex(const char *devname, unsigned char addr)
 	return (bmcr & BMCR_FULLDPLX) ? FULL : HALF;
 
 miiphy_read_failed:
-	printf (" read failed, assuming half duplex\n");
+	printf(" read failed, assuming half duplex\n");
 	return HALF;
 }
 
@@ -446,8 +560,8 @@ int miiphy_is_1000base_x(const char *devname, unsigned char addr)
 #if defined(CONFIG_PHY_GIGE)
 	u16 exsr;
 
-	if (miiphy_read (devname, addr, MII_ESTATUS, &exsr)) {
-		printf ("PHY extended status read failed, assuming no "
+	if (miiphy_read(devname, addr, MII_ESTATUS, &exsr)) {
+		printf("PHY extended status read failed, assuming no "
 			"1000BASE-X\n");
 		return 0;
 	}
@@ -467,17 +581,17 @@ int miiphy_link(const char *devname, unsigned char addr)
 	unsigned short reg;
 
 	/* dummy read; needed to latch some phys */
-	(void)miiphy_read (devname, addr, MII_BMSR, &reg);
-	if (miiphy_read (devname, addr, MII_BMSR, &reg)) {
-		puts ("MII_BMSR read failed, assuming no link\n");
-		return (0);
+	(void)miiphy_read(devname, addr, MII_BMSR, &reg);
+	if (miiphy_read(devname, addr, MII_BMSR, &reg)) {
+		puts("MII_BMSR read failed, assuming no link\n");
+		return 0;
 	}
 
 	/* Determine if a link is active */
 	if ((reg & BMSR_LSTATUS) != 0) {
-		return (1);
+		return 1;
 	} else {
-		return (0);
+		return 0;
 	}
 }
 #endif
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index bba8901..7cb1094 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -27,6 +27,7 @@ LIB	:= $(obj)libphy.o
 
 COBJS-$(CONFIG_BITBANGMII) += miiphybb.o
 COBJS-$(CONFIG_MV88E61XX_SWITCH) += mv88e61xx.o
+COBJS-$(CONFIG_PHYLIB) += phy.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
new file mode 100644
index 0000000..fc34271
--- /dev/null
+++ b/drivers/net/phy/phy.c
@@ -0,0 +1,719 @@
+/*
+ * Generic PHY Management code
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * author Andy Fleming
+ *
+ * Based loosely off of Linux's PHY Lib
+ */
+
+#include <config.h>
+#include <common.h>
+#include <malloc.h>
+#include <net.h>
+#include <command.h>
+#include <miiphy.h>
+#include <phy.h>
+#include <errno.h>
+
+int phy_read(struct phy_device *phydev, int devad, int regnum)
+{
+	struct mii_dev *bus = phydev->bus;
+
+	return bus->read(bus, phydev->addr, devad, regnum);
+}
+
+int phy_write(struct phy_device *phydev, int devad, int regnum, u16 val)
+{
+	struct mii_dev *bus = phydev->bus;
+
+	return bus->write(bus, phydev->addr, devad, regnum, val);
+}
+
+
+int gen10g_shutdown(struct phy_device *phydev)
+{
+	return 0;
+}
+
+int gen10g_startup(struct phy_device *phydev)
+{
+	int devad, reg;
+	u32 mmd_mask = phydev->mmds;
+
+	phydev->link = 1;
+
+	/* For now just lie and say it's 10G all the time */
+	phydev->speed = SPEED_10000;
+	phydev->duplex = DUPLEX_FULL;
+
+	for (devad = 0; mmd_mask; devad++, mmd_mask = mmd_mask >> 1) {
+		if (!mmd_mask & 1)
+			continue;
+
+		/* Read twice because link state is latched and a
+		 * read moves the current state into the register */
+		phy_read(phydev, devad, MDIO_STAT1);
+		reg = phy_read(phydev, devad, MDIO_STAT1);
+		if (reg < 0 || !(reg & MDIO_STAT1_LSTATUS))
+			phydev->link = 0;
+	}
+
+	return 0;
+}
+
+int gen10g_config(struct phy_device *phydev)
+{
+	int mmd, stat2, devs1, devs2;
+
+	phydev->supported = phydev->advertising = SUPPORTED_10000baseT_Full;
+
+	/* Assume PHY must have at least one of PMA/PMD, WIS, PCS, PHY
+	 * XS or DTE XS; give up if none is present. */
+	for (mmd = 1; mmd <= 5; mmd++) {
+		/* Is this MMD present? */
+		stat2 = phy_read(phydev, mmd, MDIO_STAT2);
+		if (stat2 < 0 ||
+			(stat2 & MDIO_STAT2_DEVPRST) != MDIO_STAT2_DEVPRST_VAL)
+			continue;
+
+		/* It should tell us about all the other MMDs */
+		devs1 = phy_read(phydev, mmd, MDIO_DEVS1);
+		devs2 = phy_read(phydev, mmd, MDIO_DEVS2);
+		if (devs1 < 0 || devs2 < 0)
+			continue;
+
+		phydev->mmds = devs1 | (devs2 << 16);
+		return 0;
+	}
+
+	return -1;
+}
+
+
+static struct phy_driver gen10g_driver = {
+	.uid		= 0xffffffff,
+	.mask		= 0xffffffff,
+	.name		= "Generic 10G PHY",
+	.features	= 0,
+	.config		= gen10g_config,
+	.startup	= gen10g_startup,
+	.shutdown	= gen10g_shutdown,
+};
+
+/* Generic PHY support and helper functions */
+
+/**
+ * genphy_config_advert - sanitize and advertise auto-negotation parameters
+ * @phydev: target phy_device struct
+ *
+ * Description: Writes MII_ADVERTISE with the appropriate values,
+ *   after sanitizing the values to make sure we only advertise
+ *   what is supported.  Returns < 0 on error, 0 if the PHY's advertisement
+ *   hasn't changed, and > 0 if it has changed.
+ */
+int genphy_config_advert(struct phy_device *phydev)
+{
+	u32 advertise;
+	int oldadv, adv;
+	int err, changed = 0;
+
+	/* Only allow advertising what
+	 * this PHY supports */
+	phydev->advertising &= phydev->supported;
+	advertise = phydev->advertising;
+
+	/* Setup standard advertisement */
+	oldadv = adv = phy_read(phydev, MDIO_DEVAD_NONE, MII_ADVERTISE);
+
+	if (adv < 0)
+		return adv;
+
+	adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP |
+		 ADVERTISE_PAUSE_ASYM);
+	if (advertise & ADVERTISED_10baseT_Half)
+		adv |= ADVERTISE_10HALF;
+	if (advertise & ADVERTISED_10baseT_Full)
+		adv |= ADVERTISE_10FULL;
+	if (advertise & ADVERTISED_100baseT_Half)
+		adv |= ADVERTISE_100HALF;
+	if (advertise & ADVERTISED_100baseT_Full)
+		adv |= ADVERTISE_100FULL;
+	if (advertise & ADVERTISED_Pause)
+		adv |= ADVERTISE_PAUSE_CAP;
+	if (advertise & ADVERTISED_Asym_Pause)
+		adv |= ADVERTISE_PAUSE_ASYM;
+
+	if (adv != oldadv) {
+		err = phy_write(phydev, MDIO_DEVAD_NONE, MII_ADVERTISE, adv);
+
+		if (err < 0)
+			return err;
+		changed = 1;
+	}
+
+	/* Configure gigabit if it's supported */
+	if (phydev->supported & (SUPPORTED_1000baseT_Half |
+				SUPPORTED_1000baseT_Full)) {
+		oldadv = adv = phy_read(phydev, MDIO_DEVAD_NONE, MII_CTRL1000);
+
+		if (adv < 0)
+			return adv;
+
+		adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
+		if (advertise & SUPPORTED_1000baseT_Half)
+			adv |= ADVERTISE_1000HALF;
+		if (advertise & SUPPORTED_1000baseT_Full)
+			adv |= ADVERTISE_1000FULL;
+
+		if (adv != oldadv) {
+			err = phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000,
+					adv);
+
+			if (err < 0)
+				return err;
+			changed = 1;
+		}
+	}
+
+	return changed;
+}
+
+
+/**
+ * genphy_setup_forced - configures/forces speed/duplex from @phydev
+ * @phydev: target phy_device struct
+ *
+ * Description: Configures MII_BMCR to force speed/duplex
+ *   to the values in phydev. Assumes that the values are valid.
+ */
+int genphy_setup_forced(struct phy_device *phydev)
+{
+	int err;
+	int ctl = 0;
+
+	phydev->pause = phydev->asym_pause = 0;
+
+	if (SPEED_1000 == phydev->speed)
+		ctl |= BMCR_SPEED1000;
+	else if (SPEED_100 == phydev->speed)
+		ctl |= BMCR_SPEED100;
+
+	if (DUPLEX_FULL == phydev->duplex)
+		ctl |= BMCR_FULLDPLX;
+
+	err = phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, ctl);
+
+	return err;
+}
+
+
+/**
+ * genphy_restart_aneg - Enable and Restart Autonegotiation
+ * @phydev: target phy_device struct
+ */
+int genphy_restart_aneg(struct phy_device *phydev)
+{
+	int ctl;
+
+	ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
+
+	if (ctl < 0)
+		return ctl;
+
+	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
+
+	/* Don't isolate the PHY if we're negotiating */
+	ctl &= ~(BMCR_ISOLATE);
+
+	ctl = phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, ctl);
+
+	return ctl;
+}
+
+
+/**
+ * genphy_config_aneg - restart auto-negotiation or write BMCR
+ * @phydev: target phy_device struct
+ *
+ * Description: If auto-negotiation is enabled, we configure the
+ *   advertising, and then restart auto-negotiation.  If it is not
+ *   enabled, then we write the BMCR.
+ */
+int genphy_config_aneg(struct phy_device *phydev)
+{
+	int result;
+
+	if (AUTONEG_ENABLE != phydev->autoneg)
+		return genphy_setup_forced(phydev);
+
+	result = genphy_config_advert(phydev);
+
+	if (result < 0) /* error */
+		return result;
+
+	if (result == 0) {
+		/* Advertisment hasn't changed, but maybe aneg was never on to
+		 * begin with?  Or maybe phy was isolated? */
+		int ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
+
+		if (ctl < 0)
+			return ctl;
+
+		if (!(ctl & BMCR_ANENABLE) || (ctl & BMCR_ISOLATE))
+			result = 1; /* do restart aneg */
+	}
+
+	/* Only restart aneg if we are advertising something different
+	 * than we were before.	 */
+	if (result > 0)
+		result = genphy_restart_aneg(phydev);
+
+	return result;
+}
+
+/**
+ * genphy_update_link - update link status in @phydev
+ * @phydev: target phy_device struct
+ *
+ * Description: Update the value in phydev->link to reflect the
+ *   current link value.  In order to do this, we need to read
+ *   the status register twice, keeping the second value.
+ */
+int genphy_update_link(struct phy_device *phydev)
+{
+	unsigned int mii_reg;
+
+	/*
+	 * Wait if the link is up, and autonegotiation is in progress
+	 * (ie - we're capable and it's not done)
+	 */
+	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
+
+	/*
+	 * If we already saw the link up, and it hasn't gone down, then
+	 * we don't need to wait for autoneg again
+	 */
+	if (phydev->link && mii_reg & BMSR_LSTATUS)
+		return 0;
+
+	if ((mii_reg & BMSR_ANEGCAPABLE) && !(mii_reg & BMSR_ANEGCOMPLETE)) {
+		int i = 0;
+
+		printf("%s Waiting for PHY auto negotiation to complete",
+			phydev->dev->name);
+		while (!(mii_reg & BMSR_ANEGCOMPLETE)) {
+			/*
+			 * Timeout reached ?
+			 */
+			if (i > PHY_ANEG_TIMEOUT) {
+				printf(" TIMEOUT !\n");
+				phydev->link = 0;
+				return 0;
+			}
+
+			if (ctrlc()) {
+				puts("user interrupt!\n");
+				phydev->link = 0;
+				return -EINTR;
+			}
+
+			if ((i++ % 500) == 0)
+				printf(".");
+
+			udelay(1000);	/* 1 ms */
+			mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
+		}
+		printf(" done\n");
+		phydev->link = 1;
+	} else {
+		/* Read the link a second time to clear the latched state */
+		mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
+
+		if (mii_reg & BMSR_LSTATUS)
+			phydev->link = 1;
+		else
+			phydev->link = 0;
+	}
+
+	return 0;
+}
+
+/*
+ * Generic function which updates the speed and duplex.  If
+ * autonegotiation is enabled, it uses the AND of the link
+ * partner's advertised capabilities and our advertised
+ * capabilities.  If autonegotiation is disabled, we use the
+ * appropriate bits in the control register.
+ *
+ * Stolen from Linux's mii.c and phy_device.c
+ */
+static int genphy_parse_link(struct phy_device *phydev)
+{
+	int mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
+
+	/* We're using autonegotiation */
+	if (mii_reg & BMSR_ANEGCAPABLE) {
+		u32 lpa = 0;
+		u32 gblpa = 0;
+
+		/* Check for gigabit capability */
+		if (mii_reg & BMSR_ERCAP) {
+			/* We want a list of states supported by
+			 * both PHYs in the link
+			 */
+			gblpa = phy_read(phydev, MDIO_DEVAD_NONE, MII_STAT1000);
+			gblpa &= phy_read(phydev,
+					MDIO_DEVAD_NONE, MII_CTRL1000) << 2;
+		}
+
+		/* Set the baseline so we only have to set them
+		 * if they're different
+		 */
+		phydev->speed = SPEED_10;
+		phydev->duplex = DUPLEX_HALF;
+
+		/* Check the gigabit fields */
+		if (gblpa & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)) {
+			phydev->speed = SPEED_1000;
+
+			if (gblpa & PHY_1000BTSR_1000FD)
+				phydev->duplex = DUPLEX_FULL;
+
+			/* We're done! */
+			return 0;
+		}
+
+		lpa = phy_read(phydev, MDIO_DEVAD_NONE, MII_ADVERTISE);
+		lpa &= phy_read(phydev, MDIO_DEVAD_NONE, MII_LPA);
+
+		if (lpa & (LPA_100FULL | LPA_100HALF)) {
+			phydev->speed = SPEED_100;
+
+			if (lpa & LPA_100FULL)
+				phydev->duplex = DUPLEX_FULL;
+
+		} else if (lpa & LPA_10FULL)
+			phydev->duplex = DUPLEX_FULL;
+	} else {
+		u32 bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
+
+		phydev->speed = SPEED_10;
+		phydev->duplex = DUPLEX_HALF;
+
+		if (bmcr & BMCR_FULLDPLX)
+			phydev->duplex = DUPLEX_FULL;
+
+		if (bmcr & BMCR_SPEED1000)
+			phydev->speed = SPEED_1000;
+		else if (bmcr & BMCR_SPEED100)
+			phydev->speed = SPEED_100;
+	}
+
+	return 0;
+}
+
+int genphy_config(struct phy_device *phydev)
+{
+	int val;
+	u32 features;
+
+	/* For now, I'll claim that the generic driver supports
+	 * all possible port types */
+	features = (SUPPORTED_TP | SUPPORTED_MII
+			| SUPPORTED_AUI | SUPPORTED_FIBRE |
+			SUPPORTED_BNC);
+
+	/* Do we support autonegotiation? */
+	val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
+
+	if (val < 0)
+		return val;
+
+	if (val & BMSR_ANEGCAPABLE)
+		features |= SUPPORTED_Autoneg;
+
+	if (val & BMSR_100FULL)
+		features |= SUPPORTED_100baseT_Full;
+	if (val & BMSR_100HALF)
+		features |= SUPPORTED_100baseT_Half;
+	if (val & BMSR_10FULL)
+		features |= SUPPORTED_10baseT_Full;
+	if (val & BMSR_10HALF)
+		features |= SUPPORTED_10baseT_Half;
+
+	if (val & BMSR_ESTATEN) {
+		val = phy_read(phydev, MDIO_DEVAD_NONE, MII_ESTATUS);
+
+		if (val < 0)
+			return val;
+
+		if (val & ESTATUS_1000_TFULL)
+			features |= SUPPORTED_1000baseT_Full;
+		if (val & ESTATUS_1000_THALF)
+			features |= SUPPORTED_1000baseT_Half;
+	}
+
+	phydev->supported = features;
+	phydev->advertising = features;
+
+	genphy_config_aneg(phydev);
+
+	return 0;
+}
+
+int genphy_startup(struct phy_device *phydev)
+{
+	genphy_update_link(phydev);
+	genphy_parse_link(phydev);
+
+	return 0;
+}
+
+int genphy_shutdown(struct phy_device *phydev)
+{
+	return 0;
+}
+
+static struct phy_driver genphy_driver = {
+	.uid		= 0xffffffff,
+	.mask		= 0xffffffff,
+	.name		= "Generic PHY",
+	.features	= 0,
+	.config		= genphy_config,
+	.startup	= genphy_startup,
+	.shutdown	= genphy_shutdown,
+};
+
+static struct list_head phy_drivers;
+
+int phy_init(void)
+{
+	INIT_LIST_HEAD(&phy_drivers);
+
+	return 0;
+}
+
+int phy_register(struct phy_driver *drv)
+{
+	INIT_LIST_HEAD(&drv->list);
+	list_add_tail(&drv->list, &phy_drivers);
+
+	return 0;
+}
+
+int phy_probe(struct phy_device *phydev)
+{
+	int err = 0;
+
+	phydev->advertising = phydev->supported = phydev->drv->features;
+
+	if (phydev->drv->probe)
+		err = phydev->drv->probe(phydev);
+
+	return err;
+}
+
+struct phy_driver *get_phy_driver(struct phy_device *phydev,
+				phy_interface_t interface)
+{
+	struct list_head *entry;
+	int phy_id = phydev->phy_id;
+	struct phy_driver *drv = NULL;
+
+	list_for_each(entry, &phy_drivers) {
+		drv = list_entry(entry, struct phy_driver, list);
+		if ((drv->uid & drv->mask) == (phy_id & drv->mask))
+			return drv;
+	}
+
+	/* If we made it here, there's no driver for this PHY */
+	if (interface == PHY_INTERFACE_MODE_XGMII)
+		return &gen10g_driver;
+	else
+		return &genphy_driver;
+}
+
+struct phy_device *phy_device_create(struct mii_dev *bus, int addr, int phy_id,
+					phy_interface_t interface)
+{
+	struct phy_device *dev;
+
+	/* We allocate the device, and initialize the
+	 * default values */
+	dev = malloc(sizeof(*dev));
+	if (!dev) {
+		printf("Failed to allocate PHY device for %s:%d\n",
+			bus->name, addr);
+		return NULL;
+	}
+
+	memset(dev, 0, sizeof(*dev));
+
+	dev->duplex = -1;
+	dev->link = 1;
+	dev->interface = interface;
+
+	dev->autoneg = AUTONEG_ENABLE;
+
+	dev->addr = addr;
+	dev->phy_id = phy_id;
+	dev->bus = bus;
+
+	dev->drv = get_phy_driver(dev, interface);
+
+	phy_probe(dev);
+
+	return dev;
+}
+
+/**
+ * get_phy_id - reads the specified addr for its ID.
+ * @bus: the target MII bus
+ * @addr: PHY address on the MII bus
+ * @phy_id: where to store the ID retrieved.
+ *
+ * Description: Reads the ID registers of the PHY at @addr on the
+ *   @bus, stores it in @phy_id and returns zero on success.
+ */
+int get_phy_id(struct mii_dev *bus, int addr, int devad, u32 *phy_id)
+{
+	int phy_reg;
+
+	/* Grab the bits from PHYIR1, and put them
+	 * in the upper half */
+	phy_reg = bus->read(bus, addr, devad, MII_PHYSID1);
+
+	if (phy_reg < 0)
+		return -EIO;
+
+	*phy_id = (phy_reg & 0xffff) << 16;
+
+	/* Grab the bits from PHYIR2, and put them in the lower half */
+	phy_reg = bus->read(bus, addr, devad, MII_PHYSID2);
+
+	if (phy_reg < 0)
+		return -EIO;
+
+	*phy_id |= (phy_reg & 0xffff);
+
+	return 0;
+}
+
+/**
+ * get_phy_device - reads the specified PHY device and returns its @phy_device struct
+ * @bus: the target MII bus
+ * @addr: PHY address on the MII bus
+ *
+ * Description: Reads the ID registers of the PHY@@addr on the
+ *   @bus, then allocates and returns the phy_device to represent it.
+ */
+struct phy_device *get_phy_device(struct mii_dev *bus, int addr,
+				phy_interface_t interface)
+{
+	u32 phy_id = 0x1fffffff;
+	int i;
+	int r;
+
+	/* Try Standard (ie Clause 22) access */
+	r = get_phy_id(bus, addr, MDIO_DEVAD_NONE, &phy_id);
+	if (r)
+		return NULL;
+
+	/* If the PHY ID is mostly f's, we didn't find anything */
+	if ((phy_id & 0x1fffffff) != 0x1fffffff)
+		return phy_device_create(bus, addr, phy_id, interface);
+
+	/* Otherwise we have to try Clause 45 */
+	for (i = 1; i < 5; i++) {
+		r = get_phy_id(bus, addr, i, &phy_id);
+		if (r)
+			return NULL;
+
+		/* If the phy_id is mostly Fs, there is no device there */
+		if ((phy_id & 0x1fffffff) != 0x1fffffff)
+			break;
+	}
+
+	return phy_device_create(bus, addr, phy_id, interface);
+}
+
+struct phy_device *phy_connect(struct mii_dev *bus, int addr,
+				struct eth_device *dev,
+				phy_interface_t interface)
+{
+	/* Reset the bus */
+	bus->reset(bus);
+
+	/* If the PHY is not in the map, probe the PHY to id it */
+	if (!bus->phymap[addr]) {
+		bus->phymap[addr] = get_phy_device(bus, addr, interface);
+
+		if (!bus->phymap[addr])
+			printf("Could not get PHY for %s:%d\n", bus->name,
+				addr);
+	}
+
+	if (bus->phymap[addr]->dev)
+		printf("%s:%d is connected to %s.  Reconnecting to %s\n",
+			bus->name, addr, bus->phymap[addr]->dev->name,
+			dev->name);
+
+	bus->phymap[addr]->dev = dev;
+
+	printf("%s connected to %s\n", dev->name,
+		bus->phymap[addr]->drv->name);
+
+	return bus->phymap[addr];
+}
+
+int phy_startup(struct phy_device *phydev)
+{
+	if (phydev->drv->startup)
+		phydev->drv->startup(phydev);
+
+	return 0;
+}
+
+static int __board_phy_config(struct phy_device *phydev)
+{
+	return 0;
+}
+
+int board_phy_config(struct phy_device *phydev)
+	__attribute__((weak, alias("__board_phy_config")));
+
+int phy_config(struct phy_device *phydev)
+{
+	if (phydev->drv->config)
+		phydev->drv->config(phydev);
+
+	/* Invoke an optional board-specific helper */
+	board_phy_config(phydev);
+
+	return 0;
+}
+
+int phy_shutdown(struct phy_device *phydev)
+{
+	if (phydev->drv->shutdown)
+		phydev->drv->shutdown(phydev);
+
+	return 0;
+}
diff --git a/include/miiphy.h b/include/miiphy.h
index 42dc127..00db2dc 100644
--- a/include/miiphy.h
+++ b/include/miiphy.h
@@ -34,35 +34,66 @@
 #ifndef _miiphy_h_
 #define _miiphy_h_
 
+#include <common.h>
 #include <linux/mii.h>
+#include <linux/list.h>
 #include <net.h>
+#include <phy.h>
 
-int miiphy_read (const char *devname, unsigned char addr, unsigned char reg,
+struct legacy_mii_dev {
+	int (*read)(const char *devname, unsigned char addr,
+		     unsigned char reg, unsigned short *value);
+	int (*write)(const char *devname, unsigned char addr,
+		      unsigned char reg, unsigned short value);
+};
+
+#define MDIO_NAME_LEN 32
+
+struct mii_dev {
+	struct list_head link;
+	char *name;
+	void *priv;
+	int (*read)(struct mii_dev *bus, int addr, int devad, int reg);
+	int (*write)(struct mii_dev *bus, int addr, int devad, int reg,
+			u16 val);
+	int (*reset)(struct mii_dev *bus);
+	struct phy_device *phymap[PHY_MAX_ADDR];
+	u32 phy_mask;
+};
+
+int miiphy_read(const char *devname, unsigned char addr, unsigned char reg,
 		 unsigned short *value);
-int miiphy_write (const char *devname, unsigned char addr, unsigned char reg,
+int miiphy_write(const char *devname, unsigned char addr, unsigned char reg,
 		  unsigned short value);
-int miiphy_info (const char *devname, unsigned char addr, unsigned int *oui,
+int miiphy_info(const char *devname, unsigned char addr, unsigned int *oui,
 		 unsigned char *model, unsigned char *rev);
-int miiphy_reset (const char *devname, unsigned char addr);
-int miiphy_speed (const char *devname, unsigned char addr);
-int miiphy_duplex (const char *devname, unsigned char addr);
-int miiphy_is_1000base_x (const char *devname, unsigned char addr);
+int miiphy_reset(const char *devname, unsigned char addr);
+int miiphy_speed(const char *devname, unsigned char addr);
+int miiphy_duplex(const char *devname, unsigned char addr);
+int miiphy_is_1000base_x(const char *devname, unsigned char addr);
 #ifdef CONFIG_SYS_FAULT_ECHO_LINK_DOWN
-int miiphy_link (const char *devname, unsigned char addr);
+int miiphy_link(const char *devname, unsigned char addr);
 #endif
 
-void miiphy_init (void);
+void miiphy_init(void);
 
-void miiphy_register (const char *devname,
-		      int (*read) (const char *devname, unsigned char addr,
+void miiphy_register(const char *devname,
+		      int (*read)(const char *devname, unsigned char addr,
 				   unsigned char reg, unsigned short *value),
-		      int (*write) (const char *devname, unsigned char addr,
+		      int (*write)(const char *devname, unsigned char addr,
 				    unsigned char reg, unsigned short value));
 
-int miiphy_set_current_dev (const char *devname);
-const char *miiphy_get_current_dev (void);
+int miiphy_set_current_dev(const char *devname);
+const char *miiphy_get_current_dev(void);
+struct mii_dev *mdio_get_current_dev(void);
+struct mii_dev *miiphy_get_dev_by_name(const char *devname);
+struct phy_device *mdio_phydev_for_ethname(const char *devname);
+
+void miiphy_listdev(void);
 
-void miiphy_listdev (void);
+struct mii_dev *mdio_alloc(void);
+int mdio_register(struct mii_dev *bus);
+void mdio_list_devices(void);
 
 #ifdef CONFIG_BITBANGMII
 
@@ -85,10 +116,10 @@ struct bb_miiphy_bus {
 extern struct bb_miiphy_bus bb_miiphy_buses[];
 extern int bb_miiphy_buses_num;
 
-void bb_miiphy_init (void);
-int bb_miiphy_read (const char *devname, unsigned char addr,
+void bb_miiphy_init(void);
+int bb_miiphy_read(const char *devname, unsigned char addr,
 		    unsigned char reg, unsigned short *value);
-int bb_miiphy_write (const char *devname, unsigned char addr,
+int bb_miiphy_write(const char *devname, unsigned char addr,
 		     unsigned char reg, unsigned short value);
 #endif
 
diff --git a/include/phy.h b/include/phy.h
new file mode 100644
index 0000000..1053a9d
--- /dev/null
+++ b/include/phy.h
@@ -0,0 +1,489 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ *	Andy Fleming <afleming@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * This file pretty much stolen from Linux's mii.h/ethtool.h/phy.h
+ */
+
+#ifndef _PHY_H
+#define _PHY_H
+
+#include <linux/list.h>
+#include <linux/mii.h>
+
+/* MDIO Manageable Devices (MMDs). */
+#define MDIO_MMD_PMAPMD		1	/* Physical Medium Attachment/
+					 * Physical Medium Dependent */
+#define MDIO_MMD_WIS		2	/* WAN Interface Sublayer */
+#define MDIO_MMD_PCS		3	/* Physical Coding Sublayer */
+#define MDIO_MMD_PHYXS		4	/* PHY Extender Sublayer */
+#define MDIO_MMD_DTEXS		5	/* DTE Extender Sublayer */
+#define MDIO_MMD_TC		6	/* Transmission Convergence */
+#define MDIO_MMD_AN		7	/* Auto-Negotiation */
+#define MDIO_MMD_C22EXT		29	/* Clause 22 extension */
+#define MDIO_MMD_VEND1		30	/* Vendor specific 1 */
+#define MDIO_MMD_VEND2		31	/* Vendor specific 2 */
+
+/* Generic MDIO registers. */
+#define MDIO_CTRL1		MII_BMCR
+#define MDIO_STAT1		MII_BMSR
+#define MDIO_DEVID1		MII_PHYSID1
+#define MDIO_DEVID2		MII_PHYSID2
+#define MDIO_SPEED		4	/* Speed ability */
+#define MDIO_DEVS1		5	/* Devices in package */
+#define MDIO_DEVS2		6
+#define MDIO_CTRL2		7	/* 10G control 2 */
+#define MDIO_STAT2		8	/* 10G status 2 */
+#define MDIO_PMA_TXDIS		9	/* 10G PMA/PMD transmit disable */
+#define MDIO_PMA_RXDET		10	/* 10G PMA/PMD receive signal detect */
+#define MDIO_PMA_EXTABLE	11	/* 10G PMA/PMD extended ability */
+#define MDIO_PKGID1		14	/* Package identifier */
+#define MDIO_PKGID2		15
+#define MDIO_AN_ADVERTISE	16	/* AN advertising (base page) */
+#define MDIO_AN_LPA		19	/* AN LP abilities (base page) */
+#define MDIO_PHYXS_LNSTAT	24	/* PHY XGXS lane state */
+
+/* Media-dependent registers. */
+#define MDIO_PMA_10GBT_SWAPPOL	130	/* 10GBASE-T pair swap & polarity */
+#define MDIO_PMA_10GBT_TXPWR	131	/* 10GBASE-T TX power control */
+#define MDIO_PMA_10GBT_SNR	133	/* 10GBASE-T SNR margin, lane A.
+					 * Lanes B-D are numbered 134-136. */
+#define MDIO_PMA_10GBR_FECABLE	170	/* 10GBASE-R FEC ability */
+#define MDIO_PCS_10GBX_STAT1	24	/* 10GBASE-X PCS status 1 */
+#define MDIO_PCS_10GBRT_STAT1	32	/* 10GBASE-R/-T PCS status 1 */
+#define MDIO_PCS_10GBRT_STAT2	33	/* 10GBASE-R/-T PCS status 2 */
+#define MDIO_AN_10GBT_CTRL	32	/* 10GBASE-T auto-negotiation control */
+#define MDIO_AN_10GBT_STAT	33	/* 10GBASE-T auto-negotiation status */
+
+/* LASI (Link Alarm Status Interrupt) registers, defined by XENPAK MSA. */
+#define MDIO_PMA_LASI_RXCTRL	0x9000	/* RX_ALARM control */
+#define MDIO_PMA_LASI_TXCTRL	0x9001	/* TX_ALARM control */
+#define MDIO_PMA_LASI_CTRL	0x9002	/* LASI control */
+#define MDIO_PMA_LASI_RXSTAT	0x9003	/* RX_ALARM status */
+#define MDIO_PMA_LASI_TXSTAT	0x9004	/* TX_ALARM status */
+#define MDIO_PMA_LASI_STAT	0x9005	/* LASI status */
+
+/* Control register 1. */
+/* Enable extended speed selection */
+#define MDIO_CTRL1_SPEEDSELEXT		(BMCR_SPEED1000 | BMCR_SPEED100)
+/* All speed selection bits */
+#define MDIO_CTRL1_SPEEDSEL		(MDIO_CTRL1_SPEEDSELEXT | 0x003c)
+#define MDIO_CTRL1_FULLDPLX		BMCR_FULLDPLX
+#define MDIO_CTRL1_LPOWER		BMCR_PDOWN
+#define MDIO_CTRL1_RESET		BMCR_RESET
+#define MDIO_PMA_CTRL1_LOOPBACK		0x0001
+#define MDIO_PMA_CTRL1_SPEED1000	BMCR_SPEED1000
+#define MDIO_PMA_CTRL1_SPEED100		BMCR_SPEED100
+#define MDIO_PCS_CTRL1_LOOPBACK		BMCR_LOOPBACK
+#define MDIO_PHYXS_CTRL1_LOOPBACK	BMCR_LOOPBACK
+#define MDIO_AN_CTRL1_RESTART		BMCR_ANRESTART
+#define MDIO_AN_CTRL1_ENABLE		BMCR_ANENABLE
+#define MDIO_AN_CTRL1_XNP		0x2000	/* Enable extended next page */
+
+/* 10 Gb/s */
+#define MDIO_CTRL1_SPEED10G		(MDIO_CTRL1_SPEEDSELEXT | 0x00)
+/* 10PASS-TS/2BASE-TL */
+#define MDIO_CTRL1_SPEED10P2B		(MDIO_CTRL1_SPEEDSELEXT | 0x04)
+
+/* Status register 1. */
+#define MDIO_STAT1_LPOWERABLE		0x0002	/* Low-power ability */
+#define MDIO_STAT1_LSTATUS		BMSR_LSTATUS
+#define MDIO_STAT1_FAULT		0x0080	/* Fault */
+#define MDIO_AN_STAT1_LPABLE		0x0001	/* Link partner AN ability */
+#define MDIO_AN_STAT1_ABLE		BMSR_ANEGCAPABLE
+#define MDIO_AN_STAT1_RFAULT		BMSR_RFAULT
+#define MDIO_AN_STAT1_COMPLETE		BMSR_ANEGCOMPLETE
+#define MDIO_AN_STAT1_PAGE		0x0040	/* Page received */
+#define MDIO_AN_STAT1_XNP		0x0080	/* Extended next page status */
+
+/* Speed register. */
+#define MDIO_SPEED_10G			0x0001	/* 10G capable */
+#define MDIO_PMA_SPEED_2B		0x0002	/* 2BASE-TL capable */
+#define MDIO_PMA_SPEED_10P		0x0004	/* 10PASS-TS capable */
+#define MDIO_PMA_SPEED_1000		0x0010	/* 1000M capable */
+#define MDIO_PMA_SPEED_100		0x0020	/* 100M capable */
+#define MDIO_PMA_SPEED_10		0x0040	/* 10M capable */
+#define MDIO_PCS_SPEED_10P2B		0x0002	/* 10PASS-TS/2BASE-TL capable */
+
+/* Device present registers. */
+#define MDIO_DEVS_PRESENT(devad)	(1 << (devad))
+#define MDIO_DEVS_PMAPMD		MDIO_DEVS_PRESENT(MDIO_MMD_PMAPMD)
+#define MDIO_DEVS_WIS			MDIO_DEVS_PRESENT(MDIO_MMD_WIS)
+#define MDIO_DEVS_PCS			MDIO_DEVS_PRESENT(MDIO_MMD_PCS)
+#define MDIO_DEVS_PHYXS			MDIO_DEVS_PRESENT(MDIO_MMD_PHYXS)
+#define MDIO_DEVS_DTEXS			MDIO_DEVS_PRESENT(MDIO_MMD_DTEXS)
+#define MDIO_DEVS_TC			MDIO_DEVS_PRESENT(MDIO_MMD_TC)
+#define MDIO_DEVS_AN			MDIO_DEVS_PRESENT(MDIO_MMD_AN)
+#define MDIO_DEVS_C22EXT		MDIO_DEVS_PRESENT(MDIO_MMD_C22EXT)
+#define MDIO_DEVS_VEND1			MDIO_DEVS_PRESENT(MDIO_MMD_VEND1)
+#define MDIO_DEVS_VEND2			MDIO_DEVS_PRESENT(MDIO_MMD_VEND2)
+
+/* Control register 2. */
+#define MDIO_PMA_CTRL2_TYPE		0x000f	/* PMA/PMD type selection */
+#define MDIO_PMA_CTRL2_10GBCX4		0x0000	/* 10GBASE-CX4 type */
+#define MDIO_PMA_CTRL2_10GBEW		0x0001	/* 10GBASE-EW type */
+#define MDIO_PMA_CTRL2_10GBLW		0x0002	/* 10GBASE-LW type */
+#define MDIO_PMA_CTRL2_10GBSW		0x0003	/* 10GBASE-SW type */
+#define MDIO_PMA_CTRL2_10GBLX4		0x0004	/* 10GBASE-LX4 type */
+#define MDIO_PMA_CTRL2_10GBER		0x0005	/* 10GBASE-ER type */
+#define MDIO_PMA_CTRL2_10GBLR		0x0006	/* 10GBASE-LR type */
+#define MDIO_PMA_CTRL2_10GBSR		0x0007	/* 10GBASE-SR type */
+#define MDIO_PMA_CTRL2_10GBLRM		0x0008	/* 10GBASE-LRM type */
+#define MDIO_PMA_CTRL2_10GBT		0x0009	/* 10GBASE-T type */
+#define MDIO_PMA_CTRL2_10GBKX4		0x000a	/* 10GBASE-KX4 type */
+#define MDIO_PMA_CTRL2_10GBKR		0x000b	/* 10GBASE-KR type */
+#define MDIO_PMA_CTRL2_1000BT		0x000c	/* 1000BASE-T type */
+#define MDIO_PMA_CTRL2_1000BKX		0x000d	/* 1000BASE-KX type */
+#define MDIO_PMA_CTRL2_100BTX		0x000e	/* 100BASE-TX type */
+#define MDIO_PMA_CTRL2_10BT		0x000f	/* 10BASE-T type */
+#define MDIO_PCS_CTRL2_TYPE		0x0003	/* PCS type selection */
+#define MDIO_PCS_CTRL2_10GBR		0x0000	/* 10GBASE-R type */
+#define MDIO_PCS_CTRL2_10GBX		0x0001	/* 10GBASE-X type */
+#define MDIO_PCS_CTRL2_10GBW		0x0002	/* 10GBASE-W type */
+#define MDIO_PCS_CTRL2_10GBT		0x0003	/* 10GBASE-T type */
+
+/* Status register 2. */
+#define MDIO_STAT2_RXFAULT		0x0400	/* Receive fault */
+#define MDIO_STAT2_TXFAULT		0x0800	/* Transmit fault */
+#define MDIO_STAT2_DEVPRST		0xc000	/* Device present */
+#define MDIO_STAT2_DEVPRST_VAL		0x8000	/* Device present value */
+#define MDIO_PMA_STAT2_LBABLE		0x0001	/* PMA loopback ability */
+#define MDIO_PMA_STAT2_10GBEW		0x0002	/* 10GBASE-EW ability */
+#define MDIO_PMA_STAT2_10GBLW		0x0004	/* 10GBASE-LW ability */
+#define MDIO_PMA_STAT2_10GBSW		0x0008	/* 10GBASE-SW ability */
+#define MDIO_PMA_STAT2_10GBLX4		0x0010	/* 10GBASE-LX4 ability */
+#define MDIO_PMA_STAT2_10GBER		0x0020	/* 10GBASE-ER ability */
+#define MDIO_PMA_STAT2_10GBLR		0x0040	/* 10GBASE-LR ability */
+#define MDIO_PMA_STAT2_10GBSR		0x0080	/* 10GBASE-SR ability */
+#define MDIO_PMD_STAT2_TXDISAB		0x0100	/* PMD TX disable ability */
+#define MDIO_PMA_STAT2_EXTABLE		0x0200	/* Extended abilities */
+#define MDIO_PMA_STAT2_RXFLTABLE	0x1000	/* Receive fault ability */
+#define MDIO_PMA_STAT2_TXFLTABLE	0x2000	/* Transmit fault ability */
+#define MDIO_PCS_STAT2_10GBR		0x0001	/* 10GBASE-R capable */
+#define MDIO_PCS_STAT2_10GBX		0x0002	/* 10GBASE-X capable */
+#define MDIO_PCS_STAT2_10GBW		0x0004	/* 10GBASE-W capable */
+#define MDIO_PCS_STAT2_RXFLTABLE	0x1000	/* Receive fault ability */
+#define MDIO_PCS_STAT2_TXFLTABLE	0x2000	/* Transmit fault ability */
+
+/* Transmit disable register. */
+#define MDIO_PMD_TXDIS_GLOBAL		0x0001	/* Global PMD TX disable */
+#define MDIO_PMD_TXDIS_0		0x0002	/* PMD TX disable 0 */
+#define MDIO_PMD_TXDIS_1		0x0004	/* PMD TX disable 1 */
+#define MDIO_PMD_TXDIS_2		0x0008	/* PMD TX disable 2 */
+#define MDIO_PMD_TXDIS_3		0x0010	/* PMD TX disable 3 */
+
+/* Receive signal detect register. */
+#define MDIO_PMD_RXDET_GLOBAL		0x0001 /* Global PMD RX signal detect */
+#define MDIO_PMD_RXDET_0		0x0002	/* PMD RX signal detect 0 */
+#define MDIO_PMD_RXDET_1		0x0004	/* PMD RX signal detect 1 */
+#define MDIO_PMD_RXDET_2		0x0008	/* PMD RX signal detect 2 */
+#define MDIO_PMD_RXDET_3		0x0010	/* PMD RX signal detect 3 */
+
+/* Extended abilities register. */
+#define MDIO_PMA_EXTABLE_10GCX4		0x0001	/* 10GBASE-CX4 ability */
+#define MDIO_PMA_EXTABLE_10GBLRM	0x0002	/* 10GBASE-LRM ability */
+#define MDIO_PMA_EXTABLE_10GBT		0x0004	/* 10GBASE-T ability */
+#define MDIO_PMA_EXTABLE_10GBKX4	0x0008	/* 10GBASE-KX4 ability */
+#define MDIO_PMA_EXTABLE_10GBKR		0x0010	/* 10GBASE-KR ability */
+#define MDIO_PMA_EXTABLE_1000BT		0x0020	/* 1000BASE-T ability */
+#define MDIO_PMA_EXTABLE_1000BKX	0x0040	/* 1000BASE-KX ability */
+#define MDIO_PMA_EXTABLE_100BTX		0x0080	/* 100BASE-TX ability */
+#define MDIO_PMA_EXTABLE_10BT		0x0100	/* 10BASE-T ability */
+
+/* PHY XGXS lane state register. */
+#define MDIO_PHYXS_LNSTAT_SYNC0		0x0001
+#define MDIO_PHYXS_LNSTAT_SYNC1		0x0002
+#define MDIO_PHYXS_LNSTAT_SYNC2		0x0004
+#define MDIO_PHYXS_LNSTAT_SYNC3		0x0008
+#define MDIO_PHYXS_LNSTAT_ALIGN		0x1000
+
+/* PMA 10GBASE-T pair swap & polarity */
+#define MDIO_PMA_10GBT_SWAPPOL_ABNX	0x0001	/* Pair A/B uncrossed */
+#define MDIO_PMA_10GBT_SWAPPOL_CDNX	0x0002	/* Pair C/D uncrossed */
+#define MDIO_PMA_10GBT_SWAPPOL_AREV	0x0100	/* Pair A polarity reversed */
+#define MDIO_PMA_10GBT_SWAPPOL_BREV	0x0200	/* Pair B polarity reversed */
+#define MDIO_PMA_10GBT_SWAPPOL_CREV	0x0400	/* Pair C polarity reversed */
+#define MDIO_PMA_10GBT_SWAPPOL_DREV	0x0800	/* Pair D polarity reversed */
+
+/* PMA 10GBASE-T TX power register. */
+#define MDIO_PMA_10GBT_TXPWR_SHORT	0x0001	/* Short-reach mode */
+
+/* PMA 10GBASE-T SNR registers. */
+/* Value is SNR margin in dB, clamped to range [-127, 127], plus 0x8000. */
+#define MDIO_PMA_10GBT_SNR_BIAS		0x8000
+#define MDIO_PMA_10GBT_SNR_MAX		127
+
+/* PMA 10GBASE-R FEC ability register. */
+#define MDIO_PMA_10GBR_FECABLE_ABLE	0x0001	/* FEC ability */
+#define MDIO_PMA_10GBR_FECABLE_ERRABLE	0x0002	/* FEC error indic. ability */
+
+/* PCS 10GBASE-R/-T status register 1. */
+#define MDIO_PCS_10GBRT_STAT1_BLKLK	0x0001	/* Block lock attained */
+
+/* PCS 10GBASE-R/-T status register 2. */
+#define MDIO_PCS_10GBRT_STAT2_ERR	0x00ff
+#define MDIO_PCS_10GBRT_STAT2_BER	0x3f00
+
+/* AN 10GBASE-T control register. */
+#define MDIO_AN_10GBT_CTRL_ADV10G	0x1000	/* Advertise 10GBASE-T */
+
+/* AN 10GBASE-T status register. */
+#define MDIO_AN_10GBT_STAT_LPTRR	0x0200	/* LP training reset req. */
+#define MDIO_AN_10GBT_STAT_LPLTABLE	0x0400	/* LP loop timing ability */
+#define MDIO_AN_10GBT_STAT_LP10G	0x0800	/* LP is 10GBT capable */
+#define MDIO_AN_10GBT_STAT_REMOK	0x1000	/* Remote OK */
+#define MDIO_AN_10GBT_STAT_LOCOK	0x2000	/* Local OK */
+#define MDIO_AN_10GBT_STAT_MS		0x4000	/* Master/slave config */
+#define MDIO_AN_10GBT_STAT_MSFLT	0x8000	/* Master/slave config fault */
+
+/* LASI RX_ALARM control/status registers. */
+#define MDIO_PMA_LASI_RX_PHYXSLFLT	0x0001	/* PHY XS RX local fault */
+#define MDIO_PMA_LASI_RX_PCSLFLT	0x0008	/* PCS RX local fault */
+#define MDIO_PMA_LASI_RX_PMALFLT	0x0010	/* PMA/PMD RX local fault */
+#define MDIO_PMA_LASI_RX_OPTICPOWERFLT	0x0020	/* RX optical power fault */
+#define MDIO_PMA_LASI_RX_WISLFLT	0x0200	/* WIS local fault */
+
+/* LASI TX_ALARM control/status registers. */
+#define MDIO_PMA_LASI_TX_PHYXSLFLT	0x0001	/* PHY XS TX local fault */
+#define MDIO_PMA_LASI_TX_PCSLFLT	0x0008	/* PCS TX local fault */
+#define MDIO_PMA_LASI_TX_PMALFLT	0x0010	/* PMA/PMD TX local fault */
+#define MDIO_PMA_LASI_TX_LASERPOWERFLT	0x0080	/* Laser output power fault */
+#define MDIO_PMA_LASI_TX_LASERTEMPFLT	0x0100	/* Laser temperature fault */
+#define MDIO_PMA_LASI_TX_LASERBICURRFLT	0x0200	/* Laser bias current fault */
+
+/* LASI control/status registers. */
+#define MDIO_PMA_LASI_LSALARM		0x0001	/* LS_ALARM enable/status */
+#define MDIO_PMA_LASI_TXALARM		0x0002	/* TX_ALARM enable/status */
+#define MDIO_PMA_LASI_RXALARM		0x0004	/* RX_ALARM enable/status */
+
+/* Mapping between MDIO PRTAD/DEVAD and mii_ioctl_data::phy_id */
+
+#define MDIO_PHY_ID_C45			0x8000
+#define MDIO_PHY_ID_PRTAD		0x03e0
+#define MDIO_PHY_ID_DEVAD		0x001f
+#define MDIO_PHY_ID_C45_MASK						\
+	(MDIO_PHY_ID_C45 | MDIO_PHY_ID_PRTAD | MDIO_PHY_ID_DEVAD)
+
+/* Indicates what features are supported by the interface. */
+#define SUPPORTED_10baseT_Half		(1 << 0)
+#define SUPPORTED_10baseT_Full		(1 << 1)
+#define SUPPORTED_100baseT_Half		(1 << 2)
+#define SUPPORTED_100baseT_Full		(1 << 3)
+#define SUPPORTED_1000baseT_Half	(1 << 4)
+#define SUPPORTED_1000baseT_Full	(1 << 5)
+#define SUPPORTED_Autoneg		(1 << 6)
+#define SUPPORTED_TP			(1 << 7)
+#define SUPPORTED_AUI			(1 << 8)
+#define SUPPORTED_MII			(1 << 9)
+#define SUPPORTED_FIBRE			(1 << 10)
+#define SUPPORTED_BNC			(1 << 11)
+#define SUPPORTED_10000baseT_Full	(1 << 12)
+#define SUPPORTED_Pause			(1 << 13)
+#define SUPPORTED_Asym_Pause		(1 << 14)
+#define SUPPORTED_2500baseX_Full	(1 << 15)
+#define SUPPORTED_Backplane		(1 << 16)
+#define SUPPORTED_1000baseKX_Full	(1 << 17)
+#define SUPPORTED_10000baseKX4_Full	(1 << 18)
+#define SUPPORTED_10000baseKR_Full	(1 << 19)
+#define SUPPORTED_10000baseR_FEC	(1 << 20)
+
+/* Indicates what features are advertised by the interface. */
+#define ADVERTISED_10baseT_Half		(1 << 0)
+#define ADVERTISED_10baseT_Full		(1 << 1)
+#define ADVERTISED_100baseT_Half	(1 << 2)
+#define ADVERTISED_100baseT_Full	(1 << 3)
+#define ADVERTISED_1000baseT_Half	(1 << 4)
+#define ADVERTISED_1000baseT_Full	(1 << 5)
+#define ADVERTISED_Autoneg		(1 << 6)
+#define ADVERTISED_TP			(1 << 7)
+#define ADVERTISED_AUI			(1 << 8)
+#define ADVERTISED_MII			(1 << 9)
+#define ADVERTISED_FIBRE		(1 << 10)
+#define ADVERTISED_BNC			(1 << 11)
+#define ADVERTISED_10000baseT_Full	(1 << 12)
+#define ADVERTISED_Pause		(1 << 13)
+#define ADVERTISED_Asym_Pause		(1 << 14)
+#define ADVERTISED_2500baseX_Full	(1 << 15)
+#define ADVERTISED_Backplane		(1 << 16)
+#define ADVERTISED_1000baseKX_Full	(1 << 17)
+#define ADVERTISED_10000baseKX4_Full	(1 << 18)
+#define ADVERTISED_10000baseKR_Full	(1 << 19)
+#define ADVERTISED_10000baseR_FEC	(1 << 20)
+
+/* The following are all involved in forcing a particular link
+ * mode for the device for setting things.  When getting the
+ * devices settings, these indicate the current mode and whether
+ * it was foced up into this mode or autonegotiated.
+ */
+
+/* The forced speed, 10Mb, 100Mb, gigabit, 2.5Gb, 10GbE. */
+#define SPEED_10		10
+#define SPEED_100		100
+#define SPEED_1000		1000
+#define SPEED_2500		2500
+#define SPEED_10000		10000
+
+/* Duplex, half or full. */
+#define DUPLEX_HALF		0x00
+#define DUPLEX_FULL		0x01
+
+/* Which connector port. */
+#define PORT_TP			0x00
+#define PORT_AUI		0x01
+#define PORT_MII		0x02
+#define PORT_FIBRE		0x03
+#define PORT_BNC		0x04
+#define PORT_DA			0x05
+#define PORT_NONE		0xef
+#define PORT_OTHER		0xff
+
+/* Which transceiver to use. */
+#define XCVR_INTERNAL		0x00
+#define XCVR_EXTERNAL		0x01
+#define XCVR_DUMMY1		0x02
+#define XCVR_DUMMY2		0x03
+#define XCVR_DUMMY3		0x04
+
+/* Enable or disable autonegotiation.  If this is set to enable,
+ * the forced link modes above are completely ignored.
+ */
+#define AUTONEG_DISABLE		0x00
+#define AUTONEG_ENABLE		0x01
+
+#define MDIO_DEVAD_NONE -1
+#define PHY_MAX_ADDR 32
+
+#define PHY_BASIC_FEATURES	(SUPPORTED_10baseT_Half | \
+				 SUPPORTED_10baseT_Full | \
+				 SUPPORTED_100baseT_Half | \
+				 SUPPORTED_100baseT_Full | \
+				 SUPPORTED_Autoneg | \
+				 SUPPORTED_TP | \
+				 SUPPORTED_MII)
+
+#define PHY_GBIT_FEATURES	(PHY_BASIC_FEATURES | \
+				 SUPPORTED_1000baseT_Half | \
+				 SUPPORTED_1000baseT_Full)
+
+#define PHY_10G_FEATURES	(PHY_GBIT_FEATURES | \
+				SUPPORTED_10000baseT_Full)
+
+#define PHY_ANEG_TIMEOUT	4000
+
+
+typedef enum {
+	PHY_INTERFACE_MODE_MII,
+	PHY_INTERFACE_MODE_GMII,
+	PHY_INTERFACE_MODE_SGMII,
+	PHY_INTERFACE_MODE_TBI,
+	PHY_INTERFACE_MODE_RMII,
+	PHY_INTERFACE_MODE_RGMII,
+	PHY_INTERFACE_MODE_RGMII_ID,
+	PHY_INTERFACE_MODE_RGMII_RXID,
+	PHY_INTERFACE_MODE_RGMII_TXID,
+	PHY_INTERFACE_MODE_RTBI,
+	PHY_INTERFACE_MODE_XGMII
+} phy_interface_t;
+
+struct phy_device;
+
+/* struct phy_driver: a structure which defines PHY behavior
+ *
+ * uid will contain a number which represents the PHY.  During
+ * startup, the driver will poll the PHY to find out what its
+ * UID--as defined by registers 2 and 3--is.  The 32-bit result
+ * gotten from the PHY will be masked to
+ * discard any bits which may change based on revision numbers
+ * unimportant to functionality
+ *
+ */
+struct phy_driver {
+	char *name;
+	unsigned int uid;
+	unsigned int mask;
+
+	u32 features;
+
+	/* Called to do any driver startup necessities */
+	/* Will be called during phy_connect */
+	int (*probe)(struct phy_device *phydev);
+
+	/* Called to configure the PHY, and modify the controller
+	 * based on the results.  Should be called after phy_connect */
+	int (*config)(struct phy_device *phydev);
+
+	/* Called when starting up the controller */
+	int (*startup)(struct phy_device *phydev);
+
+	/* Called when bringing down the controller */
+	int (*shutdown)(struct phy_device *phydev);
+
+	struct list_head list;
+};
+
+struct phy_device {
+	/* Information about the PHY type */
+	/* And management functions */
+	struct mii_dev *bus;
+	struct phy_driver *drv;
+	void *priv;
+
+	struct eth_device *dev;
+
+	/* forced speed & duplex (no autoneg)
+	 * partner speed & duplex & pause (autoneg)
+	 */
+	int speed;
+	int duplex;
+
+	/* The most recently read link state */
+	int link;
+	int port;
+	phy_interface_t interface;
+
+	u32 advertising;
+	u32 supported;
+	u32 mmds;
+
+	int autoneg;
+	int addr;
+	int pause;
+	int asym_pause;
+	u32 phy_id;
+	u32 flags;
+};
+
+int phy_init(void);
+struct phy_device *phy_connect(struct mii_dev *bus, int addr,
+				struct eth_device *dev,
+				phy_interface_t interface);
+int phy_startup(struct phy_device *phydev);
+int phy_config(struct phy_device *phydev);
+int phy_shutdown(struct phy_device *phydev);
+int phy_write(struct phy_device *phydev, int devad, int reg, u16 val);
+int phy_read(struct phy_device *phydev, int devad, int reg);
+int phy_register(struct phy_driver *drv);
+int genphy_config_aneg(struct phy_device *phydev);
+int genphy_update_link(struct phy_device *phydev);
+int genphy_config(struct phy_device *phydev);
+int genphy_startup(struct phy_device *phydev);
+int genphy_shutdown(struct phy_device *phydev);
+int gen10g_config(struct phy_device *phydev);
+int gen10g_startup(struct phy_device *phydev);
+int gen10g_shutdown(struct phy_device *phydev);
+#endif
diff --git a/net/eth.c b/net/eth.c
index 3a7ff50..6523834 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -25,6 +25,7 @@
 #include <command.h>
 #include <net.h>
 #include <miiphy.h>
+#include <phy.h>
 
 void eth_parse_enetaddr(const char *addr, uchar *enetaddr)
 {
@@ -217,6 +218,11 @@ int eth_initialize(bd_t *bis)
 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
 	miiphy_init();
 #endif
+
+#ifdef CONFIG_PHYLIB
+	phy_init();
+#endif
+
 	/*
 	 * If board-specific initialization exists, call it.
 	 * If not, call a CPU-specific one
-- 
1.6.5.2.g6ff9a

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [U-Boot] [PATCH v2 5/6] phylib: Add a bunch of PHY drivers from tsec
  2011-04-05 21:59       ` [U-Boot] [PATCH v2 4/6] Create PHY Lib for U-Boot Andy Fleming
@ 2011-04-05 21:59         ` Andy Fleming
  2011-04-05 21:59           ` [U-Boot] [PATCH v2 6/6] tsec: Convert tsec to use PHY Lib Andy Fleming
                             ` (2 more replies)
  2011-04-06 12:56         ` [U-Boot] [PATCH v2 4/6] Create PHY Lib for U-Boot Detlev Zundel
                           ` (3 subsequent siblings)
  4 siblings, 3 replies; 27+ messages in thread
From: Andy Fleming @ 2011-04-05 21:59 UTC (permalink / raw)
  To: u-boot

The tsec driver had a bunch of PHY drivers already written. This
converts them all into PHY Lib drivers, and serves as the first
set of PHY drivers for PHY Lib.

While doing that, cleaned up a number of magic numbers (though
not all of them, as PHY vendors like to keep their numbers as
magical as possible).  Also, noticed that almost all of the
vitesse/cicada PHYs had the same config/parse/startup functions,
so those have been collapsed into one.

Signed-off-by: Andy Fleming <afleming@freescale.com>
---
* Added teranetics_init() to init function
* Sorted init functions in phy_init and in phy.h
* Sorted PHYs in drivers/net/phy/Makefile
* GPL v2+ on all new files
* Left the 500ms delay after autonegotiation for PHY drivers that had it,
  as I don't want to break the driver-specific functionality. I suspect that
  either we've already fixed the bug this was really working around, or we
  will need a bug fix in the generic code. Either way, this code doesn't
  change the previous behavior, and can always be fixed at a later date,
  when one of us has time to actually test it out.
* Added many constants and consolidated the vitesse functions

 drivers/net/phy/Makefile     |   11 ++
 drivers/net/phy/atheros.c    |   48 ++++++
 drivers/net/phy/broadcom.c   |  286 ++++++++++++++++++++++++++++++++
 drivers/net/phy/davicom.c    |   98 +++++++++++
 drivers/net/phy/lxt.c        |   87 ++++++++++
 drivers/net/phy/marvell.c    |  376 ++++++++++++++++++++++++++++++++++++++++++
 drivers/net/phy/micrel.c     |   40 +++++
 drivers/net/phy/natsemi.c    |   96 +++++++++++
 drivers/net/phy/phy.c        |   31 ++++
 drivers/net/phy/realtek.c    |  130 +++++++++++++++
 drivers/net/phy/teranetics.c |   54 ++++++
 drivers/net/phy/vitesse.c    |  242 +++++++++++++++++++++++++++
 include/phy.h                |   11 ++
 include/phylib_all_drivers.h |   25 +++
 14 files changed, 1535 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/phy/atheros.c
 create mode 100644 drivers/net/phy/broadcom.c
 create mode 100644 drivers/net/phy/davicom.c
 create mode 100644 drivers/net/phy/lxt.c
 create mode 100644 drivers/net/phy/marvell.c
 create mode 100644 drivers/net/phy/micrel.c
 create mode 100644 drivers/net/phy/natsemi.c
 create mode 100644 drivers/net/phy/realtek.c
 create mode 100644 drivers/net/phy/teranetics.c
 create mode 100644 drivers/net/phy/vitesse.c
 create mode 100644 include/phylib_all_drivers.h

diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 7cb1094..8e205ac 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -27,7 +27,18 @@ LIB	:= $(obj)libphy.o
 
 COBJS-$(CONFIG_BITBANGMII) += miiphybb.o
 COBJS-$(CONFIG_MV88E61XX_SWITCH) += mv88e61xx.o
+
 COBJS-$(CONFIG_PHYLIB) += phy.o
+COBJS-$(CONFIG_PHY_ATHEROS) += atheros.o
+COBJS-$(CONFIG_PHY_BROADCOM) += broadcom.o
+COBJS-$(CONFIG_PHY_DAVICOM) += davicom.o
+COBJS-$(CONFIG_PHY_LXT) += lxt.o
+COBJS-$(CONFIG_PHY_MARVELL) += marvell.o
+COBJS-$(CONFIG_PHY_MICREL) += micrel.o
+COBJS-$(CONFIG_PHY_NATSEMI) += natsemi.o
+COBJS-$(CONFIG_PHY_REALTEK) += realtek.o
+COBJS-$(CONFIG_PHY_TERANETICS) += teranetics.o
+COBJS-$(CONFIG_PHY_VITESSE) += vitesse.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c
new file mode 100644
index 0000000..a51be92
--- /dev/null
+++ b/drivers/net/phy/atheros.c
@@ -0,0 +1,48 @@
+/*
+ * Atheros PHY drivers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * author Andy Fleming
+ *
+ */
+#include <phy.h>
+
+static int ar8021_config(struct phy_device *phydev)
+{
+	phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x05);
+	phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x3D47);
+
+	return 0;
+}
+
+struct phy_driver AR8021_driver =  {
+	.name = "AR8021",
+	.uid = 0x4dd040,
+	.mask = 0xfffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = ar8021_config,
+	.startup = genphy_startup,
+	.shutdown = genphy_shutdown,
+};
+
+int atheros_init(void)
+{
+	phy_register(&AR8021_driver);
+
+	return 0;
+}
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
new file mode 100644
index 0000000..fe2e28e
--- /dev/null
+++ b/drivers/net/phy/broadcom.c
@@ -0,0 +1,286 @@
+/*
+ * Broadcom PHY drivers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ * author Andy Fleming
+ *
+ */
+#include <config.h>
+#include <common.h>
+#include <phy.h>
+
+/* Broadcom BCM54xx -- taken from linux sungem_phy */
+#define MIIM_BCM54xx_AUXCNTL			0x18
+#define MIIM_BCM54xx_AUXCNTL_ENCODE(val) (((val & 0x7) << 12)|(val & 0x7))
+#define MIIM_BCM54xx_AUXSTATUS			0x19
+#define MIIM_BCM54xx_AUXSTATUS_LINKMODE_MASK	0x0700
+#define MIIM_BCM54xx_AUXSTATUS_LINKMODE_SHIFT	8
+
+#define MIIM_BCM54XX_SHD			0x1c
+#define MIIM_BCM54XX_SHD_WRITE			0x8000
+#define MIIM_BCM54XX_SHD_VAL(x)			((x & 0x1f) << 10)
+#define MIIM_BCM54XX_SHD_DATA(x)		((x & 0x3ff) << 0)
+#define MIIM_BCM54XX_SHD_WR_ENCODE(val, data)	\
+	(MIIM_BCM54XX_SHD_WRITE | MIIM_BCM54XX_SHD_VAL(val) | \
+	 MIIM_BCM54XX_SHD_DATA(data))
+
+#define MIIM_BCM54XX_EXP_DATA		0x15	/* Expansion register data */
+#define MIIM_BCM54XX_EXP_SEL		0x17	/* Expansion register select */
+#define MIIM_BCM54XX_EXP_SEL_SSD	0x0e00	/* Secondary SerDes select */
+#define MIIM_BCM54XX_EXP_SEL_ER		0x0f00	/* Expansion register select */
+
+/* Broadcom BCM5461S */
+static int bcm5461_config(struct phy_device *phydev)
+{
+	genphy_config_aneg(phydev);
+
+	return 0;
+}
+
+static int bcm54xx_parse_status(struct phy_device *phydev)
+{
+	unsigned int mii_reg;
+
+	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_BCM54xx_AUXSTATUS);
+
+	switch ((mii_reg & MIIM_BCM54xx_AUXSTATUS_LINKMODE_MASK) >>
+			MIIM_BCM54xx_AUXSTATUS_LINKMODE_SHIFT) {
+	case 1:
+		phydev->duplex = DUPLEX_HALF;
+		phydev->speed = SPEED_10;
+		break;
+	case 2:
+		phydev->duplex = DUPLEX_FULL;
+		phydev->speed = SPEED_10;
+		break;
+	case 3:
+		phydev->duplex = DUPLEX_HALF;
+		phydev->speed = SPEED_100;
+		break;
+	case 5:
+		phydev->duplex = DUPLEX_FULL;
+		phydev->speed = SPEED_100;
+		break;
+	case 6:
+		phydev->duplex = DUPLEX_HALF;
+		phydev->speed = SPEED_1000;
+		break;
+	case 7:
+		phydev->duplex = DUPLEX_FULL;
+		phydev->speed = SPEED_1000;
+		break;
+	default:
+		printf("Auto-neg error, defaulting to 10BT/HD\n");
+		phydev->duplex = DUPLEX_HALF;
+		phydev->speed = SPEED_10;
+		break;
+	}
+
+	return 0;
+}
+
+static int bcm54xx_startup(struct phy_device *phydev)
+{
+	/* Read the Status (2x to make sure link is right) */
+	genphy_update_link(phydev);
+	bcm54xx_parse_status(phydev);
+
+	return 0;
+}
+
+/* Broadcom BCM5482S */
+/*
+ * "Ethernet at Wirespeed" needs to be enabled to achieve link in certain
+ * circumstances.  eg a gigabit TSEC connected to a gigabit switch with
+ * a 4-wire ethernet cable.  Both ends advertise gigabit, but can't
+ * link.  "Ethernet at Wirespeed" reduces advertised speed until link
+ * can be achieved.
+ */
+static u32 bcm5482_read_wirespeed(struct phy_device *phydev, u32 reg)
+{
+	return (phy_read(phydev, MDIO_DEVAD_NONE, reg) & 0x8FFF) | 0x8010;
+}
+
+static int bcm5482_config(struct phy_device *phydev)
+{
+	unsigned int reg;
+
+	/* reset the PHY */
+	reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
+	reg |= BMCR_RESET;
+	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, reg);
+
+	/* Setup read from auxilary control shadow register 7 */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_BCM54xx_AUXCNTL,
+			MIIM_BCM54xx_AUXCNTL_ENCODE(7));
+	/* Read Misc Control register and or in Ethernet at Wirespeed */
+	reg = bcm5482_read_wirespeed(phydev, MIIM_BCM54xx_AUXCNTL);
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_BCM54xx_AUXCNTL, reg);
+
+	/* Initial config/enable of secondary SerDes interface */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_BCM54XX_SHD,
+			MIIM_BCM54XX_SHD_WR_ENCODE(0x14, 0xf));
+	/* Write intial value to secondary SerDes Contol */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_BCM54XX_EXP_SEL,
+			MIIM_BCM54XX_EXP_SEL_SSD | 0);
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_BCM54XX_EXP_DATA,
+			BMCR_ANRESTART);
+	/* Enable copper/fiber auto-detect */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_BCM54XX_SHD,
+			MIIM_BCM54XX_SHD_WR_ENCODE(0x1e, 0x201));
+
+	genphy_config_aneg(phydev);
+
+	return 0;
+}
+
+/*
+ * Find out if PHY is in copper or serdes mode by looking at Expansion Reg
+ * 0x42 - "Operating Mode Status Register"
+ */
+static int bcm5482_is_serdes(struct phy_device *phydev)
+{
+	u16 val;
+	int serdes = 0;
+
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_BCM54XX_EXP_SEL,
+			MIIM_BCM54XX_EXP_SEL_ER | 0x42);
+	val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_BCM54XX_EXP_DATA);
+
+	switch (val & 0x1f) {
+	case 0x0d:	/* RGMII-to-100Base-FX */
+	case 0x0e:	/* RGMII-to-SGMII */
+	case 0x0f:	/* RGMII-to-SerDes */
+	case 0x12:	/* SGMII-to-SerDes */
+	case 0x13:	/* SGMII-to-100Base-FX */
+	case 0x16:	/* SerDes-to-Serdes */
+		serdes = 1;
+		break;
+	case 0x6:	/* RGMII-to-Copper */
+	case 0x14:	/* SGMII-to-Copper */
+	case 0x17:	/* SerDes-to-Copper */
+		break;
+	default:
+		printf("ERROR, invalid PHY mode (0x%x\n)", val);
+		break;
+	}
+
+	return serdes;
+}
+
+/*
+ * Determine SerDes link speed and duplex from Expansion reg 0x42 "Operating
+ * Mode Status Register"
+ */
+static u32 bcm5482_parse_serdes_sr(struct phy_device *phydev)
+{
+	u16 val;
+	int i = 0;
+
+	/* Wait 1s for link - Clause 37 autonegotiation happens very fast */
+	while (1) {
+		phy_write(phydev, MDIO_DEVAD_NONE, MIIM_BCM54XX_EXP_SEL,
+				MIIM_BCM54XX_EXP_SEL_ER | 0x42);
+		val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_BCM54XX_EXP_DATA);
+
+		if (val & 0x8000)
+			break;
+
+		if (i++ > 1000) {
+			phydev->link = 0;
+			return 1;
+		}
+
+		udelay(1000);	/* 1 ms */
+	}
+
+	phydev->link = 1;
+	switch ((val >> 13) & 0x3) {
+	case (0x00):
+		phydev->speed = 10;
+		break;
+	case (0x01):
+		phydev->speed = 100;
+		break;
+	case (0x02):
+		phydev->speed = 1000;
+		break;
+	}
+
+	phydev->duplex = (val & 0x1000) == 0x1000;
+
+	return 0;
+}
+
+/*
+ * Figure out if BCM5482 is in serdes or copper mode and determine link
+ * configuration accordingly
+ */
+static int bcm5482_startup(struct phy_device *phydev)
+{
+	if (bcm5482_is_serdes(phydev)) {
+		bcm5482_parse_serdes_sr(phydev);
+		phydev->port = PORT_FIBRE;
+	} else {
+		/* Wait for auto-negotiation to complete or fail */
+		genphy_update_link(phydev);
+		/* Parse BCM54xx copper aux status register */
+		bcm54xx_parse_status(phydev);
+	}
+
+	return 0;
+}
+
+static struct phy_driver BCM5461S_driver = {
+	.name = "Broadcom BCM5461S",
+	.uid = 0x2060c0,
+	.mask = 0xfffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &bcm5461_config,
+	.startup = &bcm54xx_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+static struct phy_driver BCM5464S_driver = {
+	.name = "Broadcom BCM5464S",
+	.uid = 0x2060b0,
+	.mask = 0xfffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &bcm5461_config,
+	.startup = &bcm54xx_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+static struct phy_driver BCM5482S_driver = {
+	.name = "Broadcom BCM5482S",
+	.uid = 0x143bcb0,
+	.mask = 0xffffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &bcm5482_config,
+	.startup = &bcm5482_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+int broadcom_init(void)
+{
+	phy_register(&BCM5482S_driver);
+	phy_register(&BCM5464S_driver);
+	phy_register(&BCM5461S_driver);
+
+	return 0;
+}
diff --git a/drivers/net/phy/davicom.c b/drivers/net/phy/davicom.c
new file mode 100644
index 0000000..8367fa1
--- /dev/null
+++ b/drivers/net/phy/davicom.c
@@ -0,0 +1,98 @@
+/*
+ * Davicom PHY drivers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ * author Andy Fleming
+ *
+ */
+#include <phy.h>
+
+#define MIIM_DM9161_SCR                0x10
+#define MIIM_DM9161_SCR_INIT   0x0610
+
+/* DM9161 Specified Configuration and Status Register */
+#define MIIM_DM9161_SCSR       0x11
+#define MIIM_DM9161_SCSR_100F  0x8000
+#define MIIM_DM9161_SCSR_100H  0x4000
+#define MIIM_DM9161_SCSR_10F   0x2000
+#define MIIM_DM9161_SCSR_10H   0x1000
+
+/* DM9161 10BT Configuration/Status */
+#define MIIM_DM9161_10BTCSR    0x12
+#define MIIM_DM9161_10BTCSR_INIT       0x7800
+
+
+/* Davicom DM9161E */
+static int dm9161_config(struct phy_device *phydev)
+{
+	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_ISOLATE);
+	/* Do not bypass the scrambler/descrambler */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_DM9161_SCR,
+			MIIM_DM9161_SCR_INIT);
+	/* Clear 10BTCSR to default */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_DM9161_10BTCSR,
+			MIIM_DM9161_10BTCSR_INIT);
+
+	genphy_config_aneg(phydev);
+
+	return 0;
+}
+
+static int dm9161_parse_status(struct phy_device *phydev)
+{
+	int mii_reg;
+
+	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_DM9161_SCSR);
+
+	if (mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_100H))
+		phydev->speed = SPEED_100;
+	else
+		phydev->speed = SPEED_10;
+
+	if (mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_10F))
+		phydev->duplex = DUPLEX_FULL;
+	else
+		phydev->duplex = DUPLEX_HALF;
+
+	return 0;
+}
+
+static int dm9161_startup(struct phy_device *phydev)
+{
+	genphy_update_link(phydev);
+	dm9161_parse_status(phydev);
+
+	return 0;
+}
+
+static struct phy_driver DM9161_driver = {
+	.name = "Davicom DM9161E",
+	.uid = 0x181b880,
+	.mask = 0xffffff0,
+	.features = PHY_BASIC_FEATURES,
+	.config = &dm9161_config,
+	.startup = &dm9161_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+int davicom_init(void)
+{
+	phy_register(&DM9161_driver);
+
+	return 0;
+}
diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c
new file mode 100644
index 0000000..d422c3a
--- /dev/null
+++ b/drivers/net/phy/lxt.c
@@ -0,0 +1,87 @@
+/*
+ * LXT PHY drivers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ * author Andy Fleming
+ *
+ */
+#include <phy.h>
+
+/* LXT971 Status 2 registers */
+#define MIIM_LXT971_SR2                     0x11  /* Status Register 2  */
+#define MIIM_LXT971_SR2_SPEED_MASK 0x4200
+#define MIIM_LXT971_SR2_10HDX     0x0000  /*  10 Mbit half duplex selected */
+#define MIIM_LXT971_SR2_10FDX     0x0200  /*  10 Mbit full duplex selected */
+#define MIIM_LXT971_SR2_100HDX    0x4000  /* 100 Mbit half duplex selected */
+#define MIIM_LXT971_SR2_100FDX    0x4200  /* 100 Mbit full duplex selected */
+
+
+/* LXT971 */
+static int lxt971_parse_status(struct phy_device *phydev)
+{
+	int mii_reg;
+	int speed;
+
+	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_LXT971_SR2);
+	speed = mii_reg & MIIM_LXT971_SR2_SPEED_MASK;
+
+	switch (speed) {
+	case MIIM_LXT971_SR2_10HDX:
+		phydev->speed = SPEED_10;
+		phydev->duplex = DUPLEX_HALF;
+		break;
+	case MIIM_LXT971_SR2_10FDX:
+		phydev->speed = SPEED_10;
+		phydev->duplex = DUPLEX_FULL;
+		break;
+	case MIIM_LXT971_SR2_100HDX:
+		phydev->speed = SPEED_100;
+		phydev->duplex = DUPLEX_HALF;
+		break;
+	default:
+		phydev->speed = SPEED_100;
+		phydev->duplex = DUPLEX_FULL;
+	}
+
+	return 0;
+}
+
+static int lxt971_startup(struct phy_device *phydev)
+{
+	genphy_update_link(phydev);
+	lxt971_parse_status(phydev);
+
+	return 0;
+}
+
+static struct phy_driver LXT971_driver = {
+	.name = "LXT971",
+	.uid = 0x1378e0,
+	.mask = 0xfffff0,
+	.features = PHY_BASIC_FEATURES,
+	.config = &genphy_config_aneg,
+	.startup = &lxt971_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+int lxt_init(void)
+{
+	phy_register(&LXT971_driver);
+
+	return 0;
+}
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
new file mode 100644
index 0000000..2a43b4f
--- /dev/null
+++ b/drivers/net/phy/marvell.c
@@ -0,0 +1,376 @@
+/*
+ * Marvell PHY drivers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ * author Andy Fleming
+ *
+ */
+#include <config.h>
+#include <common.h>
+#include <phy.h>
+
+#define PHY_AUTONEGOTIATE_TIMEOUT 5000
+
+/* 88E1011 PHY Status Register */
+#define MIIM_88E1xxx_PHY_STATUS		0x11
+#define MIIM_88E1xxx_PHYSTAT_SPEED	0xc000
+#define MIIM_88E1xxx_PHYSTAT_GBIT	0x8000
+#define MIIM_88E1xxx_PHYSTAT_100	0x4000
+#define MIIM_88E1xxx_PHYSTAT_DUPLEX	0x2000
+#define MIIM_88E1xxx_PHYSTAT_SPDDONE	0x0800
+#define MIIM_88E1xxx_PHYSTAT_LINK	0x0400
+
+#define MIIM_88E1xxx_PHY_SCR		0x10
+#define MIIM_88E1xxx_PHY_MDI_X_AUTO	0x0060
+
+/* 88E1111 PHY LED Control Register */
+#define MIIM_88E1111_PHY_LED_CONTROL	24
+#define MIIM_88E1111_PHY_LED_DIRECT	0x4100
+#define MIIM_88E1111_PHY_LED_COMBINE	0x411C
+
+/* 88E1118 PHY defines */
+#define MIIM_88E1118_PHY_PAGE		22
+#define MIIM_88E1118_PHY_LED_PAGE	3
+
+/* 88E1121 PHY LED Control Register */
+#define MIIM_88E1121_PHY_LED_CTRL	16
+#define MIIM_88E1121_PHY_LED_PAGE	3
+#define MIIM_88E1121_PHY_LED_DEF	0x0030
+
+/* 88E1121 PHY IRQ Enable/Status Register */
+#define MIIM_88E1121_PHY_IRQ_EN		18
+#define MIIM_88E1121_PHY_IRQ_STATUS	19
+
+#define MIIM_88E1121_PHY_PAGE		22
+
+/* 88E1145 Extended PHY Specific Control Register */
+#define MIIM_88E1145_PHY_EXT_CR 20
+#define MIIM_M88E1145_RGMII_RX_DELAY	0x0080
+#define MIIM_M88E1145_RGMII_TX_DELAY	0x0002
+
+#define MIIM_88E1145_PHY_LED_CONTROL	24
+#define MIIM_88E1145_PHY_LED_DIRECT	0x4100
+
+#define MIIM_88E1145_PHY_PAGE	29
+#define MIIM_88E1145_PHY_CAL_OV 30
+
+#define MIIM_88E1149_PHY_PAGE	29
+
+/* Marvell 88E1011S */
+static int m88e1011s_config(struct phy_device *phydev)
+{
+	/* Reset and configure the PHY */
+	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
+
+	phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x1f);
+	phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x200c);
+	phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x5);
+	phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0);
+	phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x100);
+
+	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
+
+	genphy_config_aneg(phydev);
+
+	return 0;
+}
+
+/* Parse the 88E1011's status register for speed and duplex
+ * information
+ */
+static uint m88e1xxx_parse_status(struct phy_device *phydev)
+{
+	unsigned int speed;
+	unsigned int mii_reg;
+
+	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1xxx_PHY_STATUS);
+
+	if ((mii_reg & MIIM_88E1xxx_PHYSTAT_LINK) &&
+		!(mii_reg & MIIM_88E1xxx_PHYSTAT_SPDDONE)) {
+		int i = 0;
+
+		puts("Waiting for PHY realtime link");
+		while (!(mii_reg & MIIM_88E1xxx_PHYSTAT_SPDDONE)) {
+			/* Timeout reached ? */
+			if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
+				puts(" TIMEOUT !\n");
+				phydev->link = 0;
+				break;
+			}
+
+			if ((i++ % 1000) == 0)
+				putc('.');
+			udelay(1000);
+			mii_reg = phy_read(phydev, MDIO_DEVAD_NONE,
+					MIIM_88E1xxx_PHY_STATUS);
+		}
+		puts(" done\n");
+		udelay(500000);	/* another 500 ms (results in faster booting) */
+	} else {
+		if (mii_reg & MIIM_88E1xxx_PHYSTAT_LINK)
+			phydev->link = 1;
+		else
+			phydev->link = 0;
+	}
+
+	if (mii_reg & MIIM_88E1xxx_PHYSTAT_DUPLEX)
+		phydev->duplex = DUPLEX_FULL;
+	else
+		phydev->duplex = DUPLEX_HALF;
+
+	speed = mii_reg & MIIM_88E1xxx_PHYSTAT_SPEED;
+
+	switch (speed) {
+	case MIIM_88E1xxx_PHYSTAT_GBIT:
+		phydev->speed = SPEED_1000;
+		break;
+	case MIIM_88E1xxx_PHYSTAT_100:
+		phydev->speed = SPEED_100;
+		break;
+	default:
+		phydev->speed = SPEED_10;
+		break;
+	}
+
+	return 0;
+}
+
+static int m88e1011s_startup(struct phy_device *phydev)
+{
+	genphy_update_link(phydev);
+	m88e1xxx_parse_status(phydev);
+
+	return 0;
+}
+
+/* Marvell 88E1111S */
+static int m88e1111s_config(struct phy_device *phydev)
+{
+	int reg;
+
+	/* Reset and configure the PHY */
+	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
+
+	if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
+			(phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) ||
+			(phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
+			(phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
+		reg = phy_read(phydev, MDIO_DEVAD_NONE, 0x1b);
+		reg = (reg & 0xfff0) | 0xb;
+		phy_write(phydev, MDIO_DEVAD_NONE, 0x1b, reg);
+	} else {
+		phy_write(phydev, MDIO_DEVAD_NONE, 0x1b, 0x1f);
+	}
+
+	phy_write(phydev, MDIO_DEVAD_NONE, 0x14, 0x0cd2);
+
+	genphy_config_aneg(phydev);
+
+	return 0;
+}
+
+/* Marvell 88E1118 */
+static int m88e1118_config(struct phy_device *phydev)
+{
+	/* Reset and configure the PHY */
+	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
+	/* Change Page Number */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0002);
+	/* Delay RGMII TX and RX */
+	phy_write(phydev, MDIO_DEVAD_NONE, 0x15, 0x1070);
+	/* Change Page Number */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0003);
+	/* Adjust LED control */
+	phy_write(phydev, MDIO_DEVAD_NONE, 0x10, 0x021e);
+	/* Change Page Number */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000);
+
+	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
+
+	genphy_config_aneg(phydev);
+
+	return 0;
+}
+
+static int m88e1118_startup(struct phy_device *phydev)
+{
+	/* Change Page Number */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000);
+
+	genphy_update_link(phydev);
+	m88e1xxx_parse_status(phydev);
+
+	return 0;
+}
+
+/* Marvell 88E1121R */
+static int m88e1121_config(struct phy_device *phydev)
+{
+	int pg;
+
+	/* Reset and configure the PHY */
+	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
+	genphy_config_aneg(phydev);
+
+	/* Switch the page to access the led register */
+	pg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_PAGE);
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_PAGE,
+			MIIM_88E1121_PHY_LED_PAGE);
+	/* Configure leds */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_LED_CTRL,
+			MIIM_88E1121_PHY_LED_DEF);
+	/* Restore the page pointer */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_PAGE, pg);
+
+	/* Disable IRQs and de-assert interrupt */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_IRQ_EN, 0);
+	phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_IRQ_STATUS);
+
+	return 0;
+}
+
+/* Marvell 88E1145 */
+static int m88e1145_config(struct phy_device *phydev)
+{
+	int reg;
+
+	/* Reset and configure the PHY */
+	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
+
+	/* Errata E0, E1 */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_PAGE, 0x001b);
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_CAL_OV, 0x418f);
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_PAGE, 0x0016);
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_CAL_OV, 0xa2da);
+
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1xxx_PHY_SCR,
+			MIIM_88E1xxx_PHY_MDI_X_AUTO);
+
+	reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_EXT_CR);
+	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
+		reg |= MIIM_M88E1145_RGMII_RX_DELAY |
+			MIIM_M88E1145_RGMII_TX_DELAY;
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_EXT_CR, reg);
+
+	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
+
+	genphy_config_aneg(phydev);
+
+	return 0;
+}
+
+static int m88e1145_startup(struct phy_device *phydev)
+{
+	genphy_update_link(phydev);
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_LED_CONTROL,
+			MIIM_88E1145_PHY_LED_DIRECT);
+	m88e1xxx_parse_status(phydev);
+
+	return 0;
+}
+
+/* Marvell 88E1149S */
+static int m88e1149_config(struct phy_device *phydev)
+{
+	/* Reset and configure the PHY */
+	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
+
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1149_PHY_PAGE, 0x1f);
+	phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x200c);
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1149_PHY_PAGE, 0x5);
+	phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x0);
+	phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x100);
+
+	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
+	genphy_config_aneg(phydev);
+
+	return 0;
+}
+
+
+static struct phy_driver M88E1011S_driver = {
+	.name = "Marvell 88E1011S",
+	.uid = 0x1410c60,
+	.mask = 0xffffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &m88e1011s_config,
+	.startup = &m88e1011s_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+static struct phy_driver M88E1111S_driver = {
+	.name = "Marvell 88E1111S",
+	.uid = 0x1410cc0,
+	.mask = 0xffffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &m88e1111s_config,
+	.startup = &m88e1011s_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+static struct phy_driver M88E1118_driver = {
+	.name = "Marvell 88E1118",
+	.uid = 0x1410e10,
+	.mask = 0xffffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &m88e1118_config,
+	.startup = &m88e1118_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+static struct phy_driver M88E1121R_driver = {
+	.name = "Marvell 88E1121R",
+	.uid = 0x1410cb0,
+	.mask = 0xffffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &m88e1121_config,
+	.startup = &genphy_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+static struct phy_driver M88E1145_driver = {
+	.name = "Marvell 88E1145",
+	.uid = 0x1410cd0,
+	.mask = 0xffffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &m88e1145_config,
+	.startup = &m88e1145_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+static struct phy_driver M88E1149S_driver = {
+	.name = "Marvell 88E1149S",
+	.uid = 0x1410ca0,
+	.mask = 0xffffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &m88e1149_config,
+	.startup = &m88e1011s_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+int marvell_init(void)
+{
+	phy_register(&M88E1149S_driver);
+	phy_register(&M88E1145_driver);
+	phy_register(&M88E1121R_driver);
+	phy_register(&M88E1118_driver);
+	phy_register(&M88E1111S_driver);
+	phy_register(&M88E1011S_driver);
+
+	return 0;
+}
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
new file mode 100644
index 0000000..b57bcfa
--- /dev/null
+++ b/drivers/net/phy/micrel.c
@@ -0,0 +1,40 @@
+/*
+ * Micrel PHY drivers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ * author Andy Fleming
+ *
+ */
+#include <phy.h>
+
+static struct phy_driver KSZ804_driver = {
+	.name = "Micrel KSZ804",
+	.uid = 0x221510,
+	.mask = 0xfffff0,
+	.features = PHY_BASIC_FEATURES,
+	.config = &genphy_config,
+	.startup = &genphy_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+int micrel_init(void)
+{
+	phy_register(&KSZ804_driver);
+
+	return 0;
+}
diff --git a/drivers/net/phy/natsemi.c b/drivers/net/phy/natsemi.c
new file mode 100644
index 0000000..2702f19
--- /dev/null
+++ b/drivers/net/phy/natsemi.c
@@ -0,0 +1,96 @@
+/*
+ * National Semiconductor PHY drivers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ * author Andy Fleming
+ *
+ */
+#include <phy.h>
+
+/* DP83865 Link and Auto-Neg Status Register */
+#define MIIM_DP83865_LANR      0x11
+#define MIIM_DP83865_SPD_MASK  0x0018
+#define MIIM_DP83865_SPD_1000  0x0010
+#define MIIM_DP83865_SPD_100   0x0008
+#define MIIM_DP83865_DPX_FULL  0x0002
+
+
+/* NatSemi DP83865 */
+static int dp83865_config(struct phy_device *phydev)
+{
+	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
+	genphy_config_aneg(phydev);
+
+	return 0;
+}
+
+static int dp83865_parse_status(struct phy_device *phydev)
+{
+	int mii_reg;
+
+	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_DP83865_LANR);
+
+	switch (mii_reg & MIIM_DP83865_SPD_MASK) {
+
+	case MIIM_DP83865_SPD_1000:
+		phydev->speed = SPEED_1000;
+		break;
+
+	case MIIM_DP83865_SPD_100:
+		phydev->speed = SPEED_100;
+		break;
+
+	default:
+		phydev->speed = SPEED_10;
+		break;
+
+	}
+
+	if (mii_reg & MIIM_DP83865_DPX_FULL)
+		phydev->duplex = DUPLEX_FULL;
+	else
+		phydev->duplex = DUPLEX_HALF;
+
+	return 0;
+}
+
+static int dp83865_startup(struct phy_device *phydev)
+{
+	genphy_update_link(phydev);
+	dp83865_parse_status(phydev);
+
+	return 0;
+}
+
+
+static struct phy_driver DP83865_driver = {
+	.name = "NatSemi DP83865",
+	.uid = 0x20005c70,
+	.mask = 0xfffffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &dp83865_config,
+	.startup = &dp83865_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+int natsemi_init(void)
+{
+	phy_register(&DP83865_driver);
+
+	return 0;
+}
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index fc34271..96026ea 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -507,6 +507,37 @@ int phy_init(void)
 {
 	INIT_LIST_HEAD(&phy_drivers);
 
+#ifdef CONFIG_PHY_ATHEROS
+	atheros_init();
+#endif
+#ifdef CONFIG_PHY_BROADCOM
+	broadcom_init();
+#endif
+#ifdef CONFIG_PHY_DAVICOM
+	davicom_init();
+#endif
+#ifdef CONFIG_PHY_LXT
+	lxt_init();
+#endif
+#ifdef CONFIG_PHY_MARVELL
+	marvell_init();
+#endif
+#ifdef CONFIG_PHY_MICREL
+	micrel_init();
+#endif
+#ifdef CONFIG_PHY_NATSEMI
+	natsemi_init();
+#endif
+#ifdef CONFIG_PHY_REALTEK
+	realtek_init();
+#endif
+#ifdef CONFIG_PHY_TERANETICS
+	teranetics_init();
+#endif
+#ifdef CONFIG_PHY_VITESSE
+	vitesse_init();
+#endif
+
 	return 0;
 }
 
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
new file mode 100644
index 0000000..e9e5014
--- /dev/null
+++ b/drivers/net/phy/realtek.c
@@ -0,0 +1,130 @@
+/*
+ * RealTek PHY drivers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ * author Andy Fleming
+ *
+ */
+#include <config.h>
+#include <common.h>
+#include <phy.h>
+
+#define PHY_AUTONEGOTIATE_TIMEOUT 5000
+
+/* RTL8211B PHY Status Register */
+#define MIIM_RTL8211B_PHY_STATUS       0x11
+#define MIIM_RTL8211B_PHYSTAT_SPEED    0xc000
+#define MIIM_RTL8211B_PHYSTAT_GBIT     0x8000
+#define MIIM_RTL8211B_PHYSTAT_100      0x4000
+#define MIIM_RTL8211B_PHYSTAT_DUPLEX   0x2000
+#define MIIM_RTL8211B_PHYSTAT_SPDDONE  0x0800
+#define MIIM_RTL8211B_PHYSTAT_LINK     0x0400
+
+
+/* RealTek RTL8211B */
+static int rtl8211b_config(struct phy_device *phydev)
+{
+	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
+
+	genphy_config_aneg(phydev);
+
+	return 0;
+}
+
+static int rtl8211b_parse_status(struct phy_device *phydev)
+{
+	unsigned int speed;
+	unsigned int mii_reg;
+
+	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211B_PHY_STATUS);
+
+	if (!(mii_reg & MIIM_RTL8211B_PHYSTAT_SPDDONE)) {
+		int i = 0;
+
+		/* in case of timeout ->link is cleared */
+		phydev->link = 1;
+		puts("Waiting for PHY realtime link");
+		while (!(mii_reg & MIIM_RTL8211B_PHYSTAT_SPDDONE)) {
+			/* Timeout reached ? */
+			if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
+				puts(" TIMEOUT !\n");
+				phydev->link = 0;
+				break;
+			}
+
+			if ((i++ % 1000) == 0)
+				putc('.');
+			udelay(1000);	/* 1 ms */
+			mii_reg = phy_read(phydev, MDIO_DEVAD_NONE,
+					MIIM_RTL8211B_PHY_STATUS);
+		}
+		puts(" done\n");
+		udelay(500000);	/* another 500 ms (results in faster booting) */
+	} else {
+		if (mii_reg & MIIM_RTL8211B_PHYSTAT_LINK)
+			phydev->link = 1;
+		else
+			phydev->link = 0;
+	}
+
+	if (mii_reg & MIIM_RTL8211B_PHYSTAT_DUPLEX)
+		phydev->duplex = DUPLEX_FULL;
+	else
+		phydev->duplex = DUPLEX_HALF;
+
+	speed = (mii_reg & MIIM_RTL8211B_PHYSTAT_SPEED);
+
+	switch (speed) {
+	case MIIM_RTL8211B_PHYSTAT_GBIT:
+		phydev->speed = SPEED_1000;
+		break;
+	case MIIM_RTL8211B_PHYSTAT_100:
+		phydev->speed = SPEED_100;
+		break;
+	default:
+		phydev->speed = SPEED_10;
+	}
+
+	return 0;
+}
+
+static int rtl8211b_startup(struct phy_device *phydev)
+{
+	/* Read the Status (2x to make sure link is right) */
+	genphy_update_link(phydev);
+	rtl8211b_parse_status(phydev);
+
+	return 0;
+}
+
+static struct phy_driver RTL8211B_driver = {
+	.name = "RealTek RTL8211B",
+	.uid = 0x1cc910,
+	.mask = 0xfffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &rtl8211b_config,
+	.startup = &rtl8211b_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+int realtek_init(void)
+{
+	phy_register(&RTL8211B_driver);
+
+	return 0;
+}
diff --git a/drivers/net/phy/teranetics.c b/drivers/net/phy/teranetics.c
new file mode 100644
index 0000000..9b92a0d
--- /dev/null
+++ b/drivers/net/phy/teranetics.c
@@ -0,0 +1,54 @@
+/*
+ * Teranetics PHY drivers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ * author Andy Fleming
+ *
+ */
+#include <phy.h>
+
+int tn2020_config(struct phy_device *phydev)
+{
+	if (phydev->port == PORT_FIBRE) {
+		phy_write(phydev, 30, 93, 2);
+		phy_write(phydev, 7, 0, 0x3200);
+	}
+
+	phydev->mmds = (MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS |
+			MDIO_DEVS_PHYXS | MDIO_DEVS_AN |
+			MDIO_DEVS_VEND1 | MDIO_DEVS_VEND2);
+
+	return 0;
+}
+
+struct phy_driver tn2020_driver = {
+	.name = "Teranetics TN2020",
+	.uid = 0x00a19410,
+	.mask = 0xfffffff0,
+	.features = PHY_10G_FEATURES,
+	.config = &tn2020_config,
+	.startup = &gen10g_startup,
+	.shutdown = &gen10g_shutdown,
+};
+
+int teranetics_init(void)
+{
+	phy_register(&tn2020_driver);
+
+	return 0;
+}
diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c
new file mode 100644
index 0000000..b2376ef
--- /dev/null
+++ b/drivers/net/phy/vitesse.c
@@ -0,0 +1,242 @@
+/*
+ * Vitesse PHY drivers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ * author Andy Fleming
+ *
+ */
+#include <miiphy.h>
+
+/* Cicada Auxiliary Control/Status Register */
+#define MIIM_CIS82xx_AUX_CONSTAT	0x1c
+#define MIIM_CIS82xx_AUXCONSTAT_INIT	0x0004
+#define MIIM_CIS82xx_AUXCONSTAT_DUPLEX	0x0020
+#define MIIM_CIS82xx_AUXCONSTAT_SPEED	0x0018
+#define MIIM_CIS82xx_AUXCONSTAT_GBIT	0x0010
+#define MIIM_CIS82xx_AUXCONSTAT_100	0x0008
+
+/* Cicada Extended Control Register 1 */
+#define MIIM_CIS82xx_EXT_CON1		0x17
+#define MIIM_CIS8201_EXTCON1_INIT	0x0000
+
+/* Cicada 8204 Extended PHY Control Register 1 */
+#define MIIM_CIS8204_EPHY_CON		0x17
+#define MIIM_CIS8204_EPHYCON_INIT	0x0006
+#define MIIM_CIS8204_EPHYCON_RGMII	0x1100
+
+/* Cicada 8204 Serial LED Control Register */
+#define MIIM_CIS8204_SLED_CON		0x1b
+#define MIIM_CIS8204_SLEDCON_INIT	0x1115
+
+/* Vitesse VSC8601 Extended PHY Control Register 1 */
+#define MIIM_VSC8601_EPHY_CON		0x17
+#define MIIM_VSC8601_EPHY_CON_INIT_SKEW	0x1120
+#define MIIM_VSC8601_SKEW_CTRL		0x1c
+
+#define PHY_EXT_PAGE_ACCESS    0x1f
+
+/* CIS8201 */
+static int vitesse_config(struct phy_device *phydev)
+{
+	/* Override PHY config settings */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT,
+			MIIM_CIS82xx_AUXCONSTAT_INIT);
+	/* Set up the interface mode */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_EXT_CON1,
+			MIIM_CIS8201_EXTCON1_INIT);
+
+	genphy_config_aneg(phydev);
+
+	return 0;
+}
+
+static int vitesse_parse_status(struct phy_device *phydev)
+{
+	int speed;
+	int mii_reg;
+
+	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT);
+
+	if (mii_reg & MIIM_CIS82xx_AUXCONSTAT_DUPLEX)
+		phydev->duplex = DUPLEX_FULL;
+	else
+		phydev->duplex = DUPLEX_HALF;
+
+	speed = mii_reg & MIIM_CIS82xx_AUXCONSTAT_SPEED;
+	switch (speed) {
+	case MIIM_CIS82xx_AUXCONSTAT_GBIT:
+		phydev->speed = SPEED_1000;
+		break;
+	case MIIM_CIS82xx_AUXCONSTAT_100:
+		phydev->speed = SPEED_100;
+		break;
+	default:
+		phydev->speed = SPEED_10;
+		break;
+	}
+
+	return 0;
+}
+
+static int vitesse_startup(struct phy_device *phydev)
+{
+	genphy_update_link(phydev);
+	vitesse_parse_status(phydev);
+
+	return 0;
+}
+
+static int cis8204_config(struct phy_device *phydev)
+{
+	/* Override PHY config settings */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT,
+			MIIM_CIS82xx_AUXCONSTAT_INIT);
+
+	genphy_config_aneg(phydev);
+
+	if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
+			(phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
+			(phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) ||
+			(phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID))
+		phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8204_EPHY_CON,
+				MIIM_CIS8204_EPHYCON_INIT |
+				MIIM_CIS8204_EPHYCON_RGMII);
+	else
+		phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8204_EPHY_CON,
+				MIIM_CIS8204_EPHYCON_INIT);
+
+	return 0;
+}
+
+/* Vitesse VSC8601 */
+int vsc8601_config(struct phy_device *phydev)
+{
+	/* Configure some basic stuff */
+#ifdef CONFIG_SYS_VSC8601_SKEWFIX
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8601_EPHY_CON,
+			MIIM_VSC8601_EPHY_CON_INIT_SKEW);
+#if defined(CONFIG_SYS_VSC8601_SKEW_TX) && defined(CONFIG_SYS_VSC8601_SKEW_RX)
+	phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 1);
+#define VSC8101_SKEW \
+	((CONFIG_SYS_VSC8601_SKEW_TX << 14) \
+	| (CONFIG_SYS_VSC8601_SKEW_RX << 12))
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8601_SKEW_CTRL,
+			VSC8101_SKEW);
+	phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0);
+#endif
+#endif
+
+	genphy_config_aneg(phydev);
+
+	return 0;
+}
+
+static struct phy_driver VSC8211_driver = {
+	.name	= "Vitesse VSC8211",
+	.uid	= 0xfc4b0,
+	.mask	= 0xffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &vitesse_config,
+	.startup = &vitesse_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+static struct phy_driver VSC8221_driver = {
+	.name = "Vitesse VSC8221",
+	.uid = 0xfc550,
+	.mask = 0xffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &genphy_config_aneg,
+	.startup = &vitesse_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+static struct phy_driver VSC8244_driver = {
+	.name = "Vitesse VSC8244",
+	.uid = 0xfc6c0,
+	.mask = 0xffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &genphy_config_aneg,
+	.startup = &vitesse_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+static struct phy_driver VSC8234_driver = {
+	.name = "Vitesse VSC8234",
+	.uid = 0xfc620,
+	.mask = 0xffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &genphy_config_aneg,
+	.startup = &vitesse_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+static struct phy_driver VSC8601_driver = {
+	.name = "Vitesse VSC8601",
+	.uid = 0x70420,
+	.mask = 0xffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &vsc8601_config,
+	.startup = &vitesse_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+static struct phy_driver VSC8641_driver = {
+	.name = "Vitesse VSC8641",
+	.uid = 0x70430,
+	.mask = 0xffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &genphy_config_aneg,
+	.startup = &vitesse_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+/* Vitesse bought Cicada, so we'll put these here */
+static struct phy_driver cis8201_driver = {
+	.name = "CIS8201",
+	.uid = 0xfc410,
+	.mask = 0xffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &vitesse_config,
+	.startup = &vitesse_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+static struct phy_driver cis8204_driver = {
+	.name = "Cicada Cis8204",
+	.uid = 0xfc440,
+	.mask = 0xffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &cis8204_config,
+	.startup = &vitesse_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+int vitesse_init(void)
+{
+	phy_register(&VSC8641_driver);
+	phy_register(&VSC8601_driver);
+	phy_register(&VSC8234_driver);
+	phy_register(&VSC8244_driver);
+	phy_register(&VSC8211_driver);
+	phy_register(&VSC8221_driver);
+	phy_register(&cis8201_driver);
+	phy_register(&cis8204_driver);
+
+	return 0;
+}
diff --git a/include/phy.h b/include/phy.h
index 1053a9d..4620089 100644
--- a/include/phy.h
+++ b/include/phy.h
@@ -486,4 +486,15 @@ int genphy_shutdown(struct phy_device *phydev);
 int gen10g_config(struct phy_device *phydev);
 int gen10g_startup(struct phy_device *phydev);
 int gen10g_shutdown(struct phy_device *phydev);
+
+int atheros_init(void);
+int broadcom_init(void);
+int davicom_init(void);
+int lxt_init(void);
+int marvell_init(void);
+int micrel_init(void);
+int natsemi_init(void);
+int realtek_init(void);
+int teranetics_init(void);
+int vitesse_init(void);
 #endif
diff --git a/include/phylib_all_drivers.h b/include/phylib_all_drivers.h
new file mode 100644
index 0000000..a73b3d7
--- /dev/null
+++ b/include/phylib_all_drivers.h
@@ -0,0 +1,25 @@
+/*
+ * Enable all PHYs
+ *
+ * This software may be used and distributed according to the
+ * terms of the GNU Public License, Version 2, incorporated
+ * herein by reference.
+ *
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * author Andy Fleming
+ *
+ */
+#ifndef _CONFIG_PHYLIB_ALL_H
+#define _CONFIG_PHYLIB_ALL_H
+
+#define CONFIG_PHY_VITESSE
+#define CONFIG_PHY_MARVELL
+#define CONFIG_PHY_MICREL
+#define CONFIG_PHY_BROADCOM
+#define CONFIG_PHY_DAVICOM
+#define CONFIG_PHY_REALTEK
+#define CONFIG_PHY_NATSEMI
+#define CONFIG_PHY_TERANETICS
+#define CONFIG_PHY_LXT
+
+#endif
-- 
1.6.5.2.g6ff9a

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [U-Boot] [PATCH v2 6/6] tsec: Convert tsec to use PHY Lib
  2011-04-05 21:59         ` [U-Boot] [PATCH v2 5/6] phylib: Add a bunch of PHY drivers from tsec Andy Fleming
@ 2011-04-05 21:59           ` Andy Fleming
  2011-04-06 13:02             ` Detlev Zundel
  2011-04-06 13:01           ` [U-Boot] [PATCH v2 5/6] phylib: Add a bunch of PHY drivers from tsec Detlev Zundel
  2011-04-06 22:50           ` Mike Frysinger
  2 siblings, 1 reply; 27+ messages in thread
From: Andy Fleming @ 2011-04-05 21:59 UTC (permalink / raw)
  To: u-boot

This converts tsec to use the new PHY Lib.  All of the old PHY support
is ripped out.  The old MDIO driver is split off, and placed in
fsl_mdio.c.  The initialization is modified to initialize the MDIO
driver as well.  The powerpc config file is modified to configure PHYLIB
if TSEC_ENET is configured.

Signed-off-by: Mingkai Hu <Mingkai.hu@freescale.com>
Signed-off-by: Andy Fleming <afleming@freescale.com>
---
* Fixed numerous sparse warnings/errors

 arch/powerpc/include/asm/config.h         |    7 +
 arch/powerpc/include/asm/fsl_enet.h       |   10 +
 board/freescale/mpc837xemds/mpc837xemds.c |    7 +
 board/freescale/mpc8536ds/mpc8536ds.c     |    6 +
 board/freescale/mpc8544ds/mpc8544ds.c     |   30 +
 board/freescale/mpc8572ds/mpc8572ds.c     |    6 +
 board/freescale/p1022ds/p1022ds.c         |    6 +
 board/freescale/p1_p2_rdb/p1_p2_rdb.c     |    6 +
 board/freescale/p2020ds/p2020ds.c         |    7 +
 drivers/net/Makefile                      |    2 +-
 drivers/net/fsl_mdio.c                    |  120 +++
 drivers/net/tsec.c                        | 1609 ++---------------------------
 include/fsl_mdio.h                        |   62 ++
 include/tsec.h                            |  298 +-----
 14 files changed, 389 insertions(+), 1787 deletions(-)
 create mode 100644 drivers/net/fsl_mdio.c
 create mode 100644 include/fsl_mdio.h

diff --git a/arch/powerpc/include/asm/config.h b/arch/powerpc/include/asm/config.h
index 536f142..42b9e1b 100644
--- a/arch/powerpc/include/asm/config.h
+++ b/arch/powerpc/include/asm/config.h
@@ -80,6 +80,13 @@
 #endif
 #endif
 
+/* The TSEC driver uses the PHYLIB infrastructure */
+#if defined(CONFIG_TSEC_ENET) || defined(CONFIG_FMAN_ENET)
+#define CONFIG_PHYLIB
+
+#include <phylib_all_drivers.h>
+#endif /* PHYLIB-supporting ethernets */
+
 /* All PPC boards must swap IDE bytes */
 #define CONFIG_IDE_SWAP_IO
 
diff --git a/arch/powerpc/include/asm/fsl_enet.h b/arch/powerpc/include/asm/fsl_enet.h
index 4fb2857..9475249 100644
--- a/arch/powerpc/include/asm/fsl_enet.h
+++ b/arch/powerpc/include/asm/fsl_enet.h
@@ -28,6 +28,16 @@ enum fsl_phy_enet_if {
 	FSL_ETH_IF_NONE,
 };
 
+typedef struct tsec_mii_mng {
+	u32 miimcfg;		/* MII management configuration reg */
+	u32 miimcom;		/* MII management command reg */
+	u32 miimadd;		/* MII management address reg */
+	u32 miimcon;		/* MII management control reg */
+	u32 miimstat;		/* MII management status reg  */
+	u32 miimind;		/* MII management indication reg */
+	u32 ifstat;		/* Interface Status Register */
+} __attribute__ ((packed))tsec_mii_t;
+
 int fdt_fixup_phy_connection(void *blob, int offset, enum fsl_phy_enet_if phyc);
 
 #endif /* __ASM_PPC_FSL_ENET_H */
diff --git a/board/freescale/mpc837xemds/mpc837xemds.c b/board/freescale/mpc837xemds/mpc837xemds.c
index 51dd692..1139cd8 100644
--- a/board/freescale/mpc837xemds/mpc837xemds.c
+++ b/board/freescale/mpc837xemds/mpc837xemds.c
@@ -21,6 +21,7 @@
 #include <libfdt.h>
 #include <fdt_support.h>
 #include <fsl_esdhc.h>
+#include <fsl_mdio.h>
 #include "pci.h"
 #include "../common/pq-mds-pib.h"
 
@@ -86,6 +87,7 @@ int board_mmc_init(bd_t *bd)
 #if defined(CONFIG_TSEC1) || defined(CONFIG_TSEC2)
 int board_eth_init(bd_t *bd)
 {
+	struct fsl_pq_mdio_info mdio_info;
 	struct tsec_info_struct tsec_info[2];
 	struct immap __iomem *im = (struct immap __iomem *)CONFIG_SYS_IMMR;
 	u32 rcwh = in_be32(&im->reset.rcwh);
@@ -131,6 +133,11 @@ int board_eth_init(bd_t *bd)
 	}
 	num++;
 #endif
+
+	mdio_info.regs = (tsec_mii_t *)CONFIG_SYS_MDIO_BASE_ADDR;
+	mdio_info.name = DEFAULT_MII_NAME;
+	fsl_pq_mdio_init(bd, &mdio_info);
+
 	return tsec_eth_init(bd, tsec_info, num);
 }
 
diff --git a/board/freescale/mpc8536ds/mpc8536ds.c b/board/freescale/mpc8536ds/mpc8536ds.c
index f83f629..da4912f 100644
--- a/board/freescale/mpc8536ds/mpc8536ds.c
+++ b/board/freescale/mpc8536ds/mpc8536ds.c
@@ -36,6 +36,7 @@
 #include <libfdt.h>
 #include <spd_sdram.h>
 #include <fdt_support.h>
+#include <fsl_mdio.h>
 #include <tsec.h>
 #include <netdev.h>
 #include <sata.h>
@@ -234,6 +235,7 @@ int board_early_init_r(void)
 int board_eth_init(bd_t *bis)
 {
 #ifdef CONFIG_TSEC_ENET
+	struct fsl_pq_mdio_info mdio_info;
 	struct tsec_info_struct tsec_info[2];
 	int num = 0;
 
@@ -268,6 +270,10 @@ int board_eth_init(bd_t *bis)
 	}
 #endif
 
+	mdio_info.regs = (tsec_mii_t *)CONFIG_SYS_MDIO_BASE_ADDR;
+	mdio_info.name = DEFAULT_MII_NAME;
+	fsl_pq_mdio_init(bis, &mdio_info);
+
 	tsec_eth_init(bis, tsec_info, num);
 #endif
 	return pci_eth_init(bis);
diff --git a/board/freescale/mpc8544ds/mpc8544ds.c b/board/freescale/mpc8544ds/mpc8544ds.c
index a48c815..798f8f7 100644
--- a/board/freescale/mpc8544ds/mpc8544ds.c
+++ b/board/freescale/mpc8544ds/mpc8544ds.c
@@ -33,6 +33,7 @@
 #include <miiphy.h>
 #include <libfdt.h>
 #include <fdt_support.h>
+#include <fsl_mdio.h>
 #include <tsec.h>
 #include <netdev.h>
 
@@ -248,9 +249,35 @@ get_board_sys_clk(ulong dummy)
 	return val;
 }
 
+
+#define MIIM_CIS8204_SLED_CON		0x1b
+#define MIIM_CIS8204_SLEDCON_INIT	0x1115
+/*
+ * Hack to write all 4 PHYs with the LED values
+ */
+int board_phy_config(struct phy_device *phydev)
+{
+	static int do_once;
+	uint phyid;
+	struct mii_dev *bus = phydev->bus;
+
+	if (do_once)
+		return 0;
+
+	for (phyid = 0; phyid < 4; phyid++)
+		bus->write(bus, phyid, MDIO_DEVAD_NONE, MIIM_CIS8204_SLED_CON,
+				MIIM_CIS8204_SLEDCON_INIT);
+
+	do_once = 1;
+
+	return 0;
+}
+
+
 int board_eth_init(bd_t *bis)
 {
 #ifdef CONFIG_TSEC_ENET
+	struct fsl_pq_mdio_info mdio_info;
 	struct tsec_info_struct tsec_info[2];
 	int num = 0;
 
@@ -282,6 +309,9 @@ int board_eth_init(bd_t *bis)
 		fsl_sgmii_riser_init(tsec_info, num);
 	}
 
+	mdio_info.regs = (tsec_mii_t *)CONFIG_SYS_MDIO_BASE_ADDR;
+	mdio_info.name = DEFAULT_MII_NAME;
+	fsl_pq_mdio_init(bis, &mdio_info);
 
 	tsec_eth_init(bis, tsec_info, num);
 #endif
diff --git a/board/freescale/mpc8572ds/mpc8572ds.c b/board/freescale/mpc8572ds/mpc8572ds.c
index f444805..2420c20 100644
--- a/board/freescale/mpc8572ds/mpc8572ds.c
+++ b/board/freescale/mpc8572ds/mpc8572ds.c
@@ -35,6 +35,7 @@
 #include <libfdt.h>
 #include <fdt_support.h>
 #include <tsec.h>
+#include <fsl_mdio.h>
 #include <netdev.h>
 
 #include "../common/sgmii_riser.h"
@@ -187,6 +188,7 @@ int board_early_init_r(void)
 #ifdef CONFIG_TSEC_ENET
 int board_eth_init(bd_t *bis)
 {
+	struct fsl_pq_mdio_info mdio_info;
 	struct tsec_info_struct tsec_info[4];
 	int num = 0;
 
@@ -233,6 +235,10 @@ int board_eth_init(bd_t *bis)
 	fsl_sgmii_riser_init(tsec_info, num);
 #endif
 
+	mdio_info.regs = (tsec_mii_t *)CONFIG_SYS_MDIO_BASE_ADDR;
+	mdio_info.name = DEFAULT_MII_NAME;
+	fsl_pq_mdio_init(bis, &mdio_info);
+
 	tsec_eth_init(bis, tsec_info, num);
 
 	return pci_eth_init(bis);
diff --git a/board/freescale/p1022ds/p1022ds.c b/board/freescale/p1022ds/p1022ds.c
index 6f20dc3..eda3372 100644
--- a/board/freescale/p1022ds/p1022ds.c
+++ b/board/freescale/p1022ds/p1022ds.c
@@ -22,6 +22,7 @@
 #include <asm/io.h>
 #include <libfdt.h>
 #include <fdt_support.h>
+#include <fsl_mdio.h>
 #include <tsec.h>
 #include <asm/fsl_law.h>
 #include <netdev.h>
@@ -245,6 +246,7 @@ int board_early_init_r(void)
  */
 int board_eth_init(bd_t *bis)
 {
+	struct fsl_pq_mdio_info mdio_info;
 	struct tsec_info_struct tsec_info[2];
 	unsigned int num = 0;
 
@@ -257,6 +259,10 @@ int board_eth_init(bd_t *bis)
 	num++;
 #endif
 
+	mdio_info.regs = (tsec_mii_t *)CONFIG_SYS_MDIO_BASE_ADDR;
+	mdio_info.name = DEFAULT_MII_NAME;
+	fsl_pq_mdio_init(bis, &mdio_info);
+
 	return tsec_eth_init(bis, tsec_info, num) + pci_eth_init(bis);
 }
 
diff --git a/board/freescale/p1_p2_rdb/p1_p2_rdb.c b/board/freescale/p1_p2_rdb/p1_p2_rdb.c
index 307c3e2..45d4d1a 100644
--- a/board/freescale/p1_p2_rdb/p1_p2_rdb.c
+++ b/board/freescale/p1_p2_rdb/p1_p2_rdb.c
@@ -31,6 +31,7 @@
 #include <miiphy.h>
 #include <libfdt.h>
 #include <fdt_support.h>
+#include <fsl_mdio.h>
 #include <tsec.h>
 #include <vsc7385.h>
 #include <netdev.h>
@@ -179,6 +180,7 @@ int board_early_init_r(void)
 #ifdef CONFIG_TSEC_ENET
 int board_eth_init(bd_t *bis)
 {
+	struct fsl_pq_mdio_info mdio_info;
 	struct tsec_info_struct tsec_info[4];
 	int num = 0;
 	char *tmp;
@@ -216,6 +218,10 @@ int board_eth_init(bd_t *bis)
 		puts("No address specified for VSC7385 microcode.\n");
 #endif
 
+	mdio_info.regs = (tsec_mii_t *)CONFIG_SYS_MDIO_BASE_ADDR;
+	mdio_info.name = DEFAULT_MII_NAME;
+	fsl_pq_mdio_init(bis, &mdio_info);
+
 	tsec_eth_init(bis, tsec_info, num);
 
 	return pci_eth_init(bis);
diff --git a/board/freescale/p2020ds/p2020ds.c b/board/freescale/p2020ds/p2020ds.c
index 238b4d9..9f4d595 100644
--- a/board/freescale/p2020ds/p2020ds.c
+++ b/board/freescale/p2020ds/p2020ds.c
@@ -34,6 +34,7 @@
 #include <miiphy.h>
 #include <libfdt.h>
 #include <fdt_support.h>
+#include <fsl_mdio.h>
 #include <tsec.h>
 #include <asm/fsl_law.h>
 #include <netdev.h>
@@ -201,6 +202,7 @@ int board_early_init_r(void)
 #ifdef CONFIG_TSEC_ENET
 int board_eth_init(bd_t *bis)
 {
+	struct fsl_pq_mdio_info mdio_info;
 	struct tsec_info_struct tsec_info[4];
 	int num = 0;
 
@@ -235,6 +237,11 @@ int board_eth_init(bd_t *bis)
 	fsl_sgmii_riser_init(tsec_info, num);
 #endif
 
+	mdio_info.regs = (tsec_mii_t *)CONFIG_SYS_MDIO_BASE_ADDR;
+	mdio_info.name = DEFAULT_MII_NAME;
+
+	fsl_pq_mdio_init(bis, &mdio_info);
+
 	tsec_eth_init(bis, tsec_info, num);
 
 	return pci_eth_init(bis);
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index fd9d0b4..819b197 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -79,7 +79,7 @@ COBJS-$(CONFIG_TIGON3) += tigon3.o
 COBJS-$(CONFIG_TIGON3) += bcm570x_autoneg.o
 COBJS-$(CONFIG_TIGON3) += 5701rls.o
 COBJS-$(CONFIG_DRIVER_TI_EMAC) += davinci_emac.o
-COBJS-$(CONFIG_TSEC_ENET) += tsec.o
+COBJS-$(CONFIG_TSEC_ENET) += tsec.o fsl_mdio.o
 COBJS-$(CONFIG_TSI108_ETH) += tsi108_eth.o
 COBJS-$(CONFIG_ULI526X) += uli526x.o
 COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o
diff --git a/drivers/net/fsl_mdio.c b/drivers/net/fsl_mdio.c
new file mode 100644
index 0000000..558a45e
--- /dev/null
+++ b/drivers/net/fsl_mdio.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *	Jun-jie Zhang <b18070@freescale.com>
+ *	Mingkai Hu <Mingkai.hu@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#include <common.h>
+#include <miiphy.h>
+#include <phy.h>
+#include <fsl_mdio.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+#include <asm/fsl_enet.h>
+
+void tsec_local_mdio_write(tsec_mii_t *phyregs, int port_addr,
+		int dev_addr, int regnum, int value)
+{
+	int timeout = 1000000;
+
+	out_be32(&phyregs->miimadd, (port_addr << 8) | (regnum & 0x1f));
+	out_be32(&phyregs->miimcon, value);
+	asm("sync");
+
+	while ((in_be32(&phyregs->miimind) & MIIMIND_BUSY) && timeout--)
+		;
+}
+
+int tsec_local_mdio_read(tsec_mii_t *phyregs, int port_addr,
+		int dev_addr, int regnum)
+{
+	int value;
+	int timeout = 1000000;
+
+	/* Put the address of the phy, and the register
+	 * number into MIIMADD */
+	out_be32(&phyregs->miimadd, (port_addr << 8) | (regnum & 0x1f));
+
+	/* Clear the command register, and wait */
+	out_be32(&phyregs->miimcom, 0);
+	asm("sync");
+
+	/* Initiate a read command, and wait */
+	out_be32(&phyregs->miimcom, MIIMCOM_READ_CYCLE);
+	asm("sync");
+
+	/* Wait for the the indication that the read is done */
+	while ((in_be32(&phyregs->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY))
+			&& timeout--)
+		;
+
+	/* Grab the value read from the PHY */
+	value = in_be32(&phyregs->miimstat);
+
+	return value;
+}
+
+static int fsl_pq_mdio_reset(struct mii_dev *bus)
+{
+	tsec_mii_t *regs = bus->priv;
+
+	/* Reset MII (due to new addresses) */
+	out_be32(&regs->miimcfg, MIIMCFG_RESET_MGMT);
+
+	out_be32(&regs->miimcfg, MIIMCFG_INIT_VALUE);
+
+	while (in_be32(&regs->miimind) & MIIMIND_BUSY)
+		;
+
+	return 0;
+}
+
+int tsec_phy_read(struct mii_dev *bus, int addr, int dev_addr, int regnum)
+{
+	tsec_mii_t *phyregs = bus->priv;
+
+	return tsec_local_mdio_read(phyregs, addr, dev_addr, regnum);
+}
+
+int tsec_phy_write(struct mii_dev *bus, int addr, int dev_addr, int regnum,
+			u16 value)
+{
+	tsec_mii_t *phyregs = bus->priv;
+
+	tsec_local_mdio_write(phyregs, addr, dev_addr, regnum, value);
+
+	return 0;
+}
+
+int fsl_pq_mdio_init(bd_t *bis, struct fsl_pq_mdio_info *info)
+{
+	struct mii_dev *bus = mdio_alloc();
+
+	if (!bus) {
+		printf("Failed to allocate FSL MDIO bus\n");
+		return -1;
+	}
+
+	bus->read = tsec_phy_read;
+	bus->write = tsec_phy_write;
+	bus->reset = fsl_pq_mdio_reset;
+	sprintf(bus->name, info->name);
+
+	bus->priv = info->regs;
+
+	return mdio_register(bus);
+}
diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c
index 1ee189d..1f00afd 100644
--- a/drivers/net/tsec.c
+++ b/drivers/net/tsec.c
@@ -17,10 +17,9 @@
 #include <net.h>
 #include <command.h>
 #include <tsec.h>
+#include <fsl_mdio.h>
 #include <asm/errno.h>
 
-#include "miiphy.h"
-
 DECLARE_GLOBAL_DATA_PTR;
 
 #define TX_BUF_CNT		2
@@ -56,10 +55,10 @@ static struct tsec_info_struct tsec_info[] = {
 #ifdef CONFIG_MPC85XX_FEC
 	{
 		.regs = (tsec_t *)(TSEC_BASE_ADDR + 0x2000),
-		.miiregs = (tsec_mdio_t *)(MDIO_BASE_ADDR),
 		.devname = CONFIG_MPC85XX_FEC_NAME,
 		.phyaddr = FEC_PHY_ADDR,
-		.flags = FEC_FLAGS
+		.flags = FEC_FLAGS,
+		.mii_devname = DEFAULT_MII_NAME
 	},			/* FEC */
 #endif
 #ifdef CONFIG_TSEC3
@@ -70,61 +69,6 @@ static struct tsec_info_struct tsec_info[] = {
 #endif
 };
 
-/* Writes the given phy's reg with value, using the specified MDIO regs */
-static void tsec_local_mdio_write(tsec_mdio_t *phyregs, uint addr,
-		uint reg, uint value)
-{
-	int timeout = 1000000;
-
-	out_be32(&phyregs->miimadd, (addr << 8) | reg);
-	out_be32(&phyregs->miimcon, value);
-	asm("sync");
-
-	timeout = 1000000;
-	while ((in_be32(&phyregs->miimind) & MIIMIND_BUSY) && timeout--)
-		;
-}
-
-/* Provide the default behavior of writing the PHY of this ethernet device */
-#define write_phy_reg(priv, regnum, value) \
-	tsec_local_mdio_write(priv->phyregs,priv->phyaddr,regnum,value)
-
-/* Reads register regnum on the device's PHY through the
- * specified registers.	 It lowers and raises the read
- * command, and waits for the data to become valid (miimind
- * notvalid bit cleared), and the bus to cease activity (miimind
- * busy bit cleared), and then returns the value
- */
-static uint tsec_local_mdio_read(tsec_mdio_t *phyregs, uint phyid, uint regnum)
-{
-	uint value;
-
-	/* Put the address of the phy, and the register
-	 * number into MIIMADD */
-	out_be32(&phyregs->miimadd, (phyid << 8) | regnum);
-
-	/* Clear the command register, and wait */
-	out_be32(&phyregs->miimcom, 0);
-	asm("sync");
-
-	/* Initiate a read command, and wait */
-	out_be32(&phyregs->miimcom, MIIM_READ_COMMAND);
-	asm("sync");
-
-	/* Wait for the the indication that the read is done */
-	while ((in_be32(&phyregs->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY)))
-		;
-
-	/* Grab the value read from the PHY */
-	value = in_be32(&phyregs->miimstat);
-
-	return value;
-}
-
-/* #define to provide old read_phy_reg functionality without duplicating code */
-#define read_phy_reg(priv,regnum) \
-	tsec_local_mdio_read(priv->phyregs,priv->phyaddr,regnum)
-
 #define TBIANA_SETTINGS ( \
 		TBIANA_ASYMMETRIC_PAUSE \
 		| TBIANA_SYMMETRIC_PAUSE \
@@ -146,1408 +90,14 @@ static void tsec_configure_serdes(struct tsec_private *priv)
 {
 	/* Access TBI PHY registers at given TSEC register offset as opposed
 	 * to the register offset used for external PHY accesses */
-	tsec_local_mdio_write(priv->phyregs_sgmii, priv->regs->tbipa, TBI_ANA,
-			TBIANA_SETTINGS);
-	tsec_local_mdio_write(priv->phyregs_sgmii, priv->regs->tbipa, TBI_TBICON,
-			TBICON_CLK_SELECT);
-	tsec_local_mdio_write(priv->phyregs_sgmii, priv->regs->tbipa, TBI_CR,
-			CONFIG_TSEC_TBICR_SETTINGS);
-}
-
-/*
- * Returns which value to write to the control register.
- * For 10/100, the value is slightly different
- */
-static uint mii_cr_init(uint mii_reg, struct tsec_private * priv)
-{
-	if (priv->flags & TSEC_GIGABIT)
-		return MIIM_CONTROL_INIT;
-	else
-		return MIIM_CR_INIT;
-}
-
-/*
- * Wait for auto-negotiation to complete, then determine link
- */
-static uint mii_parse_sr(uint mii_reg, struct tsec_private * priv)
-{
-	/*
-	 * Wait if the link is up, and autonegotiation is in progress
-	 * (ie - we're capable and it's not done)
-	 */
-	mii_reg = read_phy_reg(priv, MIIM_STATUS);
-	if ((mii_reg & BMSR_ANEGCAPABLE) && !(mii_reg & BMSR_ANEGCOMPLETE)) {
-		int i = 0;
-
-		puts("Waiting for PHY auto negotiation to complete");
-		while (!(mii_reg & BMSR_ANEGCOMPLETE)) {
-			/*
-			 * Timeout reached ?
-			 */
-			if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
-				puts(" TIMEOUT !\n");
-				priv->link = 0;
-				return 0;
-			}
-
-			if (ctrlc()) {
-				puts("user interrupt!\n");
-				priv->link = 0;
-				return -EINTR;
-			}
-
-			if ((i++ % 1000) == 0) {
-				putc('.');
-			}
-			udelay(1000);	/* 1 ms */
-			mii_reg = read_phy_reg(priv, MIIM_STATUS);
-		}
-		puts(" done\n");
-
-		/* Link status bit is latched low, read it again */
-		mii_reg = read_phy_reg(priv, MIIM_STATUS);
-
-		udelay(500000);	/* another 500 ms (results in faster booting) */
-	}
-
-	priv->link = mii_reg & MIIM_STATUS_LINK ? 1 : 0;
-
-	return 0;
-}
-
-/* Generic function which updates the speed and duplex.  If
- * autonegotiation is enabled, it uses the AND of the link
- * partner's advertised capabilities and our advertised
- * capabilities.  If autonegotiation is disabled, we use the
- * appropriate bits in the control register.
- *
- * Stolen from Linux's mii.c and phy_device.c
- */
-static uint mii_parse_link(uint mii_reg, struct tsec_private *priv)
-{
-	/* We're using autonegotiation */
-	if (mii_reg & BMSR_ANEGCAPABLE) {
-		uint lpa = 0;
-		uint gblpa = 0;
-
-		/* Check for gigabit capability */
-		if (mii_reg & BMSR_ERCAP) {
-			/* We want a list of states supported by
-			 * both PHYs in the link
-			 */
-			gblpa = read_phy_reg(priv, MII_STAT1000);
-			gblpa &= read_phy_reg(priv, MII_CTRL1000) << 2;
-		}
-
-		/* Set the baseline so we only have to set them
-		 * if they're different
-		 */
-		priv->speed = 10;
-		priv->duplexity = 0;
-
-		/* Check the gigabit fields */
-		if (gblpa & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)) {
-			priv->speed = 1000;
-
-			if (gblpa & PHY_1000BTSR_1000FD)
-				priv->duplexity = 1;
-
-			/* We're done! */
-			return 0;
-		}
-
-		lpa = read_phy_reg(priv, MII_ADVERTISE);
-		lpa &= read_phy_reg(priv, MII_LPA);
-
-		if (lpa & (LPA_100FULL | LPA_100HALF)) {
-			priv->speed = 100;
-
-			if (lpa & LPA_100FULL)
-				priv->duplexity = 1;
-
-		} else if (lpa & LPA_10FULL)
-			priv->duplexity = 1;
-	} else {
-		uint bmcr = read_phy_reg(priv, MII_BMCR);
-
-		priv->speed = 10;
-		priv->duplexity = 0;
-
-		if (bmcr & BMCR_FULLDPLX)
-			priv->duplexity = 1;
-
-		if (bmcr & BMCR_SPEED1000)
-			priv->speed = 1000;
-		else if (bmcr & BMCR_SPEED100)
-			priv->speed = 100;
-	}
-
-	return 0;
-}
-
-/*
- * "Ethernet at Wirespeed" needs to be enabled to achieve link in certain
- * circumstances.  eg a gigabit TSEC connected to a gigabit switch with
- * a 4-wire ethernet cable.  Both ends advertise gigabit, but can't
- * link.  "Ethernet at Wirespeed" reduces advertised speed until link
- * can be achieved.
- */
-static uint mii_BCM54xx_wirespeed(uint mii_reg, struct tsec_private *priv)
-{
-	return (read_phy_reg(priv, mii_reg) & 0x8FFF) | 0x8010;
-}
-
-/*
- * Parse the BCM54xx status register for speed and duplex information.
- * The linux sungem_phy has this information, but in a table format.
- */
-static uint mii_parse_BCM54xx_sr(uint mii_reg, struct tsec_private *priv)
-{
-	/* If there is no link, speed and duplex don't matter */
-	if (!priv->link)
-		return 0;
-
-	switch ((mii_reg & MIIM_BCM54xx_AUXSTATUS_LINKMODE_MASK) >>
-		MIIM_BCM54xx_AUXSTATUS_LINKMODE_SHIFT) {
-	case 1:
-		priv->duplexity = 0;
-		priv->speed = 10;
-		break;
-	case 2:
-		priv->duplexity = 1;
-		priv->speed = 10;
-		break;
-	case 3:
-		priv->duplexity = 0;
-		priv->speed = 100;
-		break;
-	case 5:
-		priv->duplexity = 1;
-		priv->speed = 100;
-		break;
-	case 6:
-		priv->duplexity = 0;
-		priv->speed = 1000;
-		break;
-	case 7:
-		priv->duplexity = 1;
-		priv->speed = 1000;
-		break;
-	default:
-		printf("Auto-neg error, defaulting to 10BT/HD\n");
-		priv->duplexity = 0;
-		priv->speed = 10;
-		break;
-	}
-
-	return 0;
-}
-
-/*
- * Find out if PHY is in copper or serdes mode by looking at Expansion Reg
- * 0x42 - "Operating Mode Status Register"
- */
-static int BCM8482_is_serdes(struct tsec_private *priv)
-{
-	u16 val;
-	int serdes = 0;
-
-	write_phy_reg(priv, MIIM_BCM54XX_EXP_SEL, MIIM_BCM54XX_EXP_SEL_ER | 0x42);
-	val = read_phy_reg(priv, MIIM_BCM54XX_EXP_DATA);
-
-	switch (val & 0x1f) {
-	case 0x0d:	/* RGMII-to-100Base-FX */
-	case 0x0e:	/* RGMII-to-SGMII */
-	case 0x0f:	/* RGMII-to-SerDes */
-	case 0x12:	/* SGMII-to-SerDes */
-	case 0x13:	/* SGMII-to-100Base-FX */
-	case 0x16:	/* SerDes-to-Serdes */
-		serdes = 1;
-		break;
-	case 0x6:	/* RGMII-to-Copper */
-	case 0x14:	/* SGMII-to-Copper */
-	case 0x17:	/* SerDes-to-Copper */
-		break;
-	default:
-		printf("ERROR, invalid PHY mode (0x%x\n)", val);
-		break;
-	}
-
-	return serdes;
-}
-
-/*
- * Determine SerDes link speed and duplex from Expansion reg 0x42 "Operating
- * Mode Status Register"
- */
-uint mii_parse_BCM5482_serdes_sr(struct tsec_private *priv)
-{
-	u16 val;
-	int i = 0;
-
-	/* Wait 1s for link - Clause 37 autonegotiation happens very fast */
-	while (1) {
-		write_phy_reg(priv, MIIM_BCM54XX_EXP_SEL,
-				MIIM_BCM54XX_EXP_SEL_ER | 0x42);
-		val = read_phy_reg(priv, MIIM_BCM54XX_EXP_DATA);
-
-		if (val & 0x8000)
-			break;
-
-		if (i++ > 1000) {
-			priv->link = 0;
-			return 1;
-		}
-
-		udelay(1000);	/* 1 ms */
-	}
-
-	priv->link = 1;
-	switch ((val >> 13) & 0x3) {
-	case (0x00):
-		priv->speed = 10;
-		break;
-	case (0x01):
-		priv->speed = 100;
-		break;
-	case (0x02):
-		priv->speed = 1000;
-		break;
-	}
-
-	priv->duplexity = (val & 0x1000) == 0x1000;
-
-	return 0;
-}
-
-/*
- * Figure out if BCM5482 is in serdes or copper mode and determine link
- * configuration accordingly
- */
-static uint mii_parse_BCM5482_sr(uint mii_reg, struct tsec_private *priv)
-{
-	if (BCM8482_is_serdes(priv)) {
-		mii_parse_BCM5482_serdes_sr(priv);
-		priv->flags |= TSEC_FIBER;
-	} else {
-		/* Wait for auto-negotiation to complete or fail */
-		mii_parse_sr(mii_reg, priv);
-
-		/* Parse BCM54xx copper aux status register */
-		mii_reg = read_phy_reg(priv, MIIM_BCM54xx_AUXSTATUS);
-		mii_parse_BCM54xx_sr(mii_reg, priv);
-	}
-
-	return 0;
-}
-
-/* Parse the 88E1011's status register for speed and duplex
- * information
- */
-static uint mii_parse_88E1011_psr(uint mii_reg, struct tsec_private * priv)
-{
-	uint speed;
-
-	mii_reg = read_phy_reg(priv, MIIM_88E1011_PHY_STATUS);
-
-	if ((mii_reg & MIIM_88E1011_PHYSTAT_LINK) &&
-		!(mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE)) {
-		int i = 0;
-
-		puts("Waiting for PHY realtime link");
-		while (!(mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE)) {
-			/* Timeout reached ? */
-			if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
-				puts(" TIMEOUT !\n");
-				priv->link = 0;
-				break;
-			}
-
-			if ((i++ % 1000) == 0) {
-				putc('.');
-			}
-			udelay(1000);	/* 1 ms */
-			mii_reg = read_phy_reg(priv, MIIM_88E1011_PHY_STATUS);
-		}
-		puts(" done\n");
-		udelay(500000);	/* another 500 ms (results in faster booting) */
-	} else {
-		if (mii_reg & MIIM_88E1011_PHYSTAT_LINK)
-			priv->link = 1;
-		else
-			priv->link = 0;
-	}
-
-	if (mii_reg & MIIM_88E1011_PHYSTAT_DUPLEX)
-		priv->duplexity = 1;
-	else
-		priv->duplexity = 0;
-
-	speed = (mii_reg & MIIM_88E1011_PHYSTAT_SPEED);
-
-	switch (speed) {
-	case MIIM_88E1011_PHYSTAT_GBIT:
-		priv->speed = 1000;
-		break;
-	case MIIM_88E1011_PHYSTAT_100:
-		priv->speed = 100;
-		break;
-	default:
-		priv->speed = 10;
-	}
-
-	return 0;
-}
-
-/* Parse the RTL8211B's status register for speed and duplex
- * information
- */
-static uint mii_parse_RTL8211B_sr(uint mii_reg, struct tsec_private * priv)
-{
-	uint speed;
-
-	mii_reg = read_phy_reg(priv, MIIM_RTL8211B_PHY_STATUS);
-	if (!(mii_reg & MIIM_RTL8211B_PHYSTAT_SPDDONE)) {
-		int i = 0;
-
-		/* in case of timeout ->link is cleared */
-		priv->link = 1;
-		puts("Waiting for PHY realtime link");
-		while (!(mii_reg & MIIM_RTL8211B_PHYSTAT_SPDDONE)) {
-			/* Timeout reached ? */
-			if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
-				puts(" TIMEOUT !\n");
-				priv->link = 0;
-				break;
-			}
-
-			if ((i++ % 1000) == 0) {
-				putc('.');
-			}
-			udelay(1000);	/* 1 ms */
-			mii_reg = read_phy_reg(priv, MIIM_RTL8211B_PHY_STATUS);
-		}
-		puts(" done\n");
-		udelay(500000);	/* another 500 ms (results in faster booting) */
-	} else {
-		if (mii_reg & MIIM_RTL8211B_PHYSTAT_LINK)
-			priv->link = 1;
-		else
-			priv->link = 0;
-	}
-
-	if (mii_reg & MIIM_RTL8211B_PHYSTAT_DUPLEX)
-		priv->duplexity = 1;
-	else
-		priv->duplexity = 0;
-
-	speed = (mii_reg & MIIM_RTL8211B_PHYSTAT_SPEED);
-
-	switch (speed) {
-	case MIIM_RTL8211B_PHYSTAT_GBIT:
-		priv->speed = 1000;
-		break;
-	case MIIM_RTL8211B_PHYSTAT_100:
-		priv->speed = 100;
-		break;
-	default:
-		priv->speed = 10;
-	}
-
-	return 0;
-}
-
-/* Parse the cis8201's status register for speed and duplex
- * information
- */
-static uint mii_parse_cis8201(uint mii_reg, struct tsec_private * priv)
-{
-	uint speed;
-
-	if (mii_reg & MIIM_CIS8201_AUXCONSTAT_DUPLEX)
-		priv->duplexity = 1;
-	else
-		priv->duplexity = 0;
-
-	speed = mii_reg & MIIM_CIS8201_AUXCONSTAT_SPEED;
-	switch (speed) {
-	case MIIM_CIS8201_AUXCONSTAT_GBIT:
-		priv->speed = 1000;
-		break;
-	case MIIM_CIS8201_AUXCONSTAT_100:
-		priv->speed = 100;
-		break;
-	default:
-		priv->speed = 10;
-		break;
-	}
-
-	return 0;
-}
-
-/* Parse the vsc8244's status register for speed and duplex
- * information
- */
-static uint mii_parse_vsc8244(uint mii_reg, struct tsec_private * priv)
-{
-	uint speed;
-
-	if (mii_reg & MIIM_VSC8244_AUXCONSTAT_DUPLEX)
-		priv->duplexity = 1;
-	else
-		priv->duplexity = 0;
-
-	speed = mii_reg & MIIM_VSC8244_AUXCONSTAT_SPEED;
-	switch (speed) {
-	case MIIM_VSC8244_AUXCONSTAT_GBIT:
-		priv->speed = 1000;
-		break;
-	case MIIM_VSC8244_AUXCONSTAT_100:
-		priv->speed = 100;
-		break;
-	default:
-		priv->speed = 10;
-		break;
-	}
-
-	return 0;
-}
-
-/* Parse the DM9161's status register for speed and duplex
- * information
- */
-static uint mii_parse_dm9161_scsr(uint mii_reg, struct tsec_private * priv)
-{
-	if (mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_100H))
-		priv->speed = 100;
-	else
-		priv->speed = 10;
-
-	if (mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_10F))
-		priv->duplexity = 1;
-	else
-		priv->duplexity = 0;
-
-	return 0;
-}
-
-/*
- * Hack to write all 4 PHYs with the LED values
- */
-static uint mii_cis8204_fixled(uint mii_reg, struct tsec_private * priv)
-{
-	uint phyid;
-	tsec_mdio_t *regbase = priv->phyregs;
-	int timeout = 1000000;
-
-	for (phyid = 0; phyid < 4; phyid++) {
-		out_be32(&regbase->miimadd, (phyid << 8) | mii_reg);
-		out_be32(&regbase->miimcon, MIIM_CIS8204_SLEDCON_INIT);
-		asm("sync");
-
-		timeout = 1000000;
-		while ((in_be32(&regbase->miimind) & MIIMIND_BUSY) && timeout--)
-			;
-	}
-
-	return MIIM_CIS8204_SLEDCON_INIT;
-}
-
-static uint mii_cis8204_setmode(uint mii_reg, struct tsec_private * priv)
-{
-	if (priv->flags & TSEC_REDUCED)
-		return MIIM_CIS8204_EPHYCON_INIT | MIIM_CIS8204_EPHYCON_RGMII;
-	else
-		return MIIM_CIS8204_EPHYCON_INIT;
-}
-
-static uint mii_m88e1111s_setmode(uint mii_reg, struct tsec_private *priv)
-{
-	uint mii_data = read_phy_reg(priv, mii_reg);
-
-	if (priv->flags & TSEC_REDUCED)
-		mii_data = (mii_data & 0xfff0) | 0x000b;
-	return mii_data;
-}
-
-static struct phy_info phy_info_M88E1149S = {
-	0x1410ca,
-	"Marvell 88E1149S",
-	4,
-	(struct phy_cmd[]) {     /* config */
-		/* Reset and configure the PHY */
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{0x1d, 0x1f, NULL},
-		{0x1e, 0x200c, NULL},
-		{0x1d, 0x5, NULL},
-		{0x1e, 0x0, NULL},
-		{0x1e, 0x100, NULL},
-		{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
-		{MIIM_ANAR, MIIM_ANAR_INIT, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {     /* startup */
-		/* Status is read once to clear old link state */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the status */
-		{MIIM_88E1011_PHY_STATUS, miim_read, &mii_parse_88E1011_psr},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {     /* shutdown */
-		{miim_end,}
-	},
-};
-
-/* The 5411 id is 0x206070, the 5421 is 0x2060e0 */
-static struct phy_info phy_info_BCM5461S = {
-	0x02060c1,	/* 5461 ID */
-	"Broadcom BCM5461S",
-	0, /* not clear to me what minor revisions we can shift away */
-	(struct phy_cmd[]) { /* config */
-		/* Reset and configure the PHY */
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
-		{MIIM_ANAR, MIIM_ANAR_INIT, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) { /* startup */
-		/* Status is read once to clear old link state */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the status */
-		{MIIM_BCM54xx_AUXSTATUS, miim_read, &mii_parse_BCM54xx_sr},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) { /* shutdown */
-		{miim_end,}
-	},
-};
-
-static struct phy_info phy_info_BCM5464S = {
-	0x02060b1,	/* 5464 ID */
-	"Broadcom BCM5464S",
-	0, /* not clear to me what minor revisions we can shift away */
-	(struct phy_cmd[]) { /* config */
-		/* Reset and configure the PHY */
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
-		{MIIM_ANAR, MIIM_ANAR_INIT, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) { /* startup */
-		/* Status is read once to clear old link state */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the status */
-		{MIIM_BCM54xx_AUXSTATUS, miim_read, &mii_parse_BCM54xx_sr},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) { /* shutdown */
-		{miim_end,}
-	},
-};
-
-static struct phy_info phy_info_BCM5482S =  {
-	0x0143bcb,
-	"Broadcom BCM5482S",
-	4,
-	(struct phy_cmd[]) { /* config */
-		/* Reset and configure the PHY */
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		/* Setup read from auxilary control shadow register 7 */
-		{MIIM_BCM54xx_AUXCNTL, MIIM_BCM54xx_AUXCNTL_ENCODE(7), NULL},
-		/* Read Misc Control register and or in Ethernet at Wirespeed */
-		{MIIM_BCM54xx_AUXCNTL, 0, &mii_BCM54xx_wirespeed},
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-		/* Initial config/enable of secondary SerDes interface */
-		{MIIM_BCM54XX_SHD, MIIM_BCM54XX_SHD_WR_ENCODE(0x14, 0xf), NULL},
-		/* Write intial value to secondary SerDes Contol */
-		{MIIM_BCM54XX_EXP_SEL, MIIM_BCM54XX_EXP_SEL_SSD | 0, NULL},
-		{MIIM_BCM54XX_EXP_DATA, MIIM_CONTROL_RESTART, NULL},
-		/* Enable copper/fiber auto-detect */
-		{MIIM_BCM54XX_SHD, MIIM_BCM54XX_SHD_WR_ENCODE(0x1e, 0x201)},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) { /* startup */
-		/* Status is read once to clear old link state */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Determine copper/fiber, auto-negotiate, and read the result */
-		{MIIM_STATUS, miim_read, &mii_parse_BCM5482_sr},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) { /* shutdown */
-		{miim_end,}
-	},
-};
-
-static struct phy_info phy_info_M88E1011S = {
-	0x01410c6,
-	"Marvell 88E1011S",
-	4,
-	(struct phy_cmd[]) {	/* config */
-		/* Reset and configure the PHY */
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{0x1d, 0x1f, NULL},
-		{0x1e, 0x200c, NULL},
-		{0x1d, 0x5, NULL},
-		{0x1e, 0x0, NULL},
-		{0x1e, 0x100, NULL},
-		{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
-		{MIIM_ANAR, MIIM_ANAR_INIT, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* startup */
-		/* Status is read once to clear old link state */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the status */
-		{MIIM_88E1011_PHY_STATUS, miim_read, &mii_parse_88E1011_psr},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* shutdown */
-		{miim_end,}
-	},
-};
-
-static struct phy_info phy_info_M88E1111S = {
-	0x01410cc,
-	"Marvell 88E1111S",
-	4,
-	(struct phy_cmd[]) {	/* config */
-		/* Reset and configure the PHY */
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{0x1b, 0x848f, &mii_m88e1111s_setmode},
-		{0x14, 0x0cd2, NULL}, /* Delay RGMII TX and RX */
-		{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
-		{MIIM_ANAR, MIIM_ANAR_INIT, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* startup */
-		/* Status is read once to clear old link state */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the status */
-		{MIIM_88E1011_PHY_STATUS, miim_read, &mii_parse_88E1011_psr},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* shutdown */
-		{miim_end,}
-	},
-};
-
-static struct phy_info phy_info_M88E1118 = {
-	0x01410e1,
-	"Marvell 88E1118",
-	4,
-	(struct phy_cmd[]) {	/* config */
-		/* Reset and configure the PHY */
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{0x16, 0x0002, NULL}, /* Change Page Number */
-		{0x15, 0x1070, NULL}, /* Delay RGMII TX and RX */
-		{0x16, 0x0003, NULL}, /* Change Page Number */
-		{0x10, 0x021e, NULL}, /* Adjust LED control */
-		{0x16, 0x0000, NULL}, /* Change Page Number */
-		{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
-		{MIIM_ANAR, MIIM_ANAR_INIT, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* startup */
-		{0x16, 0x0000, NULL}, /* Change Page Number */
-		/* Status is read once to clear old link state */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the status */
-		{MIIM_88E1011_PHY_STATUS, miim_read,
-		 &mii_parse_88E1011_psr},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* shutdown */
-		{miim_end,}
-	},
-};
-
-/*
- *  Since to access LED register we need do switch the page, we
- * do LED configuring in the miim_read-like function as follows
- */
-static uint mii_88E1121_set_led (uint mii_reg, struct tsec_private *priv)
-{
-	uint pg;
-
-	/* Switch the page to access the led register */
-	pg = read_phy_reg(priv, MIIM_88E1121_PHY_PAGE);
-	write_phy_reg(priv, MIIM_88E1121_PHY_PAGE, MIIM_88E1121_PHY_LED_PAGE);
-
-	/* Configure leds */
-	write_phy_reg(priv, MIIM_88E1121_PHY_LED_CTRL,
-		      MIIM_88E1121_PHY_LED_DEF);
-
-	/* Restore the page pointer */
-	write_phy_reg(priv, MIIM_88E1121_PHY_PAGE, pg);
-	return 0;
-}
-
-static struct phy_info phy_info_M88E1121R = {
-	0x01410cb,
-	"Marvell 88E1121R",
-	4,
-	(struct phy_cmd[]) {	/* config */
-		/* Reset and configure the PHY */
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
-		{MIIM_ANAR, MIIM_ANAR_INIT, NULL},
-		/* Configure leds */
-		{MIIM_88E1121_PHY_LED_CTRL, miim_read, &mii_88E1121_set_led},
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-		/* Disable IRQs and de-assert interrupt */
-		{MIIM_88E1121_PHY_IRQ_EN, 0, NULL},
-		{MIIM_88E1121_PHY_IRQ_STATUS, miim_read, NULL},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* startup */
-		/* Status is read once to clear old link state */
-		{MIIM_STATUS, miim_read, NULL},
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		{MIIM_STATUS, miim_read, &mii_parse_link},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* shutdown */
-		{miim_end,}
-	},
-};
-
-static unsigned int m88e1145_setmode(uint mii_reg, struct tsec_private *priv)
-{
-	uint mii_data = read_phy_reg(priv, mii_reg);
-
-	/* Setting MIIM_88E1145_PHY_EXT_CR */
-	if (priv->flags & TSEC_REDUCED)
-		return mii_data |
-		    MIIM_M88E1145_RGMII_RX_DELAY | MIIM_M88E1145_RGMII_TX_DELAY;
-	else
-		return mii_data;
-}
-
-static struct phy_info phy_info_M88E1145 = {
-	0x01410cd,
-	"Marvell 88E1145",
-	4,
-	(struct phy_cmd[]) {	/* config */
-		/* Reset the PHY */
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-
-		/* Errata E0, E1 */
-		{29, 0x001b, NULL},
-		{30, 0x418f, NULL},
-		{29, 0x0016, NULL},
-		{30, 0xa2da, NULL},
-
-		/* Configure the PHY */
-		{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
-		{MIIM_ANAR, MIIM_ANAR_INIT, NULL},
-		{MIIM_88E1011_PHY_SCR, MIIM_88E1011_PHY_MDI_X_AUTO, NULL},
-		{MIIM_88E1145_PHY_EXT_CR, 0, &m88e1145_setmode},
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, NULL},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* startup */
-		/* Status is read once to clear old link state */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		{MIIM_88E1111_PHY_LED_CONTROL, MIIM_88E1111_PHY_LED_DIRECT, NULL},
-		/* Read the Status */
-		{MIIM_88E1011_PHY_STATUS, miim_read, &mii_parse_88E1011_psr},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* shutdown */
-		{miim_end,}
-	},
-};
-
-static struct phy_info phy_info_cis8204 = {
-	0x3f11,
-	"Cicada Cis8204",
-	6,
-	(struct phy_cmd[]) {	/* config */
-		/* Override PHY config settings */
-		{MIIM_CIS8201_AUX_CONSTAT, MIIM_CIS8201_AUXCONSTAT_INIT, NULL},
-		/* Configure some basic stuff */
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-		{MIIM_CIS8204_SLED_CON, MIIM_CIS8204_SLEDCON_INIT,
-		 &mii_cis8204_fixled},
-		{MIIM_CIS8204_EPHY_CON, MIIM_CIS8204_EPHYCON_INIT,
-		 &mii_cis8204_setmode},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* startup */
-		/* Read the Status (2x to make sure link is right) */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the status */
-		{MIIM_CIS8201_AUX_CONSTAT, miim_read, &mii_parse_cis8201},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* shutdown */
-		{miim_end,}
-	},
-};
-
-/* Cicada 8201 */
-static struct phy_info phy_info_cis8201 = {
-	0xfc41,
-	"CIS8201",
-	4,
-	(struct phy_cmd[]) {	/* config */
-		/* Override PHY config settings */
-		{MIIM_CIS8201_AUX_CONSTAT, MIIM_CIS8201_AUXCONSTAT_INIT, NULL},
-		/* Set up the interface mode */
-		{MIIM_CIS8201_EXT_CON1, MIIM_CIS8201_EXTCON1_INIT, NULL},
-		/* Configure some basic stuff */
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* startup */
-		/* Read the Status (2x to make sure link is right) */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the status */
-		{MIIM_CIS8201_AUX_CONSTAT, miim_read, &mii_parse_cis8201},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* shutdown */
-		{miim_end,}
-	},
-};
-
-static struct phy_info phy_info_VSC8211 = {
-	0xfc4b,
-	"Vitesse VSC8211",
-	4,
-	(struct phy_cmd[]) { /* config */
-		/* Override PHY config settings */
-		{MIIM_CIS8201_AUX_CONSTAT, MIIM_CIS8201_AUXCONSTAT_INIT, NULL},
-		/* Set up the interface mode */
-		{MIIM_CIS8201_EXT_CON1, MIIM_CIS8201_EXTCON1_INIT, NULL},
-		/* Configure some basic stuff */
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) { /* startup */
-		/* Read the Status (2x to make sure link is right) */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the status */
-		{MIIM_CIS8201_AUX_CONSTAT, miim_read, &mii_parse_cis8201},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) { /* shutdown */
-		{miim_end,}
-	},
-};
-
-static struct phy_info phy_info_VSC8244 = {
-	0x3f1b,
-	"Vitesse VSC8244",
-	6,
-	(struct phy_cmd[]) {	/* config */
-		/* Override PHY config settings */
-		/* Configure some basic stuff */
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* startup */
-		/* Read the Status (2x to make sure link is right) */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the status */
-		{MIIM_VSC8244_AUX_CONSTAT, miim_read, &mii_parse_vsc8244},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* shutdown */
-		{miim_end,}
-	},
-};
-
-static struct phy_info phy_info_VSC8641 = {
-	0x7043,
-	"Vitesse VSC8641",
-	4,
-	(struct phy_cmd[]) {	/* config */
-		/* Configure some basic stuff */
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* startup */
-		/* Read the Status (2x to make sure link is right) */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the status */
-		{MIIM_VSC8244_AUX_CONSTAT, miim_read, &mii_parse_vsc8244},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* shutdown */
-		{miim_end,}
-	},
-};
-
-static struct phy_info phy_info_VSC8221 = {
-	0xfc55,
-	"Vitesse VSC8221",
-	4,
-	(struct phy_cmd[]) {	/* config */
-		/* Configure some basic stuff */
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* startup */
-		/* Read the Status (2x to make sure link is right) */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the status */
-		{MIIM_VSC8244_AUX_CONSTAT, miim_read, &mii_parse_vsc8244},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* shutdown */
-		{miim_end,}
-	},
-};
-
-static struct phy_info phy_info_VSC8601 = {
-	0x00007042,
-	"Vitesse VSC8601",
-	4,
-	(struct phy_cmd[]) {     /* config */
-		/* Override PHY config settings */
-		/* Configure some basic stuff */
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-#ifdef CONFIG_SYS_VSC8601_SKEWFIX
-		{MIIM_VSC8601_EPHY_CON,MIIM_VSC8601_EPHY_CON_INIT_SKEW,NULL},
-#if defined(CONFIG_SYS_VSC8601_SKEW_TX) && defined(CONFIG_SYS_VSC8601_SKEW_RX)
-		{MIIM_EXT_PAGE_ACCESS,1,NULL},
-#define VSC8101_SKEW \
-	(CONFIG_SYS_VSC8601_SKEW_TX << 14) | (CONFIG_SYS_VSC8601_SKEW_RX << 12)
-		{MIIM_VSC8601_SKEW_CTRL,VSC8101_SKEW,NULL},
-		{MIIM_EXT_PAGE_ACCESS,0,NULL},
-#endif
-#endif
-		{MIIM_ANAR, MIIM_ANAR_INIT, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_RESTART, &mii_cr_init},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {     /* startup */
-		/* Read the Status (2x to make sure link is right) */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the status */
-		{MIIM_VSC8244_AUX_CONSTAT, miim_read, &mii_parse_vsc8244},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {     /* shutdown */
-		{miim_end,}
-	},
-};
-
-static struct phy_info phy_info_dm9161 = {
-	0x0181b88,
-	"Davicom DM9161E",
-	4,
-	(struct phy_cmd[]) {	/* config */
-		{MIIM_CONTROL, MIIM_DM9161_CR_STOP, NULL},
-		/* Do not bypass the scrambler/descrambler */
-		{MIIM_DM9161_SCR, MIIM_DM9161_SCR_INIT, NULL},
-		/* Clear 10BTCSR to default */
-		{MIIM_DM9161_10BTCSR, MIIM_DM9161_10BTCSR_INIT, NULL},
-		/* Configure some basic stuff */
-		{MIIM_CONTROL, MIIM_CR_INIT, NULL},
-		/* Restart Auto Negotiation */
-		{MIIM_CONTROL, MIIM_DM9161_CR_RSTAN, NULL},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* startup */
-		/* Status is read once to clear old link state */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the status */
-		{MIIM_DM9161_SCSR, miim_read, &mii_parse_dm9161_scsr},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* shutdown */
-		{miim_end,}
-	},
-};
-
-/* micrel KSZ804  */
-static struct phy_info phy_info_ksz804 =  {
-	0x0022151,
-	"Micrel KSZ804 PHY",
-	4,
-	(struct phy_cmd[]) { /* config */
-		{MII_BMCR, BMCR_RESET, NULL},
-		{MII_BMCR, BMCR_ANENABLE|BMCR_ANRESTART, NULL},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) { /* startup */
-		{MII_BMSR, miim_read, NULL},
-		{MII_BMSR, miim_read, &mii_parse_sr},
-		{MII_BMSR, miim_read, &mii_parse_link},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) { /* shutdown */
-		{miim_end,}
-	}
-};
-
-/* a generic flavor.  */
-static struct phy_info phy_info_generic =  {
-	0,
-	"Unknown/Generic PHY",
-	32,
-	(struct phy_cmd[]) { /* config */
-		{MII_BMCR, BMCR_RESET, NULL},
-		{MII_BMCR, BMCR_ANENABLE|BMCR_ANRESTART, NULL},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) { /* startup */
-		{MII_BMSR, miim_read, NULL},
-		{MII_BMSR, miim_read, &mii_parse_sr},
-		{MII_BMSR, miim_read, &mii_parse_link},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) { /* shutdown */
-		{miim_end,}
-	}
-};
-
-static uint mii_parse_lxt971_sr2(uint mii_reg, struct tsec_private *priv)
-{
-	unsigned int speed;
-	if (priv->link) {
-		speed = mii_reg & MIIM_LXT971_SR2_SPEED_MASK;
-
-		switch (speed) {
-		case MIIM_LXT971_SR2_10HDX:
-			priv->speed = 10;
-			priv->duplexity = 0;
-			break;
-		case MIIM_LXT971_SR2_10FDX:
-			priv->speed = 10;
-			priv->duplexity = 1;
-			break;
-		case MIIM_LXT971_SR2_100HDX:
-			priv->speed = 100;
-			priv->duplexity = 0;
-			break;
-		default:
-			priv->speed = 100;
-			priv->duplexity = 1;
-		}
-	} else {
-		priv->speed = 0;
-		priv->duplexity = 0;
-	}
-
-	return 0;
-}
-
-static struct phy_info phy_info_lxt971 = {
-	0x0001378e,
-	"LXT971",
-	4,
-	(struct phy_cmd[]) {	/* config */
-		{MIIM_CR, MIIM_CR_INIT, mii_cr_init},	/* autonegotiate */
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* startup - enable interrupts */
-		/* { 0x12, 0x00f2, NULL }, */
-		{MIIM_STATUS, miim_read, NULL},
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		{MIIM_LXT971_SR2, miim_read, &mii_parse_lxt971_sr2},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* shutdown - disable interrupts */
-		{miim_end,}
-	},
-};
-
-/* Parse the DP83865's link and auto-neg status register for speed and duplex
- * information
- */
-static uint mii_parse_dp83865_lanr(uint mii_reg, struct tsec_private *priv)
-{
-	switch (mii_reg & MIIM_DP83865_SPD_MASK) {
-
-	case MIIM_DP83865_SPD_1000:
-		priv->speed = 1000;
-		break;
-
-	case MIIM_DP83865_SPD_100:
-		priv->speed = 100;
-		break;
-
-	default:
-		priv->speed = 10;
-		break;
-
-	}
-
-	if (mii_reg & MIIM_DP83865_DPX_FULL)
-		priv->duplexity = 1;
-	else
-		priv->duplexity = 0;
-
-	return 0;
+	tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa),
+			0, TBI_ANA, TBIANA_SETTINGS);
+	tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa),
+			0, TBI_TBICON, TBICON_CLK_SELECT);
+	tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa),
+			0, TBI_CR, CONFIG_TSEC_TBICR_SETTINGS);
 }
 
-static struct phy_info phy_info_dp83865 = {
-	0x20005c7,
-	"NatSemi DP83865",
-	4,
-	(struct phy_cmd[]) {	/* config */
-		{MIIM_CONTROL, MIIM_DP83865_CR_INIT, NULL},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* startup */
-		/* Status is read once to clear old link state */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the link and auto-neg status */
-		{MIIM_DP83865_LANR, miim_read, &mii_parse_dp83865_lanr},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* shutdown */
-		{miim_end,}
-	},
-};
-
-static struct phy_info phy_info_rtl8211b = {
-	0x001cc91,
-	"RealTek RTL8211B",
-	4,
-	(struct phy_cmd[]) {	/* config */
-		/* Reset and configure the PHY */
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
-		{MIIM_ANAR, MIIM_ANAR_INIT, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* startup */
-		/* Status is read once to clear old link state */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, &mii_parse_sr},
-		/* Read the status */
-		{MIIM_RTL8211B_PHY_STATUS, miim_read, &mii_parse_RTL8211B_sr},
-		{miim_end,}
-	},
-	(struct phy_cmd[]) {	/* shutdown */
-		{miim_end,}
-	},
-};
-
-struct phy_info phy_info_AR8021 =  {
-        0x4dd04,
-        "AR8021",
-        4,
-        (struct phy_cmd[]) { /* config */
-                {MII_BMCR, BMCR_RESET, NULL},
-                {MII_BMCR, BMCR_ANENABLE|BMCR_ANRESTART, NULL},
-                {0x1d, 0x05, NULL},
-                {0x1e, 0x3D47, NULL},
-                {miim_end,}
-        },
-        (struct phy_cmd[]) { /* startup */
-                {MII_BMSR, miim_read, NULL},
-                {MII_BMSR, miim_read, &mii_parse_sr},
-                {MII_BMSR, miim_read, &mii_parse_link},
-                {miim_end,}
-        },
-        (struct phy_cmd[]) { /* shutdown */
-                {miim_end,}
-        }
-};
-
-static struct phy_info *phy_info[] = {
-	&phy_info_cis8204,
-	&phy_info_cis8201,
-	&phy_info_BCM5461S,
-	&phy_info_BCM5464S,
-	&phy_info_BCM5482S,
-	&phy_info_M88E1011S,
-	&phy_info_M88E1111S,
-	&phy_info_M88E1118,
-	&phy_info_M88E1121R,
-	&phy_info_M88E1145,
-	&phy_info_M88E1149S,
-	&phy_info_dm9161,
-	&phy_info_ksz804,
-	&phy_info_lxt971,
-	&phy_info_VSC8211,
-	&phy_info_VSC8244,
-	&phy_info_VSC8601,
-	&phy_info_VSC8641,
-	&phy_info_VSC8221,
-	&phy_info_dp83865,
-	&phy_info_rtl8211b,
-	&phy_info_AR8021,
-	&phy_info_generic,	/* must be last; has ID 0 and 32 bit mask */
-	NULL
-};
-
-/* Grab the identifier of the device's PHY, and search through
- * all of the known PHYs to see if one matches.	 If so, return
- * it, if not, return NULL
- */
-static struct phy_info *get_phy_info(struct eth_device *dev)
-{
-	struct tsec_private *priv = (struct tsec_private *)dev->priv;
-	uint phy_reg, phy_ID;
-	int i;
-	struct phy_info *theInfo = NULL;
-
-	/* Grab the bits from PHYIR1, and put them in the upper half */
-	phy_reg = read_phy_reg(priv, MIIM_PHYIR1);
-	phy_ID = (phy_reg & 0xffff) << 16;
-
-	/* Grab the bits from PHYIR2, and put them in the lower half */
-	phy_reg = read_phy_reg(priv, MIIM_PHYIR2);
-	phy_ID |= (phy_reg & 0xffff);
-
-	/* loop through all the known PHY types, and find one that */
-	/* matches the ID we read from the PHY. */
-	for (i = 0; phy_info[i]; i++) {
-		if (phy_info[i]->id == (phy_ID >> phy_info[i]->shift)) {
-			theInfo = phy_info[i];
-			break;
-		}
-	}
-
-	if (theInfo == &phy_info_generic) {
-		printf("%s: No support for PHY id %x; assuming generic\n",
-			dev->name, phy_ID);
-	} else {
-		debug("%s: PHY is %s (%x)\n", dev->name, theInfo->name, phy_ID);
-	}
-
-	return theInfo;
-}
-
-/* Execute the given series of commands on the given device's
- * PHY, running functions as necessary
- */
-static void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd)
-{
-	int i;
-	uint result;
-	tsec_mdio_t *phyregs = priv->phyregs;
-
-	out_be32(&phyregs->miimcfg, MIIMCFG_RESET);
-
-	out_be32(&phyregs->miimcfg, MIIMCFG_INIT_VALUE);
-
-	while (in_be32(&phyregs->miimind) & MIIMIND_BUSY)
-		;
-
-	for (i = 0; cmd->mii_reg != miim_end; i++) {
-		if (cmd->mii_data == miim_read) {
-			result = read_phy_reg(priv, cmd->mii_reg);
-
-			if (cmd->funct != NULL)
-				(*(cmd->funct)) (result, priv);
-
-		} else {
-			if (cmd->funct != NULL)
-				result = (*(cmd->funct)) (cmd->mii_reg, priv);
-			else
-				result = cmd->mii_data;
-
-			write_phy_reg(priv, cmd->mii_reg, result);
-
-		}
-		cmd++;
-	}
-}
-
-#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \
-	&& !defined(BITBANGMII)
-
-/*
- * Read a MII PHY register.
- *
- * Returns:
- *  0 on success
- */
-static int tsec_miiphy_read(const char *devname, unsigned char addr,
-			    unsigned char reg, unsigned short *value)
-{
-	unsigned short ret;
-	struct tsec_private *priv = privlist[0];
-
-	if (NULL == priv) {
-		printf("Can't read PHY at address %d\n", addr);
-		return -1;
-	}
-
-	ret = (unsigned short)tsec_local_mdio_read(priv->phyregs, addr, reg);
-	*value = ret;
-
-	return 0;
-}
-
-/*
- * Write a MII PHY register.
- *
- * Returns:
- *  0 on success
- */
-static int tsec_miiphy_write(const char *devname, unsigned char addr,
-			     unsigned char reg, unsigned short value)
-{
-	struct tsec_private *priv = privlist[0];
-
-	if (NULL == priv) {
-		printf("Can't write PHY at address %d\n", addr);
-		return -1;
-	}
-
-	tsec_local_mdio_write(priv->phyregs, addr, reg, value);
-
-	return 0;
-}
-
-#endif
-
 #ifdef CONFIG_MCAST_TFTP
 
 /* CREDITS: linux gianfar driver, slightly adjusted... thanx. */
@@ -1639,14 +189,13 @@ static void init_registers(tsec_t *regs)
 /* Configure maccfg2 based on negotiated speed and duplex
  * reported by PHY handling code
  */
-static void adjust_link(struct eth_device *dev)
+static void adjust_link(struct tsec_private *priv, struct phy_device *phydev)
 {
-	struct tsec_private *priv = (struct tsec_private *)dev->priv;
 	tsec_t *regs = priv->regs;
 	u32 ecntrl, maccfg2;
 
-	if (!priv->link) {
-		printf("%s: No link.\n", dev->name);
+	if (!phydev->link) {
+		printf("%s: No link.\n", phydev->dev->name);
 		return;
 	}
 
@@ -1657,10 +206,10 @@ static void adjust_link(struct eth_device *dev)
 	maccfg2 = in_be32(&regs->maccfg2);
 	maccfg2 &= ~(MACCFG2_IF | MACCFG2_FULL_DUPLEX);
 
-	if (priv->duplexity)
+	if (phydev->duplex)
 		maccfg2 |= MACCFG2_FULL_DUPLEX;
 
-	switch (priv->speed) {
+	switch (phydev->speed) {
 	case 1000:
 		maccfg2 |= MACCFG2_GMII;
 		break;
@@ -1671,20 +220,20 @@ static void adjust_link(struct eth_device *dev)
 		/* Set R100 bit in all modes although
 		 * it is only used in RGMII mode
 		 */
-		if (priv->speed == 100)
+		if (phydev->speed == 100)
 			ecntrl |= ECNTRL_R100;
 		break;
 	default:
-		printf("%s: Speed was bad\n", dev->name);
+		printf("%s: Speed was bad\n", phydev->dev->name);
 		break;
 	}
 
 	out_be32(&regs->ecntrl, ecntrl);
 	out_be32(&regs->maccfg2, maccfg2);
 
-	printf("Speed: %d, %s duplex%s\n", priv->speed,
-			(priv->duplexity) ? "full" : "half",
-			(priv->flags & TSEC_FIBER) ? ", fiber mode" : "");
+	printf("Speed: %d, %s duplex%s\n", phydev->speed,
+			(phydev->duplex) ? "full" : "half",
+			(phydev->port == PORT_FIBRE) ? ", fiber mode" : "");
 }
 
 /* Set up the buffers and their descriptors, and bring up the
@@ -1696,6 +245,10 @@ static void startup_tsec(struct eth_device *dev)
 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
 	tsec_t *regs = priv->regs;
 
+	/* reset the indices to zero */
+	rxIdx = 0;
+	txIdx = 0;
+
 	/* Point to the buffer descriptors */
 	out_be32(&regs->tbase, (unsigned int)(&rtx.txbd[txIdx]));
 	out_be32(&regs->rbase, (unsigned int)(&rtx.rxbd[rxIdx]));
@@ -1716,12 +269,6 @@ static void startup_tsec(struct eth_device *dev)
 	}
 	rtx.txbd[TX_BUF_CNT - 1].status |= TXBD_WRAP;
 
-	/* Start up the PHY */
-	if (priv->phyinfo)
-		phy_run_commands(priv, priv->phyinfo->startup);
-
-	adjust_link(dev);
-
 	/* Enable Transmit and Receive */
 	setbits_be32(&regs->maccfg1, MACCFG1_RX_EN | MACCFG1_TX_EN);
 
@@ -1826,8 +373,7 @@ static void tsec_halt(struct eth_device *dev)
 	clrbits_be32(&regs->maccfg1, MACCFG1_TX_EN | MACCFG1_RX_EN);
 
 	/* Shut down the PHY, as needed */
-	if (priv->phyinfo)
-		phy_run_commands(priv, priv->phyinfo->shutdown);
+	phy_shutdown(priv->phydev);
 }
 
 /* Initializes data structures and registers for the controller,
@@ -1866,20 +412,64 @@ static int tsec_init(struct eth_device *dev, bd_t * bd)
 
 	out_be32(&regs->macstnaddr2, tempval);
 
-	/* reset the indices to zero */
-	rxIdx = 0;
-	txIdx = 0;
-
 	/* Clear out (for the most part) the other registers */
 	init_registers(regs);
 
 	/* Ready the device for tx/rx */
 	startup_tsec(dev);
 
+	/* Start up the PHY */
+	phy_startup(priv->phydev);
+
+	adjust_link(priv, priv->phydev);
+
 	/* If there's no link, fail */
-	return priv->link ? 0 : -1;
+	return priv->phydev->link ? 0 : -1;
 }
 
+static phy_interface_t tsec_get_interface(struct tsec_private *priv)
+{
+	tsec_t *regs = priv->regs;
+	u32 ecntrl;
+
+	ecntrl = in_be32(&regs->ecntrl);
+
+	if (ecntrl & ECNTRL_SGMII_MODE)
+		return PHY_INTERFACE_MODE_SGMII;
+
+	if (ecntrl & ECNTRL_TBI_MODE) {
+		if (ecntrl & ECNTRL_REDUCED_MODE)
+			return PHY_INTERFACE_MODE_RTBI;
+		else
+			return PHY_INTERFACE_MODE_TBI;
+	}
+
+	if (ecntrl & ECNTRL_REDUCED_MODE) {
+		if (ecntrl & ECNTRL_REDUCED_MII_MODE)
+			return PHY_INTERFACE_MODE_RMII;
+		else {
+			phy_interface_t interface = priv->interface;
+
+			/*
+			 * This isn't autodetected, so it must
+			 * be set by the platform code.
+			 */
+			if ((interface == PHY_INTERFACE_MODE_RGMII_ID) ||
+				 (interface == PHY_INTERFACE_MODE_RGMII_TXID) ||
+				 (interface == PHY_INTERFACE_MODE_RGMII_RXID))
+				return interface;
+
+			return PHY_INTERFACE_MODE_RGMII;
+		}
+	}
+
+	if (priv->flags & TSEC_GIGABIT)
+		return PHY_INTERFACE_MODE_GMII;
+
+	return PHY_INTERFACE_MODE_MII;
+}
+
+
 /* Discover which PHY is attached to the device, and configure it
  * properly.  If the PHY is not recognized, then return 0
  * (failure).  Otherwise, return 1
@@ -1887,38 +477,32 @@ static int tsec_init(struct eth_device *dev, bd_t * bd)
 static int init_phy(struct eth_device *dev)
 {
 	struct tsec_private *priv = (struct tsec_private *)dev->priv;
-	struct phy_info *curphy;
+	struct phy_device *phydev;
 	tsec_t *regs = priv->regs;
+	u32 supported = (SUPPORTED_10baseT_Half |
+			SUPPORTED_10baseT_Full |
+			SUPPORTED_100baseT_Half |
+			SUPPORTED_100baseT_Full);
+
+	if (priv->flags & TSEC_GIGABIT)
+		supported |= SUPPORTED_1000baseT_Full;
 
 	/* Assign a Physical address to the TBI */
 	out_be32(&regs->tbipa, CONFIG_SYS_TBIPA_VALUE);
-	asm("sync");
-
-	/* Reset MII (due to new addresses) */
-	out_be32(&priv->phyregs->miimcfg, MIIMCFG_RESET);
-	asm("sync");
-	out_be32(&priv->phyregs->miimcfg, MIIMCFG_INIT_VALUE);
-	asm("sync");
-	while (in_be32(&priv->phyregs->miimind) & MIIMIND_BUSY)
-		;
 
-	/* Get the cmd structure corresponding to the attached
-	 * PHY */
-	curphy = get_phy_info(dev);
+	priv->interface = tsec_get_interface(priv);
 
-	if (curphy == NULL) {
-		priv->phyinfo = NULL;
-		printf("%s: No PHY found\n", dev->name);
+	if (priv->interface == PHY_INTERFACE_MODE_SGMII)
+		tsec_configure_serdes(priv);
 
-		return 0;
-	}
+	phydev = phy_connect(priv->bus, priv->phyaddr, dev, priv->interface);
 
-	if (in_be32(&regs->ecntrl) & ECNTRL_SGMII_MODE)
-		tsec_configure_serdes(priv);
+	phydev->supported &= supported;
+	phydev->advertising = phydev->supported;
 
-	priv->phyinfo = curphy;
+	priv->phydev = phydev;
 
-	phy_run_commands(priv, priv->phyinfo->config);
+	phy_config(phydev);
 
 	return 1;
 }
@@ -1946,13 +530,14 @@ static int tsec_initialize(bd_t *bis, struct tsec_info_struct *tsec_info)
 
 	privlist[num_tsecs++] = priv;
 	priv->regs = tsec_info->regs;
-	priv->phyregs = tsec_info->miiregs;
 	priv->phyregs_sgmii = tsec_info->miiregs_sgmii;
 
 	priv->phyaddr = tsec_info->phyaddr;
 	priv->flags = tsec_info->flags;
 
 	sprintf(dev->name, tsec_info->devname);
+	priv->interface = tsec_info->interface;
+	priv->bus = miiphy_get_dev_by_name(tsec_info->mii_devname);
 	dev->iobase = 0;
 	dev->priv = priv;
 	dev->init = tsec_init;
@@ -1974,11 +559,6 @@ static int tsec_initialize(bd_t *bis, struct tsec_info_struct *tsec_info)
 	udelay(2);  /* Soft Reset must be asserted for 3 TX clocks */
 	clrbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
 
-#if defined(CONFIG_MII) || defined(CONFIG_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);
 }
@@ -2004,6 +584,13 @@ int tsec_eth_init(bd_t *bis, struct tsec_info_struct *tsecs, int num)
 
 int tsec_standard_init(bd_t *bis)
 {
+	struct fsl_pq_mdio_info info;
+
+	info.regs = (tsec_mii_t *)CONFIG_SYS_MDIO_BASE_ADDR;
+	info.name = DEFAULT_MII_NAME;
+
+	fsl_pq_mdio_init(bis, &info);
+
 	return tsec_eth_init(bis, tsec_info, ARRAY_SIZE(tsec_info));
 }
 
diff --git a/include/fsl_mdio.h b/include/fsl_mdio.h
new file mode 100644
index 0000000..5a36507
--- /dev/null
+++ b/include/fsl_mdio.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *	Jun-jie Zhang <b18070@freescale.com>
+ *	Mingkai Hu <Mingkai.hu@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#ifndef __FSL_PHY_H__
+#define __FSL_PHY_H__
+
+#include <net.h>
+#include <miiphy.h>
+#include <asm/fsl_enet.h>
+
+/* PHY register offsets */
+#define PHY_EXT_PAGE_ACCESS	0x1f
+
+/* MII Management Configuration Register */
+#define MIIMCFG_RESET_MGMT          0x80000000
+#define MIIMCFG_MGMT_CLOCK_SELECT   0x00000007
+#define MIIMCFG_INIT_VALUE	    0x00000003
+
+/* MII Management Command Register */
+#define MIIMCOM_READ_CYCLE	0x00000001
+#define MIIMCOM_SCAN_CYCLE	0x00000002
+
+/* MII Management Address Register */
+#define MIIMADD_PHY_ADDR_SHIFT	8
+
+/* MII Management Indicator Register */
+#define MIIMIND_BUSY		0x00000001
+#define MIIMIND_NOTVALID	0x00000004
+
+void tsec_local_mdio_write(tsec_mii_t *phyregs, int port_addr, int dev_addr,
+		int reg, int value);
+int tsec_local_mdio_read(tsec_mii_t *phyregs, int port_addr, int dev_addr,
+		int regnum);
+int tsec_phy_read(struct mii_dev *bus, int addr, int dev_addr, int regnum);
+int tsec_phy_write(struct mii_dev *bus, int addr, int dev_addr, int regnum,
+		u16 value);
+
+struct fsl_pq_mdio_info {
+	tsec_mii_t *regs;
+	char *name;
+};
+int fsl_pq_mdio_init(bd_t *bis, struct fsl_pq_mdio_info *info);
+
+#endif /* __FSL_PHY_H__ */
+
diff --git a/include/tsec.h b/include/tsec.h
index a066d97..2b2f70d 100644
--- a/include/tsec.h
+++ b/include/tsec.h
@@ -19,30 +19,36 @@
 
 #include <net.h>
 #include <config.h>
+#include <phy.h>
+#include <asm/fsl_enet.h>
 
 #define TSEC_SIZE 		0x01000
 #define TSEC_MDIO_OFFSET	0x01000
 
+#define CONFIG_SYS_MDIO_BASE_ADDR (TSEC_BASE_ADDR + 0x520)
+
+#define DEFAULT_MII_NAME "FSL_MDIO"
+
 #define STD_TSEC_INFO(num) \
 {			\
 	.regs = (tsec_t *)(TSEC_BASE_ADDR + ((num - 1) * TSEC_SIZE)), \
-	.miiregs = (tsec_mdio_t *)(MDIO_BASE_ADDR), \
-	.miiregs_sgmii = (tsec_mdio_t *)(MDIO_BASE_ADDR \
+	.miiregs_sgmii = (tsec_mii_t *)(CONFIG_SYS_MDIO_BASE_ADDR \
 					 + (num - 1) * TSEC_MDIO_OFFSET), \
 	.devname = CONFIG_TSEC##num##_NAME, \
 	.phyaddr = TSEC##num##_PHY_ADDR, \
-	.flags = TSEC##num##_FLAGS \
+	.flags = TSEC##num##_FLAGS, \
+	.mii_devname = DEFAULT_MII_NAME \
 }
 
 #define SET_STD_TSEC_INFO(x, num) \
 {			\
 	x.regs = (tsec_t *)(TSEC_BASE_ADDR + ((num - 1) * TSEC_SIZE)); \
-	x.miiregs = (tsec_mdio_t *)(MDIO_BASE_ADDR); \
-	x.miiregs_sgmii = (tsec_mdio_t *)(MDIO_BASE_ADDR \
+	x.miiregs_sgmii = (tsec_mii_t *)(CONFIG_SYS_MDIO_BASE_ADDR \
 					  + (num - 1) * TSEC_MDIO_OFFSET); \
 	x.devname = CONFIG_TSEC##num##_NAME; \
 	x.phyaddr = TSEC##num##_PHY_ADDR; \
 	x.flags = TSEC##num##_FLAGS;\
+	x.mii_devname = DEFAULT_MII_NAME;\
 }
 
 #define MAC_ADDR_LEN 6
@@ -51,8 +57,6 @@
 #define TSEC_TIMEOUT 1000
 #define TOUT_LOOP	1000000
 
-#define PHY_AUTONEGOTIATE_TIMEOUT	5000 /* in ms */
-
 /* TBI register addresses */
 #define TBI_CR			0x00
 #define TBI_SR			0x01
@@ -96,204 +100,14 @@
 
 #define ECNTRL_INIT_SETTINGS	0x00001000
 #define ECNTRL_TBI_MODE		0x00000020
+#define ECNTRL_REDUCED_MODE	0x00000010
 #define ECNTRL_R100		0x00000008
+#define ECNTRL_REDUCED_MII_MODE	0x00000004
 #define ECNTRL_SGMII_MODE	0x00000002
 
-#define miim_end -2
-#define miim_read -1
-
 #ifndef CONFIG_SYS_TBIPA_VALUE
     #define CONFIG_SYS_TBIPA_VALUE	0x1f
 #endif
-#define MIIMCFG_INIT_VALUE	0x00000003
-#define MIIMCFG_RESET		0x80000000
-
-#define MIIMIND_BUSY		0x00000001
-#define MIIMIND_NOTVALID	0x00000004
-
-#define MIIM_CONTROL		0x00
-#define MIIM_CONTROL_RESET	0x00009140
-#define MIIM_CONTROL_INIT	0x00001140
-#define MIIM_CONTROL_RESTART	0x00001340
-#define MIIM_ANEN		0x00001000
-
-#define MIIM_CR			0x00
-#define MIIM_CR_RST		0x00008000
-#define MIIM_CR_INIT		0x00001000
-
-#define MIIM_STATUS		0x1
-#define MIIM_STATUS_AN_DONE	0x00000020
-#define MIIM_STATUS_LINK	0x0004
-
-#define MIIM_PHYIR1		0x2
-#define MIIM_PHYIR2		0x3
-
-#define MIIM_ANAR		0x4
-#define MIIM_ANAR_INIT		0x1e1
-
-#define MIIM_TBI_ANLPBPA	0x5
-#define MIIM_TBI_ANLPBPA_HALF	0x00000040
-#define MIIM_TBI_ANLPBPA_FULL	0x00000020
-
-#define MIIM_TBI_ANEX		0x6
-#define MIIM_TBI_ANEX_NP	0x00000004
-#define MIIM_TBI_ANEX_PRX	0x00000002
-
-#define MIIM_GBIT_CONTROL	0x9
-#define MIIM_GBIT_CONTROL_INIT	0xe00
-
-#define MIIM_EXT_PAGE_ACCESS	0x1f
-
-/* Broadcom BCM54xx -- taken from linux sungem_phy */
-#define MIIM_BCM54xx_AUXCNTL			0x18
-#define MIIM_BCM54xx_AUXCNTL_ENCODE(val)	((val & 0x7) << 12)|(val & 0x7)
-#define MIIM_BCM54xx_AUXSTATUS			0x19
-#define MIIM_BCM54xx_AUXSTATUS_LINKMODE_MASK	0x0700
-#define MIIM_BCM54xx_AUXSTATUS_LINKMODE_SHIFT	8
-
-#define MIIM_BCM54XX_SHD	0x1c	/* 0x1c shadow registers */
-#define MIIM_BCM54XX_SHD_WRITE	0x8000
-#define MIIM_BCM54XX_SHD_VAL(x)	((x & 0x1f) << 10)
-#define MIIM_BCM54XX_SHD_DATA(x)	((x & 0x3ff) << 0)
-#define MIIM_BCM54XX_SHD_WR_ENCODE(val, data)	\
-	(MIIM_BCM54XX_SHD_WRITE | MIIM_BCM54XX_SHD_VAL(val) | \
-	 MIIM_BCM54XX_SHD_DATA(data))
-
-#define MIIM_BCM54XX_EXP_DATA	0x15	/* Expansion register data */
-#define MIIM_BCM54XX_EXP_SEL	0x17	/* Expansion register select */
-#define MIIM_BCM54XX_EXP_SEL_SSD	0x0e00	/* Secondary SerDes select */
-#define MIIM_BCM54XX_EXP_SEL_ER	0x0f00	/* Expansion register select */
-
-/* Cicada Auxiliary Control/Status Register */
-#define MIIM_CIS8201_AUX_CONSTAT	0x1c
-#define MIIM_CIS8201_AUXCONSTAT_INIT	0x0004
-#define MIIM_CIS8201_AUXCONSTAT_DUPLEX	0x0020
-#define MIIM_CIS8201_AUXCONSTAT_SPEED	0x0018
-#define MIIM_CIS8201_AUXCONSTAT_GBIT	0x0010
-#define MIIM_CIS8201_AUXCONSTAT_100	0x0008
-
-/* Cicada Extended Control Register 1 */
-#define MIIM_CIS8201_EXT_CON1		0x17
-#define MIIM_CIS8201_EXTCON1_INIT	0x0000
-
-/* Cicada 8204 Extended PHY Control Register 1 */
-#define MIIM_CIS8204_EPHY_CON		0x17
-#define MIIM_CIS8204_EPHYCON_INIT	0x0006
-#define MIIM_CIS8204_EPHYCON_RGMII	0x1100
-
-/* Cicada 8204 Serial LED Control Register */
-#define MIIM_CIS8204_SLED_CON		0x1b
-#define MIIM_CIS8204_SLEDCON_INIT	0x1115
-
-#define MIIM_GBIT_CON		0x09
-#define MIIM_GBIT_CON_ADVERT	0x0e00
-
-/* Entry for Vitesse VSC8244 regs starts here */
-/* Vitesse VSC8244 Auxiliary Control/Status Register */
-#define MIIM_VSC8244_AUX_CONSTAT	0x1c
-#define MIIM_VSC8244_AUXCONSTAT_INIT	0x0000
-#define MIIM_VSC8244_AUXCONSTAT_DUPLEX	0x0020
-#define MIIM_VSC8244_AUXCONSTAT_SPEED	0x0018
-#define MIIM_VSC8244_AUXCONSTAT_GBIT	0x0010
-#define MIIM_VSC8244_AUXCONSTAT_100	0x0008
-#define MIIM_CONTROL_INIT_LOOPBACK	0x4000
-
-/* Vitesse VSC8244 Extended PHY Control Register 1 */
-#define MIIM_VSC8244_EPHY_CON		0x17
-#define MIIM_VSC8244_EPHYCON_INIT	0x0006
-
-/* Vitesse VSC8244 Serial LED Control Register */
-#define MIIM_VSC8244_LED_CON		0x1b
-#define MIIM_VSC8244_LEDCON_INIT	0xF011
-
-/* Entry for Vitesse VSC8601 regs starts here (Not complete) */
-/* Vitesse VSC8601 Extended PHY Control Register 1 */
-#define MIIM_VSC8601_EPHY_CON		0x17
-#define MIIM_VSC8601_EPHY_CON_INIT_SKEW	0x1120
-#define MIIM_VSC8601_SKEW_CTRL		0x1c
-
-/* 88E1011 PHY Status Register */
-#define MIIM_88E1011_PHY_STATUS		0x11
-#define MIIM_88E1011_PHYSTAT_SPEED	0xc000
-#define MIIM_88E1011_PHYSTAT_GBIT	0x8000
-#define MIIM_88E1011_PHYSTAT_100	0x4000
-#define MIIM_88E1011_PHYSTAT_DUPLEX	0x2000
-#define MIIM_88E1011_PHYSTAT_SPDDONE	0x0800
-#define MIIM_88E1011_PHYSTAT_LINK	0x0400
-
-#define MIIM_88E1011_PHY_SCR		0x10
-#define MIIM_88E1011_PHY_MDI_X_AUTO	0x0060
-
-/* 88E1111 PHY LED Control Register */
-#define MIIM_88E1111_PHY_LED_CONTROL	24
-#define MIIM_88E1111_PHY_LED_DIRECT	0x4100
-#define MIIM_88E1111_PHY_LED_COMBINE	0x411C
-
-/* 88E1121 PHY LED Control Register */
-#define MIIM_88E1121_PHY_LED_CTRL	16
-#define MIIM_88E1121_PHY_LED_PAGE	3
-#define MIIM_88E1121_PHY_LED_DEF	0x0030
-
-/* 88E1121 PHY IRQ Enable/Status Register */
-#define MIIM_88E1121_PHY_IRQ_EN		18
-#define MIIM_88E1121_PHY_IRQ_STATUS	19
-
-#define MIIM_88E1121_PHY_PAGE		22
-
-/* 88E1145 Extended PHY Specific Control Register */
-#define MIIM_88E1145_PHY_EXT_CR 20
-#define MIIM_M88E1145_RGMII_RX_DELAY	0x0080
-#define MIIM_M88E1145_RGMII_TX_DELAY	0x0002
-
-#define MIIM_88E1145_PHY_PAGE	29
-#define MIIM_88E1145_PHY_CAL_OV 30
-
-/* RTL8211B PHY Status Register */
-#define MIIM_RTL8211B_PHY_STATUS	0x11
-#define MIIM_RTL8211B_PHYSTAT_SPEED	0xc000
-#define MIIM_RTL8211B_PHYSTAT_GBIT	0x8000
-#define MIIM_RTL8211B_PHYSTAT_100	0x4000
-#define MIIM_RTL8211B_PHYSTAT_DUPLEX	0x2000
-#define MIIM_RTL8211B_PHYSTAT_SPDDONE	0x0800
-#define MIIM_RTL8211B_PHYSTAT_LINK	0x0400
-
-/* DM9161 Control register values */
-#define MIIM_DM9161_CR_STOP	0x0400
-#define MIIM_DM9161_CR_RSTAN	0x1200
-
-#define MIIM_DM9161_SCR		0x10
-#define MIIM_DM9161_SCR_INIT	0x0610
-
-/* DM9161 Specified Configuration and Status Register */
-#define MIIM_DM9161_SCSR	0x11
-#define MIIM_DM9161_SCSR_100F	0x8000
-#define MIIM_DM9161_SCSR_100H	0x4000
-#define MIIM_DM9161_SCSR_10F	0x2000
-#define MIIM_DM9161_SCSR_10H	0x1000
-
-/* DM9161 10BT Configuration/Status */
-#define MIIM_DM9161_10BTCSR	0x12
-#define MIIM_DM9161_10BTCSR_INIT	0x7800
-
-/* LXT971 Status 2 registers */
-#define MIIM_LXT971_SR2		     0x11  /* Status Register 2  */
-#define MIIM_LXT971_SR2_SPEED_MASK 0x4200
-#define MIIM_LXT971_SR2_10HDX	   0x0000  /*  10 Mbit half duplex selected */
-#define MIIM_LXT971_SR2_10FDX	   0x0200  /*  10 Mbit full duplex selected */
-#define MIIM_LXT971_SR2_100HDX	   0x4000  /* 100 Mbit half duplex selected */
-#define MIIM_LXT971_SR2_100FDX	   0x4200  /* 100 Mbit full duplex selected */
-
-/* DP83865 Control register values */
-#define MIIM_DP83865_CR_INIT	0x9200
-
-/* DP83865 Link and Auto-Neg Status Register */
-#define MIIM_DP83865_LANR	0x11
-#define MIIM_DP83865_SPD_MASK	0x0018
-#define MIIM_DP83865_SPD_1000	0x0010
-#define MIIM_DP83865_SPD_100	0x0008
-#define MIIM_DP83865_DPX_FULL	0x0002
-
-#define MIIM_READ_COMMAND	0x00000001
 
 #define MRBLR_INIT_SETTINGS	PKTSIZE_ALIGN
 
@@ -467,22 +281,6 @@ typedef struct tsec_hash_regs
 	uint	res2[24];
 } tsec_hash_t;
 
-typedef struct tsec_mdio {
-	uint	res1[4];
-	uint	ieventm;
-	uint	imaskm;
-	uint	res2;
-	uint	emapm;
-	uint	res3[320];
-	uint	miimcfg;	/* MII Management: Configuration */
-	uint	miimcom;	/* MII Management: Command */
-	uint	miimadd;	/* MII Management: Address */
-	uint	miimcon;	/* MII Management: Control */
-	uint	miimstat;	/* MII Management: Status */
-	uint	miimind;	/* MII Management: Indicators */
-	uint	res4[690];
-} tsec_mdio_t;
-
 typedef struct tsec
 {
 	/* General Control and Status Registers (0x2_n000) */
@@ -578,79 +376,29 @@ typedef struct tsec
 	uint	resc00[256];
 } tsec_t;
 
-#define TSEC_GIGABIT (1)
+#define TSEC_GIGABIT (1 << 0)
 
-/* This flag currently only has
- * meaning if we're using the eTSEC */
+/* These flags currently only have meaning if we're using the eTSEC */
 #define TSEC_REDUCED	(1 << 1)	/* MAC-PHY interface uses RGMII */
 #define TSEC_SGMII	(1 << 2)	/* MAC-PHY interface uses SGMII */
-#define TSEC_FIBER	(1 << 3)	/* PHY uses fiber, eg 1000 Base-X */
 
 struct tsec_private {
 	tsec_t *regs;
-	tsec_mdio_t *phyregs;
-	tsec_mdio_t *phyregs_sgmii;
-	struct phy_info *phyinfo;
+	tsec_mii_t *phyregs_sgmii;
+	struct phy_device *phydev;
+	phy_interface_t interface;
+	struct mii_dev *bus;
 	uint phyaddr;
+	char mii_devname[16];
 	u32 flags;
-	uint link;
-	uint duplexity;
-	uint speed;
-};
-
-
-/*
- * struct phy_cmd:  A command for reading or writing a PHY register
- *
- * mii_reg:  The register to read or write
- *
- * mii_data:  For writes, the value to put in the register.
- *	A value of -1 indicates this is a read.
- *
- * funct: A function pointer which is invoked for each command.
- *	For reads, this function will be passed the value read
- *	from the PHY, and process it.
- *	For writes, the result of this function will be written
- *	to the PHY register
- */
-struct phy_cmd {
-	uint mii_reg;
-	uint mii_data;
-	uint (*funct) (uint mii_reg, struct tsec_private * priv);
-};
-
-/* struct phy_info: a structure which defines attributes for a PHY
- *
- * id will contain a number which represents the PHY.  During
- * startup, the driver will poll the PHY to find out what its
- * UID--as defined by registers 2 and 3--is.  The 32-bit result
- * gotten from the PHY will be shifted right by "shift" bits to
- * discard any bits which may change based on revision numbers
- * unimportant to functionality
- *
- * The struct phy_cmd entries represent pointers to an arrays of
- * commands which tell the driver what to do to the PHY.
- */
-struct phy_info {
-	uint id;
-	char *name;
-	uint shift;
-	/* Called to configure the PHY, and modify the controller
-	 * based on the results */
-	struct phy_cmd *config;
-
-	/* Called when starting up the controller */
-	struct phy_cmd *startup;
-
-	/* Called when bringing down the controller */
-	struct phy_cmd *shutdown;
 };
 
 struct tsec_info_struct {
 	tsec_t *regs;
-	tsec_mdio_t *miiregs;
-	tsec_mdio_t *miiregs_sgmii;
+	tsec_mii_t *miiregs_sgmii;
 	char *devname;
+	char *mii_devname;
+	phy_interface_t interface;
 	unsigned int phyaddr;
 	u32 flags;
 };
-- 
1.6.5.2.g6ff9a

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [U-Boot] [PATCH v2 0/6] Universal PHY Infrastructure
  2011-04-05 21:59 [U-Boot] [PATCH v2 0/6] Universal PHY Infrastructure Andy Fleming
  2011-04-05 21:59 ` [U-Boot] [PATCH v2 1/6] tsec: use IO accessors for IO accesses Andy Fleming
@ 2011-04-06 12:07 ` Detlev Zundel
  2011-04-07 14:13   ` Andy Fleming
  1 sibling, 1 reply; 27+ messages in thread
From: Detlev Zundel @ 2011-04-06 12:07 UTC (permalink / raw)
  To: u-boot

Hi Andy,

> This second version cleans up all checkpatch errors that I reasonably could,
> and addresses most of the comments from the first round of reviews.

  WARNING: Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt
  #1299: FILE: drivers/net/tsec.c:1740:
  +static int tsec_send(struct eth_device *dev, volatile void *packet, int length)

Ah I see.  This is needed because include/net.h prescribes this as the
interface.  Oh well, we should clean this up at some later point, so
it's ok from my perspective to ignore this and at least stay consistent.
  
  WARNING: do not add new typedefs
  #4271: FILE: include/phy.h:389:
  +typedef enum {

I know that we have lots of typedefs, but we should not add new ones.
Actually not using this typedef for an enum-type would make the sources
easier for me to read as I don't have to do this extra lookup step.
  
  WARNING: do not add new typedefs
  #6304: FILE: arch/powerpc/include/asm/fsl_enet.h:31:
  +typedef struct tsec_mii_mng {

I'd also appreciate if you use "struct tsec_mii_mng" explicitely instead
of adding another typedef.
  
Overall I agree, checkpatch is much happier now ;)

Cheers
  Detlev

-- 
Cyberwar is certainly not a myth. But you haven't seen it yet, despite
the attacks on Estonia. Cyberwar is warfare in cyberspace. And warfare
involves massive death and destruction. When you see it, you'll know it.
                           -- Bruce Schneier, Nov. 2007
--
DENX Software Engineering GmbH,      MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich,  Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-40 Fax: (+49)-8142-66989-80 Email: dzu at denx.de

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [U-Boot] [PATCH v2 1/6] tsec: use IO accessors for IO accesses
  2011-04-05 21:59 ` [U-Boot] [PATCH v2 1/6] tsec: use IO accessors for IO accesses Andy Fleming
  2011-04-05 21:59   ` [U-Boot] [PATCH v2 2/6] tsec: arrange the code to avoid useless function declaration Andy Fleming
@ 2011-04-06 12:29   ` Detlev Zundel
  2011-04-06 12:32     ` Kumar Gala
  1 sibling, 1 reply; 27+ messages in thread
From: Detlev Zundel @ 2011-04-06 12:29 UTC (permalink / raw)
  To: u-boot

Hi Andy,

> From: Mingkai Hu <Mingkai.hu@freescale.com>
>
> Signed-off-by: Mingkai Hu <Mingkai.hu@freescale.com>
> Acked-by: Andy Fleming <afleming@freescale.com>
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
> ---
> Fixed the commit message's spelling
>
>  drivers/net/tsec.c |  242 +++++++++++++++++++++++++++-------------------------
>  include/tsec.h     |    8 +-
>  2 files changed, 130 insertions(+), 120 deletions(-)

Despite what Kumar says I can't see that patch in mpc85xx/next so let's
see.

> diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c
> index 9a91b9e..4ea9813 100644
> --- a/drivers/net/tsec.c
> +++ b/drivers/net/tsec.c

[...]

> @@ -230,17 +230,18 @@ static int tsec_init(struct eth_device *dev, bd_t * bd)
>  }
>  
>  /* Writes the given phy's reg with value, using the specified MDIO regs */
> -static void tsec_local_mdio_write(volatile tsec_mdio_t *phyregs, uint addr,
> +static void tsec_local_mdio_write(tsec_mdio_t *phyregs, uint addr,
>  		uint reg, uint value)
>  {
>  	int timeout = 1000000;
>  
> -	phyregs->miimadd = (addr << 8) | reg;
> -	phyregs->miimcon = value;
> +	out_be32(&phyregs->miimadd, (addr << 8) | reg);
> +	out_be32(&phyregs->miimcon, value);
>  	asm("sync");

We don't need the sync here anymore, as this is done by the next
in_be32.

>  
>  	timeout = 1000000;
> -	while ((phyregs->miimind & MIIMIND_BUSY) && timeout--) ;
> +	while ((in_be32(&phyregs->miimind) & MIIMIND_BUSY) && timeout--)
> +		;
>  }
>  
>  
> @@ -254,28 +255,28 @@ static void tsec_local_mdio_write(volatile tsec_mdio_t *phyregs, uint addr,
>   * notvalid bit cleared), and the bus to cease activity (miimind
>   * busy bit cleared), and then returns the value
>   */
> -static uint tsec_local_mdio_read(volatile tsec_mdio_t *phyregs,
> -				uint phyid, uint regnum)
> +static uint tsec_local_mdio_read(tsec_mdio_t *phyregs, uint phyid, uint regnum)
>  {
>  	uint value;
>  
>  	/* Put the address of the phy, and the register
>  	 * number into MIIMADD */
> -	phyregs->miimadd = (phyid << 8) | regnum;
> +	out_be32(&phyregs->miimadd, (phyid << 8) | regnum);
>  
>  	/* Clear the command register, and wait */
> -	phyregs->miimcom = 0;
> +	out_be32(&phyregs->miimcom, 0);
>  	asm("sync");

Not needed anymore, done by the next accessor.

>  	/* Initiate a read command, and wait */
> -	phyregs->miimcom = MIIM_READ_COMMAND;
> +	out_be32(&phyregs->miimcom, MIIM_READ_COMMAND);
>  	asm("sync");

Dito.

>  
>  	/* Wait for the the indication that the read is done */
> -	while ((phyregs->miimind & (MIIMIND_NOTVALID | MIIMIND_BUSY))) ;
> +	while ((in_be32(&phyregs->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY)))
> +		;
>  
>  	/* Grab the value read from the PHY */
> -	value = phyregs->miimstat;
> +	value = in_be32(&phyregs->miimstat);
>  
>  	return value;
>  }
> @@ -321,18 +322,19 @@ static int init_phy(struct eth_device *dev)
>  {
>  	struct tsec_private *priv = (struct tsec_private *)dev->priv;
>  	struct phy_info *curphy;
> -	volatile tsec_t *regs = priv->regs;
> +	tsec_t *regs = priv->regs;
>  
>  	/* Assign a Physical address to the TBI */
> -	regs->tbipa = CONFIG_SYS_TBIPA_VALUE;
> +	out_be32(&regs->tbipa, CONFIG_SYS_TBIPA_VALUE);
>  	asm("sync");

dito

>  
>  	/* Reset MII (due to new addresses) */
> -	priv->phyregs->miimcfg = MIIMCFG_RESET;
> +	out_be32(&priv->phyregs->miimcfg, MIIMCFG_RESET);
>  	asm("sync");

dito

> -	priv->phyregs->miimcfg = MIIMCFG_INIT_VALUE;
> +	out_be32(&priv->phyregs->miimcfg, MIIMCFG_INIT_VALUE);
>  	asm("sync");

once more

> -	while (priv->phyregs->miimind & MIIMIND_BUSY) ;
> +	while (in_be32(&priv->phyregs->miimind) & MIIMIND_BUSY)
> +		;
>  
>  	/* Get the cmd structure corresponding to the attached
>  	 * PHY */
> @@ -345,7 +347,7 @@ static int init_phy(struct eth_device *dev)
>  		return 0;
>  	}
>  
> -	if (regs->ecntrl & ECNTRL_SGMII_MODE)
> +	if (in_be32(&regs->ecntrl) & ECNTRL_SGMII_MODE)
>  		tsec_configure_serdes(priv);
>  
>  	priv->phyinfo = curphy;
> @@ -838,16 +840,17 @@ static uint mii_parse_dm9161_scsr(uint mii_reg, struct tsec_private * priv)
>  static uint mii_cis8204_fixled(uint mii_reg, struct tsec_private * priv)
>  {
>  	uint phyid;
> -	volatile tsec_mdio_t *regbase = priv->phyregs;
> +	tsec_mdio_t *regbase = priv->phyregs;
>  	int timeout = 1000000;
>  
>  	for (phyid = 0; phyid < 4; phyid++) {
> -		regbase->miimadd = (phyid << 8) | mii_reg;
> -		regbase->miimcon = MIIM_CIS8204_SLEDCON_INIT;
> +		out_be32(&regbase->miimadd, (phyid << 8) | mii_reg);
> +		out_be32(&regbase->miimcon, MIIM_CIS8204_SLEDCON_INIT);
>  		asm("sync");

and again

>  
>  		timeout = 1000000;
> -		while ((regbase->miimind & MIIMIND_BUSY) && timeout--) ;
> +		while ((in_be32(&regbase->miimind) & MIIMIND_BUSY) && timeout--)
> +			;
>  	}
>  
>  	return MIIM_CIS8204_SLEDCON_INIT;

[...]

> @@ -922,44 +925,49 @@ static void init_registers(volatile tsec_t * regs)
>  static void adjust_link(struct eth_device *dev)
>  {
>  	struct tsec_private *priv = (struct tsec_private *)dev->priv;
> -	volatile tsec_t *regs = priv->regs;
> +	tsec_t *regs = priv->regs;
> +	u32 ecntrl, maccfg2;
>  
> -	if (priv->link) {
> -		if (priv->duplexity != 0)
> -			regs->maccfg2 |= MACCFG2_FULL_DUPLEX;
> -		else
> -			regs->maccfg2 &= ~(MACCFG2_FULL_DUPLEX);
> +	if (!priv->link) {
> +		printf("%s: No link.\n", dev->name);
> +		return;
> +	}
>  
> -		switch (priv->speed) {
> -		case 1000:
> -			regs->maccfg2 = ((regs->maccfg2 & ~(MACCFG2_IF))
> -					 | MACCFG2_GMII);
> -			break;
> -		case 100:
> -		case 10:
> -			regs->maccfg2 = ((regs->maccfg2 & ~(MACCFG2_IF))
> -					 | MACCFG2_MII);
> +	/* clear all bits relative with interface mode */
> +	ecntrl = in_be32(&regs->ecntrl);
> +	ecntrl &= ~ECNTRL_R100;
>  
> -			/* Set R100 bit in all modes although
> -			 * it is only used in RGMII mode
> -			 */
> -			if (priv->speed == 100)
> -				regs->ecntrl |= ECNTRL_R100;
> -			else
> -				regs->ecntrl &= ~(ECNTRL_R100);
> -			break;
> -		default:
> -			printf("%s: Speed was bad\n", dev->name);
> -			break;
> -		}
> +	maccfg2 = in_be32(&regs->maccfg2);
> +	maccfg2 &= ~(MACCFG2_IF | MACCFG2_FULL_DUPLEX);
>  
> -		printf("Speed: %d, %s duplex%s\n", priv->speed,
> -		       (priv->duplexity) ? "full" : "half",
> -		       (priv->flags & TSEC_FIBER) ? ", fiber mode" : "");
> +	if (priv->duplexity)
> +		maccfg2 |= MACCFG2_FULL_DUPLEX;
>  
> -	} else {
> -		printf("%s: No link.\n", dev->name);
> +	switch (priv->speed) {
> +	case 1000:
> +		maccfg2 |= MACCFG2_GMII;
> +		break;
> +	case 100:
> +	case 10:
> +		maccfg2 |= MACCFG2_MII;
> +
> +		/* Set R100 bit in all modes although
> +		 * it is only used in RGMII mode
> +		 */
> +		if (priv->speed == 100)
> +			ecntrl |= ECNTRL_R100;
> +		break;
> +	default:
> +		printf("%s: Speed was bad\n", dev->name);
> +		break;
>  	}
> +
> +	out_be32(&regs->ecntrl, ecntrl);
> +	out_be32(&regs->maccfg2, maccfg2);
> +
> +	printf("Speed: %d, %s duplex%s\n", priv->speed,
> +			(priv->duplexity) ? "full" : "half",
> +			(priv->flags & TSEC_FIBER) ? ", fiber mode" : "");
>  }

Hm, this hunk is definitely more than changing to accessors, but if I
read it correctly, it introduces a short-cut way out and thus changes
indentation but does not change functionality.  Still would have been
nice to split this out into a change before and only do whats advertised
in the patch description here.

Cheers
  Detlev

-- 
Wissenschaft ohne Verstand ist doppelte Narrheit.
                                    --- Baltasar Gracian
--
DENX Software Engineering GmbH,      MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich,  Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-40 Fax: (+49)-8142-66989-80 Email: dzu at denx.de

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [U-Boot] [PATCH v2 2/6] tsec: arrange the code to avoid useless function declaration
  2011-04-05 21:59   ` [U-Boot] [PATCH v2 2/6] tsec: arrange the code to avoid useless function declaration Andy Fleming
  2011-04-05 21:59     ` [U-Boot] [PATCH v2 3/6] Remove instances of phy_read/write Andy Fleming
@ 2011-04-06 12:31     ` Detlev Zundel
  1 sibling, 0 replies; 27+ messages in thread
From: Detlev Zundel @ 2011-04-06 12:31 UTC (permalink / raw)
  To: u-boot

Hi Andy,

> From: Mingkai Hu <Mingkai.hu@freescale.com>
>
> This is merely a rearrangement.  No changes to the code, except
> to remove now-useless declarations.

The syncs from the previous patches will go away here also as a
consequence.

Cheers
  Detlev

-- 
Perfecting oneself is as much unlearning as it is learning. 
                                        -- Edsger Dijkstra 
--
DENX Software Engineering GmbH,      MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich,  Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-40 Fax: (+49)-8142-66989-80 Email: dzu at denx.de

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [U-Boot] [PATCH v2 1/6] tsec: use IO accessors for IO accesses
  2011-04-06 12:29   ` [U-Boot] [PATCH v2 1/6] tsec: use IO accessors for IO accesses Detlev Zundel
@ 2011-04-06 12:32     ` Kumar Gala
  0 siblings, 0 replies; 27+ messages in thread
From: Kumar Gala @ 2011-04-06 12:32 UTC (permalink / raw)
  To: u-boot


On Apr 6, 2011, at 7:29 AM, Detlev Zundel wrote:

> Hi Andy,
> 
>> From: Mingkai Hu <Mingkai.hu@freescale.com>
>> 
>> Signed-off-by: Mingkai Hu <Mingkai.hu@freescale.com>
>> Acked-by: Andy Fleming <afleming@freescale.com>
>> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
>> ---
>> Fixed the commit message's spelling
>> 
>> drivers/net/tsec.c |  242 +++++++++++++++++++++++++++-------------------------
>> include/tsec.h     |    8 +-
>> 2 files changed, 130 insertions(+), 120 deletions(-)
> 
> Despite what Kumar says I can't see that patch in mpc85xx/next so let's
> see.

I dropped it after talking to Andy about this patch sequence.

- k

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [U-Boot] [PATCH v2 3/6] Remove instances of phy_read/write
  2011-04-05 21:59     ` [U-Boot] [PATCH v2 3/6] Remove instances of phy_read/write Andy Fleming
  2011-04-05 21:59       ` [U-Boot] [PATCH v2 4/6] Create PHY Lib for U-Boot Andy Fleming
@ 2011-04-06 12:32       ` Detlev Zundel
  1 sibling, 0 replies; 27+ messages in thread
From: Detlev Zundel @ 2011-04-06 12:32 UTC (permalink / raw)
  To: u-boot

Hi Andy,

> There were a few files which were already using phy_read and phy_write
> for their PHY function names.  It's only a few places, and the name
> seems most appropriate for the high-level abstraction, so let's
> rename the other versions to something more specific.
>
> Also, uec_phy.c had a marvell_init function which I renamed to not
> conflict with the one in marvell.c
>
> Lastly, uec_phy.c was putting a space between the phy writing
> function names, and the open paren, so I fixed that
>
> Signed-off-by: Andy Fleming <afleming@freescale.com>

I already gave my

Acked-by: Detlev Zundel <dzu@denx.de>

on this patch.

Cheers
  Detlev

-- 
Infolge sklavischer "Kategoritis"  werden die wissenschaftlichen unlogischen
und - wie wir sehen werden -  oft sinnlosen Fragen wie "Wo wohnst du?", "Was
bist du?", "Welche Religion?", "Welche Rasse?", "Welche Nationalit?t?" alle-
samt heute f?r logische Fragen gehalten.       -- Richard Buckminster Fuller
--
DENX Software Engineering GmbH,      MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich,  Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-40 Fax: (+49)-8142-66989-80 Email: dzu at denx.de

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [U-Boot] [PATCH v2 4/6] Create PHY Lib for U-Boot
  2011-04-05 21:59       ` [U-Boot] [PATCH v2 4/6] Create PHY Lib for U-Boot Andy Fleming
  2011-04-05 21:59         ` [U-Boot] [PATCH v2 5/6] phylib: Add a bunch of PHY drivers from tsec Andy Fleming
@ 2011-04-06 12:56         ` Detlev Zundel
  2011-04-06 23:09         ` Mike Frysinger
                           ` (2 subsequent siblings)
  4 siblings, 0 replies; 27+ messages in thread
From: Detlev Zundel @ 2011-04-06 12:56 UTC (permalink / raw)
  To: u-boot

Hi Andy,

> Extends the mii_dev structure to participate in a full-blown MDIO and
> PHY driver scheme.  The mii_dev structure and miiphy calls are modified
> in such a way to allow the original mii command and miiphy
> infrastructure to work as before, but also to support a new set of APIs
> which allow (among other things) sharing of PHY driver code and 10G support
>
> The mii command will continue to support normal PHY management functions
> (Clause 22 of 802.3), but will not be changed to support 10G
> (Clause 45).
>
> The basic design is similar to PHY Lib from Linux, but simplified for
> U-Boot's network and driver infrastructure.
>
> We now have MDIO drivers and PHY drivers
>
> An MDIO driver provides:
> read
> write
> reset
>
> A PHY driver provides:
> (optionally): probe
> config - initial setup, starting of auto-negotiation
> startup - waiting for AN, and reading link state
> shutdown - any cleanup needed
>
> The ethernet drivers interact with the PHY Lib using these functions:
> phy_connect()
> phy_config()
> phy_startup()
> phy_shutdown()
>
> Each PHY driver can be configured separately, or all at once using
> phylib_all_drivers.h (added in the patch which adds the drivers)
>
> In the process, cleaned up a number of whitespace issues in miiphyutil.c
>
> Signed-off-by: Andy Fleming <afleming@freescale.com>
> ---
> * Fixed some sparse warnings/errors
> * Changed headers for new files to GPL v2+
> * Removed the unexplained 500ms delay after autonegotiation

Looks good, thanks!

Acked-by: Detlev Zundel <dzu@denx.de>

Cheers
  Detlev

-- 
Modern methods of production have given us the possibility of ease and
security for all;  we have chosen, instead,  to have overwork for some
and starvation for others.
                                    -- Bertrand Russell
--
DENX Software Engineering GmbH,      MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich,  Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-40 Fax: (+49)-8142-66989-80 Email: dzu at denx.de

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [U-Boot] [PATCH v2 5/6] phylib: Add a bunch of PHY drivers from tsec
  2011-04-05 21:59         ` [U-Boot] [PATCH v2 5/6] phylib: Add a bunch of PHY drivers from tsec Andy Fleming
  2011-04-05 21:59           ` [U-Boot] [PATCH v2 6/6] tsec: Convert tsec to use PHY Lib Andy Fleming
@ 2011-04-06 13:01           ` Detlev Zundel
  2011-04-06 22:50           ` Mike Frysinger
  2 siblings, 0 replies; 27+ messages in thread
From: Detlev Zundel @ 2011-04-06 13:01 UTC (permalink / raw)
  To: u-boot

Hi Andy,

> The tsec driver had a bunch of PHY drivers already written. This
> converts them all into PHY Lib drivers, and serves as the first
> set of PHY drivers for PHY Lib.
>
> While doing that, cleaned up a number of magic numbers (though
> not all of them, as PHY vendors like to keep their numbers as
> magical as possible).  Also, noticed that almost all of the
> vitesse/cicada PHYs had the same config/parse/startup functions,
> so those have been collapsed into one.
>
> Signed-off-by: Andy Fleming <afleming@freescale.com>
> ---
> * Added teranetics_init() to init function
> * Sorted init functions in phy_init and in phy.h
> * Sorted PHYs in drivers/net/phy/Makefile
> * GPL v2+ on all new files
> * Left the 500ms delay after autonegotiation for PHY drivers that had it,
>   as I don't want to break the driver-specific functionality. I suspect that
>   either we've already fixed the bug this was really working around, or we
>   will need a bug fix in the generic code. Either way, this code doesn't
>   change the previous behavior, and can always be fixed at a later date,
>   when one of us has time to actually test it out.
> * Added many constants and consolidated the vitesse functions

Thanks for the changes, especially for the tedious constants stuff.  This
looks really good now.

Acked-by: Detlev Zundel <dzu@denx.de>

Cheers
  Detlev

-- 
These days, even the most pure and abstract mathematics is in danger
to be applied.
--
DENX Software Engineering GmbH,      MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich,  Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-40 Fax: (+49)-8142-66989-80 Email: dzu at denx.de

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [U-Boot] [PATCH v2 6/6] tsec: Convert tsec to use PHY Lib
  2011-04-05 21:59           ` [U-Boot] [PATCH v2 6/6] tsec: Convert tsec to use PHY Lib Andy Fleming
@ 2011-04-06 13:02             ` Detlev Zundel
  0 siblings, 0 replies; 27+ messages in thread
From: Detlev Zundel @ 2011-04-06 13:02 UTC (permalink / raw)
  To: u-boot

Hi Andy,

> This converts tsec to use the new PHY Lib.  All of the old PHY support
> is ripped out.  The old MDIO driver is split off, and placed in
> fsl_mdio.c.  The initialization is modified to initialize the MDIO
> driver as well.  The powerpc config file is modified to configure PHYLIB
> if TSEC_ENET is configured.
>
> Signed-off-by: Mingkai Hu <Mingkai.hu@freescale.com>
> Signed-off-by: Andy Fleming <afleming@freescale.com>
> ---
> * Fixed numerous sparse warnings/errors

When the typedef is gone, you have my

Acked-by: Detlev Zundel <dzu@denx.de>

Cheers
  Detlev

-- 
Q:  What does FAQ stand for?
A:  We are Frequently Asked this Question, and we have no idea.
--
DENX Software Engineering GmbH,      MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich,  Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-40 Fax: (+49)-8142-66989-80 Email: dzu at denx.de

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [U-Boot] [PATCH v2 5/6] phylib: Add a bunch of PHY drivers from tsec
  2011-04-05 21:59         ` [U-Boot] [PATCH v2 5/6] phylib: Add a bunch of PHY drivers from tsec Andy Fleming
  2011-04-05 21:59           ` [U-Boot] [PATCH v2 6/6] tsec: Convert tsec to use PHY Lib Andy Fleming
  2011-04-06 13:01           ` [U-Boot] [PATCH v2 5/6] phylib: Add a bunch of PHY drivers from tsec Detlev Zundel
@ 2011-04-06 22:50           ` Mike Frysinger
  2 siblings, 0 replies; 27+ messages in thread
From: Mike Frysinger @ 2011-04-06 22:50 UTC (permalink / raw)
  To: u-boot

On Tuesday, April 05, 2011 17:59:53 Andy Fleming wrote:
> --- a/include/phy.h
> +++ b/include/phy.h
> +int atheros_init(void);
> +int broadcom_init(void);
> +int davicom_init(void);
> +int lxt_init(void);
> +int marvell_init(void);
> +int micrel_init(void);
> +int natsemi_init(void);
> +int realtek_init(void);
> +int teranetics_init(void);
> +int vitesse_init(void);

imo, these should have a "phy_" prefix on their names.  these are pretty 
generic otherwise.

> diff --git a/include/phylib_all_drivers.h b/include/phylib_all_drivers.h

this probably should be prefixed with a "config_" to match the existing header 
filename style.
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20110406/d39a2262/attachment.pgp 

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [U-Boot] [PATCH v2 4/6] Create PHY Lib for U-Boot
  2011-04-05 21:59       ` [U-Boot] [PATCH v2 4/6] Create PHY Lib for U-Boot Andy Fleming
  2011-04-05 21:59         ` [U-Boot] [PATCH v2 5/6] phylib: Add a bunch of PHY drivers from tsec Andy Fleming
  2011-04-06 12:56         ` [U-Boot] [PATCH v2 4/6] Create PHY Lib for U-Boot Detlev Zundel
@ 2011-04-06 23:09         ` Mike Frysinger
  2011-04-07 14:16           ` Andy Fleming
  2011-04-07  4:43         ` Wolfgang Denk
  2011-04-07  5:19         ` Wolfgang Denk
  4 siblings, 1 reply; 27+ messages in thread
From: Mike Frysinger @ 2011-04-06 23:09 UTC (permalink / raw)
  To: u-boot

On Tuesday, April 05, 2011 17:59:52 Andy Fleming wrote:
> -#define debug(fmt,args...)	printf (fmt ,##args)
> +#define debug(fmt, args...)	printf(fmt, ##args)

it'd be nice if all these unrelated formatting changes werent intermingled.  
but i guess too hard for you to untangle now.  make it a pita to pick out what 
are functional changes and what is pure noise.

> +struct mii_dev *mdio_alloc(void)
> +{
> +	struct mii_dev *bus;
> +
> +	bus = malloc(sizeof(*bus));
> +	if (!bus)
> +		return bus;
> +
> +	memset(bus, 0, sizeof(*bus));
> +
> +	bus->name = malloc(MDIO_NAME_LEN);

considering the name len is hardcoded at build time, it'd be nice to inline 
that into the struct itself to avoid having to do multiple mallocs.  but i 
guess it might be hard to keep working with the legacy code ?  or maybe not if 
you just grep the tree to make sure no one using legacy code has a name longer 
than 31 bytes ...

> +struct phy_device *mdio_phydev_for_ethname(const char *ethname)
> ...
> +			if ((!bus->phymap[i]) || (!bus->phymap[i]->dev))

useless paren around both expressions here

> --- /dev/null
> +++ b/drivers/net/phy/phy.c
>
> +int phy_read(struct phy_device *phydev, int devad, int regnum)
> +{
> +	struct mii_dev *bus = phydev->bus;
> +
> +	return bus->read(bus, phydev->addr, devad, regnum);
> +}
> +
> +int phy_write(struct phy_device *phydev, int devad, int regnum, u16 val)
> +{
> +	struct mii_dev *bus = phydev->bus;
> +
> +	return bus->write(bus, phydev->addr, devad, regnum, val);
> +}

seems like it'd make sense for these to be inlines in the phy header

> +static struct phy_driver gen10g_driver = {
> +	.uid		= 0xffffffff,
> +	.mask		= 0xffffffff,
> +	.name		= "Generic 10G PHY",
> +	.features	= 0,
> +	.config		= gen10g_config,
> +	.startup	= gen10g_startup,
> +	.shutdown	= gen10g_shutdown,
> +};

this probably should be split out into a dedicated phy driver.  you might care 
about it, but i cant think of any board atm where i would use this.  i imagine 
for most people, it's simply useless bloat.

> +static struct phy_driver genphy_driver = {
> +	.uid		= 0xffffffff,
> +	.mask		= 0xffffffff,
> +	.name		= "Generic PHY",
> +	.features	= 0,
> +	.config		= genphy_config,
> +	.startup	= genphy_startup,
> +	.shutdown	= genphy_shutdown,
> +};

i think this should be split too for the board maintainers who know exactly 
why phy they're going to have in their system.

> +static struct list_head phy_drivers;
> +
> +int phy_init(void)
> +{
> +	INIT_LIST_HEAD(&phy_drivers);
> +
> +	return 0;
> +}

isnt there a macro for declaring/initializing a list structure statically ?  
then we could avoid this useless phy_init() call.

> +/* Indicates what features are supported by the interface. */
> +#define SUPPORTED_10baseT_Half		(1 << 0)
> +#define SUPPORTED_10baseT_Full		(1 << 1)
> +#define SUPPORTED_100baseT_Half		(1 << 2)

this stuff looks suspiciously like it was copy & pasted from linux/ethtool.h.  
why not just copy the file over instead of creating your own custom variant ?
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20110406/05ece4d6/attachment.pgp 

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [U-Boot] [PATCH v2 4/6] Create PHY Lib for U-Boot
  2011-04-05 21:59       ` [U-Boot] [PATCH v2 4/6] Create PHY Lib for U-Boot Andy Fleming
                           ` (2 preceding siblings ...)
  2011-04-06 23:09         ` Mike Frysinger
@ 2011-04-07  4:43         ` Wolfgang Denk
  2011-04-07  4:47           ` Mike Frysinger
  2011-04-07  5:19         ` Wolfgang Denk
  4 siblings, 1 reply; 27+ messages in thread
From: Wolfgang Denk @ 2011-04-07  4:43 UTC (permalink / raw)
  To: u-boot

Dear Andy Fleming,

In message <1302040794-19837-5-git-send-email-afleming@freescale.com> you wrote:
> Extends the mii_dev structure to participate in a full-blown MDIO and
> PHY driver scheme.  The mii_dev structure and miiphy calls are modified
> in such a way to allow the original mii command and miiphy
> infrastructure to work as before, but also to support a new set of APIs
> which allow (among other things) sharing of PHY driver code and 10G support
...
> +#define SUPPORTED_10baseT_Half		(1 << 0)
> +#define SUPPORTED_10baseT_Full		(1 << 1)
> +#define SUPPORTED_100baseT_Half		(1 << 2)
> +#define SUPPORTED_100baseT_Full		(1 << 3)
> +#define SUPPORTED_1000baseT_Half	(1 << 4)
> +#define SUPPORTED_1000baseT_Full	(1 << 5)
> +#define SUPPORTED_Autoneg		(1 << 6)
> +#define SUPPORTED_TP			(1 << 7)
> +#define SUPPORTED_AUI			(1 << 8)
> +#define SUPPORTED_MII			(1 << 9)
> +#define SUPPORTED_FIBRE			(1 << 10)
> +#define SUPPORTED_BNC			(1 << 11)
> +#define SUPPORTED_10000baseT_Full	(1 << 12)
> +#define SUPPORTED_Pause			(1 << 13)
> +#define SUPPORTED_Asym_Pause		(1 << 14)
> +#define SUPPORTED_2500baseX_Full	(1 << 15)
> +#define SUPPORTED_Backplane		(1 << 16)
> +#define SUPPORTED_1000baseKX_Full	(1 << 17)
> +#define SUPPORTED_10000baseKX4_Full	(1 << 18)
> +#define SUPPORTED_10000baseKR_Full	(1 << 19)
> +#define SUPPORTED_10000baseR_FEC	(1 << 20)

We don't allow for CamelCaps identifiers or macro names. Macros are
all caps, please.  Please fix globally.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
Of all the things I've lost, I miss my mind the most.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [U-Boot] [PATCH v2 4/6] Create PHY Lib for U-Boot
  2011-04-07  4:43         ` Wolfgang Denk
@ 2011-04-07  4:47           ` Mike Frysinger
  2011-04-07  7:12             ` Wolfgang Denk
  0 siblings, 1 reply; 27+ messages in thread
From: Mike Frysinger @ 2011-04-07  4:47 UTC (permalink / raw)
  To: u-boot

On Thursday, April 07, 2011 00:43:44 Wolfgang Denk wrote:
> Andy Fleming wrote:
> > +#define SUPPORTED_10baseT_Half		(1 << 0)
> > +#define SUPPORTED_10baseT_Full		(1 << 1)
> > +#define SUPPORTED_100baseT_Half		(1 << 2)
> > +#define SUPPORTED_100baseT_Full		(1 << 3)
> > +#define SUPPORTED_1000baseT_Half	(1 << 4)
> > +#define SUPPORTED_1000baseT_Full	(1 << 5)
> > +#define SUPPORTED_Autoneg		(1 << 6)
> > +#define SUPPORTED_TP			(1 << 7)
> > +#define SUPPORTED_AUI			(1 << 8)
> > +#define SUPPORTED_MII			(1 << 9)
> > +#define SUPPORTED_FIBRE			(1 << 10)
> > +#define SUPPORTED_BNC			(1 << 11)
> > +#define SUPPORTED_10000baseT_Full	(1 << 12)
> > +#define SUPPORTED_Pause			(1 << 13)
> > +#define SUPPORTED_Asym_Pause		(1 << 14)
> > +#define SUPPORTED_2500baseX_Full	(1 << 15)
> > +#define SUPPORTED_Backplane		(1 << 16)
> > +#define SUPPORTED_1000baseKX_Full	(1 << 17)
> > +#define SUPPORTED_10000baseKX4_Full	(1 << 18)
> > +#define SUPPORTED_10000baseKR_Full	(1 << 19)
> > +#define SUPPORTED_10000baseR_FEC	(1 << 20)
> 
> We don't allow for CamelCaps identifiers or macro names. Macros are
> all caps, please.  Please fix globally.

these are taken straight from Linux which makes code sharing a lot easier
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20110407/8db57cf3/attachment.pgp 

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [U-Boot] [PATCH v2 4/6] Create PHY Lib for U-Boot
  2011-04-05 21:59       ` [U-Boot] [PATCH v2 4/6] Create PHY Lib for U-Boot Andy Fleming
                           ` (3 preceding siblings ...)
  2011-04-07  4:43         ` Wolfgang Denk
@ 2011-04-07  5:19         ` Wolfgang Denk
  4 siblings, 0 replies; 27+ messages in thread
From: Wolfgang Denk @ 2011-04-07  5:19 UTC (permalink / raw)
  To: u-boot

Dear Andy Fleming,

In message <1302040794-19837-5-git-send-email-afleming@freescale.com> you wrote:
> Extends the mii_dev structure to participate in a full-blown MDIO and
> PHY driver scheme.  The mii_dev structure and miiphy calls are modified
> in such a way to allow the original mii command and miiphy
> infrastructure to work as before, but also to support a new set of APIs
> which allow (among other things) sharing of PHY driver code and 10G support
...
> The basic design is similar to PHY Lib from Linux, but simplified for
> U-Boot's network and driver infrastructure.

Did you copy any actual code?  If so, please make sure to identify the
exact origin; see
http://www.denx.de/wiki/view/U-Boot/Patches#Attributing_Code_Copyrights_Sign

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Intuition, however illogical, is recognized as a command prerogative.
	-- Kirk, "Obsession", stardate 3620.7

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [U-Boot] [PATCH v2 4/6] Create PHY Lib for U-Boot
  2011-04-07  4:47           ` Mike Frysinger
@ 2011-04-07  7:12             ` Wolfgang Denk
  0 siblings, 0 replies; 27+ messages in thread
From: Wolfgang Denk @ 2011-04-07  7:12 UTC (permalink / raw)
  To: u-boot

Dear Mike Frysinger,

In message <201104070047.28480.vapier@gentoo.org> you wrote:
>
> > We don't allow for CamelCaps identifiers or macro names. Macros are
> > all caps, please.  Please fix globally.
> 
> these are taken straight from Linux which makes code sharing a lot easier

I realized this later - but in this case the attribution is missing.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Nothing in progression can rest on its original plan. We may as  well
think  of  rocking  a grown man in the cradle of an infant.
- Edmund Burke

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [U-Boot] [PATCH v2 0/6] Universal PHY Infrastructure
  2011-04-06 12:07 ` [U-Boot] [PATCH v2 0/6] Universal PHY Infrastructure Detlev Zundel
@ 2011-04-07 14:13   ` Andy Fleming
  2011-04-07 19:43     ` Mike Frysinger
  0 siblings, 1 reply; 27+ messages in thread
From: Andy Fleming @ 2011-04-07 14:13 UTC (permalink / raw)
  To: u-boot


On Apr 6, 2011, at 7:07 AM, Detlev Zundel wrote:

> Hi Andy,
> 
>> This second version cleans up all checkpatch errors that I reasonably could,
>> and addresses most of the comments from the first round of reviews.
> 
>  WARNING: Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt
>  #1299: FILE: drivers/net/tsec.c:1740:
>  +static int tsec_send(struct eth_device *dev, volatile void *packet, int length)
> 
> Ah I see.  This is needed because include/net.h prescribes this as the
> interface.  Oh well, we should clean this up at some later point, so
> it's ok from my perspective to ignore this and at least stay consistent.
> 
>  WARNING: do not add new typedefs
>  #4271: FILE: include/phy.h:389:
>  +typedef enum {
> 
> I know that we have lots of typedefs, but we should not add new ones.
> Actually not using this typedef for an enum-type would make the sources
> easier for me to read as I don't have to do this extra lookup step.


True, but this typedef is in Linux the same way. It seemed sensible to keep them the same


> 
>  WARNING: do not add new typedefs
>  #6304: FILE: arch/powerpc/include/asm/fsl_enet.h:31:
>  +typedef struct tsec_mii_mng {
> 
> I'd also appreciate if you use "struct tsec_mii_mng" explicitely instead
> of adding another typedef.


Yeah, you're right.  I'll eliminate this one.

Andy

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [U-Boot] [PATCH v2 4/6] Create PHY Lib for U-Boot
  2011-04-06 23:09         ` Mike Frysinger
@ 2011-04-07 14:16           ` Andy Fleming
  2011-04-07 15:01             ` Wolfgang Denk
  2011-04-07 19:37             ` Mike Frysinger
  0 siblings, 2 replies; 27+ messages in thread
From: Andy Fleming @ 2011-04-07 14:16 UTC (permalink / raw)
  To: u-boot


On Apr 6, 2011, at 6:09 PM, Mike Frysinger wrote:

> On Tuesday, April 05, 2011 17:59:52 Andy Fleming wrote:
>> -#define debug(fmt,args...)	printf (fmt ,##args)
>> +#define debug(fmt, args...)	printf(fmt, ##args)
> 
> it'd be nice if all these unrelated formatting changes werent intermingled.  
> but i guess too hard for you to untangle now.  make it a pita to pick out what 
> are functional changes and what is pure noise.


A lot of that's due to checkpatch errors that hit on lines I changed, so I went through and changed all instances.


> 
>> +struct mii_dev *mdio_alloc(void)
>> +{
>> +	struct mii_dev *bus;
>> +
>> +	bus = malloc(sizeof(*bus));
>> +	if (!bus)
>> +		return bus;
>> +
>> +	memset(bus, 0, sizeof(*bus));
>> +
>> +	bus->name = malloc(MDIO_NAME_LEN);
> 
> considering the name len is hardcoded at build time, it'd be nice to inline 
> that into the struct itself to avoid having to do multiple mallocs.  but i 
> guess it might be hard to keep working with the legacy code ?  or maybe not if 
> you just grep the tree to make sure no one using legacy code has a name longer 
> than 31 bytes ...


Hmmm... I can go look, but it's really hard to make sure I've found all instances of ->name that are miiphy-related.


> 
>> +struct phy_device *mdio_phydev_for_ethname(const char *ethname)
>> ...
>> +			if ((!bus->phymap[i]) || (!bus->phymap[i]->dev))
> 
> useless paren around both expressions here
> 
>> --- /dev/null
>> +++ b/drivers/net/phy/phy.c
>> 
>> +int phy_read(struct phy_device *phydev, int devad, int regnum)
>> +{
>> +	struct mii_dev *bus = phydev->bus;
>> +
>> +	return bus->read(bus, phydev->addr, devad, regnum);
>> +}
>> +
>> +int phy_write(struct phy_device *phydev, int devad, int regnum, u16 val)
>> +{
>> +	struct mii_dev *bus = phydev->bus;
>> +
>> +	return bus->write(bus, phydev->addr, devad, regnum, val);
>> +}
> 
> seems like it'd make sense for these to be inlines in the phy header


Sure.


> 
>> +static struct phy_driver gen10g_driver = {
>> +	.uid		= 0xffffffff,
>> +	.mask		= 0xffffffff,
>> +	.name		= "Generic 10G PHY",
>> +	.features	= 0,
>> +	.config		= gen10g_config,
>> +	.startup	= gen10g_startup,
>> +	.shutdown	= gen10g_shutdown,
>> +};
> 
> this probably should be split out into a dedicated phy driver.  you might care 
> about it, but i cant think of any board atm where i would use this.  i imagine 
> for most people, it's simply useless bloat.
> 
>> +static struct phy_driver genphy_driver = {
>> +	.uid		= 0xffffffff,
>> +	.mask		= 0xffffffff,
>> +	.name		= "Generic PHY",
>> +	.features	= 0,
>> +	.config		= genphy_config,
>> +	.startup	= genphy_startup,
>> +	.shutdown	= genphy_shutdown,
>> +};
> 
> i think this should be split too for the board maintainers who know exactly 
> why phy they're going to have in their system.


Hmmm... I'm of two minds about this.  Admittedly, the 10G stuff is currently floating unused, and will only be slightly less so when I can get our 10G driver pushed out, but these drivers are meant to serve as the backstop for the driver detection process.  So I can see board authors eliminating the drivers because they've properly enabled the one driver they need, but I will need to rework the connect code to exit more cleanly if they did it wrong.

As a second note, if you look carefully at the follow-on driver code, you'll see that (for genphy, at least), it's not actually much bloat if you use most drivers.  The genphy_startup and genphy_shutdown functions are used all of the time by the drivers, as is genphy_config_aneg().

I also hope to add some more interesting generic 10G code at some point, which would make the 10G driver less bloaty as well.  Well, more bloated, but also more useful.  I can add a CONFIG which controls the existence of 10G support.  I'll take a look at what would be needed to cut out the generic drivers (via CONFIG option), but I suspect that all you'll save is the phy_driver struct, itself, plus the genphy_config() function.  The rest are needed by various PHY drivers.


> 
>> +static struct list_head phy_drivers;
>> +
>> +int phy_init(void)
>> +{
>> +	INIT_LIST_HEAD(&phy_drivers);
>> +
>> +	return 0;
>> +}
> 
> isnt there a macro for declaring/initializing a list structure statically ?  
> then we could avoid this useless phy_init() call.


This will do all of the driver initialization, it just looks useless in this patch.


> 
>> +/* Indicates what features are supported by the interface. */
>> +#define SUPPORTED_10baseT_Half		(1 << 0)
>> +#define SUPPORTED_10baseT_Full		(1 << 1)
>> +#define SUPPORTED_100baseT_Half		(1 << 2)
> 
> this stuff looks suspiciously like it was copy & pasted from linux/ethtool.h.  
> why not just copy the file over instead of creating your own custom variant ?

Well, I'm torn.  It is definitely copied.  But include/linux/ethtool.h is 796 lines, and I've copied less than 100 of them.  Most of the header is concerned with the ethtool command, which is definitely not appropriate for U-Boot.  I should add attribution, definitely.  Maybe what should be done is to take those PHY-specific bits, and move them to a separate header in Linux, and then copy *that* header to u-boot.  Perhaps just copy them into mii.h, which is already reflected in U-Boot?

Andy

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [U-Boot] [PATCH v2 4/6] Create PHY Lib for U-Boot
  2011-04-07 14:16           ` Andy Fleming
@ 2011-04-07 15:01             ` Wolfgang Denk
  2011-04-07 19:37             ` Mike Frysinger
  1 sibling, 0 replies; 27+ messages in thread
From: Wolfgang Denk @ 2011-04-07 15:01 UTC (permalink / raw)
  To: u-boot

Dear Andy Fleming,

In message <B06395E4-2CF2-4AF7-BC5B-BE74508B4D73@freescale.com> you wrote:
> 
> > it'd be nice if all these unrelated formatting changes werent > intermingled.  
> > but i guess too hard for you to untangle now.  make it a pita to pick > out what 
> > are functional changes and what is pure noise.
>
>
> A lot of that's due to checkpatch errors that hit on lines I changed, so > I went through and changed all instances.

This [cs]hould have done in some initial cleanup patch, then.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Worlds are conquered, galaxies destroyed -- but a woman is  always  a
woman.
	-- Kirk, "Conscience of the King", stardate unknown

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [U-Boot] [PATCH v2 4/6] Create PHY Lib for U-Boot
  2011-04-07 14:16           ` Andy Fleming
  2011-04-07 15:01             ` Wolfgang Denk
@ 2011-04-07 19:37             ` Mike Frysinger
  1 sibling, 0 replies; 27+ messages in thread
From: Mike Frysinger @ 2011-04-07 19:37 UTC (permalink / raw)
  To: u-boot

On Thu, Apr 7, 2011 at 10:16 AM, Andy Fleming wrote:
> On Apr 6, 2011, at 6:09 PM, Mike Frysinger wrote:
>> On Tuesday, April 05, 2011 17:59:52 Andy Fleming wrote:
>>> -#define debug(fmt,args...) ?printf (fmt ,##args)
>>> +#define debug(fmt, args...) printf(fmt, ##args)
>>
>> it'd be nice if all these unrelated formatting changes werent intermingled.
>> but i guess too hard for you to untangle now. ?make it a pita to pick out what
>> are functional changes and what is pure noise.
>
> A lot of that's due to checkpatch errors that hit on lines I changed, so I went through and changed all instances.

you should of course know that checkpatch is simply another tool.  it
does not get the final say on things.

however, you should still know that style issues in unrelated code
belongs in a sep changeset.  if you're changing the code anyways (by
moving/deleting/whatever), then that's one thing.  but this patch is
full of hunks where *only* style is mangled.

>>> +static struct phy_driver gen10g_driver = {
>>> + ? ?.uid ? ? ? ? ? ?= 0xffffffff,
>>> + ? ?.mask ? ? ? ? ? = 0xffffffff,
>>> + ? ?.name ? ? ? ? ? = "Generic 10G PHY",
>>> + ? ?.features ? ? ? = 0,
>>> + ? ?.config ? ? ? ? = gen10g_config,
>>> + ? ?.startup ? ? ? ?= gen10g_startup,
>>> + ? ?.shutdown ? ? ? = gen10g_shutdown,
>>> +};
>>
>> this probably should be split out into a dedicated phy driver. ?you might care
>> about it, but i cant think of any board atm where i would use this. ?i imagine
>> for most people, it's simply useless bloat.
>>
>>> +static struct phy_driver genphy_driver = {
>>> + ? ?.uid ? ? ? ? ? ?= 0xffffffff,
>>> + ? ?.mask ? ? ? ? ? = 0xffffffff,
>>> + ? ?.name ? ? ? ? ? = "Generic PHY",
>>> + ? ?.features ? ? ? = 0,
>>> + ? ?.config ? ? ? ? = genphy_config,
>>> + ? ?.startup ? ? ? ?= genphy_startup,
>>> + ? ?.shutdown ? ? ? = genphy_shutdown,
>>> +};
>>
>> i think this should be split too for the board maintainers who know exactly
>> why phy they're going to have in their system.
>
>
> Hmmm... I'm of two minds about this. ?Admittedly, the 10G stuff is currently floating unused, and will only be slightly less so when I can get our 10G driver pushed out, but these drivers are meant to serve as the backstop for the driver detection process. ?So I can see board authors eliminating the drivers because they've properly enabled the one driver they need, but I will need to rework the connect code to exit more cleanly if they did it wrong.
>
> As a second note, if you look carefully at the follow-on driver code, you'll see that (for genphy, at least), it's not actually much bloat if you use most drivers. ?The genphy_startup and genphy_shutdown functions are used all of the time by the drivers, as is genphy_config_aneg().
>
> I also hope to add some more interesting generic 10G code at some point, which would make the 10G driver less bloaty as well. ?Well, more bloated, but also more useful. ?I can add a CONFIG which controls the existence of 10G support. ?I'll take a look at what would be needed to cut out the generic drivers (via CONFIG option), but I suspect that all you'll save is the phy_driver struct, itself, plus the genphy_config() function. ?The rest are needed by various PHY drivers.

i can live with the genphy_driver always being there as a safety net
(plus that code gets re-used quite a bit by other phy drivers), but i
dont think the 10G for everyone makes sense.  even if there was a
driver in the tree that used it right now, it doesnt make sense to
force onto everyone.

i'd venture to say that even today, 1GB is not that common.  certainly
not to the degree that 100mbit is.

>>> +static struct list_head phy_drivers;
>>> +
>>> +int phy_init(void)
>>> +{
>>> + ? ?INIT_LIST_HEAD(&phy_drivers);
>>> +
>>> + ? ?return 0;
>>> +}
>>
>> isnt there a macro for declaring/initializing a list structure statically ?
>> then we could avoid this useless phy_init() call.
>
> This will do all of the driver initialization, it just looks useless in this patch.

true, but the INIT_LIST_HEAD() call would still be useless runtime
overhead.  since you need to allocate/zero the data anyways, right ?

>>> +/* Indicates what features are supported by the interface. */
>>> +#define SUPPORTED_10baseT_Half ? ? ? ? ? ? ?(1 << 0)
>>> +#define SUPPORTED_10baseT_Full ? ? ? ? ? ? ?(1 << 1)
>>> +#define SUPPORTED_100baseT_Half ? ? ? ? ? ? (1 << 2)
>>
>> this stuff looks suspiciously like it was copy & pasted from linux/ethtool.h.
>> why not just copy the file over instead of creating your own custom variant ?
>
> Well, I'm torn. ?It is definitely copied. ?But include/linux/ethtool.h is 796 lines, and I've copied less than 100 of them. ?Most of the header is concerned with the ethtool command, which is definitely not appropriate for U-Boot. ?I should add attribution, definitely. ?Maybe what should be done is to take those PHY-specific bits, and move them to a separate header in Linux, and then copy *that* header to u-boot. ?Perhaps just copy them into mii.h, which is already reflected in U-Boot?

no, i really would like to keep the structure mirrored.  copy the file
and rip out the stuff you dont want.  after having dealt with other
network related headers which took the approach you have here, i can
say that what i'm suggesting makes things a lot easier (at least for
me).

also, please fix your e-mailer to properly wrap long lines.
-mike

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [U-Boot] [PATCH v2 0/6] Universal PHY Infrastructure
  2011-04-07 14:13   ` Andy Fleming
@ 2011-04-07 19:43     ` Mike Frysinger
  2011-04-08 11:44       ` Detlev Zundel
  0 siblings, 1 reply; 27+ messages in thread
From: Mike Frysinger @ 2011-04-07 19:43 UTC (permalink / raw)
  To: u-boot

On Thu, Apr 7, 2011 at 10:13 AM, Andy Fleming wrote:
> On Apr 6, 2011, at 7:07 AM, Detlev Zundel wrote:
>>> This second version cleans up all checkpatch errors that I reasonably could,
>>> and addresses most of the comments from the first round of reviews.
>>
>> ?WARNING: Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt
>> ?#1299: FILE: drivers/net/tsec.c:1740:
>> ?+static int tsec_send(struct eth_device *dev, volatile void *packet, int length)
>>
>> Ah I see. ?This is needed because include/net.h prescribes this as the
>> interface. ?Oh well, we should clean this up at some later point, so
>> it's ok from my perspective to ignore this and at least stay consistent.
>>
>> ?WARNING: do not add new typedefs
>> ?#4271: FILE: include/phy.h:389:
>> ?+typedef enum {
>>
>> I know that we have lots of typedefs, but we should not add new ones.
>> Actually not using this typedef for an enum-type would make the sources
>> easier for me to read as I don't have to do this extra lookup step.
>
> True, but this typedef is in Linux the same way. It seemed sensible to keep them the same

agreed.  fwiw :p.
-mike

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [U-Boot] [PATCH v2 0/6] Universal PHY Infrastructure
  2011-04-07 19:43     ` Mike Frysinger
@ 2011-04-08 11:44       ` Detlev Zundel
  0 siblings, 0 replies; 27+ messages in thread
From: Detlev Zundel @ 2011-04-08 11:44 UTC (permalink / raw)
  To: u-boot

Hi,

> On Thu, Apr 7, 2011 at 10:13 AM, Andy Fleming wrote:
>> On Apr 6, 2011, at 7:07 AM, Detlev Zundel wrote:
>>>> This second version cleans up all checkpatch errors that I reasonably could,
>>>> and addresses most of the comments from the first round of reviews.
>>>
>>> ?WARNING: Use of volatile is usually wrong: see
>>> Documentation/volatile-considered-harmful.txt
>>> ?#1299: FILE: drivers/net/tsec.c:1740:
>>> ?+static int tsec_send(struct eth_device *dev, volatile void *packet, int length)
>>>
>>> Ah I see. ?This is needed because include/net.h prescribes this as the
>>> interface. ?Oh well, we should clean this up at some later point, so
>>> it's ok from my perspective to ignore this and at least stay consistent.
>>>
>>> ?WARNING: do not add new typedefs
>>> ?#4271: FILE: include/phy.h:389:
>>> ?+typedef enum {
>>>
>>> I know that we have lots of typedefs, but we should not add new ones.
>>> Actually not using this typedef for an enum-type would make the sources
>>> easier for me to read as I don't have to do this extra lookup step.
>>
>> True, but this typedef is in Linux the same way. It seemed sensible to keep them the same
>
> agreed.  fwiw :p.

I'm also fine with that.

Cheers
  Detlev

-- 
Warning: this comic occasionally contains strong language (which may be unsuit-
able for children), unusual humor (which may be unsuitable for adults), and ad-
vanced mathematics (which may be unsuitable for liberal-arts majors). /xkcd.org
--
DENX Software Engineering GmbH,      MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich,  Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-40 Fax: (+49)-8142-66989-80 Email: dzu at denx.de

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2011-04-08 11:44 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-04-05 21:59 [U-Boot] [PATCH v2 0/6] Universal PHY Infrastructure Andy Fleming
2011-04-05 21:59 ` [U-Boot] [PATCH v2 1/6] tsec: use IO accessors for IO accesses Andy Fleming
2011-04-05 21:59   ` [U-Boot] [PATCH v2 2/6] tsec: arrange the code to avoid useless function declaration Andy Fleming
2011-04-05 21:59     ` [U-Boot] [PATCH v2 3/6] Remove instances of phy_read/write Andy Fleming
2011-04-05 21:59       ` [U-Boot] [PATCH v2 4/6] Create PHY Lib for U-Boot Andy Fleming
2011-04-05 21:59         ` [U-Boot] [PATCH v2 5/6] phylib: Add a bunch of PHY drivers from tsec Andy Fleming
2011-04-05 21:59           ` [U-Boot] [PATCH v2 6/6] tsec: Convert tsec to use PHY Lib Andy Fleming
2011-04-06 13:02             ` Detlev Zundel
2011-04-06 13:01           ` [U-Boot] [PATCH v2 5/6] phylib: Add a bunch of PHY drivers from tsec Detlev Zundel
2011-04-06 22:50           ` Mike Frysinger
2011-04-06 12:56         ` [U-Boot] [PATCH v2 4/6] Create PHY Lib for U-Boot Detlev Zundel
2011-04-06 23:09         ` Mike Frysinger
2011-04-07 14:16           ` Andy Fleming
2011-04-07 15:01             ` Wolfgang Denk
2011-04-07 19:37             ` Mike Frysinger
2011-04-07  4:43         ` Wolfgang Denk
2011-04-07  4:47           ` Mike Frysinger
2011-04-07  7:12             ` Wolfgang Denk
2011-04-07  5:19         ` Wolfgang Denk
2011-04-06 12:32       ` [U-Boot] [PATCH v2 3/6] Remove instances of phy_read/write Detlev Zundel
2011-04-06 12:31     ` [U-Boot] [PATCH v2 2/6] tsec: arrange the code to avoid useless function declaration Detlev Zundel
2011-04-06 12:29   ` [U-Boot] [PATCH v2 1/6] tsec: use IO accessors for IO accesses Detlev Zundel
2011-04-06 12:32     ` Kumar Gala
2011-04-06 12:07 ` [U-Boot] [PATCH v2 0/6] Universal PHY Infrastructure Detlev Zundel
2011-04-07 14:13   ` Andy Fleming
2011-04-07 19:43     ` Mike Frysinger
2011-04-08 11:44       ` Detlev Zundel

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.