diff options
52 files changed, 4895 insertions, 2315 deletions
| diff --git a/arch/powerpc/cpu/mpc8xxx/fdt.c b/arch/powerpc/cpu/mpc8xxx/fdt.c index 0c166fd6c..520cb9028 100644 --- a/arch/powerpc/cpu/mpc8xxx/fdt.c +++ b/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 diff --git a/arch/powerpc/include/asm/config.h b/arch/powerpc/include/asm/config.h index 536f14233..624d8c2cc 100644 --- a/arch/powerpc/include/asm/config.h +++ b/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 diff --git a/arch/powerpc/include/asm/fsl_enet.h b/arch/powerpc/include/asm/fsl_enet.h index 4fb2857f3..8227b667c 100644 --- a/arch/powerpc/include/asm/fsl_enet.h +++ b/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 */ diff --git a/board/freescale/mpc8360emds/mpc8360emds.c b/board/freescale/mpc8360emds/mpc8360emds.c index 0babd2648..51d803520 100644 --- a/board/freescale/mpc8360emds/mpc8360emds.c +++ b/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  		} diff --git a/board/freescale/mpc837xemds/mpc837xemds.c b/board/freescale/mpc837xemds/mpc837xemds.c index 51dd692c2..650a4fe48 100644 --- a/board/freescale/mpc837xemds/mpc837xemds.c +++ b/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: " diff --git a/board/freescale/mpc8536ds/mpc8536ds.c b/board/freescale/mpc8536ds/mpc8536ds.c index f83f629d4..b292e1354 100644 --- a/board/freescale/mpc8536ds/mpc8536ds.c +++ b/board/freescale/mpc8536ds/mpc8536ds.c @@ -36,6 +36,7 @@  #include <libfdt.h>  #include <spd_sdram.h>  #include <fdt_support.h> +#include <fsl_mdio.h>  #include <tsec.h>  #include <netdev.h>  #include <sata.h> @@ -234,6 +235,7 @@ int board_early_init_r(void)  int board_eth_init(bd_t *bis)  {  #ifdef CONFIG_TSEC_ENET +	struct fsl_pq_mdio_info mdio_info;  	struct tsec_info_struct tsec_info[2];  	int num = 0; @@ -268,6 +270,10 @@ int board_eth_init(bd_t *bis)  	}  #endif +	mdio_info.regs = (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); diff --git a/board/freescale/mpc8544ds/mpc8544ds.c b/board/freescale/mpc8544ds/mpc8544ds.c index a48c8155c..6fe8d3963 100644 --- a/board/freescale/mpc8544ds/mpc8544ds.c +++ b/board/freescale/mpc8544ds/mpc8544ds.c @@ -33,6 +33,7 @@  #include <miiphy.h>  #include <libfdt.h>  #include <fdt_support.h> +#include <fsl_mdio.h>  #include <tsec.h>  #include <netdev.h> @@ -248,9 +249,35 @@ get_board_sys_clk(ulong dummy)  	return val;  } + +#define MIIM_CIS8204_SLED_CON		0x1b +#define MIIM_CIS8204_SLEDCON_INIT	0x1115 +/* + * Hack to write all 4 PHYs with the LED values + */ +int board_phy_config(struct phy_device *phydev) +{ +	static int do_once; +	uint phyid; +	struct mii_dev *bus = phydev->bus; + +	if (do_once) +		return 0; + +	for (phyid = 0; phyid < 4; phyid++) +		bus->write(bus, phyid, MDIO_DEVAD_NONE, MIIM_CIS8204_SLED_CON, +				MIIM_CIS8204_SLEDCON_INIT); + +	do_once = 1; + +	return 0; +} + +  int board_eth_init(bd_t *bis)  {  #ifdef CONFIG_TSEC_ENET +	struct fsl_pq_mdio_info mdio_info;  	struct tsec_info_struct tsec_info[2];  	int num = 0; @@ -282,6 +309,9 @@ int board_eth_init(bd_t *bis)  		fsl_sgmii_riser_init(tsec_info, num);  	} +	mdio_info.regs = (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 diff --git a/board/freescale/mpc8569mds/mpc8569mds.c b/board/freescale/mpc8569mds/mpc8569mds.c index ecda22299..89557d221 100644 --- a/board/freescale/mpc8569mds/mpc8569mds.c +++ b/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 " diff --git a/board/freescale/mpc8572ds/mpc8572ds.c b/board/freescale/mpc8572ds/mpc8572ds.c index f444805a4..b20299e36 100644 --- a/board/freescale/mpc8572ds/mpc8572ds.c +++ b/board/freescale/mpc8572ds/mpc8572ds.c @@ -35,6 +35,7 @@  #include <libfdt.h>  #include <fdt_support.h>  #include <tsec.h> +#include <fsl_mdio.h>  #include <netdev.h>  #include "../common/sgmii_riser.h" @@ -187,6 +188,7 @@ int board_early_init_r(void)  #ifdef CONFIG_TSEC_ENET  int board_eth_init(bd_t *bis)  { +	struct fsl_pq_mdio_info mdio_info;  	struct tsec_info_struct tsec_info[4];  	int num = 0; @@ -233,6 +235,10 @@ int board_eth_init(bd_t *bis)  	fsl_sgmii_riser_init(tsec_info, num);  #endif +	mdio_info.regs = (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); diff --git a/board/freescale/p1022ds/p1022ds.c b/board/freescale/p1022ds/p1022ds.c index 8b78404b8..73a10213b 100644 --- a/board/freescale/p1022ds/p1022ds.c +++ b/board/freescale/p1022ds/p1022ds.c @@ -22,6 +22,7 @@  #include <asm/io.h>  #include <libfdt.h>  #include <fdt_support.h> +#include <fsl_mdio.h>  #include <tsec.h>  #include <asm/fsl_law.h>  #include <netdev.h> @@ -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);  } diff --git a/board/freescale/p1_p2_rdb/p1_p2_rdb.c b/board/freescale/p1_p2_rdb/p1_p2_rdb.c index 307c3e256..0b4ae9d7f 100644 --- a/board/freescale/p1_p2_rdb/p1_p2_rdb.c +++ b/board/freescale/p1_p2_rdb/p1_p2_rdb.c @@ -31,6 +31,7 @@  #include <miiphy.h>  #include <libfdt.h>  #include <fdt_support.h> +#include <fsl_mdio.h>  #include <tsec.h>  #include <vsc7385.h>  #include <netdev.h> @@ -179,6 +180,7 @@ int board_early_init_r(void)  #ifdef CONFIG_TSEC_ENET  int board_eth_init(bd_t *bis)  { +	struct fsl_pq_mdio_info mdio_info;  	struct tsec_info_struct tsec_info[4];  	int num = 0;  	char *tmp; @@ -216,6 +218,10 @@ int board_eth_init(bd_t *bis)  		puts("No address specified for VSC7385 microcode.\n");  #endif +	mdio_info.regs = (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); diff --git a/board/freescale/p2020ds/p2020ds.c b/board/freescale/p2020ds/p2020ds.c index 238b4d925..d3af6cf18 100644 --- a/board/freescale/p2020ds/p2020ds.c +++ b/board/freescale/p2020ds/p2020ds.c @@ -34,6 +34,7 @@  #include <miiphy.h>  #include <libfdt.h>  #include <fdt_support.h> +#include <fsl_mdio.h>  #include <tsec.h>  #include <asm/fsl_law.h>  #include <netdev.h> @@ -201,6 +202,7 @@ int board_early_init_r(void)  #ifdef CONFIG_TSEC_ENET  int board_eth_init(bd_t *bis)  { +	struct fsl_pq_mdio_info mdio_info;  	struct tsec_info_struct tsec_info[4];  	int num = 0; @@ -235,6 +237,11 @@ int board_eth_init(bd_t *bis)  	fsl_sgmii_riser_init(tsec_info, num);  #endif +	mdio_info.regs = (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); diff --git a/common/Makefile b/common/Makefile index 4fb050eb5..f81cff93c 100644 --- a/common/Makefile +++ b/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 diff --git a/common/cmd_mdio.c b/common/cmd_mdio.c new file mode 100644 index 000000000..cac070308 --- /dev/null +++ b/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, +					®lo, ®hi)) +				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" +); diff --git a/common/miiphyutil.c b/common/miiphyutil.c index e282096a1..243cae97a 100644 --- a/common/miiphyutil.c +++ b/common/miiphyutil.c @@ -28,6 +28,7 @@  #include <common.h>  #include <miiphy.h> +#include <phy.h>  #include <asm/types.h>  #include <linux/list.h> @@ -39,27 +40,18 @@  #undef debug  #ifdef MII_DEBUG -#define debug(fmt,args...)	printf (fmt ,##args) +#define debug(fmt, args...)	printf(fmt, ##args)  #else -#define debug(fmt,args...) +#define debug(fmt, args...)  #endif /* MII_DEBUG */ -struct mii_dev { -	struct list_head link; -	const char *name; -	int (*read) (const char *devname, unsigned char addr, -		     unsigned char reg, unsigned short *value); -	int (*write) (const char *devname, unsigned char addr, -		      unsigned char reg, unsigned short value); -}; -  static struct list_head mii_devs;  static struct mii_dev *current_mii;  /*   * Lookup the mii_dev struct by the registered device name.   */ -static struct mii_dev *miiphy_get_dev_by_name(const char *devname, int quiet) +struct mii_dev *miiphy_get_dev_by_name(const char *devname)  {  	struct list_head *entry;  	struct mii_dev *dev; @@ -75,8 +67,6 @@ static struct mii_dev *miiphy_get_dev_by_name(const char *devname, int quiet)  			return dev;  	} -	if (!quiet) -		printf("No such device: %s\n", devname);  	return NULL;  } @@ -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, ®) != 0) { -		debug ("PHY status read failed\n"); -		return (-1); +	if (miiphy_read(devname, addr, MII_BMCR, ®) != 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, ®); -	if (miiphy_read (devname, addr, MII_BMSR, ®)) { -		puts ("MII_BMSR read failed, assuming no link\n"); -		return (0); +	(void)miiphy_read(devname, addr, MII_BMSR, ®); +	if (miiphy_read(devname, addr, MII_BMSR, ®)) { +		puts("MII_BMSR read failed, assuming no link\n"); +		return 0;  	}  	/* Determine if a link is active */  	if ((reg & BMSR_LSTATUS) != 0) { -		return (1); +		return 1;  	} else { -		return (0); +		return 0;  	}  }  #endif diff --git a/drivers/net/Makefile b/drivers/net/Makefile index fd9d0b4be..819b19767 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -79,7 +79,7 @@ COBJS-$(CONFIG_TIGON3) += tigon3.o  COBJS-$(CONFIG_TIGON3) += bcm570x_autoneg.o  COBJS-$(CONFIG_TIGON3) += 5701rls.o  COBJS-$(CONFIG_DRIVER_TI_EMAC) += davinci_emac.o -COBJS-$(CONFIG_TSEC_ENET) += tsec.o +COBJS-$(CONFIG_TSEC_ENET) += tsec.o fsl_mdio.o  COBJS-$(CONFIG_TSI108_ETH) += tsi108_eth.o  COBJS-$(CONFIG_ULI526X) += uli526x.o  COBJS-$(CONFIG_VSC7385_ENET) += vsc7385.o diff --git a/drivers/net/dm9000x.c b/drivers/net/dm9000x.c index 709f67aac..b5c55738f 100644 --- a/drivers/net/dm9000x.c +++ b/drivers/net/dm9000x.c @@ -110,8 +110,8 @@ static board_info_t dm9000_info;  /* function declaration ------------------------------------- */  static int dm9000_probe(void); -static u16 phy_read(int); -static void phy_write(int, u16); +static u16 dm9000_phy_read(int); +static void dm9000_phy_write(int, u16);  static u8 DM9000_ior(int);  static void DM9000_iow(int reg, u8 value); @@ -361,7 +361,7 @@ static int dm9000_init(struct eth_device *dev, bd_t *bd)  	DM9000_iow(DM9000_IMR, IMR_PAR);  	i = 0; -	while (!(phy_read(1) & 0x20)) {	/* autonegation complete bit */ +	while (!(dm9000_phy_read(1) & 0x20)) {	/* autonegation complete bit */  		udelay(1000);  		i++;  		if (i == 10000) { @@ -371,7 +371,7 @@ static int dm9000_init(struct eth_device *dev, bd_t *bd)  	}  	/* see what we've got */ -	lnk = phy_read(17) >> 12; +	lnk = dm9000_phy_read(17) >> 12;  	printf("operating at ");  	switch (lnk) {  	case 1: @@ -445,7 +445,7 @@ static void dm9000_halt(struct eth_device *netdev)  	DM9000_DBG("%s\n", __func__);  	/* RESET devie */ -	phy_write(0, 0x8000);	/* PHY RESET */ +	dm9000_phy_write(0, 0x8000);	/* PHY RESET */  	DM9000_iow(DM9000_GPR, 0x01);	/* Power-Down PHY */  	DM9000_iow(DM9000_IMR, 0x80);	/* Disable all interrupt */  	DM9000_iow(DM9000_RCR, 0x00);	/* Disable RX */ @@ -581,7 +581,7 @@ DM9000_iow(int reg, u8 value)     Read a word from phyxcer  */  static u16 -phy_read(int reg) +dm9000_phy_read(int reg)  {  	u16 val; @@ -593,7 +593,7 @@ phy_read(int reg)  	val = (DM9000_ior(DM9000_EPDRH) << 8) | DM9000_ior(DM9000_EPDRL);  	/* The read data keeps on REG_0D & REG_0E */ -	DM9000_DBG("phy_read(0x%x): 0x%x\n", reg, val); +	DM9000_DBG("dm9000_phy_read(0x%x): 0x%x\n", reg, val);  	return val;  } @@ -601,7 +601,7 @@ phy_read(int reg)     Write a word to phyxcer  */  static void -phy_write(int reg, u16 value) +dm9000_phy_write(int reg, u16 value)  {  	/* Fill the phyxcer register into REG_0C */ @@ -613,7 +613,7 @@ phy_write(int reg, u16 value)  	DM9000_iow(DM9000_EPCR, 0xa);	/* Issue phyxcer write command */  	udelay(500);			/* Wait write complete */  	DM9000_iow(DM9000_EPCR, 0x0);	/* Clear phyxcer write command */ -	DM9000_DBG("phy_write(reg:0x%x, value:0x%x)\n", reg, value); +	DM9000_DBG("dm9000_phy_write(reg:0x%x, value:0x%x)\n", reg, value);  }  int dm9000_initialize(bd_t *bis) diff --git a/drivers/net/enc28j60.c b/drivers/net/enc28j60.c index 6c161b632..d55cacdac 100644 --- a/drivers/net/enc28j60.c +++ b/drivers/net/enc28j60.c @@ -314,7 +314,7 @@ static void enc_release_bus(enc_dev_t *enc)  /*   * Read PHY register   */ -static u16 phy_read(enc_dev_t *enc, const u8 addr) +static u16 enc_phy_read(enc_dev_t *enc, const u8 addr)  {  	uint64_t etime;  	u8 status; @@ -339,7 +339,7 @@ static u16 phy_read(enc_dev_t *enc, const u8 addr)  /*   * Write PHY register   */ -static void phy_write(enc_dev_t *enc, const u8 addr, const u16 data) +static void enc_phy_write(enc_dev_t *enc, const u8 addr, const u16 data)  {  	uint64_t etime;  	u8 status; @@ -374,7 +374,7 @@ static int enc_phy_link_wait(enc_dev_t *enc)  #ifdef CONFIG_ENC_SILENTLINK  	/* check if we have a link, then just return */ -	status = phy_read(enc, PHY_REG_PHSTAT1); +	status = enc_phy_read(enc, PHY_REG_PHSTAT1);  	if (status & ENC_PHSTAT1_LLSTAT)  		return 0;  #endif @@ -382,10 +382,10 @@ static int enc_phy_link_wait(enc_dev_t *enc)  	/* wait for link with 1 second timeout */  	etime = get_ticks() + get_tbclk();  	while (get_ticks() <= etime) { -		status = phy_read(enc, PHY_REG_PHSTAT1); +		status = enc_phy_read(enc, PHY_REG_PHSTAT1);  		if (status & ENC_PHSTAT1_LLSTAT) {  			/* now we have a link */ -			status = phy_read(enc, PHY_REG_PHSTAT2); +			status = enc_phy_read(enc, PHY_REG_PHSTAT2);  			duplex = (status & ENC_PHSTAT2_DPXSTAT) ? 1 : 0;  			printf("%s: link up, 10Mbps %s-duplex\n",  				enc->dev->name, duplex ? "full" : "half"); @@ -678,8 +678,8 @@ static int enc_setup(enc_dev_t *enc)  	enc->bank = 0xff;	/* invalidate current bank in enc28j60 */  	/* verify PHY identification */ -	phid1 = phy_read(enc, PHY_REG_PHID1); -	phid2 = phy_read(enc, PHY_REG_PHID2) & ENC_PHID2_MASK; +	phid1 = enc_phy_read(enc, PHY_REG_PHID1); +	phid2 = enc_phy_read(enc, PHY_REG_PHID2) & ENC_PHID2_MASK;  	if (phid1 != ENC_PHID1_VALUE || phid2 != ENC_PHID2_VALUE) {  		printf("%s: failed to identify PHY. Found %04x:%04x\n",  			enc->dev->name, phid1, phid2); @@ -694,7 +694,7 @@ static int enc_setup(enc_dev_t *enc)  	 * Prevent automatic loopback of data beeing transmitted by setting  	 * ENC_PHCON2_HDLDIS  	 */ -	phy_write(enc, PHY_REG_PHCON2, (1<<8)); +	enc_phy_write(enc, PHY_REG_PHCON2, (1<<8));  	/*  	 * LEDs configuration @@ -702,10 +702,10 @@ static int enc_setup(enc_dev_t *enc)  	 * LEDB: LBCFG = 0111 -> display TX & RX activity  	 * STRCH = 1 -> LED pulses  	 */ -	phy_write(enc, PHY_REG_PHLCON, 0x0472); +	enc_phy_write(enc, PHY_REG_PHLCON, 0x0472);  	/* Reset PDPXMD-bit => half duplex */ -	phy_write(enc, PHY_REG_PHCON1, 0); +	enc_phy_write(enc, PHY_REG_PHCON1, 0);  #ifdef CONFIG_USE_IRQ  	/* enable interrupts */ @@ -771,7 +771,7 @@ int enc_miiphy_read(const char *devname, u8 phy_adr, u8 reg, u16 *value)  		enc_release_bus(enc);  		return -1;  	} -	*value = phy_read(enc, reg); +	*value = enc_phy_read(enc, reg);  	enc_release_bus(enc);  	return 0;  } @@ -796,7 +796,7 @@ int enc_miiphy_write(const char *devname, u8 phy_adr, u8 reg, u16 value)  		enc_release_bus(enc);  		return -1;  	} -	phy_write(enc, reg, value); +	enc_phy_write(enc, reg, value);  	enc_release_bus(enc);  	return 0;  } diff --git a/drivers/net/fsl_mdio.c b/drivers/net/fsl_mdio.c new file mode 100644 index 000000000..1aab30789 --- /dev/null +++ b/drivers/net/fsl_mdio.c @@ -0,0 +1,120 @@ +/* + * Copyright 2009-2010 Freescale Semiconductor, Inc. + *	Jun-jie Zhang <b18070@freescale.com> + *	Mingkai Hu <Mingkai.hu@freescale.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#include <common.h> +#include <miiphy.h> +#include <phy.h> +#include <fsl_mdio.h> +#include <asm/io.h> +#include <asm/errno.h> +#include <asm/fsl_enet.h> + +void tsec_local_mdio_write(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(®s->miimcfg, MIIMCFG_RESET_MGMT); + +	out_be32(®s->miimcfg, MIIMCFG_INIT_VALUE); + +	while (in_be32(®s->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); +} diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index bba890189..a59834b29 100644 --- a/drivers/net/phy/Makefile +++ b/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)) diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c new file mode 100644 index 000000000..798473dd6 --- /dev/null +++ b/drivers/net/phy/atheros.c @@ -0,0 +1,48 @@ +/* + * Atheros PHY drivers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * Copyright 2011 Freescale Semiconductor, Inc. + * author Andy Fleming + * + */ +#include <phy.h> + +static int ar8021_config(struct phy_device *phydev) +{ +	phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x05); +	phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x3D47); + +	return 0; +} + +struct phy_driver AR8021_driver =  { +	.name = "AR8021", +	.uid = 0x4dd040, +	.mask = 0xfffff0, +	.features = PHY_GBIT_FEATURES, +	.config = ar8021_config, +	.startup = genphy_startup, +	.shutdown = genphy_shutdown, +}; + +int phy_atheros_init(void) +{ +	phy_register(&AR8021_driver); + +	return 0; +} diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c new file mode 100644 index 000000000..427ac6013 --- /dev/null +++ b/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; +} diff --git a/drivers/net/phy/davicom.c b/drivers/net/phy/davicom.c new file mode 100644 index 000000000..e96a4af03 --- /dev/null +++ b/drivers/net/phy/davicom.c @@ -0,0 +1,98 @@ +/* + * Davicom PHY drivers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * Copyright 2010-2011 Freescale Semiconductor, Inc. + * author Andy Fleming + * + */ +#include <phy.h> + +#define MIIM_DM9161_SCR                0x10 +#define MIIM_DM9161_SCR_INIT   0x0610 + +/* DM9161 Specified Configuration and Status Register */ +#define MIIM_DM9161_SCSR       0x11 +#define MIIM_DM9161_SCSR_100F  0x8000 +#define MIIM_DM9161_SCSR_100H  0x4000 +#define MIIM_DM9161_SCSR_10F   0x2000 +#define MIIM_DM9161_SCSR_10H   0x1000 + +/* DM9161 10BT Configuration/Status */ +#define MIIM_DM9161_10BTCSR    0x12 +#define MIIM_DM9161_10BTCSR_INIT       0x7800 + + +/* Davicom DM9161E */ +static int dm9161_config(struct phy_device *phydev) +{ +	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_ISOLATE); +	/* Do not bypass the scrambler/descrambler */ +	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_DM9161_SCR, +			MIIM_DM9161_SCR_INIT); +	/* Clear 10BTCSR to default */ +	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_DM9161_10BTCSR, +			MIIM_DM9161_10BTCSR_INIT); + +	genphy_config_aneg(phydev); + +	return 0; +} + +static int dm9161_parse_status(struct phy_device *phydev) +{ +	int mii_reg; + +	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_DM9161_SCSR); + +	if (mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_100H)) +		phydev->speed = SPEED_100; +	else +		phydev->speed = SPEED_10; + +	if (mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_10F)) +		phydev->duplex = DUPLEX_FULL; +	else +		phydev->duplex = DUPLEX_HALF; + +	return 0; +} + +static int dm9161_startup(struct phy_device *phydev) +{ +	genphy_update_link(phydev); +	dm9161_parse_status(phydev); + +	return 0; +} + +static struct phy_driver DM9161_driver = { +	.name = "Davicom DM9161E", +	.uid = 0x181b880, +	.mask = 0xffffff0, +	.features = PHY_BASIC_FEATURES, +	.config = &dm9161_config, +	.startup = &dm9161_startup, +	.shutdown = &genphy_shutdown, +}; + +int phy_davicom_init(void) +{ +	phy_register(&DM9161_driver); + +	return 0; +} diff --git a/drivers/net/phy/generic_10g.c b/drivers/net/phy/generic_10g.c new file mode 100644 index 000000000..315c50867 --- /dev/null +++ b/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, +}; + diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c new file mode 100644 index 000000000..d67bbdd9c --- /dev/null +++ b/drivers/net/phy/lxt.c @@ -0,0 +1,87 @@ +/* + * LXT PHY drivers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * Copyright 2010-2011 Freescale Semiconductor, Inc. + * author Andy Fleming + * + */ +#include <phy.h> + +/* LXT971 Status 2 registers */ +#define MIIM_LXT971_SR2                     0x11  /* Status Register 2  */ +#define MIIM_LXT971_SR2_SPEED_MASK 0x4200 +#define MIIM_LXT971_SR2_10HDX     0x0000  /*  10 Mbit half duplex selected */ +#define MIIM_LXT971_SR2_10FDX     0x0200  /*  10 Mbit full duplex selected */ +#define MIIM_LXT971_SR2_100HDX    0x4000  /* 100 Mbit half duplex selected */ +#define MIIM_LXT971_SR2_100FDX    0x4200  /* 100 Mbit full duplex selected */ + + +/* LXT971 */ +static int lxt971_parse_status(struct phy_device *phydev) +{ +	int mii_reg; +	int speed; + +	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_LXT971_SR2); +	speed = mii_reg & MIIM_LXT971_SR2_SPEED_MASK; + +	switch (speed) { +	case MIIM_LXT971_SR2_10HDX: +		phydev->speed = SPEED_10; +		phydev->duplex = DUPLEX_HALF; +		break; +	case MIIM_LXT971_SR2_10FDX: +		phydev->speed = SPEED_10; +		phydev->duplex = DUPLEX_FULL; +		break; +	case MIIM_LXT971_SR2_100HDX: +		phydev->speed = SPEED_100; +		phydev->duplex = DUPLEX_HALF; +		break; +	default: +		phydev->speed = SPEED_100; +		phydev->duplex = DUPLEX_FULL; +	} + +	return 0; +} + +static int lxt971_startup(struct phy_device *phydev) +{ +	genphy_update_link(phydev); +	lxt971_parse_status(phydev); + +	return 0; +} + +static struct phy_driver LXT971_driver = { +	.name = "LXT971", +	.uid = 0x1378e0, +	.mask = 0xfffff0, +	.features = PHY_BASIC_FEATURES, +	.config = &genphy_config_aneg, +	.startup = &lxt971_startup, +	.shutdown = &genphy_shutdown, +}; + +int phy_lxt_init(void) +{ +	phy_register(&LXT971_driver); + +	return 0; +} diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c new file mode 100644 index 000000000..bd1cdc4f1 --- /dev/null +++ b/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; +} diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c new file mode 100644 index 000000000..47064a185 --- /dev/null +++ b/drivers/net/phy/micrel.c @@ -0,0 +1,40 @@ +/* + * Micrel PHY drivers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * Copyright 2010-2011 Freescale Semiconductor, Inc. + * author Andy Fleming + * + */ +#include <phy.h> + +static struct phy_driver KSZ804_driver = { +	.name = "Micrel KSZ804", +	.uid = 0x221510, +	.mask = 0xfffff0, +	.features = PHY_BASIC_FEATURES, +	.config = &genphy_config, +	.startup = &genphy_startup, +	.shutdown = &genphy_shutdown, +}; + +int phy_micrel_init(void) +{ +	phy_register(&KSZ804_driver); + +	return 0; +} diff --git a/drivers/net/phy/natsemi.c b/drivers/net/phy/natsemi.c new file mode 100644 index 000000000..ea60ac1b0 --- /dev/null +++ b/drivers/net/phy/natsemi.c @@ -0,0 +1,96 @@ +/* + * National Semiconductor PHY drivers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * Copyright 2010-2011 Freescale Semiconductor, Inc. + * author Andy Fleming + * + */ +#include <phy.h> + +/* DP83865 Link and Auto-Neg Status Register */ +#define MIIM_DP83865_LANR      0x11 +#define MIIM_DP83865_SPD_MASK  0x0018 +#define MIIM_DP83865_SPD_1000  0x0010 +#define MIIM_DP83865_SPD_100   0x0008 +#define MIIM_DP83865_DPX_FULL  0x0002 + + +/* NatSemi DP83865 */ +static int dp83865_config(struct phy_device *phydev) +{ +	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); +	genphy_config_aneg(phydev); + +	return 0; +} + +static int dp83865_parse_status(struct phy_device *phydev) +{ +	int mii_reg; + +	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_DP83865_LANR); + +	switch (mii_reg & MIIM_DP83865_SPD_MASK) { + +	case MIIM_DP83865_SPD_1000: +		phydev->speed = SPEED_1000; +		break; + +	case MIIM_DP83865_SPD_100: +		phydev->speed = SPEED_100; +		break; + +	default: +		phydev->speed = SPEED_10; +		break; + +	} + +	if (mii_reg & MIIM_DP83865_DPX_FULL) +		phydev->duplex = DUPLEX_FULL; +	else +		phydev->duplex = DUPLEX_HALF; + +	return 0; +} + +static int dp83865_startup(struct phy_device *phydev) +{ +	genphy_update_link(phydev); +	dp83865_parse_status(phydev); + +	return 0; +} + + +static struct phy_driver DP83865_driver = { +	.name = "NatSemi DP83865", +	.uid = 0x20005c70, +	.mask = 0xfffffff0, +	.features = PHY_GBIT_FEATURES, +	.config = &dp83865_config, +	.startup = &dp83865_startup, +	.shutdown = &genphy_shutdown, +}; + +int phy_natsemi_init(void) +{ +	phy_register(&DP83865_driver); + +	return 0; +} diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c new file mode 100644 index 000000000..c7edcc090 --- /dev/null +++ b/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; +} diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c new file mode 100644 index 000000000..b7e2753f7 --- /dev/null +++ b/drivers/net/phy/realtek.c @@ -0,0 +1,130 @@ +/* + * RealTek PHY drivers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * Copyright 2010-2011 Freescale Semiconductor, Inc. + * author Andy Fleming + * + */ +#include <config.h> +#include <common.h> +#include <phy.h> + +#define PHY_AUTONEGOTIATE_TIMEOUT 5000 + +/* RTL8211B PHY Status Register */ +#define MIIM_RTL8211B_PHY_STATUS       0x11 +#define MIIM_RTL8211B_PHYSTAT_SPEED    0xc000 +#define MIIM_RTL8211B_PHYSTAT_GBIT     0x8000 +#define MIIM_RTL8211B_PHYSTAT_100      0x4000 +#define MIIM_RTL8211B_PHYSTAT_DUPLEX   0x2000 +#define MIIM_RTL8211B_PHYSTAT_SPDDONE  0x0800 +#define MIIM_RTL8211B_PHYSTAT_LINK     0x0400 + + +/* RealTek RTL8211B */ +static int rtl8211b_config(struct phy_device *phydev) +{ +	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); + +	genphy_config_aneg(phydev); + +	return 0; +} + +static int rtl8211b_parse_status(struct phy_device *phydev) +{ +	unsigned int speed; +	unsigned int mii_reg; + +	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211B_PHY_STATUS); + +	if (!(mii_reg & MIIM_RTL8211B_PHYSTAT_SPDDONE)) { +		int i = 0; + +		/* in case of timeout ->link is cleared */ +		phydev->link = 1; +		puts("Waiting for PHY realtime link"); +		while (!(mii_reg & MIIM_RTL8211B_PHYSTAT_SPDDONE)) { +			/* Timeout reached ? */ +			if (i > PHY_AUTONEGOTIATE_TIMEOUT) { +				puts(" TIMEOUT !\n"); +				phydev->link = 0; +				break; +			} + +			if ((i++ % 1000) == 0) +				putc('.'); +			udelay(1000);	/* 1 ms */ +			mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, +					MIIM_RTL8211B_PHY_STATUS); +		} +		puts(" done\n"); +		udelay(500000);	/* another 500 ms (results in faster booting) */ +	} else { +		if (mii_reg & MIIM_RTL8211B_PHYSTAT_LINK) +			phydev->link = 1; +		else +			phydev->link = 0; +	} + +	if (mii_reg & MIIM_RTL8211B_PHYSTAT_DUPLEX) +		phydev->duplex = DUPLEX_FULL; +	else +		phydev->duplex = DUPLEX_HALF; + +	speed = (mii_reg & MIIM_RTL8211B_PHYSTAT_SPEED); + +	switch (speed) { +	case MIIM_RTL8211B_PHYSTAT_GBIT: +		phydev->speed = SPEED_1000; +		break; +	case MIIM_RTL8211B_PHYSTAT_100: +		phydev->speed = SPEED_100; +		break; +	default: +		phydev->speed = SPEED_10; +	} + +	return 0; +} + +static int rtl8211b_startup(struct phy_device *phydev) +{ +	/* Read the Status (2x to make sure link is right) */ +	genphy_update_link(phydev); +	rtl8211b_parse_status(phydev); + +	return 0; +} + +static struct phy_driver RTL8211B_driver = { +	.name = "RealTek RTL8211B", +	.uid = 0x1cc910, +	.mask = 0xfffff0, +	.features = PHY_GBIT_FEATURES, +	.config = &rtl8211b_config, +	.startup = &rtl8211b_startup, +	.shutdown = &genphy_shutdown, +}; + +int phy_realtek_init(void) +{ +	phy_register(&RTL8211B_driver); + +	return 0; +} diff --git a/drivers/net/phy/teranetics.c b/drivers/net/phy/teranetics.c new file mode 100644 index 000000000..a771791b7 --- /dev/null +++ b/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; +} diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c new file mode 100644 index 000000000..d48d4fe73 --- /dev/null +++ b/drivers/net/phy/vitesse.c @@ -0,0 +1,242 @@ +/* + * Vitesse PHY drivers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * Copyright 2010-2011 Freescale Semiconductor, Inc. + * author Andy Fleming + * + */ +#include <miiphy.h> + +/* Cicada Auxiliary Control/Status Register */ +#define MIIM_CIS82xx_AUX_CONSTAT	0x1c +#define MIIM_CIS82xx_AUXCONSTAT_INIT	0x0004 +#define MIIM_CIS82xx_AUXCONSTAT_DUPLEX	0x0020 +#define MIIM_CIS82xx_AUXCONSTAT_SPEED	0x0018 +#define MIIM_CIS82xx_AUXCONSTAT_GBIT	0x0010 +#define MIIM_CIS82xx_AUXCONSTAT_100	0x0008 + +/* Cicada Extended Control Register 1 */ +#define MIIM_CIS82xx_EXT_CON1		0x17 +#define MIIM_CIS8201_EXTCON1_INIT	0x0000 + +/* Cicada 8204 Extended PHY Control Register 1 */ +#define MIIM_CIS8204_EPHY_CON		0x17 +#define MIIM_CIS8204_EPHYCON_INIT	0x0006 +#define MIIM_CIS8204_EPHYCON_RGMII	0x1100 + +/* Cicada 8204 Serial LED Control Register */ +#define MIIM_CIS8204_SLED_CON		0x1b +#define MIIM_CIS8204_SLEDCON_INIT	0x1115 + +/* Vitesse VSC8601 Extended PHY Control Register 1 */ +#define MIIM_VSC8601_EPHY_CON		0x17 +#define MIIM_VSC8601_EPHY_CON_INIT_SKEW	0x1120 +#define MIIM_VSC8601_SKEW_CTRL		0x1c + +#define PHY_EXT_PAGE_ACCESS    0x1f + +/* CIS8201 */ +static int vitesse_config(struct phy_device *phydev) +{ +	/* Override PHY config settings */ +	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT, +			MIIM_CIS82xx_AUXCONSTAT_INIT); +	/* Set up the interface mode */ +	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_EXT_CON1, +			MIIM_CIS8201_EXTCON1_INIT); + +	genphy_config_aneg(phydev); + +	return 0; +} + +static int vitesse_parse_status(struct phy_device *phydev) +{ +	int speed; +	int mii_reg; + +	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT); + +	if (mii_reg & MIIM_CIS82xx_AUXCONSTAT_DUPLEX) +		phydev->duplex = DUPLEX_FULL; +	else +		phydev->duplex = DUPLEX_HALF; + +	speed = mii_reg & MIIM_CIS82xx_AUXCONSTAT_SPEED; +	switch (speed) { +	case MIIM_CIS82xx_AUXCONSTAT_GBIT: +		phydev->speed = SPEED_1000; +		break; +	case MIIM_CIS82xx_AUXCONSTAT_100: +		phydev->speed = SPEED_100; +		break; +	default: +		phydev->speed = SPEED_10; +		break; +	} + +	return 0; +} + +static int vitesse_startup(struct phy_device *phydev) +{ +	genphy_update_link(phydev); +	vitesse_parse_status(phydev); + +	return 0; +} + +static int cis8204_config(struct phy_device *phydev) +{ +	/* Override PHY config settings */ +	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS82xx_AUX_CONSTAT, +			MIIM_CIS82xx_AUXCONSTAT_INIT); + +	genphy_config_aneg(phydev); + +	if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || +			(phydev->interface == PHY_INTERFACE_MODE_RGMII) || +			(phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) || +			(phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)) +		phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8204_EPHY_CON, +				MIIM_CIS8204_EPHYCON_INIT | +				MIIM_CIS8204_EPHYCON_RGMII); +	else +		phy_write(phydev, MDIO_DEVAD_NONE, MIIM_CIS8204_EPHY_CON, +				MIIM_CIS8204_EPHYCON_INIT); + +	return 0; +} + +/* Vitesse VSC8601 */ +int vsc8601_config(struct phy_device *phydev) +{ +	/* Configure some basic stuff */ +#ifdef CONFIG_SYS_VSC8601_SKEWFIX +	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8601_EPHY_CON, +			MIIM_VSC8601_EPHY_CON_INIT_SKEW); +#if defined(CONFIG_SYS_VSC8601_SKEW_TX) && defined(CONFIG_SYS_VSC8601_SKEW_RX) +	phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 1); +#define VSC8101_SKEW \ +	((CONFIG_SYS_VSC8601_SKEW_TX << 14) \ +	| (CONFIG_SYS_VSC8601_SKEW_RX << 12)) +	phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8601_SKEW_CTRL, +			VSC8101_SKEW); +	phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, 0); +#endif +#endif + +	genphy_config_aneg(phydev); + +	return 0; +} + +static struct phy_driver VSC8211_driver = { +	.name	= "Vitesse VSC8211", +	.uid	= 0xfc4b0, +	.mask	= 0xffff0, +	.features = PHY_GBIT_FEATURES, +	.config = &vitesse_config, +	.startup = &vitesse_startup, +	.shutdown = &genphy_shutdown, +}; + +static struct phy_driver VSC8221_driver = { +	.name = "Vitesse VSC8221", +	.uid = 0xfc550, +	.mask = 0xffff0, +	.features = PHY_GBIT_FEATURES, +	.config = &genphy_config_aneg, +	.startup = &vitesse_startup, +	.shutdown = &genphy_shutdown, +}; + +static struct phy_driver VSC8244_driver = { +	.name = "Vitesse VSC8244", +	.uid = 0xfc6c0, +	.mask = 0xffff0, +	.features = PHY_GBIT_FEATURES, +	.config = &genphy_config_aneg, +	.startup = &vitesse_startup, +	.shutdown = &genphy_shutdown, +}; + +static struct phy_driver VSC8234_driver = { +	.name = "Vitesse VSC8234", +	.uid = 0xfc620, +	.mask = 0xffff0, +	.features = PHY_GBIT_FEATURES, +	.config = &genphy_config_aneg, +	.startup = &vitesse_startup, +	.shutdown = &genphy_shutdown, +}; + +static struct phy_driver VSC8601_driver = { +	.name = "Vitesse VSC8601", +	.uid = 0x70420, +	.mask = 0xffff0, +	.features = PHY_GBIT_FEATURES, +	.config = &vsc8601_config, +	.startup = &vitesse_startup, +	.shutdown = &genphy_shutdown, +}; + +static struct phy_driver VSC8641_driver = { +	.name = "Vitesse VSC8641", +	.uid = 0x70430, +	.mask = 0xffff0, +	.features = PHY_GBIT_FEATURES, +	.config = &genphy_config_aneg, +	.startup = &vitesse_startup, +	.shutdown = &genphy_shutdown, +}; + +/* Vitesse bought Cicada, so we'll put these here */ +static struct phy_driver cis8201_driver = { +	.name = "CIS8201", +	.uid = 0xfc410, +	.mask = 0xffff0, +	.features = PHY_GBIT_FEATURES, +	.config = &vitesse_config, +	.startup = &vitesse_startup, +	.shutdown = &genphy_shutdown, +}; + +static struct phy_driver cis8204_driver = { +	.name = "Cicada Cis8204", +	.uid = 0xfc440, +	.mask = 0xffff0, +	.features = PHY_GBIT_FEATURES, +	.config = &cis8204_config, +	.startup = &vitesse_startup, +	.shutdown = &genphy_shutdown, +}; + +int 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; +} diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c index 9a91b9e0b..06e5834a9 100644 --- a/drivers/net/tsec.c +++ b/drivers/net/tsec.c @@ -5,7 +5,7 @@   * terms of the GNU Public License, Version 2, incorporated   * herein by reference.   * - * Copyright 2004-2010 Freescale Semiconductor, Inc. + * Copyright 2004-2011 Freescale Semiconductor, Inc.   * (C) Copyright 2003, Motorola, Inc.   * author Andy Fleming   * @@ -17,10 +17,9 @@  #include <net.h>  #include <command.h>  #include <tsec.h> +#include <fsl_mdio.h>  #include <asm/errno.h> -#include "miiphy.h" -  DECLARE_GLOBAL_DATA_PTR;  #define TX_BUF_CNT		2 @@ -44,31 +43,6 @@ static RTXBD rtx __attribute__ ((aligned(8)));  #error "rtx must be 64-bit aligned"  #endif -static int tsec_send(struct eth_device *dev, -		     volatile void *packet, int length); -static int tsec_recv(struct eth_device *dev); -static int tsec_init(struct eth_device *dev, bd_t * bd); -static int tsec_initialize(bd_t * bis, struct tsec_info_struct *tsec_info); -static void tsec_halt(struct eth_device *dev); -static void init_registers(volatile tsec_t * regs); -static void startup_tsec(struct eth_device *dev); -static int init_phy(struct eth_device *dev); -void write_phy_reg(struct tsec_private *priv, uint regnum, uint value); -uint read_phy_reg(struct tsec_private *priv, uint regnum); -static struct phy_info *get_phy_info(struct eth_device *dev); -static void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd); -static void adjust_link(struct eth_device *dev); -#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \ -	&& !defined(BITBANGMII) -static int tsec_miiphy_write(const char *devname, unsigned char addr, -			     unsigned char reg, unsigned short value); -static int tsec_miiphy_read(const char *devname, unsigned char addr, -			    unsigned char reg, unsigned short *value); -#endif -#ifdef CONFIG_MCAST_TFTP -static int tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set); -#endif -  /* Default initializations for TSEC controllers. */  static struct tsec_info_struct tsec_info[] = { @@ -81,10 +55,10 @@ static struct tsec_info_struct tsec_info[] = {  #ifdef CONFIG_MPC85XX_FEC  	{  		.regs = (tsec_t *)(TSEC_BASE_ADDR + 0x2000), -		.miiregs = (tsec_mdio_t *)(MDIO_BASE_ADDR),  		.devname = CONFIG_MPC85XX_FEC_NAME,  		.phyaddr = FEC_PHY_ADDR, -		.flags = FEC_FLAGS +		.flags = FEC_FLAGS, +		.mii_devname = DEFAULT_MII_NAME  	},			/* FEC */  #endif  #ifdef CONFIG_TSEC3 @@ -95,195 +69,6 @@ static struct tsec_info_struct tsec_info[] = {  #endif  }; -/* - * Initialize all the TSEC devices - * - * Returns the number of TSEC devices that were initialized - */ -int tsec_eth_init(bd_t *bis, struct tsec_info_struct *tsecs, int num) -{ -	int i; -	int ret, count = 0; - -	for (i = 0; i < num; i++) { -		ret = tsec_initialize(bis, &tsecs[i]); -		if (ret > 0) -			count += ret; -	} - -	return count; -} - -int tsec_standard_init(bd_t *bis) -{ -	return tsec_eth_init(bis, tsec_info, ARRAY_SIZE(tsec_info)); -} - -/* Initialize device structure. Returns success if PHY - * initialization succeeded (i.e. if it recognizes the PHY) - */ -static int tsec_initialize(bd_t * bis, struct tsec_info_struct *tsec_info) -{ -	struct eth_device *dev; -	int i; -	struct tsec_private *priv; - -	dev = (struct eth_device *)malloc(sizeof *dev); - -	if (NULL == dev) -		return 0; - -	memset(dev, 0, sizeof *dev); - -	priv = (struct tsec_private *)malloc(sizeof(*priv)); - -	if (NULL == priv) -		return 0; - -	privlist[num_tsecs++] = priv; -	priv->regs = tsec_info->regs; -	priv->phyregs = tsec_info->miiregs; -	priv->phyregs_sgmii = tsec_info->miiregs_sgmii; - -	priv->phyaddr = tsec_info->phyaddr; -	priv->flags = tsec_info->flags; - -	sprintf(dev->name, tsec_info->devname); -	dev->iobase = 0; -	dev->priv = priv; -	dev->init = tsec_init; -	dev->halt = tsec_halt; -	dev->send = tsec_send; -	dev->recv = tsec_recv; -#ifdef CONFIG_MCAST_TFTP -	dev->mcast = tsec_mcast_addr; -#endif - -	/* Tell u-boot to get the addr from the env */ -	for (i = 0; i < 6; i++) -		dev->enetaddr[i] = 0; - -	eth_register(dev); - -	/* Reset the MAC */ -	priv->regs->maccfg1 |= MACCFG1_SOFT_RESET; -	udelay(2);  /* Soft Reset must be asserted for 3 TX clocks */ -	priv->regs->maccfg1 &= ~(MACCFG1_SOFT_RESET); - -#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \ -	&& !defined(BITBANGMII) -	miiphy_register(dev->name, tsec_miiphy_read, tsec_miiphy_write); -#endif - -	/* Try to initialize PHY here, and return */ -	return init_phy(dev); -} - -/* Initializes data structures and registers for the controller, - * and brings the interface up.	 Returns the link status, meaning - * that it returns success if the link is up, failure otherwise. - * This allows u-boot to find the first active controller. - */ -static int tsec_init(struct eth_device *dev, bd_t * bd) -{ -	uint tempval; -	char tmpbuf[MAC_ADDR_LEN]; -	int i; -	struct tsec_private *priv = (struct tsec_private *)dev->priv; -	volatile tsec_t *regs = priv->regs; - -	/* Make sure the controller is stopped */ -	tsec_halt(dev); - -	/* Init MACCFG2.  Defaults to GMII */ -	regs->maccfg2 = MACCFG2_INIT_SETTINGS; - -	/* Init ECNTRL */ -	regs->ecntrl = ECNTRL_INIT_SETTINGS; - -	/* Copy the station address into the address registers. -	 * Backwards, because little endian MACS are dumb */ -	for (i = 0; i < MAC_ADDR_LEN; i++) { -		tmpbuf[MAC_ADDR_LEN - 1 - i] = dev->enetaddr[i]; -	} -	tempval = (tmpbuf[0] << 24) | (tmpbuf[1] << 16) | (tmpbuf[2] << 8) | -		  tmpbuf[3]; - -	regs->macstnaddr1 = tempval; - -	tempval = *((uint *) (tmpbuf + 4)); - -	regs->macstnaddr2 = tempval; - -	/* reset the indices to zero */ -	rxIdx = 0; -	txIdx = 0; - -	/* Clear out (for the most part) the other registers */ -	init_registers(regs); - -	/* Ready the device for tx/rx */ -	startup_tsec(dev); - -	/* If there's no link, fail */ -	return (priv->link ? 0 : -1); -} - -/* Writes the given phy's reg with value, using the specified MDIO regs */ -static void tsec_local_mdio_write(volatile tsec_mdio_t *phyregs, uint addr, -		uint reg, uint value) -{ -	int timeout = 1000000; - -	phyregs->miimadd = (addr << 8) | reg; -	phyregs->miimcon = value; -	asm("sync"); - -	timeout = 1000000; -	while ((phyregs->miimind & MIIMIND_BUSY) && timeout--) ; -} - - -/* Provide the default behavior of writing the PHY of this ethernet device */ -#define write_phy_reg(priv, regnum, value) \ -	tsec_local_mdio_write(priv->phyregs,priv->phyaddr,regnum,value) - -/* Reads register regnum on the device's PHY through the - * specified registers.	 It lowers and raises the read - * command, and waits for the data to become valid (miimind - * notvalid bit cleared), and the bus to cease activity (miimind - * busy bit cleared), and then returns the value - */ -static uint tsec_local_mdio_read(volatile tsec_mdio_t *phyregs, -				uint phyid, uint regnum) -{ -	uint value; - -	/* Put the address of the phy, and the register -	 * number into MIIMADD */ -	phyregs->miimadd = (phyid << 8) | regnum; - -	/* Clear the command register, and wait */ -	phyregs->miimcom = 0; -	asm("sync"); - -	/* Initiate a read command, and wait */ -	phyregs->miimcom = MIIM_READ_COMMAND; -	asm("sync"); - -	/* Wait for the the indication that the read is done */ -	while ((phyregs->miimind & (MIIMIND_NOTVALID | MIIMIND_BUSY))) ; - -	/* Grab the value read from the PHY */ -	value = phyregs->miimstat; - -	return value; -} - -/* #define to provide old read_phy_reg functionality without duplicating code */ -#define read_phy_reg(priv,regnum) \ -	tsec_local_mdio_read(priv->phyregs,priv->phyaddr,regnum) -  #define TBIANA_SETTINGS ( \  		TBIANA_ASYMMETRIC_PAUSE \  		| TBIANA_SYMMETRIC_PAUSE \ @@ -305,661 +90,150 @@ static void tsec_configure_serdes(struct tsec_private *priv)  {  	/* Access TBI PHY registers at given TSEC register offset as opposed  	 * to the register offset used for external PHY accesses */ -	tsec_local_mdio_write(priv->phyregs_sgmii, priv->regs->tbipa, TBI_ANA, -			TBIANA_SETTINGS); -	tsec_local_mdio_write(priv->phyregs_sgmii, priv->regs->tbipa, TBI_TBICON, -			TBICON_CLK_SELECT); -	tsec_local_mdio_write(priv->phyregs_sgmii, priv->regs->tbipa, TBI_CR, -			CONFIG_TSEC_TBICR_SETTINGS); -} - -/* Discover which PHY is attached to the device, and configure it - * properly.  If the PHY is not recognized, then return 0 - * (failure).  Otherwise, return 1 - */ -static int init_phy(struct eth_device *dev) -{ -	struct tsec_private *priv = (struct tsec_private *)dev->priv; -	struct phy_info *curphy; -	volatile tsec_t *regs = priv->regs; - -	/* Assign a Physical address to the TBI */ -	regs->tbipa = CONFIG_SYS_TBIPA_VALUE; -	asm("sync"); - -	/* Reset MII (due to new addresses) */ -	priv->phyregs->miimcfg = MIIMCFG_RESET; -	asm("sync"); -	priv->phyregs->miimcfg = MIIMCFG_INIT_VALUE; -	asm("sync"); -	while (priv->phyregs->miimind & MIIMIND_BUSY) ; - -	/* Get the cmd structure corresponding to the attached -	 * PHY */ -	curphy = get_phy_info(dev); - -	if (curphy == NULL) { -		priv->phyinfo = NULL; -		printf("%s: No PHY found\n", dev->name); - -		return 0; -	} - -	if (regs->ecntrl & ECNTRL_SGMII_MODE) -		tsec_configure_serdes(priv); - -	priv->phyinfo = curphy; - -	phy_run_commands(priv, priv->phyinfo->config); - -	return 1; -} - -/* - * Returns which value to write to the control register. - * For 10/100, the value is slightly different - */ -static uint mii_cr_init(uint mii_reg, struct tsec_private * priv) -{ -	if (priv->flags & TSEC_GIGABIT) -		return MIIM_CONTROL_INIT; -	else -		return MIIM_CR_INIT; -} - -/* - * Wait for auto-negotiation to complete, then determine link - */ -static uint mii_parse_sr(uint mii_reg, struct tsec_private * priv) -{ -	/* -	 * Wait if the link is up, and autonegotiation is in progress -	 * (ie - we're capable and it's not done) -	 */ -	mii_reg = read_phy_reg(priv, MIIM_STATUS); -	if ((mii_reg & BMSR_ANEGCAPABLE) && !(mii_reg & BMSR_ANEGCOMPLETE)) { -		int i = 0; - -		puts("Waiting for PHY auto negotiation to complete"); -		while (!(mii_reg & BMSR_ANEGCOMPLETE)) { -			/* -			 * Timeout reached ? -			 */ -			if (i > PHY_AUTONEGOTIATE_TIMEOUT) { -				puts(" TIMEOUT !\n"); -				priv->link = 0; -				return 0; -			} - -			if (ctrlc()) { -				puts("user interrupt!\n"); -				priv->link = 0; -				return -EINTR; -			} - -			if ((i++ % 1000) == 0) { -				putc('.'); -			} -			udelay(1000);	/* 1 ms */ -			mii_reg = read_phy_reg(priv, MIIM_STATUS); -		} -		puts(" done\n"); - -		/* Link status bit is latched low, read it again */ -		mii_reg = read_phy_reg(priv, MIIM_STATUS); - -		udelay(500000);	/* another 500 ms (results in faster booting) */ -	} - -	priv->link = mii_reg & MIIM_STATUS_LINK ? 1 : 0; - -	return 0; -} - -/* Generic function which updates the speed and duplex.  If - * autonegotiation is enabled, it uses the AND of the link - * partner's advertised capabilities and our advertised - * capabilities.  If autonegotiation is disabled, we use the - * appropriate bits in the control register. - * - * Stolen from Linux's mii.c and phy_device.c - */ -static uint mii_parse_link(uint mii_reg, struct tsec_private *priv) -{ -	/* We're using autonegotiation */ -	if (mii_reg & BMSR_ANEGCAPABLE) { -		uint lpa = 0; -		uint gblpa = 0; - -		/* Check for gigabit capability */ -		if (mii_reg & BMSR_ERCAP) { -			/* We want a list of states supported by -			 * both PHYs in the link -			 */ -			gblpa = read_phy_reg(priv, MII_STAT1000); -			gblpa &= read_phy_reg(priv, MII_CTRL1000) << 2; -		} - -		/* Set the baseline so we only have to set them -		 * if they're different -		 */ -		priv->speed = 10; -		priv->duplexity = 0; - -		/* Check the gigabit fields */ -		if (gblpa & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)) { -			priv->speed = 1000; - -			if (gblpa & PHY_1000BTSR_1000FD) -				priv->duplexity = 1; - -			/* We're done! */ -			return 0; -		} - -		lpa = read_phy_reg(priv, MII_ADVERTISE); -		lpa &= read_phy_reg(priv, MII_LPA); - -		if (lpa & (LPA_100FULL | LPA_100HALF)) { -			priv->speed = 100; - -			if (lpa & LPA_100FULL) -				priv->duplexity = 1; - -		} else if (lpa & LPA_10FULL) -			priv->duplexity = 1; -	} else { -		uint bmcr = read_phy_reg(priv, MII_BMCR); - -		priv->speed = 10; -		priv->duplexity = 0; - -		if (bmcr & BMCR_FULLDPLX) -			priv->duplexity = 1; - -		if (bmcr & BMCR_SPEED1000) -			priv->speed = 1000; -		else if (bmcr & BMCR_SPEED100) -			priv->speed = 100; -	} - -	return 0; -} - -/* - * "Ethernet@Wirespeed" needs to be enabled to achieve link in certain - * circumstances.  eg a gigabit TSEC connected to a gigabit switch with - * a 4-wire ethernet cable.  Both ends advertise gigabit, but can't - * link.  "Ethernet@Wirespeed" reduces advertised speed until link - * can be achieved. - */ -static uint mii_BCM54xx_wirespeed(uint mii_reg, struct tsec_private *priv) -{ -	return (read_phy_reg(priv, mii_reg) & 0x8FFF) | 0x8010; +	tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa), +			0, TBI_ANA, TBIANA_SETTINGS); +	tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa), +			0, TBI_TBICON, TBICON_CLK_SELECT); +	tsec_local_mdio_write(priv->phyregs_sgmii, in_be32(&priv->regs->tbipa), +			0, TBI_CR, CONFIG_TSEC_TBICR_SETTINGS);  } -/* - * Parse the BCM54xx status register for speed and duplex information. - * The linux sungem_phy has this information, but in a table format. - */ -static uint mii_parse_BCM54xx_sr(uint mii_reg, struct tsec_private *priv) -{ -	/* If there is no link, speed and duplex don't matter */ -	if (!priv->link) -		return 0; - -	switch ((mii_reg & MIIM_BCM54xx_AUXSTATUS_LINKMODE_MASK) >> -		MIIM_BCM54xx_AUXSTATUS_LINKMODE_SHIFT) { -	case 1: -		priv->duplexity = 0; -		priv->speed = 10; -		break; -	case 2: -		priv->duplexity = 1; -		priv->speed = 10; -		break; -	case 3: -		priv->duplexity = 0; -		priv->speed = 100; -		break; -	case 5: -		priv->duplexity = 1; -		priv->speed = 100; -		break; -	case 6: -		priv->duplexity = 0; -		priv->speed = 1000; -		break; -	case 7: -		priv->duplexity = 1; -		priv->speed = 1000; -		break; -	default: -		printf("Auto-neg error, defaulting to 10BT/HD\n"); -		priv->duplexity = 0; -		priv->speed = 10; -		break; -	} - -	return 0; -} - -/* - * Find out if PHY is in copper or serdes mode by looking at Expansion Reg - * 0x42 - "Operating Mode Status Register" - */ -static int BCM8482_is_serdes(struct tsec_private *priv) -{ -	u16 val; -	int serdes = 0; - -	write_phy_reg(priv, MIIM_BCM54XX_EXP_SEL, MIIM_BCM54XX_EXP_SEL_ER | 0x42); -	val = read_phy_reg(priv, MIIM_BCM54XX_EXP_DATA); - -	switch (val & 0x1f) { -	case 0x0d:	/* RGMII-to-100Base-FX */ -	case 0x0e:	/* RGMII-to-SGMII */ -	case 0x0f:	/* RGMII-to-SerDes */ -	case 0x12:	/* SGMII-to-SerDes */ -	case 0x13:	/* SGMII-to-100Base-FX */ -	case 0x16:	/* SerDes-to-Serdes */ -		serdes = 1; -		break; -	case 0x6:	/* RGMII-to-Copper */ -	case 0x14:	/* SGMII-to-Copper */ -	case 0x17:	/* SerDes-to-Copper */ -		break; -	default: -		printf("ERROR, invalid PHY mode (0x%x\n)", val); -		break; -	} - -	return serdes; -} - -/* - * Determine SerDes link speed and duplex from Expansion reg 0x42 "Operating - * Mode Status Register" - */ -uint mii_parse_BCM5482_serdes_sr(struct tsec_private *priv) -{ -	u16 val; -	int i = 0; - -	/* Wait 1s for link - Clause 37 autonegotiation happens very fast */ -	while (1) { -		write_phy_reg(priv, MIIM_BCM54XX_EXP_SEL, -				MIIM_BCM54XX_EXP_SEL_ER | 0x42); -		val = read_phy_reg(priv, MIIM_BCM54XX_EXP_DATA); - -		if (val & 0x8000) -			break; - -		if (i++ > 1000) { -			priv->link = 0; -			return 1; -		} - -		udelay(1000);	/* 1 ms */ -	} - -	priv->link = 1; -	switch ((val >> 13) & 0x3) { -	case (0x00): -		priv->speed = 10; -		break; -	case (0x01): -		priv->speed = 100; -		break; -	case (0x02): -		priv->speed = 1000; -		break; -	} - -	priv->duplexity = (val & 0x1000) == 0x1000; - -	return 0; -} - -/* - * Figure out if BCM5482 is in serdes or copper mode and determine link - * configuration accordingly - */ -static uint mii_parse_BCM5482_sr(uint mii_reg, struct tsec_private *priv) -{ -	if (BCM8482_is_serdes(priv)) { -		mii_parse_BCM5482_serdes_sr(priv); -		priv->flags |= TSEC_FIBER; -	} else { -		/* Wait for auto-negotiation to complete or fail */ -		mii_parse_sr(mii_reg, priv); - -		/* Parse BCM54xx copper aux status register */ -		mii_reg = read_phy_reg(priv, MIIM_BCM54xx_AUXSTATUS); -		mii_parse_BCM54xx_sr(mii_reg, priv); -	} - -	return 0; -} - -/* Parse the 88E1011's status register for speed and duplex - * information - */ -static uint mii_parse_88E1011_psr(uint mii_reg, struct tsec_private * priv) -{ -	uint speed; - -	mii_reg = read_phy_reg(priv, MIIM_88E1011_PHY_STATUS); - -	if ((mii_reg & MIIM_88E1011_PHYSTAT_LINK) && -		!(mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE)) { -		int i = 0; - -		puts("Waiting for PHY realtime link"); -		while (!(mii_reg & MIIM_88E1011_PHYSTAT_SPDDONE)) { -			/* Timeout reached ? */ -			if (i > PHY_AUTONEGOTIATE_TIMEOUT) { -				puts(" TIMEOUT !\n"); -				priv->link = 0; -				break; -			} - -			if ((i++ % 1000) == 0) { -				putc('.'); -			} -			udelay(1000);	/* 1 ms */ -			mii_reg = read_phy_reg(priv, MIIM_88E1011_PHY_STATUS); -		} -		puts(" done\n"); -		udelay(500000);	/* another 500 ms (results in faster booting) */ -	} else { -		if (mii_reg & MIIM_88E1011_PHYSTAT_LINK) -			priv->link = 1; -		else -			priv->link = 0; -	} - -	if (mii_reg & MIIM_88E1011_PHYSTAT_DUPLEX) -		priv->duplexity = 1; -	else -		priv->duplexity = 0; - -	speed = (mii_reg & MIIM_88E1011_PHYSTAT_SPEED); +#ifdef CONFIG_MCAST_TFTP -	switch (speed) { -	case MIIM_88E1011_PHYSTAT_GBIT: -		priv->speed = 1000; -		break; -	case MIIM_88E1011_PHYSTAT_100: -		priv->speed = 100; -		break; -	default: -		priv->speed = 10; -	} +/* CREDITS: linux gianfar driver, slightly adjusted... thanx. */ -	return 0; -} +/* Set the appropriate hash bit for the given addr */ -/* Parse the RTL8211B's status register for speed and duplex - * information - */ -static uint mii_parse_RTL8211B_sr(uint mii_reg, struct tsec_private * priv) +/* The algorithm works like so: + * 1) Take the Destination Address (ie the multicast address), and + * do a CRC on it (little endian), and reverse the bits of the + * result. + * 2) Use the 8 most significant bits as a hash into a 256-entry + * table.  The table is controlled through 8 32-bit registers: + * gaddr0-7.  gaddr0's MSB is entry 0, and gaddr7's LSB is + * gaddr7.  This means that the 3 most significant bits in the + * hash index which gaddr register to use, and the 5 other bits + * indicate which bit (assuming an IBM numbering scheme, which + * for PowerPC (tm) is usually the case) in the tregister holds + * the entry. */ +static int +tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set)  { -	uint speed; +	struct tsec_private *priv = privlist[1]; +	volatile tsec_t *regs = priv->regs; +	volatile u32  *reg_array, value; +	u8 result, whichbit, whichreg; -	mii_reg = read_phy_reg(priv, MIIM_RTL8211B_PHY_STATUS); -	if (!(mii_reg & MIIM_RTL8211B_PHYSTAT_SPDDONE)) { -		int i = 0; +	result = (u8)((ether_crc(MAC_ADDR_LEN,mcast_mac) >> 24) & 0xff); +	whichbit = result & 0x1f;	/* the 5 LSB = which bit to set */ +	whichreg = result >> 5;		/* the 3 MSB = which reg to set it in */ +	value = (1 << (31-whichbit)); -		/* in case of timeout ->link is cleared */ -		priv->link = 1; -		puts("Waiting for PHY realtime link"); -		while (!(mii_reg & MIIM_RTL8211B_PHYSTAT_SPDDONE)) { -			/* Timeout reached ? */ -			if (i > PHY_AUTONEGOTIATE_TIMEOUT) { -				puts(" TIMEOUT !\n"); -				priv->link = 0; -				break; -			} +	reg_array = &(regs->hash.gaddr0); -			if ((i++ % 1000) == 0) { -				putc('.'); -			} -			udelay(1000);	/* 1 ms */ -			mii_reg = read_phy_reg(priv, MIIM_RTL8211B_PHY_STATUS); -		} -		puts(" done\n"); -		udelay(500000);	/* another 500 ms (results in faster booting) */ +	if (set) { +		reg_array[whichreg] |= value;  	} else { -		if (mii_reg & MIIM_RTL8211B_PHYSTAT_LINK) -			priv->link = 1; -		else -			priv->link = 0; -	} - -	if (mii_reg & MIIM_RTL8211B_PHYSTAT_DUPLEX) -		priv->duplexity = 1; -	else -		priv->duplexity = 0; - -	speed = (mii_reg & MIIM_RTL8211B_PHYSTAT_SPEED); - -	switch (speed) { -	case MIIM_RTL8211B_PHYSTAT_GBIT: -		priv->speed = 1000; -		break; -	case MIIM_RTL8211B_PHYSTAT_100: -		priv->speed = 100; -		break; -	default: -		priv->speed = 10; -	} - -	return 0; -} - -/* Parse the cis8201's status register for speed and duplex - * information - */ -static uint mii_parse_cis8201(uint mii_reg, struct tsec_private * priv) -{ -	uint speed; - -	if (mii_reg & MIIM_CIS8201_AUXCONSTAT_DUPLEX) -		priv->duplexity = 1; -	else -		priv->duplexity = 0; - -	speed = mii_reg & MIIM_CIS8201_AUXCONSTAT_SPEED; -	switch (speed) { -	case MIIM_CIS8201_AUXCONSTAT_GBIT: -		priv->speed = 1000; -		break; -	case MIIM_CIS8201_AUXCONSTAT_100: -		priv->speed = 100; -		break; -	default: -		priv->speed = 10; -		break; -	} - -	return 0; -} - -/* Parse the vsc8244's status register for speed and duplex - * information - */ -static uint mii_parse_vsc8244(uint mii_reg, struct tsec_private * priv) -{ -	uint speed; - -	if (mii_reg & MIIM_VSC8244_AUXCONSTAT_DUPLEX) -		priv->duplexity = 1; -	else -		priv->duplexity = 0; - -	speed = mii_reg & MIIM_VSC8244_AUXCONSTAT_SPEED; -	switch (speed) { -	case MIIM_VSC8244_AUXCONSTAT_GBIT: -		priv->speed = 1000; -		break; -	case MIIM_VSC8244_AUXCONSTAT_100: -		priv->speed = 100; -		break; -	default: -		priv->speed = 10; -		break; +		reg_array[whichreg] &= ~value;  	} -  	return 0;  } - -/* Parse the DM9161's status register for speed and duplex - * information - */ -static uint mii_parse_dm9161_scsr(uint mii_reg, struct tsec_private * priv) -{ -	if (mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_100H)) -		priv->speed = 100; -	else -		priv->speed = 10; - -	if (mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_10F)) -		priv->duplexity = 1; -	else -		priv->duplexity = 0; - -	return 0; -} - -/* - * Hack to write all 4 PHYs with the LED values - */ -static uint mii_cis8204_fixled(uint mii_reg, struct tsec_private * priv) -{ -	uint phyid; -	volatile tsec_mdio_t *regbase = priv->phyregs; -	int timeout = 1000000; - -	for (phyid = 0; phyid < 4; phyid++) { -		regbase->miimadd = (phyid << 8) | mii_reg; -		regbase->miimcon = MIIM_CIS8204_SLEDCON_INIT; -		asm("sync"); - -		timeout = 1000000; -		while ((regbase->miimind & MIIMIND_BUSY) && timeout--) ; -	} - -	return MIIM_CIS8204_SLEDCON_INIT; -} - -static uint mii_cis8204_setmode(uint mii_reg, struct tsec_private * priv) -{ -	if (priv->flags & TSEC_REDUCED) -		return MIIM_CIS8204_EPHYCON_INIT | MIIM_CIS8204_EPHYCON_RGMII; -	else -		return MIIM_CIS8204_EPHYCON_INIT; -} - -static uint mii_m88e1111s_setmode(uint mii_reg, struct tsec_private *priv) -{ -	uint mii_data = read_phy_reg(priv, mii_reg); - -	if (priv->flags & TSEC_REDUCED) -		mii_data = (mii_data & 0xfff0) | 0x000b; -	return mii_data; -} +#endif /* Multicast TFTP ? */  /* Initialized required registers to appropriate values, zeroing   * those we don't care about (unless zero is bad, in which case,   * choose a more appropriate value)   */ -static void init_registers(volatile tsec_t * regs) +static void init_registers(tsec_t *regs)  {  	/* Clear IEVENT */ -	regs->ievent = IEVENT_INIT_CLEAR; +	out_be32(®s->ievent, IEVENT_INIT_CLEAR); -	regs->imask = IMASK_INIT_CLEAR; +	out_be32(®s->imask, IMASK_INIT_CLEAR); -	regs->hash.iaddr0 = 0; -	regs->hash.iaddr1 = 0; -	regs->hash.iaddr2 = 0; -	regs->hash.iaddr3 = 0; -	regs->hash.iaddr4 = 0; -	regs->hash.iaddr5 = 0; -	regs->hash.iaddr6 = 0; -	regs->hash.iaddr7 = 0; +	out_be32(®s->hash.iaddr0, 0); +	out_be32(®s->hash.iaddr1, 0); +	out_be32(®s->hash.iaddr2, 0); +	out_be32(®s->hash.iaddr3, 0); +	out_be32(®s->hash.iaddr4, 0); +	out_be32(®s->hash.iaddr5, 0); +	out_be32(®s->hash.iaddr6, 0); +	out_be32(®s->hash.iaddr7, 0); -	regs->hash.gaddr0 = 0; -	regs->hash.gaddr1 = 0; -	regs->hash.gaddr2 = 0; -	regs->hash.gaddr3 = 0; -	regs->hash.gaddr4 = 0; -	regs->hash.gaddr5 = 0; -	regs->hash.gaddr6 = 0; -	regs->hash.gaddr7 = 0; +	out_be32(®s->hash.gaddr0, 0); +	out_be32(®s->hash.gaddr1, 0); +	out_be32(®s->hash.gaddr2, 0); +	out_be32(®s->hash.gaddr3, 0); +	out_be32(®s->hash.gaddr4, 0); +	out_be32(®s->hash.gaddr5, 0); +	out_be32(®s->hash.gaddr6, 0); +	out_be32(®s->hash.gaddr7, 0); -	regs->rctrl = 0x00000000; +	out_be32(®s->rctrl, 0x00000000);  	/* Init RMON mib registers */  	memset((void *)&(regs->rmon), 0, sizeof(rmon_mib_t)); -	regs->rmon.cam1 = 0xffffffff; -	regs->rmon.cam2 = 0xffffffff; +	out_be32(®s->rmon.cam1, 0xffffffff); +	out_be32(®s->rmon.cam2, 0xffffffff); -	regs->mrblr = MRBLR_INIT_SETTINGS; +	out_be32(®s->mrblr, MRBLR_INIT_SETTINGS); -	regs->minflr = MINFLR_INIT_SETTINGS; +	out_be32(®s->minflr, MINFLR_INIT_SETTINGS); -	regs->attr = ATTR_INIT_SETTINGS; -	regs->attreli = ATTRELI_INIT_SETTINGS; +	out_be32(®s->attr, ATTR_INIT_SETTINGS); +	out_be32(®s->attreli, ATTRELI_INIT_SETTINGS);  }  /* Configure maccfg2 based on negotiated speed and duplex   * reported by PHY handling code   */ -static void adjust_link(struct eth_device *dev) +static void adjust_link(struct tsec_private *priv, struct phy_device *phydev)  { -	struct tsec_private *priv = (struct tsec_private *)dev->priv; -	volatile tsec_t *regs = priv->regs; +	tsec_t *regs = priv->regs; +	u32 ecntrl, maccfg2; -	if (priv->link) { -		if (priv->duplexity != 0) -			regs->maccfg2 |= MACCFG2_FULL_DUPLEX; -		else -			regs->maccfg2 &= ~(MACCFG2_FULL_DUPLEX); +	if (!phydev->link) { +		printf("%s: No link.\n", phydev->dev->name); +		return; +	} -		switch (priv->speed) { -		case 1000: -			regs->maccfg2 = ((regs->maccfg2 & ~(MACCFG2_IF)) -					 | MACCFG2_GMII); -			break; -		case 100: -		case 10: -			regs->maccfg2 = ((regs->maccfg2 & ~(MACCFG2_IF)) -					 | MACCFG2_MII); +	/* clear all bits relative with interface mode */ +	ecntrl = in_be32(®s->ecntrl); +	ecntrl &= ~ECNTRL_R100; -			/* Set R100 bit in all modes although -			 * it is only used in RGMII mode -			 */ -			if (priv->speed == 100) -				regs->ecntrl |= ECNTRL_R100; -			else -				regs->ecntrl &= ~(ECNTRL_R100); -			break; -		default: -			printf("%s: Speed was bad\n", dev->name); -			break; -		} +	maccfg2 = in_be32(®s->maccfg2); +	maccfg2 &= ~(MACCFG2_IF | MACCFG2_FULL_DUPLEX); -		printf("Speed: %d, %s duplex%s\n", priv->speed, -		       (priv->duplexity) ? "full" : "half", -		       (priv->flags & TSEC_FIBER) ? ", fiber mode" : ""); +	if (phydev->duplex) +		maccfg2 |= MACCFG2_FULL_DUPLEX; -	} else { -		printf("%s: No link.\n", dev->name); +	switch (phydev->speed) { +	case 1000: +		maccfg2 |= MACCFG2_GMII; +		break; +	case 100: +	case 10: +		maccfg2 |= MACCFG2_MII; + +		/* Set R100 bit in all modes although +		 * it is only used in RGMII mode +		 */ +		if (phydev->speed == 100) +			ecntrl |= ECNTRL_R100; +		break; +	default: +		printf("%s: Speed was bad\n", phydev->dev->name); +		break;  	} + +	out_be32(®s->ecntrl, ecntrl); +	out_be32(®s->maccfg2, maccfg2); + +	printf("Speed: %d, %s duplex%s\n", phydev->speed, +			(phydev->duplex) ? "full" : "half", +			(phydev->port == PORT_FIBRE) ? ", fiber mode" : "");  }  /* Set up the buffers and their descriptors, and bring up the @@ -969,11 +243,15 @@ static void startup_tsec(struct eth_device *dev)  {  	int i;  	struct tsec_private *priv = (struct tsec_private *)dev->priv; -	volatile tsec_t *regs = priv->regs; +	tsec_t *regs = priv->regs; + +	/* reset the indices to zero */ +	rxIdx = 0; +	txIdx = 0;  	/* Point to the buffer descriptors */ -	regs->tbase = (unsigned int)(&rtx.txbd[txIdx]); -	regs->rbase = (unsigned int)(&rtx.rxbd[rxIdx]); +	out_be32(®s->tbase, (unsigned int)(&rtx.txbd[txIdx])); +	out_be32(®s->rbase, (unsigned int)(&rtx.rxbd[rxIdx]));  	/* Initialize the Rx Buffer descriptors */  	for (i = 0; i < PKTBUFSRX; i++) { @@ -991,20 +269,14 @@ static void startup_tsec(struct eth_device *dev)  	}  	rtx.txbd[TX_BUF_CNT - 1].status |= TXBD_WRAP; -	/* Start up the PHY */ -	if(priv->phyinfo) -		phy_run_commands(priv, priv->phyinfo->startup); - -	adjust_link(dev); -  	/* Enable Transmit and Receive */ -	regs->maccfg1 |= (MACCFG1_RX_EN | MACCFG1_TX_EN); +	setbits_be32(®s->maccfg1, MACCFG1_RX_EN | MACCFG1_TX_EN);  	/* Tell the DMA it is clear to go */ -	regs->dmactrl |= DMACTRL_INIT_SETTINGS; -	regs->tstat = TSTAT_CLEAR_THALT; -	regs->rstat = RSTAT_CLEAR_RHALT; -	regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS); +	setbits_be32(®s->dmactrl, DMACTRL_INIT_SETTINGS); +	out_be32(®s->tstat, TSTAT_CLEAR_THALT); +	out_be32(®s->rstat, RSTAT_CLEAR_RHALT); +	clrbits_be32(®s->dmactrl, DMACTRL_GRS | DMACTRL_GTS);  }  /* This returns the status bits of the device.	The return value @@ -1017,7 +289,7 @@ static int tsec_send(struct eth_device *dev, volatile void *packet, int length)  	int i;  	int result = 0;  	struct tsec_private *priv = (struct tsec_private *)dev->priv; -	volatile tsec_t *regs = priv->regs; +	tsec_t *regs = priv->regs;  	/* Find an empty buffer descriptor */  	for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) { @@ -1033,7 +305,7 @@ static int tsec_send(struct eth_device *dev, volatile void *packet, int length)  	    (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT);  	/* Tell the DMA to go */ -	regs->tstat = TSTAT_CLEAR_THALT; +	out_be32(®s->tstat, TSTAT_CLEAR_THALT);  	/* Wait for buffer to be transmitted */  	for (i = 0; rtx.txbd[txIdx].status & TXBD_READY; i++) { @@ -1053,7 +325,7 @@ static int tsec_recv(struct eth_device *dev)  {  	int length;  	struct tsec_private *priv = (struct tsec_private *)dev->priv; -	volatile tsec_t *regs = priv->regs; +	tsec_t *regs = priv->regs;  	while (!(rtx.rxbd[rxIdx].status & RXBD_EMPTY)) { @@ -1076,9 +348,9 @@ static int tsec_recv(struct eth_device *dev)  		rxIdx = (rxIdx + 1) % PKTBUFSRX;  	} -	if (regs->ievent & IEVENT_BSY) { -		regs->ievent = IEVENT_BSY; -		regs->rstat = RSTAT_CLEAR_RHALT; +	if (in_be32(®s->ievent) & IEVENT_BSY) { +		out_be32(®s->ievent, IEVENT_BSY); +		out_be32(®s->rstat, RSTAT_CLEAR_RHALT);  	}  	return -1; @@ -1089,936 +361,236 @@ static int tsec_recv(struct eth_device *dev)  static void tsec_halt(struct eth_device *dev)  {  	struct tsec_private *priv = (struct tsec_private *)dev->priv; -	volatile tsec_t *regs = priv->regs; +	tsec_t *regs = priv->regs; -	regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS); -	regs->dmactrl |= (DMACTRL_GRS | DMACTRL_GTS); +	clrbits_be32(®s->dmactrl, DMACTRL_GRS | DMACTRL_GTS); +	setbits_be32(®s->dmactrl, DMACTRL_GRS | DMACTRL_GTS); -	while ((regs->ievent & (IEVENT_GRSC | IEVENT_GTSC)) -		!= (IEVENT_GRSC | IEVENT_GTSC)) ; +	while ((in_be32(®s->ievent) & (IEVENT_GRSC | IEVENT_GTSC)) +			!= (IEVENT_GRSC | IEVENT_GTSC)) +		; -	regs->maccfg1 &= ~(MACCFG1_TX_EN | MACCFG1_RX_EN); +	clrbits_be32(®s->maccfg1, MACCFG1_TX_EN | MACCFG1_RX_EN);  	/* Shut down the PHY, as needed */ -	if(priv->phyinfo) -		phy_run_commands(priv, priv->phyinfo->shutdown); +	phy_shutdown(priv->phydev);  } -static struct phy_info phy_info_M88E1149S = { -	0x1410ca, -	"Marvell 88E1149S", -	4, -	(struct phy_cmd[]) {     /* config */ -		/* Reset and configure the PHY */ -		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, -		{0x1d, 0x1f, NULL}, -		{0x1e, 0x200c, NULL}, -		{0x1d, 0x5, NULL}, -		{0x1e, 0x0, NULL}, -		{0x1e, 0x100, NULL}, -		{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, -		{MIIM_ANAR, MIIM_ANAR_INIT, NULL}, -		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, -		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {     /* startup */ -		/* Status is read once to clear old link state */ -		{MIIM_STATUS, miim_read, NULL}, -		/* Auto-negotiate */ -		{MIIM_STATUS, miim_read, &mii_parse_sr}, -		/* Read the status */ -		{MIIM_88E1011_PHY_STATUS, miim_read, &mii_parse_88E1011_psr}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {     /* shutdown */ -		{miim_end,} -	}, -}; - -/* The 5411 id is 0x206070, the 5421 is 0x2060e0 */ -static struct phy_info phy_info_BCM5461S = { -	0x02060c1,	/* 5461 ID */ -	"Broadcom BCM5461S", -	0, /* not clear to me what minor revisions we can shift away */ -	(struct phy_cmd[]) { /* config */ -		/* Reset and configure the PHY */ -		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, -		{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, -		{MIIM_ANAR, MIIM_ANAR_INIT, NULL}, -		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, -		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, -		{miim_end,} -	}, -	(struct phy_cmd[]) { /* startup */ -		/* Status is read once to clear old link state */ -		{MIIM_STATUS, miim_read, NULL}, -		/* Auto-negotiate */ -		{MIIM_STATUS, miim_read, &mii_parse_sr}, -		/* Read the status */ -		{MIIM_BCM54xx_AUXSTATUS, miim_read, &mii_parse_BCM54xx_sr}, -		{miim_end,} -	}, -	(struct phy_cmd[]) { /* shutdown */ -		{miim_end,} -	}, -}; - -static struct phy_info phy_info_BCM5464S = { -	0x02060b1,	/* 5464 ID */ -	"Broadcom BCM5464S", -	0, /* not clear to me what minor revisions we can shift away */ -	(struct phy_cmd[]) { /* config */ -		/* Reset and configure the PHY */ -		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, -		{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, -		{MIIM_ANAR, MIIM_ANAR_INIT, NULL}, -		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, -		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, -		{miim_end,} -	}, -	(struct phy_cmd[]) { /* startup */ -		/* Status is read once to clear old link state */ -		{MIIM_STATUS, miim_read, NULL}, -		/* Auto-negotiate */ -		{MIIM_STATUS, miim_read, &mii_parse_sr}, -		/* Read the status */ -		{MIIM_BCM54xx_AUXSTATUS, miim_read, &mii_parse_BCM54xx_sr}, -		{miim_end,} -	}, -	(struct phy_cmd[]) { /* shutdown */ -		{miim_end,} -	}, -}; - -static struct phy_info phy_info_BCM5482S =  { -	0x0143bcb, -	"Broadcom BCM5482S", -	4, -	(struct phy_cmd[]) { /* config */ -		/* Reset and configure the PHY */ -		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, -		/* Setup read from auxilary control shadow register 7 */ -		{MIIM_BCM54xx_AUXCNTL, MIIM_BCM54xx_AUXCNTL_ENCODE(7), NULL}, -		/* Read Misc Control register and or in Ethernet@Wirespeed */ -		{MIIM_BCM54xx_AUXCNTL, 0, &mii_BCM54xx_wirespeed}, -		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, -		/* Initial config/enable of secondary SerDes interface */ -		{MIIM_BCM54XX_SHD, MIIM_BCM54XX_SHD_WR_ENCODE(0x14, 0xf), NULL}, -		/* Write intial value to secondary SerDes Contol */ -		{MIIM_BCM54XX_EXP_SEL, MIIM_BCM54XX_EXP_SEL_SSD | 0, NULL}, -		{MIIM_BCM54XX_EXP_DATA, MIIM_CONTROL_RESTART, NULL}, -		/* Enable copper/fiber auto-detect */ -		{MIIM_BCM54XX_SHD, MIIM_BCM54XX_SHD_WR_ENCODE(0x1e, 0x201)}, -		{miim_end,} -	}, -	(struct phy_cmd[]) { /* startup */ -		/* Status is read once to clear old link state */ -		{MIIM_STATUS, miim_read, NULL}, -		/* Determine copper/fiber, auto-negotiate, and read the result */ -		{MIIM_STATUS, miim_read, &mii_parse_BCM5482_sr}, -		{miim_end,} -	}, -	(struct phy_cmd[]) { /* shutdown */ -		{miim_end,} -	}, -}; - -static struct phy_info phy_info_M88E1011S = { -	0x01410c6, -	"Marvell 88E1011S", -	4, -	(struct phy_cmd[]) {	/* config */ -		/* Reset and configure the PHY */ -		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, -		{0x1d, 0x1f, NULL}, -		{0x1e, 0x200c, NULL}, -		{0x1d, 0x5, NULL}, -		{0x1e, 0x0, NULL}, -		{0x1e, 0x100, NULL}, -		{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, -		{MIIM_ANAR, MIIM_ANAR_INIT, NULL}, -		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, -		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {	/* startup */ -		/* Status is read once to clear old link state */ -		{MIIM_STATUS, miim_read, NULL}, -		/* Auto-negotiate */ -		{MIIM_STATUS, miim_read, &mii_parse_sr}, -		/* Read the status */ -		{MIIM_88E1011_PHY_STATUS, miim_read, &mii_parse_88E1011_psr}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {	/* shutdown */ -		{miim_end,} -	}, -}; - -static struct phy_info phy_info_M88E1111S = { -	0x01410cc, -	"Marvell 88E1111S", -	4, -	(struct phy_cmd[]) {	/* config */ -		/* Reset and configure the PHY */ -		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, -		{0x1b, 0x848f, &mii_m88e1111s_setmode}, -		{0x14, 0x0cd2, NULL}, /* Delay RGMII TX and RX */ -		{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, -		{MIIM_ANAR, MIIM_ANAR_INIT, NULL}, -		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, -		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {	/* startup */ -		/* Status is read once to clear old link state */ -		{MIIM_STATUS, miim_read, NULL}, -		/* Auto-negotiate */ -		{MIIM_STATUS, miim_read, &mii_parse_sr}, -		/* Read the status */ -		{MIIM_88E1011_PHY_STATUS, miim_read, &mii_parse_88E1011_psr}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {	/* shutdown */ -		{miim_end,} -	}, -}; - -static struct phy_info phy_info_M88E1118 = { -	0x01410e1, -	"Marvell 88E1118", -	4, -	(struct phy_cmd[]) {	/* config */ -		/* Reset and configure the PHY */ -		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, -		{0x16, 0x0002, NULL}, /* Change Page Number */ -		{0x15, 0x1070, NULL}, /* Delay RGMII TX and RX */ -		{0x16, 0x0003, NULL}, /* Change Page Number */ -		{0x10, 0x021e, NULL}, /* Adjust LED control */ -		{0x16, 0x0000, NULL}, /* Change Page Number */ -		{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, -		{MIIM_ANAR, MIIM_ANAR_INIT, NULL}, -		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, -		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {	/* startup */ -		{0x16, 0x0000, NULL}, /* Change Page Number */ -		/* Status is read once to clear old link state */ -		{MIIM_STATUS, miim_read, NULL}, -		/* Auto-negotiate */ -		{MIIM_STATUS, miim_read, &mii_parse_sr}, -		/* Read the status */ -		{MIIM_88E1011_PHY_STATUS, miim_read, -		 &mii_parse_88E1011_psr}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {	/* shutdown */ -		{miim_end,} -	}, -}; - -/* - *  Since to access LED register we need do switch the page, we - * do LED configuring in the miim_read-like function as follows +/* Initializes data structures and registers for the controller, + * and brings the interface up.	 Returns the link status, meaning + * that it returns success if the link is up, failure otherwise. + * This allows u-boot to find the first active controller.   */ -static uint mii_88E1121_set_led (uint mii_reg, struct tsec_private *priv) +static int tsec_init(struct eth_device *dev, bd_t * bd)  { -	uint pg; - -	/* Switch the page to access the led register */ -	pg = read_phy_reg(priv, MIIM_88E1121_PHY_PAGE); -	write_phy_reg(priv, MIIM_88E1121_PHY_PAGE, MIIM_88E1121_PHY_LED_PAGE); +	uint tempval; +	char tmpbuf[MAC_ADDR_LEN]; +	int i; +	struct tsec_private *priv = (struct tsec_private *)dev->priv; +	tsec_t *regs = priv->regs; -	/* Configure leds */ -	write_phy_reg(priv, MIIM_88E1121_PHY_LED_CTRL, -		      MIIM_88E1121_PHY_LED_DEF); +	/* Make sure the controller is stopped */ +	tsec_halt(dev); -	/* Restore the page pointer */ -	write_phy_reg(priv, MIIM_88E1121_PHY_PAGE, pg); -	return 0; -} +	/* Init MACCFG2.  Defaults to GMII */ +	out_be32(®s->maccfg2, MACCFG2_INIT_SETTINGS); -static struct phy_info phy_info_M88E1121R = { -	0x01410cb, -	"Marvell 88E1121R", -	4, -	(struct phy_cmd[]) {	/* config */ -		/* Reset and configure the PHY */ -		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, -		{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, -		{MIIM_ANAR, MIIM_ANAR_INIT, NULL}, -		/* Configure leds */ -		{MIIM_88E1121_PHY_LED_CTRL, miim_read, &mii_88E1121_set_led}, -		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, -		/* Disable IRQs and de-assert interrupt */ -		{MIIM_88E1121_PHY_IRQ_EN, 0, NULL}, -		{MIIM_88E1121_PHY_IRQ_STATUS, miim_read, NULL}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {	/* startup */ -		/* Status is read once to clear old link state */ -		{MIIM_STATUS, miim_read, NULL}, -		{MIIM_STATUS, miim_read, &mii_parse_sr}, -		{MIIM_STATUS, miim_read, &mii_parse_link}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {	/* shutdown */ -		{miim_end,} -	}, -}; +	/* Init ECNTRL */ +	out_be32(®s->ecntrl, ECNTRL_INIT_SETTINGS); -static unsigned int m88e1145_setmode(uint mii_reg, struct tsec_private *priv) -{ -	uint mii_data = read_phy_reg(priv, mii_reg); +	/* Copy the station address into the address registers. +	 * Backwards, because little endian MACS are dumb */ +	for (i = 0; i < MAC_ADDR_LEN; i++) +		tmpbuf[MAC_ADDR_LEN - 1 - i] = dev->enetaddr[i]; -	/* Setting MIIM_88E1145_PHY_EXT_CR */ -	if (priv->flags & TSEC_REDUCED) -		return mii_data | -		    MIIM_M88E1145_RGMII_RX_DELAY | MIIM_M88E1145_RGMII_TX_DELAY; -	else -		return mii_data; -} +	tempval = (tmpbuf[0] << 24) | (tmpbuf[1] << 16) | (tmpbuf[2] << 8) | +		  tmpbuf[3]; -static struct phy_info phy_info_M88E1145 = { -	0x01410cd, -	"Marvell 88E1145", -	4, -	(struct phy_cmd[]) {	/* config */ -		/* Reset the PHY */ -		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, +	out_be32(®s->macstnaddr1, tempval); -		/* Errata E0, E1 */ -		{29, 0x001b, NULL}, -		{30, 0x418f, NULL}, -		{29, 0x0016, NULL}, -		{30, 0xa2da, NULL}, +	tempval = *((uint *) (tmpbuf + 4)); -		/* Configure the PHY */ -		{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, -		{MIIM_ANAR, MIIM_ANAR_INIT, NULL}, -		{MIIM_88E1011_PHY_SCR, MIIM_88E1011_PHY_MDI_X_AUTO, NULL}, -		{MIIM_88E1145_PHY_EXT_CR, 0, &m88e1145_setmode}, -		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, -		{MIIM_CONTROL, MIIM_CONTROL_INIT, NULL}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {	/* startup */ -		/* Status is read once to clear old link state */ -		{MIIM_STATUS, miim_read, NULL}, -		/* Auto-negotiate */ -		{MIIM_STATUS, miim_read, &mii_parse_sr}, -		{MIIM_88E1111_PHY_LED_CONTROL, MIIM_88E1111_PHY_LED_DIRECT, NULL}, -		/* Read the Status */ -		{MIIM_88E1011_PHY_STATUS, miim_read, &mii_parse_88E1011_psr}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {	/* shutdown */ -		{miim_end,} -	}, -}; +	out_be32(®s->macstnaddr2, tempval); -static struct phy_info phy_info_cis8204 = { -	0x3f11, -	"Cicada Cis8204", -	6, -	(struct phy_cmd[]) {	/* config */ -		/* Override PHY config settings */ -		{MIIM_CIS8201_AUX_CONSTAT, MIIM_CIS8201_AUXCONSTAT_INIT, NULL}, -		/* Configure some basic stuff */ -		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, -		{MIIM_CIS8204_SLED_CON, MIIM_CIS8204_SLEDCON_INIT, -		 &mii_cis8204_fixled}, -		{MIIM_CIS8204_EPHY_CON, MIIM_CIS8204_EPHYCON_INIT, -		 &mii_cis8204_setmode}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {	/* startup */ -		/* Read the Status (2x to make sure link is right) */ -		{MIIM_STATUS, miim_read, NULL}, -		/* Auto-negotiate */ -		{MIIM_STATUS, miim_read, &mii_parse_sr}, -		/* Read the status */ -		{MIIM_CIS8201_AUX_CONSTAT, miim_read, &mii_parse_cis8201}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {	/* shutdown */ -		{miim_end,} -	}, -}; +	/* Clear out (for the most part) the other registers */ +	init_registers(regs); -/* Cicada 8201 */ -static struct phy_info phy_info_cis8201 = { -	0xfc41, -	"CIS8201", -	4, -	(struct phy_cmd[]) {	/* config */ -		/* Override PHY config settings */ -		{MIIM_CIS8201_AUX_CONSTAT, MIIM_CIS8201_AUXCONSTAT_INIT, NULL}, -		/* Set up the interface mode */ -		{MIIM_CIS8201_EXT_CON1, MIIM_CIS8201_EXTCON1_INIT, NULL}, -		/* Configure some basic stuff */ -		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {	/* startup */ -		/* Read the Status (2x to make sure link is right) */ -		{MIIM_STATUS, miim_read, NULL}, -		/* Auto-negotiate */ -		{MIIM_STATUS, miim_read, &mii_parse_sr}, -		/* Read the status */ -		{MIIM_CIS8201_AUX_CONSTAT, miim_read, &mii_parse_cis8201}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {	/* shutdown */ -		{miim_end,} -	}, -}; +	/* Ready the device for tx/rx */ +	startup_tsec(dev); -static struct phy_info phy_info_VSC8211 = { -	0xfc4b, -	"Vitesse VSC8211", -	4, -	(struct phy_cmd[]) { /* config */ -		/* Override PHY config settings */ -		{MIIM_CIS8201_AUX_CONSTAT, MIIM_CIS8201_AUXCONSTAT_INIT, NULL}, -		/* Set up the interface mode */ -		{MIIM_CIS8201_EXT_CON1, MIIM_CIS8201_EXTCON1_INIT, NULL}, -		/* Configure some basic stuff */ -		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, -		{miim_end,} -	}, -	(struct phy_cmd[]) { /* startup */ -		/* Read the Status (2x to make sure link is right) */ -		{MIIM_STATUS, miim_read, NULL}, -		/* Auto-negotiate */ -		{MIIM_STATUS, miim_read, &mii_parse_sr}, -		/* Read the status */ -		{MIIM_CIS8201_AUX_CONSTAT, miim_read, &mii_parse_cis8201}, -		{miim_end,} -	}, -	(struct phy_cmd[]) { /* shutdown */ -		{miim_end,} -	}, -}; +	/* Start up the PHY */ +	phy_startup(priv->phydev); -static struct phy_info phy_info_VSC8244 = { -	0x3f1b, -	"Vitesse VSC8244", -	6, -	(struct phy_cmd[]) {	/* config */ -		/* Override PHY config settings */ -		/* Configure some basic stuff */ -		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {	/* startup */ -		/* Read the Status (2x to make sure link is right) */ -		{MIIM_STATUS, miim_read, NULL}, -		/* Auto-negotiate */ -		{MIIM_STATUS, miim_read, &mii_parse_sr}, -		/* Read the status */ -		{MIIM_VSC8244_AUX_CONSTAT, miim_read, &mii_parse_vsc8244}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {	/* shutdown */ -		{miim_end,} -	}, -}; +	adjust_link(priv, priv->phydev); -static struct phy_info phy_info_VSC8641 = { -	0x7043, -	"Vitesse VSC8641", -	4, -	(struct phy_cmd[]) {	/* config */ -		/* Configure some basic stuff */ -		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {	/* startup */ -		/* Read the Status (2x to make sure link is right) */ -		{MIIM_STATUS, miim_read, NULL}, -		/* Auto-negotiate */ -		{MIIM_STATUS, miim_read, &mii_parse_sr}, -		/* Read the status */ -		{MIIM_VSC8244_AUX_CONSTAT, miim_read, &mii_parse_vsc8244}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {	/* shutdown */ -		{miim_end,} -	}, -}; +	/* If there's no link, fail */ +	return priv->phydev->link ? 0 : -1; +} -static struct phy_info phy_info_VSC8221 = { -	0xfc55, -	"Vitesse VSC8221", -	4, -	(struct phy_cmd[]) {	/* config */ -		/* Configure some basic stuff */ -		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {	/* startup */ -		/* Read the Status (2x to make sure link is right) */ -		{MIIM_STATUS, miim_read, NULL}, -		/* Auto-negotiate */ -		{MIIM_STATUS, miim_read, &mii_parse_sr}, -		/* Read the status */ -		{MIIM_VSC8244_AUX_CONSTAT, miim_read, &mii_parse_vsc8244}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {	/* shutdown */ -		{miim_end,} -	}, -}; +static phy_interface_t tsec_get_interface(struct tsec_private *priv) +{ +	tsec_t *regs = priv->regs; +	u32 ecntrl; -static struct phy_info phy_info_VSC8601 = { -	0x00007042, -	"Vitesse VSC8601", -	4, -	(struct phy_cmd[]) {     /* config */ -		/* Override PHY config settings */ -		/* Configure some basic stuff */ -		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, -#ifdef CONFIG_SYS_VSC8601_SKEWFIX -		{MIIM_VSC8601_EPHY_CON,MIIM_VSC8601_EPHY_CON_INIT_SKEW,NULL}, -#if defined(CONFIG_SYS_VSC8601_SKEW_TX) && defined(CONFIG_SYS_VSC8601_SKEW_RX) -		{MIIM_EXT_PAGE_ACCESS,1,NULL}, -#define VSC8101_SKEW \ -	(CONFIG_SYS_VSC8601_SKEW_TX << 14) | (CONFIG_SYS_VSC8601_SKEW_RX << 12) -		{MIIM_VSC8601_SKEW_CTRL,VSC8101_SKEW,NULL}, -		{MIIM_EXT_PAGE_ACCESS,0,NULL}, -#endif -#endif -		{MIIM_ANAR, MIIM_ANAR_INIT, NULL}, -		{MIIM_CONTROL, MIIM_CONTROL_RESTART, &mii_cr_init}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {     /* startup */ -		/* Read the Status (2x to make sure link is right) */ -		{MIIM_STATUS, miim_read, NULL}, -		/* Auto-negotiate */ -		{MIIM_STATUS, miim_read, &mii_parse_sr}, -		/* Read the status */ -		{MIIM_VSC8244_AUX_CONSTAT, miim_read, &mii_parse_vsc8244}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {     /* shutdown */ -		{miim_end,} -	}, -}; +	ecntrl = in_be32(®s->ecntrl); -static struct phy_info phy_info_dm9161 = { -	0x0181b88, -	"Davicom DM9161E", -	4, -	(struct phy_cmd[]) {	/* config */ -		{MIIM_CONTROL, MIIM_DM9161_CR_STOP, NULL}, -		/* Do not bypass the scrambler/descrambler */ -		{MIIM_DM9161_SCR, MIIM_DM9161_SCR_INIT, NULL}, -		/* Clear 10BTCSR to default */ -		{MIIM_DM9161_10BTCSR, MIIM_DM9161_10BTCSR_INIT, NULL}, -		/* Configure some basic stuff */ -		{MIIM_CONTROL, MIIM_CR_INIT, NULL}, -		/* Restart Auto Negotiation */ -		{MIIM_CONTROL, MIIM_DM9161_CR_RSTAN, NULL}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {	/* startup */ -		/* Status is read once to clear old link state */ -		{MIIM_STATUS, miim_read, NULL}, -		/* Auto-negotiate */ -		{MIIM_STATUS, miim_read, &mii_parse_sr}, -		/* Read the status */ -		{MIIM_DM9161_SCSR, miim_read, &mii_parse_dm9161_scsr}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {	/* shutdown */ -		{miim_end,} -	}, -}; +	if (ecntrl & ECNTRL_SGMII_MODE) +		return PHY_INTERFACE_MODE_SGMII; -/* micrel KSZ804  */ -static struct phy_info phy_info_ksz804 =  { -	0x0022151, -	"Micrel KSZ804 PHY", -	4, -	(struct phy_cmd[]) { /* config */ -		{MII_BMCR, BMCR_RESET, NULL}, -		{MII_BMCR, BMCR_ANENABLE|BMCR_ANRESTART, NULL}, -		{miim_end,} -	}, -	(struct phy_cmd[]) { /* startup */ -		{MII_BMSR, miim_read, NULL}, -		{MII_BMSR, miim_read, &mii_parse_sr}, -		{MII_BMSR, miim_read, &mii_parse_link}, -		{miim_end,} -	}, -	(struct phy_cmd[]) { /* shutdown */ -		{miim_end,} +	if (ecntrl & ECNTRL_TBI_MODE) { +		if (ecntrl & ECNTRL_REDUCED_MODE) +			return PHY_INTERFACE_MODE_RTBI; +		else +			return PHY_INTERFACE_MODE_TBI;  	} -}; -/* a generic flavor.  */ -static struct phy_info phy_info_generic =  { -	0, -	"Unknown/Generic PHY", -	32, -	(struct phy_cmd[]) { /* config */ -		{MII_BMCR, BMCR_RESET, NULL}, -		{MII_BMCR, BMCR_ANENABLE|BMCR_ANRESTART, NULL}, -		{miim_end,} -	}, -	(struct phy_cmd[]) { /* startup */ -		{MII_BMSR, miim_read, NULL}, -		{MII_BMSR, miim_read, &mii_parse_sr}, -		{MII_BMSR, miim_read, &mii_parse_link}, -		{miim_end,} -	}, -	(struct phy_cmd[]) { /* shutdown */ -		{miim_end,} -	} -}; +	if (ecntrl & ECNTRL_REDUCED_MODE) { +		if (ecntrl & ECNTRL_REDUCED_MII_MODE) +			return PHY_INTERFACE_MODE_RMII; +		else { +			phy_interface_t interface = priv->interface; -static uint mii_parse_lxt971_sr2(uint mii_reg, struct tsec_private *priv) -{ -	unsigned int speed; -	if (priv->link) { -		speed = mii_reg & MIIM_LXT971_SR2_SPEED_MASK; +			/* +			 * This isn't autodetected, so it must +			 * be set by the platform code. +			 */ +			if ((interface == PHY_INTERFACE_MODE_RGMII_ID) || +				 (interface == PHY_INTERFACE_MODE_RGMII_TXID) || +				 (interface == PHY_INTERFACE_MODE_RGMII_RXID)) +				return interface; -		switch (speed) { -		case MIIM_LXT971_SR2_10HDX: -			priv->speed = 10; -			priv->duplexity = 0; -			break; -		case MIIM_LXT971_SR2_10FDX: -			priv->speed = 10; -			priv->duplexity = 1; -			break; -		case MIIM_LXT971_SR2_100HDX: -			priv->speed = 100; -			priv->duplexity = 0; -			break; -		default: -			priv->speed = 100; -			priv->duplexity = 1; +			return PHY_INTERFACE_MODE_RGMII;  		} -	} else { -		priv->speed = 0; -		priv->duplexity = 0;  	} -	return 0; +	if (priv->flags & TSEC_GIGABIT) +		return PHY_INTERFACE_MODE_GMII; + +	return PHY_INTERFACE_MODE_MII;  } -static struct phy_info phy_info_lxt971 = { -	0x0001378e, -	"LXT971", -	4, -	(struct phy_cmd[]) {	/* config */ -		{MIIM_CR, MIIM_CR_INIT, mii_cr_init},	/* autonegotiate */ -		{miim_end,} -	}, -	(struct phy_cmd[]) {	/* startup - enable interrupts */ -		/* { 0x12, 0x00f2, NULL }, */ -		{MIIM_STATUS, miim_read, NULL}, -		{MIIM_STATUS, miim_read, &mii_parse_sr}, -		{MIIM_LXT971_SR2, miim_read, &mii_parse_lxt971_sr2}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {	/* shutdown - disable interrupts */ -		{miim_end,} -	}, -}; -/* Parse the DP83865's link and auto-neg status register for speed and duplex - * information +/* Discover which PHY is attached to the device, and configure it + * properly.  If the PHY is not recognized, then return 0 + * (failure).  Otherwise, return 1   */ -static uint mii_parse_dp83865_lanr(uint mii_reg, struct tsec_private *priv) +static int init_phy(struct eth_device *dev)  { -	switch (mii_reg & MIIM_DP83865_SPD_MASK) { - -	case MIIM_DP83865_SPD_1000: -		priv->speed = 1000; -		break; - -	case MIIM_DP83865_SPD_100: -		priv->speed = 100; -		break; - -	default: -		priv->speed = 10; -		break; - -	} - -	if (mii_reg & MIIM_DP83865_DPX_FULL) -		priv->duplexity = 1; -	else -		priv->duplexity = 0; - -	return 0; -} - -static struct phy_info phy_info_dp83865 = { -	0x20005c7, -	"NatSemi DP83865", -	4, -	(struct phy_cmd[]) {	/* config */ -		{MIIM_CONTROL, MIIM_DP83865_CR_INIT, NULL}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {	/* startup */ -		/* Status is read once to clear old link state */ -		{MIIM_STATUS, miim_read, NULL}, -		/* Auto-negotiate */ -		{MIIM_STATUS, miim_read, &mii_parse_sr}, -		/* Read the link and auto-neg status */ -		{MIIM_DP83865_LANR, miim_read, &mii_parse_dp83865_lanr}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {	/* shutdown */ -		{miim_end,} -	}, -}; +	struct tsec_private *priv = (struct tsec_private *)dev->priv; +	struct phy_device *phydev; +	tsec_t *regs = priv->regs; +	u32 supported = (SUPPORTED_10baseT_Half | +			SUPPORTED_10baseT_Full | +			SUPPORTED_100baseT_Half | +			SUPPORTED_100baseT_Full); -static struct phy_info phy_info_rtl8211b = { -	0x001cc91, -	"RealTek RTL8211B", -	4, -	(struct phy_cmd[]) {	/* config */ -		/* Reset and configure the PHY */ -		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, -		{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, -		{MIIM_ANAR, MIIM_ANAR_INIT, NULL}, -		{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, -		{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {	/* startup */ -		/* Status is read once to clear old link state */ -		{MIIM_STATUS, miim_read, NULL}, -		/* Auto-negotiate */ -		{MIIM_STATUS, miim_read, &mii_parse_sr}, -		/* Read the status */ -		{MIIM_RTL8211B_PHY_STATUS, miim_read, &mii_parse_RTL8211B_sr}, -		{miim_end,} -	}, -	(struct phy_cmd[]) {	/* shutdown */ -		{miim_end,} -	}, -}; +	if (priv->flags & TSEC_GIGABIT) +		supported |= SUPPORTED_1000baseT_Full; -struct phy_info phy_info_AR8021 =  { -        0x4dd04, -        "AR8021", -        4, -        (struct phy_cmd[]) { /* config */ -                {MII_BMCR, BMCR_RESET, NULL}, -                {MII_BMCR, BMCR_ANENABLE|BMCR_ANRESTART, NULL}, -                {0x1d, 0x05, NULL}, -                {0x1e, 0x3D47, NULL}, -                {miim_end,} -        }, -        (struct phy_cmd[]) { /* startup */ -                {MII_BMSR, miim_read, NULL}, -                {MII_BMSR, miim_read, &mii_parse_sr}, -                {MII_BMSR, miim_read, &mii_parse_link}, -                {miim_end,} -        }, -        (struct phy_cmd[]) { /* shutdown */ -                {miim_end,} -        } -}; +	/* Assign a Physical address to the TBI */ +	out_be32(®s->tbipa, CONFIG_SYS_TBIPA_VALUE); -static struct phy_info *phy_info[] = { -	&phy_info_cis8204, -	&phy_info_cis8201, -	&phy_info_BCM5461S, -	&phy_info_BCM5464S, -	&phy_info_BCM5482S, -	&phy_info_M88E1011S, -	&phy_info_M88E1111S, -	&phy_info_M88E1118, -	&phy_info_M88E1121R, -	&phy_info_M88E1145, -	&phy_info_M88E1149S, -	&phy_info_dm9161, -	&phy_info_ksz804, -	&phy_info_lxt971, -	&phy_info_VSC8211, -	&phy_info_VSC8244, -	&phy_info_VSC8601, -	&phy_info_VSC8641, -	&phy_info_VSC8221, -	&phy_info_dp83865, -	&phy_info_rtl8211b, -	&phy_info_AR8021, -	&phy_info_generic,	/* must be last; has ID 0 and 32 bit mask */ -	NULL -}; +	priv->interface = tsec_get_interface(priv); -/* Grab the identifier of the device's PHY, and search through - * all of the known PHYs to see if one matches.	 If so, return - * it, if not, return NULL - */ -static struct phy_info *get_phy_info(struct eth_device *dev) -{ -	struct tsec_private *priv = (struct tsec_private *)dev->priv; -	uint phy_reg, phy_ID; -	int i; -	struct phy_info *theInfo = NULL; +	if (priv->interface == PHY_INTERFACE_MODE_SGMII) +		tsec_configure_serdes(priv); -	/* Grab the bits from PHYIR1, and put them in the upper half */ -	phy_reg = read_phy_reg(priv, MIIM_PHYIR1); -	phy_ID = (phy_reg & 0xffff) << 16; +	phydev = phy_connect(priv->bus, priv->phyaddr, dev, priv->interface); -	/* Grab the bits from PHYIR2, and put them in the lower half */ -	phy_reg = read_phy_reg(priv, MIIM_PHYIR2); -	phy_ID |= (phy_reg & 0xffff); +	phydev->supported &= supported; +	phydev->advertising = phydev->supported; -	/* loop through all the known PHY types, and find one that */ -	/* matches the ID we read from the PHY. */ -	for (i = 0; phy_info[i]; i++) { -		if (phy_info[i]->id == (phy_ID >> phy_info[i]->shift)) { -			theInfo = phy_info[i]; -			break; -		} -	} +	priv->phydev = phydev; -	if (theInfo == &phy_info_generic) { -		printf("%s: No support for PHY id %x; assuming generic\n", -			dev->name, phy_ID); -	} else { -		debug("%s: PHY is %s (%x)\n", dev->name, theInfo->name, phy_ID); -	} +	phy_config(phydev); -	return theInfo; +	return 1;  } -/* Execute the given series of commands on the given device's - * PHY, running functions as necessary +/* Initialize device structure. Returns success if PHY + * initialization succeeded (i.e. if it recognizes the PHY)   */ -static void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd) +static int tsec_initialize(bd_t *bis, struct tsec_info_struct *tsec_info)  { +	struct eth_device *dev;  	int i; -	uint result; -	volatile tsec_mdio_t *phyregs = priv->phyregs; - -	phyregs->miimcfg = MIIMCFG_RESET; +	struct tsec_private *priv; -	phyregs->miimcfg = MIIMCFG_INIT_VALUE; +	dev = (struct eth_device *)malloc(sizeof *dev); -	while (phyregs->miimind & MIIMIND_BUSY) ; +	if (NULL == dev) +		return 0; -	for (i = 0; cmd->mii_reg != miim_end; i++) { -		if (cmd->mii_data == miim_read) { -			result = read_phy_reg(priv, cmd->mii_reg); +	memset(dev, 0, sizeof *dev); -			if (cmd->funct != NULL) -				(*(cmd->funct)) (result, priv); +	priv = (struct tsec_private *)malloc(sizeof(*priv)); -		} else { -			if (cmd->funct != NULL) -				result = (*(cmd->funct)) (cmd->mii_reg, priv); -			else -				result = cmd->mii_data; +	if (NULL == priv) +		return 0; -			write_phy_reg(priv, cmd->mii_reg, result); +	privlist[num_tsecs++] = priv; +	priv->regs = tsec_info->regs; +	priv->phyregs_sgmii = tsec_info->miiregs_sgmii; -		} -		cmd++; -	} -} +	priv->phyaddr = tsec_info->phyaddr; +	priv->flags = tsec_info->flags; -#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \ -	&& !defined(BITBANGMII) +	sprintf(dev->name, tsec_info->devname); +	priv->interface = tsec_info->interface; +	priv->bus = miiphy_get_dev_by_name(tsec_info->mii_devname); +	dev->iobase = 0; +	dev->priv = priv; +	dev->init = tsec_init; +	dev->halt = tsec_halt; +	dev->send = tsec_send; +	dev->recv = tsec_recv; +#ifdef CONFIG_MCAST_TFTP +	dev->mcast = tsec_mcast_addr; +#endif -/* - * Read a MII PHY register. - * - * Returns: - *  0 on success - */ -static int tsec_miiphy_read(const char *devname, unsigned char addr, -			    unsigned char reg, unsigned short *value) -{ -	unsigned short ret; -	struct tsec_private *priv = privlist[0]; +	/* Tell u-boot to get the addr from the env */ +	for (i = 0; i < 6; i++) +		dev->enetaddr[i] = 0; -	if (NULL == priv) { -		printf("Can't read PHY at address %d\n", addr); -		return -1; -	} +	eth_register(dev); -	ret = (unsigned short)tsec_local_mdio_read(priv->phyregs, addr, reg); -	*value = ret; +	/* Reset the MAC */ +	setbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET); +	udelay(2);  /* Soft Reset must be asserted for 3 TX clocks */ +	clrbits_be32(&priv->regs->maccfg1, MACCFG1_SOFT_RESET); -	return 0; +	/* Try to initialize PHY here, and return */ +	return init_phy(dev);  }  /* - * Write a MII PHY register. + * Initialize all the TSEC devices   * - * Returns: - *  0 on success + * Returns the number of TSEC devices that were initialized   */ -static int tsec_miiphy_write(const char *devname, unsigned char addr, -			     unsigned char reg, unsigned short value) +int tsec_eth_init(bd_t *bis, struct tsec_info_struct *tsecs, int num)  { -	struct tsec_private *priv = privlist[0]; +	int i; +	int ret, count = 0; -	if (NULL == priv) { -		printf("Can't write PHY at address %d\n", addr); -		return -1; +	for (i = 0; i < num; i++) { +		ret = tsec_initialize(bis, &tsecs[i]); +		if (ret > 0) +			count += ret;  	} -	tsec_local_mdio_write(priv->phyregs, addr, reg, value); - -	return 0; +	return count;  } -#endif - -#ifdef CONFIG_MCAST_TFTP - -/* CREDITS: linux gianfar driver, slightly adjusted... thanx. */ - -/* Set the appropriate hash bit for the given addr */ - -/* The algorithm works like so: - * 1) Take the Destination Address (ie the multicast address), and - * do a CRC on it (little endian), and reverse the bits of the - * result. - * 2) Use the 8 most significant bits as a hash into a 256-entry - * table.  The table is controlled through 8 32-bit registers: - * gaddr0-7.  gaddr0's MSB is entry 0, and gaddr7's LSB is - * gaddr7.  This means that the 3 most significant bits in the - * hash index which gaddr register to use, and the 5 other bits - * indicate which bit (assuming an IBM numbering scheme, which - * for PowerPC (tm) is usually the case) in the tregister holds - * the entry. */ -static int -tsec_mcast_addr (struct eth_device *dev, u8 mcast_mac, u8 set) +int tsec_standard_init(bd_t *bis)  { -	struct tsec_private *priv = privlist[1]; -	volatile tsec_t *regs = priv->regs; -	volatile u32  *reg_array, value; -	u8 result, whichbit, whichreg; +	struct fsl_pq_mdio_info info; -	result = (u8)((ether_crc(MAC_ADDR_LEN,mcast_mac) >> 24) & 0xff); -	whichbit = result & 0x1f;	/* the 5 LSB = which bit to set */ -	whichreg = result >> 5;		/* the 3 MSB = which reg to set it in */ -	value = (1 << (31-whichbit)); +	info.regs = (struct tsec_mii_mng *)CONFIG_SYS_MDIO_BASE_ADDR; +	info.name = DEFAULT_MII_NAME; -	reg_array = &(regs->hash.gaddr0); +	fsl_pq_mdio_init(bis, &info); -	if (set) { -		reg_array[whichreg] |= value; -	} else { -		reg_array[whichreg] &= ~value; -	} -	return 0; +	return tsec_eth_init(bis, tsec_info, ARRAY_SIZE(tsec_info));  } -#endif /* Multicast TFTP ? */ + diff --git a/drivers/net/uli526x.c b/drivers/net/uli526x.c index a4624e173..5933bddce 100644 --- a/drivers/net/uli526x.c +++ b/drivers/net/uli526x.c @@ -175,9 +175,9 @@ static u16 read_srom_word(long, int);  static void uli526x_descriptor_init(struct uli526x_board_info *, unsigned long);  static void allocate_rx_buffer(struct uli526x_board_info *);  static void update_cr6(u32, unsigned long); -static u16 phy_read(unsigned long, u8, u8, u32); +static u16 uli_phy_read(unsigned long, u8, u8, u32);  static u16 phy_readby_cr10(unsigned long, u8, u8); -static void phy_write(unsigned long, u8, u8, u16, u32); +static void uli_phy_write(unsigned long, u8, u8, u16, u32);  static void phy_writeby_cr10(unsigned long, u8, u8, u16);  static void phy_write_1bit(unsigned long, u32, u32);  static u16 phy_read_1bit(unsigned long, u32); @@ -349,7 +349,7 @@ static void uli526x_disable(struct eth_device *dev)  		/* Reset & stop ULI526X board */  		outl(ULI526X_RESET, db->ioaddr + DCR0);  		udelay(5); -		phy_write(db->ioaddr, db->phy_addr, 0, 0x8000, db->chip_id); +		uli_phy_write(db->ioaddr, db->phy_addr, 0, 0x8000, db->chip_id);  		/* reset the board */  		db->cr6_data &= ~(CR6_RXSC | CR6_TXSC);	/* Disable Tx/Rx */ @@ -385,7 +385,7 @@ static void uli526x_init(struct eth_device *dev)  	db->tx_packet_cnt = 0;  	for (phy_tmp = 0; phy_tmp < 32; phy_tmp++) {  		/* peer add */ -		phy_value = phy_read(db->ioaddr, phy_tmp, 3, db->chip_id); +		phy_value = uli_phy_read(db->ioaddr, phy_tmp, 3, db->chip_id);  		if (phy_value != 0xffff && phy_value != 0) {  			db->phy_addr = phy_tmp;  			break; @@ -404,10 +404,10 @@ static void uli526x_init(struct eth_device *dev)  	if (!(inl(db->ioaddr + DCR12) & 0x8)) {  		/* Phyxcer capability setting */ -		phy_reg_reset = phy_read(db->ioaddr, +		phy_reg_reset = uli_phy_read(db->ioaddr,  			db->phy_addr, 0, db->chip_id);  		phy_reg_reset = (phy_reg_reset | 0x8000); -		phy_write(db->ioaddr, db->phy_addr, 0, +		uli_phy_write(db->ioaddr, db->phy_addr, 0,  			phy_reg_reset, db->chip_id);  		udelay(500); @@ -781,7 +781,8 @@ static void uli526x_set_phyxcer(struct uli526x_board_info *db)  	u16 phy_reg;  	/* Phyxcer capability setting */ -	phy_reg = phy_read(db->ioaddr, db->phy_addr, 4, db->chip_id) & ~0x01e0; +	phy_reg = uli_phy_read(db->ioaddr, +			db->phy_addr, 4, db->chip_id) & ~0x01e0;  	if (db->media_mode & ULI526X_AUTO) {  		/* AUTO Mode */ @@ -802,10 +803,10 @@ static void uli526x_set_phyxcer(struct uli526x_board_info *db)  		phy_reg |= db->PHY_reg4;  		db->media_mode |= ULI526X_AUTO;  	} -	phy_write(db->ioaddr, db->phy_addr, 4, phy_reg, db->chip_id); +	uli_phy_write(db->ioaddr, db->phy_addr, 4, phy_reg, db->chip_id);  	/* Restart Auto-Negotiation */ -	phy_write(db->ioaddr, db->phy_addr, 0, 0x1200, db->chip_id); +	uli_phy_write(db->ioaddr, db->phy_addr, 0, 0x1200, db->chip_id);  	udelay(50);  } @@ -813,7 +814,7 @@ static void uli526x_set_phyxcer(struct uli526x_board_info *db)   *	Write a word to Phy register   */ -static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset, +static void uli_phy_write(unsigned long iobase, u8 phy_addr, u8 offset,  	u16 phy_data, u32 chip_id)  {  	u16 i; @@ -862,7 +863,8 @@ static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset,   *	Read a word data from phy register   */ -static u16 phy_read(unsigned long iobase, u8 phy_addr, u8 offset, u32 chip_id) +static u16 uli_phy_read(unsigned long iobase, u8 phy_addr, u8 offset, +			u32 chip_id)  {  	int i;  	u16 phy_data; diff --git a/drivers/qe/uec.c b/drivers/qe/uec.c index 811e3fc31..1ecb1379a 100644 --- a/drivers/qe/uec.c +++ b/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); diff --git a/drivers/qe/uec.h b/drivers/qe/uec.h index 94eb9a26d..e63bf3a65 100644 --- a/drivers/qe/uec.h +++ b/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; diff --git a/drivers/qe/uec_phy.c b/drivers/qe/uec_phy.c index 55c262294..e26218be8 100644 --- a/drivers/qe/uec_phy.c +++ b/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); diff --git a/include/config_phylib_all_drivers.h b/include/config_phylib_all_drivers.h new file mode 100644 index 000000000..903c7a775 --- /dev/null +++ b/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 */ diff --git a/include/configs/MPC8323ERDB.h b/include/configs/MPC8323ERDB.h index 1191eea10..e25d5acc1 100644 --- a/include/configs/MPC8323ERDB.h +++ b/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 diff --git a/include/configs/MPC832XEMDS.h b/include/configs/MPC832XEMDS.h index affa3a9cf..f136a8e16 100644 --- a/include/configs/MPC832XEMDS.h +++ b/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 diff --git a/include/configs/MPC8360EMDS.h b/include/configs/MPC8360EMDS.h index a9599405d..49d64a55e 100644 --- a/include/configs/MPC8360EMDS.h +++ b/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 diff --git a/include/configs/MPC8360ERDK.h b/include/configs/MPC8360ERDK.h index b0cdc02c1..a4f42cf22 100644 --- a/include/configs/MPC8360ERDK.h +++ b/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 diff --git a/include/configs/MPC8568MDS.h b/include/configs/MPC8568MDS.h index 3674e495c..6237b23b7 100644 --- a/include/configs/MPC8568MDS.h +++ b/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 */ diff --git a/include/configs/MPC8569MDS.h b/include/configs/MPC8569MDS.h index 5a7e99ee6..8835ef5c9 100644 --- a/include/configs/MPC8569MDS.h +++ b/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 */ diff --git a/include/configs/kmeter1.h b/include/configs/kmeter1.h index 8fcadfee5..b98e6a137 100644 --- a/include/configs/kmeter1.h +++ b/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 diff --git a/include/fsl_mdio.h b/include/fsl_mdio.h new file mode 100644 index 000000000..17ca79c90 --- /dev/null +++ b/include/fsl_mdio.h @@ -0,0 +1,62 @@ +/* + * Copyright 2009-2010 Freescale Semiconductor, Inc. + *	Jun-jie Zhang <b18070@freescale.com> + *	Mingkai Hu <Mingkai.hu@freescale.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#ifndef __FSL_PHY_H__ +#define __FSL_PHY_H__ + +#include <net.h> +#include <miiphy.h> +#include <asm/fsl_enet.h> + +/* PHY register offsets */ +#define PHY_EXT_PAGE_ACCESS	0x1f + +/* MII Management Configuration Register */ +#define MIIMCFG_RESET_MGMT          0x80000000 +#define MIIMCFG_MGMT_CLOCK_SELECT   0x00000007 +#define MIIMCFG_INIT_VALUE	    0x00000003 + +/* MII Management Command Register */ +#define MIIMCOM_READ_CYCLE	0x00000001 +#define MIIMCOM_SCAN_CYCLE	0x00000002 + +/* MII Management Address Register */ +#define MIIMADD_PHY_ADDR_SHIFT	8 + +/* MII Management Indicator Register */ +#define MIIMIND_BUSY		0x00000001 +#define MIIMIND_NOTVALID	0x00000004 + +void tsec_local_mdio_write(struct tsec_mii_mng *phyregs, int port_addr, +		int dev_addr, int reg, int value); +int tsec_local_mdio_read(struct tsec_mii_mng *phyregs, int port_addr, +		int dev_addr, int regnum); +int tsec_phy_read(struct mii_dev *bus, int addr, int dev_addr, int regnum); +int tsec_phy_write(struct mii_dev *bus, int addr, int dev_addr, int regnum, +		u16 value); + +struct fsl_pq_mdio_info { +	struct tsec_mii_mng *regs; +	char *name; +}; +int fsl_pq_mdio_init(bd_t *bis, struct fsl_pq_mdio_info *info); + +#endif /* __FSL_PHY_H__ */ + diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h new file mode 100644 index 000000000..fcb20fe10 --- /dev/null +++ b/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 */ diff --git a/include/linux/mdio.h b/include/linux/mdio.h new file mode 100644 index 000000000..022d77214 --- /dev/null +++ b/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__ */ diff --git a/include/miiphy.h b/include/miiphy.h index 42dc12715..7e70cf81e 100644 --- a/include/miiphy.h +++ b/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 diff --git a/include/phy.h b/include/phy.h new file mode 100644 index 000000000..d5817bf19 --- /dev/null +++ b/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 diff --git a/include/tsec.h b/include/tsec.h index d56ec2cd0..8ed30aca0 100644 --- a/include/tsec.h +++ b/include/tsec.h @@ -7,7 +7,7 @@   *  terms of the GNU Public License, Version 2, incorporated   *  herein by reference.   * - * Copyright 2004, 2007, 2009  Freescale Semiconductor, Inc. + * Copyright 2004, 2007, 2009, 2011  Freescale Semiconductor, Inc.   * (C) Copyright 2003, Motorola, Inc.   * maintained by Xianghua Xiao (x.xiao@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;  }; @@ -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 |