浏览代码

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

Wolfgang Denk 17 年之前
父节点
当前提交
f9eabcb357
共有 14 个文件被更改,包括 993 次插入17 次删除
  1. 17 0
      README
  2. 1 1
      common/cmd_mii.c
  3. 1 0
      drivers/net/Makefile
  4. 51 3
      drivers/net/e1000.c
  5. 43 10
      drivers/net/e1000.h
  6. 661 0
      drivers/net/greth.c
  7. 97 0
      drivers/net/greth.h
  8. 7 0
      drivers/net/mcffec.c
  9. 71 2
      drivers/net/smc91111.h
  10. 30 0
      drivers/net/tsec.c
  11. 5 0
      drivers/net/tsec.h
  12. 1 0
      include/pci_ids.h
  13. 4 1
      net/bootp.c
  14. 4 0
      net/eth.c

+ 17 - 0
README

@@ -751,6 +751,9 @@ The following options need to be configured:
 		CONFIG_E1000
 		CONFIG_E1000
 		Support for Intel 8254x gigabit chips.
 		Support for Intel 8254x gigabit chips.
 
 
+		CONFIG_E1000_FALLBACK_MAC
+		default MAC for empty eeprom after production.
+
 		CONFIG_EEPRO100
 		CONFIG_EEPRO100
 		Support for Intel 82557/82559/82559ER chips.
 		Support for Intel 82557/82559/82559ER chips.
 		Optional CONFIG_EEPRO100_SROM_WRITE enables eeprom
 		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
 		of the "hostname" environment variable is passed as
 		option 12 to the DHCP server.
 		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:
  - CDP Options:
 		CONFIG_CDP_DEVICE_ID
 		CONFIG_CDP_DEVICE_ID
 
 

+ 1 - 1
common/cmd_mii.c

@@ -306,7 +306,7 @@ int do_mii (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
 		return 1;
 		return 1;
 	}
 	}
 
 
-#if defined(CONFIG_8xx) || defined(CONFIG_MCF532x)
+#if defined(CONFIG_8xx) || defined(CONFIG_MCF532x) || defined(CONFIG_MII_INIT)
 	mii_init ();
 	mii_init ();
 #endif
 #endif
 
 

+ 1 - 0
drivers/net/Makefile

@@ -35,6 +35,7 @@ COBJS-y += e1000.o
 COBJS-y += eepro100.o
 COBJS-y += eepro100.o
 COBJS-y += enc28j60.o
 COBJS-y += enc28j60.o
 COBJS-y += fsl_mcdmafec.o
 COBJS-y += fsl_mcdmafec.o
+COBJS-$(CONFIG_GRETH) += greth.o
 COBJS-y += inca-ip_sw.o
 COBJS-y += inca-ip_sw.o
 COBJS-y += ks8695eth.o
 COBJS-y += ks8695eth.o
 COBJS-y += lan91c96.o
 COBJS-y += lan91c96.o

+ 51 - 3
drivers/net/e1000.c

@@ -1,5 +1,5 @@
 /**************************************************************************
 /**************************************************************************
-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
 Drivers are port from Intel's Linux driver e1000-4.3.15
 and from Etherboot pro 1000 driver by mrakes at vivato dot net
 and from Etherboot pro 1000 driver by mrakes at vivato dot net
 tested on both gig copper and gig fiber boards
 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_82545EM_FIBER},
 	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82546EB_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_82540EM_LOM},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82541ER},
 };
 };
 
 
 /* Function forward declarations */
 /* 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 */
 		/* Invert the last bit if this is the second device */
 		nic->enetaddr[5] += 1;
 		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
 #else
 	/*
 	/*
 	 * The AP1000's e1000 has no eeprom; the MAC address is stored in the
 	 * 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:
 	case E1000_DEV_ID_82546EB_FIBER:
 		hw->mac_type = e1000_82546;
 		hw->mac_type = e1000_82546;
 		break;
 		break;
+	case E1000_DEV_ID_82541ER:
+	        hw->mac_type = e1000_82541_rev_2;
+	        break;
 	default:
 	default:
 		/* Should never have loaded on this device */
 		/* Should never have loaded on this device */
 		return -E1000_ERR_MAC_TYPE;
 		return -E1000_ERR_MAC_TYPE;
@@ -2485,6 +2494,36 @@ e1000_phy_reset(struct e1000_hw *hw)
 	return 0;
 	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
 * Probes the expected PHY address for known PHY IDs
 *
 *
