Merge branch 'phylib' of git://git.denx.de/u-boot-mmc
authorWolfgang Denk <wd@denx.de>
Wed, 20 Apr 2011 21:01:52 +0000 (23:01 +0200)
committerWolfgang Denk <wd@denx.de>
Wed, 20 Apr 2011 21:01:52 +0000 (23:01 +0200)
52 files changed:
arch/powerpc/cpu/mpc8xxx/fdt.c
arch/powerpc/include/asm/config.h
arch/powerpc/include/asm/fsl_enet.h
board/freescale/mpc8360emds/mpc8360emds.c
board/freescale/mpc837xemds/mpc837xemds.c
board/freescale/mpc8536ds/mpc8536ds.c
board/freescale/mpc8544ds/mpc8544ds.c
board/freescale/mpc8569mds/mpc8569mds.c
board/freescale/mpc8572ds/mpc8572ds.c
board/freescale/p1022ds/p1022ds.c
board/freescale/p1_p2_rdb/p1_p2_rdb.c
board/freescale/p2020ds/p2020ds.c
common/Makefile
common/cmd_mdio.c [new file with mode: 0644]
common/miiphyutil.c
drivers/net/Makefile
drivers/net/dm9000x.c
drivers/net/enc28j60.c
drivers/net/fsl_mdio.c [new file with mode: 0644]
drivers/net/phy/Makefile
drivers/net/phy/atheros.c [new file with mode: 0644]
drivers/net/phy/broadcom.c [new file with mode: 0644]
drivers/net/phy/davicom.c [new file with mode: 0644]
drivers/net/phy/generic_10g.c [new file with mode: 0644]
drivers/net/phy/lxt.c [new file with mode: 0644]
drivers/net/phy/marvell.c [new file with mode: 0644]
drivers/net/phy/micrel.c [new file with mode: 0644]
drivers/net/phy/natsemi.c [new file with mode: 0644]
drivers/net/phy/phy.c [new file with mode: 0644]
drivers/net/phy/realtek.c [new file with mode: 0644]
drivers/net/phy/teranetics.c [new file with mode: 0644]
drivers/net/phy/vitesse.c [new file with mode: 0644]
drivers/net/tsec.c
drivers/net/uli526x.c
drivers/qe/uec.c
drivers/qe/uec.h
drivers/qe/uec_phy.c
include/config_phylib_all_drivers.h [new file with mode: 0644]
include/configs/MPC8323ERDB.h
include/configs/MPC832XEMDS.h
include/configs/MPC8360EMDS.h
include/configs/MPC8360ERDK.h
include/configs/MPC8568MDS.h
include/configs/MPC8569MDS.h
include/configs/kmeter1.h
include/fsl_mdio.h [new file with mode: 0644]
include/linux/ethtool.h [new file with mode: 0644]
include/linux/mdio.h [new file with mode: 0644]
include/miiphy.h
include/phy.h [new file with mode: 0644]
include/tsec.h
net/eth.c

index 0c166fd6c9c53432d641179d9ad4e4f1e9e12a3c..520cb90280967f5fa349c8f356aba3080f70ca61 100644 (file)
@@ -27,8 +27,8 @@
 #include <libfdt.h>
 #include <fdt_support.h>
 #include <asm/mp.h>
-#include <asm/fsl_enet.h>
 #include <asm/fsl_serdes.h>
+#include <phy.h>
 
 #if defined(CONFIG_MP) && (defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx))
 static int ft_del_cpuhandle(void *blob, int cpuhandle)
@@ -218,27 +218,10 @@ void fdt_fixup_crypto_node(void *blob, int sec_rev)
 }
 #endif
 
-int fdt_fixup_phy_connection(void *blob, int offset, enum fsl_phy_enet_if phyc)
+int fdt_fixup_phy_connection(void *blob, int offset, phy_interface_t phyc)
 {
-       static const char *fsl_phy_enet_if_str[] = {
-               [MII]           = "mii",
-               [RMII]          = "rmii",
-               [GMII]          = "gmii",
-               [RGMII]         = "rgmii",
-               [RGMII_ID]      = "rgmii-id",
-               [RGMII_RXID]    = "rgmii-rxid",
-               [SGMII]         = "sgmii",
-               [TBI]           = "tbi",
-               [RTBI]          = "rtbi",
-               [XAUI]          = "xgmii",
-               [FSL_ETH_IF_NONE] = "",
-       };
-
-       if (phyc > ARRAY_SIZE(fsl_phy_enet_if_str))
-               return fdt_setprop_string(blob, offset, "phy-connection-type", "");
-
        return fdt_setprop_string(blob, offset, "phy-connection-type",
-                                        fsl_phy_enet_if_str[phyc]);
+                                        phy_string_for_interface(phyc));
 }
 
 #ifdef CONFIG_SYS_SRIO
index 536f1423313aa0920d90bd85bcbdabd7ee196e73..624d8c2cc0477715433e4cdffd0e0ab4ee4123fd 100644 (file)
 #endif
 #endif
 
+/* The TSEC driver uses the PHYLIB infrastructure */
+#ifndef CONFIG_PHYLIB
+#if defined(CONFIG_TSEC_ENET)
+#define CONFIG_PHYLIB
+
+#include <config_phylib_all_drivers.h>
+#endif /* TSEC_ENET */
+#endif /* !CONFIG_PHYLIB */
+
 /* All PPC boards must swap IDE bytes */
 #define CONFIG_IDE_SWAP_IO
 
index 4fb2857f3e56fc8a6fc9c595f103639903718519..8227b667cb3561b345ff722c39194ad88aafef9b 100644 (file)
 #ifndef __ASM_PPC_FSL_ENET_H
 #define __ASM_PPC_FSL_ENET_H
 
-enum fsl_phy_enet_if {
-       MII,
-       RMII,
-       GMII,
-       RGMII,
-       RGMII_ID,
-       RGMII_RXID,
-       RGMII_TXID,
-       SGMII,
-       TBI,
-       RTBI,
-       XAUI,
-       FSL_ETH_IF_NONE,
-};
+#include <phy.h>
 
-int fdt_fixup_phy_connection(void *blob, int offset, enum fsl_phy_enet_if phyc);
+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));
+
+int fdt_fixup_phy_connection(void *blob, int offset, phy_interface_t phyc);
 
 #endif /* __ASM_PPC_FSL_ENET_H */
index 0babd2648afce1f0661e9d8c86238a3dfce8e493..51d8035203fec240e0e247e28fdbea977f47dd65 100644 (file)
@@ -16,6 +16,7 @@
 #include <mpc83xx.h>
 #include <i2c.h>
 #include <miiphy.h>
+#include <phy.h>
 #if defined(CONFIG_PCI)
 #include <pci.h>
 #endif
@@ -160,8 +161,9 @@ int board_eth_init(bd_t *bd)
                int i;
 
                for (i = 0; i < ARRAY_SIZE(uec_info); i++)
-                       uec_info[i].enet_interface_type = RGMII_RXID;
-                       uec_info[i].speed = 1000;
+                       uec_info[i].enet_interface_type =
+                               PHY_INTERFACE_MODE_RGMII_RXID;
+                       uec_info[i].speed = SPEED_1000;
        }
        return uec_eth_init(bd, uec_info, ARRAY_SIZE(uec_info));
 }
@@ -398,7 +400,7 @@ void ft_board_setup(void *blob, bd_t *bd)
                                                   "phy-connection-type", 0);
                                if (prop && (strcmp(prop, "rgmii-id") == 0))
                                        fdt_fixup_phy_connection(blob, path,
-                                                               RGMII_RXID);
+                                               PHY_INTERFACE_MODE_RGMII_RXID);
                        }
 #endif
 #if defined(CONFIG_HAS_ETH1)
@@ -410,7 +412,7 @@ void ft_board_setup(void *blob, bd_t *bd)
                                                   "phy-connection-type", 0);
                                if (prop && (strcmp(prop, "rgmii-id") == 0))
                                        fdt_fixup_phy_connection(blob, path,
-                                                               RGMII_RXID);
+                                               PHY_INTERFACE_MODE_RGMII_RXID);
                        }
 #endif
                }
index 51dd692c2e41b93b8e17ce7e3cecacd44c8cbd7b..650a4fe483955740d5d67ee65479e0ac5d984324 100644 (file)
@@ -21,6 +21,8 @@
 #include <libfdt.h>
 #include <fdt_support.h>
 #include <fsl_esdhc.h>
+#include <fsl_mdio.h>
+#include <phy.h>
 #include "pci.h"
 #include "../common/pq-mds-pib.h"
 
@@ -86,6 +88,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 +134,11 @@ int board_eth_init(bd_t *bd)
        }
        num++;
 #endif
+
+       mdio_info.regs = (struct tsec_mii_mng *)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);
 }
 
@@ -148,7 +156,7 @@ static void __ft_tsec_fixup(void *blob, bd_t *bd, const char *alias,
                return;
        }
 
-       err = fdt_fixup_phy_connection(blob, off, SGMII);
+       err = fdt_fixup_phy_connection(blob, off, PHY_INTERFACE_MODE_SGMII);
 
        if (err) {
                printf("WARNING: could not set phy-connection-type for %s: "
index f83f629d4689584714352f4a1022a0a7fa6ab792..b292e1354187f0fa51df9e93dd88bea0c4ee00a0 100644 (file)
@@ -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 = (struct tsec_mii_mng *)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);
index a48c8155c5086be73a23cea3785ed67fa6727566..6fe8d3963214cf538228f2960545343fae51820b 100644 (file)
@@ -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 = (struct tsec_mii_mng *)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
index ecda2229902dd7b863ac23fbf4370cff05c91479..89557d221f99895e65c0012464602d9f1a346453 100644 (file)
@@ -39,6 +39,7 @@
 #include <libfdt.h>
 #include <fdt_support.h>
 #include <fsl_esdhc.h>
+#include <phy.h>
 
 #include "bcsr.h"
 #if defined(CONFIG_PQ_MDS_PIB)
@@ -550,7 +551,8 @@ void ft_board_setup(void *blob, bd_t *bd)
                        break;
                }
 
-               err = fdt_fixup_phy_connection(blob, nodeoff, RMII);
+               err = fdt_fixup_phy_connection(blob, nodeoff,
+                               PHY_INTERFACE_MODE_RMII);
 
                if (err < 0) {
                        printf("WARNING: could not set phy-connection-type "
index f444805a4d3f95f963df65f85501bfdd794d0613..b20299e36f678ec94a8a69ffb56623d976f0ccd8 100644 (file)
@@ -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 = (struct tsec_mii_mng *)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);
index 8b78404b85d2ae04c5aa031decf4fd88288fb93b..73a10213be920cc5a7273bcfb94a894b858ed24e 100644 (file)
@@ -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>
@@ -279,6 +280,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;
 
@@ -291,6 +293,10 @@ int board_eth_init(bd_t *bis)
        num++;
 #endif
 
+       mdio_info.regs = (struct tsec_mii_mng *)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);
 }
 
index 307c3e2564d9182492573e1a7c63559f3fe8f75c..0b4ae9d7fd03211a1e4959f7bc83c8f495a8040e 100644 (file)
@@ -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 = (struct tsec_mii_mng *)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);
index 238b4d925c18a864d23deeda388afcd966863a15..d3af6cf185167e3fc4af9b76f38d1ff1291b349d 100644 (file)
@@ -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 = (struct tsec_mii_mng *)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);
index 4fb050eb58e235787a5f4fc6c741a51a456f153a..f81cff93c973309bdfcedab9a54acaed8add2f68 100644 (file)
@@ -117,7 +117,11 @@ 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
+ifdef CONFIG_PHYLIB
+COBJS-$(CONFIG_CMD_MII) += cmd_mdio.o
+endif
 COBJS-$(CONFIG_CMD_MISC) += cmd_misc.o
 COBJS-$(CONFIG_CMD_MMC) += cmd_mmc.o
 COBJS-$(CONFIG_CMD_MMC_SPI) += cmd_mmc_spi.o
