Преглед на файлове

Merge branch 'phylib' of git://git.denx.de/u-boot-mmc

Wolfgang Denk преди 14 години
родител
ревизия
aef293bc85
променени са 52 файла, в които са добавени 4733 реда и са изтрити 1451 реда
  1. 3 20
      arch/powerpc/cpu/mpc8xxx/fdt.c
  2. 9 0
      arch/powerpc/include/asm/config.h
  3. 12 15
      arch/powerpc/include/asm/fsl_enet.h
  4. 6 4
      board/freescale/mpc8360emds/mpc8360emds.c
  5. 9 1
      board/freescale/mpc837xemds/mpc837xemds.c
  6. 6 0
      board/freescale/mpc8536ds/mpc8536ds.c
  7. 30 0
      board/freescale/mpc8544ds/mpc8544ds.c
  8. 3 1
      board/freescale/mpc8569mds/mpc8569mds.c
  9. 6 0
      board/freescale/mpc8572ds/mpc8572ds.c
  10. 6 0
      board/freescale/p1022ds/p1022ds.c
  11. 6 0
      board/freescale/p1_p2_rdb/p1_p2_rdb.c
  12. 7 0
      board/freescale/p2020ds/p2020ds.c
  13. 4 0
      common/Makefile
  14. 286 0
      common/cmd_mdio.c
  15. 210 101
      common/miiphyutil.c
  16. 1 1
      drivers/net/Makefile
  17. 9 9
      drivers/net/dm9000x.c
  18. 12 12
      drivers/net/enc28j60.c
  19. 120 0
      drivers/net/fsl_mdio.c
  20. 13 0
      drivers/net/phy/Makefile
  21. 48 0
      drivers/net/phy/atheros.c
  22. 288 0
      drivers/net/phy/broadcom.c
  23. 98 0
      drivers/net/phy/davicom.c
  24. 105 0
      drivers/net/phy/generic_10g.c
  25. 87 0
      drivers/net/phy/lxt.c
  26. 367 0
      drivers/net/phy/marvell.c
  27. 40 0
      drivers/net/phy/micrel.c
  28. 96 0
      drivers/net/phy/natsemi.c
  29. 755 0
      drivers/net/phy/phy.c
  30. 130 0
      drivers/net/phy/realtek.c
  31. 62 0
      drivers/net/phy/teranetics.c
  32. 242 0
      drivers/net/phy/vitesse.c
  33. 113 839
      drivers/net/tsec.c
  34. 13 11
      drivers/net/uli526x.c
  35. 29 30
      drivers/qe/uec.c
  36. 2 1
      drivers/qe/uec.h
  37. 91 90
      drivers/qe/uec_phy.c
  38. 32 0
      include/config_phylib_all_drivers.h
  39. 2 2
      include/configs/MPC8323ERDB.h
  40. 2 2
      include/configs/MPC832XEMDS.h
  41. 2 2
      include/configs/MPC8360EMDS.h
  42. 2 2
      include/configs/MPC8360ERDK.h
  43. 2 2
      include/configs/MPC8568MDS.h
  44. 10 10
      include/configs/MPC8569MDS.h
  45. 1 1
      include/configs/kmeter1.h
  46. 62 0
      include/fsl_mdio.h
  47. 721 0
      include/linux/ethtool.h
  48. 278 0
      include/linux/mdio.h
  49. 35 18
      include/miiphy.h
  50. 229 0
      include/phy.h
  51. 25 277
      include/tsec.h
  52. 6 0
      net/eth.c

+ 3 - 20
arch/powerpc/cpu/mpc8xxx/fdt.c

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

+ 9 - 0
arch/powerpc/include/asm/config.h

@@ -80,6 +80,15 @@
 #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
 

+ 12 - 15
arch/powerpc/include/asm/fsl_enet.h

@@ -13,21 +13,18 @@
 #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 */

+ 6 - 4
board/freescale/mpc8360emds/mpc8360emds.c

@@ -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
 		}

+ 9 - 1
board/freescale/mpc837xemds/mpc837xemds.c

@@ -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: "

+ 6 - 0
board/freescale/mpc8536ds/mpc8536ds.c

@@ -36,6 +36,7 @@
 #include <libfdt.h>
 #include <spd_sdram.h>
 #include <fdt_support.h>
+#include <fsl_mdio.h>
 #include <tsec.h>
 #include <netdev.h>
 #include <sata.h>
@@ -234,6 +235,7 @@ int board_early_init_r(void)
 int board_eth_init(bd_t *bis)
 {
 #ifdef CONFIG_TSEC_ENET
+	struct fsl_pq_mdio_info mdio_info;
 	struct tsec_info_struct tsec_info[2];
 	int num = 0;
 
@@ -268,6 +270,10 @@ int board_eth_init(bd_t *bis)
 	}
 #endif
 
+	mdio_info.regs = (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);

+ 30 - 0
board/freescale/mpc8544ds/mpc8544ds.c

@@ -33,6 +33,7 @@
 #include <miiphy.h>
 #include <libfdt.h>
 #include <fdt_support.h>
+#include <fsl_mdio.h>
 #include <tsec.h>
 #include <netdev.h>
 
@@ -248,9 +249,35 @@ get_board_sys_clk(ulong dummy)
 	return val;
 }
 
+
+#define MIIM_CIS8204_SLED_CON		0x1b
+#define MIIM_CIS8204_SLEDCON_INIT	0x1115
+/*
+ * Hack to write all 4 PHYs with the LED values
+ */
+int board_phy_config(struct phy_device *phydev)
+{
+	static int do_once;
+	uint phyid;
+	struct mii_dev *bus = phydev->bus;
+
+	if (do_once)
+		return 0;
+
+	for (phyid = 0; phyid < 4; phyid++)
+		bus->write(bus, phyid, MDIO_DEVAD_NONE, MIIM_CIS8204_SLED_CON,
+				MIIM_CIS8204_SLEDCON_INIT);
+
+	do_once = 1;
+
+	return 0;
+}
+
+
 int board_eth_init(bd_t *bis)
 {
 #ifdef CONFIG_TSEC_ENET
+	struct fsl_pq_mdio_info mdio_info;
 	struct tsec_info_struct tsec_info[2];
 	int num = 0;
 
@@ -282,6 +309,9 @@ int board_eth_init(bd_t *bis)
 		fsl_sgmii_riser_init(tsec_info, num);
 	}
 
+	mdio_info.regs = (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

+ 3 - 1
board/freescale/mpc8569mds/mpc8569mds.c

@@ -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 "

+ 6 - 0
board/freescale/mpc8572ds/mpc8572ds.c

@@ -35,6 +35,7 @@
 #include <libfdt.h>
 #include <fdt_support.h>
 #include <tsec.h>
+#include <fsl_mdio.h>
 #include <netdev.h>
 
 #include "../common/sgmii_riser.h"
@@ -187,6 +188,7 @@ int board_early_init_r(void)
 #ifdef CONFIG_TSEC_ENET
 int board_eth_init(bd_t *bis)
 {
+	struct fsl_pq_mdio_info mdio_info;
 	struct tsec_info_struct tsec_info[4];
 	int num = 0;
 
@@ -233,6 +235,10 @@ int board_eth_init(bd_t *bis)
 	fsl_sgmii_riser_init(tsec_info, num);
 #endif
 
+	mdio_info.regs = (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);

+ 6 - 0
board/freescale/p1022ds/p1022ds.c

@@ -22,6 +22,7 @@
 #include <asm/io.h>
 #include <libfdt.h>
 #include <fdt_support.h>
+#include <fsl_mdio.h>
 #include <tsec.h>
 #include <asm/fsl_law.h>
 #include <netdev.h>
@@ -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);
 }
 

