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

This commit is contained in:
Wolfgang Denk 2011-04-20 23:01:52 +02:00
commit aef293bc85
52 changed files with 5085 additions and 2505 deletions

View file

@ -27,8 +27,8 @@
#include <libfdt.h>
#include <fdt_support.h>
#include <asm/mp.h>
#include <asm/fsl_enet.h>
#include <asm/fsl_serdes.h>
#include <phy.h>
#if defined(CONFIG_MP) && (defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx))
static int ft_del_cpuhandle(void *blob, int cpuhandle)
@ -218,27 +218,10 @@ void fdt_fixup_crypto_node(void *blob, int sec_rev)
}
#endif
int fdt_fixup_phy_connection(void *blob, int offset, enum fsl_phy_enet_if phyc)
int fdt_fixup_phy_connection(void *blob, int offset, phy_interface_t phyc)
{
static const char *fsl_phy_enet_if_str[] = {
[MII] = "mii",
[RMII] = "rmii",
[GMII] = "gmii",
[RGMII] = "rgmii",
[RGMII_ID] = "rgmii-id",
[RGMII_RXID] = "rgmii-rxid",
[SGMII] = "sgmii",
[TBI] = "tbi",
[RTBI] = "rtbi",
[XAUI] = "xgmii",
[FSL_ETH_IF_NONE] = "",
};
if (phyc > ARRAY_SIZE(fsl_phy_enet_if_str))
return fdt_setprop_string(blob, offset, "phy-connection-type", "");
return fdt_setprop_string(blob, offset, "phy-connection-type",
fsl_phy_enet_if_str[phyc]);
phy_string_for_interface(phyc));
}
#ifdef CONFIG_SYS_SRIO

View file

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

View file

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

View file

@ -16,6 +16,7 @@
#include <mpc83xx.h>
#include <i2c.h>
#include <miiphy.h>
#include <phy.h>
#if defined(CONFIG_PCI)
#include <pci.h>
#endif
@ -160,8 +161,9 @@ int board_eth_init(bd_t *bd)
int i;
for (i = 0; i < ARRAY_SIZE(uec_info); i++)
uec_info[i].enet_interface_type = RGMII_RXID;
uec_info[i].speed = 1000;
uec_info[i].enet_interface_type =
PHY_INTERFACE_MODE_RGMII_RXID;
uec_info[i].speed = SPEED_1000;
}
return uec_eth_init(bd, uec_info, ARRAY_SIZE(uec_info));
}
@ -398,7 +400,7 @@ void ft_board_setup(void *blob, bd_t *bd)
"phy-connection-type", 0);
if (prop && (strcmp(prop, "rgmii-id") == 0))
fdt_fixup_phy_connection(blob, path,
RGMII_RXID);
PHY_INTERFACE_MODE_RGMII_RXID);
}
#endif
#if defined(CONFIG_HAS_ETH1)
@ -410,7 +412,7 @@ void ft_board_setup(void *blob, bd_t *bd)
"phy-connection-type", 0);
if (prop && (strcmp(prop, "rgmii-id") == 0))
fdt_fixup_phy_connection(blob, path,
RGMII_RXID);
PHY_INTERFACE_MODE_RGMII_RXID);
}
#endif
}

View file