diff --git a/common/cmd_mdio.c b/common/cmd_mdio.c
new file mode 100644 (file)
index 0000000..cac0703
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+ * (C) Copyright 2011 Freescale Semiconductor, Inc
+ * Andy Fleming
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * MDIO Commands
+ */
+
+#include <common.h>
+#include <command.h>
+#include <miiphy.h>
+#include <phy.h>
+
+
+static char last_op[2];
+static uint last_data;
+static uint last_addr_lo;
+static uint last_addr_hi;
+static uint last_devad_lo;
+static uint last_devad_hi;
+static uint last_reg_lo;
+static uint last_reg_hi;
+
+static int extract_range(char *input, int *plo, int *phi)
+{
+       char *end;
+       *plo = simple_strtol(input, &end, 0);
+       if (end == input)
+               return -1;
+
+       if ((*end == '-') && *(++end))
+               *phi = simple_strtol(end, NULL, 0);
+       else if (*end == '\0')
+               *phi = *plo;
+       else
+               return -1;
+
+       return 0;
+}
+
+int mdio_write_ranges(struct mii_dev *bus, int addrlo,
+                       int addrhi, int devadlo, int devadhi,
+                       int reglo, int reghi, unsigned short data)
+{
+       int addr, devad, reg;
+       int err = 0;
+
+       for (addr = addrlo; addr <= addrhi; addr++) {
+               for (devad = devadlo; devad <= devadhi; devad++) {
+                       for (reg = reglo; reg <= reghi; reg++) {
+                               err = bus->write(bus, addr, devad, reg, data);
+
+                               if (err)
+                                       goto err_out;
+                       }
+               }
+       }
+
+err_out:
+       return err;
+}
+
+int mdio_read_ranges(struct mii_dev *bus, int addrlo,
+                       int addrhi, int devadlo, int devadhi,
+                       int reglo, int reghi)
+{
+       int addr, devad, reg;
+
+       printf("Reading from bus %s\n", bus->name);
+       for (addr = addrlo; addr <= addrhi; addr++) {
+               printf("PHY at address %d:\n", addr);
+
+               for (devad = devadlo; devad <= devadhi; devad++) {
+                       for (reg = reglo; reg <= reghi; reg++) {
+                               u16 val;
+                               val = bus->read(bus, addr, devad, reg);
+
+                               if (val < 0) {
+                                       printf("Error\n");
+
+                                       return val;
+                               }
+
+                               if (devad >= 0)
+                                       printf("%d.", devad);
+
+                               printf("%d - 0x%x\n", reg, val & 0xffff);
+                       }
+               }
+       }
+
+       return 0;
+}
+
+/* The register will be in the form [a[-b].]x[-y] */
+int extract_reg_range(char *input, int *devadlo, int *devadhi,
+               int *reglo, int *reghi)
+{
+       char *regstr;
+
+       /* use strrchr to find the last string after a '.' */
+       regstr = strrchr(input, '.');
+
+       /* If it exists, extract the devad(s) */
+       if (regstr) {
+               char devadstr[32];
+
+               strncpy(devadstr, input, regstr - input);
+               devadstr[regstr - input] = '\0';
+
+               if (extract_range(devadstr, devadlo, devadhi))
+                       return -1;
+
+               regstr++;
+       } else {
+               /* Otherwise, we have no devad, and we just got regs */
+               *devadlo = *devadhi = MDIO_DEVAD_NONE;
+
+               regstr = input;
+       }
+
+       return extract_range(regstr, reglo, reghi);
+}
+
+int extract_phy_range(char *const argv[], int argc, struct mii_dev **bus,
+               int *addrlo, int *addrhi)
+{
+       struct phy_device *phydev;
+
+       if ((argc < 1) || (argc > 2))
+               return -1;
+
+       /* If there are two arguments, it's busname addr */
+       if (argc == 2) {
+               *bus = miiphy_get_dev_by_name(argv[0]);
+
+               if (!*bus)
+                       return -1;
+
+               return extract_range(argv[1], addrlo, addrhi);
+       }
+
+       /* It must be one argument, here */
+
+       /*
+        * This argument can be one of two things:
+        * 1) Ethernet device name
+        * 2) Just an address (use the previously-used bus)
+        *
+        * We check all buses for a PHY which is connected to an ethernet
+        * device by the given name.  If none are found, we call
+        * extract_range() on the string, and see if it's an address range.
+        */
+       phydev = mdio_phydev_for_ethname(argv[0]);
+
+       if (phydev) {
+               *addrlo = *addrhi = phydev->addr;
+               *bus = phydev->bus;
+
+               return 0;
+       }
+
+       /* It's an address or nothing useful */
+       return extract_range(argv[0], addrlo, addrhi);
+}
+
+/* ---------------------------------------------------------------- */
+static int do_mdio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       char op[2];
+       int addrlo, addrhi, reglo, reghi, devadlo, devadhi;
+       unsigned short  data;
+       int pos = argc - 1;
+       struct mii_dev *bus;
+
+       if (argc < 2)
+               return cmd_usage(cmdtp);
+
+       /*
+        * We use the last specified parameters, unless new ones are
+        * entered.
+        */
+       op[0] = argv[1][0];
+       addrlo = last_addr_lo;
+       addrhi = last_addr_hi;
+       devadlo = last_devad_lo;
+       devadhi = last_devad_hi;
+       reglo  = last_reg_lo;
+       reghi  = last_reg_hi;
+       data   = last_data;
+
+       bus = mdio_get_current_dev();
+
+       if (flag & CMD_FLAG_REPEAT)
+               op[0] = last_op[0];
+
+       switch (op[0]) {
+       case 'w':
+               if (pos > 1)
+                       data = simple_strtoul(argv[pos--], NULL, 16);
+       case 'r':
+               if (pos > 1)
+                       if (extract_reg_range(argv[pos--], &devadlo, &devadhi,
+                                       &reglo, &reghi))
+                               return -1;
+
+       default:
+               if (pos > 1)
+                       if (extract_phy_range(&(argv[2]), pos - 1, &bus,
+                                       &addrlo, &addrhi))
+                               return -1;
+
+               break;
+       }
+
+       if (op[0] == 'l') {
+               mdio_list_devices();
+
+               return 0;
+       }
+
+       /* Save the chosen bus */
+       miiphy_set_current_dev(bus->name);
+
+       switch (op[0]) {
+       case 'w':
+               mdio_write_ranges(bus, addrlo, addrhi, devadlo, devadhi,
+                               reglo, reghi, data);
+               break;
+
+       case 'r':
+               mdio_read_ranges(bus, addrlo, addrhi, devadlo, devadhi,
+                               reglo, reghi);
+               break;
+       }
+
+       /*
+        * Save the parameters for repeats.
+        */
+       last_op[0] = op[0];
+       last_addr_lo = addrlo;
+       last_addr_hi = addrhi;
+       last_devad_lo = devadlo;
+       last_devad_hi = devadhi;
+       last_reg_lo  = reglo;
+       last_reg_hi  = reghi;
+       last_data    = data;
+
+       return 0;
+}
+
+/***************************************************/
+
+U_BOOT_CMD(
+       mdio,   6,      1,      do_mdio,
+       "MDIO utility commands",
+       "list                   - List MDIO buses\n"
+       "mdio read <phydev> [<devad>.]<reg> - "
+               "read PHY's register at <devad>.<reg>\n"
+       "mdio write <phydev> [<devad>.]<reg> <data> - "
+               "write PHY's register at <devad>.<reg>\n"
+       "<phydev> may be:\n"
+       "   <busname>  <addr>\n"
+       "   <addr>\n"
+       "   <eth name>\n"
+       "<addr> <devad>, and <reg> may be ranges, e.g. 1-5.4-0x1f.\n"
+);
index e282096a13460866c9f7b2054b3ce8c38de48f7f..243cae97a468111c68b3b155541b73a13e00877d 100644 (file)
@@ -28,6 +28,7 @@
 
 #include <common.h>
 #include <miiphy.h>
+#include <phy.h>
 
 #include <asm/types.h>
 #include <linux/list.h>
 
 #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;
 }
 
@@ -86,74 +76,190 @@ static struct mii_dev *miiphy_get_dev_by_name(const char *devname, int quiet)
  */
 void miiphy_init(void)
 {
-       INIT_LIST_HEAD (&mii_devs);
+       INIT_LIST_HEAD(&mii_devs);
        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);
+       if (name_len > MDIO_NAME_LEN - 1) {
+               /* Hopefully this won't happen, but if it does, we'll know */
+               printf("miiphy_register: MDIO name was longer than %d\n",
+                       MDIO_NAME_LEN);
+               return;
+       }
+
+       new_dev = mdio_alloc();
+       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);
 
        /* initalize mii_dev struct fields */