+ 6 - 0
board/freescale/p1_p2_rdb/p1_p2_rdb.c

@@ -31,6 +31,7 @@
 #include <miiphy.h>
 #include <libfdt.h>
 #include <fdt_support.h>
+#include <fsl_mdio.h>
 #include <tsec.h>
 #include <vsc7385.h>
 #include <netdev.h>
@@ -179,6 +180,7 @@ int board_early_init_r(void)
 #ifdef CONFIG_TSEC_ENET
 int board_eth_init(bd_t *bis)
 {
+	struct fsl_pq_mdio_info mdio_info;
 	struct tsec_info_struct tsec_info[4];
 	int num = 0;
 	char *tmp;
@@ -216,6 +218,10 @@ int board_eth_init(bd_t *bis)
 		puts("No address specified for VSC7385 microcode.\n");
 #endif
 
+	mdio_info.regs = (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);

+ 7 - 0
board/freescale/p2020ds/p2020ds.c

@@ -34,6 +34,7 @@
 #include <miiphy.h>
 #include <libfdt.h>
 #include <fdt_support.h>
+#include <fsl_mdio.h>
 #include <tsec.h>
 #include <asm/fsl_law.h>
 #include <netdev.h>
@@ -201,6 +202,7 @@ int board_early_init_r(void)
 #ifdef CONFIG_TSEC_ENET
 int board_eth_init(bd_t *bis)
 {
+	struct fsl_pq_mdio_info mdio_info;
 	struct tsec_info_struct tsec_info[4];
 	int num = 0;
 
@@ -235,6 +237,11 @@ int board_eth_init(bd_t *bis)
 	fsl_sgmii_riser_init(tsec_info, num);
 #endif
 
+	mdio_info.regs = (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);

+ 4 - 0
common/Makefile

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

+ 286 - 0
common/cmd_mdio.c

@@ -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"
+);

+ 210 - 101
common/miiphyutil.c

@@ -28,6 +28,7 @@
 
 #include <common.h>
 #include <miiphy.h>
+#include <phy.h>
 
 #include <asm/types.h>
 #include <linux/list.h>
@@ -39,27 +40,18 @@
 
 #undef debug
 #ifdef MII_DEBUG
-#define debug(fmt,args...)	printf (fmt ,##args)
+#define debug(fmt, args...)	printf(fmt, ##args)
 #else
-#define debug(fmt,args...)
+#define debug(fmt, args...)
 #endif /* MII_DEBUG */
 
-struct mii_dev {
-	struct list_head link;
-	const char *name;
-	int (*read) (const char *devname, unsigned char addr,
-		     unsigned char reg, unsigned short *value);
-	int (*write) (const char *devname, unsigned char addr,
-		      unsigned char reg, unsigned short value);
-};
-
 static struct list_head mii_devs;
 static struct mii_dev *current_mii;
 
 /*
  * Lookup the mii_dev struct by the registered device name.
  */
-static struct mii_dev *miiphy_get_dev_by_name(const char *devname, int quiet)
+struct mii_dev *miiphy_get_dev_by_name(const char *devname)
 {
 	struct list_head *entry;
 	struct mii_dev *dev;
@@ -75,8 +67,6 @@ static struct mii_dev *miiphy_get_dev_by_name(const char *devname, int quiet)
 			return dev;
 	}
 
-	if (!quiet)
-		printf("No such device: %s\n", devname);
 	return NULL;
 }
 
@@ -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

+ 1 - 1
drivers/net/Makefile

@@ -79,7 +79,7 @@ COBJS-$(CONFIG_TIGON3) += tigon3.o
 COBJS-$(CONFIG_TIGON3) += bcm570x_autoneg.o
 COBJS-$(CONFIG_TIGON3) += 5701rls.o
 COBJS-$(CONFIG_DRIVER_TI_EMAC) += davinci_emac.o
-COBJS-$(CONFIG_TSEC_ENET) += tsec.o
+COBJS-$(CONFIG_TSEC_ENET) += tsec.o fsl_mdio.o
 COBJS-$(CONFIG_TSI108_ETH) += tsi108_eth.o
 COBJS-$(CONFIG_ULI526X) += uli526x.o
 COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o

+ 9 - 9
drivers/net/dm9000x.c

@@ -110,8 +110,8 @@ static board_info_t dm9000_info;
 
 /* function declaration ------------------------------------- */
 static int dm9000_probe(void);
-static u16 phy_read(int);
-static void phy_write(int, u16);
+static u16 dm9000_phy_read(int);
+static void dm9000_phy_write(int, u16);
 static u8 DM9000_ior(int);
 static void DM9000_iow(int reg, u8 value);
 
@@ -361,7 +361,7 @@ static int dm9000_init(struct eth_device *dev, bd_t *bd)
 	DM9000_iow(DM9000_IMR, IMR_PAR);
 
 	i = 0;