@ -21,6 +21,8 @@
#include <libfdt.h>
#include <fdt_support.h>
#include <fsl_esdhc.h>
#include <fsl_mdio.h>
#include <phy.h>
#include "pci.h"
#include "../common/pq-mds-pib.h"
@ -86,6 +88,7 @@ int board_mmc_init(bd_t *bd)
#if defined(CONFIG_TSEC1) || defined(CONFIG_TSEC2)
int board_eth_init(bd_t *bd)
{
struct fsl_pq_mdio_info mdio_info;
struct tsec_info_struct tsec_info[2];
struct immap __iomem *im = (struct immap __iomem *)CONFIG_SYS_IMMR;
u32 rcwh = in_be32(&im->reset.rcwh);
@ -131,6 +134,11 @@ int board_eth_init(bd_t *bd)
}
num++;
#endif
mdio_info.regs = (struct tsec_mii_mng *)CONFIG_SYS_MDIO_BASE_ADDR;
mdio_info.name = DEFAULT_MII_NAME;
fsl_pq_mdio_init(bd, &mdio_info);
return tsec_eth_init(bd, tsec_info, num);
}
@ -148,7 +156,7 @@ static void __ft_tsec_fixup(void *blob, bd_t *bd, const char *alias,
return;
}
err = fdt_fixup_phy_connection(blob, off, SGMII);
err = fdt_fixup_phy_connection(blob, off, PHY_INTERFACE_MODE_SGMII);
if (err) {
printf("WARNING: could not set phy-connection-type for %s: "

View file

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

View file

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

View file

@ -39,6 +39,7 @@
#include <libfdt.h>
#include <fdt_support.h>
#include <fsl_esdhc.h>
#include <phy.h>
#include "bcsr.h"
#if defined(CONFIG_PQ_MDS_PIB)
@ -550,7 +551,8 @@ void ft_board_setup(void *blob, bd_t *bd)
break;
}
err = fdt_fixup_phy_connection(blob, nodeoff, RMII);
err = fdt_fixup_phy_connection(blob, nodeoff,
PHY_INTERFACE_MODE_RMII);
if (err < 0) {
printf("WARNING: could not set phy-connection-type "

View file

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

View file

@ -22,6 +22,7 @@
#include <asm/io.h>
#include <libfdt.h>
#include <fdt_support.h>
#include <fsl_mdio.h>
#include <tsec.h>
#include <asm/fsl_law.h>
#include <netdev.h>
@ -279,6 +280,7 @@ int board_early_init_r(void)
*/
int board_eth_init(bd_t *bis)
{
struct fsl_pq_mdio_info mdio_info;
struct tsec_info_struct tsec_info[2];
unsigned int num = 0;
@ -291,6 +293,10 @@ int board_eth_init(bd_t *bis)
num++;
#endif
mdio_info.regs = (struct tsec_mii_mng *)CONFIG_SYS_MDIO_BASE_ADDR;
mdio_info.name = DEFAULT_MII_NAME;
fsl_pq_mdio_init(bis, &mdio_info);
return tsec_eth_init(bis, tsec_info, num) + pci_eth_init(bis);
}

View file

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

View file

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

View file

@ -117,7 +117,11 @@ COBJS-$(CONFIG_CMD_MFSL) += cmd_mfsl.o
COBJS-$(CONFIG_CMD_MG_DISK) += cmd_mgdisk.o
COBJS-$(CONFIG_MII) += miiphyutil.o
COBJS-$(CONFIG_CMD_MII) += miiphyutil.o
COBJS-$(CONFIG_PHYLIB) += miiphyutil.o
COBJS-$(CONFIG_CMD_MII) += cmd_mii.o
ifdef CONFIG_PHYLIB
COBJS-$(CONFIG_CMD_MII) += cmd_mdio.o
endif
COBJS-$(CONFIG_CMD_MISC) += cmd_misc.o
COBJS-$(CONFIG_CMD_MMC) += cmd_mmc.o
COBJS-$(CONFIG_CMD_MMC_SPI) += cmd_mmc_spi.o

286
common/cmd_mdio.c Normal file
View file

@ -0,0 +1,286 @@
/*
* (C) Copyright 2011 Freescale Semiconductor, Inc
* Andy Fleming
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/*
* MDIO Commands
*/
#include <common.h>
#include <command.h>
#include <miiphy.h>
#include <phy.h>
static char last_op[2];
static uint last_data;
static uint last_addr_lo;
static uint last_addr_hi;
static uint last_devad_lo;
static uint last_devad_hi;
static uint last_reg_lo;
static uint last_reg_hi;
static int extract_range(char *input, int *plo, int *phi)
{
char *end;
*plo = simple_strtol(input, &end, 0);
if (end == input)
return -1;
if ((*end == '-') && *(++end))
*phi = simple_strtol(end, NULL, 0);
else if (*end == '\0')
*phi = *plo;
else
return -1;
return 0;
}
int mdio_write_ranges(struct mii_dev *bus, int addrlo,
int addrhi, int devadlo, int devadhi,
int reglo, int reghi, unsigned short data)
{
int addr, devad, reg;
int err = 0;
for (addr = addrlo; addr <= addrhi; addr++) {
for (devad = devadlo; devad <= devadhi; devad++) {
for (reg = reglo; reg <= reghi; reg++) {
err = bus->write(bus, addr, devad, reg, data);
if (err)
goto err_out;
}
}
}
err_out:
return err;
}
int mdio_read_ranges(struct mii_dev *bus, int addrlo,
int addrhi, int devadlo, int devadhi,
int reglo, int reghi)
{
int addr, devad, reg;
printf("Reading from bus %s\n", bus->name);
for (addr = addrlo; addr <= addrhi; addr++) {
printf("PHY at address %d:\n", addr);
for (devad = devadlo; devad <= devadhi; devad++) {
for (reg = reglo; reg <= reghi; reg++) {
u16 val;
val = bus->read(bus, addr, devad, reg);
if (val < 0) {
printf("Error\n");
return val;
}
if (devad >= 0)
printf("%d.", devad);
printf("%d - 0x%x\n", reg, val & 0xffff);
}
}
}
return 0;
}
/* The register will be in the form [a[-b].]x[-y] */
int extract_reg_range(char *input, int *devadlo, int *devadhi,
int *reglo, int *reghi)
{
char *regstr;
/* use strrchr to find the last string after a '.' */
regstr = strrchr(input, '.');
/* If it exists, extract the devad(s) */
if (regstr) {
char devadstr[32];
strncpy(devadstr, input, regstr - input);
devadstr[regstr - input] = '\0';
if (extract_range(devadstr, devadlo, devadhi))
return -1;
regstr++;
} else {
/* Otherwise, we have no devad, and we just got regs */
*devadlo = *devadhi = MDIO_DEVAD_NONE;
regstr = input;
}
return extract_range(regstr, reglo, reghi);
}
int extract_phy_range(char *const argv[], int argc, struct mii_dev **bus,
int *addrlo, int *addrhi)
{
struct phy_device *phydev;
if ((argc < 1) || (argc > 2))
return -1;
/* If there are two arguments, it's busname addr */
if (argc == 2) {
*bus = miiphy_get_dev_by_name(argv[0]);
if (!*bus)
return -1;
return extract_range(argv[1], addrlo, addrhi);
}
/* It must be one argument, here */
/*
* This argument can be one of two things:
* 1) Ethernet device name
* 2) Just an address (use the previously-used bus)
*
* We check all buses for a PHY which is connected to an ethernet
* device by the given name. If none are found, we call
* extract_range() on the string, and see if it's an address range.
*/
phydev = mdio_phydev_for_ethname(argv[0]);
if (phydev) {
*addrlo = *addrhi = phydev->addr;
*bus = phydev->bus;
return 0;
}
/* It's an address or nothing useful */
return extract_range(argv[0], addrlo, addrhi);
}
/* ---------------------------------------------------------------- */
static int do_mdio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
char op[2];
int addrlo, addrhi, reglo, reghi, devadlo, devadhi;
unsigned short data;
int pos = argc - 1;
struct mii_dev *bus;
if (argc < 2)
return cmd_usage(cmdtp);
/*
* We use the last specified parameters, unless new ones are
* entered.
*/
op[0] = argv[1][0];
addrlo = last_addr_lo;
addrhi = last_addr_hi;
devadlo = last_devad_lo;
devadhi = last_devad_hi;
reglo = last_reg_lo;
reghi = last_reg_hi;
data = last_data;
bus = mdio_get_current_dev();
if (flag & CMD_FLAG_REPEAT)
op[0] = last_op[0];
switch (op[0]) {
case 'w':
if (pos > 1)
data = simple_strtoul(argv[pos--], NULL, 16);
case 'r':
if (pos > 1)
if (extract_reg_range(argv[pos--], &devadlo, &devadhi,
&reglo, &reghi))
return -1;
default:
if (pos > 1)
if (extract_phy_range(&(argv[2]), pos - 1, &bus,
&addrlo, &addrhi))
return -1;
break;
}
if (op[0] == 'l') {
mdio_list_devices();
return 0;
}
/* Save the chosen bus */
miiphy_set_current_dev(bus->name);
switch (op[0]) {
case 'w':
mdio_write_ranges(bus, addrlo, addrhi, devadlo, devadhi,
reglo, reghi, data);
break;
case 'r':
mdio_read_ranges(bus, addrlo, addrhi, devadlo, devadhi,
reglo, reghi);
break;
}
/*
* Save the parameters for repeats.
*/
last_op[0] = op[0];
last_addr_lo = addrlo;
last_addr_hi = addrhi;
last_devad_lo = devadlo;
last_devad_hi = devadhi;
last_reg_lo = reglo;
last_reg_hi = reghi;
last_data = data;
return 0;
}
/***************************************************/
U_BOOT_CMD(
mdio, 6, 1, do_mdio,
"MDIO utility commands",
"list - List MDIO buses\n"
"mdio read <phydev> [<devad>.]<reg> - "
"read PHY's register at <devad>.<reg>\n"
"mdio write <phydev> [<devad>.]<reg> <data> - "
"write PHY's register at <devad>.<reg>\n"
"<phydev> may be:\n"
" <busname> <addr>\n"
" <addr>\n"
" <eth name>\n"
"<addr> <devad>, and <reg> may be ranges, e.g. 1-5.4-0x1f.\n"
);

View file

@ -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;
}
if (new_dev == NULL) {
printf ("miiphy_register: cannot allocate memory for '%s'\n",
new_dev = mdio_alloc();
ldev = malloc(sizeof(*ldev));
if (new_dev == NULL || ldev == NULL) {
printf("miiphy_register: cannot allocate memory for '%s'\n",
name);
return;
}
memset (new_dev, 0, sizeof (struct mii_dev) + name_len);
/* initalize mii_dev struct fields */
INIT_LIST_HEAD (&new_dev->link);
new_dev->read = read;
new_dev->write = write;
new_dev->name = new_name = (char *)(new_dev + 1);
strncpy (new_name, name, name_len);
new_name[name_len] = '\0';
new_dev->read = legacy_miiphy_read;
new_dev->write = legacy_miiphy_write;
sprintf(new_dev->name, name);
ldev->read = read;
ldev->write = write;
new_dev->priv = ldev;
debug ("miiphy_register: added '%s', read=0x%08lx, write=0x%08lx\n",
new_dev->name, new_dev->read, new_dev->write);
debug("miiphy_register: added '%s', read=0x%08lx, write=0x%08lx\n",
new_dev->name, ldev->read, ldev->write);
/* add it to the list */
list_add_tail (&new_dev->link, &mii_devs);
list_add_tail(&new_dev->link, &mii_devs);
if (!current_mii)
current_mii = new_dev;
}
struct mii_dev *mdio_alloc(void)
{
struct mii_dev *bus;
bus = malloc(sizeof(*bus));
if (!bus)
return bus;
memset(bus, 0, sizeof(*bus));
/* initalize mii_dev struct fields */
INIT_LIST_HEAD(&bus->link);
return bus;
}
int mdio_register(struct mii_dev *bus)
{
if (!bus || !bus->name || !bus->read || !bus->write)
return -1;
/* check if we have unique name */
if (miiphy_get_dev_by_name(bus->name)) {
printf("mdio_register: non unique device name '%s'\n",
bus->name);
return -1;
}
/* add it to the list */
list_add_tail(&bus->link, &mii_devs);
if (!current_mii)
current_mii = bus;
return 0;
}
void mdio_list_devices(void)
{
struct list_head *entry;
list_for_each(entry, &mii_devs) {
int i;
struct mii_dev *bus = list_entry(entry, struct mii_dev, link);
printf("%s:\n", bus->name);
for (i = 0; i < PHY_MAX_ADDR; i++) {
struct phy_device *phydev = bus->phymap[i];
if (phydev) {
printf("%d - %s", i, phydev->drv->name);
if (phydev->dev)
printf(" <--> %s\n", phydev->dev->name);
else
printf("\n");
}
}
}
}
int miiphy_set_current_dev(const char *devname)
{
struct mii_dev *dev;
dev = miiphy_get_dev_by_name(devname, 0);
dev = miiphy_get_dev_by_name(devname);
if (dev) {
current_mii = dev;
return 0;
}
printf("No such device: %s\n", devname);
return 1;
}
struct mii_dev *mdio_get_current_dev(void)
{
return current_mii;
}
struct phy_device *mdio_phydev_for_ethname(const char *ethname)
{
struct list_head *entry;
struct mii_dev *bus;
list_for_each(entry, &mii_devs) {
int i;
bus = list_entry(entry, struct mii_dev, link);
for (i = 0; i < PHY_MAX_ADDR; i++) {
if (!bus->phymap[i] || !bus->phymap[i]->dev)
continue;
if (strcmp(bus->phymap[i]->dev->name, ethname) == 0)
return bus->phymap[i];
}
}
printf("%s is not a known ethernet\n", ethname);
return NULL;
}
const char *miiphy_get_current_dev(void)
{
if (current_mii)
@ -187,13 +293,15 @@ static struct mii_dev *miiphy_get_active_dev(const char *devname)
int miiphy_read(const char *devname, unsigned char addr, unsigned char reg,
unsigned short *value)
{
struct mii_dev *dev;
struct mii_dev *bus;
dev = miiphy_get_active_dev(devname);
if (dev)
return dev->read(devname, addr, reg, value);
bus = miiphy_get_active_dev(devname);
if (bus)
*value = bus->read(bus, addr, MDIO_DEVAD_NONE, reg);
else
return 1;
return 1;
return (*value < 0) ? 1 : 0;
}
/*****************************************************************************
@ -207,11 +315,11 @@ int miiphy_read(const char *devname, unsigned char addr, unsigned char reg,
int miiphy_write(const char *devname, unsigned char addr, unsigned char reg,
unsigned short value)
{
struct mii_dev *dev;
struct mii_dev *bus;
dev = miiphy_get_active_dev(devname);
if (dev)
return dev->write(devname, addr, reg, value);
bus = miiphy_get_active_dev(devname);
if (bus)
return bus->write(bus, addr, MDIO_DEVAD_NONE, reg, value);
return 1;
}
@ -220,20 +328,20 @@ int miiphy_write(const char *devname, unsigned char addr, unsigned char reg,
*
* Print out list of registered MII capable devices.
*/
void miiphy_listdev (void)
void miiphy_listdev(void)
{
struct list_head *entry;
struct mii_dev *dev;
puts ("MII devices: ");
list_for_each (entry, &mii_devs) {
dev = list_entry (entry, struct mii_dev, link);
printf ("'%s' ", dev->name);
puts("MII devices: ");
list_for_each(entry, &mii_devs) {
dev = list_entry(entry, struct mii_dev, link);
printf("'%s' ", dev->name);
}
puts ("\n");
puts("\n");
if (current_mii)
printf ("Current device: '%s'\n", current_mii->name);
printf("Current device: '%s'\n", current_mii->name);
}
/*****************************************************************************
@ -253,32 +361,33 @@ int miiphy_info(const char *devname, unsigned char addr, unsigned int *oui,
unsigned int reg = 0;
unsigned short tmp;
if (miiphy_read (devname, addr, MII_PHYSID2, &tmp) != 0) {
debug ("PHY ID register 2 read failed\n");
return (-1);
if (miiphy_read(devname, addr, MII_PHYSID2, &tmp) != 0) {
debug("PHY ID register 2 read failed\n");
return -1;
}
reg = tmp;
debug ("MII_PHYSID2 @ 0x%x = 0x%04x\n", addr, reg);
debug("MII_PHYSID2 @ 0x%x = 0x%04x\n", addr, reg);
if (reg == 0xFFFF) {
/* No physical device present at this address */
return (-1);
return -1;
}
if (miiphy_read (devname, addr, MII_PHYSID1, &tmp) != 0) {
debug ("PHY ID register 1 read failed\n");
return (-1);
if (miiphy_read(devname, addr, MII_PHYSID1, &tmp) != 0) {
debug("PHY ID register 1 read failed\n");
return -1;
}
reg |= tmp << 16;
debug ("PHY_PHYIDR[1,2] @ 0x%x = 0x%08x\n", addr, reg);
debug("PHY_PHYIDR[1,2] @ 0x%x = 0x%08x\n", addr, reg);
*oui = (reg >> 10);
*model = (unsigned char)((reg >> 4) & 0x0000003F);
*rev = (unsigned char)(reg & 0x0000000F);
return (0);
return 0;
}
#ifndef CONFIG_PHYLIB
/*****************************************************************************
*
* Reset the PHY.
@ -290,16 +399,16 @@ int miiphy_reset(const char *devname, unsigned char addr)
unsigned short reg;
int timeout = 500;
if (miiphy_read (devname, addr, MII_BMCR, &reg) != 0) {
debug ("PHY status read failed\n");
return (-1);
if (miiphy_read(devname, addr, MII_BMCR, &reg) != 0) {
debug("PHY status read failed\n");
return -1;
}
if (miiphy_write (devname, addr, MII_BMCR, reg | BMCR_RESET) != 0) {
debug ("PHY reset failed\n");
return (-1);
if (miiphy_write(devname, addr, MII_BMCR, reg | BMCR_RESET) != 0) {
debug("PHY reset failed\n");
return -1;
}
#ifdef CONFIG_PHY_RESET_DELAY
udelay (CONFIG_PHY_RESET_DELAY); /* Intel LXT971A needs this */
udelay(CONFIG_PHY_RESET_DELAY); /* Intel LXT971A needs this */
#endif
/*
* Poll the control register for the reset bit to go to 0 (it is
@ -315,13 +424,14 @@ int miiphy_reset(const char *devname, unsigned char addr)
udelay(1000);
}
if ((reg & 0x8000) == 0) {
return (0);
return 0;
} else {
puts ("PHY reset timed out\n");
return (-1);
puts("PHY reset timed out\n");
return -1;
}
return (0);
return 0;
}
#endif /* !PHYLIB */
/*****************************************************************************
*
@ -338,33 +448,32 @@ int miiphy_speed(const char *devname, unsigned char addr)
* Check for 1000BASE-X. If it is supported, then assume that the speed
* is 1000.
*/
if (miiphy_is_1000base_x (devname, addr)) {
if (miiphy_is_1000base_x(devname, addr))
return _1000BASET;
}
/*
* No 1000BASE-X, so assume 1000BASE-T/100BASE-TX/10BASE-T register set.
*/
/* Check for 1000BASE-T. */
if (miiphy_read (devname, addr, MII_STAT1000, &btsr)) {
printf ("PHY 1000BT status");
if (miiphy_read(devname, addr, MII_STAT1000, &btsr)) {
printf("PHY 1000BT status");
goto miiphy_read_failed;
}
if (btsr != 0xFFFF &&
(btsr & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD))) {
(btsr & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)))
return _1000BASET;
}
#endif /* CONFIG_PHY_GIGE */
/* Check Basic Management Control Register first. */
if (miiphy_read (devname, addr, MII_BMCR, &bmcr)) {
printf ("PHY speed");
if (miiphy_read(devname, addr, MII_BMCR, &bmcr)) {
printf("PHY speed");
goto miiphy_read_failed;
}
/* Check if auto-negotiation is on. */
if (bmcr & BMCR_ANENABLE) {
/* Get auto-negotiation results. */
if (miiphy_read (devname, addr, MII_LPA, &anlpar)) {
printf ("PHY AN speed");
if (miiphy_read(devname, addr, MII_LPA, &anlpar)) {
printf("PHY AN speed");
goto miiphy_read_failed;
}
return (anlpar & LPA_100) ? _100BASET : _10BASET;
@ -373,7 +482,7 @@ int miiphy_speed(const char *devname, unsigned char addr)
return (bmcr & BMCR_SPEED100) ? _100BASET : _10BASET;
miiphy_read_failed:
printf (" read failed, assuming 10BASE-T\n");
printf(" read failed, assuming 10BASE-T\n");
return _10BASET;
}
@ -389,10 +498,10 @@ int miiphy_duplex(const char *devname, unsigned char addr)
u16 btsr;
/* Check for 1000BASE-X. */
if (miiphy_is_1000base_x (devname, addr)) {
if (miiphy_is_1000base_x(devname, addr)) {
/* 1000BASE-X */
if (miiphy_read (devname, addr, MII_LPA, &anlpar)) {
printf ("1000BASE-X PHY AN duplex");
if (miiphy_read(devname, addr, MII_LPA, &anlpar)) {
printf("1000BASE-X PHY AN duplex");
goto miiphy_read_failed;
}
}
@ -400,8 +509,8 @@ int miiphy_duplex(const char *devname, unsigned char addr)
* No 1000BASE-X, so assume 1000BASE-T/100BASE-TX/10BASE-T register set.
*/
/* Check for 1000BASE-T. */
if (miiphy_read (devname, addr, MII_STAT1000, &btsr)) {
printf ("PHY 1000BT status");
if (miiphy_read(devname, addr, MII_STAT1000, &btsr)) {
printf("PHY 1000BT status");
goto miiphy_read_failed;
}
if (btsr != 0xFFFF) {
@ -414,15 +523,15 @@ int miiphy_duplex(const char *devname, unsigned char addr)
#endif /* CONFIG_PHY_GIGE */
/* Check Basic Management Control Register first. */
if (miiphy_read (devname, addr, MII_BMCR, &bmcr)) {
puts ("PHY duplex");
if (miiphy_read(devname, addr, MII_BMCR, &bmcr)) {
puts("PHY duplex");
goto miiphy_read_failed;
}
/* Check if auto-negotiation is on. */
if (bmcr & BMCR_ANENABLE) {
/* Get auto-negotiation results. */
if (miiphy_read (devname, addr, MII_LPA, &anlpar)) {
puts ("PHY AN duplex");
if (miiphy_read(devname, addr, MII_LPA, &anlpar)) {
puts("PHY AN duplex");
goto miiphy_read_failed;
}
return (anlpar & (LPA_10FULL | LPA_100FULL)) ?
@ -432,7 +541,7 @@ int miiphy_duplex(const char *devname, unsigned char addr)
return (bmcr & BMCR_FULLDPLX) ? FULL : HALF;
miiphy_read_failed:
printf (" read failed, assuming half duplex\n");
printf(" read failed, assuming half duplex\n");
return HALF;
}
@ -446,8 +555,8 @@ int miiphy_is_1000base_x(const char *devname, unsigned char addr)
#if defined(CONFIG_PHY_GIGE)
u16 exsr;
if (miiphy_read (devname, addr, MII_ESTATUS, &exsr)) {
printf ("PHY extended status read failed, assuming no "
if (miiphy_read(devname, addr, MII_ESTATUS, &exsr)) {
printf("PHY extended status read failed, assuming no "
"1000BASE-X\n");
return 0;
}
@ -467,17 +576,17 @@ int miiphy_link(const char *devname, unsigned char addr)
unsigned short reg;
/* dummy read; needed to latch some phys */
(void)miiphy_read (devname, addr, MII_BMSR, &reg);
if (miiphy_read (devname, addr, MII_BMSR, &reg)) {
puts ("MII_BMSR read failed, assuming no link\n");
return (0);
(void)miiphy_read(devname, addr, MII_BMSR, &reg);
if (miiphy_read(devname, addr, MII_BMSR, &reg)) {
puts("MII_BMSR read failed, assuming no link\n");
return 0;
}
/* Determine if a link is active */
if ((reg & BMSR_LSTATUS) != 0) {
return (1);
return 1;
} else {
return (0);
return 0;
}
}
#endif

View file

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

View file

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

View file

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

120
drivers/net/fsl_mdio.c Normal file
View file

@ -0,0 +1,120 @@
/*
* Copyright 2009-2010 Freescale Semiconductor, Inc.
* Jun-jie Zhang <b18070@freescale.com>
* Mingkai Hu <Mingkai.hu@freescale.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <miiphy.h>
#include <phy.h>
#include <fsl_mdio.h>
#include <asm/io.h>
#include <asm/errno.h>
#include <asm/fsl_enet.h>
void tsec_local_mdio_write(struct tsec_mii_mng *phyregs, int port_addr,
int dev_addr, int regnum, int value)
{
int timeout = 1000000;
out_be32(&phyregs->miimadd, (port_addr << 8) | (regnum & 0x1f));
out_be32(&phyregs->miimcon, value);
asm("sync");
while ((in_be32(&phyregs->miimind) & MIIMIND_BUSY) && timeout--)
;
}
int tsec_local_mdio_read(struct tsec_mii_mng *phyregs, int port_addr,
int dev_addr, int regnum)
{
int value;
int timeout = 1000000;
/* Put the address of the phy, and the register
* number into MIIMADD */
out_be32(&phyregs->miimadd, (port_addr << 8) | (regnum & 0x1f));
/* Clear the command register, and wait */
out_be32(&phyregs->miimcom, 0);
asm("sync");
/* Initiate a read command, and wait */
out_be32(&phyregs->miimcom, MIIMCOM_READ_CYCLE);
asm("sync");
/* Wait for the the indication that the read is done */
while ((in_be32(&phyregs->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY))
&& timeout--)
;
/* Grab the value read from the PHY */
value = in_be32(&phyregs->miimstat);
return value;
}
static int fsl_pq_mdio_reset(struct mii_dev *bus)
{
struct tsec_mii_mng *regs = bus->priv;
/* Reset MII (due to new addresses) */
out_be32(&regs->miimcfg, MIIMCFG_RESET_MGMT);
out_be32(&regs->miimcfg, MIIMCFG_INIT_VALUE);
while (in_be32(&regs->miimind) & MIIMIND_BUSY)
;
return 0;
}
int tsec_phy_read(struct mii_dev *bus, int addr, int dev_addr, int regnum)
{
struct tsec_mii_mng *phyregs = bus->priv;
return tsec_local_mdio_read(phyregs, addr, dev_addr, regnum);
}
int tsec_phy_write(struct mii_dev *bus, int addr, int dev_addr, int regnum,
u16 value)
{
struct tsec_mii_mng *phyregs = bus->priv;
tsec_local_mdio_write(phyregs, addr, dev_addr, regnum, value);
return 0;
}
int fsl_pq_mdio_init(bd_t *bis, struct fsl_pq_mdio_info *info)
{
struct mii_dev *bus = mdio_alloc();
if (!bus) {
printf("Failed to allocate FSL MDIO bus\n");
return -1;
}
bus->read = tsec_phy_read;
bus->write = tsec_phy_write;
bus->reset = fsl_pq_mdio_reset;
sprintf(bus->name, info->name);
bus->priv = info->regs;
return mdio_register(bus);
}

View file

@ -28,6 +28,19 @@ LIB := $(obj)libphy.o
COBJS-$(CONFIG_BITBANGMII) += miiphybb.o
COBJS-$(CONFIG_MV88E61XX_SWITCH) += mv88e61xx.o
COBJS-$(CONFIG_PHYLIB) += phy.o
COBJS-$(CONFIG_PHYLIB_10G) += generic_10g.o
COBJS-$(CONFIG_PHY_ATHEROS) += atheros.o
COBJS-$(CONFIG_PHY_BROADCOM) += broadcom.o
COBJS-$(CONFIG_PHY_DAVICOM) += davicom.o
COBJS-$(CONFIG_PHY_LXT) += lxt.o
COBJS-$(CONFIG_PHY_MARVELL) += marvell.o
COBJS-$(CONFIG_PHY_MICREL) += micrel.o
COBJS-$(CONFIG_PHY_NATSEMI) += natsemi.o
COBJS-$(CONFIG_PHY_REALTEK) += realtek.o
COBJS-$(CONFIG_PHY_TERANETICS) += teranetics.o
COBJS-$(CONFIG_PHY_VITESSE) += vitesse.o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))

48
drivers/net/phy/atheros.c Normal file
View file

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

288
drivers/net/phy/broadcom.c Normal file
View file

@ -0,0 +1,288 @@
/*
* Broadcom PHY drivers
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
* Copyright 2010-2011 Freescale Semiconductor, Inc.
* author Andy Fleming
*
*/
#include <config.h>
#include <common.h>
#include <phy.h>
/* Broadcom BCM54xx -- taken from linux sungem_phy */
#define MIIM_BCM54xx_AUXCNTL 0x18
#define MIIM_BCM54xx_AUXCNTL_ENCODE(val) (((val & 0x7) << 12)|(val & 0x7))
#define MIIM_BCM54xx_AUXSTATUS 0x19
#define MIIM_BCM54xx_AUXSTATUS_LINKMODE_MASK 0x0700
#define MIIM_BCM54xx_AUXSTATUS_LINKMODE_SHIFT 8
#define MIIM_BCM54XX_SHD 0x1c
#define MIIM_BCM54XX_SHD_WRITE 0x8000
#define MIIM_BCM54XX_SHD_VAL(x) ((x & 0x1f) << 10)
#define MIIM_BCM54XX_SHD_DATA(x) ((x & 0x3ff) << 0)
#define MIIM_BCM54XX_SHD_WR_ENCODE(val, data) \
(MIIM_BCM54XX_SHD_WRITE | MIIM_BCM54XX_SHD_VAL(val) | \
MIIM_BCM54XX_SHD_DATA(data))
#define MIIM_BCM54XX_EXP_DATA 0x15 /* Expansion register data */
#define MIIM_BCM54XX_EXP_SEL 0x17 /* Expansion register select */
#define MIIM_BCM54XX_EXP_SEL_SSD 0x0e00 /* Secondary SerDes select */
#define MIIM_BCM54XX_EXP_SEL_ER 0x0f00 /* Expansion register select */
/* Broadcom BCM5461S */
static int bcm5461_config(struct phy_device *phydev)
{
genphy_config_aneg(phydev);
phy_reset(phydev);
return 0;
}
static int bcm54xx_parse_status(struct phy_device *phydev)
{
unsigned int mii_reg;
mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_BCM54xx_AUXSTATUS);
switch ((mii_reg & MIIM_BCM54xx_AUXSTATUS_LINKMODE_MASK) >>
MIIM_BCM54xx_AUXSTATUS_LINKMODE_SHIFT) {
case 1:
phydev->duplex = DUPLEX_HALF;
phydev->speed = SPEED_10;
break;
case 2:
phydev->duplex = DUPLEX_FULL;
phydev->speed = SPEED_10;
break;
case 3:
phydev->duplex = DUPLEX_HALF;
phydev->speed = SPEED_100;
break;
case 5:
phydev->duplex = DUPLEX_FULL;
phydev->speed = SPEED_100;
break;
case 6:
phydev->duplex = DUPLEX_HALF;
phydev->speed = SPEED_1000;
break;
case 7:
phydev->duplex = DUPLEX_FULL;
phydev->speed = SPEED_1000;
break;
default:
printf("Auto-neg error, defaulting to 10BT/HD\n");
phydev->duplex = DUPLEX_HALF;
phydev->speed = SPEED_10;
break;
}
return 0;
}
static int bcm54xx_startup(struct phy_device *phydev)
{
/* Read the Status (2x to make sure link is right) */
genphy_update_link(phydev);
bcm54xx_parse_status(phydev);
return 0;
}
/* Broadcom BCM5482S */
/*
* "Ethernet@Wirespeed" needs to be enabled to achieve link in certain
* circumstances. eg a gigabit TSEC connected to a gigabit switch with
* a 4-wire ethernet cable. Both ends advertise gigabit, but can't
* link. "Ethernet@Wirespeed" reduces advertised speed until link
* can be achieved.
*/
static u32 bcm5482_read_wirespeed(struct phy_device *phydev, u32 reg)
{
return (phy_read(phydev, MDIO_DEVAD_NONE, reg) & 0x8FFF) | 0x8010;
}
static int bcm5482_config(struct phy_device *phydev)
{
unsigned int reg;
/* reset the PHY */
reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
reg |= BMCR_RESET;
phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, reg);
/* Setup read from auxilary control shadow register 7 */
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_BCM54xx_AUXCNTL,
MIIM_BCM54xx_AUXCNTL_ENCODE(7));
/* Read Misc Control register and or in Ethernet@Wirespeed */
reg = bcm5482_read_wirespeed(phydev, MIIM_BCM54xx_AUXCNTL);
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_BCM54xx_AUXCNTL, reg);
/* Initial config/enable of secondary SerDes interface */
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_BCM54XX_SHD,
MIIM_BCM54XX_SHD_WR_ENCODE(0x14, 0xf));
/* Write intial value to secondary SerDes Contol */
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_BCM54XX_EXP_SEL,
MIIM_BCM54XX_EXP_SEL_SSD | 0);
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_BCM54XX_EXP_DATA,
BMCR_ANRESTART);
/* Enable copper/fiber auto-detect */
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_BCM54XX_SHD,
MIIM_BCM54XX_SHD_WR_ENCODE(0x1e, 0x201));
genphy_config_aneg(phydev);
return 0;
}
/*
* Find out if PHY is in copper or serdes mode by looking at Expansion Reg
* 0x42 - "Operating Mode Status Register"
*/
static int bcm5482_is_serdes(struct phy_device *phydev)
{
u16 val;
int serdes = 0;
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_BCM54XX_EXP_SEL,
MIIM_BCM54XX_EXP_SEL_ER | 0x42);
val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_BCM54XX_EXP_DATA);
switch (val & 0x1f) {
case 0x0d: /* RGMII-to-100Base-FX */
case 0x0e: /* RGMII-to-SGMII */
case 0x0f: /* RGMII-to-SerDes */
case 0x12: /* SGMII-to-SerDes */
case 0x13: /* SGMII-to-100Base-FX */
case 0x16: /* SerDes-to-Serdes */
serdes = 1;
break;
case 0x6: /* RGMII-to-Copper */
case 0x14: /* SGMII-to-Copper */
case 0x17: /* SerDes-to-Copper */
break;
default:
printf("ERROR, invalid PHY mode (0x%x\n)", val);
break;
}
return serdes;
}
/*
* Determine SerDes link speed and duplex from Expansion reg 0x42 "Operating
* Mode Status Register"
*/
static u32 bcm5482_parse_serdes_sr(struct phy_device *phydev)
{
u16 val;
int i = 0;
/* Wait 1s for link - Clause 37 autonegotiation happens very fast */
while (1) {
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_BCM54XX_EXP_SEL,
MIIM_BCM54XX_EXP_SEL_ER | 0x42);
val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_BCM54XX_EXP_DATA);
if (val & 0x8000)
break;
if (i++ > 1000) {
phydev->link = 0;
return 1;
}
udelay(1000); /* 1 ms */
}
phydev->link = 1;
switch ((val >> 13) & 0x3) {
case (0x00):
phydev->speed = 10;
break;
case (0x01):
phydev->speed = 100;
break;
case (0x02):
phydev->speed = 1000;
break;
}
phydev->duplex = (val & 0x1000) == 0x1000;
return 0;
}
/*
* Figure out if BCM5482 is in serdes or copper mode and determine link
* configuration accordingly
*/
static int bcm5482_startup(struct phy_device *phydev)
{
if (bcm5482_is_serdes(phydev)) {
bcm5482_parse_serdes_sr(phydev);
phydev->port = PORT_FIBRE;
} else {
/* Wait for auto-negotiation to complete or fail */
genphy_update_link(phydev);
/* Parse BCM54xx copper aux status register */
bcm54xx_parse_status(phydev);
}
return 0;
}
static struct phy_driver BCM5461S_driver = {
.name = "Broadcom BCM5461S",
.uid = 0x2060c0,
.mask = 0xfffff0,
.features = PHY_GBIT_FEATURES,
.config = &bcm5461_config,
.startup = &bcm54xx_startup,
.shutdown = &genphy_shutdown,
};
static struct phy_driver BCM5464S_driver = {
.name = "Broadcom BCM5464S",
.uid = 0x2060b0,
.mask = 0xfffff0,
.features = PHY_GBIT_FEATURES,
.config = &bcm5461_config,
.startup = &bcm54xx_startup,
.shutdown = &genphy_shutdown,
};
static struct phy_driver BCM5482S_driver = {
.name = "Broadcom BCM5482S",
.uid = 0x143bcb0,
.mask = 0xffffff0,
.features = PHY_GBIT_FEATURES,
.config = &bcm5482_config,
.startup = &bcm5482_startup,
.shutdown = &genphy_shutdown,
};
int phy_broadcom_init(void)
{
phy_register(&BCM5482S_driver);
phy_register(&BCM5464S_driver);
phy_register(&BCM5461S_driver);
return 0;
}