-       INIT_LIST_HEAD (&new_dev->link);
-       new_dev->read = read;
-       new_dev->write = write;
-       new_dev->name = new_name = (char *)(new_dev + 1);
-       strncpy (new_name, name, name_len);
-       new_name[name_len] = '\0';
+       new_dev->read = legacy_miiphy_read;
+       new_dev->write = legacy_miiphy_write;
+       sprintf(new_dev->name, name);
+       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));
+
+       /* 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 +293,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 +315,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 +328,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,32 +361,33 @@ 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;
 }
 
+#ifndef CONFIG_PHYLIB
 /*****************************************************************************
  *
  * Reset the PHY.
@@ -290,16 +399,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,13 +424,14 @@ 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;
 }
+#endif /* !PHYLIB */
 
 /*****************************************************************************
  *
@@ -338,33 +448,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 +482,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 +498,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 +509,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 +523,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 +541,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 +555,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 +576,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
index fd9d0b4be115a10674f1ab5d9cdd5909c966dfa3..819b197673b28efc3abd8ada48b9f6e166891df0 100644 (file)
@@ -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
index 709f67aac2c0fa51a01473b958864a33ad3a5984..b5c55738f76aefaaf3018be54c76edf89f53d898 100644 (file)
@@ -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)
index 6c161b632f4165b87e7939c5ae494f736d72e855..d55cacdac8c0acf9b453d0341c779b2856b77571 100644 (file)
@@ -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/fsl_mdio.c b/drivers/net/fsl_mdio.c
new file mode 100644 (file)
index 0000000..1aab307
--- /dev/null
@@ -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(struct tsec_mii_mng *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(struct tsec_mii_mng *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)
+{
+       struct tsec_mii_mng *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)
+{
+       struct tsec_mii_mng *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)
+{
+       struct tsec_mii_mng *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);
+}
index bba890189a2c7bfdc1ba8afcfc104f3c99b1a5f2..a59834b292d8cb1503db30ae8d1f7474bb3e4cfb 100644 (file)
@@ -28,6 +28,19 @@ LIB  := $(obj)libphy.o
 COBJS-$(CONFIG_BITBANGMII) += miiphybb.o
 COBJS-$(CONFIG_MV88E61XX_SWITCH) += mv88e61xx.o
 
+COBJS-$(CONFIG_PHYLIB) += phy.o
+COBJS-$(CONFIG_PHYLIB_10G) += generic_10g.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)
 OBJS   := $(addprefix $(obj),$(COBJS))
diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c
new file mode 100644 (file)
index 0000000..798473d
--- /dev/null
@@ -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 phy_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 (file)
index 0000000..427ac60
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ * 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);
+
+       phy_reset(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 phy_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 (file)
index 0000000..e96a4af
--- /dev/null
@@ -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 phy_davicom_init(void)
+{
+       phy_register(&DM9161_driver);
+
+       return 0;
+}
diff --git a/drivers/net/phy/generic_10g.c b/drivers/net/phy/generic_10g.c
new file mode 100644 (file)
index 0000000..315c508
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * 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 <miiphy.h>
+#include <phy.h>
+
+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_discover_mmds(struct phy_device *phydev)
+{
+       int mmd, stat2, devs1, devs2;
+
+       /* 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 0;
+}
+
+int gen10g_config(struct phy_device *phydev)
+{
+       /* For now, assume 10000baseT. Fill in later */
+       phydev->supported = phydev->advertising = SUPPORTED_10000baseT_Full;
+
+       return gen10g_discover_mmds(phydev);
+}
+
+struct phy_driver gen10g_driver = {
+       .uid            = 0xffffffff,
+       .mask           = 0xffffffff,
+       .name           = "Generic 10G PHY",
+       .features       = 0,
+       .config         = gen10g_config,
+       .startup        = gen10g_startup,
+       .shutdown       = gen10g_shutdown,
+};
+
diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c
new file mode 100644 (file)
index 0000000..d67bbdd
--- /dev/null
@@ -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 phy_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 (file)
index 0000000..bd1cdc4
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+ * 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;
+
+       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);
+
+       phy_reset(phydev);
+
+       return 0;
+}
+
+/* Marvell 88E1118 */
+static int m88e1118_config(struct phy_device *phydev)
+{
+       /* 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);
+
+       genphy_config_aneg(phydev);
+
+       phy_reset(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;
+
+       /* Configure the PHY */
+       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;
+
+       /* 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);
+
+       genphy_config_aneg(phydev);
+
+       phy_reset(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)
+{
+       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);
+
+       genphy_config_aneg(phydev);
+
+       phy_reset(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 phy_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 (file)
index 0000000..47064a1
--- /dev/null
@@ -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 phy_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 (file)
index 0000000..ea60ac1
--- /dev/null
@@ -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 phy_natsemi_init(void)
+{
+       phy_register(&DP83865_driver);
+
+       return 0;
+}
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
new file mode 100644 (file)
index 0000000..c7edcc0
--- /dev/null
@@ -0,0 +1,755 @@
+/*
+ * 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>
+
+/* 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 LIST_HEAD(phy_drivers);
+
+int phy_init(void)
+{
+#ifdef CONFIG_PHY_ATHEROS
+       phy_atheros_init();
+#endif
+#ifdef CONFIG_PHY_BROADCOM
+       phy_broadcom_init();
+#endif
+#ifdef CONFIG_PHY_DAVICOM
+       phy_davicom_init();
+#endif
+#ifdef CONFIG_PHY_LXT
+       phy_lxt_init();
+#endif
+#ifdef CONFIG_PHY_MARVELL
+       phy_marvell_init();
+#endif
+#ifdef CONFIG_PHY_MICREL
+       phy_micrel_init();
+#endif
+#ifdef CONFIG_PHY_NATSEMI
+       phy_natsemi_init();
+#endif
+#ifdef CONFIG_PHY_REALTEK
+       phy_realtek_init();
+#endif
+#ifdef CONFIG_PHY_TERANETICS
+       phy_teranetics_init();
+#endif
+#ifdef CONFIG_PHY_VITESSE
+       phy_vitesse_init();
+#endif
+
+       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;
+       phydev->mmds = phydev->drv->mmds;
+
+       if (phydev->drv->probe)
+               err = phydev->drv->probe(phydev);
+
+       return err;
+}
+
+static struct phy_driver *generic_for_interface(phy_interface_t interface)
+{
+#ifdef CONFIG_PHYLIB_10G
+       if (is_10g_interface(interface))
+               return &gen10g_driver;
+#endif
+
+       return &genphy_driver;
+}
+
+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 */
+       return generic_for_interface(interface);
+}
+
+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);
+
+       bus->phymap[addr] = 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 at @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;
+
+       /* If we have one, return the existing device, with new interface */
+       if (bus->phymap[addr]) {
+               bus->phymap[addr]->interface = interface;
+
+               return bus->phymap[addr];
+       }
+
+       /* 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);
+}
+
+int phy_reset(struct phy_device *phydev)
+{
+       int reg;
+       int timeout = 500;
+       int devad = MDIO_DEVAD_NONE;
+
+#ifdef CONFIG_PHYLIB_10G
+       /* If it's 10G, we need to issue reset through one of the MMDs */
+       if (is_10g_interface(phydev->interface)) {
+               if (!phydev->mmds)
+                       gen10g_discover_mmds(phydev);
+
+               devad = ffs(phydev->mmds) - 1;
+       }
+#endif
+
+       reg = phy_read(phydev, devad, MII_BMCR);
+       if (reg < 0) {
+               debug("PHY status read failed\n");
+               return -1;
+       }
+
+       reg |= BMCR_RESET;
+
+       if (phy_write(phydev, devad, MII_BMCR, reg) < 0) {
+               debug("PHY reset failed\n");
+               return -1;
+       }
+
+#ifdef CONFIG_PHY_RESET_DELAY
+       udelay(CONFIG_PHY_RESET_DELAY); /* Intel LXT971A needs this */
+#endif
+       /*
+        * Poll the control register for the reset bit to go to 0 (it is
+        * auto-clearing).  This should happen within 0.5 seconds per the
+        * IEEE spec.
+        */
+       while ((reg & BMCR_RESET) && timeout--) {
+               reg = phy_read(phydev, devad, MII_BMCR);
+
+               if (reg < 0) {
+                       debug("PHY status read failed\n");
+                       return -1;
+               }
+               udelay(1000);
+       }
+
+       if (reg & BMCR_RESET) {
+               puts("PHY reset timed out\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+int miiphy_reset(const char *devname, unsigned char addr)
+{
+       struct mii_dev *bus = miiphy_get_dev_by_name(devname);
+       struct phy_device *phydev;
+
+       /*
+        * miiphy_reset was only used on standard PHYs, so we'll fake it here.
+        * If later code tries to connect with the right interface, this will
+        * be corrected by get_phy_device in phy_connect()
+        */
+       phydev = get_phy_device(bus, addr, PHY_INTERFACE_MODE_MII);
+
+       return phy_reset(phydev);
+}
+
+struct phy_device *phy_connect(struct mii_dev *bus, int addr,
+                               struct eth_device *dev,
+                               phy_interface_t interface)
+{
+       struct phy_device *phydev;
+
+       /* Reset the bus */
+       bus->reset(bus);
+
+       /* Wait 15ms to make sure the PHY has come out of hard reset */
+       udelay(15000);
+
+       phydev = get_phy_device(bus, addr, interface);
+
+       if (!phydev) {
+               printf("Could not get PHY for %s:%d\n", bus->name, addr);
+
+               return NULL;
+       }
+
+       /* Soft Reset the PHY */
+       phy_reset(phydev);
+
+       if (phydev->dev)
+               printf("%s:%d is connected to %s.  Reconnecting to %s\n",
+                       bus->name, addr, phydev->dev->name, dev->name);
+
+       phydev->dev = dev;
+
+       printf("%s connected to %s\n", dev->name, phydev->drv->name);
+
+       return phydev;
+}
+
+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/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
new file mode 100644 (file)
index 0000000..b7e2753
--- /dev/null
@@ -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 phy_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 (file)
index 0000000..a771791
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * 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 <config.h>
+#include <phy.h>
+
+#ifndef CONFIG_PHYLIB_10G
+#error The Teranetics PHY needs 10G support
+#endif
+
+int tn2020_config(struct phy_device *phydev)
+{
+       if (phydev->port == PORT_FIBRE) {
+               unsigned short restart_an = (MDIO_AN_CTRL1_RESTART |
+                                               MDIO_AN_CTRL1_ENABLE |
+                                               MDIO_AN_CTRL1_XNP);
+
+               phy_write(phydev, 30, 93, 2);
+               phy_write(phydev, MDIO_MMD_AN, MDIO_CTRL1, restart_an);
+       }
+
+       return 0;
+}
+
+struct phy_driver tn2020_driver = {
+       .name = "Teranetics TN2020",
+       .uid = 0x00a19410,
+       .mask = 0xfffffff0,
+       .features = PHY_10G_FEATURES,
+       .mmds = (MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS |
+                       MDIO_DEVS_PHYXS | MDIO_DEVS_AN |
+                       MDIO_DEVS_VEND1 | MDIO_DEVS_VEND2),
+       .config = &tn2020_config,
+       .startup = &gen10g_startup,
+       .shutdown = &gen10g_shutdown,
+};
+
+int phy_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 (file)
index 0000000..d48d4fe
--- /dev/null
@@ -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 phy_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;
+}
index 9a91b9e0b85130deb0d608f05841eac08929debd..06e5834a94ca32cb6798e2a51db47d3ab9ef27c1 100644 (file)
@@ -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
  *
 #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
@@ -44,31 +43,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(volatile 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[] = {
@@ -81,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
@@ -95,195 +69,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 */
-       priv->regs->maccfg1 |= MACCFG1_SOFT_RESET;
-       udelay(2);  /* Soft Reset must be asserted for 3 TX clocks */
-       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;
-       volatile tsec_t *regs = priv->regs;
-
-       /* Make sure the controller is stopped */
-       tsec_halt(dev);
-
-       /* Init MACCFG2.  Defaults to GMII */
-       regs->maccfg2 = MACCFG2_INIT_SETTINGS;
-
-       /* Init ECNTRL */
-       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];
-
-       regs->macstnaddr1 = tempval;
-
-       tempval = *((uint *) (tmpbuf + 4));
-
-       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(volatile tsec_mdio_t *phyregs, uint addr,
-               uint reg, uint value)
-{
-       int timeout = 1000000;
-
-       phyregs->miimadd = (addr << 8) | reg;
-       phyregs->miimcon = value;
-       asm("sync");
-
-       timeout = 1000000;
-       while ((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(volatile 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;
-
-       /* Clear the command register, and wait */
-       phyregs->miimcom = 0;
-       asm("sync");
-
-       /* Initiate a read command, and wait */
-       phyregs->miimcom = MIIM_READ_COMMAND;
-       asm("sync");
-
-       /* Wait for the the indication that the read is done */
-       while ((phyregs->miimind & (MIIMIND_NOTVALID | MIIMIND_BUSY))) ;
-
-       /* Grab the value read from the PHY */
-       value = 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 \
@@ -305,661 +90,150 @@ 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);
-}
-
-/* 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;
-       volatile tsec_t *regs = priv->regs;
-
-       /* Assign a Physical address to the TBI */
-       regs->tbipa = CONFIG_SYS_TBIPA_VALUE;
-       asm("sync");
-
-       /* Reset MII (due to new addresses) */
-       priv->phyregs->miimcfg = MIIMCFG_RESET;
-       asm("sync");
-       priv->phyregs->miimcfg = MIIMCFG_INIT_VALUE;
-       asm("sync");
-       while (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 (regs->ecntrl & ECNTRL_SGMII_MODE)
-               tsec_configure_serdes(priv);
-
-       priv->phyinfo = curphy;
-
-       phy_run_commands(priv, priv->phyinfo->config);
-
-       return 1;
+       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);
 }
 
-/*
- * 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@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 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;
+#ifdef CONFIG_MCAST_TFTP
 
-       if (mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_10F))
-               priv->duplexity = 1;
-       else
-               priv->duplexity = 0;
+/* CREDITS: linux gianfar driver, slightly adjusted... thanx. */
 
-       return 0;
-}
+/* Set the appropriate hash bit for the given addr */
 
-/*
- * Hack to write all 4 PHYs with the LED values
- */
-static uint mii_cis8204_fixled(uint mii_reg, struct tsec_private * priv)
+/* The algorithm works like so:
+ * 1) Take the Destination Address (ie the multicast address), and
+ * do a CRC on it (little endian), and reverse the bits of the
+ * result.
+ * 2) Use the 8 most significant bits as a hash into a 256-entry
+ * table.  The table is controlled through 8 32-bit registers:
+ * gaddr0-7.  gaddr0's MSB is entry 0, and gaddr7's LSB is
+ * gaddr7.  This means that the 3 most significant bits in the
+ * hash index which gaddr register to use, and the 5 other bits
+ * indicate which bit (assuming an IBM numbering scheme, which
+ * for PowerPC (tm) is usually the case) in the tregister holds
+ * the entry. */
+static int
+tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set)
 {
-       uint phyid;
-       volatile 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;
-               asm("sync");
-
-               timeout = 1000000;
-               while ((regbase->miimind & MIIMIND_BUSY) && timeout--) ;
-       }
-
-       return MIIM_CIS8204_SLEDCON_INIT;
-}
+       struct tsec_private *priv = privlist[1];
+       volatile tsec_t *regs = priv->regs;
+       volatile u32  *reg_array, value;
+       u8 result, whichbit, whichreg;
 
-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;
-}
+       result = (u8)((ether_crc(MAC_ADDR_LEN,mcast_mac) >> 24) & 0xff);
+       whichbit = result & 0x1f;       /* the 5 LSB = which bit to set */
+       whichreg = result >> 5;         /* the 3 MSB = which reg to set it in */
+       value = (1 << (31-whichbit));
 
-static uint mii_m88e1111s_setmode(uint mii_reg, struct tsec_private *priv)
-{
-       uint mii_data = read_phy_reg(priv, mii_reg);
+       reg_array = &(regs->hash.gaddr0);
 
-       if (priv->flags & TSEC_REDUCED)
-               mii_data = (mii_data & 0xfff0) | 0x000b;
-       return mii_data;
+       if (set) {
+               reg_array[whichreg] |= value;
+       } else {
+               reg_array[whichreg] &= ~value;
+       }
+       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(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);
 
 }
 
 /* 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;
-       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);
-
-               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);
-
-                       /* 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;
-               }
+       if (!phydev->link) {
+               printf("%s: No link.\n", phydev->dev->name);
+               return;
+       }
 
-               printf("Speed: %d, %s duplex%s\n", priv->speed,
-                      (priv->duplexity) ? "full" : "half",
-                      (priv->flags & TSEC_FIBER) ? ", fiber mode" : "");
+       /* clear all bits relative with interface mode */
+       ecntrl = in_be32(&regs->ecntrl);
+       ecntrl &= ~ECNTRL_R100;
 
-       } else {
-               printf("%s: No link.\n", dev->name);
+       maccfg2 = in_be32(&regs->maccfg2);
+       maccfg2 &= ~(MACCFG2_IF | MACCFG2_FULL_DUPLEX);
+
+       if (phydev->duplex)
+               maccfg2 |= MACCFG2_FULL_DUPLEX;
+
+       switch (phydev->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 (phydev->speed == 100)
+                       ecntrl |= ECNTRL_R100;
+               break;
+       default:
+               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", phydev->speed,
+                       (phydev->duplex) ? "full" : "half",
+                       (phydev->port == PORT_FIBRE) ? ", fiber mode" : "");
 }
 
 /* Set up the buffers and their descriptors, and bring up the
@@ -969,11 +243,15 @@ 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;
+
+       /* reset the indices to zero */
+       rxIdx = 0;
+       txIdx = 0;
 
        /* 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++) {
@@ -991,20 +269,14 @@ 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 */
-       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 +289,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 +305,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 +325,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 +348,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,936 +361,236 @@ 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)
-               phy_run_commands(priv, priv->phyinfo->shutdown);
+       phy_shutdown(priv->phydev);
 }
 
-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@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
+/* 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 uint mii_88E1121_set_led (uint mii_reg, struct tsec_private *priv)
+static int tsec_init(struct eth_device *dev, bd_t * bd)
 {
-       uint pg;
+       uint tempval;
+       char tmpbuf[MAC_ADDR_LEN];
+       int i;
+       struct tsec_private *priv = (struct tsec_private *)dev->priv;
+       tsec_t *regs = priv->regs;
 
-       /* 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);
+       /* Make sure the controller is stopped */
+       tsec_halt(dev);
 
-       /* Configure leds */
-       write_phy_reg(priv, MIIM_88E1121_PHY_LED_CTRL,
-                     MIIM_88E1121_PHY_LED_DEF);
+       /* Init MACCFG2.  Defaults to GMII */
+       out_be32(&regs->maccfg2, MACCFG2_INIT_SETTINGS);
 
-       /* Restore the page pointer */
-       write_phy_reg(priv, MIIM_88E1121_PHY_PAGE, pg);
-       return 0;
-}
+       /* Init ECNTRL */
+       out_be32(&regs->ecntrl, ECNTRL_INIT_SETTINGS);
 
-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,}
-       },
-};
+       /* 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];
 
-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;
-}
+       tempval = (tmpbuf[0] << 24) | (tmpbuf[1] << 16) | (tmpbuf[2] << 8) |
+                 tmpbuf[3];
 
-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,}
-       },
-};
+       out_be32(&regs->macstnaddr1, tempval);
 
-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,}
-       },
-};
+       tempval = *((uint *) (tmpbuf + 4));
 
-/* 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,}
-       },
-};
+       out_be32(&regs->macstnaddr2, tempval);
 
-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,}
-       },
-};
+       /* Clear out (for the most part) the other registers */
+       init_registers(regs);
 
-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,}
-       },
-};
+       /* Ready the device for tx/rx */
+       startup_tsec(dev);
 
-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,}
-       },
-};
+       /* Start up the PHY */
+       phy_startup(priv->phydev);
 
-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,}
-       },
-};
+       adjust_link(priv, priv->phydev);
 
-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,}
-       },
-};
+       /* If there's no link, fail */
+       return priv->phydev->link ? 0 : -1;
+}
 
