Merge branch 'master' of git://www.denx.de/git/u-boot-net

This commit is contained in:
Wolfgang Denk 2008-01-23 14:20:49 +01:00
commit 2468592d79
10 changed files with 273 additions and 122 deletions

4
README
View File

@ -2699,6 +2699,10 @@ Some configuration options can be set using Environment Variables:
=> setenv ethact SCC ETHERNET
=> ping 10.0.0.1 # traffic sent on SCC ETHERNET
ethrotate - When set to "no" U-Boot does not go through all
available network interfaces.
It just stays at the currently selected interface.
netretry - When set to "no" each network operation will
either succeed or fail without retrying.
When set to "once" the network operation will

View File

@ -30,8 +30,25 @@
#include <command.h>
#include <asm/blackfin.h>
#include <asm/io.h>
#include <net.h>
#include "ether_bf537.h"
/**
* is_valid_ether_addr - Determine if the given Ethernet address is valid
* @addr: Pointer to a six-byte array containing the Ethernet address
*
* Check that the Ethernet address (MAC) is not 00:00:00:00:00:00, is not
* a multicast address, and is not FF:FF:FF:FF:FF:FF.
*
* Return true if the address is valid.
*/
static inline int is_valid_ether_addr(const u8 * addr)
{
/* FF:FF:FF:FF:FF:FF is a multicast address so we don't need to
* explicitly check for it here. */
return !is_multicast_ether_addr(addr) && !is_zero_ether_addr(addr);
}
DECLARE_GLOBAL_DATA_PTR;
#define POST_WORD_ADDR 0xFF903FFC

View File

@ -69,42 +69,3 @@ void SoftResetPHY(void);
void DumpPHYRegs(void);
int SetupSystemRegs(int *opmode);
/**
* is_zero_ether_addr - Determine if give Ethernet address is all zeros.
* @addr: Pointer to a six-byte array containing the Ethernet address
*
* Return true if the address is all zeroes.
*/
static inline int is_zero_ether_addr(const u8 * addr)
{
return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]);
}
/**
* is_multicast_ether_addr - Determine if the Ethernet address is a multicast.
* @addr: Pointer to a six-byte array containing the Ethernet address
*
* Return true if the address is a multicast address.
* By definition the broadcast address is also a multicast address.
*/
static inline int is_multicast_ether_addr(const u8 * addr)
{
return (0x01 & addr[0]);
}
/**
* is_valid_ether_addr - Determine if the given Ethernet address is valid
* @addr: Pointer to a six-byte array containing the Ethernet address
*
* Check that the Ethernet address (MAC) is not 00:00:00:00:00:00, is not
* a multicast address, and is not FF:FF:FF:FF:FF:FF.
*
* Return true if the address is valid.
*/
static inline int is_valid_ether_addr(const u8 * addr)
{
/* FF:FF:FF:FF:FF:FF is a multicast address so we don't need to
* explicitly check for it here. */
return !is_multicast_ether_addr(addr) && !is_zero_ether_addr(addr);
}

View File

