[U-Boot-Users] Patch: MPC8220 FEC and DMA update - part 1

TsiChung Liew Tsi-Chung.Liew at freescale.com
Tue May 15 01:23:29 CEST 2007


- Better handling in ethernet MII, applied new DMA functions
 
Regards,
TsiChung Liew
 
Signed-off by: TsiChung Liew Tsi-Chung.Liew at freescale.com

diff -rupN u-boot-all.git/cpu/mpc8220/cpu_init.c u-boot-all-8220-
fec/cpu/mpc8220/cpu_init.c
--- u-boot-all.git/cpu/mpc8220/cpu_init.c 2007-04-03 19:18:56.000000000
-0500
+++ u-boot-all-8220-fec/cpu/mpc8220/cpu_init.c 2007-05-10
16:51:31.000000000 -0500
@@ -23,6 +23,7 @@

#include <common.h>
#include <mpc8220.h>
+#include "MCD_dma.h"

DECLARE_GLOBAL_DATA_PTR;

@@ -129,8 +130,8 @@ int cpu_init_r (void)
*(vu_long *) 0xf0000710 |= 0x00000001;

#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_MPC8220_FEC)
- /* load FEC microcode */
- loadtask (0, 2);
+ MCD_initDma((dmaRegs *) (MMAP_DMA), (void *)(MMAP_SRAM + 512),
+     MCD_RELOC_TASKS);
#endif
return (0);
}
diff -rupN u-boot-all.git/cpu/mpc8220/dma.h u-boot-all-8220-
fec/cpu/mpc8220/dma.h
--- u-boot-all.git/cpu/mpc8220/dma.h 2007-04-03 19:18:56.000000000 -0500
+++ u-boot-all-8220-fec/cpu/mpc8220/dma.h 2007-05-10 16:51:42.000000000
-0500
@@ -23,21 +23,8 @@
  *---------------------------------------------------------------------
  */

-/* Layout of Ethernet controller Parameter SRAM area:
- * ----------------------------------------------------------------
- * 0x00: TBD_BASE, base address of TX BD ring
- * 0x04: TBD_NEXT, address of next TX BD to be processed
- * 0x08: RBD_BASE, base address of RX BD ring
- * 0x0C: RBD_NEXT, address of next RX BD to be processed
- * ---------------------------------------------------------------
- * ALL PARAMETERS ARE ALL LONGWORDS (FOUR BYTES EACH).
- */
-
-/* base address of SRAM area to store parameters used by Ethernet tasks
*/
-#define FEC_PARAM_BASE  (MMAP_SRAM + 0x5b00)
-
/* base address of SRAM area for buffer descriptors */
-#define FEC_BD_BASE     (MMAP_SRAM + 0x5b20)
+#define FEC1_BD_BASE     (MMAP_SRAM + 0x2200)

/*---------------------------------------------------------------------
  * common shortcuts  used  by driver C code
diff -rupN u-boot-all.git/cpu/mpc8220/fec.c u-boot-all-8220-
fec/cpu/mpc8220/fec.c
--- u-boot-all.git/cpu/mpc8220/fec.c 2007-04-03 19:18:56.000000000 -0500
+++ u-boot-all-8220-fec/cpu/mpc8220/fec.c 2007-05-10 16:52:47.000000000
-0500
@@ -12,41 +12,173 @@
#include <net.h>
#include <miiphy.h>
#include "dma.h"
+#include "MCD_dma.h"
#include "fec.h"

-#undef  DEBUG
#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
     defined(CONFIG_MPC8220_FEC)

+DECLARE_GLOBAL_DATA_PTR;
+
#if !(defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII))
#error "CONFIG_MII has to be defined!"
#endif

-#ifdef DEBUG
-static void tfifo_print (char *devname, mpc8220_fec_priv * fec);
-static void rfifo_print (char *devname, mpc8220_fec_priv * fec);
-#endif /* DEBUG */
-
-#ifdef DEBUG
-static u32 local_crc32 (char *string, unsigned int crc_value, int len);
+/* dma related defines */
+#define FEC1_RX_TASK        0
+#define FEC1_TX_TASK        1
+#define FEC1_RX_PRIORITY    6
+#define FEC1_TX_PRIORITY    7
+#define FEC1_RX_INIT        16
+#define FEC1_TX_INIT        17
+
+#define FEC2_RX_TASK        2
+#define FEC2_TX_TASK        3
+#define FEC2_RX_PRIORITY    6
+#define FEC2_TX_PRIORITY    7
+#define FEC2_RX_INIT        30
+#define FEC2_TX_INIT        31
+
+#define FEC1_TBD_BASE FEC1_BD_BASE
+#define FEC1_RBD_BASE FEC1_BD_BASE + (FEC_TBD_NUM * sizeof(FEC_BD))
+#define FEC2_TBD_BASE FEC1_RBD_BASE + (FEC_RBD_NUM * sizeof(FEC_BD))
+#define FEC2_RBD_BASE FEC2_TBD_BASE + (FEC_TBD_NUM * sizeof(FEC_BD))
+
+#define PKT_MAXBUF_SIZE 1518
+#define TOUT_LOOP 8000
+#define FIFO_ERRSTAT (FIFO_STAT_RXW | FIFO_STAT_UF | FIFO_STAT_OF)
+
+#undef ET_DEBUG
+
+mpc8220_fec_priv fec_info[] = {
+ {
+ MMAP_FEC1, /* io base */
+ 0, /* num */
+ FEC1_RX_TASK, /* rxTask */
+ FEC1_TX_TASK, /* txTask */
+ FEC1_RX_PRIORITY, /* rxPri */
+ FEC1_TX_PRIORITY, /* txPri */
+ FEC1_RX_INIT, /* rxInit */
+ FEC1_TX_INIT, /* txInit */
+ MII10, /* xcv_type */
+#ifdef CFG_DISCOVER_PHY
+ -1, /* phy_addr */
+#else
+ CONFIG_PHY_ADDR,
#endif
-
-typedef struct {
- u8 data[1500]; /* actual data */
- int length; /* actual length */
- int used; /* buffer in use or not */
- u8 head[16]; /* MAC header(6 + 6 + 2) + 2(aligned) */
-} NBUF;
+ 0, /* phy_dupspd */
+ 0, /* phy_name */
+ 0, /* phyname init */
+ (FEC_BD *) FEC1_RBD_BASE, /* rbdBase */
+ (FEC_BD *) FEC1_TBD_BASE, /* tbdBase */
+ 0, /* rbdIndex */
+ 0, /* tbdIndex */
+ 0, /* usedTbdIndex */
+ 0, /* cleanTbdNum */
+ }
+ ,
+#ifdef CONFIG_HAS_ETH1
+ {
+ MMAP_FEC2, /* io base */
+ 1, /* num */
+ FEC2_RX_TASK, /* rxTask */
+ FEC2_TX_TASK, /* txTask */
+ FEC2_RX_PRIORITY, /* rxPri */
+ FEC2_TX_PRIORITY, /* txPri */
+ FEC2_RX_INIT, /* rxInit */
+ FEC2_TX_INIT, /* txInit */
+ MII10, /* xcv_type */
+#ifdef CFG_DISCOVER_PHY
+ -1, /* phy_addr */
+#else
+ CONFIG_PHY1_ADDR,
+#endif
+ 0, /* phy_dupspd */
+ 0, /* phy_name */
+ 0, /* phyname init */
+ (FEC_BD *) FEC2_RBD_BASE, /* rbdBase */
+ (FEC_BD *) FEC2_TBD_BASE, /* tbdBase */
+ 0, /* rbdIndex */
+ 0, /* tbdIndex */
+ 0, /* usedTbdIndex */
+ 0, /* cleanTbdNum */
+ }
+#endif
+};
+
+int mpc8220_fec_rbd_init(mpc8220_fec_priv * fec);
+void mpc8220_fec_tbd_init(mpc8220_fec_priv * fec);
+void mpc8220_fec_rbd_clean(mpc8220_fec_priv * fec, FEC_BD * pRbd);
+void mpc8220_fec_rbd_clean(mpc8220_fec_priv * fec, FEC_BD * pRbd);
+void mpc8220_fec_tbd_scrub(mpc8220_fec_priv * fec);
+void mpc8220_fec_set_hwaddr(mpc8220_fec_priv * fec, char *mac);
+void mpc8220_fec_set_hwaddr(mpc8220_fec_priv * fec, char *mac);
+void mpc8220_fec_halt(struct eth_device *dev);
+int mpc8220_fec_init(struct eth_device *dev, bd_t * bis);
+int mpc8220_fec_send(struct eth_device *dev, volatile void *eth_data,
+      int data_length);
+int mpc8220_fec_recv(struct eth_device *dev);
+int mpc8220_fec_initialize(bd_t * bis);
+void setFecDuplexSpeed(mpc8220_fec_priv * fec);
+void mii_discover_phy(struct eth_device *dev);
+int check_connection(struct eth_device *dev);

