* Patch by Jon Loeliger, 2005-07-25
authorJon Loeliger <jdl@freescale.com>
Mon, 25 Jul 2005 20:38:06 +0000 (15:38 -0500)
committerJon Loeliger <jdl@freescale.com>
Mon, 25 Jul 2005 20:38:06 +0000 (15:38 -0500)
  Move the TSEC driver out of cpu/mpc85xx as it will be shared
  by the upcoming mpc83xx family as well.

16 files changed:
CHANGELOG
board/cds/mpc8541cds/u-boot.lds
board/cds/mpc8548cds/u-boot.lds
board/cds/mpc8555cds/u-boot.lds
board/mpc8540ads/u-boot.lds
board/mpc8560ads/u-boot.lds
board/pm854/u-boot.lds
board/stxgp3/u-boot.lds
board/tqm8540/u-boot.lds
board/tqm8560/u-boot.lds
cpu/mpc85xx/Makefile
cpu/mpc85xx/tsec.c [deleted file]
cpu/mpc85xx/tsec.h [deleted file]
drivers/Makefile
drivers/tsec.c [new file with mode: 0644]
drivers/tsec.h [new file with mode: 0644]

index 2213bf068aa7a4aaae5ff5cb2f5dced7ba9f6020..6cbd636c66e962d8012f3239933b5e5825e03ac4 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,10 @@
 ======================================================================
 Changes for U-Boot 1.1.3:
 ======================================================================
+* Patch by Jon Loeliger, 2005-07-25
+  Move the TSEC driver out of cpu/mpc85xx as it will be shared
+  by the upcoming mpc83xx family as well.
+
 * Patch by Jon Loeliger, 2005-05-05
   Implemented support for MPC8548CDS board.
   Added DDR II support based on SPD values for MPC85xx boards.
index f8cee53eeb302ac229a2a3134c8bf6f9526e28e0..bd697d8d0c56378f314f139a79b0cfa003974025 100644 (file)
@@ -69,7 +69,6 @@ SECTIONS
     cpu/mpc85xx/interrupts.o (.text)
     cpu/mpc85xx/cpu_init.o (.text)
     cpu/mpc85xx/cpu.o (.text)
-    cpu/mpc85xx/tsec.o (.text)
     cpu/mpc85xx/speed.o (.text)
     cpu/mpc85xx/pci.o (.text)
     common/dlmalloc.o (.text)
index 91ea9fdd72e65a7ef62f3ee584362d3d58eaee4f..36d24073d20a3f5e7fa929cf38dd72fb220af979 100644 (file)
@@ -69,7 +69,6 @@ SECTIONS
     cpu/mpc85xx/interrupts.o (.text)
     cpu/mpc85xx/cpu_init.o (.text)
     cpu/mpc85xx/cpu.o (.text)
-    cpu/mpc85xx/tsec.o (.text)
     cpu/mpc85xx/speed.o (.text)
     cpu/mpc85xx/pci.o (.text)
     common/dlmalloc.o (.text)
index d14cb9c03ba0fecad1211479668c8bc4f4ad50ef..5d45d38036310b2ae2a7da16808fa9224382c8ad 100644 (file)
@@ -69,7 +69,6 @@ SECTIONS
     cpu/mpc85xx/interrupts.o (.text)
     cpu/mpc85xx/cpu_init.o (.text)
     cpu/mpc85xx/cpu.o (.text)
-    cpu/mpc85xx/tsec.o (.text)
     cpu/mpc85xx/speed.o (.text)
     cpu/mpc85xx/pci.o (.text)
     common/dlmalloc.o (.text)
index 56dd457aeadd1d6a4488f9ba41a59ad11f1db7c7..85852d59d3f269d7a3c50f153d483de0600f38df 100644 (file)
@@ -70,7 +70,6 @@ SECTIONS
     cpu/mpc85xx/interrupts.o (.text)
     cpu/mpc85xx/cpu_init.o (.text)
     cpu/mpc85xx/cpu.o (.text)
-    cpu/mpc85xx/tsec.o (.text)
     cpu/mpc85xx/speed.o (.text)
     cpu/mpc85xx/pci.o (.text)
     common/dlmalloc.o (.text)
index 4c6c7db380d1de5251c5c6912210879b8dff2a17..c307d638526dfc3c4f4ed940679c8ea93827cc14 100644 (file)
@@ -73,7 +73,6 @@ SECTIONS
     cpu/mpc85xx/ether_fcc.o (.text)
     cpu/mpc85xx/cpu_init.o (.text)
     cpu/mpc85xx/cpu.o (.text)
-    cpu/mpc85xx/tsec.o (.text)
     cpu/mpc85xx/speed.o (.text)
     cpu/mpc85xx/i2c.o (.text)
     cpu/mpc85xx/spd_sdram.o (.text)
index 5f24f76a7bced530538a9d015f390c9bf3c9523d..4db6b342bd6074c2e3315ee2012b6d6ad4e4aecb 100644 (file)
@@ -70,7 +70,6 @@ SECTIONS
     cpu/mpc85xx/interrupts.o (.text)
     cpu/mpc85xx/cpu_init.o (.text)
     cpu/mpc85xx/cpu.o (.text)
-    cpu/mpc85xx/tsec.o (.text)
     cpu/mpc85xx/speed.o (.text)
     cpu/mpc85xx/pci.o (.text)
     common/dlmalloc.o (.text)
index 587994671d2819805bdda7ad3edff44741279dee..dae5acbc38bc869c750748faaab23331d58e0ad4 100644 (file)
@@ -78,7 +78,6 @@ SECTIONS
     cpu/mpc85xx/ether_fcc.o (.text)
     cpu/mpc85xx/cpu_init.o (.text)
     cpu/mpc85xx/cpu.o (.text)
-    cpu/mpc85xx/tsec.o (.text)
     cpu/mpc85xx/speed.o (.text)
     cpu/mpc85xx/i2c.o (.text)
     cpu/mpc85xx/spd_sdram.o (.text)
index eb84aeb7d224dd8825d08e50751209cfb0ed83e2..ffd75629b73828d6af691b87d3537cf627b36f39 100644 (file)
@@ -70,7 +70,6 @@ SECTIONS
     cpu/mpc85xx/interrupts.o (.text)
     cpu/mpc85xx/cpu_init.o (.text)
     cpu/mpc85xx/cpu.o (.text)
-    cpu/mpc85xx/tsec.o (.text)
     cpu/mpc85xx/speed.o (.text)
     cpu/mpc85xx/pci.o (.text)
     common/dlmalloc.o (.text)
index 19b77bec8857bcfd3bb95b21cb6203a3e65dc0b9..ebe22401a4ffd046698475c0bec5d2be92df1921 100644 (file)
@@ -70,7 +70,6 @@ SECTIONS
     cpu/mpc85xx/interrupts.o (.text)
     cpu/mpc85xx/cpu_init.o (.text)
     cpu/mpc85xx/cpu.o (.text)
-    cpu/mpc85xx/tsec.o (.text)
     cpu/mpc85xx/speed.o (.text)
     cpu/mpc85xx/pci.o (.text)
     common/dlmalloc.o (.text)
index 996915e11c0c6f7f7d6cbec88ae1c4ebb3cbe632..5298dc113f2e6ed23d5f87cab71a687c5cdb0b62 100644 (file)
@@ -26,7 +26,7 @@ include $(TOPDIR)/config.mk
 LIB    = lib$(CPU).a
 
 START  = start.o resetvec.o
-COBJS  = traps.o cpu.o cpu_init.o speed.o interrupts.o tsec.o \
+COBJS  = traps.o cpu.o cpu_init.o speed.o interrupts.o \
          pci.o serial_scc.o commproc.o ether_fcc.o i2c.o spd_sdram.o
 OBJS   = $(COBJS)
 