@@ -2493,6 +2532,7 @@ e1000_phy_reset(struct e1000_hw *hw)
 static int
 static int
 e1000_detect_gig_phy(struct e1000_hw *hw)
 e1000_detect_gig_phy(struct e1000_hw *hw)
 {
 {
+	int32_t phy_init_status;
 	uint16_t phy_id_high, phy_id_low;
 	uint16_t phy_id_high, phy_id_low;
 	int match = FALSE;
 	int match = FALSE;
 
 
@@ -2526,11 +2566,19 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
 		if (hw->phy_id == M88E1011_I_PHY_ID)
 		if (hw->phy_id == M88E1011_I_PHY_ID)
 			match = TRUE;
 			match = TRUE;
 		break;
 		break;
+	case e1000_82541_rev_2:
+		if(hw->phy_id == IGP01E1000_I_PHY_ID)
+			match = TRUE;
+
+		break;
 	default:
 	default:
 		DEBUGOUT("Invalid MAC type %d\n", hw->mac_type);
 		DEBUGOUT("Invalid MAC type %d\n", hw->mac_type);
 		return -E1000_ERR_CONFIG;
 		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);
 		DEBUGOUT("PHY ID 0x%X detected\n", hw->phy_id);
 		return 0;
 		return 0;
 	}
 	}
@@ -2985,7 +3033,7 @@ e1000_initialize(bd_t * bis)
 			free(nic);
 			free(nic);
 			return 0;
 			return 0;
 		}
 		}
