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 <aflem...@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@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@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@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


_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to