-	while (!(phy_read(1) & 0x20)) {	/* autonegation complete bit */
+	while (!(dm9000_phy_read(1) & 0x20)) {	/* autonegation complete bit */
 		udelay(1000);
 		i++;
 		if (i == 10000) {
@@ -371,7 +371,7 @@ static int dm9000_init(struct eth_device *dev, bd_t *bd)
 	}
 
 	/* see what we've got */
-	lnk = phy_read(17) >> 12;
+	lnk = dm9000_phy_read(17) >> 12;
 	printf("operating at ");
 	switch (lnk) {
 	case 1:
@@ -445,7 +445,7 @@ static void dm9000_halt(struct eth_device *netdev)
 	DM9000_DBG("%s\n", __func__);
 
 	/* RESET devie */
-	phy_write(0, 0x8000);	/* PHY RESET */
+	dm9000_phy_write(0, 0x8000);	/* PHY RESET */
 	DM9000_iow(DM9000_GPR, 0x01);	/* Power-Down PHY */
 	DM9000_iow(DM9000_IMR, 0x80);	/* Disable all interrupt */
 	DM9000_iow(DM9000_RCR, 0x00);	/* Disable RX */
@@ -581,7 +581,7 @@ DM9000_iow(int reg, u8 value)
    Read a word from phyxcer
 */
 static u16
-phy_read(int reg)
+dm9000_phy_read(int reg)
 {
 	u16 val;
 
@@ -593,7 +593,7 @@ phy_read(int reg)
 	val = (DM9000_ior(DM9000_EPDRH) << 8) | DM9000_ior(DM9000_EPDRL);
 
 	/* The read data keeps on REG_0D & REG_0E */
-	DM9000_DBG("phy_read(0x%x): 0x%x\n", reg, val);
+	DM9000_DBG("dm9000_phy_read(0x%x): 0x%x\n", reg, val);
 	return val;
 }
 
@@ -601,7 +601,7 @@ phy_read(int reg)
    Write a word to phyxcer
 */
 static void
-phy_write(int reg, u16 value)
+dm9000_phy_write(int reg, u16 value)
 {
 
 	/* Fill the phyxcer register into REG_0C */
@@ -613,7 +613,7 @@ phy_write(int reg, u16 value)
 	DM9000_iow(DM9000_EPCR, 0xa);	/* Issue phyxcer write command */
 	udelay(500);			/* Wait write complete */
 	DM9000_iow(DM9000_EPCR, 0x0);	/* Clear phyxcer write command */
-	DM9000_DBG("phy_write(reg:0x%x, value:0x%x)\n", reg, value);
+	DM9000_DBG("dm9000_phy_write(reg:0x%x, value:0x%x)\n", reg, value);
 }
 
 int dm9000_initialize(bd_t *bis)

+ 12 - 12
drivers/net/enc28j60.c

@@ -314,7 +314,7 @@ static void enc_release_bus(enc_dev_t *enc)
 /*
  * Read PHY register
  */
-static u16 phy_read(enc_dev_t *enc, const u8 addr)
+static u16 enc_phy_read(enc_dev_t *enc, const u8 addr)
 {
 	uint64_t etime;
 	u8 status;
@@ -339,7 +339,7 @@ static u16 phy_read(enc_dev_t *enc, const u8 addr)
 /*
  * Write PHY register
  */
-static void phy_write(enc_dev_t *enc, const u8 addr, const u16 data)
+static void enc_phy_write(enc_dev_t *enc, const u8 addr, const u16 data)
 {
 	uint64_t etime;
 	u8 status;
@@ -374,7 +374,7 @@ static int enc_phy_link_wait(enc_dev_t *enc)
 
 #ifdef CONFIG_ENC_SILENTLINK
 	/* check if we have a link, then just return */
-	status = phy_read(enc, PHY_REG_PHSTAT1);
+	status = enc_phy_read(enc, PHY_REG_PHSTAT1);
 	if (status & ENC_PHSTAT1_LLSTAT)
 		return 0;
 #endif
@@ -382,10 +382,10 @@ static int enc_phy_link_wait(enc_dev_t *enc)
 	/* wait for link with 1 second timeout */
 	etime = get_ticks() + get_tbclk();
 	while (get_ticks() <= etime) {
-		status = phy_read(enc, PHY_REG_PHSTAT1);
+		status = enc_phy_read(enc, PHY_REG_PHSTAT1);
 		if (status & ENC_PHSTAT1_LLSTAT) {
 			/* now we have a link */
-			status = phy_read(enc, PHY_REG_PHSTAT2);
+			status = enc_phy_read(enc, PHY_REG_PHSTAT2);
 			duplex = (status & ENC_PHSTAT2_DPXSTAT) ? 1 : 0;
 			printf("%s: link up, 10Mbps %s-duplex\n",
 				enc->dev->name, duplex ? "full" : "half");
@@ -678,8 +678,8 @@ static int enc_setup(enc_dev_t *enc)
 	enc->bank = 0xff;	/* invalidate current bank in enc28j60 */
 
 	/* verify PHY identification */
-	phid1 = phy_read(enc, PHY_REG_PHID1);
-	phid2 = phy_read(enc, PHY_REG_PHID2) & ENC_PHID2_MASK;
+	phid1 = enc_phy_read(enc, PHY_REG_PHID1);
+	phid2 = enc_phy_read(enc, PHY_REG_PHID2) & ENC_PHID2_MASK;
 	if (phid1 != ENC_PHID1_VALUE || phid2 != ENC_PHID2_VALUE) {
 		printf("%s: failed to identify PHY. Found %04x:%04x\n",
 			enc->dev->name, phid1, phid2);
@@ -694,7 +694,7 @@ static int enc_setup(enc_dev_t *enc)
 	 * Prevent automatic loopback of data beeing transmitted by setting
 	 * ENC_PHCON2_HDLDIS
 	 */
-	phy_write(enc, PHY_REG_PHCON2, (1<<8));
+	enc_phy_write(enc, PHY_REG_PHCON2, (1<<8));
 
 	/*
 	 * LEDs configuration
@@ -702,10 +702,10 @@ static int enc_setup(enc_dev_t *enc)
 	 * LEDB: LBCFG = 0111 -> display TX & RX activity
 	 * STRCH = 1 -> LED pulses
 	 */
-	phy_write(enc, PHY_REG_PHLCON, 0x0472);
+	enc_phy_write(enc, PHY_REG_PHLCON, 0x0472);
 
 	/* Reset PDPXMD-bit => half duplex */
-	phy_write(enc, PHY_REG_PHCON1, 0);
+	enc_phy_write(enc, PHY_REG_PHCON1, 0);
 
 #ifdef CONFIG_USE_IRQ
 	/* enable interrupts */
@@ -771,7 +771,7 @@ int enc_miiphy_read(const char *devname, u8 phy_adr, u8 reg, u16 *value)
 		enc_release_bus(enc);
 		return -1;
 	}
-	*value = phy_read(enc, reg);
+	*value = enc_phy_read(enc, reg);
 	enc_release_bus(enc);
 	return 0;
 }
@@ -796,7 +796,7 @@ int enc_miiphy_write(const char *devname, u8 phy_adr, u8 reg, u16 value)
 		enc_release_bus(enc);
 		return -1;
 	}
-	phy_write(enc, reg, value);
+	enc_phy_write(enc, reg, value);
 	enc_release_bus(enc);
 	return 0;
 }

+ 120 - 0
drivers/net/fsl_mdio.c

@@ -0,0 +1,120 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *	Jun-jie Zhang <b18070@freescale.com>
+ *	Mingkai Hu <Mingkai.hu@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#include <common.h>
+#include <miiphy.h>
+#include <phy.h>
+#include <fsl_mdio.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+#include <asm/fsl_enet.h>
+
+void tsec_local_mdio_write(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);
+}

+ 13 - 0
drivers/net/phy/Makefile

@@ -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))

+ 48 - 0
drivers/net/phy/atheros.c

@@ -0,0 +1,48 @@
+/*
+ * Atheros PHY drivers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * author Andy Fleming
+ *
+ */
+#include <phy.h>
+
+static int ar8021_config(struct phy_device *phydev)
+{
+	phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x05);
+	phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x3D47);
+
+	return 0;
+}
+
+struct phy_driver AR8021_driver =  {
+	.name = "AR8021",
+	.uid = 0x4dd040,
+	.mask = 0xfffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = ar8021_config,
+	.startup = genphy_startup,
+	.shutdown = genphy_shutdown,
+};
+
+int phy_atheros_init(void)
+{
+	phy_register(&AR8021_driver);
+
+	return 0;
+}

+ 288 - 0
drivers/net/phy/broadcom.c

@@ -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;
+}

+ 98 - 0
drivers/net/phy/davicom.c

@@ -0,0 +1,98 @@
+/*
+ * Davicom PHY drivers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ * author Andy Fleming
+ *
+ */
+#include <phy.h>
+
+#define MIIM_DM9161_SCR                0x10
+#define MIIM_DM9161_SCR_INIT   0x0610
+
+/* DM9161 Specified Configuration and Status Register */
+#define MIIM_DM9161_SCSR       0x11
+#define MIIM_DM9161_SCSR_100F  0x8000
+#define MIIM_DM9161_SCSR_100H  0x4000
+#define MIIM_DM9161_SCSR_10F   0x2000
+#define MIIM_DM9161_SCSR_10H   0x1000
+
+/* DM9161 10BT Configuration/Status */
+#define MIIM_DM9161_10BTCSR    0x12
+#define MIIM_DM9161_10BTCSR_INIT       0x7800
+
+
+/* Davicom DM9161E */
+static int dm9161_config(struct phy_device *phydev)
+{
+	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_ISOLATE);
+	/* Do not bypass the scrambler/descrambler */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_DM9161_SCR,
+			MIIM_DM9161_SCR_INIT);
+	/* Clear 10BTCSR to default */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_DM9161_10BTCSR,
+			MIIM_DM9161_10BTCSR_INIT);
+
+	genphy_config_aneg(phydev);
+
+	return 0;
+}
+
+static int dm9161_parse_status(struct phy_device *phydev)
+{
+	int mii_reg;
+
+	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_DM9161_SCSR);
+
+	if (mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_100H))
+		phydev->speed = SPEED_100;
+	else
+		phydev->speed = SPEED_10;
+
+	if (mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_10F))
+		phydev->duplex = DUPLEX_FULL;
+	else
+		phydev->duplex = DUPLEX_HALF;
+
+	return 0;
+}
+
+static int dm9161_startup(struct phy_device *phydev)
+{
+	genphy_update_link(phydev);
+	dm9161_parse_status(phydev);
+
+	return 0;
+}
+
+static struct phy_driver DM9161_driver = {
+	.name = "Davicom DM9161E",
+	.uid = 0x181b880,
+	.mask = 0xffffff0,
+	.features = PHY_BASIC_FEATURES,
+	.config = &dm9161_config,
+	.startup = &dm9161_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+int phy_davicom_init(void)
+{
+	phy_register(&DM9161_driver);
+
+	return 0;
+}

+ 105 - 0
drivers/net/phy/generic_10g.c

@@ -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,
+};
+