diff --git a/cpu/mpc85xx/tsec.c b/cpu/mpc85xx/tsec.c
deleted file mode 100644 (file)
index 5ac6334..0000000
+++ /dev/null
@@ -1,1074 +0,0 @@
-/*
- * tsec.c
- * Freescale Three Speed Ethernet Controller driver
- *
- * This software may be used and distributed according to the
- * terms of the GNU Public License, Version 2, incorporated
- * herein by reference.
- *
- * Copyright 2004 Freescale Semiconductor.
- * (C) Copyright 2003, Motorola, Inc.
- * maintained by Jon Loeliger (loeliger@freescale.com)
- * author Andy Fleming
- *
- */
-
-#include <config.h>
-#include <mpc85xx.h>
-#include <common.h>
-#include <malloc.h>
-#include <net.h>
-#include <command.h>
-
-#if defined(CONFIG_TSEC_ENET)
-#include "tsec.h"
-
-#define TX_BUF_CNT 2
-
-static uint rxIdx;     /* index of the current RX buffer */
-static uint txIdx;     /* index of the current TX buffer */
-
-typedef volatile struct rtxbd {
-       txbd8_t txbd[TX_BUF_CNT];
-       rxbd8_t rxbd[PKTBUFSRX];
-}  RTXBD;
-
-struct tsec_info_struct {
-       unsigned int phyaddr;
-       u32 flags;
-       unsigned int phyregidx;
-};
-
-
-/* The tsec_info structure contains 3 values which the
- * driver uses to determine how to operate a given ethernet
- * device.  For now, the structure is initialized with the
- * knowledge that all current implementations have 2 TSEC
- * devices, and one FEC.  The information needed is:
- *  phyaddr - The address of the PHY which is attached to
- *     the given device.
- *
- *  flags - This variable indicates whether the device
- *     supports gigabit speed ethernet, and whether it should be
- *     in reduced mode.
- *
- *  phyregidx - This variable specifies which ethernet device
- *     controls the MII Management registers which are connected
- *     to the PHY.  For 8540/8560, only TSEC1 (index 0) has
- *     access to the PHYs, so all of the entries have "0".
- *
- * The values specified in the table are taken from the board's
- * config file in include/configs/.  When implementing a new
- * board with ethernet capability, it is necessary to define:
- *   TSEC1_PHY_ADDR
- *   TSEC1_PHYIDX
- *   TSEC2_PHY_ADDR
- *   TSEC2_PHYIDX
- *
- * and for 8560:
- *   FEC_PHY_ADDR
- *   FEC_PHYIDX
- */
-static struct tsec_info_struct tsec_info[] = {
-#ifdef CONFIG_MPC85XX_TSEC1
-       {TSEC1_PHY_ADDR, TSEC_GIGABIT, TSEC1_PHYIDX},
-#else
-       { 0, 0, 0},
-#endif
-#ifdef CONFIG_MPC85XX_TSEC2
-       {TSEC2_PHY_ADDR, TSEC_GIGABIT, TSEC2_PHYIDX},
-#else
-       { 0, 0, 0},
-#endif
-#ifdef CONFIG_MPC85XX_FEC
-       {FEC_PHY_ADDR, 0, FEC_PHYIDX},
-#else
-#    ifdef CONFIG_MPC85XX_TSEC3
-       {TSEC3_PHY_ADDR, TSEC_GIGABIT | TSEC_REDUCED, TSEC3_PHYIDX},
-#    else
-       { 0, 0, 0},
-#    endif
-#    ifdef CONFIG_MPC85XX_TSEC4
-       {TSEC4_PHY_ADDR, TSEC_REDUCED, TSEC4_PHYIDX},
-#    else
-       { 0, 0, 0},
-#    endif
-#endif
-};
-
-#define MAXCONTROLLERS (4)
-
-static int relocated = 0;
-
-static struct tsec_private *privlist[MAXCONTROLLERS];
-
-#ifdef __GNUC__
-static RTXBD rtx __attribute__ ((aligned(8)));
-#else
-#error "rtx must be 64-bit aligned"
-#endif
-
-static int tsec_send(struct eth_device* dev, volatile void *packet, int length);
-static int tsec_recv(struct eth_device* dev);
-static int tsec_init(struct eth_device* dev, bd_t * bd);
-static void tsec_halt(struct eth_device* dev);
-static void init_registers(volatile tsec_t *regs);
-static void startup_tsec(struct eth_device *dev);
-static int init_phy(struct eth_device *dev);
-void write_phy_reg(struct tsec_private *priv, uint regnum, uint value);
-uint read_phy_reg(struct tsec_private *priv, uint regnum);
-struct phy_info * get_phy_info(struct eth_device *dev);
-void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd);
-static void adjust_link(struct eth_device *dev);
-static void relocate_cmds(void);
-
-/* Initialize device structure. Returns success if PHY
- * initialization succeeded (i.e. if it recognizes the PHY)
- */
-int tsec_initialize(bd_t *bis, int index, char *devname)
-{
-       struct eth_device* dev;
-       int i;
-       struct tsec_private *priv;
-
-       dev = (struct eth_device*) malloc(sizeof *dev);
-
-       if(NULL == dev)
-               return 0;
-
-       memset(dev, 0, sizeof *dev);
-
-       priv = (struct tsec_private *) malloc(sizeof(*priv));
-
-       if(NULL == priv)
-               return 0;
-
-       privlist[index] = priv;
-       priv->regs = (volatile tsec_t *)(TSEC_BASE_ADDR + index*TSEC_SIZE);
-       priv->phyregs = (volatile tsec_t *)(TSEC_BASE_ADDR +
-                       tsec_info[index].phyregidx*TSEC_SIZE);
-
-       priv->phyaddr = tsec_info[index].phyaddr;
-       priv->flags = tsec_info[index].flags;
-
-       sprintf(dev->name, devname);
-       dev->iobase = 0;
-       dev->priv   = priv;
-       dev->init   = tsec_init;
-       dev->halt   = tsec_halt;
-       dev->send   = tsec_send;
-       dev->recv   = tsec_recv;
-
-       /* Tell u-boot to get the addr from the env */
-       for(i=0;i<6;i++)
-               dev->enetaddr[i] = 0;
-
-       eth_register(dev);
-
-
-       /* Reset the MAC */
-       priv->regs->maccfg1 |= MACCFG1_SOFT_RESET;
-       priv->regs->maccfg1 &= ~(MACCFG1_SOFT_RESET);
-
-       /* Try to initialize PHY here, and return */
-       return init_phy(dev);
-}
-
-
-/* Initializes data structures and registers for the controller,
- * and brings the interface up.         Returns the link status, meaning
- * that it returns success if the link is up, failure otherwise.
- * This allows u-boot to find the first active controller. */
-int tsec_init(struct eth_device* dev, bd_t * bd)
-{
-       uint tempval;
-       char tmpbuf[MAC_ADDR_LEN];
-       int i;
-       struct tsec_private *priv = (struct tsec_private *)dev->priv;
-       volatile tsec_t *regs = priv->regs;
-
-       /* Make sure the controller is stopped */
-       tsec_halt(dev);
-
-       /* Init MACCFG2.  Defaults to GMII */
-       regs->maccfg2 = MACCFG2_INIT_SETTINGS;
-
-       /* Init ECNTRL */
-       regs->ecntrl = ECNTRL_INIT_SETTINGS;
-
-       /* Copy the station address into the address registers.
-        * Backwards, because little endian MACS are dumb */
-       for(i=0;i<MAC_ADDR_LEN;i++) {
-               tmpbuf[MAC_ADDR_LEN - 1 - i] = dev->enetaddr[i];
-       }
-       (uint)(regs->macstnaddr1) = *((uint *)(tmpbuf));
-
-       tempval = *((uint *)(tmpbuf +4));
-
-       (uint)(regs->macstnaddr2) = tempval;
-
-       /* reset the indices to zero */
-       rxIdx = 0;
-       txIdx = 0;
-
-       /* Clear out (for the most part) the other registers */
-       init_registers(regs);
-
-       /* Ready the device for tx/rx */
-       startup_tsec(dev);
-
-       /* If there's no link, fail */
-       return priv->link;
-
-}
-
-
-/* Write value to the device's PHY through the registers
- * specified in priv, modifying the register specified in regnum.
- * It will wait for the write to be done (or for a timeout to
- * expire) before exiting
- */
-void write_phy_reg(struct tsec_private *priv, uint regnum, uint value)
-{
-       volatile tsec_t *regbase = priv->phyregs;
-       uint phyid = priv->phyaddr;
-       int timeout=1000000;
-
-       regbase->miimadd = (phyid << 8) | regnum;
-       regbase->miimcon = value;
-       asm("msync");
-
-       timeout=1000000;
-       while((regbase->miimind & MIIMIND_BUSY) && timeout--);
-}
-
-
-/* Reads register regnum on the device's PHY through the
- * registers specified in priv.         It lowers and raises the read
- * command, and waits for the data to become valid (miimind
- * notvalid bit cleared), and the bus to cease activity (miimind
- * busy bit cleared), and then returns the value
- */
-uint read_phy_reg(struct tsec_private *priv, uint regnum)
-{
-       uint value;
-       volatile tsec_t *regbase = priv->phyregs;
-       uint phyid = priv->phyaddr;
-
-       /* Put the address of the phy, and the register
-        * number into MIIMADD */
-       regbase->miimadd = (phyid << 8) | regnum;
-
-       /* Clear the command register, and wait */
-       regbase->miimcom = 0;
-       asm("msync");
-
-       /* Initiate a read command, and wait */
-       regbase->miimcom = MIIM_READ_COMMAND;
-       asm("msync");
-
-       /* Wait for the the indication that the read is done */
-       while((regbase->miimind & (MIIMIND_NOTVALID | MIIMIND_BUSY)));
-
-       /* Grab the value read from the PHY */
-       value = regbase->miimstat;
-
-       return value;
-}
-
-
-/* Discover which PHY is attached to the device, and configure it
- * properly.  If the PHY is not recognized, then return 0
- * (failure).  Otherwise, return 1
- */
-static int init_phy(struct eth_device *dev)
-{
-       struct tsec_private *priv = (struct tsec_private *)dev->priv;
-       struct phy_info *curphy;
-
-       /* Assign a Physical address to the TBI */
-
-       {
-               volatile tsec_t *regs = (volatile tsec_t *)(TSEC_BASE_ADDR);
-               regs->tbipa = TBIPA_VALUE;
-               regs = (volatile tsec_t *)(TSEC_BASE_ADDR + TSEC_SIZE);
-               regs->tbipa = TBIPA_VALUE;
-               asm("msync");
-       }
-
-       /* Reset MII (due to new addresses) */
-       priv->phyregs->miimcfg = MIIMCFG_RESET;
-       asm("msync");
-       priv->phyregs->miimcfg = MIIMCFG_INIT_VALUE;
-       asm("msync");
-       while(priv->phyregs->miimind & MIIMIND_BUSY);
-
-       if(0 == relocated)
-               relocate_cmds();
-
-       /* Get the cmd structure corresponding to the attached
-        * PHY */
-       curphy = get_phy_info(dev);
-
-       if(NULL == curphy) {
-               printf("%s: No PHY found\n", dev->name);
-
-               return 0;
-       }
-
-       priv->phyinfo = curphy;
-
-       phy_run_commands(priv, priv->phyinfo->config);
-
-       return 1;
-}
-
-
-/* Returns which value to write to the control register. */
-/* For 10/100, the value is slightly different */
-uint mii_cr_init(uint mii_reg, struct tsec_private *priv)
-{
-       if(priv->flags & TSEC_GIGABIT)
-               return MIIM_CONTROL_INIT;
-       else
-               return MIIM_CR_INIT;
-}
-
-
-/* Parse the status register for link, and then do
- * auto-negotiation */
-uint mii_parse_sr(uint mii_reg, struct tsec_private *priv)
-{
-       uint timeout = TSEC_TIMEOUT;
-
-       if(mii_reg & MIIM_STATUS_LINK)
-               priv->link = 1;
-       else
-               priv->link = 0;
-
-       if(priv->link) {
-               while((!(mii_reg & MIIM_STATUS_AN_DONE)) && timeout--)
-                       mii_reg = read_phy_reg(priv, MIIM_STATUS);
-       }
-
-       return 0;
-}
-
-
-/* Parse the 88E1011's status register for speed and duplex
- * information */
-uint mii_parse_88E1011_psr(uint mii_reg, struct tsec_private *priv)
-{
-       uint speed;
-
-       if(mii_reg & MIIM_88E1011_PHYSTAT_DUPLEX)
-               priv->duplexity = 1;
-       else
-               priv->duplexity = 0;
-
-       speed = (mii_reg &MIIM_88E1011_PHYSTAT_SPEED);
-
-       switch(speed) {
-               case MIIM_88E1011_PHYSTAT_GBIT:
-                       priv->speed = 1000;
-                       break;
-               case MIIM_88E1011_PHYSTAT_100:
-                       priv->speed = 100;
-                       break;
-               default:
-                       priv->speed = 10;
-       }
-
-       return 0;
-}
-
-
-/* Parse the cis8201's status register for speed and duplex
- * information */
-uint mii_parse_cis8201(uint mii_reg, struct tsec_private *priv)
-{
-       uint speed;
-
-       if(mii_reg & MIIM_CIS8201_AUXCONSTAT_DUPLEX)
-               priv->duplexity = 1;
-       else
-               priv->duplexity = 0;
-
-       speed = mii_reg & MIIM_CIS8201_AUXCONSTAT_SPEED;
-       switch(speed) {
-               case MIIM_CIS8201_AUXCONSTAT_GBIT:
-                       priv->speed = 1000;
-                       break;
-               case MIIM_CIS8201_AUXCONSTAT_100:
-                       priv->speed = 100;
-                       break;
-               default:
-                       priv->speed = 10;
-                       break;
-       }
-
-       return 0;
-}
-
-
-/* Parse the DM9161's status register for speed and duplex
- * information */
-uint mii_parse_dm9161_scsr(uint mii_reg, struct tsec_private *priv)
-{
-       if(mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_100H))
-               priv->speed = 100;
-       else
-               priv->speed = 10;
-
-       if(mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_10F))
-               priv->duplexity = 1;
-       else
-               priv->duplexity = 0;
-
-       return 0;
-}
-
-
-/* Hack to write all 4 PHYs with the LED values */
-uint mii_cis8204_fixled(uint mii_reg, struct tsec_private *priv)
-{
-       uint phyid;
-       volatile tsec_t *regbase = priv->phyregs;
-       int timeout=1000000;
-
-       for(phyid=0;phyid<4;phyid++) {
-               regbase->miimadd = (phyid << 8) | mii_reg;
-               regbase->miimcon = MIIM_CIS8204_SLEDCON_INIT;
-               asm("msync");
-
-               timeout=1000000;
-               while((regbase->miimind & MIIMIND_BUSY) && timeout--);
-       }
-
-       return MIIM_CIS8204_SLEDCON_INIT;
-}
-
-uint mii_cis8204_setmode(uint mii_reg, struct tsec_private *priv)
-{
-       if (priv->flags & TSEC_REDUCED)
-               return MIIM_CIS8204_EPHYCON_INIT | MIIM_CIS8204_EPHYCON_RGMII;
-       else
-               return MIIM_CIS8204_EPHYCON_INIT;
-}
-
-/* Initialized required registers to appropriate values, zeroing
- * those we don't care about (unless zero is bad, in which case,
- * choose a more appropriate value) */
-static void init_registers(volatile tsec_t *regs)
-{
-       /* Clear IEVENT */
-       regs->ievent = IEVENT_INIT_CLEAR;
-
-       regs->imask = IMASK_INIT_CLEAR;
-
-       regs->hash.iaddr0 = 0;
-       regs->hash.iaddr1 = 0;
-       regs->hash.iaddr2 = 0;
-       regs->hash.iaddr3 = 0;
-       regs->hash.iaddr4 = 0;
-       regs->hash.iaddr5 = 0;
-       regs->hash.iaddr6 = 0;
-       regs->hash.iaddr7 = 0;
-
-       regs->hash.gaddr0 = 0;
-       regs->hash.gaddr1 = 0;
-       regs->hash.gaddr2 = 0;
-       regs->hash.gaddr3 = 0;
-       regs->hash.gaddr4 = 0;
-       regs->hash.gaddr5 = 0;
-       regs->hash.gaddr6 = 0;
-       regs->hash.gaddr7 = 0;
-
-       regs->rctrl = 0x00000000;
-
-       /* Init RMON mib registers */
-       memset((void *)&(regs->rmon), 0, sizeof(rmon_mib_t));
-
-       regs->rmon.cam1 = 0xffffffff;
-       regs->rmon.cam2 = 0xffffffff;
-
-       regs->mrblr = MRBLR_INIT_SETTINGS;
-
-       regs->minflr = MINFLR_INIT_SETTINGS;
-
-       regs->attr = ATTR_INIT_SETTINGS;
-       regs->attreli = ATTRELI_INIT_SETTINGS;
-
-}
-
-
-/* Configure maccfg2 based on negotiated speed and duplex
- * reported by PHY handling code */
-static void adjust_link(struct eth_device *dev)
-{
-       struct tsec_private *priv = (struct tsec_private *)dev->priv;
-       volatile tsec_t *regs = priv->regs;
-
-       if(priv->link) {
-               if(priv->duplexity != 0)
-                       regs->maccfg2 |= MACCFG2_FULL_DUPLEX;
-               else
-                       regs->maccfg2 &= ~(MACCFG2_FULL_DUPLEX);
-
-               switch(priv->speed) {
-                       case 1000:
-                               regs->maccfg2 = ((regs->maccfg2&~(MACCFG2_IF))
-                                       | MACCFG2_GMII);
-                               break;
-                       case 100:
-                       case 10:
-                               regs->maccfg2 = ((regs->maccfg2&~(MACCFG2_IF))
-                                       | MACCFG2_MII);
-
-                               /* If We're in reduced mode, we
-                                * need to say whether we're 10
-                                * or 100 MB. */
-                               if ((priv->speed == 100) 
-                                               && (priv->flags & TSEC_REDUCED))
-                                       regs->ecntrl |= ECNTRL_R100;
-                               else
-                                       regs->ecntrl &= ~(ECNTRL_R100);
-                               break;
-                       default:
-                               printf("%s: Speed was bad\n", dev->name);
-                               break;
-               }
-
-               printf("Speed: %d, %s duplex\n", priv->speed,
-                               (priv->duplexity) ? "full" : "half");
-
-       } else {
-               printf("%s: No link.\n", dev->name);
-       }
-}
-
-
-/* Set up the buffers and their descriptors, and bring up the
- * interface */
-static void startup_tsec(struct eth_device *dev)
-{
-       int i;
-       struct tsec_private *priv = (struct tsec_private *)dev->priv;
-       volatile tsec_t *regs = priv->regs;
-
-       /* Point to the buffer descriptors */
-       regs->tbase = (unsigned int)(&rtx.txbd[txIdx]);
-       regs->rbase = (unsigned int)(&rtx.rxbd[rxIdx]);
-
-       /* Initialize the Rx Buffer descriptors */
-       for (i = 0; i < PKTBUFSRX; i++) {
-               rtx.rxbd[i].status = RXBD_EMPTY;
-               rtx.rxbd[i].length = 0;
-               rtx.rxbd[i].bufPtr = (uint)NetRxPackets[i];
-       }
-       rtx.rxbd[PKTBUFSRX -1].status |= RXBD_WRAP;
-
-       /* Initialize the TX Buffer Descriptors */
-       for(i=0; i<TX_BUF_CNT; i++) {
-               rtx.txbd[i].status = 0;
-               rtx.txbd[i].length = 0;
-               rtx.txbd[i].bufPtr = 0;
-       }
-       rtx.txbd[TX_BUF_CNT -1].status |= TXBD_WRAP;
-
-       /* Start up the PHY */
-       phy_run_commands(priv, priv->phyinfo->startup);
-       adjust_link(dev);
-
-       /* Enable Transmit and Receive */
-       regs->maccfg1 |= (MACCFG1_RX_EN | MACCFG1_TX_EN);
-
-       /* Tell the DMA it is clear to go */
-       regs->dmactrl |= DMACTRL_INIT_SETTINGS;
-       regs->tstat = TSTAT_CLEAR_THALT;
-       regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
-}
-
-/* This returns the status bits of the device. The return value
- * is never checked, and this is what the 8260 driver did, so we
- * do the same.         Presumably, this would be zero if there were no
- * errors */
-static int tsec_send(struct eth_device* dev, volatile void *packet, int length)
-{
-       int i;
-       int result = 0;
-       struct tsec_private *priv = (struct tsec_private *)dev->priv;
-       volatile tsec_t *regs = priv->regs;
-
-       /* Find an empty buffer descriptor */
-       for(i=0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
-               if (i >= TOUT_LOOP) {
-                       debug ("%s: tsec: tx buffers full\n", dev->name);
-                       return result;
-               }
-       }
-
-       rtx.txbd[txIdx].bufPtr = (uint)packet;
-       rtx.txbd[txIdx].length = length;
-       rtx.txbd[txIdx].status |= (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT);
-
-       /* Tell the DMA to go */
-       regs->tstat = TSTAT_CLEAR_THALT;
-
-       /* Wait for buffer to be transmitted */
-       for(i=0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
-               if (i >= TOUT_LOOP) {
-                       debug ("%s: tsec: tx error\n", dev->name);
-                       return result;
-               }
-       }
-
-       txIdx = (txIdx + 1) % TX_BUF_CNT;
-       result = rtx.txbd[txIdx].status & TXBD_STATS;
-
-       return result;
-}
-
-static int tsec_recv(struct eth_device* dev)
-{
-       int length;
-       struct tsec_private *priv = (struct tsec_private *)dev->priv;
-       volatile tsec_t *regs = priv->regs;
-
-       while(!(rtx.rxbd[rxIdx].status & RXBD_EMPTY)) {
-
-               length = rtx.rxbd[rxIdx].length;
-
-               /* Send the packet up if there were no errors */
-               if (!(rtx.rxbd[rxIdx].status & RXBD_STATS)) {
-                       NetReceive(NetRxPackets[rxIdx], length - 4);
-               } else {
-                       printf("Got error %x\n",
-                                       (rtx.rxbd[rxIdx].status & RXBD_STATS));
-               }
-
-               rtx.rxbd[rxIdx].length = 0;
-
-               /* Set the wrap bit if this is the last element in the list */
-               rtx.rxbd[rxIdx].status = RXBD_EMPTY | (((rxIdx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0);
-
-               rxIdx = (rxIdx + 1) % PKTBUFSRX;
-       }
-
-       if(regs->ievent&IEVENT_BSY) {
-               regs->ievent = IEVENT_BSY;
-               regs->rstat = RSTAT_CLEAR_RHALT;
-       }
-
-       return -1;
-
-}
-
-
-/* Stop the interface */
-static void tsec_halt(struct eth_device* dev)
-{
-       struct tsec_private *priv = (struct tsec_private *)dev->priv;
-       volatile tsec_t *regs = priv->regs;
-
-       regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
-       regs->dmactrl |= (DMACTRL_GRS | DMACTRL_GTS);
-
-       while(!(regs->ievent & (IEVENT_GRSC | IEVENT_GTSC)));
-
-       regs->maccfg1 &= ~(MACCFG1_TX_EN | MACCFG1_RX_EN);
-
-       /* Shut down the PHY, as needed */
-       phy_run_commands(priv, priv->phyinfo->shutdown);
-}
-
-
-struct phy_info phy_info_M88E1011S = {
-       0x01410c6,
-       "Marvell 88E1011S",
-       4,
-       (struct phy_cmd[]) { /* config */
-               /* Reset and configure the PHY */
-               {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-               {0x1d, 0x1f, NULL},
-               {0x1e, 0x200c, NULL},
-               {0x1d, 0x5, NULL},
-               {0x1e, 0x0, NULL},
-               {0x1e, 0x100, 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_88E1011_PHY_STATUS, miim_read, &mii_parse_88E1011_psr},
-               {miim_end,}
-       },
-       (struct phy_cmd[]) { /* shutdown */
-               {miim_end,}
-       },
-};
-
-struct phy_info phy_info_M88E1111S = {
-       0x01410cc,
-       "Marvell 88E1111S",
-       4,
-       (struct phy_cmd[]) { /* config */
-         /* Reset and configure the PHY */
-               {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
-               {0x1d, 0x1f, NULL},
-               {0x1e, 0x200c, NULL},
-               {0x1d, 0x5, NULL},
-               {0x1e, 0x0, NULL},
-               {0x1e, 0x100, 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_88E1011_PHY_STATUS, miim_read, &mii_parse_88E1011_psr},
-               {miim_end,}
-       },
-       (struct phy_cmd[]) { /* shutdown */
-               {miim_end,}
-       },
-};
-
-struct phy_info phy_info_cis8204 = {
-       0x3f11,
-       "Cicada Cis8204",
-       6,
-       (struct phy_cmd[]) { /* config */
-               /* Override PHY config settings */
-               {MIIM_CIS8201_AUX_CONSTAT, MIIM_CIS8201_AUXCONSTAT_INIT, NULL},
-               /* Configure some basic stuff */
-               {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-               {MIIM_CIS8204_SLED_CON, MIIM_CIS8204_SLEDCON_INIT, &mii_cis8204_fixled},
-               {MIIM_CIS8204_EPHY_CON, MIIM_CIS8204_EPHYCON_INIT, &mii_cis8204_setmode},
-               {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_CIS8201_AUX_CONSTAT, miim_read, &mii_parse_cis8201},
-               {miim_end,}
-       },
-       (struct phy_cmd[]) { /* shutdown */
-               {miim_end,}
-       },
-};
-
-/* Cicada 8201 */
-struct phy_info phy_info_cis8201 = {
-       0xfc41,
-       "CIS8201",
-       4,
-       (struct phy_cmd[]) { /* config */
-               /* Override PHY config settings */
-               {MIIM_CIS8201_AUX_CONSTAT, MIIM_CIS8201_AUXCONSTAT_INIT, NULL},
-               /* Set up the interface mode */
-               {MIIM_CIS8201_EXT_CON1, MIIM_CIS8201_EXTCON1_INIT, NULL},
-               /* Configure some basic stuff */
-               {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
-               {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_CIS8201_AUX_CONSTAT, miim_read, &mii_parse_cis8201},
-               {miim_end,}
-       },
-       (struct phy_cmd[]) { /* shutdown */
-               {miim_end,}
-       },
-};
-
-
-struct phy_info phy_info_dm9161 = {
-       0x0181b88,
-       "Davicom DM9161E",
-       4,
-       (struct phy_cmd[]) { /* config */
-               {MIIM_CONTROL, MIIM_DM9161_CR_STOP, NULL},
-               /* Do not bypass the scrambler/descrambler */
-               {MIIM_DM9161_SCR, MIIM_DM9161_SCR_INIT, NULL},
-               /* Clear 10BTCSR to default */
-               {MIIM_DM9161_10BTCSR, MIIM_DM9161_10BTCSR_INIT, NULL},
-               /* Configure some basic stuff */
-               {MIIM_CONTROL, MIIM_CR_INIT, NULL},
-               /* Restart Auto Negotiation */
-               {MIIM_CONTROL, MIIM_DM9161_CR_RSTAN, NULL},
-               {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_DM9161_SCSR, miim_read, &mii_parse_dm9161_scsr},
-               {miim_end,}
-       },
-       (struct phy_cmd[]) { /* shutdown */
-               {miim_end,}
-       },
-};
-
-uint mii_parse_lxt971_sr2(uint mii_reg, struct tsec_private *priv)
-{
-       unsigned int speed;
-       if (priv->link) {
-               speed = mii_reg & MIIM_LXT971_SR2_SPEED_MASK;
-
-               switch (speed) {
-               case MIIM_LXT971_SR2_10HDX:
-                       priv->speed = 10;
-                       priv->duplexity = 0;
-                       break;
-               case MIIM_LXT971_SR2_10FDX:
-                       priv->speed = 10;
-                       priv->duplexity = 1;
-                       break;
-               case MIIM_LXT971_SR2_100HDX:
-                       priv->speed = 100;
-                       priv->duplexity = 0;
-               default:
-                       priv->speed = 100;
-                       priv->duplexity = 1;
-                       break;
-               }
-       } else {
-               priv->speed = 0;
-               priv->duplexity = 0;
-       }
-
-       return 0;
-}
-
-static struct phy_info phy_info_lxt971 = {
-       0x0001378e,
-       "LXT971",
-       4,
-       (struct phy_cmd []) {  /* config */
-               { MIIM_CR, MIIM_CR_INIT, mii_cr_init }, /* autonegotiate */
-               { miim_end, }
-       },
-       (struct phy_cmd []) {  /* startup - enable interrupts */
-               /* { 0x12, 0x00f2, NULL }, */
-               { MIIM_STATUS, miim_read, NULL },
-               { MIIM_STATUS, miim_read, &mii_parse_sr },
-               { MIIM_LXT971_SR2, miim_read, &mii_parse_lxt971_sr2 },
-               { miim_end, }
-       },
-       (struct phy_cmd []) {  /* shutdown - disable interrupts */
-               { miim_end, }
-       },
-};
-
-struct phy_info *phy_info[] = {
-#if 0
-       &phy_info_cis8201,
-#endif
-       &phy_info_cis8204,
-       &phy_info_M88E1011S,
-       &phy_info_M88E1111S,
-       &phy_info_dm9161,
-       &phy_info_lxt971,
-       NULL
-};
-
-
-/* Grab the identifier of the device's PHY, and search through
- * all of the known PHYs to see if one matches.         If so, return
- * it, if not, return NULL */
-struct phy_info * get_phy_info(struct eth_device *dev)
-{
-       struct tsec_private *priv = (struct tsec_private *)dev->priv;
-       uint phy_reg, phy_ID;
-       int i;
-       struct phy_info *theInfo = NULL;
-
-       /* Grab the bits from PHYIR1, and put them in the upper half */
-       phy_reg = read_phy_reg(priv, MIIM_PHYIR1);
-       phy_ID = (phy_reg & 0xffff) << 16;
-
-       /* Grab the bits from PHYIR2, and put them in the lower half */
-       phy_reg = read_phy_reg(priv, MIIM_PHYIR2);
-       phy_ID |= (phy_reg & 0xffff);
-
-       /* loop through all the known PHY types, and find one that */
-       /* matches the ID we read from the PHY. */
-       for(i=0; phy_info[i]; i++) {
-               if(phy_info[i]->id == (phy_ID >> phy_info[i]->shift))
-                       theInfo = phy_info[i];
-       }
-
-       if(theInfo == NULL)
-       {
-               printf("%s: PHY id %x is not supported!\n", dev->name, phy_ID);
-               return NULL;
-       } else {
-               printf("%s: PHY is %s (%x)\n", dev->name, theInfo->name,
-                               phy_ID);
-       }
-
-       return theInfo;
-}
-
-
-/* Execute the given series of commands on the given device's
- * PHY, running functions as necessary*/
-void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd)
-{
-       int i;
-       uint result;
-       volatile tsec_t *phyregs = priv->phyregs;
-
-       phyregs->miimcfg = MIIMCFG_RESET;
-
-       phyregs->miimcfg = MIIMCFG_INIT_VALUE;
-
-       while(phyregs->miimind & MIIMIND_BUSY);
-
-       for(i=0;cmd->mii_reg != miim_end;i++) {
-               if(cmd->mii_data == miim_read) {
-                       result = read_phy_reg(priv, cmd->mii_reg);
-
-                       if(cmd->funct != NULL)
-                               (*(cmd->funct))(result, priv);
-
-               } else {
-                       if(cmd->funct != NULL)
-                               result = (*(cmd->funct))(cmd->mii_reg, priv);
-                       else
-                               result = cmd->mii_data;
-
-                       write_phy_reg(priv, cmd->mii_reg, result);
-
-               }
-               cmd++;
-       }
-}
-
-
-/* Relocate the function pointers in the phy cmd lists */
-static void relocate_cmds(void)
-{
-       struct phy_cmd **cmdlistptr;
-       struct phy_cmd *cmd;
-       int i,j,k;
-       DECLARE_GLOBAL_DATA_PTR;
-
-       for(i=0; phy_info[i]; i++) {
-               /* First thing's first: relocate the pointers to the
-                * PHY command structures (the structs were done) */
-               phy_info[i] = (struct phy_info *) ((uint)phy_info[i]
-                               + gd->reloc_off);
-               phy_info[i]->name += gd->reloc_off;
-               phy_info[i]->config =
-                       (struct phy_cmd *)((uint)phy_info[i]->config
-                                          + gd->reloc_off);
-               phy_info[i]->startup =
-                       (struct phy_cmd *)((uint)phy_info[i]->startup
-                                          + gd->reloc_off);
-               phy_info[i]->shutdown =
-                       (struct phy_cmd *)((uint)phy_info[i]->shutdown
-                                          + gd->reloc_off);
-
-               cmdlistptr = &phy_info[i]->config;
-               j=0;
-               for(;cmdlistptr <= &phy_info[i]->shutdown;cmdlistptr++) {
-                       k=0;
-                       for(cmd=*cmdlistptr;cmd->mii_reg != miim_end;cmd++) {
-                               /* Only relocate non-NULL pointers */
-                               if(cmd->funct)
-                                       cmd->funct += gd->reloc_off;
-
-                               k++;
-                       }
-                       j++;
-               }
-       }
-
-       relocated = 1;
-}
-
-
-#ifndef CONFIG_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.
- *
- * Returns:
- *  0 on success
- */
-int miiphy_read(unsigned char addr, unsigned char reg, unsigned short *value)
-{
-       unsigned short ret;
-       struct tsec_private *priv = get_priv_for_phy(addr);
-
-       if(NULL == priv) {
-               printf("Can't read PHY at address %d\n", addr);
-               return -1;
-       }
-
-       ret = (unsigned short)read_phy_reg(priv, reg);
-       *value = ret;
-
-       return 0;
-}
-
-/*
- * Write a MII PHY register.
- *
- * Returns:
- *  0 on success
- */
-int miiphy_write(unsigned char addr, unsigned char reg, unsigned short value)
-{
-       struct tsec_private *priv = get_priv_for_phy(addr);
-
-       if(NULL == priv) {
-               printf("Can't write PHY at address %d\n", addr);
-               return -1;
-       }
-
-       write_phy_reg(priv, reg, value);
-
-       return 0;
-}
-
-#endif /* CONFIG_BITBANGMII */
-
-#endif /* CONFIG_TSEC_ENET */
diff --git a/cpu/mpc85xx/tsec.h b/cpu/mpc85xx/tsec.h
deleted file mode 100644 (file)
index d1c70aa..0000000
+++ /dev/null
@@ -1,494 +0,0 @@
-/*
- *  tsec.h
- *
- *  Driver for the Motorola Triple Speed Ethernet Controller
- *
- *  This software may be used and distributed according to the
- *  terms of the GNU Public License, Version 2, incorporated
- *  herein by reference.
- *
- * Copyright 2004 Freescale Semiconductor.
- * (C) Copyright 2003, Motorola, Inc.
- * maintained by Xianghua Xiao (x.xiao@motorola.com)
- * author Andy Fleming
- *
- */
-
-#ifndef __TSEC_H
-#define __TSEC_H
-
-#include <net.h>
-#include <mpc85xx.h>
-
-#define TSEC_BASE_ADDR (CFG_IMMR + 0x24000)
-#define TSEC_SIZE      0x01000
-
-#define MAC_ADDR_LEN 6
-
-/* #define TSEC_TIMEOUT        1000000 */
-#define TSEC_TIMEOUT 1000
-#define TOUT_LOOP      1000000
-
-/* MAC register bits */
-#define MACCFG1_SOFT_RESET     0x80000000
-#define MACCFG1_RESET_RX_MC    0x00080000
-#define MACCFG1_RESET_TX_MC    0x00040000
-#define MACCFG1_RESET_RX_FUN   0x00020000
-#define        MACCFG1_RESET_TX_FUN    0x00010000
-#define MACCFG1_LOOPBACK       0x00000100
-#define MACCFG1_RX_FLOW                0x00000020
-#define MACCFG1_TX_FLOW                0x00000010
-#define MACCFG1_SYNCD_RX_EN    0x00000008
-#define MACCFG1_RX_EN          0x00000004
-#define MACCFG1_SYNCD_TX_EN    0x00000002
-#define MACCFG1_TX_EN          0x00000001
-
-#define MACCFG2_INIT_SETTINGS  0x00007205
-#define MACCFG2_FULL_DUPLEX    0x00000001
-#define MACCFG2_IF              0x00000300
-#define MACCFG2_GMII           0x00000200
-#define MACCFG2_MII             0x00000100
-
-#define ECNTRL_INIT_SETTINGS   0x00001000
-#define ECNTRL_TBI_MODE         0x00000020
-#define ECNTRL_R100            0x00000008
-
-#define miim_end -2
-#define miim_read -1
-
-#define TBIPA_VALUE            0x1f
-#define MIIMCFG_INIT_VALUE     0x00000003
-#define MIIMCFG_RESET          0x80000000
-
-#define MIIMIND_BUSY            0x00000001
-#define MIIMIND_NOTVALID        0x00000004
-
-#define MIIM_CONTROL            0x00
-#define MIIM_CONTROL_RESET     0x00009140
-#define MIIM_CONTROL_INIT       0x00001140
-#define MIIM_ANEN               0x00001000
-
-#define MIIM_CR                 0x00
-#define MIIM_CR_RST            0x00008000
-#define MIIM_CR_INIT           0x00001000
-
-#define MIIM_STATUS            0x1
-#define MIIM_STATUS_AN_DONE    0x00000020
-#define MIIM_STATUS_LINK       0x0004
-
-#define MIIM_PHYIR1            0x2
-#define MIIM_PHYIR2            0x3
-
-#define MIIM_ANAR              0x4
-#define MIIM_ANAR_INIT         0x1e1
-
-#define MIIM_TBI_ANLPBPA       0x5
-#define MIIM_TBI_ANLPBPA_HALF  0x00000040
-#define MIIM_TBI_ANLPBPA_FULL  0x00000020
-
-#define MIIM_TBI_ANEX          0x6
-#define MIIM_TBI_ANEX_NP       0x00000004
-#define MIIM_TBI_ANEX_PRX      0x00000002
-
-#define MIIM_GBIT_CONTROL      0x9
-#define MIIM_GBIT_CONTROL_INIT 0xe00
-
-/* Cicada Auxiliary Control/Status Register */
-#define MIIM_CIS8201_AUX_CONSTAT        0x1c
-#define MIIM_CIS8201_AUXCONSTAT_INIT    0x0004
-#define MIIM_CIS8201_AUXCONSTAT_DUPLEX  0x0020
-#define MIIM_CIS8201_AUXCONSTAT_SPEED   0x0018
-#define MIIM_CIS8201_AUXCONSTAT_GBIT    0x0010
-#define MIIM_CIS8201_AUXCONSTAT_100     0x0008
-
-/* Cicada Extended Control Register 1 */
-#define MIIM_CIS8201_EXT_CON1           0x17
-#define MIIM_CIS8201_EXTCON1_INIT       0x0000
-
-/* Cicada 8204 Extended PHY Control Register 1 */
-#define MIIM_CIS8204_EPHY_CON          0x17
-#define MIIM_CIS8204_EPHYCON_INIT      0x0006
-#define MIIM_CIS8204_EPHYCON_RGMII     0x1000
-
-/* Cicada 8204 Serial LED Control Register */
-#define MIIM_CIS8204_SLED_CON          0x1b
-#define MIIM_CIS8204_SLEDCON_INIT      0x1115
-
-#define MIIM_GBIT_CON          0x09
-#define MIIM_GBIT_CON_ADVERT   0x0e00
-
-/* 88E1011 PHY Status Register */
-#define MIIM_88E1011_PHY_STATUS         0x11
-#define MIIM_88E1011_PHYSTAT_SPEED      0xc000
-#define MIIM_88E1011_PHYSTAT_GBIT       0x8000
-#define MIIM_88E1011_PHYSTAT_100        0x4000
-#define MIIM_88E1011_PHYSTAT_DUPLEX     0x2000
-#define MIIM_88E1011_PHYSTAT_SPDDONE   0x0800
-#define MIIM_88E1011_PHYSTAT_LINK      0x0400
-
-/* DM9161 Control register values */
-#define MIIM_DM9161_CR_STOP    0x0400
-#define MIIM_DM9161_CR_RSTAN   0x1200
-
-#define MIIM_DM9161_SCR                0x10
-#define MIIM_DM9161_SCR_INIT   0x0610
-
-/* DM9161 Specified Configuration and Status Register */
-#define MIIM_DM9161_SCSR       0x11
-#define MIIM_DM9161_SCSR_100F  0x8000
-#define MIIM_DM9161_SCSR_100H  0x4000
-#define MIIM_DM9161_SCSR_10F   0x2000
-#define MIIM_DM9161_SCSR_10H   0x1000
-
-/* DM9161 10BT Configuration/Status */
-#define MIIM_DM9161_10BTCSR    0x12
-#define MIIM_DM9161_10BTCSR_INIT       0x7800
-
-/* LXT971 Status 2 registers */
-#define MIIM_LXT971_SR2        17  /* Status Register 2  */
-#define MIIM_LXT971_SR2_SPEED_MASK     0xf000
-#define MIIM_LXT971_SR2_10HDX  0x1000  /* 10 Mbit half duplex selected */
-#define MIIM_LXT971_SR2_10FDX  0x2000  /* 10 Mbit full duplex selected */
-#define MIIM_LXT971_SR2_100HDX 0x4000  /* 100 Mbit half duplex selected */
-#define MIIM_LXT971_SR2_100FDX 0x8000  /* 100 Mbit full duplex selected */
-
-#define MIIM_READ_COMMAND       0x00000001
-
-#define MRBLR_INIT_SETTINGS    PKTSIZE_ALIGN
-
-#define MINFLR_INIT_SETTINGS   0x00000040
-
-#define DMACTRL_INIT_SETTINGS   0x000000c3
-#define DMACTRL_GRS             0x00000010
-#define DMACTRL_GTS             0x00000008
-
-#define TSTAT_CLEAR_THALT       0x80000000
-#define RSTAT_CLEAR_RHALT       0x00800000
-
-
-#define IEVENT_INIT_CLEAR      0xffffffff
-#define IEVENT_BABR            0x80000000
-#define IEVENT_RXC             0x40000000
-#define IEVENT_BSY             0x20000000
-#define IEVENT_EBERR           0x10000000
-#define IEVENT_MSRO            0x04000000
-#define IEVENT_GTSC            0x02000000
-#define IEVENT_BABT            0x01000000
-#define IEVENT_TXC             0x00800000
-#define IEVENT_TXE             0x00400000
-#define IEVENT_TXB             0x00200000
-#define IEVENT_TXF             0x00100000
-#define IEVENT_IE              0x00080000
-#define IEVENT_LC              0x00040000
-#define IEVENT_CRL             0x00020000
-#define IEVENT_XFUN            0x00010000
-#define IEVENT_RXB0            0x00008000
-#define IEVENT_GRSC            0x00000100
-#define IEVENT_RXF0            0x00000080
-
-#define IMASK_INIT_CLEAR       0x00000000
-#define IMASK_TXEEN            0x00400000
-#define IMASK_TXBEN            0x00200000
-#define IMASK_TXFEN             0x00100000
-#define IMASK_RXFEN0           0x00000080
-
-
-/* Default Attribute fields */
-#define ATTR_INIT_SETTINGS     0x000000c0
-#define ATTRELI_INIT_SETTINGS  0x00000000
-
-
-/* TxBD status field bits */
-#define TXBD_READY             0x8000
-#define TXBD_PADCRC            0x4000
-#define TXBD_WRAP              0x2000
-#define TXBD_INTERRUPT         0x1000
-#define TXBD_LAST              0x0800
-#define TXBD_CRC               0x0400
-#define TXBD_DEF               0x0200
-#define TXBD_HUGEFRAME         0x0080
-#define TXBD_LATECOLLISION     0x0080
-#define TXBD_RETRYLIMIT                0x0040
-#define        TXBD_RETRYCOUNTMASK     0x003c
-#define TXBD_UNDERRUN          0x0002
-#define TXBD_STATS              0x03ff
-
-/* RxBD status field bits */
-#define RXBD_EMPTY             0x8000
-#define RXBD_RO1               0x4000
-#define RXBD_WRAP              0x2000
-#define RXBD_INTERRUPT         0x1000
-#define RXBD_LAST              0x0800
-#define RXBD_FIRST             0x0400
-#define RXBD_MISS              0x0100
-#define RXBD_BROADCAST         0x0080
-#define RXBD_MULTICAST         0x0040
-#define RXBD_LARGE             0x0020
-#define RXBD_NONOCTET          0x0010
-#define RXBD_SHORT             0x0008
-#define RXBD_CRCERR            0x0004
-#define RXBD_OVERRUN           0x0002
-#define RXBD_TRUNCATED         0x0001
-#define RXBD_STATS             0x003f
-
-typedef struct txbd8
-{
-       ushort       status;         /* Status Fields */
-       ushort       length;         /* Buffer length */
-       uint         bufPtr;         /* Buffer Pointer */
-} txbd8_t;
-
-typedef struct rxbd8
-{
-       ushort       status;         /* Status Fields */
-       ushort       length;         /* Buffer Length */
-       uint         bufPtr;         /* Buffer Pointer */
-} rxbd8_t;
-
-typedef struct rmon_mib
-{
-       /* Transmit and Receive Counters */
-       uint    tr64;           /* Transmit and Receive 64-byte Frame Counter */
-       uint    tr127;          /* Transmit and Receive 65-127 byte Frame Counter */
-       uint    tr255;          /* Transmit and Receive 128-255 byte Frame Counter */
-       uint    tr511;          /* Transmit and Receive 256-511 byte Frame Counter */
-       uint    tr1k;           /* Transmit and Receive 512-1023 byte Frame Counter */
-       uint    trmax;          /* Transmit and Receive 1024-1518 byte Frame Counter */
-       uint    trmgv;          /* Transmit and Receive 1519-1522 byte Good VLAN Frame */
-       /* Receive Counters */
-       uint    rbyt;           /* Receive Byte Counter */
-       uint    rpkt;           /* Receive Packet Counter */
-       uint    rfcs;           /* Receive FCS Error Counter */
-       uint    rmca;           /* Receive Multicast Packet (Counter) */
-       uint    rbca;           /* Receive Broadcast Packet */
-       uint    rxcf;           /* Receive Control Frame Packet */
-       uint    rxpf;           /* Receive Pause Frame Packet */
-       uint    rxuo;           /* Receive Unknown OP Code */
-       uint    raln;           /* Receive Alignment Error */
-       uint    rflr;           /* Receive Frame Length Error */
-       uint    rcde;           /* Receive Code Error */
-       uint    rcse;           /* Receive Carrier Sense Error */
-       uint    rund;           /* Receive Undersize Packet */
-       uint    rovr;           /* Receive Oversize Packet */
-       uint    rfrg;           /* Receive Fragments */
-       uint    rjbr;           /* Receive Jabber */
-       uint    rdrp;           /* Receive Drop */
-       /* Transmit Counters */
-       uint    tbyt;           /* Transmit Byte Counter */
-       uint    tpkt;           /* Transmit Packet */
-       uint    tmca;           /* Transmit Multicast Packet */
-       uint    tbca;           /* Transmit Broadcast Packet */
-       uint    txpf;           /* Transmit Pause Control Frame */
-       uint    tdfr;           /* Transmit Deferral Packet */
-       uint    tedf;           /* Transmit Excessive Deferral Packet */
-       uint    tscl;           /* Transmit Single Collision Packet */
-       /* (0x2_n700) */
-       uint    tmcl;           /* Transmit Multiple Collision Packet */
-       uint    tlcl;           /* Transmit Late Collision Packet */
-       uint    txcl;           /* Transmit Excessive Collision Packet */
-       uint    tncl;           /* Transmit Total Collision */
-
-       uint    res2;
-
-       uint    tdrp;           /* Transmit Drop Frame */
-       uint    tjbr;           /* Transmit Jabber Frame */
-       uint    tfcs;           /* Transmit FCS Error */
-       uint    txcf;           /* Transmit Control Frame */
-       uint    tovr;           /* Transmit Oversize Frame */
-       uint    tund;           /* Transmit Undersize Frame */
-       uint    tfrg;           /* Transmit Fragments Frame */
-       /* General Registers */
-       uint    car1;           /* Carry Register One */
-       uint    car2;           /* Carry Register Two */
-       uint    cam1;           /* Carry Register One Mask */
-       uint    cam2;           /* Carry Register Two Mask */
-} rmon_mib_t;
-
-typedef struct tsec_hash_regs
-{
-       uint    iaddr0;         /* Individual Address Register 0 */
-       uint    iaddr1;         /* Individual Address Register 1 */
-       uint    iaddr2;         /* Individual Address Register 2 */
-       uint    iaddr3;         /* Individual Address Register 3 */
-       uint    iaddr4;         /* Individual Address Register 4 */
-       uint    iaddr5;         /* Individual Address Register 5 */
-       uint    iaddr6;         /* Individual Address Register 6 */
-       uint    iaddr7;         /* Individual Address Register 7 */
-       uint    res1[24];
-       uint    gaddr0;         /* Group Address Register 0 */
-       uint    gaddr1;         /* Group Address Register 1 */
-       uint    gaddr2;         /* Group Address Register 2 */
-       uint    gaddr3;         /* Group Address Register 3 */
-       uint    gaddr4;         /* Group Address Register 4 */
-       uint    gaddr5;         /* Group Address Register 5 */
-       uint    gaddr6;         /* Group Address Register 6 */
-       uint    gaddr7;         /* Group Address Register 7 */
-       uint    res2[24];
-} tsec_hash_t;
-
-typedef struct tsec
-{
-       /* General Control and Status Registers (0x2_n000) */
-       uint    res000[4];
-
-       uint    ievent;         /* Interrupt Event */
-       uint    imask;          /* Interrupt Mask */
-       uint    edis;           /* Error Disabled */
-       uint    res01c;
-       uint    ecntrl;         /* Ethernet Control */
-       uint    minflr;         /* Minimum Frame Length */
-       uint    ptv;            /* Pause Time Value */
-       uint    dmactrl;        /* DMA Control */
-       uint    tbipa;          /* TBI PHY Address */
-
-       uint    res034[3];
-       uint    res040[48];
-
-       /* Transmit Control and Status Registers (0x2_n100) */
-       uint    tctrl;          /* Transmit Control */
-       uint    tstat;          /* Transmit Status */
-       uint    res108;
-       uint    tbdlen;         /* Tx BD Data Length */
-       uint    res110[5];
-       uint    ctbptr;         /* Current TxBD Pointer */
-       uint    res128[23];
-       uint    tbptr;          /* TxBD Pointer */
-       uint    res188[30];
-       /* (0x2_n200) */
-       uint        res200;
-       uint    tbase;          /* TxBD Base Address */
-       uint    res208[42];
-       uint    ostbd;          /* Out of Sequence TxBD */
-       uint    ostbdp;         /* Out of Sequence Tx Data Buffer Pointer */
-       uint        res2b8[18];
-
-       /* Receive Control and Status Registers (0x2_n300) */
-       uint    rctrl;          /* Receive Control */
-       uint    rstat;          /* Receive Status */
-       uint    res308;
-       uint    rbdlen;         /* RxBD Data Length */
-       uint    res310[4];
-       uint        res320;
-       uint    crbptr;         /* Current Receive Buffer Pointer */
-       uint    res328[6];
-       uint    mrblr;          /* Maximum Receive Buffer Length */
-       uint    res344[16];
-       uint    rbptr;          /* RxBD Pointer */
-       uint        res388[30];
-       /* (0x2_n400) */
-       uint        res400;
-       uint    rbase;          /* RxBD Base Address */
-       uint        res408[62];
-
-       /* MAC Registers (0x2_n500) */
-       uint    maccfg1;        /* MAC Configuration #1 */
-       uint    maccfg2;        /* MAC Configuration #2 */
-       uint    ipgifg;         /* Inter Packet Gap/Inter Frame Gap */
-       uint    hafdup;         /* Half-duplex */
-       uint    maxfrm;         /* Maximum Frame */
-       uint    res514;
-       uint    res518;
-
-       uint    res51c;
-
-       uint    miimcfg;        /* MII Management: Configuration */
-       uint    miimcom;        /* MII Management: Command */
-       uint    miimadd;        /* MII Management: Address */
-       uint    miimcon;        /* MII Management: Control */
-       uint    miimstat;       /* MII Management: Status */
-       uint    miimind;        /* MII Management: Indicators */
-
-       uint    res538;
-
-       uint    ifstat;         /* Interface Status */
-       uint    macstnaddr1;    /* Station Address, part 1 */
-       uint    macstnaddr2;    /* Station Address, part 2 */
-       uint    res548[46];
-
-       /* (0x2_n600) */
-       uint    res600[32];
-
-       /* RMON MIB Registers (0x2_n680-0x2_n73c) */
-       rmon_mib_t      rmon;
-       uint    res740[48];
-
-       /* Hash Function Registers (0x2_n800) */
-       tsec_hash_t     hash;
-
-       uint        res900[128];
-
-       /* Pattern Registers (0x2_nb00) */
-       uint        resb00[62];
-       uint        attr;          /* Default Attribute Register */
-       uint        attreli;       /* Default Attribute Extract Length and Index */
-
-       /* TSEC Future Expansion Space (0x2_nc00-0x2_nffc) */
-       uint    resc00[256];
-} tsec_t;
-
-#define TSEC_GIGABIT (1)
-
-/* This flag currently only has
- * meaning if we're using the eTSEC */
-#define TSEC_REDUCED (1 << 1)
-
-struct tsec_private {
-       volatile tsec_t *regs;
-       volatile tsec_t *phyregs;
-       struct phy_info *phyinfo;
-       uint phyaddr;
-       u32 flags;
-       uint link;
-       uint duplexity;
-       uint speed;
-};
-
-
-/*
- * struct phy_cmd:  A command for reading or writing a PHY register
- *
- * mii_reg:  The register to read or write
- *
- * mii_data:  For writes, the value to put in the register.
- *     A value of -1 indicates this is a read.
- *
- * funct: A function pointer which is invoked for each command.
- *     For reads, this function will be passed the value read
- *     from the PHY, and process it.
- *     For writes, the result of this function will be written
- *     to the PHY register
- */
-struct phy_cmd {
-    uint mii_reg;
-    uint mii_data;
-    uint (*funct) (uint mii_reg, struct tsec_private* priv);
-};
-
-/* struct phy_info: a structure which defines attributes for a PHY
- *
- * id will contain a number which represents the PHY.  During
- * startup, the driver will poll the PHY to find out what its
- * UID--as defined by registers 2 and 3--is.  The 32-bit result
- * gotten from the PHY will be shifted right by "shift" bits to
- * discard any bits which may change based on revision numbers
- * unimportant to functionality
- *
- * The struct phy_cmd entries represent pointers to an arrays of
- * commands which tell the driver what to do to the PHY.
- */
-struct phy_info {
-    uint id;
-    char *name;
-    uint shift;
-    /* Called to configure the PHY, and modify the controller
-     * based on the results */
-    struct phy_cmd *config;
-
-    /* Called when starting up the controller */
-    struct phy_cmd *startup;
-
-    /* Called when bringing down the controller */
-    struct phy_cmd *shutdown;
-};
-
-#endif /* __TSEC_H */
index 3461bb1c893edc3c41d3e67f1ad7b027bc592931..26a556e59ad499f532369abd8557c09c40885dc1 100644 (file)
@@ -45,7 +45,7 @@ OBJS  = 3c589.o 5701rls.o ali512x.o \
          serial_pl010.o serial_pl011.o serial_xuartlite.o \
          sl811_usb.o sm501.o smc91111.o smiLynxEM.o \
          status_led.o sym53c8xx.o \
-         ti_pci1410a.o tigon3.o \
+         ti_pci1410a.o tigon3.o tsec.o \
          usbdcore.o usbdcore_ep0.o usbdcore_omap1510.o usbtty.o \
          videomodes.o w83c553f.o \
          ks8695eth.o
diff --git a/drivers/tsec.c b/drivers/tsec.c
new file mode 100644 (file)
index 0000000..5ac6334
--- /dev/null
@@ -0,0 +1,1074 @@
+/*
+ * tsec.c
+ * Freescale Three Speed Ethernet Controller driver
+ *
+ * This software may be used and distributed according to the
+ * terms of the GNU Public License, Version 2, incorporated
+ * herein by reference.
+ *
+ * Copyright 2004 Freescale Semiconductor.
+ * (C) Copyright 2003, Motorola, Inc.
+ * maintained by Jon Loeliger (loeliger@freescale.com)
+ * author Andy Fleming
+ *
+ */
+
+#include <config.h>
+#include <mpc85xx.h>
+#include <common.h>
+#include <malloc.h>
+#include <net.h>
+#include <command.h>
+
+#if defined(CONFIG_TSEC_ENET)
+#include "tsec.h"
+
+#define TX_BUF_CNT 2
+
+static uint rxIdx;     /* index of the current RX buffer */
+static uint txIdx;     /* index of the current TX buffer */
+
+typedef volatile struct rtxbd {
+       txbd8_t txbd[TX_BUF_CNT];
+       rxbd8_t rxbd[PKTBUFSRX];
+}  RTXBD;
+
+struct tsec_info_struct {
+       unsigned int phyaddr;
+       u32 flags;
+       unsigned int phyregidx;
+};
+
+
+/* The tsec_info structure contains 3 values which the
+ * driver uses to determine how to operate a given ethernet
+ * device.  For now, the structure is initialized with the
+ * knowledge that all current implementations have 2 TSEC
+ * devices, and one FEC.  The information needed is:
+ *  phyaddr - The address of the PHY which is attached to
+ *     the given device.
+ *
+ *  flags - This variable indicates whether the device
+ *     supports gigabit speed ethernet, and whether it should be
+ *     in reduced mode.
+ *
+ *  phyregidx - This variable specifies which ethernet device
+ *     controls the MII Management registers which are connected
+ *     to the PHY.  For 8540/8560, only TSEC1 (index 0) has
+ *     access to the PHYs, so all of the entries have "0".
+ *
+ * The values specified in the table are taken from the board's
+ * config file in include/configs/.  When implementing a new
+ * board with ethernet capability, it is necessary to define:
+ *   TSEC1_PHY_ADDR
+ *   TSEC1_PHYIDX
+ *   TSEC2_PHY_ADDR
+ *   TSEC2_PHYIDX
+ *
+ * and for 8560:
+ *   FEC_PHY_ADDR
+ *   FEC_PHYIDX
+ */
+static struct tsec_info_struct tsec_info[] = {
+#ifdef CONFIG_MPC85XX_TSEC1
+       {TSEC1_PHY_ADDR, TSEC_GIGABIT, TSEC1_PHYIDX},
+#else
+       { 0, 0, 0},
+#endif
+#ifdef CONFIG_MPC85XX_TSEC2
+       {TSEC2_PHY_ADDR, TSEC_GIGABIT, TSEC2_PHYIDX},
+#else
+       { 0, 0, 0},
+#endif
+#ifdef CONFIG_MPC85XX_FEC
+       {FEC_PHY_ADDR, 0, FEC_PHYIDX},
+#else
+#    ifdef CONFIG_MPC85XX_TSEC3
+       {TSEC3_PHY_ADDR, TSEC_GIGABIT | TSEC_REDUCED, TSEC3_PHYIDX},
+#    else
+       { 0, 0, 0},
+#    endif
+#    ifdef CONFIG_MPC85XX_TSEC4
+       {TSEC4_PHY_ADDR, TSEC_REDUCED, TSEC4_PHYIDX},
+#    else
+       { 0, 0, 0},
+#    endif
+#endif
+};
+
+#define MAXCONTROLLERS (4)
+
+static int relocated = 0;
+
+static struct tsec_private *privlist[MAXCONTROLLERS];
+
+#ifdef __GNUC__
+static RTXBD rtx __attribute__ ((aligned(8)));
+#else
+#error "rtx must be 64-bit aligned"
+#endif
+
+static int tsec_send(struct eth_device* dev, volatile void *packet, int length);
+static int tsec_recv(struct eth_device* dev);
+static int tsec_init(struct eth_device* dev, bd_t * bd);
+static void tsec_halt(struct eth_device* dev);
+static void init_registers(volatile tsec_t *regs);
+static void startup_tsec(struct eth_device *dev);
+static int init_phy(struct eth_device *dev);
+void write_phy_reg(struct tsec_private *priv, uint regnum, uint value);
+uint read_phy_reg(struct tsec_private *priv, uint regnum);
+struct phy_info * get_phy_info(struct eth_device *dev);
+void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd);
+static void adjust_link(struct eth_device *dev);
+static void relocate_cmds(void);
+
+/* Initialize device structure. Returns success if PHY
+ * initialization succeeded (i.e. if it recognizes the PHY)
+ */
+int tsec_initialize(bd_t *bis, int index, char *devname)
+{
+       struct eth_device* dev;
+       int i;
+       struct tsec_private *priv;
+
+       dev = (struct eth_device*) malloc(sizeof *dev);
+
+       if(NULL == dev)
+               return 0;
+
+       memset(dev, 0, sizeof *dev);
+
+       priv = (struct tsec_private *) malloc(sizeof(*priv));
+
+       if(NULL == priv)
+               return 0;
+
+       privlist[index] = priv;
+       priv->regs = (volatile tsec_t *)(TSEC_BASE_ADDR + index*TSEC_SIZE);
+       priv->phyregs = (volatile tsec_t *)(TSEC_BASE_ADDR +
+                       tsec_info[index].phyregidx*TSEC_SIZE);
+
+       priv->phyaddr = tsec_info[index].phyaddr;
+       priv->flags = tsec_info[index].flags;
+
+       sprintf(dev->name, devname);
+       dev->iobase = 0;
+       dev->priv   = priv;
+       dev->init   = tsec_init;
+       dev->halt   = tsec_halt;
+       dev->send   = tsec_send;
+       dev->recv   = tsec_recv;
+
+       /* Tell u-boot to get the addr from the env */
+       for(i=0;i<6;i++)
+               dev->enetaddr[i] = 0;
+
+       eth_register(dev);
+
+
+       /* Reset the MAC */
+       priv->regs->maccfg1 |= MACCFG1_SOFT_RESET;
+       priv->regs->maccfg1 &= ~(MACCFG1_SOFT_RESET);
+
+       /* Try to initialize PHY here, and return */
+       return init_phy(dev);
+}
+
+
+/* Initializes data structures and registers for the controller,
+ * and brings the interface up.         Returns the link status, meaning
+ * that it returns success if the link is up, failure otherwise.
+ * This allows u-boot to find the first active controller. */
+int tsec_init(struct eth_device* dev, bd_t * bd)
+{
+       uint tempval;
+       char tmpbuf[MAC_ADDR_LEN];
+       int i;
+       struct tsec_private *priv = (struct tsec_private *)dev->priv;
+       volatile tsec_t *regs = priv->regs;
+
+       /* Make sure the controller is stopped */
+       tsec_halt(dev);
+
+       /* Init MACCFG2.  Defaults to GMII */
+       regs->maccfg2 = MACCFG2_INIT_SETTINGS;
+
+       /* Init ECNTRL */
+       regs->ecntrl = ECNTRL_INIT_SETTINGS;
+
+       /* Copy the station address into the address registers.
+        * Backwards, because little endian MACS are dumb */
+       for(i=0;i<MAC_ADDR_LEN;i++) {
+               tmpbuf[MAC_ADDR_LEN - 1 - i] = dev->enetaddr[i];
+       }
+       (uint)(regs->macstnaddr1) = *((uint *)(tmpbuf));
+
+       tempval = *((uint *)(tmpbuf +4));
+
+       (uint)(regs->macstnaddr2) = tempval;
+
+       /* reset the indices to zero */
+       rxIdx = 0;
+       txIdx = 0;
+
+       /* Clear out (for the most part) the other registers */
+       init_registers(regs);
+
+       /* Ready the device for tx/rx */
+       startup_tsec(dev);
+
+       /* If there's no link, fail */
+       return priv->link;
+
+}
+
+
+/* Write value to the device's PHY through the registers
+ * specified in priv, modifying the register specified in regnum.
+ * It will wait for the write to be done (or for a timeout to
+ * expire) before exiting
+ */
+void write_phy_reg(struct tsec_private *priv, uint regnum, uint value)
+{
+       volatile tsec_t *regbase = priv->phyregs;
+       uint phyid = priv->phyaddr;
+       int timeout=1000000;
+
+       regbase->miimadd = (phyid << 8) | regnum;
+       regbase->miimcon = value;
+       asm("msync");
+
+       timeout=1000000;
+       while((regbase->miimind & MIIMIND_BUSY) && timeout--);
+}
+
+
+/* Reads register regnum on the device's PHY through the
+ * registers specified in priv.         It lowers and raises the read
+ * command, and waits for the data to become valid (miimind
+ * notvalid bit cleared), and the bus to cease activity (miimind
+ * busy bit cleared), and then returns the value
+ */
+uint read_phy_reg(struct tsec_private *priv, uint regnum)
+{
+       uint value;
+       volatile tsec_t *regbase = priv->phyregs;
+       uint phyid = priv->phyaddr;
+
+       /* Put the address of the phy, and the register
+        * number into MIIMADD */
+       regbase->miimadd = (phyid << 8) | regnum;
+
+       /* Clear the command register, and wait */
+       regbase->miimcom = 0;
+       asm("msync");
+
+       /* Initiate a read command, and wait */
+       regbase->miimcom = MIIM_READ_COMMAND;
+       asm("msync");
+
+       /* Wait for the the indication that the read is done */
+       while((regbase->miimind & (MIIMIND_NOTVALID | MIIMIND_BUSY)));
+
+       /* Grab the value read from the PHY */
+       value = regbase->miimstat;
+
+       return value;
+}
+
+
+/* Discover which PHY is attached to the device, and configure it
+ * properly.  If the PHY is not recognized, then return 0
+ * (failure).  Otherwise, return 1
+ */
+static int init_phy(struct eth_device *dev)
+{
+       struct tsec_private *priv = (struct tsec_private *)dev->priv;
+       struct phy_info *curphy;
+
+       /* Assign a Physical address to the TBI */
+
+       {
+               volatile tsec_t *regs = (volatile tsec_t *)(TSEC_BASE_ADDR);
+               regs->tbipa = TBIPA_VALUE;
+               regs = (volatile tsec_t *)(TSEC_BASE_ADDR + TSEC_SIZE);
+               regs->tbipa = TBIPA_VALUE;
+               asm("msync");
+       }
+
+       /* Reset MII (due to new addresses) */
+       priv->phyregs->miimcfg = MIIMCFG_RESET;
+       asm("msync");
+       priv->phyregs->miimcfg = MIIMCFG_INIT_VALUE;
+       asm("msync");
+       while(priv->phyregs->miimind & MIIMIND_BUSY);
+
+       if(0 == relocated)
+               relocate_cmds();
+
+       /* Get the cmd structure corresponding to the attached
+        * PHY */
+       curphy = get_phy_info(dev);
+
+       if(NULL == curphy) {
+               printf("%s: No PHY found\n", dev->name);
+
+               return 0;
+       }
+
+       priv->phyinfo = curphy;
+
+       phy_run_commands(priv, priv->phyinfo->config);
+
+       return 1;
+}
+
+
+/* Returns which value to write to the control register. */
+/* For 10/100, the value is slightly different */
+uint mii_cr_init(uint mii_reg, struct tsec_private *priv)
+{
+       if(priv->flags & TSEC_GIGABIT)
+               return MIIM_CONTROL_INIT;
+       else
+               return MIIM_CR_INIT;
+}
+
+
+/* Parse the status register for link, and then do
+ * auto-negotiation */
+uint mii_parse_sr(uint mii_reg, struct tsec_private *priv)
+{
+       uint timeout = TSEC_TIMEOUT;
+
+       if(mii_reg & MIIM_STATUS_LINK)
+               priv->link = 1;
+       else
+               priv->link = 0;
+
+       if(priv->link) {
+               while((!(mii_reg & MIIM_STATUS_AN_DONE)) && timeout--)
+                       mii_reg = read_phy_reg(priv, MIIM_STATUS);
+       }
+
+       return 0;
+}
+
+
+/* Parse the 88E1011's status register for speed and duplex
+ * information */
+uint mii_parse_88E1011_psr(uint mii_reg, struct tsec_private *priv)
+{
+       uint speed;
+
+       if(mii_reg & MIIM_88E1011_PHYSTAT_DUPLEX)
+               priv->duplexity = 1;
+       else
+               priv->duplexity = 0;
+
+       speed = (mii_reg &MIIM_88E1011_PHYSTAT_SPEED);
+
+       switch(speed) {
+               case MIIM_88E1011_PHYSTAT_GBIT:
+                       priv->speed = 1000;
+                       break;
+               case MIIM_88E1011_PHYSTAT_100:
+                       priv->speed = 100;
+                       break;
+               default:
+                       priv->speed = 10;
+       }
+
+       return 0;
+}
+
+
+/* Parse the cis8201's status register for speed and duplex
+ * information */
+uint mii_parse_cis8201(uint mii_reg, struct tsec_private *priv)
+{
+       uint speed;
+
+       if(mii_reg & MIIM_CIS8201_AUXCONSTAT_DUPLEX)
+               priv->duplexity = 1;
+       else
+               priv->duplexity = 0;
+
+       speed = mii_reg & MIIM_CIS8201_AUXCONSTAT_SPEED;
+       switch(speed) {
+               case MIIM_CIS8201_AUXCONSTAT_GBIT:
+                       priv->speed = 1000;
+                       break;
+               case MIIM_CIS8201_AUXCONSTAT_100:
+                       priv->speed = 100;
+                       break;
+               default:
+                       priv->speed = 10;
+                       break;
+       }
+
+       return 0;
+}
+
+
+/* Parse the DM9161's status register for speed and duplex
+ * information */
+uint mii_parse_dm9161_scsr(uint mii_reg, struct tsec_private *priv)
+{
+       if(mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_100H))
+               priv->speed = 100;
+       else
+               priv->speed = 10;
+
+       if(mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_10F))
+               priv->duplexity = 1;
+       else
+               priv->duplexity = 0;
+
+       return 0;
+}
+
+
+/* Hack to write all 4 PHYs with the LED values */
+uint mii_cis8204_fixled(uint mii_reg, struct tsec_private *priv)
+{
+       uint phyid;
+       volatile tsec_t *regbase = priv->phyregs;
+       int timeout=1000000;
+
+       for(phyid=0;phyid<4;phyid++) {
+               regbase->miimadd = (phyid << 8) | mii_reg;
+               regbase->miimcon = MIIM_CIS8204_SLEDCON_INIT;
+               asm("msync");
+
+               timeout=1000000;
+               while((regbase->miimind & MIIMIND_BUSY) && timeout--);
+       }
+
+       return MIIM_CIS8204_SLEDCON_INIT;
+}
+
+uint mii_cis8204_setmode(uint mii_reg, struct tsec_private *priv)
+{
+       if (priv->flags & TSEC_REDUCED)
+               return MIIM_CIS8204_EPHYCON_INIT | MIIM_CIS8204_EPHYCON_RGMII;
+       else
+               return MIIM_CIS8204_EPHYCON_INIT;
+}
+
+/* Initialized required registers to appropriate values, zeroing
+ * those we don't care about (unless zero is bad, in which case,
+ * choose a more appropriate value) */
+static void init_registers(volatile tsec_t *regs)
+{
+       /* Clear IEVENT */
+       regs->ievent = IEVENT_INIT_CLEAR;
+
+       regs->imask = IMASK_INIT_CLEAR;
+
+       regs->hash.iaddr0 = 0;
+       regs->hash.iaddr1 = 0;
+       regs->hash.iaddr2 = 0;
+       regs->hash.iaddr3 = 0;
+       regs->hash.iaddr4 = 0;
+       regs->hash.iaddr5 = 0;
+       regs->hash.iaddr6 = 0;
+       regs->hash.iaddr7 = 0;
+
+       regs->hash.gaddr0 = 0;
+       regs->hash.gaddr1 = 0;
+       regs->hash.gaddr2 = 0;
+       regs->hash.gaddr3 = 0;
+       regs->hash.gaddr4 = 0;
+       regs->hash.gaddr5 = 0;
+       regs->hash.gaddr6 = 0;
+       regs->hash.gaddr7 = 0;
+
+       regs->rctrl = 0x00000000;
+
+       /* Init RMON mib registers */
+       memset((void *)&(regs->rmon), 0, sizeof(rmon_mib_t));
+
+       regs->rmon.cam1 = 0xffffffff;
+       regs->rmon.cam2 = 0xffffffff;
+
+       regs->mrblr = MRBLR_INIT_SETTINGS;
+
+       regs->minflr = MINFLR_INIT_SETTINGS;
+
+       regs->attr = ATTR_INIT_SETTINGS;
+       regs->attreli = ATTRELI_INIT_SETTINGS;
+
+}
+
+
+/* Configure maccfg2 based on negotiated speed and duplex
+ * reported by PHY handling code */
+static void adjust_link(struct eth_device *dev)
+{
+       struct tsec_private *priv = (struct tsec_private *)dev->priv;
+       volatile tsec_t *regs = priv->regs;
+
+       if(priv->link) {
+               if(priv->duplexity != 0)
+                       regs->maccfg2 |= MACCFG2_FULL_DUPLEX;
+               else
+                       regs->maccfg2 &= ~(MACCFG2_FULL_DUPLEX);
+
+               switch(priv->speed) {
+                       case 1000:
+                               regs->maccfg2 = ((regs->maccfg2&~(MACCFG2_IF))
+                                       | MACCFG2_GMII);
+                               break;
+                       case 100:
+                       case 10:
+                               regs->maccfg2 = ((regs->maccfg2&~(MACCFG2_IF))
+                                       | MACCFG2_MII);
+
+                               /* If We're in reduced mode, we
+                                * need to say whether we're 10
+                                * or 100 MB. */
+                               if ((priv->speed == 100) 
+                                               && (priv->flags & TSEC_REDUCED))
+                                       regs->ecntrl |= ECNTRL_R100;
+                               else
+                                       regs->ecntrl &= ~(ECNTRL_R100);
+                               break;
+                       default:
+                               printf("%s: Speed was bad\n", dev->name);
+                               break;
+               }
+
+               printf("Speed: %d, %s duplex\n", priv->speed,
+                               (priv->duplexity) ? "full" : "half");
+
+       } else {
+               printf("%s: No link.\n", dev->name);
+       }
+}
+
+
+/* Set up the buffers and their descriptors, and bring up the
+ * interface */
+static void startup_tsec(struct eth_device *dev)
+{
+       int i;
+       struct tsec_private *priv = (struct tsec_private *)dev->priv;
+       volatile tsec_t *regs = priv->regs;
+
+       /* Point to the buffer descriptors */
+       regs->tbase = (unsigned int)(&rtx.txbd[txIdx]);
+       regs->rbase = (unsigned int)(&rtx.rxbd[rxIdx]);
+
+       /* Initialize the Rx Buffer descriptors */
+       for (i = 0; i < PKTBUFSRX; i++) {
+               rtx.rxbd[i].status = RXBD_EMPTY;
+               rtx.rxbd[i].length = 0;
+               rtx.rxbd[i].bufPtr = (uint)NetRxPackets[i];
+       }
+       rtx.rxbd[PKTBUFSRX -1].status |= RXBD_WRAP;
+
+       /* Initialize the TX Buffer Descriptors */
+       for(i=0; i<TX_BUF_CNT; i++) {
+               rtx.txbd[i].status = 0;
+               rtx.txbd[i].length = 0;
+               rtx.txbd[i].bufPtr = 0;
+       }
+       rtx.txbd[TX_BUF_CNT -1].status |= TXBD_WRAP;
+
+       /* Start up the PHY */
+       phy_run_commands(priv, priv->phyinfo->startup);
+       adjust_link(dev);
+
+       /* Enable Transmit and Receive */
+       regs->maccfg1 |= (MACCFG1_RX_EN | MACCFG1_TX_EN);
+
+       /* Tell the DMA it is clear to go */
+       regs->dmactrl |= DMACTRL_INIT_SETTINGS;
+       regs->tstat = TSTAT_CLEAR_THALT;
+       regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
+}
+
+/* This returns the status bits of the device. The return value
+ * is never checked, and this is what the 8260 driver did, so we
+ * do the same.         Presumably, this would be zero if there were no
+ * errors */
+static int tsec_send(struct eth_device* dev, volatile void *packet, int length)
+{
+       int i;
+       int result = 0;
+       struct tsec_private *priv = (struct tsec_private *)dev->priv;
+       volatile tsec_t *regs = priv->regs;
+
+       /* Find an empty buffer descriptor */
+       for(i=0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
+               if (i >= TOUT_LOOP) {
+                       debug ("%s: tsec: tx buffers full\n", dev->name);
+                       return result;
+               }
+       }
+
+       rtx.txbd[txIdx].bufPtr = (uint)packet;
+       rtx.txbd[txIdx].length = length;
+       rtx.txbd[txIdx].status |= (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT);
+
+       /* Tell the DMA to go */
+       regs->tstat = TSTAT_CLEAR_THALT;
+
+       /* Wait for buffer to be transmitted */
+       for(i=0; rtx.txbd[txIdx].status & TXBD_READY; i++) {
+               if (i >= TOUT_LOOP) {
+                       debug ("%s: tsec: tx error\n", dev->name);
+                       return result;
+               }
+       }
+
+       txIdx = (txIdx + 1) % TX_BUF_CNT;
+       result = rtx.txbd[txIdx].status & TXBD_STATS;
+
+       return result;
+}
+
+static int tsec_recv(struct eth_device* dev)
+{
+       int length;
+       struct tsec_private *priv = (struct tsec_private *)dev->priv;
+       volatile tsec_t *regs = priv->regs;
+
+       while(!(rtx.rxbd[rxIdx].status & RXBD_EMPTY)) {
+
+               length = rtx.rxbd[rxIdx].length;
+
+               /* Send the packet up if there were no errors */
+               if (!(rtx.rxbd[rxIdx].status & RXBD_STATS)) {
+                       NetReceive(NetRxPackets[rxIdx], length - 4);
+               } else {
+                       printf("Got error %x\n",
+                                       (rtx.rxbd[rxIdx].status & RXBD_STATS));
+               }
+
+               rtx.rxbd[rxIdx].length = 0;
+
+               /* Set the wrap bit if this is the last element in the list */
+               rtx.rxbd[rxIdx].status = RXBD_EMPTY | (((rxIdx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0);
+
+               rxIdx = (rxIdx + 1) % PKTBUFSRX;
+       }
+
+       if(regs->ievent&IEVENT_BSY) {
+               regs->ievent = IEVENT_BSY;
+               regs->rstat = RSTAT_CLEAR_RHALT;
+       }
+
+       return -1;
+
+}
+
+
+/* Stop the interface */
+static void tsec_halt(struct eth_device* dev)
+{
+       struct tsec_private *priv = (struct tsec_private *)dev->priv;
+       volatile tsec_t *regs = priv->regs;
+
+       regs->dmactrl &= ~(DMACTRL_GRS | DMACTRL_GTS);
+       regs->dmactrl |= (DMACTRL_GRS | DMACTRL_GTS);
+
+       while(!(regs->ievent & (IEVENT_GRSC | IEVENT_GTSC)));
+
+       regs->maccfg1 &= ~(MACCFG1_TX_EN | MACCFG1_RX_EN);
+
+       /* Shut down the PHY, as needed */
+       phy_run_commands(priv, priv->phyinfo->shutdown);
+}
+
+
+struct phy_info phy_info_M88E1011S = {
+       0x01410c6,
+       "Marvell 88E1011S",
+       4,
+       (struct phy_cmd[]) { /* config */
+               /* Reset and configure the PHY */
+               {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
+               {0x1d, 0x1f, NULL},
+               {0x1e, 0x200c, NULL},
+               {0x1d, 0x5, NULL},
+               {0x1e, 0x0, NULL},
+               {0x1e, 0x100, 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_88E1011_PHY_STATUS, miim_read, &mii_parse_88E1011_psr},
+               {miim_end,}
+       },
+       (struct phy_cmd[]) { /* shutdown */
+               {miim_end,}
+       },
+};
+
+struct phy_info phy_info_M88E1111S = {
+       0x01410cc,
+       "Marvell 88E1111S",
+       4,
+       (struct phy_cmd[]) { /* config */
+         /* Reset and configure the PHY */
+               {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL},
+               {0x1d, 0x1f, NULL},
+               {0x1e, 0x200c, NULL},
+               {0x1d, 0x5, NULL},
+               {0x1e, 0x0, NULL},
+               {0x1e, 0x100, 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_88E1011_PHY_STATUS, miim_read, &mii_parse_88E1011_psr},
+               {miim_end,}
+       },
+       (struct phy_cmd[]) { /* shutdown */
+               {miim_end,}
+       },
+};
+
+struct phy_info phy_info_cis8204 = {
+       0x3f11,
+       "Cicada Cis8204",
+       6,
+       (struct phy_cmd[]) { /* config */
+               /* Override PHY config settings */
+               {MIIM_CIS8201_AUX_CONSTAT, MIIM_CIS8201_AUXCONSTAT_INIT, NULL},
+               /* Configure some basic stuff */
+               {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
+               {MIIM_CIS8204_SLED_CON, MIIM_CIS8204_SLEDCON_INIT, &mii_cis8204_fixled},
+               {MIIM_CIS8204_EPHY_CON, MIIM_CIS8204_EPHYCON_INIT, &mii_cis8204_setmode},
+               {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_CIS8201_AUX_CONSTAT, miim_read, &mii_parse_cis8201},
+               {miim_end,}
+       },
+       (struct phy_cmd[]) { /* shutdown */
+               {miim_end,}
+       },
+};
+
+/* Cicada 8201 */
+struct phy_info phy_info_cis8201 = {
+       0xfc41,
+       "CIS8201",
+       4,
+       (struct phy_cmd[]) { /* config */
+               /* Override PHY config settings */
+               {MIIM_CIS8201_AUX_CONSTAT, MIIM_CIS8201_AUXCONSTAT_INIT, NULL},
+               /* Set up the interface mode */
+               {MIIM_CIS8201_EXT_CON1, MIIM_CIS8201_EXTCON1_INIT, NULL},
+               /* Configure some basic stuff */
+               {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init},
+               {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_CIS8201_AUX_CONSTAT, miim_read, &mii_parse_cis8201},
+               {miim_end,}
+       },
+       (struct phy_cmd[]) { /* shutdown */
+               {miim_end,}
+       },
+};
+
+
+struct phy_info phy_info_dm9161 = {
+       0x0181b88,
+       "Davicom DM9161E",
+       4,
+       (struct phy_cmd[]) { /* config */
+               {MIIM_CONTROL, MIIM_DM9161_CR_STOP, NULL},
+               /* Do not bypass the scrambler/descrambler */
+               {MIIM_DM9161_SCR, MIIM_DM9161_SCR_INIT, NULL},
+               /* Clear 10BTCSR to default */
+               {MIIM_DM9161_10BTCSR, MIIM_DM9161_10BTCSR_INIT, NULL},
+               /* Configure some basic stuff */
+               {MIIM_CONTROL, MIIM_CR_INIT, NULL},
+               /* Restart Auto Negotiation */
+               {MIIM_CONTROL, MIIM_DM9161_CR_RSTAN, NULL},
+               {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_DM9161_SCSR, miim_read, &mii_parse_dm9161_scsr},
+               {miim_end,}
+       },
+       (struct phy_cmd[]) { /* shutdown */
+               {miim_end,}
+       },
+};
+
+uint mii_parse_lxt971_sr2(uint mii_reg, struct tsec_private *priv)
+{
+       unsigned int speed;
+       if (priv->link) {
+               speed = mii_reg & MIIM_LXT971_SR2_SPEED_MASK;
+
+               switch (speed) {
+               case MIIM_LXT971_SR2_10HDX:
+                       priv->speed = 10;
+                       priv->duplexity = 0;
+                       break;
+               case MIIM_LXT971_SR2_10FDX:
+                       priv->speed = 10;
+                       priv->duplexity = 1;
+                       break;
+               case MIIM_LXT971_SR2_100HDX:
+                       priv->speed = 100;
+                       priv->duplexity = 0;
+               default:
+                       priv->speed = 100;
+                       priv->duplexity = 1;
+                       break;
+               }
+       } else {
+               priv->speed = 0;
+               priv->duplexity = 0;
+       }
+
+       return 0;
+}
+
+static struct phy_info phy_info_lxt971 = {
+       0x0001378e,
+       "LXT971",
+       4,
+       (struct phy_cmd []) {  /* config */
+               { MIIM_CR, MIIM_CR_INIT, mii_cr_init }, /* autonegotiate */
+               { miim_end, }
+       },
+       (struct phy_cmd []) {  /* startup - enable interrupts */
+               /* { 0x12, 0x00f2, NULL }, */
+               { MIIM_STATUS, miim_read, NULL },
+               { MIIM_STATUS, miim_read, &mii_parse_sr },
+               { MIIM_LXT971_SR2, miim_read, &mii_parse_lxt971_sr2 },
+               { miim_end, }
+       },
+       (struct phy_cmd []) {  /* shutdown - disable interrupts */
+               { miim_end, }
+       },
+};
+
+struct phy_info *phy_info[] = {
+#if 0
+       &phy_info_cis8201,
+#endif
+       &phy_info_cis8204,
+       &phy_info_M88E1011S,
+       &phy_info_M88E1111S,
+       &phy_info_dm9161,
+       &phy_info_lxt971,
+       NULL
+};
+
+
+/* Grab the identifier of the device's PHY, and search through
+ * all of the known PHYs to see if one matches.         If so, return
+ * it, if not, return NULL */
+struct phy_info * get_phy_info(struct eth_device *dev)
+{
+       struct tsec_private *priv = (struct tsec_private *)dev->priv;
+       uint phy_reg, phy_ID;
+       int i;
+       struct phy_info *theInfo = NULL;
+
+       /* Grab the bits from PHYIR1, and put them in the upper half */
+       phy_reg = read_phy_reg(priv, MIIM_PHYIR1);
+       phy_ID = (phy_reg & 0xffff) << 16;
+
+       /* Grab the bits from PHYIR2, and put them in the lower half */
+       phy_reg = read_phy_reg(priv, MIIM_PHYIR2);
+       phy_ID |= (phy_reg & 0xffff);
+
+       /* loop through all the known PHY types, and find one that */
+       /* matches the ID we read from the PHY. */
+       for(i=0; phy_info[i]; i++) {
+               if(phy_info[i]->id == (phy_ID >> phy_info[i]->shift))
+                       theInfo = phy_info[i];
+       }
+
+       if(theInfo == NULL)
+       {
+               printf("%s: PHY id %x is not supported!\n", dev->name, phy_ID);
+               return NULL;
+       } else {
+               printf("%s: PHY is %s (%x)\n", dev->name, theInfo->name,
+                               phy_ID);
+       }
+
+       return theInfo;
+}
+
+
+/* Execute the given series of commands on the given device's
+ * PHY, running functions as necessary*/
+void phy_run_commands(struct tsec_private *priv, struct phy_cmd *cmd)
+{
+       int i;
+       uint result;
+       volatile tsec_t *phyregs = priv->phyregs;
+
+       phyregs->miimcfg = MIIMCFG_RESET;
+
+       phyregs->miimcfg = MIIMCFG_INIT_VALUE;
+
+       while(phyregs->miimind & MIIMIND_BUSY);
+
+       for(i=0;cmd->mii_reg != miim_end;i++) {
+               if(cmd->mii_data == miim_read) {
+                       result = read_phy_reg(priv, cmd->mii_reg);
+
+                       if(cmd->funct != NULL)
+                               (*(cmd->funct))(result, priv);
+
+               } else {
+                       if(cmd->funct != NULL)
+                               result = (*(cmd->funct))(cmd->mii_reg, priv);
+                       else
+                               result = cmd->mii_data;
+
+                       write_phy_reg(priv, cmd->mii_reg, result);
+
+               }
+               cmd++;
+       }
+}
+
+
+/* Relocate the function pointers in the phy cmd lists */
+static void relocate_cmds(void)
+{
+       struct phy_cmd **cmdlistptr;
+       struct phy_cmd *cmd;
+       int i,j,k;
+       DECLARE_GLOBAL_DATA_PTR;
+
+       for(i=0; phy_info[i]; i++) {
+               /* First thing's first: relocate the pointers to the
+                * PHY command structures (the structs were done) */
+               phy_info[i] = (struct phy_info *) ((uint)phy_info[i]
+                               + gd->reloc_off);
+               phy_info[i]->name += gd->reloc_off;
+               phy_info[i]->config =
+                       (struct phy_cmd *)((uint)phy_info[i]->config
+                                          + gd->reloc_off);
+               phy_info[i]->startup =
+                       (struct phy_cmd *)((uint)phy_info[i]->startup
+                                          + gd->reloc_off);
+               phy_info[i]->shutdown =
+                       (struct phy_cmd *)((uint)phy_info[i]->shutdown
+                                          + gd->reloc_off);
+
+               cmdlistptr = &phy_info[i]->config;
+               j=0;
+               for(;cmdlistptr <= &phy_info[i]->shutdown;cmdlistptr++) {
+                       k=0;
+                       for(cmd=*cmdlistptr;cmd->mii_reg != miim_end;cmd++) {
+                               /* Only relocate non-NULL pointers */
+                               if(cmd->funct)
+                                       cmd->funct += gd->reloc_off;
+
+                               k++;
+                       }
+                       j++;
+               }
+       }
+
+       relocated = 1;
+}
+
+
+#ifndef CONFIG_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.
+ *
+ * Returns:
+ *  0 on success
+ */
+int miiphy_read(unsigned char addr, unsigned char reg, unsigned short *value)
+{
+       unsigned short ret;
+       struct tsec_private *priv = get_priv_for_phy(addr);
+
+       if(NULL == priv) {
+               printf("Can't read PHY at address %d\n", addr);
+               return -1;
+       }
+
+       ret = (unsigned short)read_phy_reg(priv, reg);
+       *value = ret;
+
+       return 0;
+}
+
+/*
+ * Write a MII PHY register.
+ *
+ * Returns:
+ *  0 on success
+ */
+int miiphy_write(unsigned char addr, unsigned char reg, unsigned short value)
+{
+       struct tsec_private *priv = get_priv_for_phy(addr);
+
+       if(NULL == priv) {
+               printf("Can't write PHY at address %d\n", addr);
+               return -1;
+       }
+
+       write_phy_reg(priv, reg, value);
+
+       return 0;
+}
+
+#endif /* CONFIG_BITBANGMII */
+
+#endif /* CONFIG_TSEC_ENET */
diff --git a/drivers/tsec.h b/drivers/tsec.h
new file mode 100644 (file)
index 0000000..d1c70aa
--- /dev/null
@@ -0,0 +1,494 @@
+/*
+ *  tsec.h
+ *
+ *  Driver for the Motorola Triple Speed Ethernet Controller
+ *
+ *  This software may be used and distributed according to the
+ *  terms of the GNU Public License, Version 2, incorporated
+ *  herein by reference.
+ *
+ * Copyright 2004 Freescale Semiconductor.
+ * (C) Copyright 2003, Motorola, Inc.
+ * maintained by Xianghua Xiao (x.xiao@motorola.com)
+ * author Andy Fleming
+ *
+ */
+
+#ifndef __TSEC_H
+#define __TSEC_H
+
+#include <net.h>
+#include <mpc85xx.h>
+
+#define TSEC_BASE_ADDR (CFG_IMMR + 0x24000)
+#define TSEC_SIZE      0x01000
+
+#define MAC_ADDR_LEN 6
+
+/* #define TSEC_TIMEOUT        1000000 */
+#define TSEC_TIMEOUT 1000
+#define TOUT_LOOP      1000000
+
+/* MAC register bits */
+#define MACCFG1_SOFT_RESET     0x80000000
+#define MACCFG1_RESET_RX_MC    0x00080000
+#define MACCFG1_RESET_TX_MC    0x00040000
+#define MACCFG1_RESET_RX_FUN   0x00020000
+#define        MACCFG1_RESET_TX_FUN    0x00010000
+#define MACCFG1_LOOPBACK       0x00000100
+#define MACCFG1_RX_FLOW                0x00000020
+#define MACCFG1_TX_FLOW                0x00000010
+#define MACCFG1_SYNCD_RX_EN    0x00000008
+#define MACCFG1_RX_EN          0x00000004
+#define MACCFG1_SYNCD_TX_EN    0x00000002
+#define MACCFG1_TX_EN          0x00000001
+
+#define MACCFG2_INIT_SETTINGS  0x00007205
+#define MACCFG2_FULL_DUPLEX    0x00000001
+#define MACCFG2_IF              0x00000300
+#define MACCFG2_GMII           0x00000200
+#define MACCFG2_MII             0x00000100
+
+#define ECNTRL_INIT_SETTINGS   0x00001000
+#define ECNTRL_TBI_MODE         0x00000020
+#define ECNTRL_R100            0x00000008
+
+#define miim_end -2
+#define miim_read -1
+
+#define TBIPA_VALUE            0x1f
+#define MIIMCFG_INIT_VALUE     0x00000003
+#define MIIMCFG_RESET          0x80000000
+
+#define MIIMIND_BUSY            0x00000001
+#define MIIMIND_NOTVALID        0x00000004
+
+#define MIIM_CONTROL            0x00
+#define MIIM_CONTROL_RESET     0x00009140
+#define MIIM_CONTROL_INIT       0x00001140
+#define MIIM_ANEN               0x00001000
+
+#define MIIM_CR                 0x00
+#define MIIM_CR_RST            0x00008000
+#define MIIM_CR_INIT           0x00001000
+
+#define MIIM_STATUS            0x1
+#define MIIM_STATUS_AN_DONE    0x00000020
+#define MIIM_STATUS_LINK       0x0004
+
+#define MIIM_PHYIR1            0x2
+#define MIIM_PHYIR2            0x3
+
+#define MIIM_ANAR              0x4
+#define MIIM_ANAR_INIT         0x1e1
+
+#define MIIM_TBI_ANLPBPA       0x5
+#define MIIM_TBI_ANLPBPA_HALF  0x00000040
+#define MIIM_TBI_ANLPBPA_FULL  0x00000020
+
+#define MIIM_TBI_ANEX          0x6
+#define MIIM_TBI_ANEX_NP       0x00000004
+#define MIIM_TBI_ANEX_PRX      0x00000002
+
+#define MIIM_GBIT_CONTROL      0x9
+#define MIIM_GBIT_CONTROL_INIT 0xe00
+
+/* Cicada Auxiliary Control/Status Register */
+#define MIIM_CIS8201_AUX_CONSTAT        0x1c
+#define MIIM_CIS8201_AUXCONSTAT_INIT    0x0004
+#define MIIM_CIS8201_AUXCONSTAT_DUPLEX  0x0020
+#define MIIM_CIS8201_AUXCONSTAT_SPEED   0x0018
+#define MIIM_CIS8201_AUXCONSTAT_GBIT    0x0010
+#define MIIM_CIS8201_AUXCONSTAT_100     0x0008
+
+/* Cicada Extended Control Register 1 */
+#define MIIM_CIS8201_EXT_CON1           0x17
+#define MIIM_CIS8201_EXTCON1_INIT       0x0000
+
+/* Cicada 8204 Extended PHY Control Register 1 */
+#define MIIM_CIS8204_EPHY_CON          0x17
+#define MIIM_CIS8204_EPHYCON_INIT      0x0006
+#define MIIM_CIS8204_EPHYCON_RGMII     0x1000
+
+/* Cicada 8204 Serial LED Control Register */
+#define MIIM_CIS8204_SLED_CON          0x1b
+#define MIIM_CIS8204_SLEDCON_INIT      0x1115
+
+#define MIIM_GBIT_CON          0x09
+#define MIIM_GBIT_CON_ADVERT   0x0e00
+
+/* 88E1011 PHY Status Register */
+#define MIIM_88E1011_PHY_STATUS         0x11
+#define MIIM_88E1011_PHYSTAT_SPEED      0xc000
+#define MIIM_88E1011_PHYSTAT_GBIT       0x8000
+#define MIIM_88E1011_PHYSTAT_100        0x4000
+#define MIIM_88E1011_PHYSTAT_DUPLEX     0x2000
+#define MIIM_88E1011_PHYSTAT_SPDDONE   0x0800
+#define MIIM_88E1011_PHYSTAT_LINK      0x0400
+
+/* DM9161 Control register values */
+#define MIIM_DM9161_CR_STOP    0x0400
+#define MIIM_DM9161_CR_RSTAN   0x1200
+
+#define MIIM_DM9161_SCR                0x10
+#define MIIM_DM9161_SCR_INIT   0x0610
+
+/* DM9161 Specified Configuration and Status Register */
+#define MIIM_DM9161_SCSR       0x11
+#define MIIM_DM9161_SCSR_100F  0x8000
+#define MIIM_DM9161_SCSR_100H  0x4000
+#define MIIM_DM9161_SCSR_10F   0x2000
+#define MIIM_DM9161_SCSR_10H   0x1000
+
+/* DM9161 10BT Configuration/Status */
+#define MIIM_DM9161_10BTCSR    0x12
+#define MIIM_DM9161_10BTCSR_INIT       0x7800
+
+/* LXT971 Status 2 registers */
+#define MIIM_LXT971_SR2        17  /* Status Register 2  */
+#define MIIM_LXT971_SR2_SPEED_MASK     0xf000
+#define MIIM_LXT971_SR2_10HDX  0x1000  /* 10 Mbit half duplex selected */
+#define MIIM_LXT971_SR2_10FDX  0x2000  /* 10 Mbit full duplex selected */
+#define MIIM_LXT971_SR2_100HDX 0x4000  /* 100 Mbit half duplex selected */
+#define MIIM_LXT971_SR2_100FDX 0x8000  /* 100 Mbit full duplex selected */
+
+#define MIIM_READ_COMMAND       0x00000001
+
+#define MRBLR_INIT_SETTINGS    PKTSIZE_ALIGN
+
+#define MINFLR_INIT_SETTINGS   0x00000040
+
+#define DMACTRL_INIT_SETTINGS   0x000000c3
+#define DMACTRL_GRS             0x00000010
+#define DMACTRL_GTS             0x00000008
+
+#define TSTAT_CLEAR_THALT       0x80000000
+#define RSTAT_CLEAR_RHALT       0x00800000
+
+
+#define IEVENT_INIT_CLEAR      0xffffffff
+#define IEVENT_BABR            0x80000000
+#define IEVENT_RXC             0x40000000
+#define IEVENT_BSY             0x20000000
+#define IEVENT_EBERR           0x10000000
+#define IEVENT_MSRO            0x04000000
+#define IEVENT_GTSC            0x02000000
+#define IEVENT_BABT            0x01000000
+#define IEVENT_TXC             0x00800000
+#define IEVENT_TXE             0x00400000
+#define IEVENT_TXB             0x00200000
+#define IEVENT_TXF             0x00100000
+#define IEVENT_IE              0x00080000
+#define IEVENT_LC              0x00040000
+#define IEVENT_CRL             0x00020000
+#define IEVENT_XFUN            0x00010000
+#define IEVENT_RXB0            0x00008000
+#define IEVENT_GRSC            0x00000100
+#define IEVENT_RXF0            0x00000080
+
+#define IMASK_INIT_CLEAR       0x00000000
+#define IMASK_TXEEN            0x00400000
+#define IMASK_TXBEN            0x00200000
+#define IMASK_TXFEN             0x00100000
+#define IMASK_RXFEN0           0x00000080
+
+
+/* Default Attribute fields */
+#define ATTR_INIT_SETTINGS     0x000000c0
+#define ATTRELI_INIT_SETTINGS  0x00000000
+
+
+/* TxBD status field bits */
+#define TXBD_READY             0x8000
+#define TXBD_PADCRC            0x4000
+#define TXBD_WRAP              0x2000
+#define TXBD_INTERRUPT         0x1000
+#define TXBD_LAST              0x0800
+#define TXBD_CRC               0x0400
+#define TXBD_DEF               0x0200
+#define TXBD_HUGEFRAME         0x0080
+#define TXBD_LATECOLLISION     0x0080
+#define TXBD_RETRYLIMIT                0x0040
+#define        TXBD_RETRYCOUNTMASK     0x003c
+#define TXBD_UNDERRUN          0x0002
+#define TXBD_STATS              0x03ff
+
+/* RxBD status field bits */
+#define RXBD_EMPTY             0x8000
+#define RXBD_RO1               0x4000
+#define RXBD_WRAP              0x2000
+#define RXBD_INTERRUPT         0x1000
+#define RXBD_LAST              0x0800
+#define RXBD_FIRST             0x0400
+#define RXBD_MISS              0x0100
+#define RXBD_BROADCAST         0x0080
+#define RXBD_MULTICAST         0x0040
+#define RXBD_LARGE             0x0020
+#define RXBD_NONOCTET          0x0010
+#define RXBD_SHORT             0x0008
+#define RXBD_CRCERR            0x0004
+#define RXBD_OVERRUN           0x0002
+#define RXBD_TRUNCATED         0x0001
+#define RXBD_STATS             0x003f
+
+typedef struct txbd8
+{
+       ushort       status;         /* Status Fields */
+       ushort       length;         /* Buffer length */
+       uint         bufPtr;         /* Buffer Pointer */
+} txbd8_t;
+
+typedef struct rxbd8
+{
+       ushort       status;         /* Status Fields */
+       ushort       length;         /* Buffer Length */
+       uint         bufPtr;         /* Buffer Pointer */
+} rxbd8_t;
+
+typedef struct rmon_mib
+{
+       /* Transmit and Receive Counters */
+       uint    tr64;           /* Transmit and Receive 64-byte Frame Counter */
+       uint    tr127;          /* Transmit and Receive 65-127 byte Frame Counter */
+       uint    tr255;          /* Transmit and Receive 128-255 byte Frame Counter */
+       uint    tr511;          /* Transmit and Receive 256-511 byte Frame Counter */
+       uint    tr1k;           /* Transmit and Receive 512-1023 byte Frame Counter */
+       uint    trmax;          /* Transmit and Receive 1024-1518 byte Frame Counter */
+       uint    trmgv;          /* Transmit and Receive 1519-1522 byte Good VLAN Frame */
+       /* Receive Counters */
+       uint    rbyt;           /* Receive Byte Counter */
+       uint    rpkt;           /* Receive Packet Counter */
+       uint    rfcs;           /* Receive FCS Error Counter */
+       uint    rmca;           /* Receive Multicast Packet (Counter) */
+       uint    rbca;           /* Receive Broadcast Packet */
+       uint    rxcf;           /* Receive Control Frame Packet */
+       uint    rxpf;           /* Receive Pause Frame Packet */
+       uint    rxuo;           /* Receive Unknown OP Code */
+       uint    raln;           /* Receive Alignment Error */
+       uint    rflr;           /* Receive Frame Length Error */
+       uint    rcde;           /* Receive Code Error */
+       uint    rcse;           /* Receive Carrier Sense Error */
+       uint    rund;           /* Receive Undersize Packet */
+       uint    rovr;           /* Receive Oversize Packet */
+       uint    rfrg;           /* Receive Fragments */
+       uint    rjbr;           /* Receive Jabber */
+       uint    rdrp;           /* Receive Drop */
+       /* Transmit Counters */
+       uint    tbyt;           /* Transmit Byte Counter */
+       uint    tpkt;           /* Transmit Packet */
+       uint    tmca;           /* Transmit Multicast Packet */
+       uint    tbca;           /* Transmit Broadcast Packet */
+       uint    txpf;           /* Transmit Pause Control Frame */
+       uint    tdfr;           /* Transmit Deferral Packet */
+       uint    tedf;           /* Transmit Excessive Deferral Packet */
+       uint    tscl;           /* Transmit Single Collision Packet */
+       /* (0x2_n700) */
+       uint    tmcl;           /* Transmit Multiple Collision Packet */
+       uint    tlcl;           /* Transmit Late Collision Packet */
+       uint    txcl;           /* Transmit Excessive Collision Packet */
+       uint    tncl;           /* Transmit Total Collision */
+
+       uint    res2;
+
+       uint    tdrp;           /* Transmit Drop Frame */
+       uint    tjbr;           /* Transmit Jabber Frame */
+       uint    tfcs;           /* Transmit FCS Error */
+       uint    txcf;           /* Transmit Control Frame */
+       uint    tovr;           /* Transmit Oversize Frame */
+       uint    tund;           /* Transmit Undersize Frame */
+       uint    tfrg;           /* Transmit Fragments Frame */
+       /* General Registers */
+       uint    car1;           /* Carry Register One */
+       uint    car2;           /* Carry Register Two */
+       uint    cam1;           /* Carry Register One Mask */
+       uint    cam2;           /* Carry Register Two Mask */
+} rmon_mib_t;
+
+typedef struct tsec_hash_regs
+{
+       uint    iaddr0;         /* Individual Address Register 0 */
+       uint    iaddr1;         /* Individual Address Register 1 */
+       uint    iaddr2;         /* Individual Address Register 2 */
+       uint    iaddr3;         /* Individual Address Register 3 */
+       uint    iaddr4;         /* Individual Address Register 4 */
+       uint    iaddr5;         /* Individual Address Register 5 */
+       uint    iaddr6;         /* Individual Address Register 6 */
+       uint    iaddr7;         /* Individual Address Register 7 */
+       uint    res1[24];
+       uint    gaddr0;         /* Group Address Register 0 */
+       uint    gaddr1;         /* Group Address Register 1 */
+       uint    gaddr2;         /* Group Address Register 2 */
+       uint    gaddr3;         /* Group Address Register 3 */
+       uint    gaddr4;         /* Group Address Register 4 */
+       uint    gaddr5;         /* Group Address Register 5 */
+       uint    gaddr6;         /* Group Address Register 6 */
+       uint    gaddr7;         /* Group Address Register 7 */
+       uint    res2[24];
+} tsec_hash_t;
+
+typedef struct tsec
+{
+       /* General Control and Status Registers (0x2_n000) */
+       uint    res000[4];
+
+       uint    ievent;         /* Interrupt Event */
+       uint    imask;          /* Interrupt Mask */
+       uint    edis;           /* Error Disabled */
+       uint    res01c;
+       uint    ecntrl;         /* Ethernet Control */
+       uint    minflr;         /* Minimum Frame Length */
+       uint    ptv;            /* Pause Time Value */
+       uint    dmactrl;        /* DMA Control */
+       uint    tbipa;          /* TBI PHY Address */
+
+       uint    res034[3];
+       uint    res040[48];
+
+       /* Transmit Control and Status Registers (0x2_n100) */
+       uint    tctrl;          /* Transmit Control */
+       uint    tstat;          /* Transmit Status */
+       uint    res108;
+       uint    tbdlen;         /* Tx BD Data Length */
+       uint    res110[5];
+       uint    ctbptr;         /* Current TxBD Pointer */
+       uint    res128[23];
+       uint    tbptr;          /* TxBD Pointer */
+       uint    res188[30];
+       /* (0x2_n200) */
+       uint        res200;
+       uint    tbase;          /* TxBD Base Address */
+       uint    res208[42];
+       uint    ostbd;          /* Out of Sequence TxBD */
+       uint    ostbdp;         /* Out of Sequence Tx Data Buffer Pointer */
+       uint        res2b8[18];
+
+       /* Receive Control and Status Registers (0x2_n300) */
+       uint    rctrl;          /* Receive Control */
+       uint    rstat;          /* Receive Status */
+       uint    res308;
+       uint    rbdlen;         /* RxBD Data Length */
+       uint    res310[4];
+       uint        res320;
+       uint    crbptr;         /* Current Receive Buffer Pointer */
+       uint    res328[6];
+       uint    mrblr;          /* Maximum Receive Buffer Length */
+       uint    res344[16];
+       uint    rbptr;          /* RxBD Pointer */
+       uint        res388[30];
+       /* (0x2_n400) */
+       uint        res400;
+       uint    rbase;          /* RxBD Base Address */
+       uint        res408[62];
+
+       /* MAC Registers (0x2_n500) */
+       uint    maccfg1;        /* MAC Configuration #1 */
+       uint    maccfg2;        /* MAC Configuration #2 */
+       uint    ipgifg;         /* Inter Packet Gap/Inter Frame Gap */
+       uint    hafdup;         /* Half-duplex */
+       uint    maxfrm;         /* Maximum Frame */
+       uint    res514;
+       uint    res518;
+
+       uint    res51c;
+
+       uint    miimcfg;        /* MII Management: Configuration */
+       uint    miimcom;        /* MII Management: Command */
+       uint    miimadd;        /* MII Management: Address */
+       uint    miimcon;        /* MII Management: Control */
+       uint    miimstat;       /* MII Management: Status */
+       uint    miimind;        /* MII Management: Indicators */
+
+       uint    res538;
+
+       uint    ifstat;         /* Interface Status */
+       uint    macstnaddr1;    /* Station Address, part 1 */
+       uint    macstnaddr2;    /* Station Address, part 2 */
+       uint    res548[46];
+
+       /* (0x2_n600) */
+       uint    res600[32];
+
+       /* RMON MIB Registers (0x2_n680-0x2_n73c) */
+       rmon_mib_t      rmon;
+       uint    res740[48];
+
+       /* Hash Function Registers (0x2_n800) */
+       tsec_hash_t     hash;
+
+       uint        res900[128];
+
+       /* Pattern Registers (0x2_nb00) */
+       uint        resb00[62];
+       uint        attr;          /* Default Attribute Register */
+       uint        attreli;       /* Default Attribute Extract Length and Index */
+
+       /* TSEC Future Expansion Space (0x2_nc00-0x2_nffc) */
+       uint    resc00[256];
+} tsec_t;
+
+#define TSEC_GIGABIT (1)
+
+/* This flag currently only has
+ * meaning if we're using the eTSEC */
+#define TSEC_REDUCED (1 << 1)
+
+struct tsec_private {
+       volatile tsec_t *regs;
+       volatile tsec_t *phyregs;
+       struct phy_info *phyinfo;
+       uint phyaddr;
+       u32 flags;
+       uint link;
+       uint duplexity;
+       uint speed;
+};
+
+
+/*
+ * struct phy_cmd:  A command for reading or writing a PHY register
+ *
+ * mii_reg:  The register to read or write
+ *
+ * mii_data:  For writes, the value to put in the register.
+ *     A value of -1 indicates this is a read.
+ *
+ * funct: A function pointer which is invoked for each command.
+ *     For reads, this function will be passed the value read
+ *     from the PHY, and process it.
+ *     For writes, the result of this function will be written
+ *     to the PHY register
+ */
+struct phy_cmd {
+    uint mii_reg;
+    uint mii_data;
+    uint (*funct) (uint mii_reg, struct tsec_private* priv);
+};
+
+/* struct phy_info: a structure which defines attributes for a PHY
+ *
+ * id will contain a number which represents the PHY.  During
+ * startup, the driver will poll the PHY to find out what its
+ * UID--as defined by registers 2 and 3--is.  The 32-bit result
+ * gotten from the PHY will be shifted right by "shift" bits to
+ * discard any bits which may change based on revision numbers
+ * unimportant to functionality
+ *
+ * The struct phy_cmd entries represent pointers to an arrays of
+ * commands which tell the driver what to do to the PHY.
+ */
+struct phy_info {
+    uint id;
+    char *name;
+    uint shift;
+    /* Called to configure the PHY, and modify the controller
+     * based on the results */
+    struct phy_cmd *config;
+
+    /* Called when starting up the controller */
+    struct phy_cmd *startup;
+
+    /* Called when bringing down the controller */
+    struct phy_cmd *shutdown;
+};
+
+#endif /* __TSEC_H */