int fec8220_miiphy_read (char *devname, u8 phyAddr, u8 regAddr, u16 *
retVal);
int fec8220_miiphy_write (char *devname, u8 phyAddr, u8 regAddr, u16
data);

/********************************************************************/
-#ifdef DEBUG
-static void mpc8220_fec_phydump (char *devname)
+#ifdef ET_DEBUG
+static void tfifo_print(char *devname, mpc8220_fec_priv * fec)
+{
+ volatile ethernet_regs *eth = (volatile ethernet_regs *)fec->iobase;
+ u16 phyStatus;
+
+ if ((eth->tfifo_lrf_ptr != eth->tfifo_lwf_ptr)
+     || (eth->tfifo_rdptr != eth->tfifo_wrptr)) {
+
+ miiphy_read(devname, fec->phy_addr, PHY_BMSR, &phyStatus);
+ printf("\nphyStatus: 0x%04x\n", phyStatus);
+ printf("ecntrl:   0x%08x\n", eth->ecntrl);
+ printf("ievent:   0x%08x\n", eth->ievent);
+ printf("x_status: 0x%08x\n", eth->x_status);
+ printf("tfifo: status 0x%08x\n", eth->tfifo_status);
+
+ printf(" control 0x%08x\n", eth->tfifo_cntrl);
+ printf(" lrfp 0x%08x\n", eth->tfifo_lrf_ptr);
+ printf(" lwfp 0x%08x\n", eth->tfifo_lwf_ptr);
+ printf(" alarm 0x%08x\n", eth->tfifo_alarm);
+ printf(" readptr 0x%08x\n", eth->tfifo_rdptr);
+ printf(" writptr 0x%08x\n", eth->tfifo_wrptr);
+ }
+}
+
+static void rfifo_print(char *devname, mpc8220_fec_priv * fec)
+{
+ volatile ethernet_regs *eth = (volatile ethernet_regs *)fec->iobase;
+ u16 phyStatus;
+
+ if ((eth->rfifo_lrf_ptr != eth->rfifo_lwf_ptr)
+     || (eth->rfifo_rdptr != eth->rfifo_wrptr)) {
+
+ miiphy_read(devname, fec->phy_addr, PHY_BMSR, &phyStatus);
+ printf("\nphyStatus: 0x%04x\n", phyStatus);
+ printf("ecntrl:   0x%08x\n", eth->ecntrl);
+ printf("ievent:   0x%08x\n", eth->ievent);
+ printf("x_status: 0x%08x\n", eth->x_status);
+ printf("rfifo: status 0x%08x\n", eth->rfifo_status);
+
+ printf(" control 0x%08x\n", eth->rfifo_cntrl);
+ printf(" lrfp 0x%08x\n", eth->rfifo_lrf_ptr);
+ printf(" lwfp 0x%08x\n", eth->rfifo_lwf_ptr);
+ printf(" alarm 0x%08x\n", eth->rfifo_alarm);
+ printf(" readptr 0x%08x\n", eth->rfifo_rdptr);
+ printf(" writptr 0x%08x\n", eth->rfifo_wrptr);
+ }
+}
+
+static void mpc8220_fec_phydump(char *devname, mpc8220_fec_priv * fec)
{
u16 phyStatus, i;
- u8 phyAddr = CONFIG_PHY_ADDR;
u8 reg_mask[] = {
#if CONFIG_PHY_TYPE == 0x79c874 /* AMD Am79C874 */
/* regs to print: 0...7, 16...19, 21, 23, 24 */
@@ -61,7 +193,7 @@ static void mpc8220_fec_phydump (char *d

for (i = 0; i < 32; i++) {
if (reg_mask[i]) {
- miiphy_read (devname, phyAddr, i, &phyStatus);
+ miiphy_read(devname, fec->phy_addr, i, &phyStatus);
printf ("Mii reg %d: 0x%04x\n", i, phyStatus);
}
}
@@ -69,7 +201,7 @@ static void mpc8220_fec_phydump (char *d
#endif

/********************************************************************/
-static int mpc8220_fec_rbd_init (mpc8220_fec_priv * fec)
+int mpc8220_fec_rbd_init(mpc8220_fec_priv * fec)
{
int ix;
char *data;
@@ -85,7 +217,7 @@ static int mpc8220_fec_rbd_init (mpc8220
fec->rbdBase[ix].dataPointer = (u32) data;
}
fec->rbdBase[ix].status = FEC_RBD_EMPTY;
- fec->rbdBase[ix].dataLength = 0;
+ fec->rbdBase[ix].dataLength = FEC_MAX_PKT_SIZE;
}
once++;

@@ -99,7 +231,7 @@ static int mpc8220_fec_rbd_init (mpc8220
}

/********************************************************************/
-static void mpc8220_fec_tbd_init (mpc8220_fec_priv * fec)
+void mpc8220_fec_tbd_init(mpc8220_fec_priv * fec)
{
int ix;

@@ -121,7 +253,7 @@ static void mpc8220_fec_tbd_init (mpc822
}

/********************************************************************/
-static void mpc8220_fec_rbd_clean (mpc8220_fec_priv * fec, FEC_RBD *
pRbd)
+void mpc8220_fec_rbd_clean(mpc8220_fec_priv * fec, FEC_BD * pRbd)
{
/*
* Reset buffer descriptor as empty
@@ -131,12 +263,12 @@ static void mpc8220_fec_rbd_clean (mpc82
else
pRbd->status = FEC_RBD_EMPTY;

- pRbd->dataLength = 0;
+ pRbd->dataLength = FEC_MAX_PKT_SIZE;

/*
- * Now, we have an empty RxBD, restart the SmartDMA receive task
+ * Now, we have an empty RxBD, restart the DMA receive task
*/
- DMA_TASK_ENABLE (FEC_RECV_TASK_NO);
+ MCD_continDma(fec->rxTask);

/*
* Increment BD count
@@ -145,11 +277,11 @@ static void mpc8220_fec_rbd_clean (mpc82
}

/********************************************************************/
-static void mpc8220_fec_tbd_scrub (mpc8220_fec_priv * fec)
+void mpc8220_fec_tbd_scrub(mpc8220_fec_priv * fec)
{
- FEC_TBD *pUsedTbd;
+ FEC_BD *pUsedTbd;

-#ifdef DEBUG
+#ifdef ET_DEBUG
printf ("tbd_scrub: fec->cleanTbdNum = %d, fec->usedTbdIndex = %d\n",
fec->cleanTbdNum, fec->usedTbdIndex);
#endif
@@ -160,7 +292,7 @@ static void mpc8220_fec_tbd_scrub (mpc82
while (fec->cleanTbdNum < FEC_TBD_NUM) {
pUsedTbd = &fec->tbdBase[fec->usedTbdIndex];
if (pUsedTbd->status & FEC_TBD_READY) {
-#ifdef DEBUG
+#ifdef ET_DEBUG
printf ("Cannot clean TBD %d, in use\n",
fec->cleanTbdNum);
#endif
@@ -184,13 +316,13 @@ static void mpc8220_fec_tbd_scrub (mpc82
}

/********************************************************************/
-static void mpc8220_fec_set_hwaddr (mpc8220_fec_priv * fec, char *mac)
+void mpc8220_fec_set_hwaddr(mpc8220_fec_priv * fec, char *mac)
{
+ volatile ethernet_regs *eth = (volatile ethernet_regs *)fec->iobase;
u8 currByte; /* byte for which to compute the CRC */
int byte; /* loop - counter */
int bit; /* loop - counter */
u32 crc = 0xffffffff; /* initial value */
-
/*
* The algorithm used is the following:
* we loop on each of the six bytes of the provided address,
@@ -225,32 +357,32 @@ static void mpc8220_fec_set_hwaddr (mpc8
* Set individual hash table register
*/
if (crc >= 32) {
- fec->eth->iaddr1 = (1 << (crc - 32));
- fec->eth->iaddr2 = 0;
+ eth->iaddr1 = (1 << (crc - 32));
+ eth->iaddr2 = 0;
} else {
- fec->eth->iaddr1 = 0;
- fec->eth->iaddr2 = (1 << crc);
+ eth->iaddr1 = 0;
+ eth->iaddr2 = (1 << crc);
}

/*
* Set physical address
*/
- fec->eth->paddr1 =
- (mac[0] << 24) + (mac[1] << 16) + (mac[2] << 8) + mac[3];
- fec->eth->paddr2 = (mac[4] << 24) + (mac[5] << 16) + 0x8808;
+ eth->paddr1 = (mac[0] << 24) + (mac[1] << 16) + (mac[2] << 8) + mac
[3];
+ eth->paddr2 = (mac[4] << 24) + (mac[5] << 16) + 0x8808;
}

/********************************************************************/
-static int mpc8220_fec_init (struct eth_device *dev, bd_t * bis)
+int mpc8220_fec_init(struct eth_device *dev, bd_t * bis)
{
mpc8220_fec_priv *fec = (mpc8220_fec_priv *) dev->priv;
- struct mpc8220_dma *dma = (struct mpc8220_dma *) MMAP_DMA;
- const u8 phyAddr = CONFIG_PHY_ADDR; /* Only one PHY */
+ volatile ethernet_regs *eth = (volatile ethernet_regs *)fec->iobase;

-#ifdef DEBUG
+#ifdef ET_DEBUG
printf ("mpc8220_fec_init... Begin\n");
#endif

+ mpc8220_fec_halt(dev);
+
/*
* Initialize RxBD/TxBD rings
*/
@@ -258,59 +390,88 @@ static int mpc8220_fec_init (struct eth_
mpc8220_fec_tbd_init (fec);

/*
- * Set up Pin Muxing for FEC 1
+ * Set up Pin Muxing for FEC
*/
+ if (fec->num == 0) {
+ /* pin mux for fec 1 */
*(vu_long *) MMAP_PCFG = 0;
- *(vu_long *) (MMAP_PCFG + 4) = 0;
+ *(vu_long *) (MMAP_PCFG + 4) &= 0x7fffffff;
+ } else if (fec->num == 1) {
+ /* pin mux for fec 2 */
+ *(vu_long *) (MMAP_PCFG + 8) &= 0x00000013;
+ *(vu_long *) (MMAP_PCFG + 0xc) &= 0xffffffdf;
+ }
+
/*
* Clear FEC-Lite interrupt event register(IEVENT)
*/
- fec->eth->ievent = 0xffffffff;
+ eth->ievent = FEC_EIR_CLEAR_ALL;

/*
* Set interrupt mask register
*/
- fec->eth->imask = 0x00000000;
+ eth->imask = 0;

/*
- * Set FEC-Lite receive control register(R_CNTRL):
+ * Set individual address filter for unicast address
+ * and set physical address registers.
*/
- if (fec->xcv_type == SEVENWIRE) {
- /*
- * Frame length=1518; 7-wire mode
- */
- fec->eth->r_cntrl = 0x05ee0020; /*0x05ee0000;FIXME */
- } else {
+ mpc8220_fec_set_hwaddr(fec, (char *)(dev->enetaddr));
+
/*
- * Frame length=1518; MII mode;
+ * Set multicast address filter
*/
- fec->eth->r_cntrl = 0x05ee0024; /*0x05ee0004;FIXME */
- }
+ eth->gaddr1 = 0;
+ eth->gaddr2 = 0;

- fec->eth->x_cntrl = 0x00000000; /* half-duplex, heartbeat disabled */
if (fec->xcv_type != SEVENWIRE) {
/*
* Set MII_SPEED = (1/(mii_speed * 2)) * System Clock
* and do not drop the Preamble.
*/
- /* tbd - rtm */
- /*fec->eth->mii_speed = (((gd->ipb_clk >> 20) / 5) << 1); */
/* No MII for 7-wire mode */
- fec->eth->mii_speed = 0x00000030;
+ eth->mii_speed =
+     FEC_MSCR_MII_SPEED((gd->bus_clk / 1000000) / 5);
+ }
+
+ if (fec->xcv_type != SEVENWIRE) {
+#ifdef CFG_DISCOVER_PHY
+ mii_discover_phy(dev);
+#endif
+ if (check_connection(dev) == 0) {
+ printf("check cable connection!\n");
+ return -1;
+ }
+
+ /* adapt to the half/full speed settings */
+ fec->phy_dupspd = miiphy_duplex(dev->name, fec->phy_addr) << 16;
+ fec->phy_dupspd |= miiphy_speed(dev->name, fec->phy_addr);
+
+ switch (fec->phy_dupspd & 0xffff) {
+ case 10:
+ fec->xcv_type = MII10;
+ break;
+ case 100:
+ fec->xcv_type = MII100;
+ break;
+ }
}

+ setFecDuplexSpeed(fec);
+
/*
* Set Opcode/Pause Duration Register
*/
- fec->eth->op_pause = 0x00010020; /*FIXME0xffff0020; */
+ eth->op_pause = 0x00010020; /*FIXME0xffff0020; */

/*
* Set Rx FIFO alarm and granularity value
*/
- fec->eth->rfifo_cntrl = 0x0c000000;
- fec->eth->rfifo_alarm = 0x0000030c;
-#ifdef DEBUG
- if (fec->eth->rfifo_status & 0x00700000) {
+ eth->rfifo_cntrl = 0x0c000000;
+ eth->rfifo_alarm = 0x0000030c;
+
+#ifdef ET_DEBUG
+ if (eth->rfifo_status & FIFO_ERRSTAT) {
printf ("mpc8220_fec_init() RFIFO error\n");
}
#endif
@@ -318,197 +479,63 @@ static int mpc8220_fec_init (struct eth_
/*
* Set Tx FIFO granularity value
*/
- /*fec->eth->tfifo_cntrl = 0x0c000000; */ /*tbd - rtm */
- fec->eth->tfifo_cntrl = 0x0e000000;
-#ifdef DEBUG
- printf ("tfifo_status: 0x%08x\n", fec->eth->tfifo_status);
- printf ("tfifo_alarm: 0x%08x\n", fec->eth->tfifo_alarm);
+ eth->tfifo_cntrl = FIFO_CTRL_FRAME | FIFO_CTRL_GR(6) | 0x00040000;
+
+#ifdef ET_DEBUG
+ printf("tfifo_status: 0x%08x\n", eth->tfifo_status);
+ printf("tfifo_alarm: 0x%08x\n", eth->tfifo_alarm);
#endif

/*
* Set transmit fifo watermark register(X_WMRK), default = 64
*/
- fec->eth->tfifo_alarm = 0x00000080;
- fec->eth->x_wmrk = 0x2;
-
- /*
- * Set individual address filter for unicast address
- * and set physical address registers.
- */
- mpc8220_fec_set_hwaddr (fec, (char *)(dev->enetaddr));
-
- /*
- * Set multicast address filter
- */
- fec->eth->gaddr1 = 0x00000000;
- fec->eth->gaddr2 = 0x00000000;
+ eth->tfifo_alarm = 0x00000080;
+ eth->x_wmrk = 0x2;

/*
* Turn ON cheater FSM: ????
*/
- fec->eth->xmit_fsm = 0x03000000;
-
-#if 1
-/*#if defined(CONFIG_MPC5200)*/
- /*
- * Turn off COMM bus prefetch in the MGT5200 BestComm. It doesn't
- * work w/ the current receive task.
- */
- dma->PtdCntrl |= 0x00000001;
-#endif
+ eth->xmit_fsm = 0x03000000;

- /*
- * Set priority of different initiators
- */
- dma->IPR0 = 7; /* always */
- dma->IPR3 = 6; /* Eth RX */
- dma->IPR4 = 5; /* Eth Tx */
-
- /*
- * Clear SmartDMA task interrupt pending bits
- */
- DMA_CLEAR_IEVENT (FEC_RECV_TASK_NO);
-
- /*
- * Initialize SmartDMA parameters stored in SRAM
- */
- *(int *) FEC_TBD_BASE = (int) fec->tbdBase;
- *(int *) FEC_RBD_BASE = (int) fec->rbdBase;
- *(int *) FEC_TBD_NEXT = (int) fec->tbdBase;
- *(int *) FEC_RBD_NEXT = (int) fec->rbdBase;
-
- if (fec->xcv_type != SEVENWIRE) {
- /*
- * Initialize PHY(LXT971A):
- *
- *   Generally, on power up, the LXT971A reads its configuration
- *   pins to check for forced operation, If not cofigured for
- *   forced operation, it uses auto-negotiation/parallel detection
- *   to automatically determine line operating conditions.
- *   If the PHY device on the other side of the link supports
- *   auto-negotiation, the LXT971A auto-negotiates with it
- *   using Fast Link Pulse(FLP) Bursts. If the PHY partner does not
- *   support auto-negotiation, the LXT971A automatically detects
- *   the presence of either link pulses(10Mbps PHY) or Idle
- *   symbols(100Mbps) and sets its operating conditions accordingly.
- *
- *   When auto-negotiation is controlled by software, the following
- *   steps are recommended.
- *
- * Note:
- *   The physical address is dependent on hardware configuration.
- *
- */
- int timeout = 1;
- u16 phyStatus;
-
- /*
- * Reset PHY, then delay 300ns
- */
- miiphy_write (dev->name, phyAddr, 0x0, 0x8000);
- udelay (1000);
-
- if (fec->xcv_type == MII10) {
- /*
- * Force 10Base-T, FDX operation
- */
-#ifdef DEBUG
- printf ("Forcing 10 Mbps ethernet link... ");
-#endif
- miiphy_read (dev->name, phyAddr, 0x1, &phyStatus);
- /*
-    miiphy_write(fec, phyAddr, 0x0, 0x0100);
- */
- miiphy_write (dev->name, phyAddr, 0x0, 0x0180);
-
- timeout = 20;
- do { /* wait for link status to go down */
- udelay (10000);
- if ((timeout--) == 0) {
-#ifdef DEBUG
- printf ("hmmm, should not have waited...");
-#endif
- break;
- }
- miiphy_read (dev->name, phyAddr, 0x1, &phyStatus);
-#ifdef DEBUG
- printf ("=");
-#endif
- } while ((phyStatus & 0x0004)); /* !link up */
-
- timeout = 1000;
- do { /* wait for link status to come back up */
- udelay (10000);
- if ((timeout--) == 0) {
- printf ("failed. Link is down.\n");
- break;
- }
- miiphy_read (dev->name, phyAddr, 0x1, &phyStatus);
-#ifdef DEBUG
- printf ("+");
-#endif
- } while (!(phyStatus & 0x0004)); /* !link up */
-
-#ifdef DEBUG
- printf ("done.\n");
-#endif
- } else { /* MII100 */
- /*
- * Set the auto-negotiation advertisement register bits
- */
- miiphy_write (dev->name, phyAddr, 0x4, 0x01e1);
-
- /*
- * Set MDIO bit 0.12 = 1(&& bit 0.9=1?) to enable auto-negotiation
- */
- miiphy_write (dev->name, phyAddr, 0x0, 0x1200);
-
- /*
- * Wait for AN completion
- */
- timeout = 5000;
- do {
- udelay (1000);
-
- if ((timeout--) == 0) {
-#ifdef DEBUG
- printf ("PHY auto neg 0 failed...\n");
-#endif
- return -1;
- }
-
- if (miiphy_read (dev->name, phyAddr, 0x1, &phyStatus) !=
-     0) {
-#ifdef DEBUG
- printf ("PHY auto neg 1 failed 0x%04x...\n", phyStatus);
+#ifdef ET_DEBUG
+ if (fec->xcv_type != SEVENWIRE)
+ mpc8220_fec_phydump(dev->name, fec);
#endif
- return -1;
- }
- } while (!(phyStatus & 0x0004));

-#ifdef DEBUG
- printf ("PHY auto neg complete! \n");
-#endif
- }
-
- }
+ /* Enable DMA receive task */
+ MCD_startDma(fec->rxTask, /* Dma channel */
+      (u8 *) fec->rbdBase, /*Source Address */
+      0, /* Source increment */
+      (u8 *) (&eth->rfifo_data), /* dest */
+      4, /* dest increment */
+      0, /* DMA size */
+      4, /* xfer size */
+      fec->rxInit, /* initiator */
+      fec->rxPri, /* priority */
+      (MCD_FECRX_DMA | MCD_TT_FLAGS_DEF), /* Flags */
+      (MCD_NO_CSUM | MCD_NO_BYTE_SWAP) /* Function description */
+     );
+
+ /* Enable DMA tx task with no ready buffer descriptors */
+ MCD_startDma(fec->txTask, /* Dma channel */
+      (u8 *) fec->tbdBase, /*Source Address */
+      0, /* Source increment */
+      (u8 *) (&eth->tfifo_data), /* dest */
+      4, /* dest incr */
+      0, /* DMA size */
+      4, /* xfer size */
+      fec->txInit, /* initiator */
+      fec->txPri, /* priority */
+      (MCD_FECTX_DMA | MCD_TT_FLAGS_DEF), /* Flags */
+      (MCD_NO_CSUM | MCD_NO_BYTE_SWAP) /* Function description */
+     );

/*
* Enable FEC-Lite controller
*/
- fec->eth->ecntrl |= 0x00000006;
-
-#ifdef DEBUG
- if (fec->xcv_type != SEVENWIRE)
- mpc8220_fec_phydump (dev->name);
-#endif
-
- /*
- * Enable SmartDMA receive task
- */
- DMA_TASK_ENABLE (FEC_RECV_TASK_NO);
+ eth->ecntrl |= FEC_ECR_ETHER_EN;

-#ifdef DEBUG
+#ifdef ET_DEBUG
printf ("mpc8220_fec_init... Done \n");
#endif

@@ -516,120 +543,71 @@ static int mpc8220_fec_init (struct eth_
}

/********************************************************************/
-static void mpc8220_fec_halt (struct eth_device *dev)
+void mpc8220_fec_halt(struct eth_device *dev)
{
mpc8220_fec_priv *fec = (mpc8220_fec_priv *) dev->priv;
+ volatile ethernet_regs *eth = (volatile ethernet_regs *)fec->iobase;
int counter = 0xffff;

-#ifdef DEBUG
+#ifdef ET_DEBUG
+ printf("mpc8220_fec_halt...\n");
+
if (fec->xcv_type != SEVENWIRE)
- mpc8220_fec_phydump (dev->name);
+ mpc8220_fec_phydump(dev->name, fec);
#endif

/*
- * mask FEC chip interrupts
- */
- fec->eth->imask = 0;
-
- /*
* issue graceful stop command to the FEC transmitter if necessary
*/
- fec->eth->x_cntrl |= 0x00000001;
+ eth->x_cntrl |= FEC_TCR_GTS;

/*
* wait for graceful stop to register
*/
- while ((counter--) && (!(fec->eth->ievent & 0x10000000)));
+ while ((counter--) && (!(eth->ievent & FEC_EIR_GRA))) ;

/*
- * Disable SmartDMA tasks
+ * Disable DMA tasks
*/
- DMA_TASK_DISABLE (FEC_XMIT_TASK_NO);
- DMA_TASK_DISABLE (FEC_RECV_TASK_NO);
+ MCD_killDma(fec->txTask);
+ MCD_killDma(fec->rxTask);;

/*
* Disable the Ethernet Controller
*/
- fec->eth->ecntrl &= 0xfffffffd;
+ eth->ecntrl &= ~FEC_ECR_ETHER_EN;

/*
* Clear FIFO status registers
*/
- fec->eth->rfifo_status &= 0x00700000;
- fec->eth->tfifo_status &= 0x00700000;
+ eth->rfifo_status &= FIFO_ERRSTAT;
+ eth->tfifo_status &= FIFO_ERRSTAT;

- fec->eth->reset_cntrl = 0x01000000;
+ eth->reset_cntrl = 0x01000000;
+
+ /* reset phy */
+ if (fec->xcv_type != SEVENWIRE) {
+ miiphy_read(dev->name, fec->phy_addr, PHY_BMCR, PHY_BMCR_RESET);
+ udelay(10000);
+ }

/*
* Issue a reset command to the FEC chip
*/
- fec->eth->ecntrl |= 0x1;
+ eth->ecntrl |= FEC_ECR_RESET;

/*
- * wait at least 16 clock cycles
+ * wait at least 20 clock cycles
*/
- udelay (10);
+ udelay(20);

-#ifdef DEBUG
+#ifdef ET_DEBUG
printf ("Ethernet task stopped\n");
#endif
}

-#ifdef DEBUG
/********************************************************************/
-
-static void tfifo_print (char *devname, mpc8220_fec_priv * fec)
-{
- u16 phyAddr = CONFIG_PHY_ADDR;
- u16 phyStatus;
-
- if ((fec->eth->tfifo_lrf_ptr != fec->eth->tfifo_lwf_ptr)
-     || (fec->eth->tfifo_rdptr != fec->eth->tfifo_wrptr)) {
-
- miiphy_read (devname, phyAddr, 0x1, &phyStatus);
- printf ("\nphyStatus: 0x%04x\n", phyStatus);
- printf ("ecntrl:   0x%08x\n", fec->eth->ecntrl);
- printf ("ievent:   0x%08x\n", fec->eth->ievent);
- printf ("x_status: 0x%08x\n", fec->eth->x_status);
- printf ("tfifo: status 0x%08x\n", fec->eth->tfifo_status);
-
- printf (" control 0x%08x\n", fec->eth->tfifo_cntrl);
- printf (" lrfp 0x%08x\n", fec->eth->tfifo_lrf_ptr);
- printf (" lwfp 0x%08x\n", fec->eth->tfifo_lwf_ptr);
- printf (" alarm 0x%08x\n", fec->eth->tfifo_alarm);
- printf (" readptr 0x%08x\n", fec->eth->tfifo_rdptr);
- printf (" writptr 0x%08x\n", fec->eth->tfifo_wrptr);
- }
-}
-
-static void rfifo_print (char *devname, mpc8220_fec_priv * fec)
-{
- u16 phyAddr = CONFIG_PHY_ADDR;
- u16 phyStatus;
-
- if ((fec->eth->rfifo_lrf_ptr != fec->eth->rfifo_lwf_ptr)
-     || (fec->eth->rfifo_rdptr != fec->eth->rfifo_wrptr)) {
-
- miiphy_read (devname, phyAddr, 0x1, &phyStatus);
- printf ("\nphyStatus: 0x%04x\n", phyStatus);
- printf ("ecntrl:   0x%08x\n", fec->eth->ecntrl);
- printf ("ievent:   0x%08x\n", fec->eth->ievent);
- printf ("x_status: 0x%08x\n", fec->eth->x_status);
- printf ("rfifo: status 0x%08x\n", fec->eth->rfifo_status);
-
- printf (" control 0x%08x\n", fec->eth->rfifo_cntrl);
- printf (" lrfp 0x%08x\n", fec->eth->rfifo_lrf_ptr);
- printf (" lwfp 0x%08x\n", fec->eth->rfifo_lwf_ptr);
- printf (" alarm 0x%08x\n", fec->eth->rfifo_alarm);
- printf (" readptr 0x%08x\n", fec->eth->rfifo_rdptr);
- printf (" writptr 0x%08x\n", fec->eth->rfifo_wrptr);
- }
-}
-#endif /* DEBUG */
-
-/********************************************************************/
-
-static int mpc8220_fec_send (struct eth_device *dev, volatile void
*eth_data,
+int mpc8220_fec_send(struct eth_device *dev, volatile void *eth_data,
     int data_length)
{
/*
@@ -637,13 +615,20 @@ static int mpc8220_fec_send (struct eth_
* 6-byte Ethernet addresses.
*/
mpc8220_fec_priv *fec = (mpc8220_fec_priv *) dev->priv;
- FEC_TBD *pTbd;
+ FEC_BD *pTbd;

-#ifdef DEBUG
+#ifdef ET_DEBUG
printf ("tbd status: 0x%04x\n", fec->tbdBase[0].status);
tfifo_print (dev->name, fec);
#endif

+ if (fec->xcv_type != SEVENWIRE) {
+ if (check_connection(dev) == 0) {
+ printf("check cable connection!\n");
+ return -1;
+ }
+ }
+
/*
* Clear Tx BD ring at first
*/
@@ -660,7 +645,7 @@ static int mpc8220_fec_send (struct eth_
* Check the number of vacant TxBDs.
*/
if (fec->cleanTbdNum < 1) {
-#ifdef DEBUG
+#ifdef ET_DEBUG
printf ("No available TxBDs ...\n");
#endif
return -1;
@@ -675,48 +660,35 @@ static int mpc8220_fec_send (struct eth_
pTbd->status |= FEC_TBD_LAST | FEC_TBD_TC | FEC_TBD_READY;
fec->tbdIndex = (fec->tbdIndex + 1) % FEC_TBD_NUM;

-#ifdef DEBUG
+#ifdef ET_DEBUG
printf ("DMA_TASK_ENABLE, fec->tbdIndex = %d \n", fec->tbdIndex);
#endif

/*
- * Kick the MII i/f
+ * Enable DMA transmit task
*/
- if (fec->xcv_type != SEVENWIRE) {
- u16 phyStatus;
-
- miiphy_read (dev->name, 0, 0x1, &phyStatus);
- }
-
- /*
- * Enable SmartDMA transmit task
- */
-
-#ifdef DEBUG
+#ifdef ET_DEBUG
tfifo_print (dev->name, fec);
#endif

- DMA_TASK_ENABLE (FEC_XMIT_TASK_NO);
+ MCD_continDma(fec->txTask);

-#ifdef DEBUG
+#ifdef ET_DEBUG
tfifo_print (dev->name, fec);
-#endif
-
-#ifdef DEBUG
printf ("+");
#endif

fec->cleanTbdNum -= 1;

-#ifdef DEBUG
- printf ("smartDMA ethernet Tx task enabled\n");
+#ifdef ET_DEBUG
+ printf("DMA ethernet Tx task enabled\n");
#endif
/*
* wait until frame is sent .
*/
while (pTbd->status & FEC_TBD_READY) {
udelay (10);
-#ifdef DEBUG
+#ifdef ET_DEBUG
printf ("TDB status = %04x\n", pTbd->status);
#endif
}
@@ -724,47 +696,56 @@ static int mpc8220_fec_send (struct eth_
return 0;
}

-
/********************************************************************/
-static int mpc8220_fec_recv (struct eth_device *dev)
+int mpc8220_fec_recv(struct eth_device *dev)
{
/*
* This command pulls one frame from the card
*/
mpc8220_fec_priv *fec = (mpc8220_fec_priv *) dev->priv;
- FEC_RBD *pRbd = &fec->rbdBase[fec->rbdIndex];
+ volatile ethernet_regs *eth = (volatile ethernet_regs *)fec->iobase;
+ FEC_BD *pRbd = &fec->rbdBase[fec->rbdIndex];
unsigned long ievent;
int frame_length, len = 0;
- NBUF *frame;

-#ifdef DEBUG
+#ifdef ET_DEBUG
printf ("mpc8220_fec_recv %d Start...\n", fec->rbdIndex);
printf ("-");
#endif

+ if (fec->xcv_type != SEVENWIRE) {
+ if (check_connection(dev) == 0) {
+ printf("check cable connection!\n");
+ return -1;
+ }
+ }
+
/*
* Check if any critical events have happened
*/
- ievent = fec->eth->ievent;
- fec->eth->ievent = ievent;
- if (ievent & 0x20060000) {
+ ievent = eth->ievent;
+ if (ievent != 0) {
+ eth->ievent = ievent;
+
+ if (ievent & (FEC_EIR_BABT | FEC_EIR_TXERR | FEC_EIR_RXERR)) {
/* BABT, Rx/Tx FIFO errors */
mpc8220_fec_halt (dev);
mpc8220_fec_init (dev, NULL);
return 0;
}
- if (ievent & 0x80000000) {
+ if (ievent & FEC_EIR_HBERR) {
/* Heartbeat error */
- fec->eth->x_cntrl |= 0x00000001;
+ eth->x_cntrl |= FEC_TCR_GTS;
}
- if (ievent & 0x10000000) {
+ if (ievent & FEC_EIR_GRA) {
/* Graceful stop complete */
- if (fec->eth->x_cntrl & 0x00000001) {
+ if (eth->x_cntrl & FEC_TCR_GTS) {
mpc8220_fec_halt (dev);
- fec->eth->x_cntrl &= ~0x00000001;
+ eth->x_cntrl &= ~FEC_TCR_GTS;
mpc8220_fec_init (dev, NULL);
}
}
+ }

if (!(pRbd->status & FEC_RBD_EMPTY)) {
if ((pRbd->status & FEC_RBD_LAST)
@@ -774,24 +755,11 @@ static int mpc8220_fec_recv (struct eth_
/*
* Get buffer address and size
*/
- frame = (NBUF *) pRbd->dataPointer;
frame_length = pRbd->dataLength - 4;

-#if (0)
- {
- int i;
-
- printf ("recv data hdr:");
- for (i = 0; i < 14; i++)
- printf ("%x ", *(frame->head + i));
- printf ("\n");
- }
-#endif
/*
*  Fill the buffer and pass it to upper layers
*/
-/* memcpy(buff, frame->head, 14);
- memcpy(buff + 14, frame->data, frame_length);*/
NetReceive ((volatile uchar *) pRbd->dataPointer,
    frame_length);
len = frame_length;
@@ -801,55 +769,41 @@ static int mpc8220_fec_recv (struct eth_
*/
mpc8220_fec_rbd_clean (fec, pRbd);
}
- DMA_CLEAR_IEVENT (FEC_RECV_TASK_NO);
+
return len;
}

-
/********************************************************************/
int mpc8220_fec_initialize (bd_t * bis)
{
- mpc8220_fec_priv *fec;
-
-#ifdef CONFIG_HAS_ETH1
- mpc8220_fec_priv *fec2;
-#endif
- struct eth_device *dev;
- char *tmp, *end;
+ char *tmp, *end, ethaddr[16];
char env_enetaddr[6];
-
-#ifdef CONFIG_HAS_ETH1
- char env_enet1addr[6];
-#endif
+ struct eth_device *dev;
int i;

- fec = (mpc8220_fec_priv *) malloc (sizeof (*fec));
+ for (i = 0; i < sizeof(fec_info) / sizeof(fec_info[0]); i++) {
+
+ fec_info[i].phy_name = (char *)malloc(32);
+
dev = (struct eth_device *) malloc (sizeof (*dev));
- memset (dev, 0, sizeof *dev);
+ if (dev == NULL)
+ return 0;

- fec->eth = (ethernet_regs *) MMAP_FEC1;
-#ifdef CONFIG_HAS_ETH1
- fec2 = (mpc8220_fec_priv *) malloc (sizeof (*fec));
- fec2->eth = (ethernet_regs *) MMAP_FEC2;
-#endif
- fec->tbdBase = (FEC_TBD *) FEC_BD_BASE;
- fec->rbdBase =
- (FEC_RBD *) (FEC_BD_BASE + FEC_TBD_NUM * sizeof (FEC_TBD));
- fec->xcv_type = MII100;
+ memset (dev, 0, sizeof *dev);

- dev->priv = (void *) fec;
- dev->iobase = MMAP_FEC1;
+ sprintf(dev->name, "FEC%d", fec_info[i].num);
+ dev->priv = &fec_info[i];
+ dev->iobase = fec_info[i].iobase;
dev->init = mpc8220_fec_init;
dev->halt = mpc8220_fec_halt;
dev->send = mpc8220_fec_send;
dev->recv = mpc8220_fec_recv;

- sprintf (dev->name, "FEC ETHERNET");
eth_register (dev);

#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
- miiphy_register (dev->name,
- fec8220_miiphy_read, fec8220_miiphy_write);
+ miiphy_register(dev->name, fec8220_miiphy_read,
+ fec8220_miiphy_write);
#endif

/*
@@ -857,7 +811,11 @@ int mpc8220_fec_initialize (bd_t * bis)
* a garbage after reset. When not using fec for booting
* the Linux fec driver will try to work with this garbage.
*/
- tmp = getenv ("ethaddr");
+ if (i > 0)
+ sprintf(ethaddr, "ethaddr");
+ else
+ sprintf(ethaddr, "eth%daddr", i);
+ tmp = getenv(ethaddr);
if (tmp) {
for (i = 0; i < 6; i++) {
env_enetaddr[i] =
@@ -865,33 +823,165 @@ int mpc8220_fec_initialize (bd_t * bis)
if (tmp)
tmp = (*end) ? end + 1 : end;
}
- mpc8220_fec_set_hwaddr (fec, env_enetaddr);
+ mpc8220_fec_set_hwaddr(&fec_info[i], env_enetaddr);
+ }
}
-#ifdef CONFIG_HAS_ETH1
- tmp = getenv ("eth1addr");
- if (tmp) {
- for (i = 0; i < 6; i++) {
- env_enet1addr[i] =
- tmp ? simple_strtoul (tmp, &end, 16) : 0;
- if (tmp)
- tmp = (*end) ? end + 1 : end;
+
+ return 1;
+}
+
+void setFecDuplexSpeed(mpc8220_fec_priv * fec)
+{
+ volatile ethernet_regs *eth = (volatile ethernet_regs *)fec->iobase;
+
+ eth->r_cntrl = FEC_RCR_MAX_FL(PKT_MAXBUF_SIZE) | FEC_RCR_FCE;
+ if (fec->xcv_type != SEVENWIRE)
+ eth->r_cntrl |= FEC_RCR_MII_MODE;
+
+ if ((fec->phy_dupspd >> 16) == FULL) {
+ /* Set maximum frame length */
+ eth->r_cntrl |= FEC_RCR_DRT;
+ eth->x_cntrl = FEC_TCR_FDEN;
+ eth->x_cntrl &= ~FEC_TCR_FDEN;
+ } else {
+ /* Half duplex mode */
+ eth->r_cntrl |= FEC_RCR_DRT;
+ eth->x_cntrl &= ~FEC_TCR_FDEN;
+ }
+
+ if ((fec->phy_dupspd & 0xFFFF) == _100BASET) {
+#ifdef ET_DEBUG
+ printf("100Mbps\n");
+#endif
+ printf("100Mbps\n");
+ } else {
+#ifdef ET_DEBUG
+ printf("10Mbps\n");
+#endif
+ printf("10Mbps\n");
+ }
+}
+
+/* PHY identification */
+#define PHY_ID_LXT970 0x78100000 /* LXT970 */
+#define PHY_ID_LXT971 0x001378e0 /* LXT971 and 972 */
+#define PHY_ID_82555 0x02a80150 /* Intel 82555 */
+#define PHY_ID_QS6612 0x01814400 /* QS6612 */
+#define PHY_ID_AMD79C784 0x00225610 /* AMD 79C784 */
+#define PHY_ID_LSI80225 0x0016f870 /* LSI 80225 */
+#define PHY_ID_LSI80225B 0x0016f880 /* LSI 80225/B */
+#define PHY_ID_DP83848VV 0x20005C90 /* National 83848 */
+#define PHY_ID_DP83849 0x20005CA2 /* National 82849 */
+
+#define STR_ID_LXT970 "LXT970"
+#define STR_ID_LXT971 "LXT971"
+#define STR_ID_82555 "Intel82555"
+#define STR_ID_QS6612 "QS6612"
+#define STR_ID_AMD79C784 "AMD79C784"
+#define STR_ID_LSI80225 "LSI80225"
+#define STR_ID_LSI80225B "LSI80225/B"
+#define STR_ID_DP83848VV "N83848"
+#define STR_ID_DP83849 "N83849"
+
+void mii_discover_phy(struct eth_device *dev)
+{
+#define MAX_PHY_PASSES 11
+ mpc8220_fec_priv *fec = (mpc8220_fec_priv *) dev->priv;
+ int pass, phyno;
+ u16 phytype;
+ u32 phyreg;
+
+ if (fec->phyname_init)
+ return;
+
+ for (pass = 1; pass <= MAX_PHY_PASSES && fec->phy_addr < 0; ++pass) {
+ if (pass > 1) {
+ /* PHY may need more time to recover from reset.
+ * The LXT970 needs 50ms typical, no maximum is
+ * specified, so wait 10ms before try again.
+ * With 11 passes this gives it 100ms to wake up.
+ */
+ udelay(10000); /* wait 10ms */
}
- mpc8220_fec_set_hwaddr (fec2, env_enet1addr);
+
+ for (phyno = 0; phyno < 32 && fec->phy_addr < 0; ++phyno) {
+
+ miiphy_read(dev->name, phyno, PHY_PHYIDR1, &phytype);
+
+#ifdef ET_DEBUG
+ printf("PHY type 0x%x pass %d type\n", phytype, pass);
+#endif
+
+ if (phytype != 0xffff) {
+ fec->phy_addr = phyno;
+ phyreg = phytype << 16;
+ miiphy_read(dev->name, phyno, PHY_PHYIDR2,
+     &phytype);
+ phyreg |= phytype;
+
+ switch (phytype & 0xfffffff0) {
+ case PHY_ID_LXT971:
+ strcpy(fec->phy_name, STR_ID_LXT971);
+ printf(STR_ID_LXT971);
+ fec->phyname_init = 1;
+ break;
+ default:
+ strcpy(fec->phy_name, "unknown");
+ fec->phyname_init = 1;
+ break;
+ }
+ }
+ }
+ }
+ if (fec->phy_addr < 0)
+ printf("No PHY device found.\n");
}
+
+int check_connection(struct eth_device *dev)
+{
+ mpc8220_fec_priv *fec = (mpc8220_fec_priv *) dev->priv;
+ u16 autoneg = 0;
+ int i = 0;
+
+#define AUTONEGLINK (PHY_BMSR_AUTN_COMP | PHY_BMSR_LS)
+ while (i < TOUT_LOOP) {
+ autoneg = 0;
+ miiphy_read(dev->name, fec->phy_addr, PHY_BMSR, &autoneg);
+ i++;
+
+ if ((autoneg & AUTONEGLINK) == AUTONEGLINK) {
+#ifdef ET_DEBUG
+ printf("autoneg mode %x\n", autoneg);
#endif
+ break;
+ }

- return 1;
+ udelay(500);
+ }
+ if (i >= TOUT_LOOP) {
+#ifdef ET_DEBUG
+ printf("Auto Negotiation not complete\n");
+#endif
+ return (0);
+ }
+ return (1);
}

/* MII-interface related functions */
/********************************************************************/
int fec8220_miiphy_read (char *devname, u8 phyAddr, u8 regAddr, u16 *
retVal)
{
- ethernet_regs *eth = (ethernet_regs *) MMAP_FEC1;
+ struct eth_device *dev;
+ volatile ethernet_regs *eth;
u32 reg; /* convenient holder for the PHY register */
u32 phy; /* convenient holder for the PHY */
int timeout = 0xffff;

+ dev = eth_get_dev_by_name(devname);
+ eth =
+     (volatile ethernet_regs *)(((mpc8220_fec_priv *) dev->priv)->
+        iobase);
+
/*
* reading from any PHY's register is done by properly
* programming the FEC's MII data register.
@@ -906,10 +996,10 @@ int fec8220_miiphy_read (char *devname, 
/*
* wait for the related interrupt
*/
- while ((timeout--) && (!(eth->ievent & 0x00800000)));
+ while ((timeout--) && (!(eth->ievent & FEC_EIR_MII))) ;

if (timeout == 0) {
-#ifdef DEBUG
+#ifdef ET_DEBUG
printf ("Read MDIO failed...\n");
#endif
return -1;
@@ -918,7 +1008,7 @@ int fec8220_miiphy_read (char *devname, 
/*
* clear mii interrupt bit
*/
- eth->ievent = 0x00800000;
+ eth->ievent = FEC_EIR_MII;

/*
* it's now safe to read the PHY's register
@@ -931,11 +1021,17 @@ int fec8220_miiphy_read (char *devname, 
/********************************************************************/
int fec8220_miiphy_write (char *devname, u8 phyAddr, u8 regAddr, u16
data)
{
- ethernet_regs *eth = (ethernet_regs *) MMAP_FEC1;
+ struct eth_device *dev;
+ volatile ethernet_regs *eth;
u32 reg; /* convenient holder for the PHY register */
u32 phy; /* convenient holder for the PHY */
int timeout = 0xffff;

+ dev = eth_get_dev_by_name(devname);
+ eth =
+     (volatile ethernet_regs *)(((mpc8220_fec_priv *) dev->priv)->
+        iobase);
+
reg = regAddr << FEC_MII_DATA_RA_SHIFT;
phy = phyAddr << FEC_MII_DATA_PA_SHIFT;

@@ -945,10 +1041,10 @@ int fec8220_miiphy_write (char *devname,
/*
* wait for the MII interrupt
*/
- while ((timeout--) && (!(eth->ievent & 0x00800000)));
+ while ((timeout--) && (!(eth->ievent & FEC_EIR_MII))) ;

if (timeout == 0) {
-#ifdef DEBUG
+#ifdef ET_DEBUG
printf ("Write MDIO failed...\n");
#endif
return -1;
@@ -957,44 +1053,9 @@ int fec8220_miiphy_write (char *devname,
/*
* clear MII interrupt bit
*/
- eth->ievent = 0x00800000;
+ eth->ievent = FEC_EIR_MII;

return 0;
}

-#ifdef DEBUG
-static u32 local_crc32 (char *string, unsigned int crc_value, int len)
-{
- int i;
- char c;
- unsigned int crc, count;
-
- /*
- * crc32 algorithm
- */
- /*
- * crc = 0xffffffff; * The initialized value should be 0xffffffff
- */
- crc = crc_value;
-
- for (i = len; --i >= 0;) {
- c = *string++;
- for (count = 0; count < 8; count++) {
- if ((c & 0x01) ^ (crc & 0x01)) {
- crc >>= 1;
- crc = crc ^ 0xedb88320;
- } else {
- crc >>= 1;
- }
- c >>= 1;
- }
- }
-
- /*
- * In big endian system, do byte swaping for crc value
- */
- return crc;
-}
-#endif /* DEBUG */
-
#endif /* CONFIG_MPC8220_FEC */
diff -rupN u-boot-all.git/cpu/mpc8220/fec_dma_tasks.S u-boot-all-8220-
fec/cpu/mpc8220/fec_dma_tasks.S
--- u-boot-all.git/cpu/mpc8220/fec_dma_tasks.S 2007-04-03
19:18:56.000000000 -0500
+++ u-boot-all-8220-fec/cpu/mpc8220/fec_dma_tasks.S 1969-12-31
18:00:00.000000000 -0600
@@ -1,363 +0,0 @@
-/*
- * Copyright (C) 2004, Freescale Semiconductor, Inc.
- *
- * This file contains microcode for the FEC controller of the MPC8220.
- */
-
-#include <config.h>
-
-#if defined(CONFIG_MPC8220)
-
-/* sas/sccg, gas target */
-.section        smartdmaInitData,"aw", at progbits /* Initialized data for
task variables */
-.section        smartdmaTaskTable,"aw", at progbits /* Task tables */
-.align  9
-.globl taskTable
-taskTable:
-.globl scEthernetRecv_Entry
-scEthernetRecv_Entry: /* Task 0 */
-.long   scEthernetRecv_TDT - taskTable /* Task 0 Descriptor Table */
-.long   scEthernetRecv_TDT - taskTable + 0x00000094
-.long   scEthernetRecv_VarTab - taskTable /* Task 0 Variable Table */
-.long   scEthernetRecv_FDT - taskTable + 0x03 /* Task 0 Function
Descriptor Table & Flags */
-.long   0x00000000
-.long   0x00000000
-.long   scEthernetRecv_CSave - taskTable /* Task 0 context save space
*/
-.long   0xf0000000
-.globl scEthernetXmit_Entry
-scEthernetXmit_Entry: /* Task 1 */
-.long   scEthernetXmit_TDT - taskTable /* Task 1 Descriptor Table */
-.long   scEthernetXmit_TDT - taskTable + 0x000000e0
-.long   scEthernetXmit_VarTab - taskTable /* Task 1 Variable Table */
-.long   scEthernetXmit_FDT - taskTable + 0x03 /* Task 1 Function
Descriptor Table & Flags */
-.long   0x00000000
-.long   0x00000000
-.long   scEthernetXmit_CSave - taskTable /* Task 1 context save space
*/
-.long   0xf0000000
-
-





More information about the U-Boot mailing list