+ 87 - 0
drivers/net/phy/lxt.c

@@ -0,0 +1,87 @@
+/*
+ * LXT PHY drivers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ * author Andy Fleming
+ *
+ */
+#include <phy.h>
+
+/* LXT971 Status 2 registers */
+#define MIIM_LXT971_SR2                     0x11  /* Status Register 2  */
+#define MIIM_LXT971_SR2_SPEED_MASK 0x4200
+#define MIIM_LXT971_SR2_10HDX     0x0000  /*  10 Mbit half duplex selected */
+#define MIIM_LXT971_SR2_10FDX     0x0200  /*  10 Mbit full duplex selected */
+#define MIIM_LXT971_SR2_100HDX    0x4000  /* 100 Mbit half duplex selected */
+#define MIIM_LXT971_SR2_100FDX    0x4200  /* 100 Mbit full duplex selected */
+
+
+/* LXT971 */
+static int lxt971_parse_status(struct phy_device *phydev)
+{
+	int mii_reg;
+	int speed;
+
+	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_LXT971_SR2);
+	speed = mii_reg & MIIM_LXT971_SR2_SPEED_MASK;
+
+	switch (speed) {
+	case MIIM_LXT971_SR2_10HDX:
+		phydev->speed = SPEED_10;
+		phydev->duplex = DUPLEX_HALF;
+		break;
+	case MIIM_LXT971_SR2_10FDX:
+		phydev->speed = SPEED_10;
+		phydev->duplex = DUPLEX_FULL;
+		break;
+	case MIIM_LXT971_SR2_100HDX:
+		phydev->speed = SPEED_100;
+		phydev->duplex = DUPLEX_HALF;
+		break;
+	default:
+		phydev->speed = SPEED_100;
+		phydev->duplex = DUPLEX_FULL;
+	}
+
+	return 0;
+}
+
+static int lxt971_startup(struct phy_device *phydev)
+{
+	genphy_update_link(phydev);
+	lxt971_parse_status(phydev);
+
+	return 0;
+}
+
+static struct phy_driver LXT971_driver = {
+	.name = "LXT971",
+	.uid = 0x1378e0,
+	.mask = 0xfffff0,
+	.features = PHY_BASIC_FEATURES,
+	.config = &genphy_config_aneg,
+	.startup = &lxt971_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+int phy_lxt_init(void)
+{
+	phy_register(&LXT971_driver);
+
+	return 0;
+}

+ 367 - 0
drivers/net/phy/marvell.c

@@ -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;
+}

+ 40 - 0
drivers/net/phy/micrel.c

@@ -0,0 +1,40 @@
+/*
+ * Micrel PHY drivers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ * author Andy Fleming
+ *
+ */
+#include <phy.h>
+
+static struct phy_driver KSZ804_driver = {
+	.name = "Micrel KSZ804",
+	.uid = 0x221510,
+	.mask = 0xfffff0,
+	.features = PHY_BASIC_FEATURES,
+	.config = &genphy_config,
+	.startup = &genphy_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+int phy_micrel_init(void)
+{
+	phy_register(&KSZ804_driver);
+
+	return 0;
+}

+ 96 - 0
drivers/net/phy/natsemi.c

@@ -0,0 +1,96 @@
+/*
+ * National Semiconductor PHY drivers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ * author Andy Fleming
+ *
+ */
+#include <phy.h>
+
+/* DP83865 Link and Auto-Neg Status Register */
+#define MIIM_DP83865_LANR      0x11
+#define MIIM_DP83865_SPD_MASK  0x0018
+#define MIIM_DP83865_SPD_1000  0x0010
+#define MIIM_DP83865_SPD_100   0x0008
+#define MIIM_DP83865_DPX_FULL  0x0002
+
+
+/* NatSemi DP83865 */
+static int dp83865_config(struct phy_device *phydev)
+{
+	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
+	genphy_config_aneg(phydev);
+
+	return 0;
+}
+
+static int dp83865_parse_status(struct phy_device *phydev)
+{
+	int mii_reg;
+
+	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_DP83865_LANR);
+
+	switch (mii_reg & MIIM_DP83865_SPD_MASK) {
+
+	case MIIM_DP83865_SPD_1000:
+		phydev->speed = SPEED_1000;
+		break;
+
+	case MIIM_DP83865_SPD_100:
+		phydev->speed = SPEED_100;
+		break;
+
+	default:
+		phydev->speed = SPEED_10;
+		break;
+
+	}
+
+	if (mii_reg & MIIM_DP83865_DPX_FULL)
+		phydev->duplex = DUPLEX_FULL;
+	else
+		phydev->duplex = DUPLEX_HALF;
+
+	return 0;
+}
+
+static int dp83865_startup(struct phy_device *phydev)
+{
+	genphy_update_link(phydev);
+	dp83865_parse_status(phydev);
+
+	return 0;
+}
+
+
+static struct phy_driver DP83865_driver = {
+	.name = "NatSemi DP83865",
+	.uid = 0x20005c70,
+	.mask = 0xfffffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &dp83865_config,
+	.startup = &dp83865_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+int phy_natsemi_init(void)
+{
+	phy_register(&DP83865_driver);
+
+	return 0;
+}

+ 755 - 0
drivers/net/phy/phy.c

@@ -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;
+}

+ 130 - 0
drivers/net/phy/realtek.c