98
drivers/net/phy/davicom.c Normal file
View file

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

View file

@ -0,0 +1,105 @@
/*
* Generic PHY Management code
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
*
* Copyright 2011 Freescale Semiconductor, Inc.
* author Andy Fleming
*
* Based loosely off of Linux's PHY Lib
*/
#include <config.h>
#include <common.h>
#include <miiphy.h>
#include <phy.h>
int gen10g_shutdown(struct phy_device *phydev)
{
return 0;
}
int gen10g_startup(struct phy_device *phydev)
{
int devad, reg;
u32 mmd_mask = phydev->mmds;
phydev->link = 1;
/* For now just lie and say it's 10G all the time */
phydev->speed = SPEED_10000;
phydev->duplex = DUPLEX_FULL;
for (devad = 0; mmd_mask; devad++, mmd_mask = mmd_mask >> 1) {
if (!mmd_mask & 1)
continue;
/* Read twice because link state is latched and a
* read moves the current state into the register */
phy_read(phydev, devad, MDIO_STAT1);
reg = phy_read(phydev, devad, MDIO_STAT1);
if (reg < 0 || !(reg & MDIO_STAT1_LSTATUS))
phydev->link = 0;
}
return 0;
}
int gen10g_discover_mmds(struct phy_device *phydev)
{
int mmd, stat2, devs1, devs2;
/* Assume PHY must have at least one of PMA/PMD, WIS, PCS, PHY
* XS or DTE XS; give up if none is present. */
for (mmd = 1; mmd <= 5; mmd++) {
/* Is this MMD present? */
stat2 = phy_read(phydev, mmd, MDIO_STAT2);
if (stat2 < 0 ||
(stat2 & MDIO_STAT2_DEVPRST) != MDIO_STAT2_DEVPRST_VAL)
continue;
/* It should tell us about all the other MMDs */
devs1 = phy_read(phydev, mmd, MDIO_DEVS1);
devs2 = phy_read(phydev, mmd, MDIO_DEVS2);
if (devs1 < 0 || devs2 < 0)
continue;
phydev->mmds = devs1 | (devs2 << 16);
return 0;
}
return 0;
}
int gen10g_config(struct phy_device *phydev)
{
/* For now, assume 10000baseT. Fill in later */
phydev->supported = phydev->advertising = SUPPORTED_10000baseT_Full;
return gen10g_discover_mmds(phydev);
}
struct phy_driver gen10g_driver = {
.uid = 0xffffffff,
.mask = 0xffffffff,
.name = "Generic 10G PHY",
.features = 0,
.config = gen10g_config,
.startup = gen10g_startup,
.shutdown = gen10g_shutdown,
};

87
drivers/net/phy/lxt.c Normal file
View file

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

367
drivers/net/phy/marvell.c Normal file
View file

@ -0,0 +1,367 @@
/*
* Marvell PHY drivers
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
* Copyright 2010-2011 Freescale Semiconductor, Inc.
* author Andy Fleming
*
*/
#include <config.h>
#include <common.h>
#include <phy.h>
#define PHY_AUTONEGOTIATE_TIMEOUT 5000
/* 88E1011 PHY Status Register */
#define MIIM_88E1xxx_PHY_STATUS 0x11
#define MIIM_88E1xxx_PHYSTAT_SPEED 0xc000
#define MIIM_88E1xxx_PHYSTAT_GBIT 0x8000
#define MIIM_88E1xxx_PHYSTAT_100 0x4000
#define MIIM_88E1xxx_PHYSTAT_DUPLEX 0x2000
#define MIIM_88E1xxx_PHYSTAT_SPDDONE 0x0800
#define MIIM_88E1xxx_PHYSTAT_LINK 0x0400
#define MIIM_88E1xxx_PHY_SCR 0x10
#define MIIM_88E1xxx_PHY_MDI_X_AUTO 0x0060
/* 88E1111 PHY LED Control Register */
#define MIIM_88E1111_PHY_LED_CONTROL 24
#define MIIM_88E1111_PHY_LED_DIRECT 0x4100
#define MIIM_88E1111_PHY_LED_COMBINE 0x411C
/* 88E1118 PHY defines */
#define MIIM_88E1118_PHY_PAGE 22
#define MIIM_88E1118_PHY_LED_PAGE 3
/* 88E1121 PHY LED Control Register */
#define MIIM_88E1121_PHY_LED_CTRL 16
#define MIIM_88E1121_PHY_LED_PAGE 3
#define MIIM_88E1121_PHY_LED_DEF 0x0030
/* 88E1121 PHY IRQ Enable/Status Register */
#define MIIM_88E1121_PHY_IRQ_EN 18
#define MIIM_88E1121_PHY_IRQ_STATUS 19
#define MIIM_88E1121_PHY_PAGE 22
/* 88E1145 Extended PHY Specific Control Register */
#define MIIM_88E1145_PHY_EXT_CR 20
#define MIIM_M88E1145_RGMII_RX_DELAY 0x0080
#define MIIM_M88E1145_RGMII_TX_DELAY 0x0002
#define MIIM_88E1145_PHY_LED_CONTROL 24
#define MIIM_88E1145_PHY_LED_DIRECT 0x4100
#define MIIM_88E1145_PHY_PAGE 29
#define MIIM_88E1145_PHY_CAL_OV 30
#define MIIM_88E1149_PHY_PAGE 29
/* Marvell 88E1011S */
static int m88e1011s_config(struct phy_device *phydev)
{
/* Reset and configure the PHY */
phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x1f);
phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x200c);
phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x5);
phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0);
phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x100);
phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
genphy_config_aneg(phydev);
return 0;
}
/* Parse the 88E1011's status register for speed and duplex
* information
*/
static uint m88e1xxx_parse_status(struct phy_device *phydev)
{
unsigned int speed;
unsigned int mii_reg;
mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1xxx_PHY_STATUS);
if ((mii_reg & MIIM_88E1xxx_PHYSTAT_LINK) &&
!(mii_reg & MIIM_88E1xxx_PHYSTAT_SPDDONE)) {
int i = 0;
puts("Waiting for PHY realtime link");
while (!(mii_reg & MIIM_88E1xxx_PHYSTAT_SPDDONE)) {
/* Timeout reached ? */
if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
puts(" TIMEOUT !\n");
phydev->link = 0;
break;
}
if ((i++ % 1000) == 0)
putc('.');
udelay(1000);
mii_reg = phy_read(phydev, MDIO_DEVAD_NONE,
MIIM_88E1xxx_PHY_STATUS);
}
puts(" done\n");
udelay(500000); /* another 500 ms (results in faster booting) */
} else {
if (mii_reg & MIIM_88E1xxx_PHYSTAT_LINK)
phydev->link = 1;
else
phydev->link = 0;
}
if (mii_reg & MIIM_88E1xxx_PHYSTAT_DUPLEX)
phydev->duplex = DUPLEX_FULL;
else
phydev->duplex = DUPLEX_HALF;
speed = mii_reg & MIIM_88E1xxx_PHYSTAT_SPEED;
switch (speed) {
case MIIM_88E1xxx_PHYSTAT_GBIT:
phydev->speed = SPEED_1000;
break;
case MIIM_88E1xxx_PHYSTAT_100:
phydev->speed = SPEED_100;
break;
default:
phydev->speed = SPEED_10;
break;
}
return 0;
}
static int m88e1011s_startup(struct phy_device *phydev)
{
genphy_update_link(phydev);
m88e1xxx_parse_status(phydev);
return 0;
}
/* Marvell 88E1111S */
static int m88e1111s_config(struct phy_device *phydev)
{
int reg;
if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
(phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) ||
(phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
(phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
reg = phy_read(phydev, MDIO_DEVAD_NONE, 0x1b);
reg = (reg & 0xfff0) | 0xb;
phy_write(phydev, MDIO_DEVAD_NONE, 0x1b, reg);
} else {
phy_write(phydev, MDIO_DEVAD_NONE, 0x1b, 0x1f);
}
phy_write(phydev, MDIO_DEVAD_NONE, 0x14, 0x0cd2);
genphy_config_aneg(phydev);
phy_reset(phydev);
return 0;
}
/* Marvell 88E1118 */
static int m88e1118_config(struct phy_device *phydev)
{
/* Change Page Number */
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0002);
/* Delay RGMII TX and RX */
phy_write(phydev, MDIO_DEVAD_NONE, 0x15, 0x1070);
/* Change Page Number */
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0003);
/* Adjust LED control */
phy_write(phydev, MDIO_DEVAD_NONE, 0x10, 0x021e);
/* Change Page Number */
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000);
genphy_config_aneg(phydev);
phy_reset(phydev);
return 0;
}
static int m88e1118_startup(struct phy_device *phydev)
{
/* Change Page Number */
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000);
genphy_update_link(phydev);
m88e1xxx_parse_status(phydev);
return 0;
}
/* Marvell 88E1121R */
static int m88e1121_config(struct phy_device *phydev)
{
int pg;
/* Configure the PHY */
genphy_config_aneg(phydev);
/* Switch the page to access the led register */
pg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_PAGE);
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_PAGE,
MIIM_88E1121_PHY_LED_PAGE);
/* Configure leds */
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_LED_CTRL,
MIIM_88E1121_PHY_LED_DEF);
/* Restore the page pointer */
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_PAGE, pg);
/* Disable IRQs and de-assert interrupt */
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_IRQ_EN, 0);
phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_IRQ_STATUS);
return 0;
}
/* Marvell 88E1145 */
static int m88e1145_config(struct phy_device *phydev)
{
int reg;
/* Errata E0, E1 */
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_PAGE, 0x001b);
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_CAL_OV, 0x418f);
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_PAGE, 0x0016);
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_CAL_OV, 0xa2da);
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1xxx_PHY_SCR,
MIIM_88E1xxx_PHY_MDI_X_AUTO);
reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_EXT_CR);
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
reg |= MIIM_M88E1145_RGMII_RX_DELAY |
MIIM_M88E1145_RGMII_TX_DELAY;
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_EXT_CR, reg);
genphy_config_aneg(phydev);
phy_reset(phydev);
return 0;
}
static int m88e1145_startup(struct phy_device *phydev)
{
genphy_update_link(phydev);
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_LED_CONTROL,
MIIM_88E1145_PHY_LED_DIRECT);
m88e1xxx_parse_status(phydev);
return 0;
}
/* Marvell 88E1149S */
static int m88e1149_config(struct phy_device *phydev)
{
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1149_PHY_PAGE, 0x1f);
phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x200c);
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1149_PHY_PAGE, 0x5);
phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x0);
phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x100);
genphy_config_aneg(phydev);
phy_reset(phydev);
return 0;
}
static struct phy_driver M88E1011S_driver = {
.name = "Marvell 88E1011S",
.uid = 0x1410c60,
.mask = 0xffffff0,
.features = PHY_GBIT_FEATURES,
.config = &m88e1011s_config,
.startup = &m88e1011s_startup,
.shutdown = &genphy_shutdown,
};
static struct phy_driver M88E1111S_driver = {
.name = "Marvell 88E1111S",
.uid = 0x1410cc0,
.mask = 0xffffff0,
.features = PHY_GBIT_FEATURES,
.config = &m88e1111s_config,
.startup = &m88e1011s_startup,
.shutdown = &genphy_shutdown,
};
static struct phy_driver M88E1118_driver = {
.name = "Marvell 88E1118",
.uid = 0x1410e10,
.mask = 0xffffff0,
.features = PHY_GBIT_FEATURES,
.config = &m88e1118_config,
.startup = &m88e1118_startup,
.shutdown = &genphy_shutdown,
};
static struct phy_driver M88E1121R_driver = {
.name = "Marvell 88E1121R",
.uid = 0x1410cb0,
.mask = 0xffffff0,
.features = PHY_GBIT_FEATURES,
.config = &m88e1121_config,
.startup = &genphy_startup,
.shutdown = &genphy_shutdown,
};
static struct phy_driver M88E1145_driver = {
.name = "Marvell 88E1145",
.uid = 0x1410cd0,
.mask = 0xffffff0,
.features = PHY_GBIT_FEATURES,
.config = &m88e1145_config,
.startup = &m88e1145_startup,
.shutdown = &genphy_shutdown,
};
static struct phy_driver M88E1149S_driver = {
.name = "Marvell 88E1149S",
.uid = 0x1410ca0,
.mask = 0xffffff0,
.features = PHY_GBIT_FEATURES,
.config = &m88e1149_config,
.startup = &m88e1011s_startup,
.shutdown = &genphy_shutdown,
};
int phy_marvell_init(void)
{
phy_register(&M88E1149S_driver);
phy_register(&M88E1145_driver);
phy_register(&M88E1121R_driver);
phy_register(&M88E1118_driver);
phy_register(&M88E1111S_driver);
phy_register(&M88E1011S_driver);
return 0;
}