-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,}
-       },
-};
+static phy_interface_t tsec_get_interface(struct tsec_private *priv)
+{
+       tsec_t *regs = priv->regs;
+       u32 ecntrl;
 
-/* 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,}
-       }
-};
+       ecntrl = in_be32(&regs->ecntrl);
+
+       if (ecntrl & ECNTRL_SGMII_MODE)
+               return PHY_INTERFACE_MODE_SGMII;
 
-/* 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,}
+       if (ecntrl & ECNTRL_TBI_MODE) {
+               if (ecntrl & ECNTRL_REDUCED_MODE)
+                       return PHY_INTERFACE_MODE_RTBI;
+               else
+                       return PHY_INTERFACE_MODE_TBI;
        }
-};
 
-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;
+       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;
                }
-       } else {
-               priv->speed = 0;
-               priv->duplexity = 0;
        }
 
-       return 0;
+       if (priv->flags & TSEC_GIGABIT)
+               return PHY_INTERFACE_MODE_GMII;
+
+       return PHY_INTERFACE_MODE_MII;
 }
 
-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
+/* 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 uint mii_parse_dp83865_lanr(uint mii_reg, struct tsec_private *priv)
+static int init_phy(struct eth_device *dev)
 {
-       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;
-
-       }
+       struct tsec_private *priv = (struct tsec_private *)dev->priv;
+       struct phy_device *phydev;
+       tsec_t *regs = priv->regs;
+       u32 supported = (SUPPORTED_10baseT_Half |
+                       SUPPORTED_10baseT_Full |
+                       SUPPORTED_100baseT_Half |
+                       SUPPORTED_100baseT_Full);
 
-       if (mii_reg & MIIM_DP83865_DPX_FULL)
-               priv->duplexity = 1;
-       else
-               priv->duplexity = 0;
+       if (priv->flags & TSEC_GIGABIT)
+               supported |= SUPPORTED_1000baseT_Full;
 
-       return 0;
-}
+       /* Assign a Physical address to the TBI */
+       out_be32(&regs->tbipa, CONFIG_SYS_TBIPA_VALUE);
 
-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,}
-       },
-};
+       priv->interface = tsec_get_interface(priv);
 
-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,}
-       },
-};
+       if (priv->interface == PHY_INTERFACE_MODE_SGMII)
+               tsec_configure_serdes(priv);
 
-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,}
-        }
-};
+       phydev = phy_connect(priv->bus, priv->phyaddr, dev, priv->interface);
 
-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
-};
+       phydev->supported &= supported;
+       phydev->advertising = phydev->supported;
 
-/* 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;
-               }
-       }
+       priv->phydev = phydev;
 
-       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);
-       }
+       phy_config(phydev);
 
-       return theInfo;
+       return 1;
 }
 
-/* Execute the given series of commands on the given device's
- * PHY, running functions as necessary
+/* Initialize device structure. Returns success if PHY
+ * initialization succeeded (i.e. if it recognizes the PHY)
  */
-static void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd)
+static int tsec_initialize(bd_t *bis, struct tsec_info_struct *tsec_info)
 {
+       struct eth_device *dev;
        int i;
-       uint result;
-       volatile tsec_mdio_t *phyregs = priv->phyregs;
-
-       phyregs->miimcfg = MIIMCFG_RESET;
+       struct tsec_private *priv;
 
-       phyregs->miimcfg = MIIMCFG_INIT_VALUE;
+       dev = (struct eth_device *)malloc(sizeof *dev);
 
-       while (phyregs->miimind & MIIMIND_BUSY) ;
+       if (NULL == dev)
+               return 0;
 
-       for (i = 0; cmd->mii_reg != miim_end; i++) {
-               if (cmd->mii_data == miim_read) {
-                       result = read_phy_reg(priv, cmd->mii_reg);
+       memset(dev, 0, sizeof *dev);
 
-                       if (cmd->funct != NULL)
-                               (*(cmd->funct)) (result, priv);
+       priv = (struct tsec_private *)malloc(sizeof(*priv));
 
-               } else {
-                       if (cmd->funct != NULL)
-                               result = (*(cmd->funct)) (cmd->mii_reg, priv);
-                       else
-                               result = cmd->mii_data;
+       if (NULL == priv)
+               return 0;
 
-                       write_phy_reg(priv, cmd->mii_reg, result);
+       privlist[num_tsecs++] = priv;
+       priv->regs = tsec_info->regs;
+       priv->phyregs_sgmii = tsec_info->miiregs_sgmii;
 
-               }
-               cmd++;
-       }
-}
+       priv->phyaddr = tsec_info->phyaddr;
+       priv->flags = tsec_info->flags;
 
-#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \
-       && !defined(BITBANGMII)
+       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;
+       dev->halt = tsec_halt;
+       dev->send = tsec_send;
+       dev->recv = tsec_recv;
+#ifdef CONFIG_MCAST_TFTP
+       dev->mcast = tsec_mcast_addr;
+#endif
 
-/*
- * 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];
+       /* Tell u-boot to get the addr from the env */
+       for (i = 0; i < 6; i++)
+               dev->enetaddr[i] = 0;
 
-       if (NULL == priv) {
-               printf("Can't read PHY at address %d\n", addr);
-               return -1;
-       }
+       eth_register(dev);
 
-       ret = (unsigned short)tsec_local_mdio_read(priv->phyregs, addr, reg);
-       *value = ret;
+       /* 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);
 
-       return 0;
+       /* Try to initialize PHY here, and return */
+       return init_phy(dev);
 }
 
 /*
- * Write a MII PHY register.
+ * Initialize all the TSEC devices
  *
- * Returns:
- *  0 on success
+ * Returns the number of TSEC devices that were initialized
  */
-static int tsec_miiphy_write(const char *devname, unsigned char addr,
-                            unsigned char reg, unsigned short value)
+int tsec_eth_init(bd_t *bis, struct tsec_info_struct *tsecs, int num)
 {
-       struct tsec_private *priv = privlist[0];
+       int i;
+       int ret, count = 0;
 
-       if (NULL == priv) {
-               printf("Can't write PHY at address %d\n", addr);
-               return -1;
+       for (i = 0; i < num; i++) {
+               ret = tsec_initialize(bis, &tsecs[i]);
+               if (ret > 0)
+                       count += ret;
        }
 
-       tsec_local_mdio_write(priv->phyregs, addr, reg, value);
-
-       return 0;
+       return count;
 }
 
-#endif
-
-#ifdef CONFIG_MCAST_TFTP
-
-/* CREDITS: linux gianfar driver, slightly adjusted... thanx. */
-
-/* Set the appropriate hash bit for the given addr */
-
-/* The algorithm works like so:
- * 1) Take the Destination Address (ie the multicast address), and
- * do a CRC on it (little endian), and reverse the bits of the
- * result.
- * 2) Use the 8 most significant bits as a hash into a 256-entry
- * table.  The table is controlled through 8 32-bit registers:
- * gaddr0-7.  gaddr0's MSB is entry 0, and gaddr7's LSB is
- * gaddr7.  This means that the 3 most significant bits in the
- * hash index which gaddr register to use, and the 5 other bits
- * indicate which bit (assuming an IBM numbering scheme, which
- * for PowerPC (tm) is usually the case) in the tregister holds
- * the entry. */
-static int
-tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set)
+int tsec_standard_init(bd_t *bis)
 {
-       struct tsec_private *priv = privlist[1];
-       volatile tsec_t *regs = priv->regs;
-       volatile u32  *reg_array, value;
-       u8 result, whichbit, whichreg;
+       struct fsl_pq_mdio_info info;
 
-       result = (u8)((ether_crc(MAC_ADDR_LEN,mcast_mac) >> 24) & 0xff);
-       whichbit = result & 0x1f;       /* the 5 LSB = which bit to set */
-       whichreg = result >> 5;         /* the 3 MSB = which reg to set it in */
-       value = (1 << (31-whichbit));
+       info.regs = (struct tsec_mii_mng *)CONFIG_SYS_MDIO_BASE_ADDR;
+       info.name = DEFAULT_MII_NAME;
 
-       reg_array = &(regs->hash.gaddr0);
+       fsl_pq_mdio_init(bis, &info);
 
-       if (set) {
-               reg_array[whichreg] |= value;
-       } else {
-               reg_array[whichreg] &= ~value;
-       }
-       return 0;
+       return tsec_eth_init(bis, tsec_info, ARRAY_SIZE(tsec_info));
 }
-#endif /* Multicast TFTP ? */
+
index a4624e1734df9977fe210eb57e13dcf7a6698ad8..5933bddce54861d94b7500967cafff998fd2b94f 100644 (file)
@@ -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;
index 811e3fc3156752fa8c20a320dd573394bf2e14aa..1ecb1379a5c92ed80c61d0fdea47e4600b246471 100644 (file)
@@ -30,6 +30,7 @@
 #include "uec.h"
 #include "uec_phy.h"
 #include "miiphy.h"
+#include <phy.h>
 
 /* Default UTBIPAR SMI address */
 #ifndef CONFIG_UTBIPAR_INIT_TBIPA
