mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-19 21:51:31 +00:00
Merge branch 'master' of git://www.denx.de/git/u-boot-net
This commit is contained in:
commit
2468592d79
10 changed files with 273 additions and 122 deletions
4
README
4
README
|
@ -2699,6 +2699,10 @@ Some configuration options can be set using Environment Variables:
|
||||||
=> setenv ethact SCC ETHERNET
|
=> setenv ethact SCC ETHERNET
|
||||||
=> ping 10.0.0.1 # traffic sent on 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
|
netretry - When set to "no" each network operation will
|
||||||
either succeed or fail without retrying.
|
either succeed or fail without retrying.
|
||||||
When set to "once" the network operation will
|
When set to "once" the network operation will
|
||||||
|
|
|
@ -30,8 +30,25 @@
|
||||||
#include <command.h>
|
#include <command.h>
|
||||||
#include <asm/blackfin.h>
|
#include <asm/blackfin.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
#include <net.h>
|
||||||
#include "ether_bf537.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;
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
#define POST_WORD_ADDR 0xFF903FFC
|
#define POST_WORD_ADDR 0xFF903FFC
|
||||||
|
|
|
@ -69,42 +69,3 @@ void SoftResetPHY(void);
|
||||||
void DumpPHYRegs(void);
|
void DumpPHYRegs(void);
|
||||||
|
|
||||||
int SetupSystemRegs(int *opmode);
|
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(
|
U_BOOT_CMD(
|
||||||
nfs, 3, 1, do_nfs,
|
nfs, 3, 1, do_nfs,
|
||||||
"nfs\t- boot image via network using NFS protocol\n",
|
"nfs\t- boot image via network using NFS protocol\n",
|
||||||
"[loadAddress] [host ip addr:bootfilename]\n"
|
"[loadAddress] [[hostIPaddr:]bootfilename]\n"
|
||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -80,10 +80,7 @@
|
||||||
#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
|
#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
|
||||||
defined(CONFIG_RTL8139)
|
defined(CONFIG_RTL8139)
|
||||||
|
|
||||||
#define TICKS_PER_SEC CFG_HZ
|
#define RTL_TIMEOUT 100000
|
||||||
#define TICKS_PER_MS (TICKS_PER_SEC/1000)
|
|
||||||
|
|
||||||
#define RTL_TIMEOUT (1*TICKS_PER_SEC)
|
|
||||||
|
|
||||||
#define ETH_FRAME_LEN 1514
|
#define ETH_FRAME_LEN 1514
|
||||||
#define ETH_ALEN 6
|
#define ETH_ALEN 6
|
||||||
|
@ -392,6 +389,7 @@ static void rtl_reset(struct eth_device *dev)
|
||||||
#ifdef DEBUG_RX
|
#ifdef DEBUG_RX
|
||||||
printf("rx ring address is %X\n",(unsigned long)rx_ring);
|
printf("rx ring address is %X\n",(unsigned long)rx_ring);
|
||||||
#endif
|
#endif
|
||||||
|
flush_cache((unsigned long)rx_ring, RX_BUF_LEN);
|
||||||
outl(phys_to_bus((int)rx_ring), ioaddr + RxBuf);
|
outl(phys_to_bus((int)rx_ring), ioaddr + RxBuf);
|
||||||
|
|
||||||
/* If we add multicast support, the MAR0 register would have to be
|
/* 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)
|
static int rtl_transmit(struct eth_device *dev, volatile void *packet, int length)
|
||||||
{
|
{
|
||||||
unsigned int status, to;
|
unsigned int status;
|
||||||
unsigned long txstatus;
|
unsigned long txstatus;
|
||||||
unsigned int len = length;
|
unsigned int len = length;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
ioaddr = dev->iobase;
|
ioaddr = dev->iobase;
|
||||||
|
|
||||||
|
@ -432,12 +431,11 @@ static int rtl_transmit(struct eth_device *dev, volatile void *packet, int lengt
|
||||||
tx_buffer[len++] = '\0';
|
tx_buffer[len++] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flush_cache((unsigned long)tx_buffer, length);
|
||||||
outl(phys_to_bus((int)tx_buffer), ioaddr + TxAddr0 + cur_tx*4);
|
outl(phys_to_bus((int)tx_buffer), ioaddr + TxAddr0 + cur_tx*4);
|
||||||
outl(((TX_FIFO_THRESH<<11) & 0x003f0000) | len,
|
outl(((TX_FIFO_THRESH<<11) & 0x003f0000) | len,
|
||||||
ioaddr + TxStatus0 + cur_tx*4);
|
ioaddr + TxStatus0 + cur_tx*4);
|
||||||
|
|
||||||
to = currticks() + RTL_TIMEOUT;
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
status = inw(ioaddr + IntrStatus);
|
status = inw(ioaddr + IntrStatus);
|
||||||
/* Only acknlowledge interrupt sources we can properly handle
|
/* 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. */
|
* rtl_poll() function. */
|
||||||
outw(status & (TxOK | TxErr | PCIErr), ioaddr + IntrStatus);
|
outw(status & (TxOK | TxErr | PCIErr), ioaddr + IntrStatus);
|
||||||
if ((status & (TxOK | TxErr | PCIErr)) != 0) break;
|
if ((status & (TxOK | TxErr | PCIErr)) != 0) break;
|
||||||
} while (currticks() < to);
|
udelay(10);
|
||||||
|
} while (i++ < RTL_TIMEOUT);
|
||||||
|
|
||||||
txstatus = inl(ioaddr + TxStatus0 + cur_tx*4);
|
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;
|
return length;
|
||||||
} else {
|
} else {
|
||||||
#ifdef DEBUG_TX
|
#ifdef DEBUG_TX
|
||||||
printf("tx timeout/error (%d ticks), status %hX txstatus %X\n",
|
printf("tx timeout/error (%d usecs), status %hX txstatus %X\n",
|
||||||
currticks()-to, status, txstatus);
|
10*i, status, txstatus);
|
||||||
#endif
|
#endif
|
||||||
rtl_reset(dev);
|
rtl_reset(dev);
|
||||||
|
|
||||||
|
@ -489,7 +488,8 @@ static int rtl_poll(struct eth_device *dev)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ring_offs = cur_rx % RX_BUF_LEN;
|
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_size = rx_status >> 16;
|
||||||
rx_status &= 0xffff;
|
rx_status &= 0xffff;
|
||||||
|
|
||||||
|
@ -519,6 +519,7 @@ static int rtl_poll(struct eth_device *dev)
|
||||||
printf("rx packet %d bytes", rx_size-4);
|
printf("rx packet %d bytes", rx_size-4);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
flush_cache((unsigned long)rx_ring, RX_BUF_LEN);
|
||||||
|
|
||||||
cur_rx = (cur_rx + rx_size + 4 + 3) & ~3;
|
cur_rx = (cur_rx + rx_size + 4 + 3) & ~3;
|
||||||
outw(cur_rx - 16, ioaddr + RxBufPtr);
|
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
|
* It will wait for the write to be done (or for a timeout to
|
||||||
* expire) before exiting
|
* 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;
|
volatile tsec_t *regbase = priv->phyregs;
|
||||||
uint phyid = priv->phyaddr;
|
|
||||||
int timeout = 1000000;
|
int timeout = 1000000;
|
||||||
|
|
||||||
regbase->miimadd = (phyid << 8) | regnum;
|
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--) ;
|
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
|
/* Reads register regnum on the device's PHY through the
|
||||||
* registers specified in priv. It lowers and raises the read
|
* registers specified in priv. It lowers and raises the read
|
||||||
* command, and waits for the data to become valid (miimind
|
* command, and waits for the data to become valid (miimind
|
||||||
* notvalid bit cleared), and the bus to cease activity (miimind
|
* notvalid bit cleared), and the bus to cease activity (miimind
|
||||||
* busy bit cleared), and then returns the value
|
* 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;
|
uint value;
|
||||||
volatile tsec_t *regbase = priv->phyregs;
|
volatile tsec_t *regbase = priv->phyregs;
|
||||||
uint phyid = priv->phyaddr;
|
|
||||||
|
|
||||||
/* Put the address of the phy, and the register
|
/* Put the address of the phy, and the register
|
||||||
* number into MIIMADD */
|
* number into MIIMADD */
|
||||||
|
@ -288,6 +289,9 @@ uint read_phy_reg(struct tsec_private *priv, uint regnum)
|
||||||
return value;
|
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
|
/* Discover which PHY is attached to the device, and configure it
|
||||||
* properly. If the PHY is not recognized, then return 0
|
* properly. If the PHY is not recognized, then return 0
|
||||||
* (failure). Otherwise, return 1
|
* (failure). Otherwise, return 1
|
||||||
|
@ -571,6 +575,63 @@ uint mii_parse_88E1011_psr(uint mii_reg, struct tsec_private * priv)
|
||||||
return 0;
|
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
|
/* Parse the cis8201's status register for speed and duplex
|
||||||
* information
|
* 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[] = {
|
struct phy_info *phy_info[] = {
|
||||||
&phy_info_cis8204,
|
&phy_info_cis8204,
|
||||||
&phy_info_cis8201,
|
&phy_info_cis8201,
|
||||||
|
@ -1374,6 +1462,7 @@ struct phy_info *phy_info[] = {
|
||||||
&phy_info_lxt971,
|
&phy_info_lxt971,
|
||||||
&phy_info_VSC8244,
|
&phy_info_VSC8244,
|
||||||
&phy_info_dp83865,
|
&phy_info_dp83865,
|
||||||
|
&phy_info_rtl8211b,
|
||||||
&phy_info_generic,
|
&phy_info_generic,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -1497,18 +1586,6 @@ static void relocate_cmds(void)
|
||||||
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \
|
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \
|
||||||
&& !defined(BITBANGMII)
|
&& !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.
|
* 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 char reg, unsigned short *value)
|
||||||
{
|
{
|
||||||
unsigned short ret;
|
unsigned short ret;
|
||||||
struct tsec_private *priv = get_priv_for_phy(addr);
|
struct tsec_private *priv = privlist[0];
|
||||||
|
|
||||||
if (NULL == priv) {
|
if (NULL == priv) {
|
||||||
printf("Can't read PHY at address %d\n", addr);
|
printf("Can't read PHY at address %d\n", addr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = (unsigned short)read_phy_reg(priv, reg);
|
ret = (unsigned short)read_any_phy_reg(priv, addr, reg);
|
||||||
*value = ret;
|
*value = ret;
|
||||||
|
|
||||||
return 0;
|
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,
|
static int tsec_miiphy_write(char *devname, unsigned char addr,
|
||||||
unsigned char reg, unsigned short value)
|
unsigned char reg, unsigned short value)
|
||||||
{
|
{
|
||||||
struct tsec_private *priv = get_priv_for_phy(addr);
|
struct tsec_private *priv = privlist[0];
|
||||||
|
|
||||||
if (NULL == priv) {
|
if (NULL == priv) {
|
||||||
printf("Can't write PHY at address %d\n", addr);
|
printf("Can't write PHY at address %d\n", addr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
write_phy_reg(priv, reg, value);
|
write_any_phy_reg(priv, addr, reg, value);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -184,6 +184,14 @@
|
||||||
#define MIIM_88E1145_PHY_PAGE 29
|
#define MIIM_88E1145_PHY_PAGE 29
|
||||||
#define MIIM_88E1145_PHY_CAL_OV 30
|
#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 */
|
/* DM9161 Control register values */
|
||||||
#define MIIM_DM9161_CR_STOP 0x0400
|
#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,
|
.tx_clock = CFG_UEC1_TX_CLK,
|
||||||
.eth_type = CFG_UEC1_ETH_TYPE,
|
.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_tx = UEC_NUM_OF_THREADS_4,
|
||||||
.num_threads_rx = UEC_NUM_OF_THREADS_4,
|
.num_threads_rx = UEC_NUM_OF_THREADS_4,
|
||||||
|
#endif
|
||||||
.riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
|
.riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
|
||||||
.riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
|
.riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
|
||||||
.tx_bd_ring_len = 16,
|
.tx_bd_ring_len = 16,
|
||||||
|
@ -58,8 +63,13 @@ static uec_info_t eth2_uec_info = {
|
||||||
.tx_clock = CFG_UEC2_TX_CLK,
|
.tx_clock = CFG_UEC2_TX_CLK,
|
||||||
.eth_type = CFG_UEC2_ETH_TYPE,
|
.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_tx = UEC_NUM_OF_THREADS_4,
|
||||||
.num_threads_rx = UEC_NUM_OF_THREADS_4,
|
.num_threads_rx = UEC_NUM_OF_THREADS_4,
|
||||||
|
#endif
|
||||||
.riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
|
.riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
|
||||||
.riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
|
.riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
|
||||||
.tx_bd_ring_len = 16,
|
.tx_bd_ring_len = 16,
|
||||||
|
@ -68,7 +78,6 @@ static uec_info_t eth2_uec_info = {
|
||||||
.enet_interface = CFG_UEC2_INTERFACE_MODE,
|
.enet_interface = CFG_UEC2_INTERFACE_MODE,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_UEC_ETH3
|
#ifdef CONFIG_UEC_ETH3
|
||||||
static uec_info_t eth3_uec_info = {
|
static uec_info_t eth3_uec_info = {
|
||||||
.uf_info = {
|
.uf_info = {
|
||||||
|
@ -77,8 +86,13 @@ static uec_info_t eth3_uec_info = {
|
||||||
.tx_clock = CFG_UEC3_TX_CLK,
|
.tx_clock = CFG_UEC3_TX_CLK,
|
||||||
.eth_type = CFG_UEC3_ETH_TYPE,
|
.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_tx = UEC_NUM_OF_THREADS_4,
|
||||||
.num_threads_rx = UEC_NUM_OF_THREADS_4,
|
.num_threads_rx = UEC_NUM_OF_THREADS_4,
|
||||||
|
#endif
|
||||||
.riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
|
.riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
|
||||||
.riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
|
.riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
|
||||||
.tx_bd_ring_len = 16,
|
.tx_bd_ring_len = 16,
|
||||||
|
@ -87,6 +101,29 @@ static uec_info_t eth3_uec_info = {
|
||||||
.enet_interface = CFG_UEC3_INTERFACE_MODE,
|
.enet_interface = CFG_UEC3_INTERFACE_MODE,
|
||||||
};
|
};
|
||||||
#endif
|
#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)
|
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;
|
uec->mii_info = mii_info;
|
||||||
|
|
||||||
|
qe_set_mii_clk_src(uec->uec_info->uf_info.ucc_num);
|
||||||
|
|
||||||
if (init_mii_management_configuration(umii_regs)) {
|
if (init_mii_management_configuration(umii_regs)) {
|
||||||
printf("%s: The MII Bus is stuck!", dev->name);
|
printf("%s: The MII Bus is stuck!", dev->name);
|
||||||
err = -1;
|
err = -1;
|
||||||
|
@ -581,21 +620,12 @@ static void adjust_link(struct eth_device *dev)
|
||||||
static void phy_change(struct eth_device *dev)
|
static void phy_change(struct eth_device *dev)
|
||||||
{
|
{
|
||||||
uec_private_t *uec = (uec_private_t *)dev->priv;
|
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 */
|
/* 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 */
|
/* 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)
|
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)
|
static int uec_init(struct eth_device* dev, bd_t *bd)
|
||||||
{
|
{
|
||||||
uec_private_t *uec;
|
uec_private_t *uec;
|
||||||
int err;
|
int err, i;
|
||||||
|
struct phy_info *curphy;
|
||||||
|
|
||||||
uec = (uec_private_t *)dev->priv;
|
uec = (uec_private_t *)dev->priv;
|
||||||
|
|
||||||
if (uec->the_first_run == 0) {
|
if (uec->the_first_run == 0) {
|
||||||
/* Set up the MAC address */
|
err = init_phy(dev);
|
||||||
if (dev->enetaddr[0] & 0x01) {
|
if (err) {
|
||||||
printf("%s: MacAddress is multcast address\n",
|
printf("%s: Cannot initialize PHY, aborting.\n",
|
||||||
__FUNCTION__);
|
dev->name);
|
||||||
return -1;
|
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;
|
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);
|
err = uec_open(uec, COMM_DIR_RX_AND_TX);
|
||||||
if (err) {
|
if (err) {
|
||||||
printf("%s: cannot enable UEC device\n", dev->name);
|
printf("%s: cannot enable UEC device\n", dev->name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
phy_change(dev);
|
||||||
|
|
||||||
return (uec->mii_info->link ? 0 : -1);
|
return (uec->mii_info->link ? 0 : -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1261,6 +1323,10 @@ int uec_initialize(int index)
|
||||||
} else if (index == 2) {
|
} else if (index == 2) {
|
||||||
#ifdef CONFIG_UEC_ETH3
|
#ifdef CONFIG_UEC_ETH3
|
||||||
uec_info = ð3_uec_info;
|
uec_info = ð3_uec_info;
|
||||||
|
#endif
|
||||||
|
} else if (index == 3) {
|
||||||
|
#ifdef CONFIG_UEC_ETH4
|
||||||
|
uec_info = ð4_uec_info;
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
printf("%s: index is illegal.\n", __FUNCTION__);
|
printf("%s: index is illegal.\n", __FUNCTION__);
|
||||||
|
@ -1289,14 +1355,6 @@ int uec_initialize(int index)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = init_phy(dev);
|
|
||||||
if (err) {
|
|
||||||
printf("%s: Cannot initialize PHY, aborting.\n", dev->name);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
phy_change(dev);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_QE */
|
#endif /* CONFIG_QE */
|
||||||
|
|
|
@ -28,7 +28,6 @@
|
||||||
|
|
||||||
#if defined(CONFIG_QE)
|
#if defined(CONFIG_QE)
|
||||||
|
|
||||||
#define UEC_VERBOSE_DEBUG
|
|
||||||
#define ugphy_printk(format, arg...) \
|
#define ugphy_printk(format, arg...) \
|
||||||
printf(format "\n", ## 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 */
|
/* Setting up the MII Mangement Control Register with the value */
|
||||||
out_be32 (&ug_regs->miimcon, (u32) value);
|
out_be32 (&ug_regs->miimcon, (u32) value);
|
||||||
|
sync();
|
||||||
|
|
||||||
/* Wait till MII management write is complete */
|
/* Wait till MII management write is complete */
|
||||||
while ((in_be32 (&ug_regs->miimind)) & MIIMIND_BUSY);
|
while ((in_be32 (&ug_regs->miimind)) & MIIMIND_BUSY);
|
||||||
|
|
||||||
udelay (100000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reads from register regnum in the PHY for device dev, */
|
/* 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;
|
tmp_reg = ((u32) mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | mii_reg;
|
||||||
out_be32 (&ug_regs->miimadd, tmp_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);
|
out_be32 (&ug_regs->miimcom, 0);
|
||||||
|
sync();
|
||||||
|
|
||||||
|
/* Perform an MII management read cycle */
|
||||||
out_be32 (&ug_regs->miimcom, MIIMCOM_READ_CYCLE);
|
out_be32 (&ug_regs->miimcom, MIIMCOM_READ_CYCLE);
|
||||||
|
|
||||||
/* Wait till MII management write is complete */
|
/* Wait till MII management write is complete */
|
||||||
while ((in_be32 (&ug_regs->miimind)) &
|
while ((in_be32 (&ug_regs->miimind)) &
|
||||||
(MIIMIND_NOT_VALID | MIIMIND_BUSY));
|
(MIIMIND_NOT_VALID | MIIMIND_BUSY));
|
||||||
|
|
||||||
udelay (100000);
|
|
||||||
|
|
||||||
/* Read MII management status */
|
/* Read MII management status */
|
||||||
value = (u16) in_be32 (&ug_regs->miimstat);
|
value = (u16) in_be32 (&ug_regs->miimstat);
|
||||||
if (value == 0xffff)
|
if (value == 0xffff)
|
||||||
ugphy_warn
|
ugphy_vdbg
|
||||||
("read wrong value : mii_id %d,mii_reg %d, base %08x",
|
("read wrong value : mii_id %d,mii_reg %d, base %08x",
|
||||||
mii_id, mii_reg, (u32) & (ug_regs->miimcfg));
|
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;
|
u16 status;
|
||||||
|
|
||||||
/* Do a fake read */
|
/* Status is read once to clear old link state */
|
||||||
phy_read (mii_info, PHY_BMSR);
|
phy_read (mii_info, PHY_BMSR);
|
||||||
|
|
||||||
/* Read link and autonegotiation status */
|
/*
|
||||||
status = phy_read (mii_info, PHY_BMSR);
|
* Wait if the link is up, and autonegotiation is in progress
|
||||||
if ((status & PHY_BMSR_LS) == 0)
|
* (ie - we're capable and it's not done)
|
||||||
mii_info->link = 0;
|
*/
|
||||||
else
|
status = phy_read(mii_info, PHY_BMSR);
|
||||||
mii_info->link = 1;
|
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,
|
while (!(status & PHY_BMSR_AUTN_COMP)) {
|
||||||
* return an error */
|
/*
|
||||||
if (mii_info->autoneg && !(status & PHY_BMSR_AUTN_COMP))
|
* Timeout reached ?
|
||||||
return -EAGAIN;
|
*/
|
||||||
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -389,16 +406,12 @@ static int dm9161_init (struct uec_mii_info *mii_info)
|
||||||
/* PHY and MAC connect */
|
/* PHY and MAC connect */
|
||||||
phy_write (mii_info, PHY_BMCR, phy_read (mii_info, PHY_BMCR) &
|
phy_write (mii_info, PHY_BMCR, phy_read (mii_info, PHY_BMCR) &
|
||||||
~PHY_BMCR_ISO);
|
~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);
|
phy_write (mii_info, MII_DM9161_SCR, MII_DM9161_SCR_INIT);
|
||||||
#endif
|
|
||||||
config_genmii_advert (mii_info);
|
config_genmii_advert (mii_info);
|
||||||
/* Start/restart aneg */
|
/* Start/restart aneg */
|
||||||
genmii_config_aneg (mii_info);
|
genmii_config_aneg (mii_info);
|
||||||
/* Delay to wait the aneg compeleted */
|
|
||||||
udelay (3000000);
|
|
||||||
|
|
||||||
return 0;
|
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)
|
#if defined(CONFIG_UEC_ETH3)
|
||||||
uec_initialize(2);
|
uec_initialize(2);
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(CONFIG_UEC_ETH4)
|
||||||
|
uec_initialize(3);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(FEC_ENET) || defined(CONFIG_ETHER_ON_FCC)
|
#if defined(FEC_ENET) || defined(CONFIG_ETHER_ON_FCC)
|
||||||
fec_initialize(bis);
|
fec_initialize(bis);
|
||||||
|
@ -522,6 +525,15 @@ int eth_receive(volatile void *packet, int length)
|
||||||
void eth_try_another(int first_restart)
|
void eth_try_another(int first_restart)
|
||||||
{
|
{
|
||||||
static struct eth_device *first_failed = NULL;
|
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)
|
if (!eth_current)
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Add table
Reference in a new issue