40
drivers/net/phy/micrel.c Normal file
View file

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

96
drivers/net/phy/natsemi.c Normal file
View file

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

755
drivers/net/phy/phy.c Normal file
View file

@ -0,0 +1,755 @@
/*
* Generic PHY Management code
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
*
* Copyright 2011 Freescale Semiconductor, Inc.
* author Andy Fleming
*
* Based loosely off of Linux's PHY Lib
*/
#include <config.h>
#include <common.h>
#include <malloc.h>
#include <net.h>
#include <command.h>
#include <miiphy.h>
#include <phy.h>
#include <errno.h>
/* Generic PHY support and helper functions */
/**
* genphy_config_advert - sanitize and advertise auto-negotation parameters
* @phydev: target phy_device struct
*
* Description: Writes MII_ADVERTISE with the appropriate values,
* after sanitizing the values to make sure we only advertise
* what is supported. Returns < 0 on error, 0 if the PHY's advertisement
* hasn't changed, and > 0 if it has changed.
*/
int genphy_config_advert(struct phy_device *phydev)
{
u32 advertise;
int oldadv, adv;
int err, changed = 0;
/* Only allow advertising what
* this PHY supports */
phydev->advertising &= phydev->supported;
advertise = phydev->advertising;
/* Setup standard advertisement */
oldadv = adv = phy_read(phydev, MDIO_DEVAD_NONE, MII_ADVERTISE);
if (adv < 0)
return adv;
adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP |
ADVERTISE_PAUSE_ASYM);
if (advertise & ADVERTISED_10baseT_Half)
adv |= ADVERTISE_10HALF;
if (advertise & ADVERTISED_10baseT_Full)
adv |= ADVERTISE_10FULL;
if (advertise & ADVERTISED_100baseT_Half)
adv |= ADVERTISE_100HALF;
if (advertise & ADVERTISED_100baseT_Full)
adv |= ADVERTISE_100FULL;
if (advertise & ADVERTISED_Pause)
adv |= ADVERTISE_PAUSE_CAP;
if (advertise & ADVERTISED_Asym_Pause)
adv |= ADVERTISE_PAUSE_ASYM;
if (adv != oldadv) {
err = phy_write(phydev, MDIO_DEVAD_NONE, MII_ADVERTISE, adv);
if (err < 0)
return err;
changed = 1;
}
/* Configure gigabit if it's supported */
if (phydev->supported & (SUPPORTED_1000baseT_Half |
SUPPORTED_1000baseT_Full)) {
oldadv = adv = phy_read(phydev, MDIO_DEVAD_NONE, MII_CTRL1000);
if (adv < 0)
return adv;
adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
if (advertise & SUPPORTED_1000baseT_Half)
adv |= ADVERTISE_1000HALF;
if (advertise & SUPPORTED_1000baseT_Full)
adv |= ADVERTISE_1000FULL;
if (adv != oldadv) {
err = phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000,
adv);
if (err < 0)
return err;
changed = 1;
}
}
return changed;
}
/**
* genphy_setup_forced - configures/forces speed/duplex from @phydev
* @phydev: target phy_device struct
*
* Description: Configures MII_BMCR to force speed/duplex
* to the values in phydev. Assumes that the values are valid.
*/
int genphy_setup_forced(struct phy_device *phydev)
{
int err;
int ctl = 0;
phydev->pause = phydev->asym_pause = 0;
if (SPEED_1000 == phydev->speed)
ctl |= BMCR_SPEED1000;
else if (SPEED_100 == phydev->speed)
ctl |= BMCR_SPEED100;
if (DUPLEX_FULL == phydev->duplex)
ctl |= BMCR_FULLDPLX;
err = phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, ctl);
return err;
}
/**
* genphy_restart_aneg - Enable and Restart Autonegotiation
* @phydev: target phy_device struct
*/
int genphy_restart_aneg(struct phy_device *phydev)
{
int ctl;
ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
if (ctl < 0)
return ctl;
ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
/* Don't isolate the PHY if we're negotiating */
ctl &= ~(BMCR_ISOLATE);
ctl = phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, ctl);
return ctl;
}
/**
* genphy_config_aneg - restart auto-negotiation or write BMCR
* @phydev: target phy_device struct
*
* Description: If auto-negotiation is enabled, we configure the
* advertising, and then restart auto-negotiation. If it is not
* enabled, then we write the BMCR.
*/
int genphy_config_aneg(struct phy_device *phydev)
{
int result;
if (AUTONEG_ENABLE != phydev->autoneg)
return genphy_setup_forced(phydev);
result = genphy_config_advert(phydev);
if (result < 0) /* error */
return result;
if (result == 0) {
/* Advertisment hasn't changed, but maybe aneg was never on to
* begin with? Or maybe phy was isolated? */
int ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
if (ctl < 0)
return ctl;
if (!(ctl & BMCR_ANENABLE) || (ctl & BMCR_ISOLATE))
result = 1; /* do restart aneg */
}
/* Only restart aneg if we are advertising something different
* than we were before. */
if (result > 0)
result = genphy_restart_aneg(phydev);
return result;
}
/**
* genphy_update_link - update link status in @phydev
* @phydev: target phy_device struct
*
* Description: Update the value in phydev->link to reflect the
* current link value. In order to do this, we need to read
* the status register twice, keeping the second value.
*/
int genphy_update_link(struct phy_device *phydev)
{
unsigned int mii_reg;
/*
* Wait if the link is up, and autonegotiation is in progress
* (ie - we're capable and it's not done)
*/
mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
/*
* If we already saw the link up, and it hasn't gone down, then
* we don't need to wait for autoneg again
*/
if (phydev->link && mii_reg & BMSR_LSTATUS)
return 0;
if ((mii_reg & BMSR_ANEGCAPABLE) && !(mii_reg & BMSR_ANEGCOMPLETE)) {
int i = 0;
printf("%s Waiting for PHY auto negotiation to complete",
phydev->dev->name);
while (!(mii_reg & BMSR_ANEGCOMPLETE)) {
/*
* Timeout reached ?
*/
if (i > PHY_ANEG_TIMEOUT) {
printf(" TIMEOUT !\n");
phydev->link = 0;
return 0;
}
if (ctrlc()) {
puts("user interrupt!\n");
phydev->link = 0;
return -EINTR;
}
if ((i++ % 500) == 0)
printf(".");
udelay(1000); /* 1 ms */
mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
}
printf(" done\n");
phydev->link = 1;
} else {
/* Read the link a second time to clear the latched state */
mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
if (mii_reg & BMSR_LSTATUS)
phydev->link = 1;
else
phydev->link = 0;
}
return 0;
}
/*
* Generic function which updates the speed and duplex. If
* autonegotiation is enabled, it uses the AND of the link
* partner's advertised capabilities and our advertised
* capabilities. If autonegotiation is disabled, we use the
* appropriate bits in the control register.
*
* Stolen from Linux's mii.c and phy_device.c
*/
static int genphy_parse_link(struct phy_device *phydev)
{
int mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
/* We're using autonegotiation */
if (mii_reg & BMSR_ANEGCAPABLE) {
u32 lpa = 0;
u32 gblpa = 0;
/* Check for gigabit capability */
if (mii_reg & BMSR_ERCAP) {
/* We want a list of states supported by
* both PHYs in the link
*/
gblpa = phy_read(phydev, MDIO_DEVAD_NONE, MII_STAT1000);
gblpa &= phy_read(phydev,
MDIO_DEVAD_NONE, MII_CTRL1000) << 2;
}
/* Set the baseline so we only have to set them
* if they're different
*/
phydev->speed = SPEED_10;
phydev->duplex = DUPLEX_HALF;
/* Check the gigabit fields */
if (gblpa & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)) {
phydev->speed = SPEED_1000;
if (gblpa & PHY_1000BTSR_1000FD)
phydev->duplex = DUPLEX_FULL;
/* We're done! */
return 0;
}
lpa = phy_read(phydev, MDIO_DEVAD_NONE, MII_ADVERTISE);
lpa &= phy_read(phydev, MDIO_DEVAD_NONE, MII_LPA);
if (lpa & (LPA_100FULL | LPA_100HALF)) {
phydev->speed = SPEED_100;
if (lpa & LPA_100FULL)
phydev->duplex = DUPLEX_FULL;
} else if (lpa & LPA_10FULL)
phydev->duplex = DUPLEX_FULL;
} else {
u32 bmcr = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
phydev->speed = SPEED_10;
phydev->duplex = DUPLEX_HALF;
if (bmcr & BMCR_FULLDPLX)
phydev->duplex = DUPLEX_FULL;
if (bmcr & BMCR_SPEED1000)
phydev->speed = SPEED_1000;
else if (bmcr & BMCR_SPEED100)
phydev->speed = SPEED_100;
}
return 0;
}
int genphy_config(struct phy_device *phydev)
{
int val;
u32 features;
/* For now, I'll claim that the generic driver supports
* all possible port types */
features = (SUPPORTED_TP | SUPPORTED_MII
| SUPPORTED_AUI | SUPPORTED_FIBRE |
SUPPORTED_BNC);
/* Do we support autonegotiation? */
val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
if (val < 0)
return val;
if (val & BMSR_ANEGCAPABLE)
features |= SUPPORTED_Autoneg;
if (val & BMSR_100FULL)
features |= SUPPORTED_100baseT_Full;
if (val & BMSR_100HALF)
features |= SUPPORTED_100baseT_Half;
if (val & BMSR_10FULL)
features |= SUPPORTED_10baseT_Full;
if (val & BMSR_10HALF)
features |= SUPPORTED_10baseT_Half;
if (val & BMSR_ESTATEN) {
val = phy_read(phydev, MDIO_DEVAD_NONE, MII_ESTATUS);
if (val < 0)
return val;
if (val & ESTATUS_1000_TFULL)
features |= SUPPORTED_1000baseT_Full;
if (val & ESTATUS_1000_THALF)
features |= SUPPORTED_1000baseT_Half;
}
phydev->supported = features;
phydev->advertising = features;
genphy_config_aneg(phydev);
return 0;
}
int genphy_startup(struct phy_device *phydev)
{
genphy_update_link(phydev);
genphy_parse_link(phydev);
return 0;
}
int genphy_shutdown(struct phy_device *phydev)
{
return 0;
}
static struct phy_driver genphy_driver = {
.uid = 0xffffffff,
.mask = 0xffffffff,
.name = "Generic PHY",
.features = 0,
.config = genphy_config,
.startup = genphy_startup,
.shutdown = genphy_shutdown,
};
static LIST_HEAD(phy_drivers);
int phy_init(void)
{
#ifdef CONFIG_PHY_ATHEROS
phy_atheros_init();
#endif
#ifdef CONFIG_PHY_BROADCOM
phy_broadcom_init();
#endif
#ifdef CONFIG_PHY_DAVICOM
phy_davicom_init();
#endif
#ifdef CONFIG_PHY_LXT
phy_lxt_init();
#endif
#ifdef CONFIG_PHY_MARVELL
phy_marvell_init();
#endif
#ifdef CONFIG_PHY_MICREL
phy_micrel_init();
#endif
#ifdef CONFIG_PHY_NATSEMI
phy_natsemi_init();
#endif
#ifdef CONFIG_PHY_REALTEK
phy_realtek_init();
#endif
#ifdef CONFIG_PHY_TERANETICS
phy_teranetics_init();
#endif
#ifdef CONFIG_PHY_VITESSE
phy_vitesse_init();
#endif
return 0;
}
int phy_register(struct phy_driver *drv)
{
INIT_LIST_HEAD(&drv->list);
list_add_tail(&drv->list, &phy_drivers);
return 0;
}
int phy_probe(struct phy_device *phydev)
{
int err = 0;
phydev->advertising = phydev->supported = phydev->drv->features;
phydev->mmds = phydev->drv->mmds;
if (phydev->drv->probe)
err = phydev->drv->probe(phydev);
return err;
}
static struct phy_driver *generic_for_interface(phy_interface_t interface)
{
#ifdef CONFIG_PHYLIB_10G
if (is_10g_interface(interface))
return &gen10g_driver;
#endif
return &genphy_driver;
}
struct phy_driver *get_phy_driver(struct phy_device *phydev,
phy_interface_t interface)
{
struct list_head *entry;
int phy_id = phydev->phy_id;
struct phy_driver *drv = NULL;
list_for_each(entry, &phy_drivers) {
drv = list_entry(entry, struct phy_driver, list);
if ((drv->uid & drv->mask) == (phy_id & drv->mask))
return drv;
}
/* If we made it here, there's no driver for this PHY */
return generic_for_interface(interface);
}
struct phy_device *phy_device_create(struct mii_dev *bus, int addr, int phy_id,
phy_interface_t interface)
{
struct phy_device *dev;
/* We allocate the device, and initialize the
* default values */
dev = malloc(sizeof(*dev));
if (!dev) {
printf("Failed to allocate PHY device for %s:%d\n",
bus->name, addr);
return NULL;
}
memset(dev, 0, sizeof(*dev));
dev->duplex = -1;
dev->link = 1;
dev->interface = interface;
dev->autoneg = AUTONEG_ENABLE;
dev->addr = addr;
dev->phy_id = phy_id;
dev->bus = bus;
dev->drv = get_phy_driver(dev, interface);
phy_probe(dev);
bus->phymap[addr] = dev;
return dev;
}
/**
* get_phy_id - reads the specified addr for its ID.
* @bus: the target MII bus
* @addr: PHY address on the MII bus
* @phy_id: where to store the ID retrieved.
*
* Description: Reads the ID registers of the PHY at @addr on the
* @bus, stores it in @phy_id and returns zero on success.
*/
int get_phy_id(struct mii_dev *bus, int addr, int devad, u32 *phy_id)
{
int phy_reg;
/* Grab the bits from PHYIR1, and put them
* in the upper half */
phy_reg = bus->read(bus, addr, devad, MII_PHYSID1);
if (phy_reg < 0)
return -EIO;
*phy_id = (phy_reg & 0xffff) << 16;
/* Grab the bits from PHYIR2, and put them in the lower half */
phy_reg = bus->read(bus, addr, devad, MII_PHYSID2);
if (phy_reg < 0)
return -EIO;
*phy_id |= (phy_reg & 0xffff);
return 0;
}
/**
* get_phy_device - reads the specified PHY device and returns its @phy_device struct
* @bus: the target MII bus
* @addr: PHY address on the MII bus
*
* Description: Reads the ID registers of the PHY at @addr on the
* @bus, then allocates and returns the phy_device to represent it.
*/
struct phy_device *get_phy_device(struct mii_dev *bus, int addr,
phy_interface_t interface)
{
u32 phy_id = 0x1fffffff;
int i;
int r;
/* If we have one, return the existing device, with new interface */
if (bus->phymap[addr]) {
bus->phymap[addr]->interface = interface;
return bus->phymap[addr];
}
/* Try Standard (ie Clause 22) access */
r = get_phy_id(bus, addr, MDIO_DEVAD_NONE, &phy_id);
if (r)
return NULL;
/* If the PHY ID is mostly f's, we didn't find anything */
if ((phy_id & 0x1fffffff) != 0x1fffffff)
return phy_device_create(bus, addr, phy_id, interface);
/* Otherwise we have to try Clause 45 */
for (i = 1; i < 5; i++) {
r = get_phy_id(bus, addr, i, &phy_id);
if (r)
return NULL;
/* If the phy_id is mostly Fs, there is no device there */
if ((phy_id & 0x1fffffff) != 0x1fffffff)
break;
}
return phy_device_create(bus, addr, phy_id, interface);
}
int phy_reset(struct phy_device *phydev)
{
int reg;
int timeout = 500;
int devad = MDIO_DEVAD_NONE;
#ifdef CONFIG_PHYLIB_10G
/* If it's 10G, we need to issue reset through one of the MMDs */
if (is_10g_interface(phydev->interface)) {
if (!phydev->mmds)
gen10g_discover_mmds(phydev);
devad = ffs(phydev->mmds) - 1;
}
#endif
reg = phy_read(phydev, devad, MII_BMCR);
if (reg < 0) {
debug("PHY status read failed\n");
return -1;
}
reg |= BMCR_RESET;
if (phy_write(phydev, devad, MII_BMCR, reg) < 0) {
debug("PHY reset failed\n");
return -1;
}
#ifdef CONFIG_PHY_RESET_DELAY
udelay(CONFIG_PHY_RESET_DELAY); /* Intel LXT971A needs this */
#endif
/*
* Poll the control register for the reset bit to go to 0 (it is
* auto-clearing). This should happen within 0.5 seconds per the
* IEEE spec.
*/
while ((reg & BMCR_RESET) && timeout--) {
reg = phy_read(phydev, devad, MII_BMCR);
if (reg < 0) {
debug("PHY status read failed\n");
return -1;
}
udelay(1000);
}
if (reg & BMCR_RESET) {
puts("PHY reset timed out\n");
return -1;
}
return 0;
}
int miiphy_reset(const char *devname, unsigned char addr)
{
struct mii_dev *bus = miiphy_get_dev_by_name(devname);
struct phy_device *phydev;
/*
* miiphy_reset was only used on standard PHYs, so we'll fake it here.
* If later code tries to connect with the right interface, this will
* be corrected by get_phy_device in phy_connect()
*/
phydev = get_phy_device(bus, addr, PHY_INTERFACE_MODE_MII);
return phy_reset(phydev);
}
struct phy_device *phy_connect(struct mii_dev *bus, int addr,
struct eth_device *dev,
phy_interface_t interface)
{
struct phy_device *phydev;
/* Reset the bus */
bus->reset(bus);
/* Wait 15ms to make sure the PHY has come out of hard reset */
udelay(15000);
phydev = get_phy_device(bus, addr, interface);
if (!phydev) {
printf("Could not get PHY for %s:%d\n", bus->name, addr);
return NULL;
}
/* Soft Reset the PHY */
phy_reset(phydev);
if (phydev->dev)
printf("%s:%d is connected to %s. Reconnecting to %s\n",
bus->name, addr, phydev->dev->name, dev->name);
phydev->dev = dev;
printf("%s connected to %s\n", dev->name, phydev->drv->name);
return phydev;
}
int phy_startup(struct phy_device *phydev)
{
if (phydev->drv->startup)
phydev->drv->startup(phydev);
return 0;
}
static int __board_phy_config(struct phy_device *phydev)
{
return 0;
}
int board_phy_config(struct phy_device *phydev)
__attribute__((weak, alias("__board_phy_config")));
int phy_config(struct phy_device *phydev)
{
if (phydev->drv->config)
phydev->drv->config(phydev);
/* Invoke an optional board-specific helper */
board_phy_config(phydev);
return 0;
}
int phy_shutdown(struct phy_device *phydev)
{
if (phydev->drv->shutdown)
phydev->drv->shutdown(phydev);
return 0;
}