-#ifndef CONFIG_AP1000
+#if !(defined(CONFIG_AP1000) || defined(CONFIG_MVBC_1G))
 		if (e1000_validate_eeprom_checksum(nic) < 0) {
 		if (e1000_validate_eeprom_checksum(nic) < 0) {
 			printf("The EEPROM Checksum Is Not Valid\n");
 			printf("The EEPROM Checksum Is Not Valid\n");
 			free(hw);
 			free(hw);

+ 43 - 10
drivers/net/e1000.h

@@ -71,6 +71,8 @@ typedef enum {
 	e1000_82540,
 	e1000_82540,
 	e1000_82545,
 	e1000_82545,
 	e1000_82546,
 	e1000_82546,
+	e1000_82541,
+	e1000_82541_rev_2,
 	e1000_num_macs
 	e1000_num_macs
 } e1000_mac_type;
 } e1000_mac_type;
 
 
@@ -168,6 +170,13 @@ typedef enum {
 	e1000_1000t_rx_status_undefined = 0xFF
 	e1000_1000t_rx_status_undefined = 0xFF
 } e1000_1000t_rx_status;
 } 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 {
 struct e1000_phy_info {
 	e1000_cable_length cable_length;
 	e1000_cable_length cable_length;
 	e1000_10bt_ext_dist_enable extended_10bt_distance;
 	e1000_10bt_ext_dist_enable extended_10bt_distance;
@@ -184,14 +193,19 @@ struct e1000_phy_stats {
 };
 };
 
 
 /* Error Codes */
 /* 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 */
 /* PCI Device IDs */
 #define E1000_DEV_ID_82542          0x1000
 #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_82545EM_FIBER  0x1011
 #define E1000_DEV_ID_82546EB_COPPER 0x1010
 #define E1000_DEV_ID_82546EB_COPPER 0x1010
 #define E1000_DEV_ID_82546EB_FIBER  0x1012
 #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 NODE_ADDRESS_SIZE 6
 #define ETH_LENGTH_OF_ADDRESS 6
 #define ETH_LENGTH_OF_ADDRESS 6
@@ -799,6 +814,8 @@ struct e1000_hw {
 	pci_dev_t pdev;
 	pci_dev_t pdev;
 	uint8_t *hw_addr;
 	uint8_t *hw_addr;
 	e1000_mac_type mac_type;
 	e1000_mac_type mac_type;
+	e1000_phy_type phy_type;
+	uint32_t phy_init_script;
 	e1000_media_type media_type;
 	e1000_media_type media_type;
 	e1000_lan_loc lan_loc;
 	e1000_lan_loc lan_loc;
 	e1000_fc_type fc;
 	e1000_fc_type fc;
@@ -1517,7 +1534,22 @@ struct e1000_hw {
 #define M88E1000_EXT_PHY_SPEC_CTRL 0x14	/* Extended PHY Specific Control */
 #define M88E1000_EXT_PHY_SPEC_CTRL 0x14	/* Extended PHY Specific Control */
 #define M88E1000_RX_ERR_CNTR       0x15	/* Receive Error Counter */
 #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 */
 /* PHY Control Register */
 #define MII_CR_SPEED_SELECT_MSB 0x0040	/* bits 6,13: 10=1000, 01=100, 00=10 */
 #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 M88E1011_I_PHY_ID  0x01410C20
 #define M88E1000_12_PHY_ID M88E1000_E_PHY_ID
 #define M88E1000_12_PHY_ID M88E1000_E_PHY_ID
 #define M88E1000_14_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. */
 /* Miscellaneous PHY bit definitions. */
 #define PHY_PREAMBLE        0xFFFFFFFF
 #define PHY_PREAMBLE        0xFFFFFFFF

+ 661 - 0
drivers/net/greth.c

@@ -0,0 +1,661 @@
+/* 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;
+	greth_regs *regs = greth->regs;
+	greth_bd *txbd;
+	void *txbuf;
+	unsigned int status;
+#ifdef DEBUG
+	printf("greth_send\n");
+#endif
+	/* send data, wait for data to be sent, then return */
+	if (((unsigned int)eth_data & (GRETH_BUF_ALIGN - 1))
+	    && !greth->gbit_mac) {
+		/* data not aligned as needed by GRETH 10/100, solve this by allocating 4 byte aligned buffer
+		 * and copy data to before giving it to GRETH.
+		 */
+		if (!greth->txbuf) {
+			greth->txbuf = malloc(GRETH_RXBUF_SIZE);
+#ifdef DEBUG
+			printf("GRETH: allocated aligned tx-buf\n");
+#endif
+		}
+
+		txbuf = greth->txbuf;
+
+		/* copy data info buffer */
+		memcpy((char *)txbuf, (char *)eth_data, data_length);
+
+		/* keep buffer to next time */
+	} else {
+		txbuf = (void *)eth_data;
+	}
+	/* get descriptor to use, only 1 supported... hehe easy */
+	txbd = greth->txbd_base;
+
+	/* setup descriptor to wrap around to it self */
+	txbd->addr = (unsigned int)txbuf;
+	txbd->stat = GRETH_BD_EN | GRETH_BD_WR | data_length;
+
+	/* Remind Core which descriptor to use when sending */
+	GRETH_REGSAVE(&regs->tx_desc_p, (unsigned int)txbd);
+
+	/* initate send by enabling transmitter */
+	GRETH_REGORIN(&regs->control, GRETH_TXEN);
+
+	/* Wait for data to be sent */
+	while ((status = GRETH_REGLOAD(&txbd->stat)) & GRETH_BD_EN) {
+		;
+	}
+
+	/* was the packet transmitted succesfully? */
+	if (status & GRETH_TXBD_ERR_AL) {
+		greth->stats.tx_limit_errors++;
+	}
+
+	if (status & GRETH_TXBD_ERR_UE) {
+		greth->stats.tx_underrun_errors++;
+	}
+
+	if (status & GRETH_TXBD_ERR_LC) {
+		greth->stats.tx_latecol_errors++;
+	}
+
+	if (status &
+	    (GRETH_TXBD_ERR_LC | GRETH_TXBD_ERR_UE | GRETH_TXBD_ERR_AL)) {
+		/* any error */
+		greth->stats.tx_errors++;
+		return -1;
+	}
+
+	/* bump tx packet counter */
+	greth->stats.tx_packets++;
+
+	/* return succefully */
+	return 0;
+}
+
+int greth_recv(struct eth_device *dev)
+{
+	greth_priv *greth = dev->priv;
+	greth_regs *regs = greth->regs;
+	greth_bd *rxbd;
+	unsigned int status, len = 0, bad;
+	unsigned char *d;
+	int enable = 0;
+	int i;
+#ifdef DEBUG
+/*	printf("greth_recv\n"); */
+#endif
+	/* Receive One packet only, but clear as many error packets as there are
+	 * available.
+	 */
+	{
+		/* current receive descriptor */
+		rxbd = greth->rxbd_curr;
+
+		/* get status of next received packet */
+		status = GRETH_REGLOAD(&rxbd->stat);
+
+		bad = 0;
+
+		/* stop if no more packets received */
+		if (status & GRETH_BD_EN) {
+			goto done;
+		}
+#ifdef DEBUG
+		printf("greth_recv: packet 0x%lx, 0x%lx, len: %d\n",
+		       (unsigned int)rxbd, status, status & GRETH_BD_LEN);
+#endif
+
+		/* Check status for errors.
+		 */
+		if (status & GRETH_RXBD_ERR_FT) {
+			greth->stats.rx_length_errors++;
+			bad = 1;
+		}
+		if (status & (GRETH_RXBD_ERR_AE | GRETH_RXBD_ERR_OE)) {
+			greth->stats.rx_frame_errors++;
+			bad = 1;
+		}
+		if (status & GRETH_RXBD_ERR_CRC) {
+			greth->stats.rx_crc_errors++;
+			bad = 1;
+		}
+		if (bad) {
+			greth->stats.rx_errors++;
+			printf
+			    ("greth_recv: Bad packet (%d, %d, %d, 0x%08x, %d)\n",
+			     greth->stats.rx_length_errors,
+			     greth->stats.rx_frame_errors,
+			     greth->stats.rx_crc_errors, status,
+			     greth->stats.rx_packets);
+			/* print all rx descriptors */
+			for (i = 0; i < GRETH_RXBD_CNT; i++) {
+				printf("[%d]: Stat=0x%lx, Addr=0x%lx\n", i,
+				       GRETH_REGLOAD(&greth->rxbd_base[i].stat),
+				       GRETH_REGLOAD(&greth->rxbd_base[i].
+						     addr));
+			}
+		} else {
+			/* Process the incoming packet. */
+			len = status & GRETH_BD_LEN;
+			d = (char *)rxbd->addr;
+#ifdef DEBUG
+			printf
+			    ("greth_recv: new packet, length: %d. data: %x %x %x %x %x %x %x %x\n",
+			     len, d[0], d[1], d[2], d[3], d[4], d[5], d[6],
+			     d[7]);
+#endif
+			/* flush all data cache to make sure we're not reading old packet data */
+			sparc_dcache_flush_all();
+
+			/* pass packet on to network subsystem */
+			NetReceive((void *)d, len);
+
+			/* bump stats counters */
+			greth->stats.rx_packets++;
+
+			/* bad is now 0 ==> will stop loop */
+		}
+
+		/* reenable descriptor to receive more packet with this descriptor, wrap around if needed */
+		rxbd->stat =
+		    GRETH_BD_EN |
+		    (((unsigned int)greth->rxbd_curr >=
+		      (unsigned int)greth->rxbd_max) ? GRETH_BD_WR : 0);
+		enable = 1;
+
+		/* increase index */
+		greth->rxbd_curr =
+		    ((unsigned int)greth->rxbd_curr >=
+		     (unsigned int)greth->rxbd_max) ? greth->
+		    rxbd_base : (greth->rxbd_curr + 1);
+
+	};
+
+	if (enable) {
+		GRETH_REGORIN(&regs->control, GRETH_RXEN);
+	}
+      done:
+	/* return positive length of packet or 0 if non recieved */
+	return len;
+}
+
+void greth_set_hwaddr(greth_priv * greth, unsigned char *mac)
+{
+	/* save new MAC address */
+	greth->dev->enetaddr[0] = greth->hwaddr[0] = mac[0];
+	greth->dev->enetaddr[1] = greth->hwaddr[1] = mac[1];
+	greth->dev->enetaddr[2] = greth->hwaddr[2] = mac[2];
+	greth->dev->enetaddr[3] = greth->hwaddr[3] = mac[3];
+	greth->dev->enetaddr[4] = greth->hwaddr[4] = mac[4];
+	greth->dev->enetaddr[5] = greth->hwaddr[5] = mac[5];
+	greth->regs->esa_msb = (mac[0] << 8) | mac[1];
+	greth->regs->esa_lsb =
+	    (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5];
+#ifdef DEBUG
+	printf("GRETH: New MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+#endif
+}
+
+int greth_initialize(bd_t * bis)
+{
+	greth_priv *greth;
+	ambapp_apbdev apbdev;
+	struct eth_device *dev;
+	int i;
+	char *addr_str, *end;
+	unsigned char addr[6];
+#ifdef DEBUG
+	printf("Scanning for GRETH\n");
+#endif
+	/* Find Device & IRQ via AMBA Plug&Play information */
+	if (ambapp_apb_first(VENDOR_GAISLER, GAISLER_ETHMAC, &apbdev) != 1) {
+		return -1;	/* GRETH not found */
+	}
+
+	greth = (greth_priv *) malloc(sizeof(greth_priv));
+	dev = (struct eth_device *)malloc(sizeof(struct eth_device));
+	memset(dev, 0, sizeof(struct eth_device));
+	memset(greth, 0, sizeof(greth_priv));
+
+	greth->regs = (greth_regs *) apbdev.address;
+	greth->irq = apbdev.irq;
+#ifdef DEBUG
+	printf("Found GRETH at 0x%lx, irq %d\n", greth->regs, greth->irq);
+#endif
+	dev->priv = (void *)greth;
+	dev->iobase = (unsigned int)greth->regs;
+	dev->init = greth_init;
+	dev->halt = greth_halt;
+	dev->send = greth_send;
+	dev->recv = greth_recv;
+	greth->dev = dev;
+
+	/* Reset Core */
+	GRETH_REGSAVE(&greth->regs->control, GRETH_RESET);
+
+	/* Wait for core to finish reset cycle */
+	while (GRETH_REGLOAD(&greth->regs->control) & GRETH_RESET) ;
+
+	/* Get the phy address which assumed to have been set
+	   correctly with the reset value in hardware */
+	greth->phyaddr = (GRETH_REGLOAD(&greth->regs->mdio) >> 11) & 0x1F;
+
+	/* Check if mac is gigabit capable */
+	greth->gbit_mac = (GRETH_REGLOAD(&greth->regs->control) >> 27) & 1;
+
+	/* Make descriptor string */
+	if (greth->gbit_mac) {
+		sprintf(dev->name, "GRETH 10/100/GB");
+	} else {
+		sprintf(dev->name, "GRETH 10/100");
+	}
+
+	/* initiate PHY, select speed/duplex depending on connected PHY */
+	if (greth_init_phy(greth, bis)) {
+		/* Failed to init PHY (timedout) */
+		return -1;
+	}
+
+	/* Register Device to EtherNet subsystem  */
+	eth_register(dev);
+
+	/* Get MAC address */
+	if ((addr_str = getenv("ethaddr")) != NULL) {
+		for (i = 0; i < 6; i++) {
+			addr[i] =
+			    addr_str ? simple_strtoul(addr_str, &end, 16) : 0;
+			if (addr_str) {
+				addr_str = (*end) ? end + 1 : end;
+			}
+		}
+	} else {
+		/* HW Address not found in environment, Set default HW address */
+		addr[0] = GRETH_HWADDR_0;	/* MSB */
+		addr[1] = GRETH_HWADDR_1;
+		addr[2] = GRETH_HWADDR_2;
+		addr[3] = GRETH_HWADDR_3;
+		addr[4] = GRETH_HWADDR_4;
+		addr[5] = GRETH_HWADDR_5;	/* LSB */
+	}
+
+	/* set and remember MAC address */
+	greth_set_hwaddr(greth, addr);
+
+	return 1;
+}

+ 97 - 0
drivers/net/greth.h

@@ -0,0 +1,97 @@
+/* Gaisler.com GRETH 10/100/1000 Ethernet MAC driver
+ *
+ * (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
+ */
+
+#define GRETH_FD 0x10
+#define GRETH_RESET 0x40
+#define GRETH_MII_BUSY 0x8
+#define GRETH_MII_NVALID 0x10
+
+/* MII registers */
+#define GRETH_MII_EXTADV_1000FD 0x00000200
+#define GRETH_MII_EXTADV_1000HD 0x00000100
+#define GRETH_MII_EXTPRT_1000FD 0x00000800
+#define GRETH_MII_EXTPRT_1000HD 0x00000400
+
+#define GRETH_MII_100T4 0x00000200
+#define GRETH_MII_100TXFD 0x00000100
+#define GRETH_MII_100TXHD 0x00000080
+#define GRETH_MII_10FD 0x00000040
+#define GRETH_MII_10HD 0x00000020
+
+#define GRETH_BD_EN 0x800
+#define GRETH_BD_WR 0x1000
+#define GRETH_BD_IE 0x2000
+#define GRETH_BD_LEN 0x7FF
+
+#define GRETH_TXEN 0x1
+#define GRETH_INT_TX 0x8
+#define GRETH_TXI 0x4
+#define GRETH_TXBD_STATUS 0x0001C000
+#define GRETH_TXBD_MORE 0x20000
+#define GRETH_TXBD_IPCS 0x40000
+#define GRETH_TXBD_TCPCS 0x80000
+#define GRETH_TXBD_UDPCS 0x100000
+#define GRETH_TXBD_ERR_LC 0x10000
+#define GRETH_TXBD_ERR_UE 0x4000
+#define GRETH_TXBD_ERR_AL 0x8000
+#define GRETH_TXBD_NUM 128
+#define GRETH_TXBD_NUM_MASK (GRETH_TXBD_NUM-1)
+#define GRETH_TX_BUF_SIZE 2048
+
+#define GRETH_INT_RX         0x4
+#define GRETH_RXEN           0x2
+#define GRETH_RXI            0x8
+#define GRETH_RXBD_STATUS    0xFFFFC000
+#define GRETH_RXBD_ERR_AE    0x4000
+#define GRETH_RXBD_ERR_FT    0x8000
+#define GRETH_RXBD_ERR_CRC   0x10000
+#define GRETH_RXBD_ERR_OE    0x20000
+#define GRETH_RXBD_ERR_LE    0x40000
+#define GRETH_RXBD_IP_DEC    0x80000
+#define GRETH_RXBD_IP_CSERR  0x100000
+#define GRETH_RXBD_UDP_DEC   0x200000
+#define GRETH_RXBD_UDP_CSERR 0x400000
+#define GRETH_RXBD_TCP_DEC   0x800000
+#define GRETH_RXBD_TCP_CSERR 0x1000000
+
+#define GRETH_RXBD_NUM 128
+#define GRETH_RXBD_NUM_MASK (GRETH_RXBD_NUM-1)
+#define GRETH_RX_BUF_SIZE 2048
+
+/* Ethernet configuration registers */
+typedef struct _greth_regs {
+	volatile unsigned int control;
+	volatile unsigned int status;
+	volatile unsigned int esa_msb;
+	volatile unsigned int esa_lsb;
+	volatile unsigned int mdio;
+	volatile unsigned int tx_desc_p;
+	volatile unsigned int rx_desc_p;
+} greth_regs;
+
+/* Ethernet buffer descriptor */
+typedef struct _greth_bd {
+	volatile unsigned int stat;
+	unsigned int addr;	/* Buffer address not changed by HW */
+} greth_bd;

+ 7 - 0
drivers/net/mcffec.c

@@ -166,6 +166,13 @@ int fec_send(struct eth_device *dev, volatile void *packet, int length)
 	/* Activate transmit Buffer Descriptor polling */
 	/* Activate transmit Buffer Descriptor polling */
 	fecp->tdar = 0x01000000;	/* Descriptor polling active    */
 	fecp->tdar = 0x01000000;	/* Descriptor polling active    */
 
 
+	/* FEC fix for MCF5275, FEC unable to initial transmit data packet.
+	 * A nop will ensure the descriptor polling active completed.
+	 */
+#ifdef CONFIG_M5275
+	__asm__ ("nop");
+#endif
+
 #ifdef CFG_UNIFY_CACHE
 #ifdef CFG_UNIFY_CACHE
 	icache_invalid();
 	icache_invalid();
 #endif
 #endif

+ 71 - 2
drivers/net/smc91111.h

@@ -79,7 +79,7 @@ typedef unsigned long int 		dword;
 #ifdef CONFIG_XSENGINE
 #ifdef CONFIG_XSENGINE
 #define	SMC_inl(r) 	(*((volatile dword *)(SMC_BASE_ADDRESS+(r<<1))))
 #define	SMC_inl(r) 	(*((volatile dword *)(SMC_BASE_ADDRESS+(r<<1))))
 #define	SMC_inw(r) 	(*((volatile word *)(SMC_BASE_ADDRESS+(r<<1))))
 #define	SMC_inw(r) 	(*((volatile word *)(SMC_BASE_ADDRESS+(r<<1))))
-#define SMC_inb(p)	({ \
+#define SMC_inb(p)  ({ \
 	unsigned int __p = (unsigned int)(SMC_BASE_ADDRESS + (p<<1)); \
 	unsigned int __p = (unsigned int)(SMC_BASE_ADDRESS + (p<<1)); \
 	unsigned int __v = *(volatile unsigned short *)((__p) & ~2); \
 	unsigned int __v = *(volatile unsigned short *)((__p) & ~2); \
 	if (__p & 2) __v >>= 8; \
 	if (__p & 2) __v >>= 8; \
@@ -176,7 +176,76 @@ typedef unsigned long int 		dword;
 					};  \
 					};  \
 				})
 				})
 
 
