[U-Boot] [PATCH 6/7] phylib: Add a bunch of PHY drivers from tsec

Andy Fleming afleming at freescale.com
Tue Mar 29 21:30:09 CEST 2011


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.

Signed-off-by: Andy Fleming <afleming at freescale.com>
---
 drivers/net/phy/Makefile     |   10 ++
 drivers/net/phy/atheros.c    |   37 +++++
 drivers/net/phy/broadcom.c   |  275 ++++++++++++++++++++++++++++++++
 drivers/net/phy/davicom.c    |   86 ++++++++++
 drivers/net/phy/lxt.c        |   76 +++++++++
 drivers/net/phy/marvell.c    |  357 ++++++++++++++++++++++++++++++++++++++++++
 drivers/net/phy/micrel.c     |   29 ++++
 drivers/net/phy/natsemi.c    |   85 ++++++++++
 drivers/net/phy/phy.c        |   28 ++++
 drivers/net/phy/realtek.c    |  120 ++++++++++++++
 drivers/net/phy/teranetics.c |   43 +++++
 drivers/net/phy/vitesse.c    |  330 ++++++++++++++++++++++++++++++++++++++
 include/phy.h                |   11 ++
 include/phylib_all_drivers.h |   25 +++
 14 files changed, 1512 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..f67a79a 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -28,6 +28,16 @@ LIB	:= $(obj)libphy.o
 COBJS-$(CONFIG_BITBANGMII) += miiphybb.o
 COBJS-$(CONFIG_MV88E61XX_SWITCH) += mv88e61xx.o
 COBJS-$(CONFIG_PHYLIB) += phy.o