@ -87,7 +87,7 @@ int do_nfs (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
U_BOOT_CMD(
nfs, 3, 1, do_nfs,
"nfs\t- boot image via network using NFS protocol\n",
"[loadAddress] [host ip addr:bootfilename]\n"
"[loadAddress] [[hostIPaddr:]bootfilename]\n"
);
#endif

View File

@ -80,10 +80,7 @@
#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
defined(CONFIG_RTL8139)
#define TICKS_PER_SEC CFG_HZ
#define TICKS_PER_MS (TICKS_PER_SEC/1000)
#define RTL_TIMEOUT (1*TICKS_PER_SEC)
#define RTL_TIMEOUT 100000
#define ETH_FRAME_LEN 1514
#define ETH_ALEN 6
@ -392,6 +389,7 @@ static void rtl_reset(struct eth_device *dev)
#ifdef DEBUG_RX
printf("rx ring address is %X\n",(unsigned long)rx_ring);
#endif
flush_cache((unsigned long)rx_ring, RX_BUF_LEN);
outl(phys_to_bus((int)rx_ring), ioaddr + RxBuf);
/* If we add multicast support, the MAR0 register would have to be
@ -414,9 +412,10 @@ static void rtl_reset(struct eth_device *dev)
static int rtl_transmit(struct eth_device *dev, volatile void *packet, int length)
{
unsigned int status, to;
unsigned int status;
unsigned long txstatus;
unsigned int len = length;
int i = 0;
ioaddr = dev->iobase;
@ -432,12 +431,11 @@ static int rtl_transmit(struct eth_device *dev, volatile void *packet, int lengt
tx_buffer[len++] = '\0';
}
flush_cache((unsigned long)tx_buffer, length);
outl(phys_to_bus((int)tx_buffer), ioaddr + TxAddr0 + cur_tx*4);
outl(((TX_FIFO_THRESH<<11) & 0x003f0000) | len,
ioaddr + TxStatus0 + cur_tx*4);
to = currticks() + RTL_TIMEOUT;
do {
status = inw(ioaddr + IntrStatus);
/* Only acknlowledge interrupt sources we can properly handle
@ -445,7 +443,8 @@ static int rtl_transmit(struct eth_device *dev, volatile void *packet, int lengt
* rtl_poll() function. */
outw(status & (TxOK | TxErr | PCIErr), ioaddr + IntrStatus);
if ((status & (TxOK | TxErr | PCIErr)) != 0) break;
} while (currticks() < to);
udelay(10);
} while (i++ < RTL_TIMEOUT);
txstatus = inl(ioaddr + TxStatus0 + cur_tx*4);
@ -458,8 +457,8 @@ static int rtl_transmit(struct eth_device *dev, volatile void *packet, int lengt
return length;
} else {
#ifdef DEBUG_TX
printf("tx timeout/error (%d ticks), status %hX txstatus %X\n",
currticks()-to, status, txstatus);
printf("tx timeout/error (%d usecs), status %hX txstatus %X\n",
10*i, status, txstatus);
#endif
rtl_reset(dev);
@ -489,7 +488,8 @@ static int rtl_poll(struct eth_device *dev)
#endif
ring_offs = cur_rx % RX_BUF_LEN;
rx_status = *(unsigned int*)KSEG1ADDR((rx_ring + ring_offs));
/* ring_offs is guaranteed being 4-byte aligned */
rx_status = le32_to_cpu(*(unsigned int *)(rx_ring + ring_offs));
rx_size = rx_status >> 16;
rx_status &= 0xffff;
@ -519,6 +519,7 @@ static int rtl_poll(struct eth_device *dev)
printf("rx packet %d bytes", rx_size-4);
#endif
}
flush_cache((unsigned long)rx_ring, RX_BUF_LEN);
cur_rx = (cur_rx + rx_size + 4 + 3) & ~3;
outw(cur_rx - 16, ioaddr + RxBufPtr);

View File

