Merge with /home/tur/git/u-boot#motionpro
[platform/kernel/u-boot.git] / cpu / mpc5xxx / fec.c
index 1df394a..8136366 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2003
+ * (C) Copyright 2003-2005
  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  *
  * This file is based on mpc4200fec.c,
 #include "sdma.h"
 #include "fec.h"
 
+DECLARE_GLOBAL_DATA_PTR;
+
 /* #define DEBUG       0x28 */
 
 #if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
        defined(CONFIG_MPC5xxx_FEC)
 
+#if !(defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII))
+#error "CONFIG_MII has to be defined!"
+#endif
+
 #if (DEBUG & 0x60)
-static void tfifo_print(mpc5xxx_fec_priv *fec);
-static void rfifo_print(mpc5xxx_fec_priv *fec);
+static void tfifo_print(char *devname, mpc5xxx_fec_priv *fec);
+static void rfifo_print(char *devname, mpc5xxx_fec_priv *fec);
 #endif /* DEBUG */
 
 #if (DEBUG & 0x40)
@@ -35,9 +41,12 @@ typedef struct {
     uint8 head[16];             /* MAC header(6 + 6 + 2) + 2(aligned) */
 } NBUF;
 
+int fec5xxx_miiphy_read(char *devname, uint8 phyAddr, uint8 regAddr, uint16 * retVal);
+int fec5xxx_miiphy_write(char *devname, uint8 phyAddr, uint8 regAddr, uint16 data);
+
 /********************************************************************/
 #if (DEBUG & 0x2)
-static void mpc5xxx_fec_phydump (void)
+static void mpc5xxx_fec_phydump (char *devname)
 {
        uint16 phyStatus, i;
        uint8 phyAddr = CONFIG_PHY_ADDR;
@@ -55,7 +64,7 @@ static void mpc5xxx_fec_phydump (void)
 
        for (i = 0; i < 32; i++) {
                if (reg_mask[i]) {
-                       miiphy_read(phyAddr, i, &phyStatus);
+                       miiphy_read(devname, phyAddr, i, &phyStatus);
                        printf("Mii reg %d: 0x%04x\n", i, phyStatus);
                }
        }
@@ -115,7 +124,7 @@ static void mpc5xxx_fec_tbd_init(mpc5xxx_fec_priv *fec)
 }
 
 /********************************************************************/