@@ -0,0 +1,130 @@
+/*
+ * RealTek PHY drivers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ * author Andy Fleming
+ *
+ */
+#include <config.h>
+#include <common.h>
+#include <phy.h>
+
+#define PHY_AUTONEGOTIATE_TIMEOUT 5000
+
+/* RTL8211B PHY Status Register */
+#define MIIM_RTL8211B_PHY_STATUS       0x11
+#define MIIM_RTL8211B_PHYSTAT_SPEED    0xc000
+#define MIIM_RTL8211B_PHYSTAT_GBIT     0x8000
+#define MIIM_RTL8211B_PHYSTAT_100      0x4000
+#define MIIM_RTL8211B_PHYSTAT_DUPLEX   0x2000
+#define MIIM_RTL8211B_PHYSTAT_SPDDONE  0x0800
+#define MIIM_RTL8211B_PHYSTAT_LINK     0x0400
+
+
+/* RealTek RTL8211B */
+static int rtl8211b_config(struct phy_device *phydev)
+{
+	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
+
+	genphy_config_aneg(phydev);
+
+	return 0;
+}
+
+static int rtl8211b_parse_status(struct phy_device *phydev)
+{
+	unsigned int speed;
+	unsigned int mii_reg;
+
+	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211B_PHY_STATUS);
+
+	if (!(mii_reg & MIIM_RTL8211B_PHYSTAT_SPDDONE)) {
+		int i = 0;
+
+		/* in case of timeout ->link is cleared */
+		phydev->link = 1;
+		puts("Waiting for PHY realtime link");
+		while (!(mii_reg & MIIM_RTL8211B_PHYSTAT_SPDDONE)) {
+			/* Timeout reached ? */
+			if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
+				puts(" TIMEOUT !\n");
+				phydev->link = 0;
+				break;
+			}
+
+			if ((i++ % 1000) == 0)
+				putc('.');
+			udelay(1000);	/* 1 ms */
+			mii_reg = phy_read(phydev, MDIO_DEVAD_NONE,
+					MIIM_RTL8211B_PHY_STATUS);
+		}
+		puts(" done\n");
+		udelay(500000);	/* another 500 ms (results in faster booting) */
+	} else {
+		if (mii_reg & MIIM_RTL8211B_PHYSTAT_LINK)
+			phydev->link = 1;
+		else
+			phydev->link = 0;
+	}
+
+	if (mii_reg & MIIM_RTL8211B_PHYSTAT_DUPLEX)
+		phydev->duplex = DUPLEX_FULL;
+	else
+		phydev->duplex = DUPLEX_HALF;
+
+	speed = (mii_reg & MIIM_RTL8211B_PHYSTAT_SPEED);
+
+	switch (speed) {
+	case MIIM_RTL8211B_PHYSTAT_GBIT:
+		phydev->speed = SPEED_1000;
+		break;
+	case MIIM_RTL8211B_PHYSTAT_100:
+		phydev->speed = SPEED_100;
+		break;
+	default:
+		phydev->speed = SPEED_10;
+	}
+
+	return 0;
+}
+
+static int rtl8211b_startup(struct phy_device *phydev)
+{
+	/* Read the Status (2x to make sure link is right) */
+	genphy_update_link(phydev);
+	rtl8211b_parse_status(phydev);
+
+	return 0;
+}
+
+static struct phy_driver RTL8211B_driver = {
+	.name = "RealTek RTL8211B",
+	.uid = 0x1cc910,
+	.mask = 0xfffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &rtl8211b_config,
+	.startup = &rtl8211b_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+int phy_realtek_init(void)
+{
+	phy_register(&RTL8211B_driver);
+
+	return 0;
+}

+ 62 - 0
drivers/net/phy/teranetics.c

@@ -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;
+}

+ 242 - 0
drivers/net/phy/vitesse.c

