mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-25 22:20:45 +00:00
Merge branch 'phylib' of git://git.denx.de/u-boot-mmc
This commit is contained in:
commit
aef293bc85
52 changed files with 5085 additions and 2505 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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: "
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 "
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
286
common/cmd_mdio.c
Normal 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,
|
||||
®lo, ®hi))
|
||||
return -1;
|
||||
|
||||
default:
|
||||
if (pos > 1)
|
||||
if (extract_phy_range(&(argv[2]), pos - 1, &bus,
|
||||
&addrlo, &addrhi))
|
||||
return -1;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (op[0] == 'l') {
|
||||
mdio_list_devices();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Save the chosen bus */
|
||||
miiphy_set_current_dev(bus->name);
|
||||
|
||||
switch (op[0]) {
|
||||
case 'w':
|
||||
mdio_write_ranges(bus, addrlo, addrhi, devadlo, devadhi,
|
||||
reglo, reghi, data);
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
mdio_read_ranges(bus, addrlo, addrhi, devadlo, devadhi,
|
||||
reglo, reghi);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save the parameters for repeats.
|
||||
*/
|
||||
last_op[0] = op[0];
|
||||
last_addr_lo = addrlo;
|
||||
last_addr_hi = addrhi;
|
||||
last_devad_lo = devadlo;
|
||||
last_devad_hi = devadhi;
|
||||
last_reg_lo = reglo;
|
||||
last_reg_hi = reghi;
|
||||
last_data = data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************************************/
|
||||
|
||||
U_BOOT_CMD(
|
||||
mdio, 6, 1, do_mdio,
|
||||
"MDIO utility commands",
|
||||
"list - List MDIO buses\n"
|
||||
"mdio read <phydev> [<devad>.]<reg> - "
|
||||
"read PHY's register at <devad>.<reg>\n"
|
||||
"mdio write <phydev> [<devad>.]<reg> <data> - "
|
||||
"write PHY's register at <devad>.<reg>\n"
|
||||
"<phydev> may be:\n"
|
||||
" <busname> <addr>\n"
|
||||
" <addr>\n"
|
||||
" <eth name>\n"
|
||||
"<addr> <devad>, and <reg> may be ranges, e.g. 1-5.4-0x1f.\n"
|
||||
);
|
|
@ -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, ®) != 0) {
|
||||
debug ("PHY status read failed\n");
|
||||
return (-1);
|
||||
if (miiphy_read(devname, addr, MII_BMCR, ®) != 0) {
|
||||
debug("PHY status read failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (miiphy_write (devname, addr, MII_BMCR, reg | BMCR_RESET) != 0) {
|
||||
debug ("PHY reset failed\n");
|
||||
return (-1);
|
||||
if (miiphy_write(devname, addr, MII_BMCR, reg | BMCR_RESET) != 0) {
|
||||
debug("PHY reset failed\n");
|
||||
return -1;
|
||||
}
|
||||
#ifdef CONFIG_PHY_RESET_DELAY
|
||||
udelay (CONFIG_PHY_RESET_DELAY); /* Intel LXT971A needs this */
|
||||
udelay(CONFIG_PHY_RESET_DELAY); /* Intel LXT971A needs this */
|
||||
#endif
|
||||
/*
|
||||
* Poll the control register for the reset bit to go to 0 (it is
|
||||
|
@ -315,13 +424,14 @@ int miiphy_reset(const char *devname, unsigned char addr)
|
|||
udelay(1000);
|
||||
}
|
||||
if ((reg & 0x8000) == 0) {
|
||||
return (0);
|
||||
return 0;
|
||||
} else {
|
||||
puts ("PHY reset timed out\n");
|
||||
return (-1);
|
||||
puts("PHY reset timed out\n");
|
||||
return -1;
|
||||
}
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
#endif /* !PHYLIB */
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
|
@ -338,33 +448,32 @@ int miiphy_speed(const char *devname, unsigned char addr)
|
|||
* Check for 1000BASE-X. If it is supported, then assume that the speed
|
||||
* is 1000.
|
||||
*/
|
||||
if (miiphy_is_1000base_x (devname, addr)) {
|
||||
if (miiphy_is_1000base_x(devname, addr))
|
||||
return _1000BASET;
|
||||
}
|
||||
|
||||
/*
|
||||
* No 1000BASE-X, so assume 1000BASE-T/100BASE-TX/10BASE-T register set.
|
||||
*/
|
||||
/* Check for 1000BASE-T. */
|
||||
if (miiphy_read (devname, addr, MII_STAT1000, &btsr)) {
|
||||
printf ("PHY 1000BT status");
|
||||
if (miiphy_read(devname, addr, MII_STAT1000, &btsr)) {
|
||||
printf("PHY 1000BT status");
|
||||
goto miiphy_read_failed;
|
||||
}
|
||||
if (btsr != 0xFFFF &&
|
||||
(btsr & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD))) {
|
||||
(btsr & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD)))
|
||||
return _1000BASET;
|
||||
}
|
||||
#endif /* CONFIG_PHY_GIGE */
|
||||
|
||||
/* Check Basic Management Control Register first. */
|
||||
if (miiphy_read (devname, addr, MII_BMCR, &bmcr)) {
|
||||
printf ("PHY speed");
|
||||
if (miiphy_read(devname, addr, MII_BMCR, &bmcr)) {
|
||||
printf("PHY speed");
|
||||
goto miiphy_read_failed;
|
||||
}
|
||||
/* Check if auto-negotiation is on. */
|
||||
if (bmcr & BMCR_ANENABLE) {
|
||||
/* Get auto-negotiation results. */
|
||||
if (miiphy_read (devname, addr, MII_LPA, &anlpar)) {
|
||||
printf ("PHY AN speed");
|
||||
if (miiphy_read(devname, addr, MII_LPA, &anlpar)) {
|
||||
printf("PHY AN speed");
|
||||
goto miiphy_read_failed;
|
||||
}
|
||||
return (anlpar & LPA_100) ? _100BASET : _10BASET;
|
||||
|
@ -373,7 +482,7 @@ int miiphy_speed(const char *devname, unsigned char addr)
|
|||
return (bmcr & BMCR_SPEED100) ? _100BASET : _10BASET;
|
||||
|
||||
miiphy_read_failed:
|
||||
printf (" read failed, assuming 10BASE-T\n");
|
||||
printf(" read failed, assuming 10BASE-T\n");
|
||||
return _10BASET;
|
||||
}
|
||||
|
||||
|
@ -389,10 +498,10 @@ int miiphy_duplex(const char *devname, unsigned char addr)
|
|||
u16 btsr;
|
||||
|
||||
/* Check for 1000BASE-X. */
|
||||
if (miiphy_is_1000base_x (devname, addr)) {
|
||||
if (miiphy_is_1000base_x(devname, addr)) {
|
||||
/* 1000BASE-X */
|
||||
if (miiphy_read (devname, addr, MII_LPA, &anlpar)) {
|
||||
printf ("1000BASE-X PHY AN duplex");
|
||||
if (miiphy_read(devname, addr, MII_LPA, &anlpar)) {
|
||||
printf("1000BASE-X PHY AN duplex");
|
||||
goto miiphy_read_failed;
|
||||
}
|
||||
}
|
||||
|
@ -400,8 +509,8 @@ int miiphy_duplex(const char *devname, unsigned char addr)
|
|||
* No 1000BASE-X, so assume 1000BASE-T/100BASE-TX/10BASE-T register set.
|
||||
*/
|
||||
/* Check for 1000BASE-T. */
|
||||
if (miiphy_read (devname, addr, MII_STAT1000, &btsr)) {
|
||||
printf ("PHY 1000BT status");
|
||||
if (miiphy_read(devname, addr, MII_STAT1000, &btsr)) {
|
||||
printf("PHY 1000BT status");
|
||||
goto miiphy_read_failed;
|
||||
}
|
||||
if (btsr != 0xFFFF) {
|
||||
|
@ -414,15 +523,15 @@ int miiphy_duplex(const char *devname, unsigned char addr)
|
|||
#endif /* CONFIG_PHY_GIGE */
|
||||
|
||||
/* Check Basic Management Control Register first. */
|
||||
if (miiphy_read (devname, addr, MII_BMCR, &bmcr)) {
|
||||
puts ("PHY duplex");
|
||||
if (miiphy_read(devname, addr, MII_BMCR, &bmcr)) {
|
||||
puts("PHY duplex");
|
||||
goto miiphy_read_failed;
|
||||
}
|
||||
/* Check if auto-negotiation is on. */
|
||||
if (bmcr & BMCR_ANENABLE) {
|
||||
/* Get auto-negotiation results. */
|
||||
if (miiphy_read (devname, addr, MII_LPA, &anlpar)) {
|
||||
puts ("PHY AN duplex");
|
||||
if (miiphy_read(devname, addr, MII_LPA, &anlpar)) {
|
||||
puts("PHY AN duplex");
|
||||
goto miiphy_read_failed;
|
||||
}
|
||||
return (anlpar & (LPA_10FULL | LPA_100FULL)) ?
|
||||
|
@ -432,7 +541,7 @@ int miiphy_duplex(const char *devname, unsigned char addr)
|
|||
return (bmcr & BMCR_FULLDPLX) ? FULL : HALF;
|
||||
|
||||
miiphy_read_failed:
|
||||
printf (" read failed, assuming half duplex\n");
|
||||
printf(" read failed, assuming half duplex\n");
|
||||
return HALF;
|
||||
}
|
||||
|
||||
|
@ -446,8 +555,8 @@ int miiphy_is_1000base_x(const char *devname, unsigned char addr)
|
|||
#if defined(CONFIG_PHY_GIGE)
|
||||
u16 exsr;
|
||||
|
||||
if (miiphy_read (devname, addr, MII_ESTATUS, &exsr)) {
|
||||
printf ("PHY extended status read failed, assuming no "
|
||||
if (miiphy_read(devname, addr, MII_ESTATUS, &exsr)) {
|
||||
printf("PHY extended status read failed, assuming no "
|
||||
"1000BASE-X\n");
|
||||
return 0;
|
||||
}
|
||||
|
@ -467,17 +576,17 @@ int miiphy_link(const char *devname, unsigned char addr)
|
|||
unsigned short reg;
|
||||
|
||||
/* dummy read; needed to latch some phys */
|
||||
(void)miiphy_read (devname, addr, MII_BMSR, ®);
|
||||
if (miiphy_read (devname, addr, MII_BMSR, ®)) {
|
||||
puts ("MII_BMSR read failed, assuming no link\n");
|
||||
return (0);
|
||||
(void)miiphy_read(devname, addr, MII_BMSR, ®);
|
||||
if (miiphy_read(devname, addr, MII_BMSR, ®)) {
|
||||
puts("MII_BMSR read failed, assuming no link\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Determine if a link is active */
|
||||
if ((reg & BMSR_LSTATUS) != 0) {
|
||||
return (1);
|
||||
return 1;
|
||||
} else {
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
120
drivers/net/fsl_mdio.c
Normal 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(®s->miimcfg, MIIMCFG_RESET_MGMT);
|
||||
|
||||
out_be32(®s->miimcfg, MIIMCFG_INIT_VALUE);
|
||||
|
||||
while (in_be32(®s->miimind) & MIIMIND_BUSY)
|
||||
;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tsec_phy_read(struct mii_dev *bus, int addr, int dev_addr, int regnum)
|
||||
{
|
||||
struct tsec_mii_mng *phyregs = bus->priv;
|
||||
|
||||
return tsec_local_mdio_read(phyregs, addr, dev_addr, regnum);
|
||||
}
|
||||
|
||||
int tsec_phy_write(struct mii_dev *bus, int addr, int dev_addr, int regnum,
|
||||
u16 value)
|
||||
{
|
||||
struct tsec_mii_mng *phyregs = bus->priv;
|
||||
|
||||
tsec_local_mdio_write(phyregs, addr, dev_addr, regnum, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fsl_pq_mdio_init(bd_t *bis, struct fsl_pq_mdio_info *info)
|
||||
{
|
||||
struct mii_dev *bus = mdio_alloc();
|
||||
|
||||
if (!bus) {
|
||||
printf("Failed to allocate FSL MDIO bus\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
bus->read = tsec_phy_read;
|
||||
bus->write = tsec_phy_write;
|
||||
bus->reset = fsl_pq_mdio_reset;
|
||||
sprintf(bus->name, info->name);
|
||||
|
||||
bus->priv = info->regs;
|
||||
|
||||
return mdio_register(bus);
|
||||
}
|
|
@ -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
48
drivers/net/phy/atheros.c
Normal 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
288
drivers/net/phy/broadcom.c
Normal 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
98
drivers/net/phy/davicom.c
Normal 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;
|
||||
}
|
105
drivers/net/phy/generic_10g.c
Normal file
105
drivers/net/phy/generic_10g.c
Normal 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
87
drivers/net/phy/lxt.c
Normal 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
367
drivers/net/phy/marvell.c
Normal 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
40
drivers/net/phy/micrel.c
Normal 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
96
drivers/net/phy/natsemi.c
Normal 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
755
drivers/net/phy/phy.c
Normal 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
130
drivers/net/phy/realtek.c
Normal 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;
|
||||
}
|
62
drivers/net/phy/teranetics.c
Normal file
62
drivers/net/phy/teranetics.c
Normal 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
242
drivers/net/phy/vitesse.c
Normal 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;
|
||||
}
|
2358
drivers/net/tsec.c
2358
drivers/net/tsec.c
File diff suppressed because it is too large
Load diff
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "uec.h"
|
||||
#include "uec_phy.h"
|
||||
#include "miiphy.h"
|
||||
#include <phy.h>
|
||||
|
||||
#define ugphy_printk(format, arg...) \
|
||||
printf(format "\n", ## arg)
|
||||
|
@ -121,8 +122,8 @@ static int gbit_config_aneg (struct uec_mii_info *mii_info);
|
|||
static int genmii_config_aneg (struct uec_mii_info *mii_info);
|
||||
static int genmii_update_link (struct uec_mii_info *mii_info);
|
||||
static int genmii_read_status (struct uec_mii_info *mii_info);
|
||||
u16 phy_read (struct uec_mii_info *mii_info, u16 regnum);
|
||||
void phy_write (struct uec_mii_info *mii_info, u16 regnum, u16 val);
|
||||
u16 uec_phy_read(struct uec_mii_info *mii_info, u16 regnum);
|
||||
void uec_phy_write(struct uec_mii_info *mii_info, u16 regnum, u16 val);
|
||||
|
||||
/* Write value to the PHY for this device to the register at regnum, */
|
||||
/* waiting until the write is done before it returns. All PHY */
|
||||
|
@ -242,7 +243,7 @@ static void config_genmii_advert (struct uec_mii_info *mii_info)
|
|||
advertise = mii_info->advertising;
|
||||
|
||||
/* Setup standard advertisement */
|
||||
adv = phy_read (mii_info, MII_ADVERTISE);
|
||||
adv = uec_phy_read(mii_info, MII_ADVERTISE);
|
||||
adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
|
||||
if (advertise & ADVERTISED_10baseT_Half)
|
||||
adv |= ADVERTISE_10HALF;
|
||||
|
@ -252,7 +253,7 @@ static void config_genmii_advert (struct uec_mii_info *mii_info)
|
|||
adv |= ADVERTISE_100HALF;
|
||||
if (advertise & ADVERTISED_100baseT_Full)
|
||||
adv |= ADVERTISE_100FULL;
|
||||
phy_write (mii_info, MII_ADVERTISE, adv);
|
||||
uec_phy_write(mii_info, MII_ADVERTISE, adv);
|
||||
}
|
||||
|
||||
static void genmii_setup_forced (struct uec_mii_info *mii_info)
|
||||
|
@ -260,7 +261,7 @@ static void genmii_setup_forced (struct uec_mii_info *mii_info)
|
|||
u16 ctrl;
|
||||
u32 features = mii_info->phyinfo->features;
|
||||
|
||||
ctrl = phy_read (mii_info, MII_BMCR);
|
||||
ctrl = uec_phy_read(mii_info, MII_BMCR);
|
||||
|
||||
ctrl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 |
|
||||
BMCR_SPEED1000 | BMCR_ANENABLE);
|
||||
|
@ -290,7 +291,7 @@ static void genmii_setup_forced (struct uec_mii_info *mii_info)
|
|||
break;
|
||||
}
|
||||
|
||||
phy_write (mii_info, MII_BMCR, ctrl);
|
||||
uec_phy_write(mii_info, MII_BMCR, ctrl);
|
||||
}
|
||||
|
||||
/* Enable and Restart Autonegotiation */
|
||||
|
@ -298,9 +299,9 @@ static void genmii_restart_aneg (struct uec_mii_info *mii_info)
|
|||
{
|
||||
u16 ctl;
|
||||
|
||||
ctl = phy_read (mii_info, MII_BMCR);
|
||||
ctl = uec_phy_read(mii_info, MII_BMCR);
|
||||
ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
|
||||
phy_write (mii_info, MII_BMCR, ctl);
|
||||
uec_phy_write(mii_info, MII_BMCR, ctl);
|
||||
}
|
||||
|
||||
static int gbit_config_aneg (struct uec_mii_info *mii_info)
|
||||
|
@ -313,14 +314,14 @@ static int gbit_config_aneg (struct uec_mii_info *mii_info)
|
|||
config_genmii_advert (mii_info);
|
||||
advertise = mii_info->advertising;
|
||||
|
||||
adv = phy_read (mii_info, MII_CTRL1000);
|
||||
adv = uec_phy_read(mii_info, MII_CTRL1000);
|
||||
adv &= ~(ADVERTISE_1000FULL |
|
||||
ADVERTISE_1000HALF);
|
||||
if (advertise & SUPPORTED_1000baseT_Half)
|
||||
adv |= ADVERTISE_1000HALF;
|
||||
if (advertise & SUPPORTED_1000baseT_Full)
|
||||
adv |= ADVERTISE_1000FULL;
|
||||
phy_write (mii_info, MII_CTRL1000, adv);
|
||||
uec_phy_write(mii_info, MII_CTRL1000, adv);
|
||||
|
||||
/* Start/Restart aneg */
|
||||
genmii_restart_aneg (mii_info);
|
||||
|
@ -335,13 +336,13 @@ static int marvell_config_aneg (struct uec_mii_info *mii_info)
|
|||
/* The Marvell PHY has an errata which requires
|
||||
* that certain registers get written in order
|
||||
* to restart autonegotiation */
|
||||
phy_write (mii_info, MII_BMCR, BMCR_RESET);
|
||||
uec_phy_write(mii_info, MII_BMCR, BMCR_RESET);
|
||||
|
||||
phy_write (mii_info, 0x1d, 0x1f);
|
||||
phy_write (mii_info, 0x1e, 0x200c);
|
||||
phy_write (mii_info, 0x1d, 0x5);
|
||||
phy_write (mii_info, 0x1e, 0);
|
||||
phy_write (mii_info, 0x1e, 0x100);
|
||||
uec_phy_write(mii_info, 0x1d, 0x1f);
|
||||
uec_phy_write(mii_info, 0x1e, 0x200c);
|
||||
uec_phy_write(mii_info, 0x1d, 0x5);
|
||||
uec_phy_write(mii_info, 0x1e, 0);
|
||||
uec_phy_write(mii_info, 0x1e, 0x100);
|
||||
|
||||
gbit_config_aneg (mii_info);
|
||||
|
||||
|
@ -373,13 +374,13 @@ static int genmii_update_link (struct uec_mii_info *mii_info)
|
|||
u16 status;
|
||||
|
||||
/* Status is read once to clear old link state */
|
||||
phy_read (mii_info, MII_BMSR);
|
||||
uec_phy_read(mii_info, MII_BMSR);
|
||||
|
||||
/*
|
||||
* Wait if the link is up, and autonegotiation is in progress
|
||||
* (ie - we're capable and it's not done)
|
||||
*/
|
||||
status = phy_read(mii_info, MII_BMSR);
|
||||
status = uec_phy_read(mii_info, MII_BMSR);
|
||||
if ((status & BMSR_LSTATUS) && (status & BMSR_ANEGCAPABLE)
|
||||
&& !(status & BMSR_ANEGCOMPLETE)) {
|
||||
int i = 0;
|
||||
|
@ -395,7 +396,7 @@ static int genmii_update_link (struct uec_mii_info *mii_info)
|
|||
|
||||
i++;
|
||||
udelay(1000); /* 1 ms */
|
||||
status = phy_read(mii_info, MII_BMSR);
|
||||
status = uec_phy_read(mii_info, MII_BMSR);
|
||||
}
|
||||
mii_info->link = 1;
|
||||
} else {
|
||||
|
@ -420,7 +421,7 @@ static int genmii_read_status (struct uec_mii_info *mii_info)
|
|||
return err;
|
||||
|
||||
if (mii_info->autoneg) {
|
||||
status = phy_read(mii_info, MII_STAT1000);
|
||||
status = uec_phy_read(mii_info, MII_STAT1000);
|
||||
|
||||
if (status & (LPA_1000FULL | LPA_1000HALF)) {
|
||||
mii_info->speed = SPEED_1000;
|
||||
|
@ -429,7 +430,7 @@ static int genmii_read_status (struct uec_mii_info *mii_info)
|
|||
else
|
||||
mii_info->duplex = DUPLEX_HALF;
|
||||
} else {
|
||||
status = phy_read(mii_info, MII_LPA);
|
||||
status = uec_phy_read(mii_info, MII_LPA);
|
||||
|
||||
if (status & (LPA_10FULL | LPA_100FULL))
|
||||
mii_info->duplex = DUPLEX_FULL;
|
||||
|
@ -456,62 +457,63 @@ static int bcm_init(struct uec_mii_info *mii_info)
|
|||
|
||||
gbit_config_aneg(mii_info);
|
||||
|
||||
if ((uec->uec_info->enet_interface_type == RGMII_RXID) &&
|
||||
(uec->uec_info->speed == 1000)) {
|
||||
if ((uec->uec_info->enet_interface_type ==
|
||||
PHY_INTERFACE_MODE_RGMII_RXID) &&
|
||||
(uec->uec_info->speed == SPEED_1000)) {
|
||||
u16 val;
|
||||
int cnt = 50;
|
||||
|
||||
/* Wait for aneg to complete. */
|
||||
do
|
||||
val = phy_read(mii_info, MII_BMSR);
|
||||
val = uec_phy_read(mii_info, MII_BMSR);
|
||||
while (--cnt && !(val & BMSR_ANEGCOMPLETE));
|
||||
|
||||
/* Set RDX clk delay. */
|
||||
phy_write(mii_info, 0x18, 0x7 | (7 << 12));
|
||||
uec_phy_write(mii_info, 0x18, 0x7 | (7 << 12));
|
||||
|
||||
val = phy_read(mii_info, 0x18);
|
||||
val = uec_phy_read(mii_info, 0x18);
|
||||
/* Set RDX-RXC skew. */
|
||||
val |= (1 << 8);
|
||||
val |= (7 | (7 << 12));
|
||||
/* Write bits 14:0. */
|
||||
val |= (1 << 15);
|
||||
phy_write(mii_info, 0x18, val);
|
||||
uec_phy_write(mii_info, 0x18, val);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int marvell_init(struct uec_mii_info *mii_info)
|
||||
static int uec_marvell_init(struct uec_mii_info *mii_info)
|
||||
{
|
||||
struct eth_device *edev = mii_info->dev;
|
||||
uec_private_t *uec = edev->priv;
|
||||
enum fsl_phy_enet_if iface = uec->uec_info->enet_interface_type;
|
||||
phy_interface_t iface = uec->uec_info->enet_interface_type;
|
||||
int speed = uec->uec_info->speed;
|
||||
|
||||
if ((speed == 1000) &&
|
||||
(iface == RGMII_ID ||
|
||||
iface == RGMII_RXID ||
|
||||
iface == RGMII_TXID)) {
|
||||
if ((speed == SPEED_1000) &&
|
||||
(iface == PHY_INTERFACE_MODE_RGMII_ID ||
|
||||
iface == PHY_INTERFACE_MODE_RGMII_RXID ||
|
||||
iface == PHY_INTERFACE_MODE_RGMII_TXID)) {
|
||||
int temp;
|
||||
|
||||
temp = phy_read(mii_info, MII_M1111_PHY_EXT_CR);
|
||||
if (iface == RGMII_ID) {
|
||||
temp = uec_phy_read(mii_info, MII_M1111_PHY_EXT_CR);
|
||||
if (iface == PHY_INTERFACE_MODE_RGMII_ID) {
|
||||
temp |= MII_M1111_RX_DELAY | MII_M1111_TX_DELAY;
|
||||
} else if (iface == RGMII_RXID) {
|
||||
} else if (iface == PHY_INTERFACE_MODE_RGMII_RXID) {
|
||||
temp &= ~MII_M1111_TX_DELAY;
|
||||
temp |= MII_M1111_RX_DELAY;
|
||||
} else if (iface == RGMII_TXID) {
|
||||
} else if (iface == PHY_INTERFACE_MODE_RGMII_TXID) {
|
||||
temp &= ~MII_M1111_RX_DELAY;
|
||||
temp |= MII_M1111_TX_DELAY;
|
||||
}
|
||||
phy_write(mii_info, MII_M1111_PHY_EXT_CR, temp);
|
||||
uec_phy_write(mii_info, MII_M1111_PHY_EXT_CR, temp);
|
||||
|
||||
temp = phy_read(mii_info, MII_M1111_PHY_EXT_SR);
|
||||
temp = uec_phy_read(mii_info, MII_M1111_PHY_EXT_SR);
|
||||
temp &= ~MII_M1111_HWCFG_MODE_MASK;
|
||||
temp |= MII_M1111_HWCFG_MODE_RGMII;
|
||||
phy_write(mii_info, MII_M1111_PHY_EXT_SR, temp);
|
||||
uec_phy_write(mii_info, MII_M1111_PHY_EXT_SR, temp);
|
||||
|
||||
phy_write(mii_info, MII_BMCR, BMCR_RESET);
|
||||
uec_phy_write(mii_info, MII_BMCR, BMCR_RESET);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -534,7 +536,7 @@ static int marvell_read_status (struct uec_mii_info *mii_info)
|
|||
if (mii_info->autoneg && mii_info->link) {
|
||||
int speed;
|
||||
|
||||
status = phy_read (mii_info, MII_M1011_PHY_SPEC_STATUS);
|
||||
status = uec_phy_read(mii_info, MII_M1011_PHY_SPEC_STATUS);
|
||||
|
||||
/* Get the duplexity */
|
||||
if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
|
||||
|
@ -564,7 +566,7 @@ static int marvell_read_status (struct uec_mii_info *mii_info)
|
|||
static int marvell_ack_interrupt (struct uec_mii_info *mii_info)
|
||||
{
|
||||
/* Clear the interrupts by reading the reg */
|
||||
phy_read (mii_info, MII_M1011_IEVENT);
|
||||
uec_phy_read(mii_info, MII_M1011_IEVENT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -572,9 +574,10 @@ static int marvell_ack_interrupt (struct uec_mii_info *mii_info)
|
|||
static int marvell_config_intr (struct uec_mii_info *mii_info)
|
||||
{
|
||||
if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
|
||||
phy_write (mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
|
||||
uec_phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
|
||||
else
|
||||
phy_write (mii_info, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
|
||||
uec_phy_write(mii_info, MII_M1011_IMASK,
|
||||
MII_M1011_IMASK_CLEAR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -582,13 +585,13 @@ static int marvell_config_intr (struct uec_mii_info *mii_info)
|
|||
static int dm9161_init (struct uec_mii_info *mii_info)
|
||||
{
|
||||
/* Reset the PHY */
|
||||
phy_write (mii_info, MII_BMCR, phy_read (mii_info, MII_BMCR) |
|
||||
uec_phy_write(mii_info, MII_BMCR, uec_phy_read(mii_info, MII_BMCR) |
|
||||
BMCR_RESET);
|
||||
/* PHY and MAC connect */
|
||||
phy_write (mii_info, MII_BMCR, phy_read (mii_info, MII_BMCR) &
|
||||
uec_phy_write(mii_info, MII_BMCR, uec_phy_read(mii_info, MII_BMCR) &
|
||||
~BMCR_ISOLATE);
|
||||
|
||||
phy_write (mii_info, MII_DM9161_SCR, MII_DM9161_SCR_INIT);
|
||||
uec_phy_write(mii_info, MII_DM9161_SCR, MII_DM9161_SCR_INIT);
|
||||
|
||||
config_genmii_advert (mii_info);
|
||||
/* Start/restart aneg */
|
||||
|
@ -614,7 +617,7 @@ static int dm9161_read_status (struct uec_mii_info *mii_info)
|
|||
/* If the link is up, read the speed and duplex
|
||||
If we aren't autonegotiating assume speeds are as set */
|
||||
if (mii_info->autoneg && mii_info->link) {
|
||||
status = phy_read (mii_info, MII_DM9161_SCSR);
|
||||
status = uec_phy_read(mii_info, MII_DM9161_SCSR);
|
||||
if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_100H))
|
||||
mii_info->speed = SPEED_100;
|
||||
else
|
||||
|
@ -632,7 +635,7 @@ static int dm9161_read_status (struct uec_mii_info *mii_info)
|
|||
static int dm9161_ack_interrupt (struct uec_mii_info *mii_info)
|
||||
{
|
||||
/* Clear the interrupt by reading the reg */
|
||||
phy_read (mii_info, MII_DM9161_INTR);
|
||||
uec_phy_read(mii_info, MII_DM9161_INTR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -640,9 +643,9 @@ static int dm9161_ack_interrupt (struct uec_mii_info *mii_info)
|
|||
static int dm9161_config_intr (struct uec_mii_info *mii_info)
|
||||
{
|
||||
if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
|
||||
phy_write (mii_info, MII_DM9161_INTR, MII_DM9161_INTR_INIT);
|
||||
uec_phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_INIT);
|
||||
else
|
||||
phy_write (mii_info, MII_DM9161_INTR, MII_DM9161_INTR_STOP);
|
||||
uec_phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_STOP);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -696,7 +699,7 @@ static int smsc_read_status (struct uec_mii_info *mii_info)
|
|||
if (mii_info->autoneg && mii_info->link) {
|
||||
int val;
|
||||
|
||||
status = phy_read (mii_info, 0x1f);
|
||||
status = uec_phy_read(mii_info, 0x1f);
|
||||
val = (status & 0x1c) >> 2;
|
||||
|
||||
switch (val) {
|
||||
|
@ -751,7 +754,7 @@ static struct phy_info phy_info_marvell = {
|
|||
.phy_id_mask = 0xffffff00,
|
||||
.name = "Marvell 88E11x1",
|
||||
.features = MII_GBIT_FEATURES,
|
||||
.init = &marvell_init,
|
||||
.init = &uec_marvell_init,
|
||||
.config_aneg = &marvell_config_aneg,
|
||||
.read_status = &marvell_read_status,
|
||||
.ack_interrupt = &marvell_ack_interrupt,
|
||||
|
@ -804,12 +807,12 @@ static struct phy_info *phy_info[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
u16 phy_read (struct uec_mii_info *mii_info, u16 regnum)
|
||||
u16 uec_phy_read(struct uec_mii_info *mii_info, u16 regnum)
|
||||
{
|
||||
return mii_info->mdio_read (mii_info->dev, mii_info->mii_id, regnum);
|
||||
}
|
||||
|
||||
void phy_write (struct uec_mii_info *mii_info, u16 regnum, u16 val)
|
||||
void uec_phy_write(struct uec_mii_info *mii_info, u16 regnum, u16 val)
|
||||
{
|
||||
mii_info->mdio_write (mii_info->dev, mii_info->mii_id, regnum, val);
|
||||
}
|
||||
|
@ -825,11 +828,11 @@ struct phy_info *uec_get_phy_info (struct uec_mii_info *mii_info)
|
|||
struct phy_info *theInfo = NULL;
|
||||
|
||||
/* Grab the bits from PHYIR1, and put them in the upper half */
|
||||
phy_reg = phy_read (mii_info, MII_PHYSID1);
|
||||
phy_reg = uec_phy_read(mii_info, MII_PHYSID1);
|
||||
phy_ID = (phy_reg & 0xffff) << 16;
|
||||
|
||||
/* Grab the bits from PHYIR2, and put them in the lower half */
|
||||
phy_reg = phy_read (mii_info, MII_PHYSID2);
|
||||
phy_reg = uec_phy_read(mii_info, MII_PHYSID2);
|
||||
phy_ID |= (phy_reg & 0xffff);
|
||||
|
||||
/* loop through all the known PHY types, and find one that */
|
||||
|
@ -852,10 +855,8 @@ struct phy_info *uec_get_phy_info (struct uec_mii_info *mii_info)
|
|||
return theInfo;
|
||||
}
|
||||
|
||||
void marvell_phy_interface_mode (struct eth_device *dev,
|
||||
enum fsl_phy_enet_if type,
|
||||
int speed
|
||||
)
|
||||
void marvell_phy_interface_mode(struct eth_device *dev, phy_interface_t type,
|
||||
int speed)
|
||||
{
|
||||
uec_private_t *uec = (uec_private_t *) dev->priv;
|
||||
struct uec_mii_info *mii_info;
|
||||
|
@ -867,47 +868,47 @@ void marvell_phy_interface_mode (struct eth_device *dev,
|
|||
}
|
||||
mii_info = uec->mii_info;
|
||||
|
||||
if (type == RGMII) {
|
||||
if (speed == 100) {
|
||||
phy_write (mii_info, 0x00, 0x9140);
|
||||
phy_write (mii_info, 0x1d, 0x001f);
|
||||
phy_write (mii_info, 0x1e, 0x200c);
|
||||
phy_write (mii_info, 0x1d, 0x0005);
|
||||
phy_write (mii_info, 0x1e, 0x0000);
|
||||
phy_write (mii_info, 0x1e, 0x0100);
|
||||
phy_write (mii_info, 0x09, 0x0e00);
|
||||
phy_write (mii_info, 0x04, 0x01e1);
|
||||
phy_write (mii_info, 0x00, 0x9140);
|
||||
phy_write (mii_info, 0x00, 0x1000);
|
||||
if (type == PHY_INTERFACE_MODE_RGMII) {
|
||||
if (speed == SPEED_100) {
|
||||
uec_phy_write(mii_info, 0x00, 0x9140);
|
||||
uec_phy_write(mii_info, 0x1d, 0x001f);
|
||||
uec_phy_write(mii_info, 0x1e, 0x200c);
|
||||
uec_phy_write(mii_info, 0x1d, 0x0005);
|
||||
uec_phy_write(mii_info, 0x1e, 0x0000);
|
||||
uec_phy_write(mii_info, 0x1e, 0x0100);
|
||||
uec_phy_write(mii_info, 0x09, 0x0e00);
|
||||
uec_phy_write(mii_info, 0x04, 0x01e1);
|
||||
uec_phy_write(mii_info, 0x00, 0x9140);
|
||||
uec_phy_write(mii_info, 0x00, 0x1000);
|
||||
udelay (100000);
|
||||
phy_write (mii_info, 0x00, 0x2900);
|
||||
phy_write (mii_info, 0x14, 0x0cd2);
|
||||
phy_write (mii_info, 0x00, 0xa100);
|
||||
phy_write (mii_info, 0x09, 0x0000);
|
||||
phy_write (mii_info, 0x1b, 0x800b);
|
||||
phy_write (mii_info, 0x04, 0x05e1);
|
||||
phy_write (mii_info, 0x00, 0xa100);
|
||||
phy_write (mii_info, 0x00, 0x2100);
|
||||
uec_phy_write(mii_info, 0x00, 0x2900);
|
||||
uec_phy_write(mii_info, 0x14, 0x0cd2);
|
||||
uec_phy_write(mii_info, 0x00, 0xa100);
|
||||
uec_phy_write(mii_info, 0x09, 0x0000);
|
||||
uec_phy_write(mii_info, 0x1b, 0x800b);
|
||||
uec_phy_write(mii_info, 0x04, 0x05e1);
|
||||
uec_phy_write(mii_info, 0x00, 0xa100);
|
||||
uec_phy_write(mii_info, 0x00, 0x2100);
|
||||
udelay (1000000);
|
||||
} else if (speed == 10) {
|
||||
phy_write (mii_info, 0x14, 0x8e40);
|
||||
phy_write (mii_info, 0x1b, 0x800b);
|
||||
phy_write (mii_info, 0x14, 0x0c82);
|
||||
phy_write (mii_info, 0x00, 0x8100);
|
||||
} else if (speed == SPEED_10) {
|
||||
uec_phy_write(mii_info, 0x14, 0x8e40);
|
||||
uec_phy_write(mii_info, 0x1b, 0x800b);
|
||||
uec_phy_write(mii_info, 0x14, 0x0c82);
|
||||
uec_phy_write(mii_info, 0x00, 0x8100);
|
||||
udelay (1000000);
|
||||
}
|
||||
}
|
||||
|
||||
/* handle 88e1111 rev.B2 erratum 5.6 */
|
||||
if (mii_info->autoneg) {
|
||||
status = phy_read (mii_info, MII_BMCR);
|
||||
phy_write (mii_info, MII_BMCR, status | BMCR_ANENABLE);
|
||||
status = uec_phy_read(mii_info, MII_BMCR);
|
||||
uec_phy_write(mii_info, MII_BMCR, status | BMCR_ANENABLE);
|
||||
}
|
||||
/* now the B2 will correctly report autoneg completion status */
|
||||
}
|
||||
|
||||
void change_phy_interface_mode (struct eth_device *dev,
|
||||
enum fsl_phy_enet_if type, int speed)
|
||||
phy_interface_t type, int speed)
|
||||
{
|
||||
#ifdef CONFIG_PHY_MODE_NEED_CHANGE
|
||||
marvell_phy_interface_mode (dev, type, speed);
|
||||
|
|
32
include/config_phylib_all_drivers.h
Normal file
32
include/config_phylib_all_drivers.h
Normal 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 */
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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
62
include/fsl_mdio.h
Normal 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
721
include/linux/ethtool.h
Normal 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
278
include/linux/mdio.h
Normal 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__ */
|
|
@ -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
229
include/phy.h
Normal 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
|
302
include/tsec.h
302
include/tsec.h
|
@ -7,7 +7,7 @@
|
|||
* terms of the GNU Public License, Version 2, incorporated
|
||||
* herein by reference.
|
||||
*
|
||||
* Copyright 2004, 2007, 2009 Freescale Semiconductor, Inc.
|
||||
* Copyright 2004, 2007, 2009, 2011 Freescale Semiconductor, Inc.
|
||||
* (C) Copyright 2003, Motorola, Inc.
|
||||
* maintained by Xianghua Xiao (x.xiao@motorola.com)
|
||||
* author Andy Fleming
|
||||
|
@ -19,30 +19,36 @@
|
|||
|
||||
#include <net.h>
|
||||
#include <config.h>
|
||||
#include <phy.h>
|
||||
#include <asm/fsl_enet.h>
|
||||
|
||||
#define TSEC_SIZE 0x01000
|
||||
#define TSEC_MDIO_OFFSET 0x01000
|
||||
|
||||
#define CONFIG_SYS_MDIO_BASE_ADDR (TSEC_BASE_ADDR + 0x520)
|
||||
|
||||
#define DEFAULT_MII_NAME "FSL_MDIO"
|
||||
|
||||
#define STD_TSEC_INFO(num) \
|
||||
{ \
|
||||
.regs = (tsec_t *)(TSEC_BASE_ADDR + ((num - 1) * TSEC_SIZE)), \
|
||||
.miiregs = (tsec_mdio_t *)(MDIO_BASE_ADDR), \
|
||||
.miiregs_sgmii = (tsec_mdio_t *)(MDIO_BASE_ADDR \
|
||||
.miiregs_sgmii = (struct tsec_mii_mng *)(CONFIG_SYS_MDIO_BASE_ADDR \
|
||||
+ (num - 1) * TSEC_MDIO_OFFSET), \
|
||||
.devname = CONFIG_TSEC##num##_NAME, \
|
||||
.phyaddr = TSEC##num##_PHY_ADDR, \
|
||||
.flags = TSEC##num##_FLAGS \
|
||||
.flags = TSEC##num##_FLAGS, \
|
||||
.mii_devname = DEFAULT_MII_NAME \
|
||||
}
|
||||
|
||||
#define SET_STD_TSEC_INFO(x, num) \
|
||||
{ \
|
||||
x.regs = (tsec_t *)(TSEC_BASE_ADDR + ((num - 1) * TSEC_SIZE)); \
|
||||
x.miiregs = (tsec_mdio_t *)(MDIO_BASE_ADDR); \
|
||||
x.miiregs_sgmii = (tsec_mdio_t *)(MDIO_BASE_ADDR \
|
||||
x.miiregs_sgmii = (struct tsec_mii_mng *)(CONFIG_SYS_MDIO_BASE_ADDR \
|
||||
+ (num - 1) * TSEC_MDIO_OFFSET); \
|
||||
x.devname = CONFIG_TSEC##num##_NAME; \
|
||||
x.phyaddr = TSEC##num##_PHY_ADDR; \
|
||||
x.flags = TSEC##num##_FLAGS;\
|
||||
x.mii_devname = DEFAULT_MII_NAME;\
|
||||
}
|
||||
|
||||
#define MAC_ADDR_LEN 6
|
||||
|
@ -51,8 +57,6 @@
|
|||
#define TSEC_TIMEOUT 1000
|
||||
#define TOUT_LOOP 1000000
|
||||
|
||||
#define PHY_AUTONEGOTIATE_TIMEOUT 5000 /* in ms */
|
||||
|
||||
/* TBI register addresses */
|
||||
#define TBI_CR 0x00
|
||||
#define TBI_SR 0x01
|
||||
|
@ -96,204 +100,14 @@
|
|||
|
||||
#define ECNTRL_INIT_SETTINGS 0x00001000
|
||||
#define ECNTRL_TBI_MODE 0x00000020
|
||||
#define ECNTRL_REDUCED_MODE 0x00000010
|
||||
#define ECNTRL_R100 0x00000008
|
||||
#define ECNTRL_REDUCED_MII_MODE 0x00000004
|
||||
#define ECNTRL_SGMII_MODE 0x00000002
|
||||
|
||||
#define miim_end -2
|
||||
#define miim_read -1
|
||||
|
||||
#ifndef CONFIG_SYS_TBIPA_VALUE
|
||||
#define CONFIG_SYS_TBIPA_VALUE 0x1f
|
||||
#endif
|
||||
#define MIIMCFG_INIT_VALUE 0x00000003
|
||||
#define MIIMCFG_RESET 0x80000000
|
||||
|
||||
#define MIIMIND_BUSY 0x00000001
|
||||
#define MIIMIND_NOTVALID 0x00000004
|
||||
|
||||
#define MIIM_CONTROL 0x00
|
||||
#define MIIM_CONTROL_RESET 0x00009140
|
||||
#define MIIM_CONTROL_INIT 0x00001140
|
||||
#define MIIM_CONTROL_RESTART 0x00001340
|
||||
#define MIIM_ANEN 0x00001000
|
||||
|
||||
#define MIIM_CR 0x00
|
||||
#define MIIM_CR_RST 0x00008000
|
||||
#define MIIM_CR_INIT 0x00001000
|
||||
|
||||
#define MIIM_STATUS 0x1
|
||||
#define MIIM_STATUS_AN_DONE 0x00000020
|
||||
#define MIIM_STATUS_LINK 0x0004
|
||||
|
||||
#define MIIM_PHYIR1 0x2
|
||||
#define MIIM_PHYIR2 0x3
|
||||
|
||||
#define MIIM_ANAR 0x4
|
||||
#define MIIM_ANAR_INIT 0x1e1
|
||||
|
||||
#define MIIM_TBI_ANLPBPA 0x5
|
||||
#define MIIM_TBI_ANLPBPA_HALF 0x00000040
|
||||
#define MIIM_TBI_ANLPBPA_FULL 0x00000020
|
||||
|
||||
#define MIIM_TBI_ANEX 0x6
|
||||
#define MIIM_TBI_ANEX_NP 0x00000004
|
||||
#define MIIM_TBI_ANEX_PRX 0x00000002
|
||||
|
||||
#define MIIM_GBIT_CONTROL 0x9
|
||||
#define MIIM_GBIT_CONTROL_INIT 0xe00
|
||||
|
||||
#define MIIM_EXT_PAGE_ACCESS 0x1f
|
||||
|
||||
/* Broadcom BCM54xx -- taken from linux sungem_phy */
|
||||
#define MIIM_BCM54xx_AUXCNTL 0x18
|
||||
#define MIIM_BCM54xx_AUXCNTL_ENCODE(val) ((val & 0x7) << 12)|(val & 0x7)
|
||||
#define MIIM_BCM54xx_AUXSTATUS 0x19
|
||||
#define MIIM_BCM54xx_AUXSTATUS_LINKMODE_MASK 0x0700
|
||||
#define MIIM_BCM54xx_AUXSTATUS_LINKMODE_SHIFT 8
|
||||
|
||||
#define MIIM_BCM54XX_SHD 0x1c /* 0x1c shadow registers */
|
||||
#define MIIM_BCM54XX_SHD_WRITE 0x8000
|
||||
#define MIIM_BCM54XX_SHD_VAL(x) ((x & 0x1f) << 10)
|
||||
#define MIIM_BCM54XX_SHD_DATA(x) ((x & 0x3ff) << 0)
|
||||
#define MIIM_BCM54XX_SHD_WR_ENCODE(val, data) \
|
||||
(MIIM_BCM54XX_SHD_WRITE | MIIM_BCM54XX_SHD_VAL(val) | \
|
||||
MIIM_BCM54XX_SHD_DATA(data))
|
||||
|
||||
#define MIIM_BCM54XX_EXP_DATA 0x15 /* Expansion register data */
|
||||
#define MIIM_BCM54XX_EXP_SEL 0x17 /* Expansion register select */
|
||||
#define MIIM_BCM54XX_EXP_SEL_SSD 0x0e00 /* Secondary SerDes select */
|
||||
#define MIIM_BCM54XX_EXP_SEL_ER 0x0f00 /* Expansion register select */
|
||||
|
||||
/* Cicada Auxiliary Control/Status Register */
|
||||
#define MIIM_CIS8201_AUX_CONSTAT 0x1c
|
||||
#define MIIM_CIS8201_AUXCONSTAT_INIT 0x0004
|
||||
#define MIIM_CIS8201_AUXCONSTAT_DUPLEX 0x0020
|
||||
#define MIIM_CIS8201_AUXCONSTAT_SPEED 0x0018
|
||||
#define MIIM_CIS8201_AUXCONSTAT_GBIT 0x0010
|
||||
#define MIIM_CIS8201_AUXCONSTAT_100 0x0008
|
||||
|
||||
/* Cicada Extended Control Register 1 */
|
||||
#define MIIM_CIS8201_EXT_CON1 0x17
|
||||
#define MIIM_CIS8201_EXTCON1_INIT 0x0000
|
||||
|
||||
/* Cicada 8204 Extended PHY Control Register 1 */
|
||||
#define MIIM_CIS8204_EPHY_CON 0x17
|
||||
#define MIIM_CIS8204_EPHYCON_INIT 0x0006
|
||||
#define MIIM_CIS8204_EPHYCON_RGMII 0x1100
|
||||
|
||||
/* Cicada 8204 Serial LED Control Register */
|
||||
#define MIIM_CIS8204_SLED_CON 0x1b
|
||||
#define MIIM_CIS8204_SLEDCON_INIT 0x1115
|
||||
|
||||
#define MIIM_GBIT_CON 0x09
|
||||
#define MIIM_GBIT_CON_ADVERT 0x0e00
|
||||
|
||||
/* Entry for Vitesse VSC8244 regs starts here */
|
||||
/* Vitesse VSC8244 Auxiliary Control/Status Register */
|
||||
#define MIIM_VSC8244_AUX_CONSTAT 0x1c
|
||||
#define MIIM_VSC8244_AUXCONSTAT_INIT 0x0000
|
||||
#define MIIM_VSC8244_AUXCONSTAT_DUPLEX 0x0020
|
||||
#define MIIM_VSC8244_AUXCONSTAT_SPEED 0x0018
|
||||
#define MIIM_VSC8244_AUXCONSTAT_GBIT 0x0010
|
||||
#define MIIM_VSC8244_AUXCONSTAT_100 0x0008
|
||||
#define MIIM_CONTROL_INIT_LOOPBACK 0x4000
|
||||
|
||||
/* Vitesse VSC8244 Extended PHY Control Register 1 */
|
||||
#define MIIM_VSC8244_EPHY_CON 0x17
|
||||
#define MIIM_VSC8244_EPHYCON_INIT 0x0006
|
||||
|
||||
/* Vitesse VSC8244 Serial LED Control Register */
|
||||
#define MIIM_VSC8244_LED_CON 0x1b
|
||||
#define MIIM_VSC8244_LEDCON_INIT 0xF011
|
||||
|
||||
/* Entry for Vitesse VSC8601 regs starts here (Not complete) */
|
||||
/* Vitesse VSC8601 Extended PHY Control Register 1 */
|
||||
#define MIIM_VSC8601_EPHY_CON 0x17
|
||||
#define MIIM_VSC8601_EPHY_CON_INIT_SKEW 0x1120
|
||||
#define MIIM_VSC8601_SKEW_CTRL 0x1c
|
||||
|
||||
/* 88E1011 PHY Status Register */
|
||||
#define MIIM_88E1011_PHY_STATUS 0x11
|
||||
#define MIIM_88E1011_PHYSTAT_SPEED 0xc000
|
||||
#define MIIM_88E1011_PHYSTAT_GBIT 0x8000
|
||||
#define MIIM_88E1011_PHYSTAT_100 0x4000
|
||||
#define MIIM_88E1011_PHYSTAT_DUPLEX 0x2000
|
||||
#define MIIM_88E1011_PHYSTAT_SPDDONE 0x0800
|
||||
#define MIIM_88E1011_PHYSTAT_LINK 0x0400
|
||||
|
||||
#define MIIM_88E1011_PHY_SCR 0x10
|
||||
#define MIIM_88E1011_PHY_MDI_X_AUTO 0x0060
|
||||
|
||||
/* 88E1111 PHY LED Control Register */
|
||||
#define MIIM_88E1111_PHY_LED_CONTROL 24
|
||||
#define MIIM_88E1111_PHY_LED_DIRECT 0x4100
|
||||
#define MIIM_88E1111_PHY_LED_COMBINE 0x411C
|
||||
|
||||
/* 88E1121 PHY LED Control Register */
|
||||
#define MIIM_88E1121_PHY_LED_CTRL 16
|
||||
#define MIIM_88E1121_PHY_LED_PAGE 3
|
||||
#define MIIM_88E1121_PHY_LED_DEF 0x0030
|
||||
|
||||
/* 88E1121 PHY IRQ Enable/Status Register */
|
||||
#define MIIM_88E1121_PHY_IRQ_EN 18
|
||||
#define MIIM_88E1121_PHY_IRQ_STATUS 19
|
||||
|
||||
#define MIIM_88E1121_PHY_PAGE 22
|
||||
|
||||
/* 88E1145 Extended PHY Specific Control Register */
|
||||
#define MIIM_88E1145_PHY_EXT_CR 20
|
||||
#define MIIM_M88E1145_RGMII_RX_DELAY 0x0080
|
||||
#define MIIM_M88E1145_RGMII_TX_DELAY 0x0002
|
||||
|
||||
#define MIIM_88E1145_PHY_PAGE 29
|
||||
#define MIIM_88E1145_PHY_CAL_OV 30
|
||||
|
||||
/* RTL8211B PHY Status Register */
|
||||
#define MIIM_RTL8211B_PHY_STATUS 0x11
|
||||
#define MIIM_RTL8211B_PHYSTAT_SPEED 0xc000
|
||||
#define MIIM_RTL8211B_PHYSTAT_GBIT 0x8000
|
||||
#define MIIM_RTL8211B_PHYSTAT_100 0x4000
|
||||
#define MIIM_RTL8211B_PHYSTAT_DUPLEX 0x2000
|
||||
#define MIIM_RTL8211B_PHYSTAT_SPDDONE 0x0800
|
||||
#define MIIM_RTL8211B_PHYSTAT_LINK 0x0400
|
||||
|
||||
/* DM9161 Control register values */
|
||||
#define MIIM_DM9161_CR_STOP 0x0400
|
||||
#define MIIM_DM9161_CR_RSTAN 0x1200
|
||||
|
||||
#define MIIM_DM9161_SCR 0x10
|
||||
#define MIIM_DM9161_SCR_INIT 0x0610
|
||||
|
||||
/* DM9161 Specified Configuration and Status Register */
|
||||
#define MIIM_DM9161_SCSR 0x11
|
||||
#define MIIM_DM9161_SCSR_100F 0x8000
|
||||
#define MIIM_DM9161_SCSR_100H 0x4000
|
||||
#define MIIM_DM9161_SCSR_10F 0x2000
|
||||
#define MIIM_DM9161_SCSR_10H 0x1000
|
||||
|
||||
/* DM9161 10BT Configuration/Status */
|
||||
#define MIIM_DM9161_10BTCSR 0x12
|
||||
#define MIIM_DM9161_10BTCSR_INIT 0x7800
|
||||
|
||||
/* LXT971 Status 2 registers */
|
||||
#define MIIM_LXT971_SR2 0x11 /* Status Register 2 */
|
||||
#define MIIM_LXT971_SR2_SPEED_MASK 0x4200
|
||||
#define MIIM_LXT971_SR2_10HDX 0x0000 /* 10 Mbit half duplex selected */
|
||||
#define MIIM_LXT971_SR2_10FDX 0x0200 /* 10 Mbit full duplex selected */
|
||||
#define MIIM_LXT971_SR2_100HDX 0x4000 /* 100 Mbit half duplex selected */
|
||||
#define MIIM_LXT971_SR2_100FDX 0x4200 /* 100 Mbit full duplex selected */
|
||||
|
||||
/* DP83865 Control register values */
|
||||
#define MIIM_DP83865_CR_INIT 0x9200
|
||||
|
||||
/* DP83865 Link and Auto-Neg Status Register */
|
||||
#define MIIM_DP83865_LANR 0x11
|
||||
#define MIIM_DP83865_SPD_MASK 0x0018
|
||||
#define MIIM_DP83865_SPD_1000 0x0010
|
||||
#define MIIM_DP83865_SPD_100 0x0008
|
||||
#define MIIM_DP83865_DPX_FULL 0x0002
|
||||
|
||||
#define MIIM_READ_COMMAND 0x00000001
|
||||
|
||||
#define MRBLR_INIT_SETTINGS PKTSIZE_ALIGN
|
||||
|
||||
|
@ -467,22 +281,6 @@ typedef struct tsec_hash_regs
|
|||
uint res2[24];
|
||||
} tsec_hash_t;
|
||||
|
||||
typedef struct tsec_mdio {
|
||||
uint res1[4];
|
||||
uint ieventm;
|
||||
uint imaskm;
|
||||
uint res2;
|
||||
uint emapm;
|
||||
uint res3[320];
|
||||
uint miimcfg; /* MII Management: Configuration */
|
||||
uint miimcom; /* MII Management: Command */
|
||||
uint miimadd; /* MII Management: Address */
|
||||
uint miimcon; /* MII Management: Control */
|
||||
uint miimstat; /* MII Management: Status */
|
||||
uint miimind; /* MII Management: Indicators */
|
||||
uint res4[690];
|
||||
} tsec_mdio_t;
|
||||
|
||||
typedef struct tsec
|
||||
{
|
||||
/* General Control and Status Registers (0x2_n000) */
|
||||
|
@ -578,79 +376,29 @@ typedef struct tsec
|
|||
uint resc00[256];
|
||||
} tsec_t;
|
||||
|
||||
#define TSEC_GIGABIT (1)
|
||||
#define TSEC_GIGABIT (1 << 0)
|
||||
|
||||
/* This flag currently only has
|
||||
* meaning if we're using the eTSEC */
|
||||
/* These flags currently only have meaning if we're using the eTSEC */
|
||||
#define TSEC_REDUCED (1 << 1) /* MAC-PHY interface uses RGMII */
|
||||
#define TSEC_SGMII (1 << 2) /* MAC-PHY interface uses SGMII */
|
||||
#define TSEC_FIBER (1 << 3) /* PHY uses fiber, eg 1000 Base-X */
|
||||
|
||||
struct tsec_private {
|
||||
volatile tsec_t *regs;
|
||||
volatile tsec_mdio_t *phyregs;
|
||||
volatile tsec_mdio_t *phyregs_sgmii;
|
||||
struct phy_info *phyinfo;
|
||||
tsec_t *regs;
|
||||
struct tsec_mii_mng *phyregs_sgmii;
|
||||
struct phy_device *phydev;
|
||||
phy_interface_t interface;
|
||||
struct mii_dev *bus;
|
||||
uint phyaddr;
|
||||
char mii_devname[16];
|
||||
u32 flags;
|
||||
uint link;
|
||||
uint duplexity;
|
||||
uint speed;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* struct phy_cmd: A command for reading or writing a PHY register
|
||||
*
|
||||
* mii_reg: The register to read or write
|
||||
*
|
||||
* mii_data: For writes, the value to put in the register.
|
||||
* A value of -1 indicates this is a read.
|
||||
*
|
||||
* funct: A function pointer which is invoked for each command.
|
||||
* For reads, this function will be passed the value read
|
||||
* from the PHY, and process it.
|
||||
* For writes, the result of this function will be written
|
||||
* to the PHY register
|
||||
*/
|
||||
struct phy_cmd {
|
||||
uint mii_reg;
|
||||
uint mii_data;
|
||||
uint (*funct) (uint mii_reg, struct tsec_private * priv);
|
||||
};
|
||||
|
||||
/* struct phy_info: a structure which defines attributes for a PHY
|
||||
*
|
||||
* id will contain a number which represents the PHY. During
|
||||
* startup, the driver will poll the PHY to find out what its
|
||||
* UID--as defined by registers 2 and 3--is. The 32-bit result
|
||||
* gotten from the PHY will be shifted right by "shift" bits to
|
||||
* discard any bits which may change based on revision numbers
|
||||
* unimportant to functionality
|
||||
*
|
||||
* The struct phy_cmd entries represent pointers to an arrays of
|
||||
* commands which tell the driver what to do to the PHY.
|
||||
*/
|
||||
struct phy_info {
|
||||
uint id;
|
||||
char *name;
|
||||
uint shift;
|
||||
/* Called to configure the PHY, and modify the controller
|
||||
* based on the results */
|
||||
struct phy_cmd *config;
|
||||
|
||||
/* Called when starting up the controller */
|
||||
struct phy_cmd *startup;
|
||||
|
||||
/* Called when bringing down the controller */
|
||||
struct phy_cmd *shutdown;
|
||||
};
|
||||
|
||||
struct tsec_info_struct {
|
||||
tsec_t *regs;
|
||||
tsec_mdio_t *miiregs;
|
||||
tsec_mdio_t *miiregs_sgmii;
|
||||
struct tsec_mii_mng *miiregs_sgmii;
|
||||
char *devname;
|
||||
char *mii_devname;
|
||||
phy_interface_t interface;
|
||||
unsigned int phyaddr;
|
||||
u32 flags;
|
||||
};
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <command.h>
|
||||
#include <net.h>
|
||||
#include <miiphy.h>
|
||||
#include <phy.h>
|
||||
|
||||
void eth_parse_enetaddr(const char *addr, uchar *enetaddr)
|
||||
{
|
||||
|
@ -217,6 +218,11 @@ int eth_initialize(bd_t *bis)
|
|||
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
|
||||
miiphy_init();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PHYLIB
|
||||
phy_init();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If board-specific initialization exists, call it.
|
||||
* If not, call a CPU-specific one
|
||||
|
|
Loading…
Reference in a new issue