mirror of
https://github.com/u-boot/u-boot.git
synced 2024-11-30 08:03:32 +08:00
Merge branch 'master' of git://www.denx.de/git/u-boot-net
This commit is contained in:
commit
2468592d79
4
README
4
README
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
112
drivers/qe/uec.c
112
drivers/qe/uec.c
@ -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 = ð3_uec_info;
|
||||
#endif
|
||||
} else if (index == 3) {
|
||||
#ifdef CONFIG_UEC_ETH4
|
||||
uec_info = ð4_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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
12
net/eth.c
12
net/eth.c
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user