130
drivers/net/phy/realtek.c Normal file
View file

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

View file

@ -0,0 +1,62 @@
/*
* Teranetics PHY drivers
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
* Copyright 2010-2011 Freescale Semiconductor, Inc.
* author Andy Fleming
*
*/
#include <config.h>
#include <phy.h>
#ifndef CONFIG_PHYLIB_10G
#error The Teranetics PHY needs 10G support
#endif
int tn2020_config(struct phy_device *phydev)
{
if (phydev->port == PORT_FIBRE) {
unsigned short restart_an = (MDIO_AN_CTRL1_RESTART |
MDIO_AN_CTRL1_ENABLE |
MDIO_AN_CTRL1_XNP);
phy_write(phydev, 30, 93, 2);
phy_write(phydev, MDIO_MMD_AN, MDIO_CTRL1, restart_an);
}
return 0;
}
struct phy_driver tn2020_driver = {
.name = "Teranetics TN2020",
.uid = 0x00a19410,
.mask = 0xfffffff0,
.features = PHY_10G_FEATURES,
.mmds = (MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS |
MDIO_DEVS_PHYXS | MDIO_DEVS_AN |
MDIO_DEVS_VEND1 | MDIO_DEVS_VEND2),
.config = &tn2020_config,
.startup = &gen10g_startup,
.shutdown = &gen10g_shutdown,
};
int phy_teranetics_init(void)
{
phy_register(&tn2020_driver);
return 0;
}

242
drivers/net/phy/vitesse.c Normal file
View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

