Commit f9eabcb3 authored by Wolfgang Denk's avatar Wolfgang Denk
Browse files

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

parents 2c78febd 2d934ea5
......@@ -751,6 +751,9 @@ The following options need to be configured:
CONFIG_E1000
Support for Intel 8254x gigabit chips.
CONFIG_E1000_FALLBACK_MAC
default MAC for empty eeprom after production.
CONFIG_EEPRO100
Support for Intel 82557/82559/82559ER chips.
Optional CONFIG_EEPRO100_SROM_WRITE enables eeprom
......@@ -1151,6 +1154,20 @@ The following options need to be configured:
of the "hostname" environment variable is passed as
option 12 to the DHCP server.
CONFIG_BOOTP_DHCP_REQUEST_DELAY
A 32bit value in microseconds for a delay between
receiving a "DHCP Offer" and sending the "DHCP Request".
This fixes a problem with certain DHCP servers that don't
respond 100% of the time to a "DHCP request". E.g. On an
AT91RM9200 processor running at 180MHz, this delay needed
to be *at least* 15,000 usec before a Windows Server 2003
DHCP server would reply 100% of the time. I recommend at
least 50,000 usec to be safe. The alternative is to hope
that one of the retries will be successful but note that
the DHCP timeout and retry process takes a longer than
this delay.
- CDP Options:
CONFIG_CDP_DEVICE_ID
......
......@@ -306,7 +306,7 @@ int do_mii (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
return 1;
}
#if defined(CONFIG_8xx) || defined(CONFIG_MCF532x)
#if defined(CONFIG_8xx) || defined(CONFIG_MCF532x) || defined(CONFIG_MII_INIT)
mii_init ();
#endif
......
......@@ -35,6 +35,7 @@ COBJS-y += e1000.o
COBJS-y += eepro100.o
COBJS-y += enc28j60.o
COBJS-y += fsl_mcdmafec.o
COBJS-$(CONFIG_GRETH) += greth.o
COBJS-y += inca-ip_sw.o
COBJS-y += ks8695eth.o
COBJS-y += lan91c96.o
......
/**************************************************************************
Inter Pro 1000 for ppcboot/das-u-boot
Intel Pro 1000 for ppcboot/das-u-boot
Drivers are port from Intel's Linux driver e1000-4.3.15
and from Etherboot pro 1000 driver by mrakes at vivato dot net
tested on both gig copper and gig fiber boards
......@@ -82,6 +82,7 @@ static struct pci_device_id supported[] = {
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82545EM_FIBER},
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82546EB_FIBER},
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82540EM_LOM},
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82541ER},
};
/* Function forward declarations */
......@@ -512,6 +513,11 @@ e1000_read_mac_addr(struct eth_device *nic)
/* Invert the last bit if this is the second device */
nic->enetaddr[5] += 1;
}
#ifdef CONFIG_E1000_FALLBACK_MAC
if ( *(u32*)(nic->enetaddr) == 0 || *(u32*)(nic->enetaddr) == ~0 )
for ( i=0; i < NODE_ADDRESS_SIZE; i++ )
nic->enetaddr[i] = (CONFIG_E1000_FALLBACK_MAC >> (8*(5-i))) & 0xff;
#endif
#else
/*
* The AP1000's e1000 has no eeprom; the MAC address is stored in the
......@@ -639,6 +645,9 @@ e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_82546EB_FIBER:
hw->mac_type = e1000_82546;
break;
case E1000_DEV_ID_82541ER:
hw->mac_type = e1000_82541_rev_2;
break;
default:
/* Should never have loaded on this device */
return -E1000_ERR_MAC_TYPE;
......@@ -2485,6 +2494,36 @@ e1000_phy_reset(struct e1000_hw *hw)
return 0;
}
static int
e1000_set_phy_type(struct e1000_hw *hw)
{
DEBUGFUNC();
if(hw->mac_type == e1000_undefined)
return -E1000_ERR_PHY_TYPE;
switch(hw->phy_id) {
case M88E1000_E_PHY_ID:
case M88E1000_I_PHY_ID:
case M88E1011_I_PHY_ID:
hw->phy_type = e1000_phy_m88;
break;
case IGP01E1000_I_PHY_ID:
if(hw->mac_type == e1000_82541 ||
hw->mac_type == e1000_82541_rev_2) {
hw->phy_type = e1000_phy_igp;
break;
}
/* Fall Through */
default:
/* Should never have loaded on this device */
hw->phy_type = e1000_phy_undefined;
return -E1000_ERR_PHY_TYPE;
}
return E1000_SUCCESS;
}
/******************************************************************************
* Probes the expected PHY address for known PHY IDs
*
......@@ -2493,6 +2532,7 @@ e1000_phy_reset(struct e1000_hw *hw)
static int
e1000_detect_gig_phy(struct e1000_hw *hw)
{
int32_t phy_init_status;
uint16_t phy_id_high, phy_id_low;
int match = FALSE;
......@@ -2526,11 +2566,19 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
if (hw->phy_id == M88E1011_I_PHY_ID)
match = TRUE;
break;
case e1000_82541_rev_2:
if(hw->phy_id == IGP01E1000_I_PHY_ID)
match = TRUE;
break;
default:
DEBUGOUT("Invalid MAC type %d\n", hw->mac_type);
return -E1000_ERR_CONFIG;
}
if (match) {
phy_init_status = e1000_set_phy_type(hw);
if ((match) && (phy_init_status == E1000_SUCCESS)) {
DEBUGOUT("PHY ID 0x%X detected\n", hw->phy_id);
return 0;
}
......@@ -2985,7 +3033,7 @@ e1000_initialize(bd_t * bis)
free(nic);
return 0;
}
#ifndef CONFIG_AP1000
#if !(defined(CONFIG_AP1000) || defined(CONFIG_MVBC_1G))
if (e1000_validate_eeprom_checksum(nic) < 0) {
printf("The EEPROM Checksum Is Not Valid\n");
free(hw);
......
......@@ -71,6 +71,8 @@ typedef enum {
e1000_82540,
e1000_82545,
e1000_82546,
e1000_82541,
e1000_82541_rev_2,
e1000_num_macs
} e1000_mac_type;
......@@ -168,6 +170,13 @@ typedef enum {
e1000_1000t_rx_status_undefined = 0xFF
} e1000_1000t_rx_status;
typedef enum {
e1000_phy_m88 = 0,
e1000_phy_igp,
e1000_phy_igp_2,
e1000_phy_undefined = 0xFF
} e1000_phy_type;
struct e1000_phy_info {
e1000_cable_length cable_length;
e1000_10bt_ext_dist_enable extended_10bt_distance;
......@@ -184,14 +193,19 @@ struct e1000_phy_stats {
};
/* Error Codes */
#define E1000_SUCCESS 0
#define E1000_ERR_EEPROM 1
#define E1000_ERR_PHY 2
#define E1000_ERR_CONFIG 3
#define E1000_ERR_PARAM 4
#define E1000_ERR_MAC_TYPE 5
#define E1000_ERR_NOLINK 6
#define E1000_ERR_TIMEOUT 7
#define E1000_SUCCESS 0
#define E1000_ERR_EEPROM 1
#define E1000_ERR_PHY 2
#define E1000_ERR_CONFIG 3
#define E1000_ERR_PARAM 4
#define E1000_ERR_MAC_TYPE 5
#define E1000_ERR_PHY_TYPE 6
#define E1000_ERR_NOLINK 7
#define E1000_ERR_TIMEOUT 8
#define E1000_ERR_RESET 9
#define E1000_ERR_MASTER_REQUESTS_PENDING 10
#define E1000_ERR_HOST_INTERFACE_COMMAND 11
#define E1000_BLK_PHY_RESET 12
/* PCI Device IDs */
#define E1000_DEV_ID_82542 0x1000
......@@ -207,7 +221,8 @@ struct e1000_phy_stats {
#define E1000_DEV_ID_82545EM_FIBER 0x1011
#define E1000_DEV_ID_82546EB_COPPER 0x1010
#define E1000_DEV_ID_82546EB_FIBER 0x1012
#define NUM_DEV_IDS 13
#define E1000_DEV_ID_82541ER 0x1078
#define NUM_DEV_IDS 14
#define NODE_ADDRESS_SIZE 6
#define ETH_LENGTH_OF_ADDRESS 6
......@@ -799,6 +814,8 @@ struct e1000_hw {
pci_dev_t pdev;
uint8_t *hw_addr;
e1000_mac_type mac_type;
e1000_phy_type phy_type;
uint32_t phy_init_script;
e1000_media_type media_type;
e1000_lan_loc lan_loc;
e1000_fc_type fc;
......@@ -1517,7 +1534,22 @@ struct e1000_hw {
#define M88E1000_EXT_PHY_SPEC_CTRL 0x14 /* Extended PHY Specific Control */
#define M88E1000_RX_ERR_CNTR 0x15 /* Receive Error Counter */
#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */
#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */
/* IGP01E1000 specifics */
#define IGP01E1000_IEEE_REGS_PAGE 0x0000
#define IGP01E1000_IEEE_RESTART_AUTONEG 0x3300
#define IGP01E1000_IEEE_FORCE_GIGA 0x0140
/* IGP01E1000 Specific Registers */
#define IGP01E1000_PHY_PORT_CONFIG 0x10 /* PHY Specific Port Config Register */
#define IGP01E1000_PHY_PORT_STATUS 0x11 /* PHY Specific Status Register */
#define IGP01E1000_PHY_PORT_CTRL 0x12 /* PHY Specific Control Register */
#define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health Register */
#define IGP01E1000_GMII_FIFO 0x14 /* GMII FIFO Register */
#define IGP01E1000_PHY_CHANNEL_QUALITY 0x15 /* PHY Channel Quality Register */
#define IGP02E1000_PHY_POWER_MGMT 0x19
#define IGP01E1000_PHY_PAGE_SELECT 0x1F /* PHY Page Select Core Register */
/* PHY Control Register */
#define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */
......@@ -1729,6 +1761,7 @@ struct e1000_hw {
#define M88E1011_I_PHY_ID 0x01410C20
#define M88E1000_12_PHY_ID M88E1000_E_PHY_ID
#define M88E1000_14_PHY_ID M88E1000_E_PHY_ID
#define IGP01E1000_I_PHY_ID 0x02A80380
/* Miscellaneous PHY bit definitions. */
#define PHY_PREAMBLE 0xFFFFFFFF
......
/* Gaisler.com GRETH 10/100/1000 Ethernet MAC driver
*
* Driver use polling mode (no Interrupt)
*
* (C) Copyright 2007
* Daniel Hellstrom, Gaisler Research, daniel@gaisler.com
*
* 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
*/
#include <common.h>
#include <command.h>
#include <net.h>
#include <malloc.h>
#include <asm/processor.h>
#include <ambapp.h>
#include <asm/leon.h>
/* #define DEBUG */
#include "greth.h"
/* Default to 3s timeout on autonegotiation */
#ifndef GRETH_PHY_TIMEOUT_MS
#define GRETH_PHY_TIMEOUT_MS 3000
#endif
/* ByPass Cache when reading regs */
#define GRETH_REGLOAD(addr) SPARC_NOCACHE_READ(addr)
/* Write-through cache ==> no bypassing needed on writes */
#define GRETH_REGSAVE(addr,data) (*(unsigned int *)(addr) = (data))
#define GRETH_REGORIN(addr,data) GRETH_REGSAVE(addr,GRETH_REGLOAD(addr)|data)
#define GRETH_REGANDIN(addr,data) GRETH_REGSAVE(addr,GRETH_REGLOAD(addr)&data)
#define GRETH_RXBD_CNT 4
#define GRETH_TXBD_CNT 1
#define GRETH_RXBUF_SIZE 1540
#define GRETH_BUF_ALIGN 4
#define GRETH_RXBUF_EFF_SIZE \
( (GRETH_RXBUF_SIZE&~(GRETH_BUF_ALIGN-1))+GRETH_BUF_ALIGN )
typedef struct {
greth_regs *regs;
int irq;
struct eth_device *dev;
/* Hardware info */
unsigned char phyaddr;
int gbit_mac;
/* Current operating Mode */
int gb; /* GigaBit */
int fd; /* Full Duplex */
int sp; /* 10/100Mbps speed (1=100,0=10) */
int auto_neg; /* Auto negotiate done */
unsigned char hwaddr[6]; /* MAC Address */
/* Descriptors */
greth_bd *rxbd_base, *rxbd_max;
greth_bd *txbd_base, *txbd_max;
greth_bd *rxbd_curr;
/* rx buffers in rx descriptors */
void *rxbuf_base; /* (GRETH_RXBUF_SIZE+ALIGNBYTES) * GRETH_RXBD_CNT */
/* unused for gbit_mac, temp buffer for sending packets with unligned
* start.
* Pointer to packet allocated with malloc.
*/
void *txbuf;
struct {
/* rx status */
unsigned int rx_packets,
rx_crc_errors, rx_frame_errors, rx_length_errors, rx_errors;
/* tx stats */
unsigned int tx_packets,
tx_latecol_errors,
tx_underrun_errors, tx_limit_errors, tx_errors;
} stats;
} greth_priv;
/* Read MII register 'addr' from core 'regs' */
static int read_mii(int addr, volatile greth_regs * regs)
{
while (GRETH_REGLOAD(&regs->mdio) & GRETH_MII_BUSY) {
}
GRETH_REGSAVE(&regs->mdio, (0 << 11) | ((addr & 0x1F) << 6) | 2);
while (GRETH_REGLOAD(&regs->mdio) & GRETH_MII_BUSY) {
}
if (!(GRETH_REGLOAD(&regs->mdio) & GRETH_MII_NVALID)) {
return (GRETH_REGLOAD(&regs->mdio) >> 16) & 0xFFFF;
} else {
return -1;
}
}
static void write_mii(int addr, int data, volatile greth_regs * regs)
{
while (GRETH_REGLOAD(&regs->mdio) & GRETH_MII_BUSY) {
}
GRETH_REGSAVE(&regs->mdio,
((data & 0xFFFF) << 16) | (0 << 11) | ((addr & 0x1F) << 6)
| 1);
while (GRETH_REGLOAD(&regs->mdio) & GRETH_MII_BUSY) {
}
}
/* init/start hardware and allocate descriptor buffers for rx side
*
*/
int greth_init(struct eth_device *dev, bd_t * bis)
{
int i;
greth_priv *greth = dev->priv;
greth_regs *regs = greth->regs;
#ifdef DEBUG
printf("greth_init\n");
#endif
GRETH_REGSAVE(&regs->control, 0);
if (!greth->rxbd_base) {
/* allocate descriptors */
greth->rxbd_base = (greth_bd *)
memalign(0x1000, GRETH_RXBD_CNT * sizeof(greth_bd));
greth->txbd_base = (greth_bd *)
memalign(0x1000, GRETH_RXBD_CNT * sizeof(greth_bd));
/* allocate buffers to all descriptors */
greth->rxbuf_base =
malloc(GRETH_RXBUF_EFF_SIZE * GRETH_RXBD_CNT);
}
/* initate rx decriptors */
for (i = 0; i < GRETH_RXBD_CNT; i++) {
greth->rxbd_base[i].addr = (unsigned int)
greth->rxbuf_base + (GRETH_RXBUF_EFF_SIZE * i);
/* enable desciptor & set wrap bit if last descriptor */
if (i >= (GRETH_RXBD_CNT - 1)) {
greth->rxbd_base[i].stat = GRETH_BD_EN | GRETH_BD_WR;
} else {
greth->rxbd_base[i].stat = GRETH_BD_EN;
}
}
/* initiate indexes */
greth->rxbd_curr = greth->rxbd_base;
greth->rxbd_max = greth->rxbd_base + (GRETH_RXBD_CNT - 1);
greth->txbd_max = greth->txbd_base + (GRETH_TXBD_CNT - 1);
/*
* greth->txbd_base->addr = 0;
* greth->txbd_base->stat = GRETH_BD_WR;
*/
/* initate tx decriptors */
for (i = 0; i < GRETH_TXBD_CNT; i++) {
greth->txbd_base[i].addr = 0;
/* enable desciptor & set wrap bit if last descriptor */
if (i >= (GRETH_RXBD_CNT - 1)) {
greth->txbd_base[i].stat = GRETH_BD_WR;
} else {
greth->txbd_base[i].stat = 0;
}
}
/**** SET HARDWARE REGS ****/
/* Set pointer to tx/rx descriptor areas */
GRETH_REGSAVE(&regs->rx_desc_p, (unsigned int)&greth->rxbd_base[0]);
GRETH_REGSAVE(&regs->tx_desc_p, (unsigned int)&greth->txbd_base[0]);
/* Enable Transmitter, GRETH will now scan descriptors for packets
* to transmitt */
#ifdef DEBUG
printf("greth_init: enabling receiver\n");
#endif
GRETH_REGORIN(&regs->control, GRETH_RXEN);
return 0;
}
/* Initiate PHY to a relevant speed
* return:
* - 0 = success
* - 1 = timeout/fail
*/
int greth_init_phy(greth_priv * dev, bd_t * bis)
{
greth_regs *regs = dev->regs;
int tmp, tmp1, tmp2, i;
unsigned int start, timeout;
/* X msecs to ticks */
timeout = usec2ticks(GRETH_PHY_TIMEOUT_MS * 1000);
/* Get system timer0 current value
* Total timeout is 5s
*/
start = get_timer(0);
/* get phy control register default values */
while ((tmp = read_mii(0, regs)) & 0x8000) {
if (get_timer(start) > timeout)
return 1; /* Fail */
}
/* reset PHY and wait for completion */
write_mii(0, 0x8000 | tmp, regs);
while (((tmp = read_mii(0, regs))) & 0x8000) {
if (get_timer(start) > timeout)
return 1; /* Fail */
}
/* Check if PHY is autoneg capable and then determine operating
* mode, otherwise force it to 10 Mbit halfduplex
*/
dev->gb = 0;
dev->fd = 0;
dev->sp = 0;
dev->auto_neg = 0;
if (!((tmp >> 12) & 1)) {
write_mii(0, 0, regs);
} else {
/* wait for auto negotiation to complete and then check operating mode */
dev->auto_neg = 1;
i = 0;
while (!(((tmp = read_mii(1, regs)) >> 5) & 1)) {
if (get_timer(start) > timeout) {
printf("Auto negotiation timed out. "
"Selecting default config\n");
tmp = read_mii(0, regs);
dev->gb = ((tmp >> 6) & 1)
&& !((tmp >> 13) & 1);
dev->sp = !((tmp >> 6) & 1)
&& ((tmp >> 13) & 1);
dev->fd = (tmp >> 8) & 1;
goto auto_neg_done;
}
}
if ((tmp >> 8) & 1) {
tmp1 = read_mii(9, regs);
tmp2 = read_mii(10, regs);
if ((tmp1 & GRETH_MII_EXTADV_1000FD) &&
(tmp2 & GRETH_MII_EXTPRT_1000FD)) {
dev->gb = 1;
dev->fd = 1;
}
if ((tmp1 & GRETH_MII_EXTADV_1000HD) &&
(tmp2 & GRETH_MII_EXTPRT_1000HD)) {
dev->gb = 1;
dev->fd = 0;
}
}
if ((dev->gb == 0) || ((dev->gb == 1) && (dev->gbit_mac == 0))) {
tmp1 = read_mii(4, regs);
tmp2 = read_mii(5, regs);
if ((tmp1 & GRETH_MII_100TXFD) &&
(tmp2 & GRETH_MII_100TXFD)) {
dev->sp = 1;
dev->fd = 1;
}
if ((tmp1 & GRETH_MII_100TXHD) &&
(tmp2 & GRETH_MII_100TXHD)) {
dev->sp = 1;
dev->fd = 0;
}
if ((tmp1 & GRETH_MII_10FD) && (tmp2 & GRETH_MII_10FD)) {
dev->fd = 1;
}
if ((dev->gb == 1) && (dev->gbit_mac == 0)) {
dev->gb = 0;
dev->fd = 0;
write_mii(0, dev->sp << 13, regs);
}
}
}
auto_neg_done:
#ifdef DEBUG
printf("%s GRETH Ethermac at [0x%x] irq %d. Running \
%d Mbps %s duplex\n", dev->gbit_mac ? "10/100/1000" : "10/100", (unsigned int)(regs), (unsigned int)(dev->irq), dev->gb ? 1000 : (dev->sp ? 100 : 10), dev->fd ? "full" : "half");
#endif
/* Read out PHY info if extended registers are available */
if (tmp & 1) {
tmp1 = read_mii(2, regs);
tmp2 = read_mii(3, regs);
tmp1 = (tmp1 << 6) | ((tmp2 >> 10) & 0x3F);
tmp = tmp2 & 0xF;
tmp2 = (tmp2 >> 4) & 0x3F;
#ifdef DEBUG
printf("PHY: Vendor %x Device %x Revision %d\n", tmp1,
tmp2, tmp);
#endif
} else {
printf("PHY info not available\n");
}
/* set speed and duplex bits in control register */
GRETH_REGORIN(&regs->control,
(dev->gb << 8) | (dev->sp << 7) | (dev->fd << 4));
return 0;
}
void greth_halt(struct eth_device *dev)
{
greth_priv *greth;
greth_regs *regs;
int i;
#ifdef DEBUG
printf("greth_halt\n");
#endif
if (!dev || !dev->priv)
return;
greth = dev->priv;
regs = greth->regs;
if (!regs)
return;
/* disable receiver/transmitter by clearing the enable bits */
GRETH_REGANDIN(&regs->control, ~(GRETH_RXEN | GRETH_TXEN));
/* reset rx/tx descriptors */
if (greth->rxbd_base) {
for (i = 0; i < GRETH_RXBD_CNT; i++) {
greth->rxbd_base[i].stat =
(i >= (GRETH_RXBD_CNT - 1)) ? GRETH_BD_WR : 0;
}
}
if (greth->txbd_base) {
for (i = 0; i < GRETH_TXBD_CNT; i++) {
greth->txbd_base[i].stat =
(i >= (GRETH_TXBD_CNT - 1)) ? GRETH_BD_WR : 0;
}
}
}
int greth_send(struct eth_device *dev, volatile void *eth_data, int data_length)
{
greth_priv *greth = dev->priv;