-#else /* if not CONFIG_PXA250 */
+#elif defined(CONFIG_LEON)	/* if not CONFIG_PXA250 */
+
+#define SMC_LEON_SWAP16(_x_) ({ word _x = (_x_); ((_x << 8) | (_x >> 8)); })
+
+#define SMC_LEON_SWAP32(_x_)			\
+    ({ dword _x = (_x_);			\
+       ((_x << 24) |				\
+       ((0x0000FF00UL & _x) <<  8) |		\
+       ((0x00FF0000UL & _x) >>  8) |		\
+       (_x  >> 24)); })
+
+#define	SMC_inl(r) 	(SMC_LEON_SWAP32((*(volatile dword *)(SMC_BASE_ADDRESS+((r)<<0)))))
+#define	SMC_inl_nosw(r) 	((*(volatile dword *)(SMC_BASE_ADDRESS+((r)<<0))))
+#define	SMC_inw(r) 	(SMC_LEON_SWAP16((*(volatile word *)(SMC_BASE_ADDRESS+((r)<<0)))))
+#define	SMC_inw_nosw(r) 	((*(volatile word *)(SMC_BASE_ADDRESS+((r)<<0))))
+#define SMC_inb(p)	({ \
+	word ___v = SMC_inw((p) & ~1); \
+	if ((p) & 1) ___v >>= 8; \
+	else ___v &= 0xff; \
+	___v; })
+
+#define	SMC_outl(d,r)	(*(volatile dword *)(SMC_BASE_ADDRESS+((r)<<0))=SMC_LEON_SWAP32(d))
+#define	SMC_outl_nosw(d,r)	(*(volatile dword *)(SMC_BASE_ADDRESS+((r)<<0))=(d))
+#define	SMC_outw(d,r)	(*(volatile word *)(SMC_BASE_ADDRESS+((r)<<0))=SMC_LEON_SWAP16(d))
+#define	SMC_outw_nosw(d,r)	(*(volatile word *)(SMC_BASE_ADDRESS+((r)<<0))=(d))
+#define	SMC_outb(d,r)	do{	word __d = (byte)(d);  \
+				word __w = SMC_inw((r)&~1);  \
+				__w &= ((r)&1) ? 0x00FF : 0xFF00;  \
+				__w |= ((r)&1) ? __d<<8 : __d;  \
+				SMC_outw(__w,(r)&~1);  \
+			}while(0)
+#define SMC_outsl(r,b,l)	do{	int __i; \
+					dword *__b2; \
+					__b2 = (dword *) b; \
+					for (__i = 0; __i < l; __i++) { \
+					    SMC_outl_nosw( *(__b2 + __i), r); \
+					} \
+				}while(0)
+#define SMC_outsw(r,b,l)	do{	int __i; \
+					word *__b2; \
+					__b2 = (word *) b; \
+					for (__i = 0; __i < l; __i++) { \
+					    SMC_outw_nosw( *(__b2 + __i), r); \
+					} \
+				}while(0)
+#define SMC_insl(r,b,l) 	do{	int __i ;  \
+					dword *__b2;  \
+					__b2 = (dword *) b;  \
+					for (__i = 0; __i < l; __i++) {  \
+					  *(__b2 + __i) = SMC_inl_nosw(r);  \
+					};  \
+				}while(0)
+
+#define SMC_insw(r,b,l) 	do{	int __i ;  \
+					word *__b2;  \
+					__b2 = (word *) b;  \
+					for (__i = 0; __i < l; __i++) {  \
+					  *(__b2 + __i) = SMC_inw_nosw(r);  \
+					};  \
+				}while(0)
+
+#define SMC_insb(r,b,l) 	do{	int __i ;  \
+					byte *__b2;  \
+					__b2 = (byte *) b;  \
+					for (__i = 0; __i < l; __i++) {  \
+					  *(__b2 + __i) = SMC_inb(r);  \
+					};  \
+				}while(0)
+
+#else				/* if not CONFIG_PXA250 and not CONFIG_LEON */
 
 
 #ifndef CONFIG_SMC_USE_IOFUNCS /* these macros don't work on some boards */
 #ifndef CONFIG_SMC_USE_IOFUNCS /* these macros don't work on some boards */
 /*
 /*

+ 30 - 0
drivers/net/tsec.c

@@ -1267,6 +1267,35 @@ struct phy_info phy_info_VSC8244 = {
 			   },
 			   },
 };
 };
 
 
+struct phy_info phy_info_VSC8601 = {
+		0x00007042,
+		"Vitesse VSC8601",
+		4,
+		(struct phy_cmd[]){     /* config */
+				/* Override PHY config settings */
+				/* Configure some basic stuff */
+				{MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
+#ifdef CFG_VSC8601_SKEWFIX
+				{MIIM_VSC8601_EPHY_CON,MIIM_VSC8601_EPHY_CON_INIT_SKEW,NULL},
+#endif
+				{miim_end,}
+				 },
+		(struct phy_cmd[]){     /* startup */
+				/* Read the Status (2x to make sure link is right) */
+				{MIIM_STATUS, miim_read, NULL},
+				/* Auto-negotiate */
+				{MIIM_STATUS, miim_read, &mii_parse_sr},
+				/* Read the status */
+				{MIIM_VSC8244_AUX_CONSTAT, miim_read,
+						&mii_parse_vsc8244},
+				{miim_end,}
+				},
+		(struct phy_cmd[]){     /* shutdown */
+				{miim_end,}
+				},
+};
+
+
 struct phy_info phy_info_dm9161 = {
 struct phy_info phy_info_dm9161 = {
 	0x0181b88,
 	0x0181b88,
 	"Davicom DM9161E",
 	"Davicom DM9161E",
@@ -1462,6 +1491,7 @@ struct phy_info *phy_info[] = {
 	&phy_info_dm9161,
 	&phy_info_dm9161,
 	&phy_info_lxt971,
 	&phy_info_lxt971,
 	&phy_info_VSC8244,
 	&phy_info_VSC8244,
+	&phy_info_VSC8601,
 	&phy_info_dp83865,
 	&phy_info_dp83865,
 	&phy_info_rtl8211b,
 	&phy_info_rtl8211b,
 	&phy_info_generic,
 	&phy_info_generic,

+ 5 - 0
drivers/net/tsec.h

@@ -159,6 +159,11 @@
 #define MIIM_VSC8244_LED_CON            0x1b
 #define MIIM_VSC8244_LED_CON            0x1b
 #define MIIM_VSC8244_LEDCON_INIT        0xF011
 #define MIIM_VSC8244_LEDCON_INIT        0xF011
 
 
+/* Entry for Vitesse VSC8601 regs starts here (Not complete) */
+/* Vitesse VSC8601 Extended PHY Control Register 1 */
+#define MIIM_VSC8601_EPHY_CON			0x17
+#define MIIM_VSC8601_EPHY_CON_INIT_SKEW	0x1120
+
 /* 88E1011 PHY Status Register */
 /* 88E1011 PHY Status Register */
 #define MIIM_88E1011_PHY_STATUS         0x11
 #define MIIM_88E1011_PHY_STATUS         0x11
 #define MIIM_88E1011_PHYSTAT_SPEED      0xc000
 #define MIIM_88E1011_PHYSTAT_SPEED      0xc000

+ 1 - 0
include/pci_ids.h

@@ -1810,6 +1810,7 @@
 #define PCI_DEVICE_ID_INTEL_82434	0x04a3
 #define PCI_DEVICE_ID_INTEL_82434	0x04a3
 #define PCI_DEVICE_ID_INTEL_I960	0x0960
 #define PCI_DEVICE_ID_INTEL_I960	0x0960
 #define PCI_DEVICE_ID_INTEL_I960RM	0x0962
 #define PCI_DEVICE_ID_INTEL_I960RM	0x0962
+#define PCI_DEVICE_ID_INTEL_82541ER 0x1078
 #define PCI_DEVICE_ID_INTEL_82542	0x1000
 #define PCI_DEVICE_ID_INTEL_82542	0x1000
 #define PCI_DEVICE_ID_INTEL_82543GC_FIBER	0x1001
 #define PCI_DEVICE_ID_INTEL_82543GC_FIBER	0x1001
 #define PCI_DEVICE_ID_INTEL_82543GC_COPPER	0x1004
 #define PCI_DEVICE_ID_INTEL_82543GC_COPPER	0x1004

+ 4 - 1
net/bootp.c

@@ -879,7 +879,10 @@ static void DhcpSendRequestPkt(Bootp_t *bp_offer)
 	iplen = BOOTP_HDR_SIZE - sizeof(bp->bp_vend) + extlen;
 	iplen = BOOTP_HDR_SIZE - sizeof(bp->bp_vend) + extlen;
 	NetSetIP(iphdr, 0xFFFFFFFFL, PORT_BOOTPS, PORT_BOOTPC, iplen);
 	NetSetIP(iphdr, 0xFFFFFFFFL, PORT_BOOTPS, PORT_BOOTPC, iplen);
 
 
-	debug ("Transmitting DHCPREQUEST packet: len = %d\n", pktlen);
+        debug ("Transmitting DHCPREQUEST packet: len = %d\n", pktlen);
+#ifdef CONFIG_BOOTP_DHCP_REQUEST_DELAY
+	udelay(CONFIG_BOOTP_DHCP_REQUEST_DELAY);
+#endif	/* CONFIG_BOOTP_DHCP_REQUEST_DELAY */
 	NetSendPacket(NetTxPacket, pktlen);
 	NetSendPacket(NetTxPacket, pktlen);
 }
 }
 
 

+ 4 - 0
net/eth.c

@@ -60,6 +60,7 @@ extern int npe_initialize(bd_t *);
 extern int uec_initialize(int);
 extern int uec_initialize(int);
 extern int bfin_EMAC_initialize(bd_t *);
 extern int bfin_EMAC_initialize(bd_t *);
 extern int atstk1000_eth_initialize(bd_t *);
 extern int atstk1000_eth_initialize(bd_t *);
+extern int greth_initialize(bd_t *);
 extern int atngw100_eth_initialize(bd_t *);
 extern int atngw100_eth_initialize(bd_t *);
 extern int mcffec_initialize(bd_t*);
 extern int mcffec_initialize(bd_t*);
 extern int mcdmafec_initialize(bd_t*);
 extern int mcdmafec_initialize(bd_t*);
@@ -275,6 +276,9 @@ int eth_initialize(bd_t *bis)
 #if defined(CONFIG_ATSTK1000)
 #if defined(CONFIG_ATSTK1000)
 	atstk1000_eth_initialize(bis);
 	atstk1000_eth_initialize(bis);
 #endif
 #endif
+#if defined(CONFIG_GRETH)
+	greth_initialize(bis);
+#endif
 #if defined(CONFIG_ATNGW100)
 #if defined(CONFIG_ATNGW100)
 	atngw100_eth_initialize(bis);
 	atngw100_eth_initialize(bis);
 #endif
 #endif