@ -30,6 +30,7 @@
#include "uec.h"
#include "uec_phy.h"
#include "miiphy.h"
#include <phy.h>
/* Default UTBIPAR SMI address */
#ifndef CONFIG_UTBIPAR_INIT_TBIPA
@ -67,9 +68,6 @@ static uec_info_t uec_info[] = {
static struct eth_device *devlist[MAXCONTROLLERS];
u16 phy_read (struct uec_mii_info *mii_info, u16 regnum);
void phy_write (struct uec_mii_info *mii_info, u16 regnum, u16 val);
static int uec_mac_enable(uec_private_t *uec, comm_dir_e mode)
{
uec_t *uec_regs;
@ -324,9 +322,9 @@ static int uec_set_mac_duplex(uec_private_t *uec, int duplex)
}
static int uec_set_mac_if_mode(uec_private_t *uec,
enum fsl_phy_enet_if if_mode, int speed)
phy_interface_t if_mode, int speed)
{
enum fsl_phy_enet_if enet_if_mode;
phy_interface_t enet_if_mode;
uec_info_t *uec_info;
uec_t *uec_regs;
u32 upsmr;
@ -348,15 +346,15 @@ static int uec_set_mac_if_mode(uec_private_t *uec,
upsmr &= ~(UPSMR_RPM | UPSMR_TBIM | UPSMR_R10M | UPSMR_RMM);
switch (speed) {
case 10:
case SPEED_10:
maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE;
switch (enet_if_mode) {
case MII:
case PHY_INTERFACE_MODE_MII:
break;
case RGMII:
case PHY_INTERFACE_MODE_RGMII:
upsmr |= (UPSMR_RPM | UPSMR_R10M);
break;
case RMII:
case PHY_INTERFACE_MODE_RMII:
upsmr |= (UPSMR_R10M | UPSMR_RMM);
break;
default:
@ -364,15 +362,15 @@ static int uec_set_mac_if_mode(uec_private_t *uec,
break;
}
break;
case 100:
case SPEED_100:
maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE;
switch (enet_if_mode) {
case MII:
case PHY_INTERFACE_MODE_MII:
break;
case RGMII:
case PHY_INTERFACE_MODE_RGMII:
upsmr |= UPSMR_RPM;
break;
case RMII:
case PHY_INTERFACE_MODE_RMII:
upsmr |= UPSMR_RMM;
break;
default:
@ -380,23 +378,24 @@ static int uec_set_mac_if_mode(uec_private_t *uec,
break;
}
break;
case 1000:
case SPEED_1000:
maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE;
switch (enet_if_mode) {
case GMII:
case PHY_INTERFACE_MODE_GMII:
break;
case TBI:
case PHY_INTERFACE_MODE_TBI:
upsmr |= UPSMR_TBIM;
break;
case RTBI:
case PHY_INTERFACE_MODE_RTBI:
upsmr |= (UPSMR_RPM | UPSMR_TBIM);
break;
case RGMII_RXID:
case RGMII_ID:
case RGMII:
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_TXID:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII:
upsmr |= UPSMR_RPM;
break;
case SGMII:
case PHY_INTERFACE_MODE_SGMII:
upsmr |= UPSMR_SGMM;
break;
default:
@ -521,7 +520,7 @@ static void adjust_link(struct eth_device *dev)
struct uec_mii_info *mii_info = uec->mii_info;
extern void change_phy_interface_mode(struct eth_device *dev,
enum fsl_phy_enet_if mode, int speed);
phy_interface_t mode, int speed);
uec_regs = uec->uec_regs;
if (mii_info->link) {
@ -539,19 +538,19 @@ static void adjust_link(struct eth_device *dev)
}
if (mii_info->speed != uec->oldspeed) {
enum fsl_phy_enet_if mode = \
phy_interface_t mode =
uec->uec_info->enet_interface_type;
if (uec->uec_info->uf_info.eth_type == GIGA_ETH) {
switch (mii_info->speed) {
case 1000:
case SPEED_1000:
break;
case 100:
case SPEED_100:
printf ("switching to rgmii 100\n");
mode = RGMII;
mode = PHY_INTERFACE_MODE_RGMII;
break;
case 10:
case SPEED_10:
printf ("switching to rgmii 10\n");
mode = RGMII;
mode = PHY_INTERFACE_MODE_RGMII;
break;
default:
printf("%s: Ack,Speed(%d)is illegal\n",
@ -1115,8 +1114,8 @@ static int uec_startup(uec_private_t *uec)
out_be32(&uec_regs->utbipar, utbipar);
/* Configure the TBI for SGMII operation */
if ((uec->uec_info->enet_interface_type == SGMII) &&
(uec->uec_info->speed == 1000)) {
if ((uec->uec_info->enet_interface_type == PHY_INTERFACE_MODE_SGMII) &&
(uec->uec_info->speed == SPEED_1000)) {
uec_write_phy_reg(uec->dev, uec_regs->utbipar,
ENET_TBI_MII_ANA, TBIANA_SETTINGS);

View file

@ -25,6 +25,7 @@
#include "qe.h"
#include "uccf.h"
#include <phy.h>
#include <asm/fsl_enet.h>
#define MAX_TX_THREADS 8
@ -691,7 +692,7 @@ typedef struct uec_info {
u16 rx_bd_ring_len;
u16 tx_bd_ring_len;
u8 phy_address;
enum fsl_phy_enet_if enet_interface_type;
phy_interface_t enet_interface_type;
int speed;
} uec_info_t;

View file

@ -25,6 +25,7 @@
#include "uec.h"
#include "uec_phy.h"
#include "miiphy.h"
#include <phy.h>
#define ugphy_printk(format, arg...) \
printf(format "\n", ## arg)
@ -121,8 +122,8 @@ static int gbit_config_aneg (struct uec_mii_info *mii_info);
static int genmii_config_aneg (struct uec_mii_info *mii_info);
static int genmii_update_link (struct uec_mii_info *mii_info);
static int genmii_read_status (struct uec_mii_info *mii_info);
u16 phy_read (struct uec_mii_info *mii_info, u16 regnum);
void phy_write (struct uec_mii_info *mii_info, u16 regnum, u16 val);
u16 uec_phy_read(struct uec_mii_info *mii_info, u16 regnum);
void uec_phy_write(struct uec_mii_info *mii_info, u16 regnum, u16 val);
/* Write value to the PHY for this device to the register at regnum, */
/* waiting until the write is done before it returns. All PHY */
@ -242,7 +243,7 @@ static void config_genmii_advert (struct uec_mii_info *mii_info)
advertise = mii_info->advertising;
/* Setup standard advertisement */
adv = phy_read (mii_info, MII_ADVERTISE);
adv = uec_phy_read(mii_info, MII_ADVERTISE);
adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
if (advertise & ADVERTISED_10baseT_Half)
adv |= ADVERTISE_10HALF;
@ -252,7 +253,7 @@ static void config_genmii_advert (struct uec_mii_info *mii_info)
adv |= ADVERTISE_100HALF;
if (advertise & ADVERTISED_100baseT_Full)
adv |= ADVERTISE_100FULL;
phy_write (mii_info, MII_ADVERTISE, adv);
uec_phy_write(mii_info, MII_ADVERTISE, adv);
}
static void genmii_setup_forced (struct uec_mii_info *mii_info)
@ -260,7 +261,7 @@ static void genmii_setup_forced (struct uec_mii_info *mii_info)
u16 ctrl;
u32 features = mii_info->phyinfo->features;
ctrl = phy_read (mii_info, MII_BMCR);
ctrl = uec_phy_read(mii_info, MII_BMCR);
ctrl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 |
BMCR_SPEED1000 | BMCR_ANENABLE);
@ -290,7 +291,7 @@ static void genmii_setup_forced (struct uec_mii_info *mii_info)
break;
}
phy_write (mii_info, MII_BMCR, ctrl);
uec_phy_write(mii_info, MII_BMCR, ctrl);
}
/* Enable and Restart Autonegotiation */
@ -298,9 +299,9 @@ static void genmii_restart_aneg (struct uec_mii_info *mii_info)
{
u16 ctl;
ctl = phy_read (mii_info, MII_BMCR);
ctl = uec_phy_read(mii_info, MII_BMCR);
ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
phy_write (mii_info, MII_BMCR, ctl);
uec_phy_write(mii_info, MII_BMCR, ctl);
}
static int gbit_config_aneg (struct uec_mii_info *mii_info)
@ -313,14 +314,14 @@ static int gbit_config_aneg (struct uec_mii_info *mii_info)
config_genmii_advert (mii_info);
advertise = mii_info->advertising;
adv = phy_read (mii_info, MII_CTRL1000);
adv = uec_phy_read(mii_info, MII_CTRL1000);
adv &= ~(ADVERTISE_1000FULL |
ADVERTISE_1000HALF);
if (advertise & SUPPORTED_1000baseT_Half)
adv |= ADVERTISE_1000HALF;
if (advertise & SUPPORTED_1000baseT_Full)
adv |= ADVERTISE_1000FULL;
phy_write (mii_info, MII_CTRL1000, adv);
uec_phy_write(mii_info, MII_CTRL1000, adv);
/* Start/Restart aneg */
genmii_restart_aneg (mii_info);
@ -335,13 +336,13 @@ static int marvell_config_aneg (struct uec_mii_info *mii_info)
/* The Marvell PHY has an errata which requires
* that certain registers get written in order
* to restart autonegotiation */
phy_write (mii_info, MII_BMCR, BMCR_RESET);
uec_phy_write(mii_info, MII_BMCR, BMCR_RESET);
phy_write (mii_info, 0x1d, 0x1f);
phy_write (mii_info, 0x1e, 0x200c);
phy_write (mii_info, 0x1d, 0x5);
phy_write (mii_info, 0x1e, 0);
phy_write (mii_info, 0x1e, 0x100);
uec_phy_write(mii_info, 0x1d, 0x1f);
uec_phy_write(mii_info, 0x1e, 0x200c);
uec_phy_write(mii_info, 0x1d, 0x5);
uec_phy_write(mii_info, 0x1e, 0);
uec_phy_write(mii_info, 0x1e, 0x100);
gbit_config_aneg (mii_info);
@ -373,13 +374,13 @@ static int genmii_update_link (struct uec_mii_info *mii_info)
u16 status;
/* Status is read once to clear old link state */
phy_read (mii_info, MII_BMSR);
uec_phy_read(mii_info, MII_BMSR);
/*
* Wait if the link is up, and autonegotiation is in progress
* (ie - we're capable and it's not done)
*/
status = phy_read(mii_info, MII_BMSR);
status = uec_phy_read(mii_info, MII_BMSR);
if ((status & BMSR_LSTATUS) && (status & BMSR_ANEGCAPABLE)
&& !(status & BMSR_ANEGCOMPLETE)) {
int i = 0;
@ -395,7 +396,7 @@ static int genmii_update_link (struct uec_mii_info *mii_info)
i++;
udelay(1000); /* 1 ms */
status = phy_read(mii_info, MII_BMSR);
status = uec_phy_read(mii_info, MII_BMSR);
}
mii_info->link = 1;
} else {
@ -420,7 +421,7 @@ static int genmii_read_status (struct uec_mii_info *mii_info)
return err;
if (mii_info->autoneg) {
status = phy_read(mii_info, MII_STAT1000);
status = uec_phy_read(mii_info, MII_STAT1000);
if (status & (LPA_1000FULL | LPA_1000HALF)) {
mii_info->speed = SPEED_1000;
@ -429,7 +430,7 @@ static int genmii_read_status (struct uec_mii_info *mii_info)
else
mii_info->duplex = DUPLEX_HALF;
} else {
status = phy_read(mii_info, MII_LPA);
status = uec_phy_read(mii_info, MII_LPA);
if (status & (LPA_10FULL | LPA_100FULL))
mii_info->duplex = DUPLEX_FULL;
@ -456,62 +457,63 @@ static int bcm_init(struct uec_mii_info *mii_info)
gbit_config_aneg(mii_info);
if ((uec->uec_info->enet_interface_type == RGMII_RXID) &&
(uec->uec_info->speed == 1000)) {
if ((uec->uec_info->enet_interface_type ==
PHY_INTERFACE_MODE_RGMII_RXID) &&
(uec->uec_info->speed == SPEED_1000)) {
u16 val;
int cnt = 50;
/* Wait for aneg to complete. */
do
val = phy_read(mii_info, MII_BMSR);
val = uec_phy_read(mii_info, MII_BMSR);
while (--cnt && !(val & BMSR_ANEGCOMPLETE));
/* Set RDX clk delay. */
phy_write(mii_info, 0x18, 0x7 | (7 << 12));
uec_phy_write(mii_info, 0x18, 0x7 | (7 << 12));
val = phy_read(mii_info, 0x18);
val = uec_phy_read(mii_info, 0x18);
/* Set RDX-RXC skew. */
val |= (1 << 8);
val |= (7 | (7 << 12));
/* Write bits 14:0. */
val |= (1 << 15);
phy_write(mii_info, 0x18, val);
uec_phy_write(mii_info, 0x18, val);
}
return 0;
}
static int marvell_init(struct uec_mii_info *mii_info)
static int uec_marvell_init(struct uec_mii_info *mii_info)
{
struct eth_device *edev = mii_info->dev;
uec_private_t *uec = edev->priv;
enum fsl_phy_enet_if iface = uec->uec_info->enet_interface_type;
phy_interface_t iface = uec->uec_info->enet_interface_type;
int speed = uec->uec_info->speed;
if ((speed == 1000) &&
(iface == RGMII_ID ||
iface == RGMII_RXID ||
iface == RGMII_TXID)) {
if ((speed == SPEED_1000) &&
(iface == PHY_INTERFACE_MODE_RGMII_ID ||
iface == PHY_INTERFACE_MODE_RGMII_RXID ||
iface == PHY_INTERFACE_MODE_RGMII_TXID)) {
int temp;
temp = phy_read(mii_info, MII_M1111_PHY_EXT_CR);
if (iface == RGMII_ID) {
temp = uec_phy_read(mii_info, MII_M1111_PHY_EXT_CR);
if (iface == PHY_INTERFACE_MODE_RGMII_ID) {
temp |= MII_M1111_RX_DELAY | MII_M1111_TX_DELAY;
} else if (iface == RGMII_RXID) {
} else if (iface == PHY_INTERFACE_MODE_RGMII_RXID) {
temp &= ~MII_M1111_TX_DELAY;
temp |= MII_M1111_RX_DELAY;
} else if (iface == RGMII_TXID) {
} else if (iface == PHY_INTERFACE_MODE_RGMII_TXID) {
temp &= ~MII_M1111_RX_DELAY;
temp |= MII_M1111_TX_DELAY;
}
phy_write(mii_info, MII_M1111_PHY_EXT_CR, temp);
uec_phy_write(mii_info, MII_M1111_PHY_EXT_CR, temp);
temp = phy_read(mii_info, MII_M1111_PHY_EXT_SR);
temp = uec_phy_read(mii_info, MII_M1111_PHY_EXT_SR);
temp &= ~MII_M1111_HWCFG_MODE_MASK;
temp |= MII_M1111_HWCFG_MODE_RGMII;
phy_write(mii_info, MII_M1111_PHY_EXT_SR, temp);
uec_phy_write(mii_info, MII_M1111_PHY_EXT_SR, temp);
phy_write(mii_info, MII_BMCR, BMCR_RESET);
uec_phy_write(mii_info, MII_BMCR, BMCR_RESET);
}
return 0;
@ -534,7 +536,7 @@ static int marvell_read_status (struct uec_mii_info *mii_info)
if (mii_info->autoneg && mii_info->link) {
int speed;
status = phy_read (mii_info, MII_M1011_PHY_SPEC_STATUS);
status = uec_phy_read(mii_info, MII_M1011_PHY_SPEC_STATUS);
/* Get the duplexity */
if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
@ -564,7 +566,7 @@ static int marvell_read_status (struct uec_mii_info *mii_info)
static int marvell_ack_interrupt (struct uec_mii_info *mii_info)
{
/* Clear the interrupts by reading the reg */
phy_read (mii_info, MII_M1011_IEVENT);
uec_phy_read(mii_info, MII_M1011_IEVENT);
return 0;
}
@ -572,9 +574,10 @@ static int marvell_ack_interrupt (struct uec_mii_info *mii_info)
static int marvell_config_intr (struct uec_mii_info *mii_info)
{
if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
phy_write (mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
uec_phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
else
phy_write (mii_info, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
uec_phy_write(mii_info, MII_M1011_IMASK,
MII_M1011_IMASK_CLEAR);
return 0;
}
@ -582,13 +585,13 @@ static int marvell_config_intr (struct uec_mii_info *mii_info)
static int dm9161_init (struct uec_mii_info *mii_info)
{
/* Reset the PHY */
phy_write (mii_info, MII_BMCR, phy_read (mii_info, MII_BMCR) |
uec_phy_write(mii_info, MII_BMCR, uec_phy_read(mii_info, MII_BMCR) |
BMCR_RESET);
/* PHY and MAC connect */
phy_write (mii_info, MII_BMCR, phy_read (mii_info, MII_BMCR) &
uec_phy_write(mii_info, MII_BMCR, uec_phy_read(mii_info, MII_BMCR) &
~BMCR_ISOLATE);
phy_write (mii_info, MII_DM9161_SCR, MII_DM9161_SCR_INIT);
uec_phy_write(mii_info, MII_DM9161_SCR, MII_DM9161_SCR_INIT);
config_genmii_advert (mii_info);
/* Start/restart aneg */
@ -614,7 +617,7 @@ static int dm9161_read_status (struct uec_mii_info *mii_info)
/* If the link is up, read the speed and duplex
If we aren't autonegotiating assume speeds are as set */
if (mii_info->autoneg && mii_info->link) {
status = phy_read (mii_info, MII_DM9161_SCSR);
status = uec_phy_read(mii_info, MII_DM9161_SCSR);
if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_100H))
mii_info->speed = SPEED_100;
else
@ -632,7 +635,7 @@ static int dm9161_read_status (struct uec_mii_info *mii_info)
static int dm9161_ack_interrupt (struct uec_mii_info *mii_info)
{
/* Clear the interrupt by reading the reg */
phy_read (mii_info, MII_DM9161_INTR);
uec_phy_read(mii_info, MII_DM9161_INTR);
return 0;
}
@ -640,9 +643,9 @@ static int dm9161_ack_interrupt (struct uec_mii_info *mii_info)
static int dm9161_config_intr (struct uec_mii_info *mii_info)
{
if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
phy_write (mii_info, MII_DM9161_INTR, MII_DM9161_INTR_INIT);
uec_phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_INIT);
else
phy_write (mii_info, MII_DM9161_INTR, MII_DM9161_INTR_STOP);
uec_phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_STOP);
return 0;
}
@ -696,7 +699,7 @@ static int smsc_read_status (struct uec_mii_info *mii_info)
if (mii_info->autoneg && mii_info->link) {
int val;
status = phy_read (mii_info, 0x1f);
status = uec_phy_read(mii_info, 0x1f);
val = (status & 0x1c) >> 2;
switch (val) {
@ -751,7 +754,7 @@ static struct phy_info phy_info_marvell = {
.phy_id_mask = 0xffffff00,
.name = "Marvell 88E11x1",
.features = MII_GBIT_FEATURES,
.init = &marvell_init,
.init = &uec_marvell_init,
.config_aneg = &marvell_config_aneg,
.read_status = &marvell_read_status,
.ack_interrupt = &marvell_ack_interrupt,
@ -804,12 +807,12 @@ static struct phy_info *phy_info[] = {
NULL
};
u16 phy_read (struct uec_mii_info *mii_info, u16 regnum)
u16 uec_phy_read(struct uec_mii_info *mii_info, u16 regnum)
{
return mii_info->mdio_read (mii_info->dev, mii_info->mii_id, regnum);
}
void phy_write (struct uec_mii_info *mii_info, u16 regnum, u16 val)
void uec_phy_write(struct uec_mii_info *mii_info, u16 regnum, u16 val)
{
mii_info->mdio_write (mii_info->dev, mii_info->mii_id, regnum, val);
}
@ -825,11 +828,11 @@ struct phy_info *uec_get_phy_info (struct uec_mii_info *mii_info)
struct phy_info *theInfo = NULL;
/* Grab the bits from PHYIR1, and put them in the upper half */
phy_reg = phy_read (mii_info, MII_PHYSID1);
phy_reg = uec_phy_read(mii_info, MII_PHYSID1);
phy_ID = (phy_reg & 0xffff) << 16;
/* Grab the bits from PHYIR2, and put them in the lower half */
phy_reg = phy_read (mii_info, MII_PHYSID2);
phy_reg = uec_phy_read(mii_info, MII_PHYSID2);
phy_ID |= (phy_reg & 0xffff);
/* loop through all the known PHY types, and find one that */
@ -852,10 +855,8 @@ struct phy_info *uec_get_phy_info (struct uec_mii_info *mii_info)
return theInfo;
}
void marvell_phy_interface_mode (struct eth_device *dev,
enum fsl_phy_enet_if type,
int speed
)
void marvell_phy_interface_mode(struct eth_device *dev, phy_interface_t type,
int speed)
{
uec_private_t *uec = (uec_private_t *) dev->priv;
struct uec_mii_info *mii_info;
@ -867,47 +868,47 @@ void marvell_phy_interface_mode (struct eth_device *dev,
}
mii_info = uec->mii_info;
if (type == RGMII) {
if (speed == 100) {
phy_write (mii_info, 0x00, 0x9140);
phy_write (mii_info, 0x1d, 0x001f);
phy_write (mii_info, 0x1e, 0x200c);
phy_write (mii_info, 0x1d, 0x0005);
phy_write (mii_info, 0x1e, 0x0000);
phy_write (mii_info, 0x1e, 0x0100);
phy_write (mii_info, 0x09, 0x0e00);
phy_write (mii_info, 0x04, 0x01e1);
phy_write (mii_info, 0x00, 0x9140);
phy_write (mii_info, 0x00, 0x1000);
if (type == PHY_INTERFACE_MODE_RGMII) {
if (speed == SPEED_100) {
uec_phy_write(mii_info, 0x00, 0x9140);
uec_phy_write(mii_info, 0x1d, 0x001f);
uec_phy_write(mii_info, 0x1e, 0x200c);
uec_phy_write(mii_info, 0x1d, 0x0005);
uec_phy_write(mii_info, 0x1e, 0x0000);
uec_phy_write(mii_info, 0x1e, 0x0100);
uec_phy_write(mii_info, 0x09, 0x0e00);
uec_phy_write(mii_info, 0x04, 0x01e1);
uec_phy_write(mii_info, 0x00, 0x9140);
uec_phy_write(mii_info, 0x00, 0x1000);
udelay (100000);
phy_write (mii_info, 0x00, 0x2900);
phy_write (mii_info, 0x14, 0x0cd2);
phy_write (mii_info, 0x00, 0xa100);
phy_write (mii_info, 0x09, 0x0000);
phy_write (mii_info, 0x1b, 0x800b);
phy_write (mii_info, 0x04, 0x05e1);
phy_write (mii_info, 0x00, 0xa100);
phy_write (mii_info, 0x00, 0x2100);
uec_phy_write(mii_info, 0x00, 0x2900);
uec_phy_write(mii_info, 0x14, 0x0cd2);
uec_phy_write(mii_info, 0x00, 0xa100);
uec_phy_write(mii_info, 0x09, 0x0000);
uec_phy_write(mii_info, 0x1b, 0x800b);
uec_phy_write(mii_info, 0x04, 0x05e1);
uec_phy_write(mii_info, 0x00, 0xa100);
uec_phy_write(mii_info, 0x00, 0x2100);
udelay (1000000);
} else if (speed == 10) {
phy_write (mii_info, 0x14, 0x8e40);
phy_write (mii_info, 0x1b, 0x800b);
phy_write (mii_info, 0x14, 0x0c82);
phy_write (mii_info, 0x00, 0x8100);
} else if (speed == SPEED_10) {
uec_phy_write(mii_info, 0x14, 0x8e40);
uec_phy_write(mii_info, 0x1b, 0x800b);
uec_phy_write(mii_info, 0x14, 0x0c82);
uec_phy_write(mii_info, 0x00, 0x8100);
udelay (1000000);
}
}
/* handle 88e1111 rev.B2 erratum 5.6 */
if (mii_info->autoneg) {
status = phy_read (mii_info, MII_BMCR);
phy_write (mii_info, MII_BMCR, status | BMCR_ANENABLE);
status = uec_phy_read(mii_info, MII_BMCR);
uec_phy_write(mii_info, MII_BMCR, status | BMCR_ANENABLE);
}
/* now the B2 will correctly report autoneg completion status */
}
void change_phy_interface_mode (struct eth_device *dev,
enum fsl_phy_enet_if type, int speed)
phy_interface_t type, int speed)
{
#ifdef CONFIG_PHY_MODE_NEED_CHANGE
marvell_phy_interface_mode (dev, type, speed);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -334,7 +334,7 @@ extern unsigned long get_clock_freq(void);
#define CONFIG_SYS_UEC1_TX_CLK QE_CLK16
#define CONFIG_SYS_UEC1_ETH_TYPE GIGA_ETH
#define CONFIG_SYS_UEC1_PHY_ADDR 7
#define CONFIG_SYS_UEC1_INTERFACE_TYPE RGMII_ID
#define CONFIG_SYS_UEC1_INTERFACE_TYPE PHY_INTERFACE_MODE_RGMII_ID
#define CONFIG_SYS_UEC1_INTERFACE_SPEED 1000
#endif
@ -346,7 +346,7 @@ extern unsigned long get_clock_freq(void);
#define CONFIG_SYS_UEC2_TX_CLK QE_CLK16
#define CONFIG_SYS_UEC2_ETH_TYPE GIGA_ETH
#define CONFIG_SYS_UEC2_PHY_ADDR 1
#define CONFIG_SYS_UEC2_INTERFACE_TYPE RGMII_ID
#define CONFIG_SYS_UEC2_INTERFACE_TYPE PHY_INTERFACE_MODE_RGMII_ID
#define CONFIG_SYS_UEC2_INTERFACE_SPEED 1000
#endif
#endif /* CONFIG_QE */

View file

@ -385,13 +385,13 @@ extern unsigned long get_clock_freq(void);
#define CONFIG_SYS_UEC1_TX_CLK QE_CLK12
#define CONFIG_SYS_UEC1_ETH_TYPE GIGA_ETH
#define CONFIG_SYS_UEC1_PHY_ADDR 7
#define CONFIG_SYS_UEC1_INTERFACE_TYPE RGMII_ID
#define CONFIG_SYS_UEC1_INTERFACE_TYPE PHY_INTERFACE_MODE_RGMII_ID
#define CONFIG_SYS_UEC1_INTERFACE_SPEED 1000
#elif defined(CONFIG_SYS_UCC_RMII_MODE)
#define CONFIG_SYS_UEC1_TX_CLK QE_CLK16 /* CLK16 for RMII */
#define CONFIG_SYS_UEC1_ETH_TYPE FAST_ETH
#define CONFIG_SYS_UEC1_PHY_ADDR 8 /* 0x8 for RMII */
#define CONFIG_SYS_UEC1_INTERFACE_TYPE RMII
#define CONFIG_SYS_UEC1_INTERFACE_TYPE PHY_INTERFACE_MODE_RMII
#define CONFIG_SYS_UEC1_INTERFACE_SPEED 100
#endif /* CONFIG_SYS_UCC_RGMII_MODE */
#endif /* CONFIG_UEC_ETH1 */
@ -406,13 +406,13 @@ extern unsigned long get_clock_freq(void);
#define CONFIG_SYS_UEC2_TX_CLK QE_CLK17
#define CONFIG_SYS_UEC2_ETH_TYPE GIGA_ETH
#define CONFIG_SYS_UEC2_PHY_ADDR 1
#define CONFIG_SYS_UEC2_INTERFACE_TYPE RGMII_ID
#define CONFIG_SYS_UEC2_INTERFACE_TYPE PHY_INTERFACE_MODE_RGMII_ID
#define CONFIG_SYS_UEC2_INTERFACE_SPEED 1000
#elif defined(CONFIG_SYS_UCC_RMII_MODE)
#define CONFIG_SYS_UEC2_TX_CLK QE_CLK16 /* CLK 16 for RMII */
#define CONFIG_SYS_UEC2_ETH_TYPE FAST_ETH
#define CONFIG_SYS_UEC2_PHY_ADDR 0x9 /* 0x9 for RMII */
#define CONFIG_SYS_UEC2_INTERFACE_TYPE RMII
#define CONFIG_SYS_UEC2_INTERFACE_TYPE PHY_INTERFACE_MODE_RMII
#define CONFIG_SYS_UEC2_INTERFACE_SPEED 100
#endif /* CONFIG_SYS_UCC_RGMII_MODE */
#endif /* CONFIG_UEC_ETH2 */
@ -427,13 +427,13 @@ extern unsigned long get_clock_freq(void);
#define CONFIG_SYS_UEC3_TX_CLK QE_CLK12
#define CONFIG_SYS_UEC3_ETH_TYPE GIGA_ETH
#define CONFIG_SYS_UEC3_PHY_ADDR 2
#define CONFIG_SYS_UEC3_INTERFACE_TYPE RGMII_ID
#define CONFIG_SYS_UEC3_INTERFACE_TYPE PHY_INTERFACE_MODE_RGMII_ID
#define CONFIG_SYS_UEC3_INTERFACE_SPEED 1000
#elif defined(CONFIG_SYS_UCC_RMII_MODE)
#define CONFIG_SYS_UEC3_TX_CLK QE_CLK16 /* CLK_16 for RMII */
#define CONFIG_SYS_UEC3_ETH_TYPE FAST_ETH
#define CONFIG_SYS_UEC3_PHY_ADDR 0xA /* 0xA for RMII */
#define CONFIG_SYS_UEC3_INTERFACE_TYPE RMII
#define CONFIG_SYS_UEC3_INTERFACE_TYPE PHY_INTERFACE_MODE_RMII
#define CONFIG_SYS_UEC3_INTERFACE_SPEED 100
#endif /* CONFIG_SYS_UCC_RGMII_MODE */
#endif /* CONFIG_UEC_ETH3 */
@ -448,13 +448,13 @@ extern unsigned long get_clock_freq(void);
#define CONFIG_SYS_UEC4_TX_CLK QE_CLK17
#define CONFIG_SYS_UEC4_ETH_TYPE GIGA_ETH
#define CONFIG_SYS_UEC4_PHY_ADDR 3
#define CONFIG_SYS_UEC4_INTERFACE_TYPE RGMII_ID
#define CONFIG_SYS_UEC4_INTERFACE_TYPE PHY_INTERFACE_MODE_RGMII_ID
#define CONFIG_SYS_UEC4_INTERFACE_SPEED 1000
#elif defined(CONFIG_SYS_UCC_RMII_MODE)
#define CONFIG_SYS_UEC4_TX_CLK QE_CLK16 /* CLK16 for RMII */
#define CONFIG_SYS_UEC4_ETH_TYPE FAST_ETH
#define CONFIG_SYS_UEC4_PHY_ADDR 0xB /* 0xB for RMII */
#define CONFIG_SYS_UEC4_INTERFACE_TYPE RMII
#define CONFIG_SYS_UEC4_INTERFACE_TYPE PHY_INTERFACE_MODE_RMII
#define CONFIG_SYS_UEC4_INTERFACE_SPEED 100
#endif /* CONFIG_SYS_UCC_RGMII_MODE */
#endif /* CONFIG_UEC_ETH4 */
@ -468,7 +468,7 @@ extern unsigned long get_clock_freq(void);
#define CONFIG_SYS_UEC6_TX_CLK QE_CLK_NONE
#define CONFIG_SYS_UEC6_ETH_TYPE GIGA_ETH
#define CONFIG_SYS_UEC6_PHY_ADDR 4
#define CONFIG_SYS_UEC6_INTERFACE_TYPE SGMII
#define CONFIG_SYS_UEC6_INTERFACE_TYPE PHY_INTERFACE_MODE_SGMII
#define CONFIG_SYS_UEC6_INTERFACE_SPEED 1000
#endif /* CONFIG_UEC_ETH6 */
@ -481,7 +481,7 @@ extern unsigned long get_clock_freq(void);
#define CONFIG_SYS_UEC8_TX_CLK QE_CLK_NONE
#define CONFIG_SYS_UEC8_ETH_TYPE GIGA_ETH
#define CONFIG_SYS_UEC8_PHY_ADDR 6
#define CONFIG_SYS_UEC8_INTERFACE_TYPE SGMII
#define CONFIG_SYS_UEC8_INTERFACE_TYPE PHY_INTERFACE_MODE_SGMII
#define CONFIG_SYS_UEC8_INTERFACE_SPEED 1000
#endif /* CONFIG_UEC_ETH8 */

View file

@ -295,7 +295,7 @@
#define CONFIG_SYS_UEC1_TX_CLK QE_CLK17
#define CONFIG_SYS_UEC1_ETH_TYPE FAST_ETH
#define CONFIG_SYS_UEC1_PHY_ADDR 0
#define CONFIG_SYS_UEC1_INTERFACE_TYPE RMII
#define CONFIG_SYS_UEC1_INTERFACE_TYPE PHY_INTERFACE_MODE_RMII
#define CONFIG_SYS_UEC1_INTERFACE_SPEED 100
#endif

62
include/fsl_mdio.h Normal file
View file

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

721
include/linux/ethtool.h Normal file
View file

@ -0,0 +1,721 @@
/*
* ethtool.h: Defines for Linux ethtool.
*
* Copyright (C) 1998 David S. Miller (davem@redhat.com)
* Copyright 2001 Jeff Garzik <jgarzik@pobox.com>
* Portions Copyright 2001 Sun Microsystems (thockin@sun.com)
* Portions Copyright 2002 Intel (eli.kupermann@intel.com,
* christopher.leech@intel.com,
* scott.feldman@intel.com)
* Portions Copyright (C) Sun Microsystems 2008
*/
#ifndef _LINUX_ETHTOOL_H
#define _LINUX_ETHTOOL_H
#include <linux/types.h>
/* This should work for both 32 and 64 bit userland. */
struct ethtool_cmd {
__u32 cmd;
__u32 supported; /* Features this interface supports */
__u32 advertising; /* Features this interface advertises */
__u16 speed; /* The forced speed, 10Mb, 100Mb, gigabit */
__u8 duplex; /* Duplex, half or full */
__u8 port; /* Which connector port */
__u8 phy_address;
__u8 transceiver; /* Which transceiver to use */
__u8 autoneg; /* Enable or disable autonegotiation */
__u8 mdio_support;
__u32 maxtxpkt; /* Tx pkts before generating tx int */
__u32 maxrxpkt; /* Rx pkts before generating rx int */
__u16 speed_hi;
__u8 eth_tp_mdix;
__u8 reserved2;
__u32 lp_advertising; /* Features the link partner advertises */
__u32 reserved[2];
};
static inline void ethtool_cmd_speed_set(struct ethtool_cmd *ep,
__u32 speed)
{
ep->speed = (__u16)speed;
ep->speed_hi = (__u16)(speed >> 16);
}
static inline __u32 ethtool_cmd_speed(struct ethtool_cmd *ep)
{
return (ep->speed_hi << 16) | ep->speed;
}
#define ETHTOOL_FWVERS_LEN 32
#define ETHTOOL_BUSINFO_LEN 32
/* these strings are set to whatever the driver author decides... */
struct ethtool_drvinfo {
__u32 cmd;
char driver[32]; /* driver short name, "tulip", "eepro100" */
char version[32]; /* driver version string */
char fw_version[ETHTOOL_FWVERS_LEN]; /* firmware version string */
char bus_info[ETHTOOL_BUSINFO_LEN]; /* Bus info for this IF. */
/* For PCI devices, use pci_name(pci_dev). */
char reserved1[32];
char reserved2[12];
/*
* Some struct members below are filled in
* using ops->get_sset_count(). Obtaining
* this info from ethtool_drvinfo is now
* deprecated; Use ETHTOOL_GSSET_INFO
* instead.
*/
__u32 n_priv_flags; /* number of flags valid in ETHTOOL_GPFLAGS */
__u32 n_stats; /* number of u64's from ETHTOOL_GSTATS */
__u32 testinfo_len;
__u32 eedump_len; /* Size of data from ETHTOOL_GEEPROM (bytes) */
__u32 regdump_len; /* Size of data from ETHTOOL_GREGS (bytes) */
};
#define SOPASS_MAX 6
/* wake-on-lan settings */
struct ethtool_wolinfo {
__u32 cmd;
__u32 supported;
__u32 wolopts;
__u8 sopass[SOPASS_MAX]; /* SecureOn(tm) password */
};
/* for passing single values */
struct ethtool_value {
__u32 cmd;
__u32 data;
};
/* for passing big chunks of data */
struct ethtool_regs {
__u32 cmd;
__u32 version; /* driver-specific, indicates different chips/revs */
__u32 len; /* bytes */
__u8 data[0];
};
/* for passing EEPROM chunks */
struct ethtool_eeprom {
__u32 cmd;
__u32 magic;
__u32 offset; /* in bytes */
__u32 len; /* in bytes */
__u8 data[0];
};
/* for configuring coalescing parameters of chip */
struct ethtool_coalesce {
__u32 cmd; /* ETHTOOL_{G,S}COALESCE */
/* How many usecs to delay an RX interrupt after
* a packet arrives. If 0, only rx_max_coalesced_frames
* is used.
*/
__u32 rx_coalesce_usecs;
/* How many packets to delay an RX interrupt after
* a packet arrives. If 0, only rx_coalesce_usecs is
* used. It is illegal to set both usecs and max frames
* to zero as this would cause RX interrupts to never be
* generated.
*/
__u32 rx_max_coalesced_frames;
/* Same as above two parameters, except that these values
* apply while an IRQ is being serviced by the host. Not
* all cards support this feature and the values are ignored
* in that case.
*/
__u32 rx_coalesce_usecs_irq;
__u32 rx_max_coalesced_frames_irq;
/* How many usecs to delay a TX interrupt after
* a packet is sent. If 0, only tx_max_coalesced_frames
* is used.
*/
__u32 tx_coalesce_usecs;
/* How many packets to delay a TX interrupt after
* a packet is sent. If 0, only tx_coalesce_usecs is
* used. It is illegal to set both usecs and max frames
* to zero as this would cause TX interrupts to never be
* generated.
*/
__u32 tx_max_coalesced_frames;
/* Same as above two parameters, except that these values
* apply while an IRQ is being serviced by the host. Not
* all cards support this feature and the values are ignored
* in that case.
*/
__u32 tx_coalesce_usecs_irq;
__u32 tx_max_coalesced_frames_irq;
/* How many usecs to delay in-memory statistics
* block updates. Some drivers do not have an in-memory
* statistic block, and in such cases this value is ignored.
* This value must not be zero.
*/
__u32 stats_block_coalesce_usecs;
/* Adaptive RX/TX coalescing is an algorithm implemented by
* some drivers to improve latency under low packet rates and
* improve throughput under high packet rates. Some drivers
* only implement one of RX or TX adaptive coalescing. Anything
* not implemented by the driver causes these values to be
* silently ignored.
*/
__u32 use_adaptive_rx_coalesce;
__u32 use_adaptive_tx_coalesce;
/* When the packet rate (measured in packets per second)
* is below pkt_rate_low, the {rx,tx}_*_low parameters are
* used.
*/
__u32 pkt_rate_low;
__u32 rx_coalesce_usecs_low;
__u32 rx_max_coalesced_frames_low;
__u32 tx_coalesce_usecs_low;
__u32 tx_max_coalesced_frames_low;
/* When the packet rate is below pkt_rate_high but above
* pkt_rate_low (both measured in packets per second) the
* normal {rx,tx}_* coalescing parameters are used.
*/
/* When the packet rate is (measured in packets per second)
* is above pkt_rate_high, the {rx,tx}_*_high parameters are
* used.
*/
__u32 pkt_rate_high;
__u32 rx_coalesce_usecs_high;
__u32 rx_max_coalesced_frames_high;
__u32 tx_coalesce_usecs_high;
__u32 tx_max_coalesced_frames_high;
/* How often to do adaptive coalescing packet rate sampling,
* measured in seconds. Must not be zero.
*/
__u32 rate_sample_interval;
};
/* for configuring RX/TX ring parameters */
struct ethtool_ringparam {
__u32 cmd; /* ETHTOOL_{G,S}RINGPARAM */
/* Read only attributes. These indicate the maximum number
* of pending RX/TX ring entries the driver will allow the
* user to set.
*/
__u32 rx_max_pending;
__u32 rx_mini_max_pending;
__u32 rx_jumbo_max_pending;
__u32 tx_max_pending;
/* Values changeable by the user. The valid values are
* in the range 1 to the "*_max_pending" counterpart above.
*/
__u32 rx_pending;
__u32 rx_mini_pending;
__u32 rx_jumbo_pending;
__u32 tx_pending;
};
/* for configuring link flow control parameters */
struct ethtool_pauseparam {
__u32 cmd; /* ETHTOOL_{G,S}PAUSEPARAM */
/* If the link is being auto-negotiated (via ethtool_cmd.autoneg
* being true) the user may set 'autonet' here non-zero to have the
* pause parameters be auto-negotiated too. In such a case, the
* {rx,tx}_pause values below determine what capabilities are
* advertised.
*
* If 'autoneg' is zero or the link is not being auto-negotiated,
* then {rx,tx}_pause force the driver to use/not-use pause
* flow control.
*/
__u32 autoneg;
__u32 rx_pause;
__u32 tx_pause;
};
#define ETH_GSTRING_LEN 32
enum ethtool_stringset {
ETH_SS_TEST = 0,
ETH_SS_STATS,
ETH_SS_PRIV_FLAGS,
ETH_SS_NTUPLE_FILTERS,
ETH_SS_FEATURES,
};
/* for passing string sets for data tagging */
struct ethtool_gstrings {
__u32 cmd; /* ETHTOOL_GSTRINGS */
__u32 string_set; /* string set id e.c. ETH_SS_TEST, etc*/
__u32 len; /* number of strings in the string set */
__u8 data[0];
};
struct ethtool_sset_info {
__u32 cmd; /* ETHTOOL_GSSET_INFO */
__u32 reserved;
__u64 sset_mask; /* input: each bit selects an sset to query */
/* output: each bit a returned sset */
__u32 data[0]; /* ETH_SS_xxx count, in order, based on bits
in sset_mask. One bit implies one
__u32, two bits implies two
__u32's, etc. */
};
enum ethtool_test_flags {
ETH_TEST_FL_OFFLINE = (1 << 0), /* online / offline */
ETH_TEST_FL_FAILED = (1 << 1), /* test passed / failed */
};
/* for requesting NIC test and getting results*/
struct ethtool_test {
__u32 cmd; /* ETHTOOL_TEST */
__u32 flags; /* ETH_TEST_FL_xxx */
__u32 reserved;
__u32 len; /* result length, in number of u64 elements */
__u64 data[0];
};
/* for dumping NIC-specific statistics */
struct ethtool_stats {
__u32 cmd; /* ETHTOOL_GSTATS */
__u32 n_stats; /* number of u64's being returned */
__u64 data[0];
};
struct ethtool_perm_addr {
__u32 cmd; /* ETHTOOL_GPERMADDR */
__u32 size;
__u8 data[0];
};
/* boolean flags controlling per-interface behavior characteristics.
* When reading, the flag indicates whether or not a certain behavior
* is enabled/present. When writing, the flag indicates whether
* or not the driver should turn on (set) or off (clear) a behavior.
*
* Some behaviors may read-only (unconditionally absent or present).
* If such is the case, return EINVAL in the set-flags operation if the
* flag differs from the read-only value.
*/
enum ethtool_flags {
ETH_FLAG_TXVLAN = (1 << 7), /* TX VLAN offload enabled */
ETH_FLAG_RXVLAN = (1 << 8), /* RX VLAN offload enabled */
ETH_FLAG_LRO = (1 << 15), /* LRO is enabled */
ETH_FLAG_NTUPLE = (1 << 27), /* N-tuple filters enabled */
ETH_FLAG_RXHASH = (1 << 28),
};
/* The following structures are for supporting RX network flow
* classification and RX n-tuple configuration. Note, all multibyte
* fields, e.g., ip4src, ip4dst, psrc, pdst, spi, etc. are expected to
* be in network byte order.
*/
/**
* struct ethtool_tcpip4_spec - flow specification for TCP/IPv4 etc.
* @ip4src: Source host
* @ip4dst: Destination host
* @psrc: Source port
* @pdst: Destination port
* @tos: Type-of-service
*
* This can be used to specify a TCP/IPv4, UDP/IPv4 or SCTP/IPv4 flow.
*/
struct ethtool_tcpip4_spec {
__be32 ip4src;
__be32 ip4dst;
__be16 psrc;
__be16 pdst;
__u8 tos;
};
/**
* struct ethtool_ah_espip4_spec - flow specification for IPsec/IPv4
* @ip4src: Source host
* @ip4dst: Destination host
* @spi: Security parameters index
* @tos: Type-of-service
*
* This can be used to specify an IPsec transport or tunnel over IPv4.
*/
struct ethtool_ah_espip4_spec {
__be32 ip4src;
__be32 ip4dst;
__be32 spi;
__u8 tos;
};
#define ETH_RX_NFC_IP4 1
/**
* struct ethtool_usrip4_spec - general flow specification for IPv4
* @ip4src: Source host
* @ip4dst: Destination host
* @l4_4_bytes: First 4 bytes of transport (layer 4) header
* @tos: Type-of-service
* @ip_ver: Value must be %ETH_RX_NFC_IP4; mask must be 0
* @proto: Transport protocol number; mask must be 0
*/
struct ethtool_usrip4_spec {
__be32 ip4src;
__be32 ip4dst;
__be32 l4_4_bytes;
__u8 tos;
__u8 ip_ver;
__u8 proto;
};
/**
* struct ethtool_rxfh_indir - command to get or set RX flow hash indirection
* @cmd: Specific command number - %ETHTOOL_GRXFHINDIR or %ETHTOOL_SRXFHINDIR
* @size: On entry, the array size of the user buffer. On return from
* %ETHTOOL_GRXFHINDIR, the array size of the hardware indirection table.
* @ring_index: RX ring/queue index for each hash value
*/
struct ethtool_rxfh_indir {
__u32 cmd;
__u32 size;
__u32 ring_index[0];
};
#define ETHTOOL_FLASH_MAX_FILENAME 128
enum ethtool_flash_op_type {
ETHTOOL_FLASH_ALL_REGIONS = 0,
};
/* for passing firmware flashing related parameters */
struct ethtool_flash {
__u32 cmd;
__u32 region;
char data[ETHTOOL_FLASH_MAX_FILENAME];
};
/* for returning and changing feature sets */
/**
* struct ethtool_get_features_block - block with state of 32 features
* @available: mask of changeable features
* @requested: mask of features requested to be enabled if possible
* @active: mask of currently enabled features
* @never_changed: mask of features not changeable for any device
*/
struct ethtool_get_features_block {
__u32 available;
__u32 requested;
__u32 active;
__u32 never_changed;
};
/**
* struct ethtool_gfeatures - command to get state of device's features
* @cmd: command number = %ETHTOOL_GFEATURES
* @size: in: number of elements in the features[] array;
* out: number of elements in features[] needed to hold all features
* @features: state of features
*/
struct ethtool_gfeatures {
__u32 cmd;
__u32 size;
struct ethtool_get_features_block features[0];
};
/**
* struct ethtool_set_features_block - block with request for 32 features
* @valid: mask of features to be changed
* @requested: values of features to be changed
*/
struct ethtool_set_features_block {
__u32 valid;
__u32 requested;
};
/**
* struct ethtool_sfeatures - command to request change in device's features
* @cmd: command number = %ETHTOOL_SFEATURES
* @size: array size of the features[] array
* @features: feature change masks
*/
struct ethtool_sfeatures {
__u32 cmd;
__u32 size;
struct ethtool_set_features_block features[0];
};
/*
* %ETHTOOL_SFEATURES changes features present in features[].valid to the
* values of corresponding bits in features[].requested. Bits in .requested
* not set in .valid or not changeable are ignored.
*
* Returns %EINVAL when .valid contains undefined or never-changable bits
* or size is not equal to required number of features words (32-bit blocks).
* Returns >= 0 if request was completed; bits set in the value mean:
* %ETHTOOL_F_UNSUPPORTED - there were bits set in .valid that are not
* changeable (not present in %ETHTOOL_GFEATURES' features[].available)
* those bits were ignored.
* %ETHTOOL_F_WISH - some or all changes requested were recorded but the
* resulting state of bits masked by .valid is not equal to .requested.
* Probably there are other device-specific constraints on some features
* in the set. When %ETHTOOL_F_UNSUPPORTED is set, .valid is considered
* here as though ignored bits were cleared.
* %ETHTOOL_F_COMPAT - some or all changes requested were made by calling
* compatibility functions. Requested offload state cannot be properly
* managed by kernel.
*
* Meaning of bits in the masks are obtained by %ETHTOOL_GSSET_INFO (number of
* bits in the arrays - always multiple of 32) and %ETHTOOL_GSTRINGS commands
* for ETH_SS_FEATURES string set. First entry in the table corresponds to least
* significant bit in features[0] fields. Empty strings mark undefined features.
*/
enum ethtool_sfeatures_retval_bits {
ETHTOOL_F_UNSUPPORTED__BIT,
ETHTOOL_F_WISH__BIT,
ETHTOOL_F_COMPAT__BIT,
};
#define ETHTOOL_F_UNSUPPORTED (1 << ETHTOOL_F_UNSUPPORTED__BIT)
#define ETHTOOL_F_WISH (1 << ETHTOOL_F_WISH__BIT)
#define ETHTOOL_F_COMPAT (1 << ETHTOOL_F_COMPAT__BIT)
/* CMDs currently supported */
#define ETHTOOL_GSET 0x00000001 /* Get settings. */
#define ETHTOOL_SSET 0x00000002 /* Set settings. */
#define ETHTOOL_GDRVINFO 0x00000003 /* Get driver info. */
#define ETHTOOL_GREGS 0x00000004 /* Get NIC registers. */
#define ETHTOOL_GWOL 0x00000005 /* Get wake-on-lan options. */
#define ETHTOOL_SWOL 0x00000006 /* Set wake-on-lan options. */
#define ETHTOOL_GMSGLVL 0x00000007 /* Get driver message level */
#define ETHTOOL_SMSGLVL 0x00000008 /* Set driver msg level. */
#define ETHTOOL_NWAY_RST 0x00000009 /* Restart autonegotiation. */
/* Get link status for host, i.e. whether the interface *and* the
* physical port (if there is one) are up (ethtool_value). */
#define ETHTOOL_GLINK 0x0000000a
#define ETHTOOL_GEEPROM 0x0000000b /* Get EEPROM data */
#define ETHTOOL_SEEPROM 0x0000000c /* Set EEPROM data. */
#define ETHTOOL_GCOALESCE 0x0000000e /* Get coalesce config */
#define ETHTOOL_SCOALESCE 0x0000000f /* Set coalesce config. */
#define ETHTOOL_GRINGPARAM 0x00000010 /* Get ring parameters */
#define ETHTOOL_SRINGPARAM 0x00000011 /* Set ring parameters. */
#define ETHTOOL_GPAUSEPARAM 0x00000012 /* Get pause parameters */
#define ETHTOOL_SPAUSEPARAM 0x00000013 /* Set pause parameters. */
#define ETHTOOL_GRXCSUM 0x00000014 /* Get RX hw csum enable (ethtool_value) */
#define ETHTOOL_SRXCSUM 0x00000015 /* Set RX hw csum enable (ethtool_value) */
#define ETHTOOL_GTXCSUM 0x00000016 /* Get TX hw csum enable (ethtool_value) */
#define ETHTOOL_STXCSUM 0x00000017 /* Set TX hw csum enable (ethtool_value) */
#define ETHTOOL_GSG 0x00000018 /* Get scatter-gather enable
* (ethtool_value) */
#define ETHTOOL_SSG 0x00000019 /* Set scatter-gather enable
* (ethtool_value). */
#define ETHTOOL_TEST 0x0000001a /* execute NIC self-test. */
#define ETHTOOL_GSTRINGS 0x0000001b /* get specified string set */
#define ETHTOOL_PHYS_ID 0x0000001c /* identify the NIC */
#define ETHTOOL_GSTATS 0x0000001d /* get NIC-specific statistics */
#define ETHTOOL_GTSO 0x0000001e /* Get TSO enable (ethtool_value) */
#define ETHTOOL_STSO 0x0000001f /* Set TSO enable (ethtool_value) */
#define ETHTOOL_GPERMADDR 0x00000020 /* Get permanent hardware address */
#define ETHTOOL_GUFO 0x00000021 /* Get UFO enable (ethtool_value) */
#define ETHTOOL_SUFO 0x00000022 /* Set UFO enable (ethtool_value) */
#define ETHTOOL_GGSO 0x00000023 /* Get GSO enable (ethtool_value) */
#define ETHTOOL_SGSO 0x00000024 /* Set GSO enable (ethtool_value) */
#define ETHTOOL_GFLAGS 0x00000025 /* Get flags bitmap(ethtool_value) */
#define ETHTOOL_SFLAGS 0x00000026 /* Set flags bitmap(ethtool_value) */
#define ETHTOOL_GPFLAGS 0x00000027 /* Get driver-private flags bitmap */
#define ETHTOOL_SPFLAGS 0x00000028 /* Set driver-private flags bitmap */
#define ETHTOOL_GRXFH 0x00000029 /* Get RX flow hash configuration */
#define ETHTOOL_SRXFH 0x0000002a /* Set RX flow hash configuration */
#define ETHTOOL_GGRO 0x0000002b /* Get GRO enable (ethtool_value) */
#define ETHTOOL_SGRO 0x0000002c /* Set GRO enable (ethtool_value) */
#define ETHTOOL_GRXRINGS 0x0000002d /* Get RX rings available for LB */
#define ETHTOOL_GRXCLSRLCNT 0x0000002e /* Get RX class rule count */
#define ETHTOOL_GRXCLSRULE 0x0000002f /* Get RX classification rule */
#define ETHTOOL_GRXCLSRLALL 0x00000030 /* Get all RX classification rule */
#define ETHTOOL_SRXCLSRLDEL 0x00000031 /* Delete RX classification rule */
#define ETHTOOL_SRXCLSRLINS 0x00000032 /* Insert RX classification rule */
#define ETHTOOL_FLASHDEV 0x00000033 /* Flash firmware to device */
#define ETHTOOL_RESET 0x00000034 /* Reset hardware */
#define ETHTOOL_SRXNTUPLE 0x00000035 /* Add an n-tuple filter to device */
#define ETHTOOL_GRXNTUPLE 0x00000036 /* Get n-tuple filters from device */
#define ETHTOOL_GSSET_INFO 0x00000037 /* Get string set info */
#define ETHTOOL_GRXFHINDIR 0x00000038 /* Get RX flow hash indir'n table */
#define ETHTOOL_SRXFHINDIR 0x00000039 /* Set RX flow hash indir'n table */
#define ETHTOOL_GFEATURES 0x0000003a /* Get device offload settings */
#define ETHTOOL_SFEATURES 0x0000003b /* Change device offload settings */
/* compatibility with older code */
#define SPARC_ETH_GSET ETHTOOL_GSET
#define SPARC_ETH_SSET ETHTOOL_SSET
/* Indicates what features are supported by the interface. */
#define SUPPORTED_10baseT_Half (1 << 0)
#define SUPPORTED_10baseT_Full (1 << 1)
#define SUPPORTED_100baseT_Half (1 << 2)
#define SUPPORTED_100baseT_Full (1 << 3)
#define SUPPORTED_1000baseT_Half (1 << 4)
#define SUPPORTED_1000baseT_Full (1 << 5)
#define SUPPORTED_Autoneg (1 << 6)
#define SUPPORTED_TP (1 << 7)
#define SUPPORTED_AUI (1 << 8)
#define SUPPORTED_MII (1 << 9)
#define SUPPORTED_FIBRE (1 << 10)
#define SUPPORTED_BNC (1 << 11)
#define SUPPORTED_10000baseT_Full (1 << 12)
#define SUPPORTED_Pause (1 << 13)
#define SUPPORTED_Asym_Pause (1 << 14)
#define SUPPORTED_2500baseX_Full (1 << 15)
#define SUPPORTED_Backplane (1 << 16)
#define SUPPORTED_1000baseKX_Full (1 << 17)
#define SUPPORTED_10000baseKX4_Full (1 << 18)
#define SUPPORTED_10000baseKR_Full (1 << 19)
#define SUPPORTED_10000baseR_FEC (1 << 20)
/* Indicates what features are advertised by the interface. */
#define ADVERTISED_10baseT_Half (1 << 0)
#define ADVERTISED_10baseT_Full (1 << 1)
#define ADVERTISED_100baseT_Half (1 << 2)
#define ADVERTISED_100baseT_Full (1 << 3)
#define ADVERTISED_1000baseT_Half (1 << 4)
#define ADVERTISED_1000baseT_Full (1 << 5)
#define ADVERTISED_Autoneg (1 << 6)
#define ADVERTISED_TP (1 << 7)
#define ADVERTISED_AUI (1 << 8)
#define ADVERTISED_MII (1 << 9)
#define ADVERTISED_FIBRE (1 << 10)
#define ADVERTISED_BNC (1 << 11)
#define ADVERTISED_10000baseT_Full (1 << 12)
#define ADVERTISED_Pause (1 << 13)
#define ADVERTISED_Asym_Pause (1 << 14)
#define ADVERTISED_2500baseX_Full (1 << 15)
#define ADVERTISED_Backplane (1 << 16)
#define ADVERTISED_1000baseKX_Full (1 << 17)
#define ADVERTISED_10000baseKX4_Full (1 << 18)
#define ADVERTISED_10000baseKR_Full (1 << 19)
#define ADVERTISED_10000baseR_FEC (1 << 20)
/* The following are all involved in forcing a particular link
* mode for the device for setting things. When getting the
* devices settings, these indicate the current mode and whether
* it was foced up into this mode or autonegotiated.
*/
/* The forced speed, 10Mb, 100Mb, gigabit, 2.5Gb, 10GbE. */
#define SPEED_10 10
#define SPEED_100 100
#define SPEED_1000 1000
#define SPEED_2500 2500
#define SPEED_10000 10000
/* Duplex, half or full. */
#define DUPLEX_HALF 0x00
#define DUPLEX_FULL 0x01
/* Which connector port. */
#define PORT_TP 0x00
#define PORT_AUI 0x01
#define PORT_MII 0x02
#define PORT_FIBRE 0x03
#define PORT_BNC 0x04
#define PORT_DA 0x05
#define PORT_NONE 0xef
#define PORT_OTHER 0xff
/* Which transceiver to use. */
#define XCVR_INTERNAL 0x00
#define XCVR_EXTERNAL 0x01
#define XCVR_DUMMY1 0x02
#define XCVR_DUMMY2 0x03
#define XCVR_DUMMY3 0x04
/* Enable or disable autonegotiation. If this is set to enable,
* the forced link modes above are completely ignored.
*/
#define AUTONEG_DISABLE 0x00
#define AUTONEG_ENABLE 0x01
/* Mode MDI or MDI-X */
#define ETH_TP_MDI_INVALID 0x00
#define ETH_TP_MDI 0x01
#define ETH_TP_MDI_X 0x02
/* Wake-On-Lan options. */
#define WAKE_PHY (1 << 0)
#define WAKE_UCAST (1 << 1)
#define WAKE_MCAST (1 << 2)
#define WAKE_BCAST (1 << 3)
#define WAKE_ARP (1 << 4)
#define WAKE_MAGIC (1 << 5)
#define WAKE_MAGICSECURE (1 << 6) /* only meaningful if WAKE_MAGIC */
/* L2-L4 network traffic flow types */
#define TCP_V4_FLOW 0x01 /* hash or spec (tcp_ip4_spec) */
#define UDP_V4_FLOW 0x02 /* hash or spec (udp_ip4_spec) */
#define SCTP_V4_FLOW 0x03 /* hash or spec (sctp_ip4_spec) */
#define AH_ESP_V4_FLOW 0x04 /* hash only */
#define TCP_V6_FLOW 0x05 /* hash only */
#define UDP_V6_FLOW 0x06 /* hash only */
#define SCTP_V6_FLOW 0x07 /* hash only */
#define AH_ESP_V6_FLOW 0x08 /* hash only */
#define AH_V4_FLOW 0x09 /* hash or spec (ah_ip4_spec) */
#define ESP_V4_FLOW 0x0a /* hash or spec (esp_ip4_spec) */
#define AH_V6_FLOW 0x0b /* hash only */
#define ESP_V6_FLOW 0x0c /* hash only */
#define IP_USER_FLOW 0x0d /* spec only (usr_ip4_spec) */
#define IPV4_FLOW 0x10 /* hash only */
#define IPV6_FLOW 0x11 /* hash only */
#define ETHER_FLOW 0x12 /* spec only (ether_spec) */
/* L3-L4 network traffic flow hash options */
#define RXH_L2DA (1 << 1)
#define RXH_VLAN (1 << 2)
#define RXH_L3_PROTO (1 << 3)
#define RXH_IP_SRC (1 << 4)
#define RXH_IP_DST (1 << 5)
#define RXH_L4_B_0_1 (1 << 6) /* src port in case of TCP/UDP/SCTP */
#define RXH_L4_B_2_3 (1 << 7) /* dst port in case of TCP/UDP/SCTP */
#define RXH_DISCARD (1 << 31)
#define RX_CLS_FLOW_DISC 0xffffffffffffffffULL
/* Reset flags */
/* The reset() operation must clear the flags for the components which
* were actually reset. On successful return, the flags indicate the
* components which were not reset, either because they do not exist
* in the hardware or because they cannot be reset independently. The
* driver must never reset any components that were not requested.
*/
enum ethtool_reset_flags {
/* These flags represent components dedicated to the interface
* the command is addressed to. Shift any flag left by
* ETH_RESET_SHARED_SHIFT to reset a shared component of the
* same type.
*/
ETH_RESET_MGMT = 1 << 0, /* Management processor */
ETH_RESET_IRQ = 1 << 1, /* Interrupt requester */
ETH_RESET_DMA = 1 << 2, /* DMA engine */
ETH_RESET_FILTER = 1 << 3, /* Filtering/flow direction */
ETH_RESET_OFFLOAD = 1 << 4, /* Protocol offload */
ETH_RESET_MAC = 1 << 5, /* Media access controller */
ETH_RESET_PHY = 1 << 6, /* Transceiver/PHY */
ETH_RESET_RAM = 1 << 7, /* RAM shared between
* multiple components */
ETH_RESET_DEDICATED = 0x0000ffff, /* All components dedicated to
* this interface */
ETH_RESET_ALL = 0xffffffff, /* All components used by this
* interface, even if shared */
};
#define ETH_RESET_SHARED_SHIFT 16
#endif /* _LINUX_ETHTOOL_H */

278
include/linux/mdio.h Normal file
View file

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

View file

@ -34,35 +34,52 @@
#ifndef _miiphy_h_
#define _miiphy_h_
#include <common.h>
#include <linux/mii.h>
#include <linux/list.h>
#include <net.h>
#include <phy.h>
int miiphy_read (const char *devname, unsigned char addr, unsigned char reg,
struct legacy_mii_dev {
int (*read)(const char *devname, unsigned char addr,
unsigned char reg, unsigned short *value);
int (*write)(const char *devname, unsigned char addr,
unsigned char reg, unsigned short value);
};
int miiphy_read(const char *devname, unsigned char addr, unsigned char reg,
unsigned short *value);
int miiphy_write (const char *devname, unsigned char addr, unsigned char reg,
int miiphy_write(const char *devname, unsigned char addr, unsigned char reg,
unsigned short value);
int miiphy_info (const char *devname, unsigned char addr, unsigned int *oui,
int miiphy_info(const char *devname, unsigned char addr, unsigned int *oui,
unsigned char *model, unsigned char *rev);
int miiphy_reset (const char *devname, unsigned char addr);
int miiphy_speed (const char *devname, unsigned char addr);
int miiphy_duplex (const char *devname, unsigned char addr);
int miiphy_is_1000base_x (const char *devname, unsigned char addr);
int miiphy_reset(const char *devname, unsigned char addr);
int miiphy_speed(const char *devname, unsigned char addr);
int miiphy_duplex(const char *devname, unsigned char addr);
int miiphy_is_1000base_x(const char *devname, unsigned char addr);
#ifdef CONFIG_SYS_FAULT_ECHO_LINK_DOWN
int miiphy_link (const char *devname, unsigned char addr);
int miiphy_link(const char *devname, unsigned char addr);
#endif
void miiphy_init (void);
void miiphy_init(void);
void miiphy_register (const char *devname,
int (*read) (const char *devname, unsigned char addr,
void miiphy_register(const char *devname,
int (*read)(const char *devname, unsigned char addr,
unsigned char reg, unsigned short *value),
int (*write) (const char *devname, unsigned char addr,
int (*write)(const char *devname, unsigned char addr,
unsigned char reg, unsigned short value));
int miiphy_set_current_dev (const char *devname);
const char *miiphy_get_current_dev (void);
int miiphy_set_current_dev(const char *devname);
const char *miiphy_get_current_dev(void);
struct mii_dev *mdio_get_current_dev(void);
struct mii_dev *miiphy_get_dev_by_name(const char *devname);
struct phy_device *mdio_phydev_for_ethname(const char *devname);
void miiphy_listdev (void);
void miiphy_listdev(void);
struct mii_dev *mdio_alloc(void);
int mdio_register(struct mii_dev *bus);
void mdio_list_devices(void);
#ifdef CONFIG_BITBANGMII
@ -85,10 +102,10 @@ struct bb_miiphy_bus {
extern struct bb_miiphy_bus bb_miiphy_buses[];
extern int bb_miiphy_buses_num;
void bb_miiphy_init (void);
int bb_miiphy_read (const char *devname, unsigned char addr,
void bb_miiphy_init(void);
int bb_miiphy_read(const char *devname, unsigned char addr,
unsigned char reg, unsigned short *value);
int bb_miiphy_write (const char *devname, unsigned char addr,
int bb_miiphy_write(const char *devname, unsigned char addr,
unsigned char reg, unsigned short value);
#endif

229
include/phy.h Normal file
View file

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

View file

@ -7,7 +7,7 @@
* terms of the GNU Public License, Version 2, incorporated
* herein by reference.
*
* Copyright 2004, 2007, 2009 Freescale Semiconductor, Inc.
* Copyright 2004, 2007, 2009, 2011 Freescale Semiconductor, Inc.
* (C) Copyright 2003, Motorola, Inc.
* maintained by Xianghua Xiao (x.xiao@motorola.com)
* author Andy Fleming
@ -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;
};

View file

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