-static void mpc5xxx_fec_rbd_clean(mpc5xxx_fec_priv *fec, FEC_RBD * pRbd)
+static void mpc5xxx_fec_rbd_clean(mpc5xxx_fec_priv *fec, volatile FEC_RBD * pRbd)
 {
        /*
         * Reset buffer descriptor as empty
@@ -141,7 +150,7 @@ static void mpc5xxx_fec_rbd_clean(mpc5xxx_fec_priv *fec, FEC_RBD * pRbd)
 /********************************************************************/
 static void mpc5xxx_fec_tbd_scrub(mpc5xxx_fec_priv *fec)
 {
-       FEC_TBD *pUsedTbd;
+       volatile FEC_TBD *pUsedTbd;
 
 #if (DEBUG & 0x1)
        printf ("tbd_scrub: fec->cleanTbdNum = %d, fec->usedTbdIndex = %d\n",
@@ -235,10 +244,8 @@ static void mpc5xxx_fec_set_hwaddr(mpc5xxx_fec_priv *fec, char *mac)
 /********************************************************************/
 static int mpc5xxx_fec_init(struct eth_device *dev, bd_t * bis)
 {
-       DECLARE_GLOBAL_DATA_PTR;
        mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;
        struct mpc5xxx_sdma *sdma = (struct mpc5xxx_sdma *)MPC5XXX_SDMA;
-       const uint8 phyAddr = CONFIG_PHY_ADDR;  /* Only one PHY */
 
 #if (DEBUG & 0x1)
        printf ("mpc5xxx_fec_init... Begin\n");
@@ -251,17 +258,6 @@ static int mpc5xxx_fec_init(struct eth_device *dev, bd_t * bis)
        mpc5xxx_fec_tbd_init(fec);
 
        /*
-        * Initialize GPIO pins
-        */
-       if (fec->xcv_type == SEVENWIRE) {
-               /*  10MBit with 7-wire operation */
-               *(vu_long *)MPC5XXX_GPS_PORT_CONFIG |= 0x00020000;
-       } else {
-               /* 100MBit with MD operation */
-               *(vu_long *)MPC5XXX_GPS_PORT_CONFIG |= 0x00050000;
-       }
-
-       /*
         * Clear FEC-Lite interrupt event register(IEVENT)
         */
        fec->eth->ievent = 0xffffffff;
@@ -303,7 +299,8 @@ static int mpc5xxx_fec_init(struct eth_device *dev, bd_t * bis)
        /*
         * Set Rx FIFO alarm and granularity value
         */
-       fec->eth->rfifo_cntrl = 0x0c000000;
+       fec->eth->rfifo_cntrl = 0x0c000000
+                               | (fec->eth->rfifo_cntrl & ~0x0f000000);
        fec->eth->rfifo_alarm = 0x0000030c;
 #if (DEBUG & 0x22)
        if (fec->eth->rfifo_status & 0x00700000 ) {
@@ -314,7 +311,8 @@ static int mpc5xxx_fec_init(struct eth_device *dev, bd_t * bis)
        /*
         * Set Tx FIFO granularity value
         */
-       fec->eth->tfifo_cntrl = 0x0c000000;
+       fec->eth->tfifo_cntrl = 0x0c000000
+                               | (fec->eth->tfifo_cntrl & ~0x0f000000);
 #if (DEBUG & 0x2)
        printf("tfifo_status: 0x%08x\n", fec->eth->tfifo_status);
        printf("tfifo_alarm: 0x%08x\n", fec->eth->tfifo_alarm);
@@ -330,7 +328,7 @@ static int mpc5xxx_fec_init(struct eth_device *dev, bd_t * bis)
         * Set individual address filter for unicast address
         * and set physical address registers.
         */
-       mpc5xxx_fec_set_hwaddr(fec, dev->enetaddr);
+       mpc5xxx_fec_set_hwaddr(fec, (char *)dev->enetaddr);
 
        /*
         * Set multicast address filter
@@ -366,10 +364,84 @@ static int mpc5xxx_fec_init(struct eth_device *dev, bd_t * bis)
        /*
         * 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;
+       *(volatile int *)FEC_TBD_BASE = (int)fec->tbdBase;
+       *(volatile int *)FEC_RBD_BASE = (int)fec->rbdBase;
+       *(volatile int *)FEC_TBD_NEXT = (int)fec->tbdBase;
+       *(volatile int *)FEC_RBD_NEXT = (int)fec->rbdBase;
+
+       /*
+        * Enable FEC-Lite controller
+        */
+       fec->eth->ecntrl |= 0x00000006;
+
+#if (DEBUG & 0x2)
+       if (fec->xcv_type != SEVENWIRE)
+               mpc5xxx_fec_phydump (dev->name);
+#endif
+
+       /*
+        * Enable SmartDMA receive task
+        */
+       SDMA_TASK_ENABLE(FEC_RECV_TASK_NO);
+
+#if (DEBUG & 0x1)
+       printf("mpc5xxx_fec_init... Done \n");
+#endif
+
+       return 1;
+}
+
+/********************************************************************/
+static int mpc5xxx_fec_init_phy(struct eth_device *dev, bd_t * bis)
+{
+       mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;
+       const uint8 phyAddr = CONFIG_PHY_ADDR;  /* Only one PHY */
+
+#if (DEBUG & 0x1)
+       printf ("mpc5xxx_fec_init_phy... Begin\n");
+#endif
+
+       /*
+        * Initialize GPIO pins
+        */
+       if (fec->xcv_type == SEVENWIRE) {
+               /*  10MBit with 7-wire operation */
+#if defined(CONFIG_TOTAL5200)
+               /* 7-wire and USB2 on Ethernet */
+               *(vu_long *)MPC5XXX_GPS_PORT_CONFIG |= 0x00030000;
+#else  /* !CONFIG_TOTAL5200 */
+               /* 7-wire only */
+               *(vu_long *)MPC5XXX_GPS_PORT_CONFIG |= 0x00020000;
+#endif /* CONFIG_TOTAL5200 */
+       } else {
+               /* 100MBit with MD operation */
+               *(vu_long *)MPC5XXX_GPS_PORT_CONFIG |= 0x00050000;
+       }
+
+       /*
+        * Clear FEC-Lite interrupt event register(IEVENT)
+        */
+       fec->eth->ievent = 0xffffffff;
+
+       /*
+        * Set interrupt mask register
+        */
+       fec->eth->imask = 0x00000000;
+
+/*
+ * In original Promess-provided code PHY initialization is disabled with the
+ * following comment: "Phy initialization is DISABLED for now.  There was a
+ * problem with running 100 Mbps on PRO board". Thus we temporarily disable
+ * PHY initialization for the Motion-PRO board, until a proper fix is found.
+ */
+
+       if (fec->xcv_type != SEVENWIRE) {
+               /*
+                * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock
+                * and do not drop the Preamble.
+                */
+               fec->eth->mii_speed = (((gd->ipb_clk >> 20) / 5) << 1); /* No MII for 7-wire mode */
+       }
 
        if (fec->xcv_type != SEVENWIRE) {
                /*
@@ -399,9 +471,13 @@ static int mpc5xxx_fec_init(struct eth_device *dev, bd_t * bis)
                /*
                 * Reset PHY, then delay 300ns
                 */
-               miiphy_write(phyAddr, 0x0, 0x8000);
+               miiphy_write(dev->name, phyAddr, 0x0, 0x8000);
                udelay(1000);
 
+#if defined(CONFIG_UC101)
+               /* Set the LED configuration Register for the UC101 Board */
+               miiphy_write(dev->name, phyAddr, 0x14, 0x4122);
+#endif
                if (fec->xcv_type == MII10) {
                        /*
                         * Force 10Base-T, FDX operation
@@ -409,11 +485,11 @@ static int mpc5xxx_fec_init(struct eth_device *dev, bd_t * bis)
 #if (DEBUG & 0x2)
                        printf("Forcing 10 Mbps ethernet link... ");
 #endif
-                       miiphy_read(phyAddr, 0x1, &phyStatus);
+                       miiphy_read(dev->name, phyAddr, 0x1, &phyStatus);
                        /*
-                       miiphy_write(fec, phyAddr, 0x0, 0x0100);
+                       miiphy_write(dev->name, fec, phyAddr, 0x0, 0x0100);
                        */
-                       miiphy_write(phyAddr, 0x0, 0x0180);
+                       miiphy_write(dev->name, phyAddr, 0x0, 0x0180);
 
                        timeout = 20;
                        do {    /* wait for link status to go down */
@@ -424,7 +500,7 @@ static int mpc5xxx_fec_init(struct eth_device *dev, bd_t * bis)
 #endif
                                        break;
                                }
-                               miiphy_read(phyAddr, 0x1, &phyStatus);
+                               miiphy_read(dev->name, phyAddr, 0x1, &phyStatus);
 #if (DEBUG & 0x2)
                                printf("=");
 #endif
@@ -437,7 +513,7 @@ static int mpc5xxx_fec_init(struct eth_device *dev, bd_t * bis)
                                        printf("failed. Link is down.\n");
                                        break;
                                }
-                               miiphy_read(phyAddr, 0x1, &phyStatus);
+                               miiphy_read(dev->name, phyAddr, 0x1, &phyStatus);
 #if (DEBUG & 0x2)
                                printf("+");
 #endif
@@ -450,12 +526,12 @@ static int mpc5xxx_fec_init(struct eth_device *dev, bd_t * bis)
                        /*
                         * Set the auto-negotiation advertisement register bits
                         */
-                       miiphy_write(phyAddr, 0x4, 0x01e1);
+                       miiphy_write(dev->name, phyAddr, 0x4, 0x01e1);
 
                        /*
                         * Set MDIO bit 0.12 = 1(&& bit 0.9=1?) to enable auto-negotiation
                         */
-                       miiphy_write(phyAddr, 0x0, 0x1200);
+                       miiphy_write(dev->name, phyAddr, 0x0, 0x1200);
 
                        /*
                         * Wait for AN completion
@@ -471,7 +547,7 @@ static int mpc5xxx_fec_init(struct eth_device *dev, bd_t * bis)
                                        return -1;
                                }
 
-                               if (miiphy_read(phyAddr, 0x1, &phyStatus) != 0) {
+                               if (miiphy_read(dev->name, phyAddr, 0x1, &phyStatus) != 0) {
 #if (DEBUG & 0x2)
                                        printf("PHY auto neg 1 failed 0x%04x...\n", phyStatus);
 #endif
@@ -486,23 +562,14 @@ static int mpc5xxx_fec_init(struct eth_device *dev, bd_t * bis)
 
        }
 
-       /*
-        * Enable FEC-Lite controller
-        */
-       fec->eth->ecntrl |= 0x00000006;
-
 #if (DEBUG & 0x2)
        if (fec->xcv_type != SEVENWIRE)
-               mpc5xxx_fec_phydump ();
+               mpc5xxx_fec_phydump (dev->name);
 #endif
 
-       /*
-        * Enable SmartDMA receive task
-        */
-       SDMA_TASK_ENABLE(FEC_RECV_TASK_NO);
 
 #if (DEBUG & 0x1)
-       printf("mpc5xxx_fec_init... Done \n");
+       printf("mpc5xxx_fec_init_phy... Done \n");
 #endif
 
        return 1;
@@ -519,7 +586,7 @@ static void mpc5xxx_fec_halt(struct eth_device *dev)
 
 #if (DEBUG & 0x2)
        if (fec->xcv_type != SEVENWIRE)
-               mpc5xxx_fec_phydump ();
+               mpc5xxx_fec_phydump (dev->name);
 #endif
 
        /*
@@ -582,7 +649,7 @@ static void mpc5xxx_fec_halt(struct eth_device *dev)
 #if (DEBUG & 0x60)
 /********************************************************************/
 
-static void tfifo_print(mpc5xxx_fec_priv *fec)
+static void tfifo_print(char *devname, mpc5xxx_fec_priv *fec)
 {
        uint16 phyAddr = CONFIG_PHY_ADDR;
        uint16 phyStatus;
@@ -590,7 +657,7 @@ static void tfifo_print(mpc5xxx_fec_priv *fec)
        if ((fec->eth->tfifo_lrf_ptr != fec->eth->tfifo_lwf_ptr)
                || (fec->eth->tfifo_rdptr != fec->eth->tfifo_wrptr)) {
 
-               miiphy_read(phyAddr, 0x1, &phyStatus);
+               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);
@@ -606,7 +673,7 @@ static void tfifo_print(mpc5xxx_fec_priv *fec)
        }
 }
 
-static void rfifo_print(mpc5xxx_fec_priv *fec)
+static void rfifo_print(char *devname, mpc5xxx_fec_priv *fec)
 {
        uint16 phyAddr = CONFIG_PHY_ADDR;
        uint16 phyStatus;
@@ -614,7 +681,7 @@ static void rfifo_print(mpc5xxx_fec_priv *fec)
        if ((fec->eth->rfifo_lrf_ptr != fec->eth->rfifo_lwf_ptr)
                || (fec->eth->rfifo_rdptr != fec->eth->rfifo_wrptr)) {
 
-               miiphy_read(phyAddr, 0x1, &phyStatus);
+               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);
@@ -641,11 +708,11 @@ static int mpc5xxx_fec_send(struct eth_device *dev, volatile void *eth_data,
         * 6-byte Ethernet addresses.
         */
        mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;
-       FEC_TBD *pTbd;
+       volatile FEC_TBD *pTbd;
 
 #if (DEBUG & 0x20)
        printf("tbd status: 0x%04x\n", fec->tbdBase[0].status);
-       tfifo_print(fec);
+       tfifo_print(dev->name, fec);
 #endif
 
        /*
@@ -688,7 +755,7 @@ static int mpc5xxx_fec_send(struct eth_device *dev, volatile void *eth_data,
         */
        if (fec->xcv_type != SEVENWIRE) {
                uint16 phyStatus;
-               miiphy_read(0, 0x1, &phyStatus);
+               miiphy_read(dev->name, 0, 0x1, &phyStatus);
        }
 
        /*
@@ -696,11 +763,11 @@ static int mpc5xxx_fec_send(struct eth_device *dev, volatile void *eth_data,
         */
 
 #if (DEBUG & 0x20)
-       tfifo_print(fec);
+       tfifo_print(dev->name, fec);
 #endif
        SDMA_TASK_ENABLE (FEC_XMIT_TASK_NO);
 #if (DEBUG & 0x20)
-       tfifo_print(fec);
+       tfifo_print(dev->name, fec);
 #endif
 #if (DEBUG & 0x8)
        printf( "+" );
@@ -732,11 +799,11 @@ static int mpc5xxx_fec_recv(struct eth_device *dev)
         * This command pulls one frame from the card
         */
        mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;
-       FEC_RBD *pRbd = &fec->rbdBase[fec->rbdIndex];
+       volatile FEC_RBD *pRbd = &fec->rbdBase[fec->rbdIndex];
        unsigned long ievent;
        int frame_length, len = 0;
        NBUF *frame;
-       char buff[FEC_MAX_PKT_SIZE];
+       uchar buff[FEC_MAX_PKT_SIZE];
 
 #if (DEBUG & 0x1)
        printf ("mpc5xxx_fec_recv %d Start...\n", fec->rbdIndex);
@@ -822,14 +889,20 @@ int mpc5xxx_fec_initialize(bd_t * bis)
        fec->eth = (ethernet_regs *)MPC5XXX_FEC;
        fec->tbdBase = (FEC_TBD *)FEC_BD_BASE;
        fec->rbdBase = (FEC_RBD *)(FEC_BD_BASE + FEC_TBD_NUM * sizeof(FEC_TBD));
-#if defined(CONFIG_ICECUBE) || \
-    defined(CONFIG_PM520)   || \
-    defined(CONFIG_TOP5200)
+#if defined(CONFIG_CANMB)    || defined(CONFIG_HMI1001)        || \
+    defined(CONFIG_ICECUBE)  || defined(CONFIG_INKA4X0)        || \
+    defined(CONFIG_JUPITER)  || defined(CONFIG_MCC200) || \
+    defined(CONFIG_MOTIONPRO)|| defined(CONFIG_O2DNT)  || \
+    defined(CONFIG_PM520)    || defined(CONFIG_TOP5200)        || \
+    defined(CONFIG_TQM5200)  || defined(CONFIG_UC101)  || \
+    defined(CONFIG_V38B)
 # ifndef CONFIG_FEC_10MBIT
        fec->xcv_type = MII100;
 # else
        fec->xcv_type = MII10;
 # endif
+#elif defined(CONFIG_TOTAL5200)
+       fec->xcv_type = SEVENWIRE;
 #else
 #error fec->xcv_type not initialized.
 #endif
@@ -844,6 +917,11 @@ int mpc5xxx_fec_initialize(bd_t * bis)
        sprintf(dev->name, "FEC ETHERNET");
        eth_register(dev);
 
+#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
+       miiphy_register (dev->name,
+                       fec5xxx_miiphy_read, fec5xxx_miiphy_write);
+#endif
+
        /*
         * Try to set the mac address now. The fec mac address is
         * a garbage after reset. When not using fec for booting
@@ -859,12 +937,14 @@ int mpc5xxx_fec_initialize(bd_t * bis)
                mpc5xxx_fec_set_hwaddr(fec, env_enetaddr);
        }
 
+       mpc5xxx_fec_init_phy(dev, bis);
+
        return 1;
 }
 
 /* MII-interface related functions */
 /********************************************************************/
-int miiphy_read(uint8 phyAddr, uint8 regAddr, uint16 * retVal)
+int fec5xxx_miiphy_read(char *devname, uint8 phyAddr, uint8 regAddr, uint16 * retVal)
 {
        ethernet_regs *eth = (ethernet_regs *)MPC5XXX_FEC;
        uint32 reg;             /* convenient holder for the PHY register */
@@ -906,7 +986,7 @@ int miiphy_read(uint8 phyAddr, uint8 regAddr, uint16 * retVal)
 }
 
 /********************************************************************/
-int miiphy_write(uint8 phyAddr, uint8 regAddr, uint16 data)
+int fec5xxx_miiphy_write(char *devname, uint8 phyAddr, uint8 regAddr, uint16 data)
 {
        ethernet_regs *eth = (ethernet_regs *)MPC5XXX_FEC;
        uint32 reg;             /* convenient holder for the PHY register */