+COBJS-$(CONFIG_PHY_VITESSE) += vitesse.o
+COBJS-$(CONFIG_PHY_TERANETICS) += teranetics.o
+COBJS-$(CONFIG_PHY_MARVELL) += marvell.o
+COBJS-$(CONFIG_PHY_REALTEK) += realtek.o
+COBJS-$(CONFIG_PHY_BROADCOM) += broadcom.o
+COBJS-$(CONFIG_PHY_DAVICOM) += davicom.o
+COBJS-$(CONFIG_PHY_LXT) += lxt.o
+COBJS-$(CONFIG_PHY_NATSEMI) += natsemi.o
+COBJS-$(CONFIG_PHY_MICREL) += micrel.o
+COBJS-$(CONFIG_PHY_ATHEROS) += atheros.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..68bb5cd
--- /dev/null
+++ b/drivers/net/phy/atheros.c
@@ -0,0 +1,37 @@
+/*
+ * Atheros PHY drivers
+ *
+ * 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
+ *
+ */
+#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..e62a81d
--- /dev/null
+++ b/drivers/net/phy/broadcom.c
@@ -0,0 +1,275 @@
+/*
+ * Broadcom PHY drivers
+ *
+ * This software may be used and distributed according to the
+ * terms of the GNU Public License, Version 2, incorporated
+ * herein by reference.
+ *
+ * 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..229e1bd
--- /dev/null
+++ b/drivers/net/phy/davicom.c
@@ -0,0 +1,86 @@
+/*
+ * Davicom PHY drivers
+ *
+ * This software may be used and distributed according to the
+ * terms of the GNU Public License, Version 2, incorporated
+ * herein by reference.
+ *
+ * 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..4e38bb6
--- /dev/null
+++ b/drivers/net/phy/lxt.c
@@ -0,0 +1,76 @@
+/*
+ * LXT PHY drivers
+ *
+ * This software may be used and distributed according to the
+ * terms of the GNU Public License, Version 2, incorporated
+ * herein by reference.
+ *
+ * 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,
+	.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..6937c93
--- /dev/null
+++ b/drivers/net/phy/marvell.c
@@ -0,0 +1,357 @@
+/*
+ * Marvell PHY drivers
+ *
+ * This software may be used and distributed according to the
+ * terms of the GNU Public License, Version 2, incorporated
+ * herein by reference.
+ *
+ * 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_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
+
+/* 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 m88e1011s_parse_status(struct phy_device *phydev)
+{
+	unsigned int speed;
+	unsigned int mii_reg;
+
+	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, 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");
+				phydev->link = 0;
+				break;
+			}
+
+			if ((i++ % 1000) == 0) {
+				putc('.');
+			}
+			udelay(1000);
+			mii_reg = phy_read(phydev, MDIO_DEVAD_NONE,
+					MIIM_88E1011_PHY_STATUS);
+		}
+		puts(" done\n");
+		udelay(500000);	/* another 500 ms (results in faster booting) */
+	} else {
+		if (mii_reg & MIIM_88E1011_PHYSTAT_LINK)
+			phydev->link = 1;
+		else
+			phydev->link = 0;
+	}
+
+	if (mii_reg & MIIM_88E1011_PHYSTAT_DUPLEX)
+		phydev->duplex = DUPLEX_FULL;
+	else
+		phydev->duplex = DUPLEX_HALF;
+
+	speed = mii_reg & MIIM_88E1011_PHYSTAT_SPEED;
+
+	switch (speed) {
+	case MIIM_88E1011_PHYSTAT_GBIT:
+		phydev->speed = SPEED_1000;
+		break;
+	case MIIM_88E1011_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);
+	m88e1011s_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, 0x16, 0x0002);
+	/* Delay RGMII TX and RX */
+	phy_write(phydev, MDIO_DEVAD_NONE, 0x15, 0x1070);
+	/* Change Page Number */
+	phy_write(phydev, MDIO_DEVAD_NONE, 0x16, 0x0003);
+	/* Adjust LED control */
+	phy_write(phydev, MDIO_DEVAD_NONE, 0x10, 0x021e);
+	/* Change Page Number */
+	phy_write(phydev, MDIO_DEVAD_NONE, 0x16, 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, 0x16, 0x0000);
+
+	genphy_update_link(phydev);
+	m88e1011s_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, 29, 0x001b);
+	phy_write(phydev, MDIO_DEVAD_NONE, 30, 0x418f);
+	phy_write(phydev, MDIO_DEVAD_NONE, 29, 0x0016);
+	phy_write(phydev, MDIO_DEVAD_NONE, 30, 0xa2da);
+
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1011_PHY_SCR,
+			MIIM_88E1011_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_88E1111_PHY_LED_CONTROL,
+			MIIM_88E1111_PHY_LED_DIRECT);
+	m88e1011s_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, 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, 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..4e0389a
--- /dev/null
+++ b/drivers/net/phy/micrel.c
@@ -0,0 +1,29 @@
+/*
+ * Micrel PHY drivers
+ *
+ * This software may be used and distributed according to the
+ * terms of the GNU Public License, Version 2, incorporated
+ * herein by reference.
+ *
+ * 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..a669eac
--- /dev/null
+++ b/drivers/net/phy/natsemi.c
@@ -0,0 +1,85 @@
+/*
+ * National Semiconductor PHY drivers
+ *
+ * This software may be used and distributed according to the
+ * terms of the GNU Public License, Version 2, incorporated
+ * herein by reference.
+ *
+ * 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 ca35404..50e85fe 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -494,6 +494,34 @@ int phy_init(void)
 {
 	INIT_LIST_HEAD(&phy_drivers);
 
+#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_VITESSE
+	vitesse_init();
+#endif
+#ifdef CONFIG_PHY_ATHEROS
+	atheros_init();
+#endif
+
 	return 0;
 }
 
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
new file mode 100644
index 0000000..8cb696f
--- /dev/null
+++ b/drivers/net/phy/realtek.c
@@ -0,0 +1,120 @@
+/*
+ * RealTek PHY drivers
+ *
+ * This software may be used and distributed according to the
+ * terms of the GNU Public License, Version 2, incorporated
+ * herein by reference.
+ *
+ * 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..387e044
--- /dev/null
+++ b/drivers/net/phy/teranetics.c
@@ -0,0 +1,43 @@
+/*
+ * Teranetics PHY drivers
+ *
+ * This software may be used and distributed according to the
+ * terms of the GNU Public License, Version 2, incorporated
+ * herein by reference.
+ *
+ * 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..d34f04b
--- /dev/null
+++ b/drivers/net/phy/vitesse.c
@@ -0,0 +1,330 @@
+/*
+ * Vitesse PHY drivers
+ *
+ * This software may be used and distributed according to the
+ * terms of the GNU Public License, Version 2, incorporated
+ * herein by reference.
+ *
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ * author Andy Fleming
+ *
+ */
+#include <miiphy.h>
+
+/* 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
+
+/* 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 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 cis8201_config(struct phy_device *phydev)
+{
+	/* Override PHY config settings */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8201_AUX_CONSTAT,
+			MIIM_CIS8201_AUXCONSTAT_INIT);
+	/* Set up the interface mode */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8201_EXT_CON1,
+			MIIM_CIS8201_EXTCON1_INIT);
+
+	genphy_config_aneg(phydev);
+
+	return 0;
+}
+
+static int cis8201_parse_status(struct phy_device *phydev)
+{
+	int speed;
+	int mii_reg;
+
+	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_CIS8201_AUX_CONSTAT);
+
+	if (mii_reg & MIIM_CIS8201_AUXCONSTAT_DUPLEX)
+		phydev->duplex = DUPLEX_FULL;
+	else
+		phydev->duplex = DUPLEX_HALF;
+
+	speed = mii_reg & MIIM_CIS8201_AUXCONSTAT_SPEED;
+	switch (speed) {
+	case MIIM_CIS8201_AUXCONSTAT_GBIT:
+		phydev->speed = SPEED_1000;
+		break;
+	case MIIM_CIS8201_AUXCONSTAT_100:
+		phydev->speed = SPEED_100;
+		break;
+	default:
+		phydev->speed = SPEED_10;
+		break;
+	}
+
+	return 0;
+}
+
+static int cis8201_startup(struct phy_device *phydev)
+{
+	genphy_update_link(phydev);
+	cis8201_parse_status(phydev);
+
+	return 0;
+}
+
+static int cis8204_config(struct phy_device *phydev)
+{
+	/* Override PHY config settings */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8201_AUX_CONSTAT,
+			MIIM_CIS8201_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 VSC8211 */
+static int vsc8211_config(struct phy_device *phydev)
+{
+	/* Override PHY config settings */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8201_AUX_CONSTAT,
+			MIIM_CIS8201_AUXCONSTAT_INIT);
+	/* Set up the interface mode */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8201_EXT_CON1,
+			MIIM_CIS8201_EXTCON1_INIT);
+
+	genphy_config_aneg(phydev);
+
+	return 0;
+}
+
+static int vsc8211_parse_status(struct phy_device *phydev)
+{
+	unsigned int speed;
+	unsigned int mii_reg;
+
+	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_CIS8201_AUX_CONSTAT);
+
+	if (mii_reg & MIIM_CIS8201_AUXCONSTAT_DUPLEX)
+		phydev->duplex = DUPLEX_FULL;
+	else
+		phydev->duplex = DUPLEX_HALF;
+
+	speed = mii_reg & MIIM_CIS8201_AUXCONSTAT_SPEED;
+	switch (speed) {
+	case MIIM_CIS8201_AUXCONSTAT_GBIT:
+		phydev->speed = SPEED_1000;
+		break;
+	case MIIM_CIS8201_AUXCONSTAT_100:
+		phydev->speed = SPEED_100;
+		break;
+	default:
+		phydev->speed = SPEED_10;
+		break;
+	}
+
+	return 0;
+}
+
+static int vsc8211_startup(struct phy_device *phydev)
+{
+	/* Read the Status (2x to make sure link is right) */
+	genphy_update_link(phydev);
+	vsc8211_parse_status(phydev);
+
+	return 0;
+}
+
+/* Vitesse VSC8244 */
+static int vsc8244_parse_status(struct phy_device *phydev)
+{
+	unsigned int speed;
+	unsigned int mii_reg;
+
+	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8244_AUX_CONSTAT);
+
+	if (mii_reg & MIIM_VSC8244_AUXCONSTAT_DUPLEX)
+		phydev->duplex = DUPLEX_FULL;
+	else
+		phydev->duplex = DUPLEX_HALF;
+
+	speed = mii_reg & MIIM_VSC8244_AUXCONSTAT_SPEED;
+	switch (speed) {
+	case MIIM_VSC8244_AUXCONSTAT_GBIT:
+		phydev->speed = SPEED_1000;
+		break;
+	case MIIM_VSC8244_AUXCONSTAT_100:
+		phydev->speed = SPEED_100;
+		break;
+	default:
+		phydev->speed = SPEED_10;
+		break;
+	}
+
+	return 0;
+}
+
+static int vsc8244_startup(struct phy_device *phydev)
+{
+	/* Read the Status (2x to make sure link is right) */
+	genphy_update_link(phydev);
+	vsc8244_parse_status(phydev);
+
+	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 = &vsc8211_config,
+	.startup = &vsc8211_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+static struct phy_driver VSC8221_driver = {
+	.name = "Vitesse VSC8221",
+	.uid = 0xfc550,
+	.mask = 0xffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &genphy_config,
+	.startup = &vsc8244_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+static struct phy_driver VSC8244_driver = {
+	.name = "Vitesse VSC8244",
+	.uid = 0xfc6c0,
+	.mask = 0xffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &genphy_config,
+	.startup = &vsc8244_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+static struct phy_driver VSC8234_driver = {
+	.name = "Vitesse VSC8234",
+	.uid = 0xfc620,
+	.mask = 0xffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &genphy_config,
+	.startup = &vsc8244_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 = &vsc8244_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+static struct phy_driver VSC8641_driver = {
+	.name = "Vitesse VSC8641",
+	.uid = 0x70430,
+	.mask = 0xffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &genphy_config,
+	.startup = &vsc8244_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 = &cis8201_config,
+	.startup = &cis8201_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 = &cis8201_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 fccf1f7..54b5663 100644
--- a/include/phy.h
+++ b/include/phy.h
@@ -484,4 +484,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 teranetics_init(void);
+int vitesse_init(void);
+int marvell_init(void);
+int davicom_init(void);
+int realtek_init(void);
+int micrel_init(void);
+int natsemi_init(void);
+int broadcom_init(void);
+int lxt_init(void);
+int atheros_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




More information about the U-Boot mailing list