@@ -67,9 +68,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;
@@ -324,9 +322,9 @@ static int uec_set_mac_duplex(uec_private_t *uec, int duplex)
 }
 
 static int uec_set_mac_if_mode(uec_private_t *uec,
-               enum fsl_phy_enet_if if_mode, int speed)
+               phy_interface_t if_mode, int speed)
 {
-       enum fsl_phy_enet_if    enet_if_mode;
+       phy_interface_t         enet_if_mode;
        uec_info_t              *uec_info;
        uec_t                   *uec_regs;
        u32                     upsmr;
@@ -348,15 +346,15 @@ static int uec_set_mac_if_mode(uec_private_t *uec,
        upsmr &= ~(UPSMR_RPM | UPSMR_TBIM | UPSMR_R10M | UPSMR_RMM);
 
        switch (speed) {
-               case 10:
+               case SPEED_10:
                        maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE;
                        switch (enet_if_mode) {
-                               case MII:
+                               case PHY_INTERFACE_MODE_MII:
                                        break;
-                               case RGMII:
+                               case PHY_INTERFACE_MODE_RGMII:
                                        upsmr |= (UPSMR_RPM | UPSMR_R10M);
                                        break;
-                               case RMII:
+                               case PHY_INTERFACE_MODE_RMII:
                                        upsmr |= (UPSMR_R10M | UPSMR_RMM);
                                        break;
                                default:
@@ -364,15 +362,15 @@ static int uec_set_mac_if_mode(uec_private_t *uec,
                                        break;
                        }
                        break;
-               case 100:
+               case SPEED_100:
                        maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE;
                        switch (enet_if_mode) {
-                               case MII:
+                               case PHY_INTERFACE_MODE_MII:
                                        break;
-                               case RGMII:
+                               case PHY_INTERFACE_MODE_RGMII:
                                        upsmr |= UPSMR_RPM;
                                        break;
-                               case RMII:
+                               case PHY_INTERFACE_MODE_RMII:
                                        upsmr |= UPSMR_RMM;
                                        break;
                                default:
@@ -380,23 +378,24 @@ static int uec_set_mac_if_mode(uec_private_t *uec,
                                        break;
                        }
                        break;
-               case 1000:
+               case SPEED_1000:
                        maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE;
                        switch (enet_if_mode) {
-                               case GMII:
+                               case PHY_INTERFACE_MODE_GMII:
                                        break;
-                               case TBI:
+                               case PHY_INTERFACE_MODE_TBI:
                                        upsmr |= UPSMR_TBIM;
                                        break;
-                               case RTBI:
+                               case PHY_INTERFACE_MODE_RTBI:
                                        upsmr |= (UPSMR_RPM | UPSMR_TBIM);
                                        break;
-                               case RGMII_RXID:
-                               case RGMII_ID:
-                               case RGMII:
+                               case PHY_INTERFACE_MODE_RGMII_RXID:
+                               case PHY_INTERFACE_MODE_RGMII_TXID:
+                               case PHY_INTERFACE_MODE_RGMII_ID:
+                               case PHY_INTERFACE_MODE_RGMII:
                                        upsmr |= UPSMR_RPM;
                                        break;
-                               case SGMII:
+                               case PHY_INTERFACE_MODE_SGMII:
                                        upsmr |= UPSMR_SGMM;
                                        break;
                                default:
@@ -521,7 +520,7 @@ static void adjust_link(struct eth_device *dev)
        struct uec_mii_info     *mii_info = uec->mii_info;
 
        extern void change_phy_interface_mode(struct eth_device *dev,
-                                enum fsl_phy_enet_if mode, int speed);
+                                phy_interface_t mode, int speed);
        uec_regs = uec->uec_regs;
 
        if (mii_info->link) {
@@ -539,19 +538,19 @@ static void adjust_link(struct eth_device *dev)
                }
 
                if (mii_info->speed != uec->oldspeed) {
-                       enum fsl_phy_enet_if    mode = \
+                       phy_interface_t mode =
                                uec->uec_info->enet_interface_type;
                        if (uec->uec_info->uf_info.eth_type == GIGA_ETH) {
                                switch (mii_info->speed) {
-                               case 1000:
+                               case SPEED_1000:
                                        break;
-                               case 100:
+                               case SPEED_100:
                                        printf ("switching to rgmii 100\n");
-                                       mode = RGMII;
+                                       mode = PHY_INTERFACE_MODE_RGMII;
                                        break;
-                               case 10:
+                               case SPEED_10:
                                        printf ("switching to rgmii 10\n");
-                                       mode = RGMII;
+                                       mode = PHY_INTERFACE_MODE_RGMII;
                                        break;
                                default:
                                        printf("%s: Ack,Speed(%d)is illegal\n",
@@ -1115,8 +1114,8 @@ static int uec_startup(uec_private_t *uec)
        out_be32(&uec_regs->utbipar, utbipar);
 
        /* Configure the TBI for SGMII operation */
-       if ((uec->uec_info->enet_interface_type == SGMII) &&
-          (uec->uec_info->speed == 1000)) {
+       if ((uec->uec_info->enet_interface_type == PHY_INTERFACE_MODE_SGMII) &&
+          (uec->uec_info->speed == SPEED_1000)) {
                uec_write_phy_reg(uec->dev, uec_regs->utbipar,
                        ENET_TBI_MII_ANA, TBIANA_SETTINGS);
 
index 94eb9a26d7f95d8c9cf2111f0119d4c19a6569d0..e63bf3a65220d55f34a970a92fb5278a8178d215 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "qe.h"
 #include "uccf.h"
+#include <phy.h>
 #include <asm/fsl_enet.h>
 
 #define MAX_TX_THREADS                         8
@@ -691,7 +692,7 @@ typedef struct uec_info {
        u16                             rx_bd_ring_len;
        u16                             tx_bd_ring_len;
        u8                              phy_address;
-       enum fsl_phy_enet_if            enet_interface_type;
+       phy_interface_t                 enet_interface_type;
        int                             speed;
 } uec_info_t;
 
index 55c262294299e57d547d80fa298f6800f231e119..e26218be88afc64e41d35c0fd99b0927bf33824f 100644 (file)
@@ -25,6 +25,7 @@
 #include "uec.h"
 #include "uec_phy.h"
 #include "miiphy.h"
+#include <phy.h>
 
 #define ugphy_printk(format, arg...)  \
        printf(format "\n", ## arg)
@@ -121,8 +122,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 +243,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 +253,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 +261,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 +291,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 +299,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 +314,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 +336,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 +374,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 +396,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 +421,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 +430,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;
@@ -456,62 +457,63 @@ static int bcm_init(struct uec_mii_info *mii_info)
 
        gbit_config_aneg(mii_info);
 
-       if ((uec->uec_info->enet_interface_type == RGMII_RXID) &&
-          (uec->uec_info->speed == 1000)) {
+       if ((uec->uec_info->enet_interface_type ==
+                               PHY_INTERFACE_MODE_RGMII_RXID) &&
+                       (uec->uec_info->speed == SPEED_1000)) {
                u16 val;
                int cnt = 50;
 
                /* 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;
-       enum fsl_phy_enet_if iface = uec->uec_info->enet_interface_type;
+       phy_interface_t iface = uec->uec_info->enet_interface_type;
        int     speed = uec->uec_info->speed;
 
-       if ((speed == 1000) &&
-          (iface == RGMII_ID ||
-           iface == RGMII_RXID ||
-           iface == RGMII_TXID)) {
+       if ((speed == SPEED_1000) &&
+          (iface == PHY_INTERFACE_MODE_RGMII_ID ||
+           iface == PHY_INTERFACE_MODE_RGMII_RXID ||
+           iface == PHY_INTERFACE_MODE_RGMII_TXID)) {
                int temp;
 
-               temp = phy_read(mii_info, MII_M1111_PHY_EXT_CR);
-               if (iface == RGMII_ID) {
+               temp = uec_phy_read(mii_info, MII_M1111_PHY_EXT_CR);
+               if (iface == PHY_INTERFACE_MODE_RGMII_ID) {
                        temp |= MII_M1111_RX_DELAY | MII_M1111_TX_DELAY;
-               } else if (iface == RGMII_RXID) {
+               } else if (iface == PHY_INTERFACE_MODE_RGMII_RXID) {
                        temp &= ~MII_M1111_TX_DELAY;
                        temp |= MII_M1111_RX_DELAY;
-               } else if (iface == RGMII_TXID) {
+               } else if (iface == PHY_INTERFACE_MODE_RGMII_TXID) {
                        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 +536,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 +566,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 +574,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 +585,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 +617,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 +635,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 +643,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 +699,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 +754,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 +807,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 +828,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 */
@@ -852,10 +855,8 @@ struct phy_info *uec_get_phy_info (struct uec_mii_info *mii_info)
        return theInfo;
 }
 
-void marvell_phy_interface_mode (struct eth_device *dev,
-                                enum fsl_phy_enet_if type,
-                                int speed
-                               )
+void marvell_phy_interface_mode(struct eth_device *dev, phy_interface_t type,
+               int speed)
 {
        uec_private_t *uec = (uec_private_t *) dev->priv;
        struct uec_mii_info *mii_info;
@@ -867,47 +868,47 @@ void marvell_phy_interface_mode (struct eth_device *dev,
        }
        mii_info = uec->mii_info;
 
-       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);
+       if (type == PHY_INTERFACE_MODE_RGMII) {
+               if (speed == SPEED_100) {
+                       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);
+               } else if (speed == SPEED_10) {
+                       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 */
 }
 
 void change_phy_interface_mode (struct eth_device *dev,
-                               enum fsl_phy_enet_if type, int speed)
+                               phy_interface_t type, int speed)
 {
 #ifdef CONFIG_PHY_MODE_NEED_CHANGE
        marvell_phy_interface_mode (dev, type, speed);
diff --git a/include/config_phylib_all_drivers.h b/include/config_phylib_all_drivers.h
new file mode 100644 (file)
index 0000000..903c7a7
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * 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
+
+#ifdef CONFIG_PHYLIB
+
+#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_LXT
+
+#ifdef CONFIG_PHYLIB_10G
+#define CONFIG_PHY_TERANETICS
+#endif /* CONFIG_PHYLIB_10G */
+
+#endif /* CONFIG_PHYLIB */
+
+#endif /*_CONFIG_PHYLIB_ALL_H */
index 1191eea106c00dcfd66a6db22060ae0e948b6a00..e25d5acc13641907f03ec372f678470ccfc68ee7 100644 (file)
 #define CONFIG_SYS_UEC1_TX_CLK         QE_CLK10
 #define CONFIG_SYS_UEC1_ETH_TYPE       FAST_ETH
 #define CONFIG_SYS_UEC1_PHY_ADDR       4
-#define CONFIG_SYS_UEC1_INTERFACE_TYPE MII
+#define CONFIG_SYS_UEC1_INTERFACE_TYPE PHY_INTERFACE_MODE_MII
 #define CONFIG_SYS_UEC1_INTERFACE_SPEED        100
 #endif
 
 #define CONFIG_SYS_UEC2_TX_CLK         QE_CLK3
 #define CONFIG_SYS_UEC2_ETH_TYPE       FAST_ETH
 #define CONFIG_SYS_UEC2_PHY_ADDR       0
-#define CONFIG_SYS_UEC2_INTERFACE_TYPE MII
+#define CONFIG_SYS_UEC2_INTERFACE_TYPE PHY_INTERFACE_MODE_MII
 #define CONFIG_SYS_UEC2_INTERFACE_SPEED        100
 #endif
 
index affa3a9cf8dacf3e5dc00ccfd6104f7c42e669e0..f136a8e16a0832ed12d192292853e9c123b012cf 100644 (file)
 #define CONFIG_SYS_UEC1_TX_CLK         QE_CLK10
 #define CONFIG_SYS_UEC1_ETH_TYPE       FAST_ETH
 #define CONFIG_SYS_UEC1_PHY_ADDR       3
-#define CONFIG_SYS_UEC1_INTERFACE_TYPE MII
+#define CONFIG_SYS_UEC1_INTERFACE_TYPE PHY_INTERFACE_MODE_MII
 #define CONFIG_SYS_UEC1_INTERFACE_SPEED        100
 #endif
 
 #define CONFIG_SYS_UEC2_TX_CLK         QE_CLK8
 #define CONFIG_SYS_UEC2_ETH_TYPE       FAST_ETH
 #define CONFIG_SYS_UEC2_PHY_ADDR       4
-#define CONFIG_SYS_UEC2_INTERFACE_TYPE MII
+#define CONFIG_SYS_UEC2_INTERFACE_TYPE PHY_INTERFACE_MODE_MII
 #define CONFIG_SYS_UEC2_INTERFACE_SPEED        100
 #endif
 
index a9599405dd2e51260230f32dd06aa4d5b110b56f..49d64a55eb88e9bc73934e6271ba073f65986938 100644 (file)
 #define CONFIG_SYS_UEC1_TX_CLK         QE_CLK9
 #define CONFIG_SYS_UEC1_ETH_TYPE       GIGA_ETH
 #define CONFIG_SYS_UEC1_PHY_ADDR       0
-#define CONFIG_SYS_UEC1_INTERFACE_TYPE RGMII_ID
+#define CONFIG_SYS_UEC1_INTERFACE_TYPE PHY_INTERFACE_MODE_RGMII_ID
 #define CONFIG_SYS_UEC1_INTERFACE_SPEED 1000
 #endif
 
 #define CONFIG_SYS_UEC2_TX_CLK         QE_CLK4
 #define CONFIG_SYS_UEC2_ETH_TYPE       GIGA_ETH
 #define CONFIG_SYS_UEC2_PHY_ADDR       1
-#define CONFIG_SYS_UEC2_INTERFACE_TYPE RGMII_ID
+#define CONFIG_SYS_UEC2_INTERFACE_TYPE PHY_INTERFACE_MODE_RGMII_ID
 #define CONFIG_SYS_UEC2_INTERFACE_SPEED 1000
 #endif
 
index b0cdc02c1dea4f344dd4f081cdc0c75ad6541af0..a4f42cf22dd8cc1b95fc9a93e4a3a6403ad3d525 100644 (file)
 #define CONFIG_SYS_UEC1_TX_CLK         QE_CLK9
 #define CONFIG_SYS_UEC1_ETH_TYPE       GIGA_ETH
 #define CONFIG_SYS_UEC1_PHY_ADDR       2
-#define CONFIG_SYS_UEC1_INTERFACE_TYPE RGMII_RXID
+#define CONFIG_SYS_UEC1_INTERFACE_TYPE PHY_INTERFACE_MODE_RGMII_RXID
 #define CONFIG_SYS_UEC1_INTERFACE_SPEED 1000
 #endif
 
 #define CONFIG_SYS_UEC2_TX_CLK         QE_CLK4
 #define CONFIG_SYS_UEC2_ETH_TYPE       GIGA_ETH
 #define CONFIG_SYS_UEC2_PHY_ADDR       4
-#define CONFIG_SYS_UEC2_INTERFACE_TYPE RGMII_RXID
+#define CONFIG_SYS_UEC2_INTERFACE_TYPE PHY_INTERFACE_MODE_RGMII_RXID
 #define CONFIG_SYS_UEC2_INTERFACE_SPEED 1000
 #endif
 
index 3674e495c5c23997b90fa06ac312c66e6d238d52..6237b23b7ecc2ce97ac49eb633c0ef7a01a181e6 100644 (file)
@@ -334,7 +334,7 @@ extern unsigned long get_clock_freq(void);
 #define CONFIG_SYS_UEC1_TX_CLK         QE_CLK16
 #define CONFIG_SYS_UEC1_ETH_TYPE       GIGA_ETH
 #define CONFIG_SYS_UEC1_PHY_ADDR       7
-#define CONFIG_SYS_UEC1_INTERFACE_TYPE RGMII_ID
+#define CONFIG_SYS_UEC1_INTERFACE_TYPE PHY_INTERFACE_MODE_RGMII_ID
 #define CONFIG_SYS_UEC1_INTERFACE_SPEED 1000
 #endif
 
@@ -346,7 +346,7 @@ extern unsigned long get_clock_freq(void);
 #define CONFIG_SYS_UEC2_TX_CLK         QE_CLK16
 #define CONFIG_SYS_UEC2_ETH_TYPE       GIGA_ETH
 #define CONFIG_SYS_UEC2_PHY_ADDR       1
-#define CONFIG_SYS_UEC2_INTERFACE_TYPE RGMII_ID
+#define CONFIG_SYS_UEC2_INTERFACE_TYPE PHY_INTERFACE_MODE_RGMII_ID
 #define CONFIG_SYS_UEC2_INTERFACE_SPEED 1000
 #endif
 #endif /* CONFIG_QE */
index 5a7e99ee64f63d6e4a5d06d2c6cd417e8181e55c..8835ef5c9171ab35fe18fa2c1ce20e1e7c2bb246 100644 (file)
@@ -385,13 +385,13 @@ extern unsigned long get_clock_freq(void);
 #define CONFIG_SYS_UEC1_TX_CLK         QE_CLK12
 #define CONFIG_SYS_UEC1_ETH_TYPE       GIGA_ETH
 #define CONFIG_SYS_UEC1_PHY_ADDR       7
-#define CONFIG_SYS_UEC1_INTERFACE_TYPE RGMII_ID
+#define CONFIG_SYS_UEC1_INTERFACE_TYPE PHY_INTERFACE_MODE_RGMII_ID
 #define CONFIG_SYS_UEC1_INTERFACE_SPEED 1000
 #elif defined(CONFIG_SYS_UCC_RMII_MODE)
 #define CONFIG_SYS_UEC1_TX_CLK         QE_CLK16        /* CLK16 for RMII */
 #define CONFIG_SYS_UEC1_ETH_TYPE       FAST_ETH
 #define CONFIG_SYS_UEC1_PHY_ADDR       8       /* 0x8 for RMII */
-#define CONFIG_SYS_UEC1_INTERFACE_TYPE RMII
+#define CONFIG_SYS_UEC1_INTERFACE_TYPE PHY_INTERFACE_MODE_RMII
 #define CONFIG_SYS_UEC1_INTERFACE_SPEED 100
 #endif /* CONFIG_SYS_UCC_RGMII_MODE */
 #endif /* CONFIG_UEC_ETH1 */
@@ -406,13 +406,13 @@ extern unsigned long get_clock_freq(void);
 #define CONFIG_SYS_UEC2_TX_CLK         QE_CLK17
 #define CONFIG_SYS_UEC2_ETH_TYPE       GIGA_ETH
 #define CONFIG_SYS_UEC2_PHY_ADDR       1
-#define CONFIG_SYS_UEC2_INTERFACE_TYPE RGMII_ID
+#define CONFIG_SYS_UEC2_INTERFACE_TYPE PHY_INTERFACE_MODE_RGMII_ID
 #define CONFIG_SYS_UEC2_INTERFACE_SPEED 1000
 #elif defined(CONFIG_SYS_UCC_RMII_MODE)
 #define CONFIG_SYS_UEC2_TX_CLK         QE_CLK16        /* CLK 16 for RMII */
 #define CONFIG_SYS_UEC2_ETH_TYPE       FAST_ETH
 #define CONFIG_SYS_UEC2_PHY_ADDR       0x9     /* 0x9 for RMII */
-#define CONFIG_SYS_UEC2_INTERFACE_TYPE RMII
+#define CONFIG_SYS_UEC2_INTERFACE_TYPE PHY_INTERFACE_MODE_RMII
 #define CONFIG_SYS_UEC2_INTERFACE_SPEED 100
 #endif /* CONFIG_SYS_UCC_RGMII_MODE */
 #endif /* CONFIG_UEC_ETH2 */
@@ -427,13 +427,13 @@ extern unsigned long get_clock_freq(void);
 #define CONFIG_SYS_UEC3_TX_CLK         QE_CLK12
 #define CONFIG_SYS_UEC3_ETH_TYPE       GIGA_ETH
 #define CONFIG_SYS_UEC3_PHY_ADDR       2
-#define CONFIG_SYS_UEC3_INTERFACE_TYPE RGMII_ID
+#define CONFIG_SYS_UEC3_INTERFACE_TYPE PHY_INTERFACE_MODE_RGMII_ID
 #define CONFIG_SYS_UEC3_INTERFACE_SPEED 1000
 #elif defined(CONFIG_SYS_UCC_RMII_MODE)
 #define CONFIG_SYS_UEC3_TX_CLK         QE_CLK16 /* CLK_16 for RMII */
 #define CONFIG_SYS_UEC3_ETH_TYPE       FAST_ETH
 #define CONFIG_SYS_UEC3_PHY_ADDR       0xA     /* 0xA for RMII */
-#define CONFIG_SYS_UEC3_INTERFACE_TYPE RMII
+#define CONFIG_SYS_UEC3_INTERFACE_TYPE PHY_INTERFACE_MODE_RMII
 #define CONFIG_SYS_UEC3_INTERFACE_SPEED 100
 #endif /* CONFIG_SYS_UCC_RGMII_MODE */
 #endif /* CONFIG_UEC_ETH3 */
@@ -448,13 +448,13 @@ extern unsigned long get_clock_freq(void);
 #define CONFIG_SYS_UEC4_TX_CLK         QE_CLK17
 #define CONFIG_SYS_UEC4_ETH_TYPE       GIGA_ETH
 #define CONFIG_SYS_UEC4_PHY_ADDR       3
-#define CONFIG_SYS_UEC4_INTERFACE_TYPE RGMII_ID
+#define CONFIG_SYS_UEC4_INTERFACE_TYPE PHY_INTERFACE_MODE_RGMII_ID
 #define CONFIG_SYS_UEC4_INTERFACE_SPEED 1000
 #elif defined(CONFIG_SYS_UCC_RMII_MODE)
 #define CONFIG_SYS_UEC4_TX_CLK         QE_CLK16 /* CLK16 for RMII */
 #define CONFIG_SYS_UEC4_ETH_TYPE       FAST_ETH
 #define CONFIG_SYS_UEC4_PHY_ADDR       0xB     /* 0xB for RMII */
-#define CONFIG_SYS_UEC4_INTERFACE_TYPE RMII
+#define CONFIG_SYS_UEC4_INTERFACE_TYPE PHY_INTERFACE_MODE_RMII
 #define CONFIG_SYS_UEC4_INTERFACE_SPEED 100
 #endif /* CONFIG_SYS_UCC_RGMII_MODE */
 #endif /* CONFIG_UEC_ETH4 */
@@ -468,7 +468,7 @@ extern unsigned long get_clock_freq(void);
 #define CONFIG_SYS_UEC6_TX_CLK         QE_CLK_NONE
 #define CONFIG_SYS_UEC6_ETH_TYPE       GIGA_ETH
 #define CONFIG_SYS_UEC6_PHY_ADDR       4
-#define CONFIG_SYS_UEC6_INTERFACE_TYPE SGMII
+#define CONFIG_SYS_UEC6_INTERFACE_TYPE PHY_INTERFACE_MODE_SGMII
 #define CONFIG_SYS_UEC6_INTERFACE_SPEED 1000
 #endif /* CONFIG_UEC_ETH6 */
 
@@ -481,7 +481,7 @@ extern unsigned long get_clock_freq(void);
 #define CONFIG_SYS_UEC8_TX_CLK         QE_CLK_NONE
 #define CONFIG_SYS_UEC8_ETH_TYPE       GIGA_ETH
 #define CONFIG_SYS_UEC8_PHY_ADDR       6
-#define CONFIG_SYS_UEC8_INTERFACE_TYPE SGMII
+#define CONFIG_SYS_UEC8_INTERFACE_TYPE PHY_INTERFACE_MODE_SGMII
 #define CONFIG_SYS_UEC8_INTERFACE_SPEED 1000
 #endif /* CONFIG_UEC_ETH8 */
 
index 8fcadfee50603c68217d580578416591beed6814..b98e6a137450d899c10d2d19c966441ef5d3b3b2 100644 (file)
 #define CONFIG_SYS_UEC1_TX_CLK         QE_CLK17
 #define CONFIG_SYS_UEC1_ETH_TYPE       FAST_ETH
 #define CONFIG_SYS_UEC1_PHY_ADDR       0
-#define CONFIG_SYS_UEC1_INTERFACE_TYPE RMII
+#define CONFIG_SYS_UEC1_INTERFACE_TYPE PHY_INTERFACE_MODE_RMII
 #define CONFIG_SYS_UEC1_INTERFACE_SPEED 100
 #endif
 
diff --git a/include/fsl_mdio.h b/include/fsl_mdio.h
new file mode 100644 (file)
index 0000000..17ca79c
--- /dev/null
@@ -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(struct tsec_mii_mng *phyregs, int port_addr,
+               int dev_addr, int reg, int value);
+int tsec_local_mdio_read(struct tsec_mii_mng *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 {
+       struct tsec_mii_mng *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/linux/ethtool.h b/include/linux/ethtool.h
new file mode 100644 (file)
index 0000000..fcb20fe
--- /dev/null
@@ -0,0 +1,721 @@
+/*
+ * ethtool.h: Defines for Linux ethtool.
+ *
+ * Copyright (C) 1998 David S. Miller (davem@redhat.com)
+ * Copyright 2001 Jeff Garzik <jgarzik@pobox.com>
+ * Portions Copyright 2001 Sun Microsystems (thockin@sun.com)
+ * Portions Copyright 2002 Intel (eli.kupermann@intel.com,
+ *                                christopher.leech@intel.com,
+ *                                scott.feldman@intel.com)
+ * Portions Copyright (C) Sun Microsystems 2008
+ */
+
+#ifndef _LINUX_ETHTOOL_H
+#define _LINUX_ETHTOOL_H
+
+#include <linux/types.h>
+
+/* This should work for both 32 and 64 bit userland. */
+struct ethtool_cmd {
+       __u32   cmd;
+       __u32   supported;      /* Features this interface supports */
+       __u32   advertising;    /* Features this interface advertises */
+       __u16   speed;          /* The forced speed, 10Mb, 100Mb, gigabit */
+       __u8    duplex;         /* Duplex, half or full */
+       __u8    port;           /* Which connector port */
+       __u8    phy_address;
+       __u8    transceiver;    /* Which transceiver to use */
+       __u8    autoneg;        /* Enable or disable autonegotiation */
+       __u8    mdio_support;
+       __u32   maxtxpkt;       /* Tx pkts before generating tx int */
+       __u32   maxrxpkt;       /* Rx pkts before generating rx int */
+       __u16   speed_hi;
+       __u8    eth_tp_mdix;
+       __u8    reserved2;
+       __u32   lp_advertising; /* Features the link partner advertises */
+       __u32   reserved[2];
+};
+
+static inline void ethtool_cmd_speed_set(struct ethtool_cmd *ep,
+                                               __u32 speed)
+{
+
+       ep->speed = (__u16)speed;
+       ep->speed_hi = (__u16)(speed >> 16);
+}
+
+static inline __u32 ethtool_cmd_speed(struct ethtool_cmd *ep)
+{
+       return (ep->speed_hi << 16) | ep->speed;
+}
+
+#define ETHTOOL_FWVERS_LEN     32
+#define ETHTOOL_BUSINFO_LEN    32
+/* these strings are set to whatever the driver author decides... */
+struct ethtool_drvinfo {
+       __u32   cmd;
+       char    driver[32];     /* driver short name, "tulip", "eepro100" */
+       char    version[32];    /* driver version string */
+       char    fw_version[ETHTOOL_FWVERS_LEN]; /* firmware version string */
+       char    bus_info[ETHTOOL_BUSINFO_LEN];  /* Bus info for this IF. */
+                               /* For PCI devices, use pci_name(pci_dev). */
+       char    reserved1[32];
+       char    reserved2[12];
+                               /*
+                                * Some struct members below are filled in
+                                * using ops->get_sset_count().  Obtaining
+                                * this info from ethtool_drvinfo is now
+                                * deprecated; Use ETHTOOL_GSSET_INFO
+                                * instead.
+                                */
+       __u32   n_priv_flags;   /* number of flags valid in ETHTOOL_GPFLAGS */
+       __u32   n_stats;        /* number of u64's from ETHTOOL_GSTATS */
+       __u32   testinfo_len;
+       __u32   eedump_len;     /* Size of data from ETHTOOL_GEEPROM (bytes) */
+       __u32   regdump_len;    /* Size of data from ETHTOOL_GREGS (bytes) */
+};
+
+#define SOPASS_MAX     6
+/* wake-on-lan settings */
+struct ethtool_wolinfo {
+       __u32   cmd;
+       __u32   supported;
+       __u32   wolopts;
+       __u8    sopass[SOPASS_MAX]; /* SecureOn(tm) password */
+};
+
+/* for passing single values */
+struct ethtool_value {
+       __u32   cmd;
+       __u32   data;
+};
+
+/* for passing big chunks of data */
+struct ethtool_regs {
+       __u32   cmd;
+       __u32   version; /* driver-specific, indicates different chips/revs */
+       __u32   len; /* bytes */
+       __u8    data[0];
+};
+
+/* for passing EEPROM chunks */
+struct ethtool_eeprom {
+       __u32   cmd;
+       __u32   magic;
+       __u32   offset; /* in bytes */
+       __u32   len; /* in bytes */
+       __u8    data[0];
+};
+
+/* for configuring coalescing parameters of chip */
+struct ethtool_coalesce {
+       __u32   cmd;    /* ETHTOOL_{G,S}COALESCE */
+
+       /* How many usecs to delay an RX interrupt after
+        * a packet arrives.  If 0, only rx_max_coalesced_frames
+        * is used.
+        */
+       __u32   rx_coalesce_usecs;
+
+       /* How many packets to delay an RX interrupt after
+        * a packet arrives.  If 0, only rx_coalesce_usecs is
+        * used.  It is illegal to set both usecs and max frames
+        * to zero as this would cause RX interrupts to never be
+        * generated.
+        */
+       __u32   rx_max_coalesced_frames;
+
+       /* Same as above two parameters, except that these values
+        * apply while an IRQ is being serviced by the host.  Not
+        * all cards support this feature and the values are ignored
+        * in that case.
+        */
+       __u32   rx_coalesce_usecs_irq;
+       __u32   rx_max_coalesced_frames_irq;
+
+       /* How many usecs to delay a TX interrupt after
+        * a packet is sent.  If 0, only tx_max_coalesced_frames
+        * is used.
+        */
+       __u32   tx_coalesce_usecs;
+
+       /* How many packets to delay a TX interrupt after
+        * a packet is sent.  If 0, only tx_coalesce_usecs is
+        * used.  It is illegal to set both usecs and max frames
+        * to zero as this would cause TX interrupts to never be
+        * generated.
+        */
+       __u32   tx_max_coalesced_frames;
+
+       /* Same as above two parameters, except that these values
+        * apply while an IRQ is being serviced by the host.  Not
+        * all cards support this feature and the values are ignored
+        * in that case.
+        */
+       __u32   tx_coalesce_usecs_irq;
+       __u32   tx_max_coalesced_frames_irq;
+
+       /* How many usecs to delay in-memory statistics
+        * block updates.  Some drivers do not have an in-memory
+        * statistic block, and in such cases this value is ignored.
+        * This value must not be zero.
+        */
+       __u32   stats_block_coalesce_usecs;
+
+       /* Adaptive RX/TX coalescing is an algorithm implemented by
+        * some drivers to improve latency under low packet rates and
+        * improve throughput under high packet rates.  Some drivers
+        * only implement one of RX or TX adaptive coalescing.  Anything
+        * not implemented by the driver causes these values to be
+        * silently ignored.
+        */
+       __u32   use_adaptive_rx_coalesce;
+       __u32   use_adaptive_tx_coalesce;
+
+       /* When the packet rate (measured in packets per second)
+        * is below pkt_rate_low, the {rx,tx}_*_low parameters are
+        * used.
+        */
+       __u32   pkt_rate_low;
+       __u32   rx_coalesce_usecs_low;
+       __u32   rx_max_coalesced_frames_low;
+       __u32   tx_coalesce_usecs_low;
+       __u32   tx_max_coalesced_frames_low;
+
+       /* When the packet rate is below pkt_rate_high but above
+        * pkt_rate_low (both measured in packets per second) the
+        * normal {rx,tx}_* coalescing parameters are used.
+        */
+
+       /* When the packet rate is (measured in packets per second)
+        * is above pkt_rate_high, the {rx,tx}_*_high parameters are
+        * used.
+        */
+       __u32   pkt_rate_high;
+       __u32   rx_coalesce_usecs_high;
+       __u32   rx_max_coalesced_frames_high;
+       __u32   tx_coalesce_usecs_high;
+       __u32   tx_max_coalesced_frames_high;
+
+       /* How often to do adaptive coalescing packet rate sampling,
+        * measured in seconds.  Must not be zero.
+        */
+       __u32   rate_sample_interval;
+};
+
+/* for configuring RX/TX ring parameters */
+struct ethtool_ringparam {
+       __u32   cmd;    /* ETHTOOL_{G,S}RINGPARAM */
+
+       /* Read only attributes.  These indicate the maximum number
+        * of pending RX/TX ring entries the driver will allow the
+        * user to set.
+        */
+       __u32   rx_max_pending;
+       __u32   rx_mini_max_pending;
+       __u32   rx_jumbo_max_pending;
+       __u32   tx_max_pending;
+
+       /* Values changeable by the user.  The valid values are
+        * in the range 1 to the "*_max_pending" counterpart above.
+        */
+       __u32   rx_pending;
+       __u32   rx_mini_pending;
+       __u32   rx_jumbo_pending;
+       __u32   tx_pending;
+};
+
+/* for configuring link flow control parameters */
+struct ethtool_pauseparam {
+       __u32   cmd;    /* ETHTOOL_{G,S}PAUSEPARAM */
+
+       /* If the link is being auto-negotiated (via ethtool_cmd.autoneg
+        * being true) the user may set 'autonet' here non-zero to have the
+        * pause parameters be auto-negotiated too.  In such a case, the
+        * {rx,tx}_pause values below determine what capabilities are
+        * advertised.
+        *
+        * If 'autoneg' is zero or the link is not being auto-negotiated,
+        * then {rx,tx}_pause force the driver to use/not-use pause
+        * flow control.
+        */
+       __u32   autoneg;
+       __u32   rx_pause;
+       __u32   tx_pause;
+};
+
+#define ETH_GSTRING_LEN                32
+enum ethtool_stringset {
+       ETH_SS_TEST             = 0,
+       ETH_SS_STATS,
+       ETH_SS_PRIV_FLAGS,
+       ETH_SS_NTUPLE_FILTERS,
+       ETH_SS_FEATURES,
+};
+
+/* for passing string sets for data tagging */
+struct ethtool_gstrings {
+       __u32   cmd;            /* ETHTOOL_GSTRINGS */
+       __u32   string_set;     /* string set id e.c. ETH_SS_TEST, etc*/
+       __u32   len;            /* number of strings in the string set */
+       __u8    data[0];
+};
+
+struct ethtool_sset_info {
+       __u32   cmd;            /* ETHTOOL_GSSET_INFO */
+       __u32   reserved;
+       __u64   sset_mask;      /* input: each bit selects an sset to query */
+                               /* output: each bit a returned sset */
+       __u32   data[0];        /* ETH_SS_xxx count, in order, based on bits
+                                  in sset_mask.  One bit implies one
+                                  __u32, two bits implies two
+                                  __u32's, etc. */
+};
+
+enum ethtool_test_flags {
+       ETH_TEST_FL_OFFLINE     = (1 << 0),     /* online / offline */
+       ETH_TEST_FL_FAILED      = (1 << 1),     /* test passed / failed */
+};
+
+/* for requesting NIC test and getting results*/
+struct ethtool_test {
+       __u32   cmd;            /* ETHTOOL_TEST */
+       __u32   flags;          /* ETH_TEST_FL_xxx */
+       __u32   reserved;
+       __u32   len;            /* result length, in number of u64 elements */
+       __u64   data[0];
+};
+
+/* for dumping NIC-specific statistics */
+struct ethtool_stats {
+       __u32   cmd;            /* ETHTOOL_GSTATS */
+       __u32   n_stats;        /* number of u64's being returned */
+       __u64   data[0];
+};
+
+struct ethtool_perm_addr {
+       __u32   cmd;            /* ETHTOOL_GPERMADDR */
+       __u32   size;
+       __u8    data[0];
+};
+
+/* boolean flags controlling per-interface behavior characteristics.
+ * When reading, the flag indicates whether or not a certain behavior
+ * is enabled/present.  When writing, the flag indicates whether
+ * or not the driver should turn on (set) or off (clear) a behavior.
+ *
+ * Some behaviors may read-only (unconditionally absent or present).
+ * If such is the case, return EINVAL in the set-flags operation if the
+ * flag differs from the read-only value.
+ */
+enum ethtool_flags {
+       ETH_FLAG_TXVLAN         = (1 << 7),     /* TX VLAN offload enabled */
+       ETH_FLAG_RXVLAN         = (1 << 8),     /* RX VLAN offload enabled */
+       ETH_FLAG_LRO            = (1 << 15),    /* LRO is enabled */
+       ETH_FLAG_NTUPLE         = (1 << 27),    /* N-tuple filters enabled */
+       ETH_FLAG_RXHASH         = (1 << 28),
+};
+
+/* The following structures are for supporting RX network flow
+ * classification and RX n-tuple configuration. Note, all multibyte
+ * fields, e.g., ip4src, ip4dst, psrc, pdst, spi, etc. are expected to
+ * be in network byte order.
+ */
+
+/**
+ * struct ethtool_tcpip4_spec - flow specification for TCP/IPv4 etc.
+ * @ip4src: Source host
+ * @ip4dst: Destination host
+ * @psrc: Source port
+ * @pdst: Destination port
+ * @tos: Type-of-service
+ *
+ * This can be used to specify a TCP/IPv4, UDP/IPv4 or SCTP/IPv4 flow.
+ */
+struct ethtool_tcpip4_spec {
+       __be32  ip4src;
+       __be32  ip4dst;
+       __be16  psrc;
+       __be16  pdst;
+       __u8    tos;
+};
+
+/**
+ * struct ethtool_ah_espip4_spec - flow specification for IPsec/IPv4
+ * @ip4src: Source host
+ * @ip4dst: Destination host
+ * @spi: Security parameters index
+ * @tos: Type-of-service
+ *
+ * This can be used to specify an IPsec transport or tunnel over IPv4.
+ */
+struct ethtool_ah_espip4_spec {
+       __be32  ip4src;
+       __be32  ip4dst;
+       __be32  spi;
+       __u8    tos;
+};
+
+#define        ETH_RX_NFC_IP4  1
+
+/**
+ * struct ethtool_usrip4_spec - general flow specification for IPv4
+ * @ip4src: Source host
+ * @ip4dst: Destination host
+ * @l4_4_bytes: First 4 bytes of transport (layer 4) header
+ * @tos: Type-of-service
+ * @ip_ver: Value must be %ETH_RX_NFC_IP4; mask must be 0
+ * @proto: Transport protocol number; mask must be 0
+ */
+struct ethtool_usrip4_spec {
+       __be32  ip4src;
+       __be32  ip4dst;
+       __be32  l4_4_bytes;
+       __u8    tos;
+       __u8    ip_ver;
+       __u8    proto;
+};
+
+
+/**
+ * struct ethtool_rxfh_indir - command to get or set RX flow hash indirection
+ * @cmd: Specific command number - %ETHTOOL_GRXFHINDIR or %ETHTOOL_SRXFHINDIR
+ * @size: On entry, the array size of the user buffer.  On return from
+ *     %ETHTOOL_GRXFHINDIR, the array size of the hardware indirection table.
+ * @ring_index: RX ring/queue index for each hash value
+ */
+struct ethtool_rxfh_indir {
+       __u32   cmd;
+       __u32   size;
+       __u32   ring_index[0];
+};
+
+#define ETHTOOL_FLASH_MAX_FILENAME     128
+enum ethtool_flash_op_type {
+       ETHTOOL_FLASH_ALL_REGIONS       = 0,
+};
+
+/* for passing firmware flashing related parameters */
+struct ethtool_flash {
+       __u32   cmd;
+       __u32   region;
+       char    data[ETHTOOL_FLASH_MAX_FILENAME];
+};
+
+/* for returning and changing feature sets */
+
+/**
+ * struct ethtool_get_features_block - block with state of 32 features
+ * @available: mask of changeable features
+ * @requested: mask of features requested to be enabled if possible
+ * @active: mask of currently enabled features
+ * @never_changed: mask of features not changeable for any device
+ */
+struct ethtool_get_features_block {
+       __u32   available;
+       __u32   requested;
+       __u32   active;
+       __u32   never_changed;
+};
+
+/**
+ * struct ethtool_gfeatures - command to get state of device's features
+ * @cmd: command number = %ETHTOOL_GFEATURES
+ * @size: in: number of elements in the features[] array;
+ *       out: number of elements in features[] needed to hold all features
+ * @features: state of features
+ */
+struct ethtool_gfeatures {
+       __u32   cmd;
+       __u32   size;
+       struct ethtool_get_features_block features[0];
+};
+
+/**
+ * struct ethtool_set_features_block - block with request for 32 features
+ * @valid: mask of features to be changed
+ * @requested: values of features to be changed
+ */
+struct ethtool_set_features_block {
+       __u32   valid;
+       __u32   requested;
+};
+
+/**
+ * struct ethtool_sfeatures - command to request change in device's features
+ * @cmd: command number = %ETHTOOL_SFEATURES
+ * @size: array size of the features[] array
+ * @features: feature change masks
+ */
+struct ethtool_sfeatures {
+       __u32   cmd;
+       __u32   size;
+       struct ethtool_set_features_block features[0];
+};
+
+/*
+ * %ETHTOOL_SFEATURES changes features present in features[].valid to the
+ * values of corresponding bits in features[].requested. Bits in .requested
+ * not set in .valid or not changeable are ignored.
+ *
+ * Returns %EINVAL when .valid contains undefined or never-changable bits
+ * or size is not equal to required number of features words (32-bit blocks).
+ * Returns >= 0 if request was completed; bits set in the value mean:
+ *   %ETHTOOL_F_UNSUPPORTED - there were bits set in .valid that are not
+ *     changeable (not present in %ETHTOOL_GFEATURES' features[].available)
+ *     those bits were ignored.
+ *   %ETHTOOL_F_WISH - some or all changes requested were recorded but the
+ *      resulting state of bits masked by .valid is not equal to .requested.
+ *      Probably there are other device-specific constraints on some features
+ *      in the set. When %ETHTOOL_F_UNSUPPORTED is set, .valid is considered
+ *      here as though ignored bits were cleared.
+ *   %ETHTOOL_F_COMPAT - some or all changes requested were made by calling
+ *      compatibility functions. Requested offload state cannot be properly
+ *      managed by kernel.
+ *
+ * Meaning of bits in the masks are obtained by %ETHTOOL_GSSET_INFO (number of
+ * bits in the arrays - always multiple of 32) and %ETHTOOL_GSTRINGS commands
+ * for ETH_SS_FEATURES string set. First entry in the table corresponds to least
+ * significant bit in features[0] fields. Empty strings mark undefined features.
+ */
+enum ethtool_sfeatures_retval_bits {
+       ETHTOOL_F_UNSUPPORTED__BIT,
+       ETHTOOL_F_WISH__BIT,
+       ETHTOOL_F_COMPAT__BIT,
+};
+
+#define ETHTOOL_F_UNSUPPORTED   (1 << ETHTOOL_F_UNSUPPORTED__BIT)
+#define ETHTOOL_F_WISH          (1 << ETHTOOL_F_WISH__BIT)
+#define ETHTOOL_F_COMPAT        (1 << ETHTOOL_F_COMPAT__BIT)
+
+/* CMDs currently supported */
+#define ETHTOOL_GSET           0x00000001 /* Get settings. */
+#define ETHTOOL_SSET           0x00000002 /* Set settings. */
+#define ETHTOOL_GDRVINFO       0x00000003 /* Get driver info. */
+#define ETHTOOL_GREGS          0x00000004 /* Get NIC registers. */
+#define ETHTOOL_GWOL           0x00000005 /* Get wake-on-lan options. */
+#define ETHTOOL_SWOL           0x00000006 /* Set wake-on-lan options. */
+#define ETHTOOL_GMSGLVL                0x00000007 /* Get driver message level */
+#define ETHTOOL_SMSGLVL                0x00000008 /* Set driver msg level. */
+#define ETHTOOL_NWAY_RST       0x00000009 /* Restart autonegotiation. */
+/* Get link status for host, i.e. whether the interface *and* the
+ * physical port (if there is one) are up (ethtool_value). */
+#define ETHTOOL_GLINK          0x0000000a
+#define ETHTOOL_GEEPROM                0x0000000b /* Get EEPROM data */
+#define ETHTOOL_SEEPROM                0x0000000c /* Set EEPROM data. */
+#define ETHTOOL_GCOALESCE      0x0000000e /* Get coalesce config */
+#define ETHTOOL_SCOALESCE      0x0000000f /* Set coalesce config. */
+#define ETHTOOL_GRINGPARAM     0x00000010 /* Get ring parameters */
+#define ETHTOOL_SRINGPARAM     0x00000011 /* Set ring parameters. */
+#define ETHTOOL_GPAUSEPARAM    0x00000012 /* Get pause parameters */
+#define ETHTOOL_SPAUSEPARAM    0x00000013 /* Set pause parameters. */
+#define ETHTOOL_GRXCSUM                0x00000014 /* Get RX hw csum enable (ethtool_value) */
+#define ETHTOOL_SRXCSUM                0x00000015 /* Set RX hw csum enable (ethtool_value) */
+#define ETHTOOL_GTXCSUM                0x00000016 /* Get TX hw csum enable (ethtool_value) */
+#define ETHTOOL_STXCSUM                0x00000017 /* Set TX hw csum enable (ethtool_value) */
+#define ETHTOOL_GSG            0x00000018 /* Get scatter-gather enable
+                                           * (ethtool_value) */
+#define ETHTOOL_SSG            0x00000019 /* Set scatter-gather enable
+                                           * (ethtool_value). */
+#define ETHTOOL_TEST           0x0000001a /* execute NIC self-test. */
+#define ETHTOOL_GSTRINGS       0x0000001b /* get specified string set */
+#define ETHTOOL_PHYS_ID                0x0000001c /* identify the NIC */
+#define ETHTOOL_GSTATS         0x0000001d /* get NIC-specific statistics */
+#define ETHTOOL_GTSO           0x0000001e /* Get TSO enable (ethtool_value) */
+#define ETHTOOL_STSO           0x0000001f /* Set TSO enable (ethtool_value) */
+#define ETHTOOL_GPERMADDR      0x00000020 /* Get permanent hardware address */
+#define ETHTOOL_GUFO           0x00000021 /* Get UFO enable (ethtool_value) */
+#define ETHTOOL_SUFO           0x00000022 /* Set UFO enable (ethtool_value) */
+#define ETHTOOL_GGSO           0x00000023 /* Get GSO enable (ethtool_value) */
+#define ETHTOOL_SGSO           0x00000024 /* Set GSO enable (ethtool_value) */
+#define ETHTOOL_GFLAGS         0x00000025 /* Get flags bitmap(ethtool_value) */
+#define ETHTOOL_SFLAGS         0x00000026 /* Set flags bitmap(ethtool_value) */
+#define ETHTOOL_GPFLAGS                0x00000027 /* Get driver-private flags bitmap */
+#define ETHTOOL_SPFLAGS                0x00000028 /* Set driver-private flags bitmap */
+
+#define ETHTOOL_GRXFH          0x00000029 /* Get RX flow hash configuration */
+#define ETHTOOL_SRXFH          0x0000002a /* Set RX flow hash configuration */
+#define ETHTOOL_GGRO           0x0000002b /* Get GRO enable (ethtool_value) */
+#define ETHTOOL_SGRO           0x0000002c /* Set GRO enable (ethtool_value) */
+#define ETHTOOL_GRXRINGS       0x0000002d /* Get RX rings available for LB */
+#define ETHTOOL_GRXCLSRLCNT    0x0000002e /* Get RX class rule count */
+#define ETHTOOL_GRXCLSRULE     0x0000002f /* Get RX classification rule */
+#define ETHTOOL_GRXCLSRLALL    0x00000030 /* Get all RX classification rule */
+#define ETHTOOL_SRXCLSRLDEL    0x00000031 /* Delete RX classification rule */
+#define ETHTOOL_SRXCLSRLINS    0x00000032 /* Insert RX classification rule */
+#define ETHTOOL_FLASHDEV       0x00000033 /* Flash firmware to device */
+#define ETHTOOL_RESET          0x00000034 /* Reset hardware */
+#define ETHTOOL_SRXNTUPLE      0x00000035 /* Add an n-tuple filter to device */
+#define ETHTOOL_GRXNTUPLE      0x00000036 /* Get n-tuple filters from device */
+#define ETHTOOL_GSSET_INFO     0x00000037 /* Get string set info */
+#define ETHTOOL_GRXFHINDIR     0x00000038 /* Get RX flow hash indir'n table */
+#define ETHTOOL_SRXFHINDIR     0x00000039 /* Set RX flow hash indir'n table */
+
+#define ETHTOOL_GFEATURES      0x0000003a /* Get device offload settings */
+#define ETHTOOL_SFEATURES      0x0000003b /* Change device offload settings */
+
+/* compatibility with older code */
+#define SPARC_ETH_GSET         ETHTOOL_GSET
+#define SPARC_ETH_SSET         ETHTOOL_SSET
+
+/* 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
+
+/* Mode MDI or MDI-X */
+#define ETH_TP_MDI_INVALID     0x00
+#define ETH_TP_MDI             0x01
+#define ETH_TP_MDI_X           0x02
+
+/* Wake-On-Lan options. */
+#define WAKE_PHY               (1 << 0)
+#define WAKE_UCAST             (1 << 1)
+#define WAKE_MCAST             (1 << 2)
+#define WAKE_BCAST             (1 << 3)
+#define WAKE_ARP               (1 << 4)
+#define WAKE_MAGIC             (1 << 5)
+#define WAKE_MAGICSECURE       (1 << 6) /* only meaningful if WAKE_MAGIC */
+
+/* L2-L4 network traffic flow types */
+#define        TCP_V4_FLOW     0x01    /* hash or spec (tcp_ip4_spec) */
+#define        UDP_V4_FLOW     0x02    /* hash or spec (udp_ip4_spec) */
+#define        SCTP_V4_FLOW    0x03    /* hash or spec (sctp_ip4_spec) */
+#define        AH_ESP_V4_FLOW  0x04    /* hash only */
+#define        TCP_V6_FLOW     0x05    /* hash only */
+#define        UDP_V6_FLOW     0x06    /* hash only */
+#define        SCTP_V6_FLOW    0x07    /* hash only */
+#define        AH_ESP_V6_FLOW  0x08    /* hash only */
+#define        AH_V4_FLOW      0x09    /* hash or spec (ah_ip4_spec) */
+#define        ESP_V4_FLOW     0x0a    /* hash or spec (esp_ip4_spec) */
+#define        AH_V6_FLOW      0x0b    /* hash only */
+#define        ESP_V6_FLOW     0x0c    /* hash only */
+#define        IP_USER_FLOW    0x0d    /* spec only (usr_ip4_spec) */
+#define        IPV4_FLOW       0x10    /* hash only */
+#define        IPV6_FLOW       0x11    /* hash only */
+#define        ETHER_FLOW      0x12    /* spec only (ether_spec) */
+
+/* L3-L4 network traffic flow hash options */
+#define        RXH_L2DA        (1 << 1)
+#define        RXH_VLAN        (1 << 2)
+#define        RXH_L3_PROTO    (1 << 3)
+#define        RXH_IP_SRC      (1 << 4)
+#define        RXH_IP_DST      (1 << 5)
+#define        RXH_L4_B_0_1    (1 << 6) /* src port in case of TCP/UDP/SCTP */
+#define        RXH_L4_B_2_3    (1 << 7) /* dst port in case of TCP/UDP/SCTP */
+#define        RXH_DISCARD     (1 << 31)
+
+#define        RX_CLS_FLOW_DISC        0xffffffffffffffffULL
+
+/* Reset flags */
+/* The reset() operation must clear the flags for the components which
+ * were actually reset.  On successful return, the flags indicate the
+ * components which were not reset, either because they do not exist
+ * in the hardware or because they cannot be reset independently.  The
+ * driver must never reset any components that were not requested.
+ */
+enum ethtool_reset_flags {
+       /* These flags represent components dedicated to the interface
+        * the command is addressed to.  Shift any flag left by
+        * ETH_RESET_SHARED_SHIFT to reset a shared component of the
+        * same type.
+        */
+       ETH_RESET_MGMT          = 1 << 0,       /* Management processor */
+       ETH_RESET_IRQ           = 1 << 1,       /* Interrupt requester */
+       ETH_RESET_DMA           = 1 << 2,       /* DMA engine */
+       ETH_RESET_FILTER        = 1 << 3,       /* Filtering/flow direction */
+       ETH_RESET_OFFLOAD       = 1 << 4,       /* Protocol offload */
+       ETH_RESET_MAC           = 1 << 5,       /* Media access controller */
+       ETH_RESET_PHY           = 1 << 6,       /* Transceiver/PHY */
+       ETH_RESET_RAM           = 1 << 7,       /* RAM shared between
+                                                * multiple components */
+
+       ETH_RESET_DEDICATED     = 0x0000ffff,   /* All components dedicated to
+                                                * this interface */
+       ETH_RESET_ALL           = 0xffffffff,   /* All components used by this
+                                                * interface, even if shared */
+};
+#define ETH_RESET_SHARED_SHIFT 16
+
+#endif /* _LINUX_ETHTOOL_H */
diff --git a/include/linux/mdio.h b/include/linux/mdio.h
new file mode 100644 (file)
index 0000000..022d772
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+ * linux/mdio.h: definitions for MDIO (clause 45) transceivers
+ * Copyright 2006-2009 Solarflare Communications Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#ifndef __LINUX_MDIO_H__
+#define __LINUX_MDIO_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 */
+#define MDIO_AN_EEE_ADV                60      /* EEE advertisement */
+
+/* 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 */
+
+/* AN EEE Advertisement register. */
+#define MDIO_AN_EEE_ADV_100TX          0x0002  /* Advertise 100TX EEE cap */
+#define MDIO_AN_EEE_ADV_1000T          0x0004  /* Advertise 1000T EEE cap */
+
+/* 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)
+
+#define MDIO_PRTAD_NONE                        (-1)
+#define MDIO_DEVAD_NONE                        (-1)
+#define MDIO_EMULATE_C22               4
+
+#endif /* __LINUX_MDIO_H__ */
index 42dc12715cd54ccb9690b1d62c139b84d5072f17..7e70cf81e4d3d49e7a171c8af50ed39cb93e0da6 100644 (file)
 #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);
+};
+
+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 +102,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 (file)
index 0000000..d5817bf
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * 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>
+#include <linux/ethtool.h>
+#include <linux/mdio.h>
+
+#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_MODE_NONE /* Must be last */
+} phy_interface_t;
+
+static const char *phy_interface_strings[] = {
+       [PHY_INTERFACE_MODE_MII]                = "mii",
+       [PHY_INTERFACE_MODE_GMII]               = "gmii",
+       [PHY_INTERFACE_MODE_SGMII]              = "sgmii",
+       [PHY_INTERFACE_MODE_TBI]                = "tbi",
+       [PHY_INTERFACE_MODE_RMII]               = "rmii",
+       [PHY_INTERFACE_MODE_RGMII]              = "rgmii",
+       [PHY_INTERFACE_MODE_RGMII_ID]           = "rgmii-id",
+       [PHY_INTERFACE_MODE_RGMII_RXID]         = "rgmii-rxid",
+       [PHY_INTERFACE_MODE_RGMII_TXID]         = "rgmii-txid",
+       [PHY_INTERFACE_MODE_RTBI]               = "rtbi",
+       [PHY_INTERFACE_MODE_XGMII]              = "xgmii",
+       [PHY_INTERFACE_MODE_NONE]               = "",
+};
+
+static inline const char *phy_string_for_interface(phy_interface_t i)
+{
+       /* Default to unknown */
+       if (i > PHY_INTERFACE_MODE_NONE)
+               i = PHY_INTERFACE_MODE_NONE;
+
+       return phy_interface_strings[i];
+}
+
+
+struct phy_device;
+
+#define MDIO_NAME_LEN 32
+
+struct mii_dev {
+       struct list_head link;
+       char name[MDIO_NAME_LEN];
+       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;
+};
+
+/* 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;
+       unsigned int mmds;
+
+       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;
+};
+
+static inline 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);
+}
+
+static inline 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);
+}
+
+#ifdef CONFIG_PHYLIB_10G
+extern struct phy_driver gen10g_driver;
+
+/* For now, XGMII is the only 10G interface */
+static inline int is_10g_interface(phy_interface_t interface)
+{
+       return interface == PHY_INTERFACE_MODE_XGMII;
+}
+
+#endif
+
+int phy_init(void);
+int phy_reset(struct phy_device *phydev);
+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_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);
+int gen10g_discover_mmds(struct phy_device *phydev);
+
+int phy_atheros_init(void);
+int phy_broadcom_init(void);
+int phy_davicom_init(void);
+int phy_lxt_init(void);
+int phy_marvell_init(void);
+int phy_micrel_init(void);
+int phy_natsemi_init(void);
+int phy_realtek_init(void);
+int phy_teranetics_init(void);
+int phy_vitesse_init(void);
+#endif
index d56ec2cd0c5fce8caf79f9bd582924c6f7c00622..8ed30aca09b312c911f185d6e160a48a446ca00e 100644 (file)
@@ -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@motorola.com)
  * author Andy Fleming
 
 #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 = (struct tsec_mii_mng *)(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 = (struct tsec_mii_mng *)(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
 
 #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 {
-       volatile tsec_t *regs;
-       volatile tsec_mdio_t *phyregs;
-       volatile tsec_mdio_t *phyregs_sgmii;
-       struct phy_info *phyinfo;
+       tsec_t *regs;
+       struct tsec_mii_mng *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;
+       struct tsec_mii_mng *miiregs_sgmii;
        char *devname;
+       char *mii_devname;
+       phy_interface_t interface;
        unsigned int phyaddr;
        u32 flags;
 };
index 3a7ff50bf3905c1602f4ab3ea705ebb7a2bfbf7d..65238340601bc5a984b2eef59e18f86977b639b7 100644 (file)
--- 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