@ -241,10 +241,9 @@ int tsec_init(struct eth_device *dev, bd_t * bd)
* It will wait for the write to be done (or for a timeout to
* expire) before exiting
*/
void write_phy_reg(struct tsec_private *priv, uint regnum, uint value)
void write_any_phy_reg(struct tsec_private *priv, uint phyid, uint regnum, uint value)
{
volatile tsec_t *regbase = priv->phyregs;
uint phyid = priv->phyaddr;
int timeout = 1000000;
regbase->miimadd = (phyid << 8) | regnum;
@ -255,17 +254,19 @@ void write_phy_reg(struct tsec_private *priv, uint regnum, uint value)
while ((regbase->miimind & MIIMIND_BUSY) && timeout--) ;
}
/* #define to provide old write_phy_reg functionality without duplicating code */
#define write_phy_reg(priv, regnum, value) write_any_phy_reg(priv,priv->phyaddr,regnum,value)
/* Reads register regnum on the device's PHY through the
* registers specified in priv. It lowers and raises the read
* command, and waits for the data to become valid (miimind
* notvalid bit cleared), and the bus to cease activity (miimind
* busy bit cleared), and then returns the value
*/
uint read_phy_reg(struct tsec_private *priv, uint regnum)
uint read_any_phy_reg(struct tsec_private *priv, uint phyid, uint regnum)
{
uint value;
volatile tsec_t *regbase = priv->phyregs;
uint phyid = priv->phyaddr;
/* Put the address of the phy, and the register
* number into MIIMADD */
@ -288,6 +289,9 @@ uint read_phy_reg(struct tsec_private *priv, uint regnum)
return value;
}
/* #define to provide old read_phy_reg functionality without duplicating code */
#define read_phy_reg(priv,regnum) read_any_phy_reg(priv,priv->phyaddr,regnum)
/* Discover which PHY is attached to the device, and configure it
* properly. If the PHY is not recognized, then return 0
* (failure). Otherwise, return 1
@ -571,6 +575,63 @@ uint mii_parse_88E1011_psr(uint mii_reg, struct tsec_private * priv)
return 0;
}
/* Parse the RTL8211B's status register for speed and duplex
* information
*/
uint mii_parse_RTL8211B_sr(uint mii_reg, struct tsec_private * priv)
{
uint speed;
mii_reg = read_phy_reg(priv, MIIM_RTL8211B_PHY_STATUS);
if ((mii_reg & MIIM_RTL8211B_PHYSTAT_LINK) &&
!(mii_reg & MIIM_RTL8211B_PHYSTAT_SPDDONE)) {
int i = 0;
puts("Waiting for PHY realtime link");
while (!(mii_reg & MIIM_RTL8211B_PHYSTAT_SPDDONE)) {
/* Timeout reached ? */
if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
puts(" TIMEOUT !\n");
priv->link = 0;
break;
}
if ((i++ % 1000) == 0) {
putc('.');
}
udelay(1000); /* 1 ms */
mii_reg = read_phy_reg(priv, MIIM_RTL8211B_PHY_STATUS);
}
puts(" done\n");
udelay(500000); /* another 500 ms (results in faster booting) */
} else {
if (mii_reg & MIIM_RTL8211B_PHYSTAT_LINK)
priv->link = 1;
else
priv->link = 0;
}
if (mii_reg & MIIM_RTL8211B_PHYSTAT_DUPLEX)
priv->duplexity = 1;
else
priv->duplexity = 0;
speed = (mii_reg & MIIM_RTL8211B_PHYSTAT_SPEED);
switch (speed) {
case MIIM_RTL8211B_PHYSTAT_GBIT:
priv->speed = 1000;
break;
case MIIM_RTL8211B_PHYSTAT_100:
priv->speed = 100;
break;
default:
priv->speed = 10;
}
return 0;
}
/* Parse the cis8201's status register for speed and duplex
* information
*/
@ -1361,6 +1422,33 @@ struct phy_info phy_info_dp83865 = {
},
};
struct phy_info phy_info_rtl8211b = {
0x001cc91,
"RealTek RTL8211B",
4,
(struct phy_cmd[]){ /* config */
/* Reset and configure the PHY */
{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
{MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL},
{MIIM_ANAR, MIIM_ANAR_INIT, NULL},
{MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
{miim_end,}
},
(struct phy_cmd[]){ /* startup */
/* Status is read once to clear old link state */
{MIIM_STATUS, miim_read, NULL},
/* Auto-negotiate */
{MIIM_STATUS, miim_read, &mii_parse_sr},
/* Read the status */
{MIIM_RTL8211B_PHY_STATUS, miim_read, &mii_parse_RTL8211B_sr},
{miim_end,}
},
(struct phy_cmd[]){ /* shutdown */
{miim_end,}
},
};
struct phy_info *phy_info[] = {
&phy_info_cis8204,
&phy_info_cis8201,
@ -1374,6 +1462,7 @@ struct phy_info *phy_info[] = {
&phy_info_lxt971,
&phy_info_VSC8244,
&phy_info_dp83865,
&phy_info_rtl8211b,
&phy_info_generic,
NULL
};
@ -1497,18 +1586,6 @@ static void relocate_cmds(void)
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \
&& !defined(BITBANGMII)
struct tsec_private *get_priv_for_phy(unsigned char phyaddr)
{
int i;
for (i = 0; i < MAXCONTROLLERS; i++) {
if (privlist[i]->phyaddr == phyaddr)
return privlist[i];
}
return NULL;
}
/*
* Read a MII PHY register.
*
@ -1519,14 +1596,14 @@ static int tsec_miiphy_read(char *devname, unsigned char addr,
unsigned char reg, unsigned short *value)
{
unsigned short ret;
struct tsec_private *priv = get_priv_for_phy(addr);
struct tsec_private *priv = privlist[0];
if (NULL == priv) {
printf("Can't read PHY at address %d\n", addr);
return -1;
}
ret = (unsigned short)read_phy_reg(priv, reg);
ret = (unsigned short)read_any_phy_reg(priv, addr, reg);
*value = ret;
return 0;
@ -1541,14 +1618,14 @@ static int tsec_miiphy_read(char *devname, unsigned char addr,
static int tsec_miiphy_write(char *devname, unsigned char addr,
unsigned char reg, unsigned short value)
{
struct tsec_private *priv = get_priv_for_phy(addr);
struct tsec_private *priv = privlist[0];
if (NULL == priv) {
printf("Can't write PHY at address %d\n", addr);
return -1;
}
write_phy_reg(priv, reg, value);
write_any_phy_reg(priv, addr, reg, value);
return 0;
}

View File

@ -184,6 +184,14 @@
#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

View File

@ -40,8 +40,13 @@ static uec_info_t eth1_uec_info = {
.tx_clock = CFG_UEC1_TX_CLK,
.eth_type = CFG_UEC1_ETH_TYPE,
},
#if (CFG_UEC1_ETH_TYPE == FAST_ETH)
.num_threads_tx = UEC_NUM_OF_THREADS_1,
.num_threads_rx = UEC_NUM_OF_THREADS_1,
#else
.num_threads_tx = UEC_NUM_OF_THREADS_4,
.num_threads_rx = UEC_NUM_OF_THREADS_4,
#endif
.riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
.riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
.tx_bd_ring_len = 16,
@ -58,8 +63,13 @@ static uec_info_t eth2_uec_info = {
.tx_clock = CFG_UEC2_TX_CLK,
.eth_type = CFG_UEC2_ETH_TYPE,
},
#if (CFG_UEC2_ETH_TYPE == FAST_ETH)
.num_threads_tx = UEC_NUM_OF_THREADS_1,
.num_threads_rx = UEC_NUM_OF_THREADS_1,
#else
.num_threads_tx = UEC_NUM_OF_THREADS_4,
.num_threads_rx = UEC_NUM_OF_THREADS_4,
#endif
.riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
.riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
.tx_bd_ring_len = 16,
@ -68,7 +78,6 @@ static uec_info_t eth2_uec_info = {
.enet_interface = CFG_UEC2_INTERFACE_MODE,
};
#endif
#ifdef CONFIG_UEC_ETH3
static uec_info_t eth3_uec_info = {
.uf_info = {
@ -77,8 +86,13 @@ static uec_info_t eth3_uec_info = {
.tx_clock = CFG_UEC3_TX_CLK,
.eth_type = CFG_UEC3_ETH_TYPE,
},
#if (CFG_UEC3_ETH_TYPE == FAST_ETH)
.num_threads_tx = UEC_NUM_OF_THREADS_1,
.num_threads_rx = UEC_NUM_OF_THREADS_1,
#else
.num_threads_tx = UEC_NUM_OF_THREADS_4,
.num_threads_rx = UEC_NUM_OF_THREADS_4,
#endif
.riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
.riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
.tx_bd_ring_len = 16,
@ -87,6 +101,29 @@ static uec_info_t eth3_uec_info = {
.enet_interface = CFG_UEC3_INTERFACE_MODE,
};
#endif
#ifdef CONFIG_UEC_ETH4
static uec_info_t eth4_uec_info = {
.uf_info = {
.ucc_num = CFG_UEC4_UCC_NUM,
.rx_clock = CFG_UEC4_RX_CLK,
.tx_clock = CFG_UEC4_TX_CLK,
.eth_type = CFG_UEC4_ETH_TYPE,
},
#if (CFG_UEC4_ETH_TYPE == FAST_ETH)
.num_threads_tx = UEC_NUM_OF_THREADS_1,
.num_threads_rx = UEC_NUM_OF_THREADS_1,
#else
.num_threads_tx = UEC_NUM_OF_THREADS_4,
.num_threads_rx = UEC_NUM_OF_THREADS_4,
#endif
.riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
.riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
.tx_bd_ring_len = 16,
.rx_bd_ring_len = 16,
.phy_address = CFG_UEC4_PHY_ADDR,
.enet_interface = CFG_UEC4_INTERFACE_MODE,
};
#endif
static int uec_mac_enable(uec_private_t *uec, comm_dir_e mode)
{
@ -475,6 +512,8 @@ static int init_phy(struct eth_device *dev)
uec->mii_info = mii_info;
qe_set_mii_clk_src(uec->uec_info->uf_info.ucc_num);
if (init_mii_management_configuration(umii_regs)) {
printf("%s: The MII Bus is stuck!", dev->name);
err = -1;
@ -581,21 +620,12 @@ static void adjust_link(struct eth_device *dev)
static void phy_change(struct eth_device *dev)
{
uec_private_t *uec = (uec_private_t *)dev->priv;
uec_t *uec_regs;
int result = 0;
uec_regs = uec->uec_regs;
/* Delay 5s to give the PHY a chance to change the register state */
udelay(5000000);
/* Update the link, speed, duplex */
result = uec->mii_info->phyinfo->read_status(uec->mii_info);
uec->mii_info->phyinfo->read_status(uec->mii_info);
/* Adjust the interface according to speed */
if ((0 == result) || (uec->mii_info->link == 0)) {
adjust_link(dev);
}
adjust_link(dev);
}
static int uec_set_mac_address(uec_private_t *uec, u8 *mac_addr)
@ -1120,27 +1150,59 @@ static int uec_startup(uec_private_t *uec)
static int uec_init(struct eth_device* dev, bd_t *bd)
{
uec_private_t *uec;
int err;
int err, i;
struct phy_info *curphy;
uec = (uec_private_t *)dev->priv;
if (uec->the_first_run == 0) {
/* Set up the MAC address */
if (dev->enetaddr[0] & 0x01) {
printf("%s: MacAddress is multcast address\n",
__FUNCTION__);
return -1;
err = init_phy(dev);
if (err) {
printf("%s: Cannot initialize PHY, aborting.\n",
dev->name);
return err;
}
uec_set_mac_address(uec, dev->enetaddr);
curphy = uec->mii_info->phyinfo;
if (curphy->config_aneg) {
err = curphy->config_aneg(uec->mii_info);
if (err) {
printf("%s: Can't negotiate PHY\n", dev->name);
return err;
}
}
/* Give PHYs up to 5 sec to report a link */
i = 50;
do {
err = curphy->read_status(uec->mii_info);
udelay(100000);
} while (((i-- > 0) && !uec->mii_info->link) || err);
if (err || i <= 0)
printf("warning: %s: timeout on PHY link\n", dev->name);
uec->the_first_run = 1;
}
/* Set up the MAC address */
if (dev->enetaddr[0] & 0x01) {
printf("%s: MacAddress is multcast address\n",
__FUNCTION__);
return -1;
}
uec_set_mac_address(uec, dev->enetaddr);
err = uec_open(uec, COMM_DIR_RX_AND_TX);
if (err) {
printf("%s: cannot enable UEC device\n", dev->name);
return -1;
}
phy_change(dev);
return (uec->mii_info->link ? 0 : -1);
}
@ -1261,6 +1323,10 @@ int uec_initialize(int index)
} else if (index == 2) {
#ifdef CONFIG_UEC_ETH3
uec_info = &eth3_uec_info;
#endif
} else if (index == 3) {
#ifdef CONFIG_UEC_ETH4
uec_info = &eth4_uec_info;
#endif
} else {
printf("%s: index is illegal.\n", __FUNCTION__);
@ -1289,14 +1355,6 @@ int uec_initialize(int index)
return err;
}
err = init_phy(dev);
if (err) {
printf("%s: Cannot initialize PHY, aborting.\n", dev->name);
return err;
}
phy_change(dev);
return 1;
}
#endif /* CONFIG_QE */

View File

@ -28,7 +28,6 @@
#if defined(CONFIG_QE)
#define UEC_VERBOSE_DEBUG
#define ugphy_printk(format, arg...) \
printf(format "\n", ## arg)
@ -77,11 +76,10 @@ void uec_write_phy_reg (struct eth_device *dev, int mii_id, int regnum, int valu
/* Setting up the MII Mangement Control Register with the value */
out_be32 (&ug_regs->miimcon, (u32) value);
sync();
/* Wait till MII management write is complete */
while ((in_be32 (&ug_regs->miimind)) & MIIMIND_BUSY);
udelay (100000);
}
/* Reads from register regnum in the PHY for device dev, */
@ -101,20 +99,21 @@ int uec_read_phy_reg (struct eth_device *dev, int mii_id, int regnum)
tmp_reg = ((u32) mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | mii_reg;
out_be32 (&ug_regs->miimadd, tmp_reg);
/* Perform an MII management read cycle */
/* clear MII management command cycle */
out_be32 (&ug_regs->miimcom, 0);
sync();
/* Perform an MII management read cycle */
out_be32 (&ug_regs->miimcom, MIIMCOM_READ_CYCLE);
/* Wait till MII management write is complete */
while ((in_be32 (&ug_regs->miimind)) &
(MIIMIND_NOT_VALID | MIIMIND_BUSY));
udelay (100000);
/* Read MII management status */
value = (u16) in_be32 (&ug_regs->miimstat);
if (value == 0xffff)
ugphy_warn
ugphy_vdbg
("read wrong value : mii_id %d,mii_reg %d, base %08x",
mii_id, mii_reg, (u32) & (ug_regs->miimcfg));
@ -270,20 +269,38 @@ static int genmii_update_link (struct uec_mii_info *mii_info)
{
u16 status;
/* Do a fake read */
/* Status is read once to clear old link state */
phy_read (mii_info, PHY_BMSR);
/* Read link and autonegotiation status */
status = phy_read (mii_info, PHY_BMSR);
if ((status & PHY_BMSR_LS) == 0)
mii_info->link = 0;
else
mii_info->link = 1;
/*
* 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, PHY_BMSR);
if ((status & PHY_BMSR_LS) && (status & PHY_BMSR_AUTN_ABLE)
&& !(status & PHY_BMSR_AUTN_COMP)) {
int i = 0;
/* If we are autonegotiating, and not done,
* return an error */
if (mii_info->autoneg && !(status & PHY_BMSR_AUTN_COMP))
return -EAGAIN;
while (!(status & PHY_BMSR_AUTN_COMP)) {
/*
* Timeout reached ?
*/
if (i > UGETH_AN_TIMEOUT) {
mii_info->link = 0;
return 0;
}
udelay(1000); /* 1 ms */
status = phy_read(mii_info, PHY_BMSR);
}
mii_info->link = 1;
udelay(500000); /* another 500 ms (results in faster booting) */
} else {
if (status & PHY_BMSR_LS)
mii_info->link = 1;
else
mii_info->link = 0;
}
return 0;
}
@ -389,16 +406,12 @@ static int dm9161_init (struct uec_mii_info *mii_info)
/* PHY and MAC connect */
phy_write (mii_info, PHY_BMCR, phy_read (mii_info, PHY_BMCR) &
~PHY_BMCR_ISO);
#ifdef CONFIG_RMII_MODE
phy_write (mii_info, MII_DM9161_SCR, MII_DM9161_SCR_RMII_INIT);
#else
phy_write (mii_info, MII_DM9161_SCR, MII_DM9161_SCR_INIT);
#endif
config_genmii_advert (mii_info);
/* Start/restart aneg */
genmii_config_aneg (mii_info);
/* Delay to wait the aneg compeleted */
udelay (3000000);
return 0;
}

View File

@ -217,6 +217,9 @@ int eth_initialize(bd_t *bis)
#if defined(CONFIG_UEC_ETH3)
uec_initialize(2);
#endif
#if defined(CONFIG_UEC_ETH4)
uec_initialize(3);
#endif
#if defined(FEC_ENET) || defined(CONFIG_ETHER_ON_FCC)
fec_initialize(bis);
@ -522,6 +525,15 @@ int eth_receive(volatile void *packet, int length)
void eth_try_another(int first_restart)
{
static struct eth_device *first_failed = NULL;
char *ethrotate;
/*
* Do not rotate between network interfaces when
* 'ethrotate' variable is set to 'no'.
*/
if (((ethrotate = getenv ("ethrotate")) != NULL) &&
(strcmp(ethrotate, "no") == 0))
return;
if (!eth_current)
return;