@@ -0,0 +1,242 @@
+/*
+ * Vitesse PHY drivers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ * author Andy Fleming
+ *
+ */
+#include <miiphy.h>
+
+/* Cicada Auxiliary Control/Status Register */
+#define MIIM_CIS82xx_AUX_CONSTAT	0x1c
+#define MIIM_CIS82xx_AUXCONSTAT_INIT	0x0004
+#define MIIM_CIS82xx_AUXCONSTAT_DUPLEX	0x0020
+#define MIIM_CIS82xx_AUXCONSTAT_SPEED	0x0018
+#define MIIM_CIS82xx_AUXCONSTAT_GBIT	0x0010
+#define MIIM_CIS82xx_AUXCONSTAT_100	0x0008
+
+/* Cicada Extended Control Register 1 */
+#define MIIM_CIS82xx_EXT_CON1		0x17
+#define MIIM_CIS8201_EXTCON1_INIT	0x0000
+
+/* Cicada 8204 Extended PHY Control Register 1 */
+#define MIIM_CIS8204_EPHY_CON		0x17
+#define MIIM_CIS8204_EPHYCON_INIT	0x0006
+#define MIIM_CIS8204_EPHYCON_RGMII	0x1100
+
+/* Cicada 8204 Serial LED Control Register */
+#define MIIM_CIS8204_SLED_CON		0x1b
+#define MIIM_CIS8204_SLEDCON_INIT	0x1115
+
+/* Vitesse VSC8601 Extended PHY Control Register 1 */
+#define MIIM_VSC8601_EPHY_CON		0x17
+#define MIIM_VSC8601_EPHY_CON_INIT_SKEW	0x1120
+#define MIIM_VSC8601_SKEW_CTRL		0x1c
+
+#define PHY_EXT_PAGE_ACCESS    0x1f
+
+/* CIS8201 */
+static int vitesse_config(struct phy_device *phydev)
+{
+	/* Override PHY config settings */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT,
+			MIIM_CIS82xx_AUXCONSTAT_INIT);
+	/* Set up the interface mode */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_EXT_CON1,
+			MIIM_CIS8201_EXTCON1_INIT);
+
+	genphy_config_aneg(phydev);
+
+	return 0;
+}
+
+static int vitesse_parse_status(struct phy_device *phydev)
+{
+	int speed;
+	int mii_reg;
+
+	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT);
+
+	if (mii_reg & MIIM_CIS82xx_AUXCONSTAT_DUPLEX)
+		phydev->duplex = DUPLEX_FULL;
+	else
+		phydev->duplex = DUPLEX_HALF;
+
+	speed = mii_reg & MIIM_CIS82xx_AUXCONSTAT_SPEED;
+	switch (speed) {
+	case MIIM_CIS82xx_AUXCONSTAT_GBIT:
+		phydev->speed = SPEED_1000;
+		break;
+	case MIIM_CIS82xx_AUXCONSTAT_100:
+		phydev->speed = SPEED_100;
+		break;
+	default:
+		phydev->speed = SPEED_10;
+		break;
+	}
+
+	return 0;
+}
+
+static int vitesse_startup(struct phy_device *phydev)
+{
+	genphy_update_link(phydev);
+	vitesse_parse_status(phydev);
+
+	return 0;
+}
+
+static int cis8204_config(struct phy_device *phydev)
+{
+	/* Override PHY config settings */
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT,
+			MIIM_CIS82xx_AUXCONSTAT_INIT);
+
+	genphy_config_aneg(phydev);
+
+	if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
+			(phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
+			(phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) ||
+			(phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID))
+		phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8204_EPHY_CON,
+				MIIM_CIS8204_EPHYCON_INIT |
+				MIIM_CIS8204_EPHYCON_RGMII);
+	else
+		phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8204_EPHY_CON,
+				MIIM_CIS8204_EPHYCON_INIT);
+
+	return 0;
+}
+
+/* Vitesse VSC8601 */
+int vsc8601_config(struct phy_device *phydev)
+{
+	/* Configure some basic stuff */
+#ifdef CONFIG_SYS_VSC8601_SKEWFIX
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8601_EPHY_CON,
+			MIIM_VSC8601_EPHY_CON_INIT_SKEW);
+#if defined(CONFIG_SYS_VSC8601_SKEW_TX) && defined(CONFIG_SYS_VSC8601_SKEW_RX)
+	phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 1);
+#define VSC8101_SKEW \
+	((CONFIG_SYS_VSC8601_SKEW_TX << 14) \
+	| (CONFIG_SYS_VSC8601_SKEW_RX << 12))
+	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8601_SKEW_CTRL,
+			VSC8101_SKEW);
+	phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0);
+#endif
+#endif
+
+	genphy_config_aneg(phydev);
+
+	return 0;
+}
+
+static struct phy_driver VSC8211_driver = {
+	.name	= "Vitesse VSC8211",
+	.uid	= 0xfc4b0,
+	.mask	= 0xffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &vitesse_config,
+	.startup = &vitesse_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+static struct phy_driver VSC8221_driver = {
+	.name = "Vitesse VSC8221",
+	.uid = 0xfc550,
+	.mask = 0xffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &genphy_config_aneg,
+	.startup = &vitesse_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+static struct phy_driver VSC8244_driver = {
+	.name = "Vitesse VSC8244",
+	.uid = 0xfc6c0,
+	.mask = 0xffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &genphy_config_aneg,
+	.startup = &vitesse_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+static struct phy_driver VSC8234_driver = {
+	.name = "Vitesse VSC8234",
+	.uid = 0xfc620,
+	.mask = 0xffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &genphy_config_aneg,
+	.startup = &vitesse_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+static struct phy_driver VSC8601_driver = {
+	.name = "Vitesse VSC8601",
+	.uid = 0x70420,
+	.mask = 0xffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &vsc8601_config,
+	.startup = &vitesse_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+static struct phy_driver VSC8641_driver = {
+	.name = "Vitesse VSC8641",
+	.uid = 0x70430,
+	.mask = 0xffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &genphy_config_aneg,
+	.startup = &vitesse_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+/* Vitesse bought Cicada, so we'll put these here */
+static struct phy_driver cis8201_driver = {
+	.name = "CIS8201",
+	.uid = 0xfc410,
+	.mask = 0xffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &vitesse_config,
+	.startup = &vitesse_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+static struct phy_driver cis8204_driver = {
+	.name = "Cicada Cis8204",
+	.uid = 0xfc440,
+	.mask = 0xffff0,
+	.features = PHY_GBIT_FEATURES,
+	.config = &cis8204_config,
+	.startup = &vitesse_startup,
+	.shutdown = &genphy_shutdown,
+};
+
+int 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;
+}

Файловите разлики са ограничени, защото са твърде много
+ 113 - 839
drivers/net/tsec.c


+ 13 - 11
drivers/net/uli526x.c

@@ -175,9 +175,9 @@ static u16 read_srom_word(long, int);
 static void uli526x_descriptor_init(struct uli526x_board_info *, unsigned long);
 static void allocate_rx_buffer(struct uli526x_board_info *);
 static void update_cr6(u32, unsigned long);
-static u16 phy_read(unsigned long, u8, u8, u32);
+static u16 uli_phy_read(unsigned long, u8, u8, u32);
 static u16 phy_readby_cr10(unsigned long, u8, u8);
-static void phy_write(unsigned long, u8, u8, u16, u32);
+static void uli_phy_write(unsigned long, u8, u8, u16, u32);
 static void phy_writeby_cr10(unsigned long, u8, u8, u16);
 static void phy_write_1bit(unsigned long, u32, u32);
 static u16 phy_read_1bit(unsigned long, u32);
@@ -349,7 +349,7 @@ static void uli526x_disable(struct eth_device *dev)
 		/* Reset & stop ULI526X board */
 		outl(ULI526X_RESET, db->ioaddr + DCR0);
 		udelay(5);
-		phy_write(db->ioaddr, db->phy_addr, 0, 0x8000, db->chip_id);
+		uli_phy_write(db->ioaddr, db->phy_addr, 0, 0x8000, db->chip_id);
 
 		/* reset the board */
 		db->cr6_data &= ~(CR6_RXSC | CR6_TXSC);	/* Disable Tx/Rx */
@@ -385,7 +385,7 @@ static void uli526x_init(struct eth_device *dev)
 	db->tx_packet_cnt = 0;
 	for (phy_tmp = 0; phy_tmp < 32; phy_tmp++) {
 		/* peer add */
-		phy_value = phy_read(db->ioaddr, phy_tmp, 3, db->chip_id);
+		phy_value = uli_phy_read(db->ioaddr, phy_tmp, 3, db->chip_id);
 		if (phy_value != 0xffff && phy_value != 0) {
 			db->phy_addr = phy_tmp;
 			break;
@@ -404,10 +404,10 @@ static void uli526x_init(struct eth_device *dev)
 
 	if (!(inl(db->ioaddr + DCR12) & 0x8)) {
 		/* Phyxcer capability setting */
-		phy_reg_reset = phy_read(db->ioaddr,
+		phy_reg_reset = uli_phy_read(db->ioaddr,
 			db->phy_addr, 0, db->chip_id);
 		phy_reg_reset = (phy_reg_reset | 0x8000);
-		phy_write(db->ioaddr, db->phy_addr, 0,
+		uli_phy_write(db->ioaddr, db->phy_addr, 0,
 			phy_reg_reset, db->chip_id);
 		udelay(500);
 
@@ -781,7 +781,8 @@ static void uli526x_set_phyxcer(struct uli526x_board_info *db)
 	u16 phy_reg;
 
 	/* Phyxcer capability setting */
-	phy_reg = phy_read(db->ioaddr, db->phy_addr, 4, db->chip_id) & ~0x01e0;
+	phy_reg = uli_phy_read(db->ioaddr,
+			db->phy_addr, 4, db->chip_id) & ~0x01e0;
 
 	if (db->media_mode & ULI526X_AUTO) {
 		/* AUTO Mode */
@@ -802,10 +803,10 @@ static void uli526x_set_phyxcer(struct uli526x_board_info *db)
 		phy_reg |= db->PHY_reg4;
 		db->media_mode |= ULI526X_AUTO;
 	}
-	phy_write(db->ioaddr, db->phy_addr, 4, phy_reg, db->chip_id);
+	uli_phy_write(db->ioaddr, db->phy_addr, 4, phy_reg, db->chip_id);
 
 	/* Restart Auto-Negotiation */
-	phy_write(db->ioaddr, db->phy_addr, 0, 0x1200, db->chip_id);
+	uli_phy_write(db->ioaddr, db->phy_addr, 0, 0x1200, db->chip_id);
 	udelay(50);
 }
 
@@ -813,7 +814,7 @@ static void uli526x_set_phyxcer(struct uli526x_board_info *db)
  *	Write a word to Phy register
  */
 
-static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset,
+static void uli_phy_write(unsigned long iobase, u8 phy_addr, u8 offset,
 	u16 phy_data, u32 chip_id)
 {
 	u16 i;
@@ -862,7 +863,8 @@ static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset,
  *	Read a word data from phy register
  */
 
-static u16 phy_read(unsigned long iobase, u8 phy_addr, u8 offset, u32 chip_id)
+static u16 uli_phy_read(unsigned long iobase, u8 phy_addr, u8 offset,
+			u32 chip_id)
 {
 	int i;
 	u16 phy_data;

+ 29 - 30
drivers/qe/uec.c

@@ -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);
 

+ 2 - 1
drivers/qe/uec.h

@@ -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;
 

+ 91 - 90
drivers/qe/uec_phy.c

@@ -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);

+ 32 - 0
include/config_phylib_all_drivers.h

@@ -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 */

+ 2 - 2
include/configs/MPC8323ERDB.h

@@ -348,7 +348,7 @@
 #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
 
@@ -360,7 +360,7 @@
 #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
 

+ 2 - 2
include/configs/MPC832XEMDS.h

@@ -361,7 +361,7 @@
 #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
 
@@ -373,7 +373,7 @@
 #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
 

+ 2 - 2
include/configs/MPC8360EMDS.h

@@ -402,7 +402,7 @@
 #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
 
@@ -414,7 +414,7 @@
 #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
 

+ 2 - 2
include/configs/MPC8360ERDK.h

@@ -319,7 +319,7 @@
 #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
 
@@ -331,7 +331,7 @@
 #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
 

+ 2 - 2
include/configs/MPC8568MDS.h

@@ -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 */

+ 10 - 10
include/configs/MPC8569MDS.h

@@ -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 */
 

+ 1 - 1
include/configs/kmeter1.h

@@ -295,7 +295,7 @@
 #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
 

+ 62 - 0
include/fsl_mdio.h

@@ -0,0 +1,62 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *	Jun-jie Zhang <b18070@freescale.com>
+ *	Mingkai Hu <Mingkai.hu@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#ifndef __FSL_PHY_H__
+#define __FSL_PHY_H__
+
+#include <net.h>
+#include <miiphy.h>
+#include <asm/fsl_enet.h>
+
+/* PHY register offsets */
+#define PHY_EXT_PAGE_ACCESS	0x1f
+
+/* MII Management Configuration Register */
+#define MIIMCFG_RESET_MGMT          0x80000000
+#define MIIMCFG_MGMT_CLOCK_SELECT   0x00000007
+#define MIIMCFG_INIT_VALUE	    0x00000003
+
+/* MII Management Command Register */
+#define MIIMCOM_READ_CYCLE	0x00000001
+#define MIIMCOM_SCAN_CYCLE	0x00000002
+
+/* MII Management Address Register */
+#define MIIMADD_PHY_ADDR_SHIFT	8
+
+/* MII Management Indicator Register */
+#define MIIMIND_BUSY		0x00000001
+#define MIIMIND_NOTVALID	0x00000004
+
+void tsec_local_mdio_write(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__ */
+

+ 721 - 0
include/linux/ethtool.h

@@ -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 */

+ 278 - 0
include/linux/mdio.h

@@ -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__ */

+ 35 - 18
include/miiphy.h

@@ -34,35 +34,52 @@
 #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
 

+ 229 - 0
include/phy.h

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

+ 25 - 277
include/tsec.h

@@ -7,7 +7,7 @@
  *  terms of the GNU Public License, Version 2, incorporated
  *  herein by reference.
  *
- * Copyright 2004, 2007, 2009  Freescale Semiconductor, Inc.
+ * Copyright 2004, 2007, 2009, 2011  Freescale Semiconductor, Inc.
  * (C) Copyright 2003, Motorola, Inc.
  * maintained by Xianghua Xiao (x.xiao@motorola.com)
  * author Andy Fleming
@@ -19,30 +19,36 @@
 
 #include <net.h>
 #include <config.h>
+#include <phy.h>
+#include <asm/fsl_enet.h>
 
 #define TSEC_SIZE 		0x01000
 #define TSEC_MDIO_OFFSET	0x01000
 
+#define CONFIG_SYS_MDIO_BASE_ADDR (TSEC_BASE_ADDR + 0x520)
+
+#define DEFAULT_MII_NAME "FSL_MDIO"
+
 #define STD_TSEC_INFO(num) \
 {			\
 	.regs = (tsec_t *)(TSEC_BASE_ADDR + ((num - 1) * TSEC_SIZE)), \
-	.miiregs = (tsec_mdio_t *)(MDIO_BASE_ADDR), \
-	.miiregs_sgmii = (tsec_mdio_t *)(MDIO_BASE_ADDR \
+	.miiregs_sgmii = (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
@@ -96,204 +100,14 @@
 
 #define ECNTRL_INIT_SETTINGS	0x00001000
 #define ECNTRL_TBI_MODE		0x00000020
+#define ECNTRL_REDUCED_MODE	0x00000010
 #define ECNTRL_R100		0x00000008
+#define ECNTRL_REDUCED_MII_MODE	0x00000004
 #define ECNTRL_SGMII_MODE	0x00000002
 
-#define miim_end -2
-#define miim_read -1
-
 #ifndef CONFIG_SYS_TBIPA_VALUE
     #define CONFIG_SYS_TBIPA_VALUE	0x1f
 #endif
-#define MIIMCFG_INIT_VALUE	0x00000003
-#define MIIMCFG_RESET		0x80000000
-
-#define MIIMIND_BUSY		0x00000001
-#define MIIMIND_NOTVALID	0x00000004
-
-#define MIIM_CONTROL		0x00
-#define MIIM_CONTROL_RESET	0x00009140
-#define MIIM_CONTROL_INIT	0x00001140
-#define MIIM_CONTROL_RESTART	0x00001340
-#define MIIM_ANEN		0x00001000
-
-#define MIIM_CR			0x00
-#define MIIM_CR_RST		0x00008000
-#define MIIM_CR_INIT		0x00001000
-
-#define MIIM_STATUS		0x1
-#define MIIM_STATUS_AN_DONE	0x00000020
-#define MIIM_STATUS_LINK	0x0004
-
-#define MIIM_PHYIR1		0x2
-#define MIIM_PHYIR2		0x3
-
-#define MIIM_ANAR		0x4
-#define MIIM_ANAR_INIT		0x1e1
-
-#define MIIM_TBI_ANLPBPA	0x5
-#define MIIM_TBI_ANLPBPA_HALF	0x00000040
-#define MIIM_TBI_ANLPBPA_FULL	0x00000020
-
-#define MIIM_TBI_ANEX		0x6
-#define MIIM_TBI_ANEX_NP	0x00000004
-#define MIIM_TBI_ANEX_PRX	0x00000002
-
-#define MIIM_GBIT_CONTROL	0x9
-#define MIIM_GBIT_CONTROL_INIT	0xe00
-
-#define MIIM_EXT_PAGE_ACCESS	0x1f
-
-/* Broadcom BCM54xx -- taken from linux sungem_phy */
-#define MIIM_BCM54xx_AUXCNTL			0x18
-#define MIIM_BCM54xx_AUXCNTL_ENCODE(val)	((val & 0x7) << 12)|(val & 0x7)
-#define MIIM_BCM54xx_AUXSTATUS			0x19
-#define MIIM_BCM54xx_AUXSTATUS_LINKMODE_MASK	0x0700
-#define MIIM_BCM54xx_AUXSTATUS_LINKMODE_SHIFT	8
-
-#define MIIM_BCM54XX_SHD	0x1c	/* 0x1c shadow registers */
-#define MIIM_BCM54XX_SHD_WRITE	0x8000
-#define MIIM_BCM54XX_SHD_VAL(x)	((x & 0x1f) << 10)
-#define MIIM_BCM54XX_SHD_DATA(x)	((x & 0x3ff) << 0)
-#define MIIM_BCM54XX_SHD_WR_ENCODE(val, data)	\
-	(MIIM_BCM54XX_SHD_WRITE | MIIM_BCM54XX_SHD_VAL(val) | \
-	 MIIM_BCM54XX_SHD_DATA(data))
-
-#define MIIM_BCM54XX_EXP_DATA	0x15	/* Expansion register data */
-#define MIIM_BCM54XX_EXP_SEL	0x17	/* Expansion register select */
-#define MIIM_BCM54XX_EXP_SEL_SSD	0x0e00	/* Secondary SerDes select */
-#define MIIM_BCM54XX_EXP_SEL_ER	0x0f00	/* Expansion register select */
-
-/* Cicada Auxiliary Control/Status Register */
-#define MIIM_CIS8201_AUX_CONSTAT	0x1c
-#define MIIM_CIS8201_AUXCONSTAT_INIT	0x0004
-#define MIIM_CIS8201_AUXCONSTAT_DUPLEX	0x0020
-#define MIIM_CIS8201_AUXCONSTAT_SPEED	0x0018
-#define MIIM_CIS8201_AUXCONSTAT_GBIT	0x0010
-#define MIIM_CIS8201_AUXCONSTAT_100	0x0008
-
-/* Cicada Extended Control Register 1 */
-#define MIIM_CIS8201_EXT_CON1		0x17
-#define MIIM_CIS8201_EXTCON1_INIT	0x0000
-
-/* Cicada 8204 Extended PHY Control Register 1 */
-#define MIIM_CIS8204_EPHY_CON		0x17
-#define MIIM_CIS8204_EPHYCON_INIT	0x0006
-#define MIIM_CIS8204_EPHYCON_RGMII	0x1100
-
-/* Cicada 8204 Serial LED Control Register */
-#define MIIM_CIS8204_SLED_CON		0x1b
-#define MIIM_CIS8204_SLEDCON_INIT	0x1115
-
-#define MIIM_GBIT_CON		0x09
-#define MIIM_GBIT_CON_ADVERT	0x0e00
-
-/* Entry for Vitesse VSC8244 regs starts here */
-/* Vitesse VSC8244 Auxiliary Control/Status Register */
-#define MIIM_VSC8244_AUX_CONSTAT	0x1c
-#define MIIM_VSC8244_AUXCONSTAT_INIT	0x0000
-#define MIIM_VSC8244_AUXCONSTAT_DUPLEX	0x0020
-#define MIIM_VSC8244_AUXCONSTAT_SPEED	0x0018
-#define MIIM_VSC8244_AUXCONSTAT_GBIT	0x0010
-#define MIIM_VSC8244_AUXCONSTAT_100	0x0008
-#define MIIM_CONTROL_INIT_LOOPBACK	0x4000
-
-/* Vitesse VSC8244 Extended PHY Control Register 1 */
-#define MIIM_VSC8244_EPHY_CON		0x17
-#define MIIM_VSC8244_EPHYCON_INIT	0x0006
-
-/* Vitesse VSC8244 Serial LED Control Register */
-#define MIIM_VSC8244_LED_CON		0x1b
-#define MIIM_VSC8244_LEDCON_INIT	0xF011
-
-/* Entry for Vitesse VSC8601 regs starts here (Not complete) */
-/* Vitesse VSC8601 Extended PHY Control Register 1 */
-#define MIIM_VSC8601_EPHY_CON		0x17
-#define MIIM_VSC8601_EPHY_CON_INIT_SKEW	0x1120
-#define MIIM_VSC8601_SKEW_CTRL		0x1c
-
-/* 88E1011 PHY Status Register */
-#define MIIM_88E1011_PHY_STATUS		0x11
-#define MIIM_88E1011_PHYSTAT_SPEED	0xc000
-#define MIIM_88E1011_PHYSTAT_GBIT	0x8000
-#define MIIM_88E1011_PHYSTAT_100	0x4000
-#define MIIM_88E1011_PHYSTAT_DUPLEX	0x2000
-#define MIIM_88E1011_PHYSTAT_SPDDONE	0x0800
-#define MIIM_88E1011_PHYSTAT_LINK	0x0400
-
-#define MIIM_88E1011_PHY_SCR		0x10
-#define MIIM_88E1011_PHY_MDI_X_AUTO	0x0060
-
-/* 88E1111 PHY LED Control Register */
-#define MIIM_88E1111_PHY_LED_CONTROL	24
-#define MIIM_88E1111_PHY_LED_DIRECT	0x4100
-#define MIIM_88E1111_PHY_LED_COMBINE	0x411C
-
-/* 88E1121 PHY LED Control Register */
-#define MIIM_88E1121_PHY_LED_CTRL	16
-#define MIIM_88E1121_PHY_LED_PAGE	3
-#define MIIM_88E1121_PHY_LED_DEF	0x0030
-
-/* 88E1121 PHY IRQ Enable/Status Register */
-#define MIIM_88E1121_PHY_IRQ_EN		18
-#define MIIM_88E1121_PHY_IRQ_STATUS	19
-
-#define MIIM_88E1121_PHY_PAGE		22
-
-/* 88E1145 Extended PHY Specific Control Register */
-#define MIIM_88E1145_PHY_EXT_CR 20
-#define MIIM_M88E1145_RGMII_RX_DELAY	0x0080
-#define MIIM_M88E1145_RGMII_TX_DELAY	0x0002
-
-#define MIIM_88E1145_PHY_PAGE	29
-#define MIIM_88E1145_PHY_CAL_OV 30
-
-/* RTL8211B PHY Status Register */
-#define MIIM_RTL8211B_PHY_STATUS	0x11
-#define MIIM_RTL8211B_PHYSTAT_SPEED	0xc000
-#define MIIM_RTL8211B_PHYSTAT_GBIT	0x8000
-#define MIIM_RTL8211B_PHYSTAT_100	0x4000
-#define MIIM_RTL8211B_PHYSTAT_DUPLEX	0x2000
-#define MIIM_RTL8211B_PHYSTAT_SPDDONE	0x0800
-#define MIIM_RTL8211B_PHYSTAT_LINK	0x0400
-
-/* DM9161 Control register values */
-#define MIIM_DM9161_CR_STOP	0x0400
-#define MIIM_DM9161_CR_RSTAN	0x1200
-
-#define MIIM_DM9161_SCR		0x10
-#define MIIM_DM9161_SCR_INIT	0x0610
-
-/* DM9161 Specified Configuration and Status Register */
-#define MIIM_DM9161_SCSR	0x11
-#define MIIM_DM9161_SCSR_100F	0x8000
-#define MIIM_DM9161_SCSR_100H	0x4000
-#define MIIM_DM9161_SCSR_10F	0x2000
-#define MIIM_DM9161_SCSR_10H	0x1000
-
-/* DM9161 10BT Configuration/Status */
-#define MIIM_DM9161_10BTCSR	0x12
-#define MIIM_DM9161_10BTCSR_INIT	0x7800
-
-/* LXT971 Status 2 registers */
-#define MIIM_LXT971_SR2		     0x11  /* Status Register 2  */
-#define MIIM_LXT971_SR2_SPEED_MASK 0x4200
-#define MIIM_LXT971_SR2_10HDX	   0x0000  /*  10 Mbit half duplex selected */
-#define MIIM_LXT971_SR2_10FDX	   0x0200  /*  10 Mbit full duplex selected */
-#define MIIM_LXT971_SR2_100HDX	   0x4000  /* 100 Mbit half duplex selected */
-#define MIIM_LXT971_SR2_100FDX	   0x4200  /* 100 Mbit full duplex selected */
-
-/* DP83865 Control register values */
-#define MIIM_DP83865_CR_INIT	0x9200
-
-/* DP83865 Link and Auto-Neg Status Register */
-#define MIIM_DP83865_LANR	0x11
-#define MIIM_DP83865_SPD_MASK	0x0018
-#define MIIM_DP83865_SPD_1000	0x0010
-#define MIIM_DP83865_SPD_100	0x0008
-#define MIIM_DP83865_DPX_FULL	0x0002
-
-#define MIIM_READ_COMMAND	0x00000001
 
 #define MRBLR_INIT_SETTINGS	PKTSIZE_ALIGN
 
@@ -467,22 +281,6 @@ typedef struct tsec_hash_regs
 	uint	res2[24];
 } tsec_hash_t;
 
-typedef struct tsec_mdio {
-	uint	res1[4];
-	uint	ieventm;
-	uint	imaskm;
-	uint	res2;
-	uint	emapm;
-	uint	res3[320];
-	uint	miimcfg;	/* MII Management: Configuration */
-	uint	miimcom;	/* MII Management: Command */
-	uint	miimadd;	/* MII Management: Address */
-	uint	miimcon;	/* MII Management: Control */
-	uint	miimstat;	/* MII Management: Status */
-	uint	miimind;	/* MII Management: Indicators */
-	uint	res4[690];
-} tsec_mdio_t;
-
 typedef struct tsec
 {
 	/* General Control and Status Registers (0x2_n000) */
@@ -578,79 +376,29 @@ typedef struct tsec
 	uint	resc00[256];
 } tsec_t;
 
-#define TSEC_GIGABIT (1)
+#define TSEC_GIGABIT (1 << 0)
 
-/* This flag currently only has
- * meaning if we're using the eTSEC */
+/* These flags currently only have meaning if we're using the eTSEC */
 #define TSEC_REDUCED	(1 << 1)	/* MAC-PHY interface uses RGMII */
 #define TSEC_SGMII	(1 << 2)	/* MAC-PHY interface uses SGMII */
-#define TSEC_FIBER	(1 << 3)	/* PHY uses fiber, eg 1000 Base-X */
 
 struct tsec_private {
-	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;
 };

+ 6 - 0
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

Някои файлове не бяха показани, защото твърде много файлове са промени