]> git.kernelconcepts.de Git - karo-tx-redboot.git/blobdiff - packages/devs/eth/fec/v2_0/src/if_fec.c
unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / devs / eth / fec / v2_0 / src / if_fec.c
index 697c487efae3731ac39811d1b1efda6f67f767b1..5d157e8b4746e61d2258cd18f174aeaa6df5c508 100644 (file)
@@ -2,7 +2,7 @@
 //
 //      dev/if_fec.c
 //
-//      Device driver for FEC 
+//      Device driver for FEC
 //
 //==========================================================================
 //####ECOSGPLCOPYRIGHTBEGIN####
 //#####DESCRIPTIONBEGIN####
 //
 // Author(s):    Fred Fan
-// Contributors: 
+// Contributors:
 // Date:         2006-08-23
-// Purpose:      
+// Purpose:
 // Description:  Driver for FEC ethernet controller
 //
-// Note:         
+// Note:
 //
 //####DESCRIPTIONEND####
 //
@@ -91,6 +91,7 @@ void mxc_fec_phy_write(int reg, int unit, unsigned short data);
 
 #include <cyg/io/eth_phy.h>
 #endif
+static bool mxc_fec_init(struct cyg_netdevtab_entry *tab);
 
 #include <cyg/io/fec.h>
 #define __WANT_DEVS
@@ -114,71 +115,135 @@ static void mxc_fec_phy_status(mxc_fec_priv_t *dev, unsigned short value, bool s
 
 #ifndef CYGPKG_DEVS_ETH_PHY
 /*!
- * Global variable which contains the name of FEC driver and device. 
+ * Global variable which contains the name of FEC driver and device.
  */
 static char  mxc_fec_name[] = "mxc_fec";
 
 /*!
  * Global variable which defines the private structure of FEC device.
  */
-static mxc_fec_priv_t  mxc_fec_private ;
+static mxc_fec_priv_t  mxc_fec_private;
 #endif
 
 /*!
- *Global variable which defines the buffer descriptions for receiving frame
+ * Global variable which defines the buffer descriptors for receive frames
  *     comment:: it must aligned by 128-bits.
  */
-static mxc_fec_bd_t mxc_fec_rx_bd[FEC_BD_RX_NUM] __attribute__ ( ( aligned(32) ) ) ;
+static mxc_fec_bd_t mxc_fec_rx_bd[FEC_BD_RX_NUM] __attribute__ ((aligned(32)));
 
 /*!
- *Global variable which defines the buffer descriptions for receiving frame
+ * Global variable which defines the buffer descriptors for transmit frames
  *     comment:: it must aligned by 128-bits.
  */
-static mxc_fec_bd_t mxc_fec_tx_bd[FEC_BD_TX_NUM] __attribute__ ( ( aligned(32) ) ) ;
+static mxc_fec_bd_t mxc_fec_tx_bd[FEC_BD_TX_NUM] __attribute__ ((aligned(32)));
 
 /*!
- * Global variable which contains the frame buffers , 
+ * Global variable which contains the frame buffers
  */
-static unsigned char mxc_fec_rx_buf[FEC_BD_RX_NUM][2048] __attribute__ ( ( aligned(32) ) ) ;
+static unsigned char mxc_fec_rx_buf[FEC_BD_RX_NUM][2048] __attribute__ ((aligned(32)));
 
 /*!
- * Global variable which contains the frame buffers , 
+ * Global variable which contains the frame buffers
  */
-static unsigned char mxc_fec_tx_buf[FEC_BD_TX_NUM][2048] __attribute__ ( ( aligned(32) ) ) ;
+static unsigned char mxc_fec_tx_buf[FEC_BD_TX_NUM][2048] __attribute__ ((aligned(32)));
 
+#if 0
+static void dump_packet (unsigned char *pkt, size_t len)
+{
+       int i;
+
+       diag_printf("Packet dump: %u byte", len);
+       for (i = 0; i < len; i++) {
+               if (i % 16 == 0) {
+                       diag_printf("\n%04x:", i);
+               } else {
+                       if (i % 4 == 0) {
+                               diag_printf(" ");
+                       }
+                       if (i % 8 == 0) {
+                               diag_printf(" ");
+                       }
+               }
+               diag_printf(" %02x", pkt[i]);
+       }
+       if (i % 16)
+               diag_printf("\n");
+}
+#endif
+
+#define mxc_fec_reg_read(hw_reg,reg) _mxc_fec_reg_read(&(hw_reg)->reg, #reg)
+static inline unsigned long _mxc_fec_reg_read(volatile unsigned long *addr,
+                                                                                         const char *reg)
+{
+       unsigned long val = readl(addr);
+
+       if (net_debug) diag_printf("Read %08lx from FEC reg %s[%p]\n",
+                                  val, reg, addr);
+       return val;
+}
+
+#define mxc_fec_reg_write(hw_reg,reg,val) _mxc_fec_reg_write(&(hw_reg)->reg, val, #reg)
+static inline void _mxc_fec_reg_write(volatile unsigned long *addr,
+                                                                         unsigned long val, const char *reg)
+{
+       if (net_debug) diag_printf("Writing %08lx to FEC reg %s[%p]\n",
+                                  val, reg, addr);
+       writel(val, addr);
+}
+
+#define mxc_fec_reg_read16(hw_reg,reg) _mxc_fec_reg_read16(&(hw_reg)->reg, #reg)
+static inline unsigned short _mxc_fec_reg_read16(volatile unsigned short *addr,
+                                                                                               const char *reg)
+{
+       unsigned short val = readw(addr);
+
+       if (net_debug) diag_printf("Read %04x from FEC reg %s[%p]\n",
+                                  val, reg, addr);
+       return val;
+}
+
+#define mxc_fec_reg_write16(hw_reg,reg,val) _mxc_fec_reg_write16(&(hw_reg)->reg, val, #reg)
+static inline void _mxc_fec_reg_write16(volatile unsigned short *addr,
+                                                                               unsigned short val, const char *reg)
+{
+       if (net_debug) diag_printf("Writing %04x to FEC reg %s[%p]\n",
+                                  val, reg, addr);
+       writew(val, addr);
+}
 
 /*!
- * This function get the value of  PHY registers by MII interface
+ * This function gets the value of PHY registers via MII interface
  */
 static int
 mxc_fec_mii_read(volatile mxc_fec_reg_t *hw_reg, unsigned char phy_addr, unsigned char reg_addr,
-                unsigned short int *value)
+                                unsigned short int *value)
 {
        unsigned long waiting = FEC_MII_TIMEOUT;
-       
+
        if (net_debug) diag_printf("%s: Trying to read phy[%02x] reg %04x\n",
                                   __FUNCTION__, phy_addr, reg_addr);
-       if (hw_reg->eir & FEC_EVENT_MII) {
+       if (mxc_fec_reg_read(hw_reg, eir) & FEC_EVENT_MII) {
                if (net_debug) diag_printf("%s: Clearing EIR_EVENT_MII\n", __FUNCTION__);
-               hw_reg->eir = FEC_EVENT_MII ;
+               mxc_fec_reg_write(hw_reg, eir, FEC_EVENT_MII);
        }
-       if (net_debug) diag_printf("%s: EIR=%08lx\n", __FUNCTION__, hw_reg->eir);
-       hw_reg->mmfr = FEC_MII_READ(phy_addr, reg_addr);/*Write CMD*/
+       if (net_debug) diag_printf("%s: EIR=%08lx\n", __FUNCTION__, mxc_fec_reg_read(hw_reg, eir));
+       mxc_fec_reg_write(hw_reg, mmfr, FEC_MII_READ(phy_addr, reg_addr));/* Write CMD */
        while (1) {
-               if (hw_reg->eir & FEC_EVENT_MII) {
+               if (mxc_fec_reg_read(hw_reg, eir) & FEC_EVENT_MII) {
                        if (net_debug) diag_printf("%s: Got EIR_EVENT_MII: EIR=%08lx\n",
-                                                  __FUNCTION__, hw_reg->eir);
-                       hw_reg->eir = FEC_EVENT_MII ; 
+                                                  __FUNCTION__, mxc_fec_reg_read(hw_reg, eir));
+                       mxc_fec_reg_write(hw_reg, eir, FEC_EVENT_MII);
                        break;
                }
                if (--waiting == 0) {
                        diag_printf("%s: Read from PHY at addr %d reg 0x%02x timed out: EIR=%08lx\n",
-                                   __FUNCTION__, phy_addr, reg_addr, hw_reg->eir);
+                                   __FUNCTION__, phy_addr, reg_addr,
+                                   mxc_fec_reg_read(hw_reg, eir));
                        return -1;
                }
-               hal_delay_us(FEC_MII_TICK);     
+               hal_delay_us(FEC_MII_TICK);
        }
-       *value = FEC_MII_GET_DATA(hw_reg->mmfr);
+       *value = FEC_MII_GET_DATA(mxc_fec_reg_read(hw_reg, mmfr));
        if (net_debug) diag_printf("%s: Read %04x from phy[%02x] reg %04x\n", __FUNCTION__,
                                   *value, phy_addr, reg_addr);
        return 0;
@@ -187,32 +252,33 @@ mxc_fec_mii_read(volatile mxc_fec_reg_t *hw_reg, unsigned char phy_addr, unsigne
 /*!
  * This function set the value of  PHY registers by MII interface
  */
-static int 
-mxc_fec_mii_write(volatile mxc_fec_reg_t * hw_reg, unsigned char phy_addr, unsigned char reg_addr,
+static int
+mxc_fec_mii_write(volatile mxc_fec_reg_t *hw_reg, unsigned char phy_addr, unsigned char reg_addr,
                  unsigned short int value)
 {
        unsigned long waiting = FEC_MII_TIMEOUT;
-       
+
        if (net_debug) diag_printf("%s: Trying to write %04x to phy[%02x] reg %04x\n", __FUNCTION__,
                                   value, phy_addr, reg_addr);
-       if(hw_reg->eir & FEC_EVENT_MII ) {
+       if (mxc_fec_reg_read(hw_reg, eir) & FEC_EVENT_MII) {
                if (net_debug) diag_printf("%s: Clearing EIR_EVENT_MII\n", __FUNCTION__);
-               hw_reg->eir = FEC_EVENT_MII;
+               mxc_fec_reg_write(hw_reg, eir, FEC_EVENT_MII);
        }
-       if (net_debug) diag_printf("%s: EIR=%08lx\n", __FUNCTION__, hw_reg->eir);
-       hw_reg->mmfr = FEC_MII_WRITE(phy_addr, reg_addr, value);/*Write CMD*/
+       if (net_debug) diag_printf("%s: EIR=%08lx\n", __FUNCTION__, mxc_fec_reg_read(hw_reg, eir));
+       mxc_fec_reg_write(hw_reg, mmfr,  FEC_MII_WRITE(phy_addr, reg_addr, value));/* Write CMD */
        if (net_debug) diag_printf("%s: Wrote cmd %08x to MMFR\n", __FUNCTION__,
                                   FEC_MII_WRITE(phy_addr, reg_addr, value));
        while (1) {
-               if (hw_reg->eir & FEC_EVENT_MII) {
+               if (mxc_fec_reg_read(hw_reg, eir) & FEC_EVENT_MII) {
                        if (net_debug) diag_printf("%s: Got EIR_EVENT_MII: EIR=%08lx\n",
-                                                  __FUNCTION__, hw_reg->eir);
-                       hw_reg->eir = FEC_EVENT_MII ; 
+                                                  __FUNCTION__, mxc_fec_reg_read(hw_reg, eir));
+                       mxc_fec_reg_write(hw_reg, eir, FEC_EVENT_MII);
                        break;
                }
                if (--waiting == 0) {
                        diag_printf("%s: Write to PHY at addr %d reg 0x%02x timed out: EIR=%08lx\n",
-                                   __FUNCTION__, phy_addr, reg_addr, hw_reg->eir);
+                                   __FUNCTION__, phy_addr, reg_addr,
+                                   mxc_fec_reg_read(hw_reg, eir));
                        return -1;
                }
                hal_delay_us(FEC_MII_TICK);
@@ -222,57 +288,89 @@ mxc_fec_mii_write(volatile mxc_fec_reg_t * hw_reg, unsigned char phy_addr, unsig
 }
 
 static void
-mxc_fec_set_mac_address(volatile mxc_fec_reg_t *dev, unsigned char *enaddr)
+mxc_fec_set_mac_address(volatile mxc_fec_reg_t *hw_reg, unsigned char *enaddr)
 {
        unsigned long value;
-       
+
        value = enaddr[0];
        value = (value << 8) + enaddr[1];
        value = (value << 8) + enaddr[2];
        value = (value << 8) + enaddr[3];
-       dev->palr = value;
-       
+       mxc_fec_reg_write(hw_reg, palr, value);
+
        value = enaddr[4];
        value = (value << 8) + enaddr[5];
-       dev->paur = (value << 16);
+       mxc_fec_reg_write(hw_reg, paur, value << 16);
 }
 
 /*!
- * This function set the value of  PHY registers by MII interface
+ * This function enables the FEC for reception of packets
  */
-static void 
+static void
 mxc_fec_start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags)
 {
-       mxc_fec_priv_t *priv = sc?sc->driver_private:NULL;
-       volatile mxc_fec_reg_t *chip = priv?priv->hw_reg:NULL;
+       mxc_fec_priv_t *priv = sc ? sc->driver_private : NULL;
+       volatile mxc_fec_reg_t *hw_reg = priv ? priv->hw_reg : NULL;
 
-       if (!(priv && chip) || enaddr == NULL ) {
-               diag_printf("BUG[start]: MAC address or some fields in driver is NULL\n");
+       if (!(priv && hw_reg)) {
+               diag_printf("BUG[start]: FEC driver not initialized\n");
+               return;
+       }
+       if (enaddr == NULL) {
+               diag_printf("BUG[start]: no MAC address supplied\n");
                return;
        }
-       mxc_fec_set_mac_address(chip, enaddr);
+       mxc_fec_set_mac_address(hw_reg, enaddr);
 
        priv->tx_busy = 0;
-       chip->ecr |= FEC_ETHER_EN;
-       chip->rdar |= FEC_RX_TX_ACTIVE;
+       mxc_fec_reg_write(hw_reg, rdar, mxc_fec_reg_read(hw_reg, rdar) | FEC_RX_TX_ACTIVE);
+       mxc_fec_reg_write(hw_reg, ecr, mxc_fec_reg_read(hw_reg, ecr) | FEC_ETHER_EN);
+#ifdef CYGPKG_HAL_ARM_MX25
+       /*
+        * setup the MII gasket for RMII mode
+        */
+
+       /* disable the gasket */
+       mxc_fec_reg_write16(hw_reg, miigsk_enr, 0);
+
+       /* wait for the gasket to be disabled */
+       while (mxc_fec_reg_read16(hw_reg, miigsk_enr) & MIIGSK_ENR_READY)
+               hal_delay_us(FEC_COMMON_TICK);
+
+       /* configure gasket for RMII, 50 MHz, no loopback, and no echo */
+       mxc_fec_reg_write16(hw_reg, miigsk_cfgr, MIIGSK_CFGR_IF_MODE_RMII);
+
+       /* re-enable the gasket */
+       mxc_fec_reg_write16(hw_reg, miigsk_enr, MIIGSK_ENR_EN);
+
+       /* wait until MII gasket is ready */
+       int max_loops = 10;
+       while ((mxc_fec_reg_read16(hw_reg, miigsk_enr) & MIIGSK_ENR_READY) == 0) {
+               if (--max_loops <= 0) {
+                       diag_printf("WAIT for MII Gasket ready timed out\n");
+                       break;
+               }
+       }
+#endif
 }
 
 /*!
  * This function pauses the FEC controller.
  */
-static void 
+static void
 mxc_fec_stop(struct eth_drv_sc *sc)
 {
-       mxc_fec_priv_t *priv = sc?sc->driver_private:NULL;
-       volatile mxc_fec_reg_t *chip = priv?priv->hw_reg:NULL;
-       if (!(priv && chip)) {
-               diag_printf("BUG[stop]: some fields in driver is NULL\n");
+       mxc_fec_priv_t *priv = sc ? sc->driver_private : NULL;
+       volatile mxc_fec_reg_t *hw_reg = priv ? priv->hw_reg : NULL;
+
+       if (!(priv && hw_reg)) {
+               diag_printf("BUG[stop]: FEC driver not initialized\n");
                return;
        }
-       chip->ecr &= ~FEC_ETHER_EN;
+       mxc_fec_reg_write(hw_reg, ecr, mxc_fec_reg_read(hw_reg, ecr) & ~FEC_ETHER_EN);
 }
 
-static int  
+static int
 mxc_fec_control(struct eth_drv_sc *sc, unsigned long key, void *data, int data_length)
 {
        /*TODO:: Add support */
@@ -284,27 +382,27 @@ mxc_fec_control(struct eth_drv_sc *sc, unsigned long key, void *data, int data_l
 /*!
  * This function checks the status of FEC control.
  */
-static int  
+static int
 mxc_fec_can_send(struct eth_drv_sc *sc)
 {
-       mxc_fec_priv_t *priv = sc?sc->driver_private:NULL;
-       volatile mxc_fec_reg_t *hw_reg = priv?priv->hw_reg:NULL;
+       mxc_fec_priv_t *priv = sc ? sc->driver_private : NULL;
+       volatile mxc_fec_reg_t *hw_reg = priv ? priv->hw_reg : NULL;
 
        if (!(priv && hw_reg)) {
-               diag_printf("BUG[can_send]:the private pointer and register pointer in MXC_FEC is NULL\n");
+               diag_printf("BUG[can_send]: FEC driver not initialized\n");
                return 0;
        }
        if (priv->tx_busy) {
-               diag_printf("WARNING[can_send]: MXC_FEC is busy for transmittinig\n");
+               diag_printf("WARNING[can_send]: MXC_FEC is busy for transmission\n");
                return 0;
        }
 
-       if (!(hw_reg->ecr & FEC_ETHER_EN)) {
+       if (!(mxc_fec_reg_read(hw_reg, ecr) & FEC_ETHER_EN)) {
                diag_printf("WARNING[can_send]: MXC_FEC is not enabled\n");
                return 0;
        }
 
-       if (hw_reg->tcr & FEC_TCR_RFC_PAUSE) {
+       if (mxc_fec_reg_read(hw_reg, tcr) & FEC_TCR_RFC_PAUSE) {
                diag_printf("WARNING[can_send]: MXC_FEC is paused\n");
                return 0;
        }
@@ -339,31 +437,32 @@ mxc_fec_can_send(struct eth_drv_sc *sc)
 /*!
  * This function transmits a frame.
  */
-static void 
+static void
 mxc_fec_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len, int total,
-            unsigned long key)
+                        unsigned long key)
 {
-       mxc_fec_priv_t *dev = sc?sc->driver_private:NULL;
-       volatile mxc_fec_reg_t *hw_reg = dev?dev->hw_reg:NULL;
+       mxc_fec_priv_t *dev = sc ? sc->driver_private : NULL;
+       volatile mxc_fec_reg_t *hw_reg = dev ? dev->hw_reg : NULL;
        mxc_fec_bd_t *p;
        int i, off;
 
-       if ( dev == NULL || hw_reg == NULL) {
-               diag_printf("BUG[TX]: some fields in driver are NULL\n");
+       if (dev == NULL || hw_reg == NULL) {
+               diag_printf("BUG[TX]: FEC driver not initialized\n");
                return;
        }
-       if ( total > (FEC_FRAME_LEN-4)) total = FEC_FRAME_LEN-4;
-       if ( sg_list == NULL || total <= 14 ) {
-               if(sc->funs->eth_drv && sc->funs->eth_drv->tx_done) {
+       if (total > (FEC_FRAME_LEN - 4)) total = FEC_FRAME_LEN - 4;
+       if (sg_list == NULL || total <= 14) {
+               if (sc->funs->eth_drv && sc->funs->eth_drv->tx_done) {
                        sc->funs->eth_drv->tx_done(sc, key, -1);
                }
                return;
-       }       
+       }
 
-       for(i=0, off=0, p = dev->tx_cur; i<sg_len; i++) {
+       for (i = 0, off = 0, p = dev->tx_cur; i < sg_len; i++) {
                unsigned long vaddr;
-               if(p->status & BD_TX_ST_RDY) {
-                       diag_printf("BUG[TX]:MXC_FEC's status=%x\n", p->status);
+
+               if (p->status & BD_TX_ST_RDY) {
+                       diag_printf("BUG[TX]: trying to resend already finished buffer\n");
                        break;
                }
                if (sg_list[i].buf == 0) {
@@ -374,157 +473,169 @@ mxc_fec_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len, int
                memcpy((void *)vaddr, (void *)sg_list[i].buf, sg_list[i].len);
                off += sg_list[i].len;
        }
-       if ( off < 14 ) {
-               diag_printf("WARNING[TX]: data len is %d\n", off);
+       if (off < 14) {
+               diag_printf("WARNING[TX]: packet size %d too small\n", off);
                return;
        }
-       p->length = off; 
-       p->status &= ~(BD_TX_ST_LAST|BD_TX_ST_RDY|BD_TX_ST_TC|BD_TX_ST_ABC);
-       p->status |= BD_TX_ST_LAST| BD_TX_ST_RDY | BD_TX_ST_TC;
-       if(p->status & BD_TX_ST_WRAP ) {
+       p->length = off;
+       //p->status &= ~(BD_TX_ST_LAST | BD_TX_ST_RDY | BD_TX_ST_TC | BD_TX_ST_ABC);
+       p->status &= ~BD_TX_ST_ABC;
+       p->status |= BD_TX_ST_LAST | BD_TX_ST_RDY | BD_TX_ST_TC;
+       if (p->status & BD_TX_ST_WRAP) {
                p = dev->tx_bd;
-       } else p++;
+       } else {
+               p++;
+       }
        dev->tx_cur = p;
        dev->tx_busy = 1;
        dev->tx_key = key;
-       hw_reg->tdar = FEC_RX_TX_ACTIVE;        
+       mxc_fec_reg_write(hw_reg, tdar, FEC_RX_TX_ACTIVE);
 }
 
 /*!
  * This function receives ready Frame in DB.
  */
-static void 
+static void
 mxc_fec_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len)
 {
-        mxc_fec_priv_t * priv = sc?sc->driver_private:NULL;
-       mxc_fec_bd_t * p;
+        mxc_fec_priv_t *priv = sc ? sc->driver_private : NULL;
+       mxc_fec_bd_t *p;
        unsigned long vaddr;
-       if(sg_list == NULL || priv == NULL || sg_len <= 0) {
-               diag_printf("BUG[RX]: driver's private field or argument of this calling is NULL \n");
+
+       if (sg_list == NULL || priv == NULL || sg_len <= 0) {
+               diag_printf("BUG[RX]: FEC driver not initialized\n");
                return;
        }
-       
-       /*TODO: I think if buf pointer is NULL, this function 
+
+       /*TODO: I think if buf pointer is NULL, this function
         * should not be called
         */
-       if(sg_list->buf == 0) {
+       if (sg_list->buf == 0) {
                diag_printf("WARING[RX]: the sg_list is empty\n");
                return;
        }
        p = priv->rx_cur;
-       
-       if(p->status & BD_RX_ST_EMPTY) {
-               diag_printf("BUG[RX]: status =%x\n", p->status);
+
+       if (p->status & BD_RX_ST_EMPTY) {
+               diag_printf("BUG[RX]: empty buffer received; status=%04x\n", p->status);
                return;
        }
 
-       if(!(p->status & BD_RX_ST_LAST)) {
-               diag_printf("BUG[RX]: status =%x\n", p->status);
+       if (!(p->status & BD_RX_ST_LAST)) {
+               diag_printf("BUG[RX]: status=%0xx\n", p->status);
                return;
        }
        vaddr = hal_ioremap_nocache((unsigned long)p->data);
        /*TODO::D_CACHE invalid this data buffer*/
-       memcpy((void *)sg_list->buf, (void *)vaddr, p->length -4);
+       memcpy((void *)sg_list->buf, (void *)vaddr, p->length - 4);
 }
 
-static void 
+static void
 mxc_fec_deliver(struct eth_drv_sc *sc)
 {
-       /*TODO::When redboot support thread , 
+       /*TODO::When redboot support thread ,
         *      the polling function will be called at here
         */
        return;
 }
 
-static void 
-mxc_fec_check_rx_bd(struct eth_drv_sc * sc)
+/* This funtion just called by polling funtion */
+static void
+mxc_fec_check_rx_bd(struct eth_drv_sc *sc)
 {
-       /* This funtion just called by polling funtion*/
-        mxc_fec_priv_t * priv = sc->driver_private;
-       mxc_fec_bd_t * p;
-       volatile mxc_fec_reg_t * hw_reg = priv->hw_reg;
+       mxc_fec_priv_t *priv = sc->driver_private;
+       mxc_fec_bd_t *p;
+       volatile mxc_fec_reg_t *hw_reg = priv->hw_reg;
        int i;
-       
-       for(i = 0, p = priv->rx_cur; i< FEC_RX_FRAMES; i++){
-               /*TODO::D-CACHE invalid this BD.
-               *In WRITE_BACK mode: this maybe destroy the next BD 
-               *       when the CACHE_LINE write back.
-               */
-               if(p->status & BD_RX_ST_EMPTY) {
+
+       for (i = 0, p = priv->rx_cur; i < FEC_RX_FRAMES; i++) {
+               /*
+                * TODO::D-CACHE invalidate this BD.
+                * In WRITE_BACK mode: this may destroy the next BD
+                * when the CACHE_LINE is written back.
+                */
+               if (p->status & BD_RX_ST_EMPTY) {
                        break;
                }
-               if(!(p->status & BD_RX_ST_LAST)) {
-                       diag_printf("BUG[RX]: status=%x, length=%x\n", p->status, p->length);
+               if (!(p->status & BD_RX_ST_LAST)) {
+                       diag_printf("BUG[RX]: status=%04x, length=%x\n", p->status, p->length);
                        goto skip_next;
                }
-               
-               if((p->status & BD_RX_ST_ERRS)|| (p->length > FEC_FRAME_LEN)) {
-                       diag_printf("BUG[RX]: status=%x, length=%x\n", p->status, p->length);
+
+               if (p->status & BD_RX_ST_ERRS) {
+                       diag_printf("RX error: status=%08x errors=%08x\n", p->status,
+                                               p->status & BD_RX_ST_ERRS);
+               } else if (p->length > FEC_FRAME_LEN) {
+                       diag_printf("RX error: packet size 0x%08x larger than max frame length: 0x%08x\n",
+                                               p->length, FEC_FRAME_LEN);
                } else {
-                       sc->funs->eth_drv->recv(sc, p->length -4);
+                       sc->funs->eth_drv->recv(sc, p->length - 4);
                }
 skip_next:
                p->status = (p->status & BD_RX_ST_WRAP) | BD_RX_ST_EMPTY;
-               
-               if ( p->status & BD_RX_ST_WRAP) {
+
+               if (p->status & BD_RX_ST_WRAP) {
                        p = priv->rx_bd;
                } else {
                        p++;
-               } 
-               priv->rx_cur = p;       
-               hw_reg->ecr |= FEC_ETHER_EN;
-               hw_reg->rdar |= FEC_RX_TX_ACTIVE;
+               }
+               priv->rx_cur = p;
+               mxc_fec_reg_write(hw_reg, rdar, mxc_fec_reg_read(hw_reg, rdar) | FEC_RX_TX_ACTIVE);
        }
 }
 
 /*!
  * This function checks the event of FEC controller
  */
-static void 
-mxc_fec_poll(struct eth_drv_sc * sc)
+static void
+mxc_fec_poll(struct eth_drv_sc *sc)
 {
-       mxc_fec_priv_t * priv = sc?sc->driver_private:NULL;
-        volatile mxc_fec_reg_t * hw_reg = priv?priv->hw_reg:NULL;
-        unsigned long value;
+       mxc_fec_priv_t *priv = sc ? sc->driver_private : NULL;
+       volatile mxc_fec_reg_t *hw_reg = priv ? priv->hw_reg : NULL;
+       unsigned long value;
+       int dbg = net_debug;
 
-       if ( priv == NULL || hw_reg == NULL) {
-               diag_printf("BUG[POLL]: some fields in driver are NULL\n");
+       if (priv == NULL || hw_reg == NULL) {
+               diag_printf("BUG[POLL]: FEC driver not initialized\n");
                return;
        }
-       value = hw_reg->eir;
-       hw_reg->eir = value & (~FEC_EVENT_MII);
-       
-       if(value&FEC_EVENT_TX_ERR) {
-               diag_printf("WARNING[POLL]: There are errors(%lu) for transmit\n",
-                           value&FEC_EVENT_TX_ERR);
+#if 1
+       net_debug = 0;
+#endif
+       value = mxc_fec_reg_read(hw_reg, eir);
+       mxc_fec_reg_write(hw_reg, eir, value & ~FEC_EVENT_MII);
+#if 1
+       net_debug = dbg;
+#endif
+       if (value & FEC_EVENT_TX_ERR) {
+               diag_printf("WARNING[POLL]: Transmit error\n");
                sc->funs->eth_drv->tx_done(sc, priv->tx_key, -1);
                priv->tx_busy = 0;
        } else {
-               if(value&FEC_EVENT_TX) {
-                       sc->funs->eth_drv->tx_done(sc,  priv->tx_key, 0);
+               if (value & FEC_EVENT_TX) {
+                       sc->funs->eth_drv->tx_done(sc, priv->tx_key, 0);
                        priv->tx_busy = 0;
                }
        }
-       
-       if(value&FEC_EVENT_RX) {
+
+       if (value & FEC_EVENT_RX) {
                mxc_fec_check_rx_bd(sc);
        }
 
-       if(value & FEC_EVENT_HBERR) {
+       if (value & FEC_EVENT_HBERR) {
                diag_printf("WARNGING[POLL]: Hearbeat error!\n");
        }
 
-       if(value & FEC_EVENT_EBERR) {
+       if (value & FEC_EVENT_EBERR) {
                diag_printf("WARNING[POLL]: Ethernet Bus Error!\n");
        }
 }
 
-
 static int
 mxc_fec_int_vector(struct eth_drv_sc *sc)
 {
        /*TODO::
-        *      get FEC interrupt number        
+        *      get FEC interrupt number
         */
        return -1;
 }
@@ -533,70 +644,79 @@ mxc_fec_int_vector(struct eth_drv_sc *sc)
  * The function initializes the description buffer for receiving or transmitting
  */
 static void
-mxc_fec_bd_init(mxc_fec_priv_t * dev)
+mxc_fec_bd_init(mxc_fec_priv_t *dev)
 {
        int i;
-       mxc_fec_bd_t * p;
+       mxc_fec_bd_t *p;
 
        p = dev->rx_bd = (void *)hal_ioremap_nocache(hal_virt_to_phy((unsigned long)mxc_fec_rx_bd));
-       for(i=0; i<FEC_BD_RX_NUM; i++, p++){
+       for (i = 0; i < FEC_BD_RX_NUM; i++, p++) {
                p->status = BD_RX_ST_EMPTY;
                p->length = 0;
                p->data = (void *)hal_virt_to_phy((unsigned long)mxc_fec_rx_buf[i]);
        }
 
-       dev->rx_bd[i-1].status |= BD_RX_ST_WRAP;
+       dev->rx_bd[i - 1].status |= BD_RX_ST_WRAP;
        dev->rx_cur = dev->rx_bd;
 
-        p = dev->tx_bd = (void *)hal_ioremap_nocache(hal_virt_to_phy((unsigned long)mxc_fec_tx_bd));
-        for(i=0; i<FEC_BD_TX_NUM; i++, p++){
-                p->status = 0;
-                p->length = 0;
-                p->data = (void *)hal_virt_to_phy((unsigned long)mxc_fec_tx_buf[i]);
-        }
+       p = dev->tx_bd = (void *)hal_ioremap_nocache(hal_virt_to_phy((unsigned long)mxc_fec_tx_bd));
+       for (i = 0; i < FEC_BD_TX_NUM; i++, p++) {
+               p->status = 0;
+               p->length = 0;
+               p->data = (void *)hal_virt_to_phy((unsigned long)mxc_fec_tx_buf[i]);
+       }
 
-        dev->tx_bd[i-1].status |= BD_TX_ST_WRAP;
+       dev->tx_bd[i - 1].status |= BD_TX_ST_WRAP;
        dev->tx_cur = dev->tx_bd;
-       
+
        /*TODO:: add the sync function for items*/
 }
 
 /*!
- *This function initializes FEC controller. 
+ *This function initializes FEC controller.
  */
-static void 
-mxc_fec_chip_init(mxc_fec_priv_t * dev)
+static void
+mxc_fec_chip_init(mxc_fec_priv_t *dev)
 {
-       volatile mxc_fec_reg_t * chip = dev->hw_reg;
+       volatile mxc_fec_reg_t *hw_reg = dev->hw_reg;
        unsigned long ipg_clk;
 
-       chip->ecr = FEC_RESET;
-       while(chip->ecr & FEC_RESET) {
+       mxc_fec_reg_write(hw_reg, ecr, mxc_fec_reg_read(hw_reg, ecr) | FEC_RESET);
+       while (mxc_fec_reg_read(hw_reg, ecr) & FEC_RESET) {
                hal_delay_us(FEC_COMMON_TICK);
        }
 
-       chip->eimr = 0x00000000;
-       chip->eir = 0xFFFFFFFF;
-       
-       chip->rcr = (chip->rcr&~(0x0000003F))|FEC_RCR_FCE|FEC_RCR_MII_MODE;
-       chip->tcr |= FEC_TCR_FDEN;
-       chip->mibc |= FEC_MIB_DISABLE;
-       
-       chip->iaur = 0;
-       chip->ialr = 0;
-       chip->gaur = 0;
-       chip->galr = 0;
+       mxc_fec_reg_write(hw_reg, eimr, 0);
+       mxc_fec_reg_write(hw_reg, eir, ~0);
+
+       mxc_fec_reg_write(hw_reg, rcr,
+                                         (mxc_fec_reg_read(hw_reg, rcr) & ~0x3F) |
+                                         FEC_RCR_FCE | FEC_RCR_MII_MODE);
+
+       mxc_fec_reg_write(hw_reg, tcr, mxc_fec_reg_read(hw_reg, tcr) | FEC_TCR_FDEN);
+       mxc_fec_reg_write(hw_reg, mibc, mxc_fec_reg_read(hw_reg, mibc) | FEC_MIB_DISABLE);
+
+       mxc_fec_reg_write(hw_reg, iaur, 0);
+       mxc_fec_reg_write(hw_reg, ialr, 0);
+       mxc_fec_reg_write(hw_reg, gaur, 0);
+       mxc_fec_reg_write(hw_reg, galr, 0);
 
-       /*TODO:: Use MII_SPEED(IPG_CLK) to get the value*/ 
        ipg_clk = get_main_clock(IPG_CLK);
-       
-       chip->mscr = (chip->mscr & 0x7e) | (((ipg_clk + 499999) / 2500000 / 2) << 1);
-       if (net_debug) diag_printf("mscr set to %08lx for ipg_clk %ld\n", chip->mscr,
-                                  ipg_clk);
-       /*Enable ETHER_EN*/
-       chip->emrbr = 2048-16;
-       chip->erdsr = hal_virt_to_phy((unsigned long)dev->rx_bd);
-       chip->etdsr = hal_virt_to_phy((unsigned long)dev->tx_bd);
+
+       mxc_fec_reg_write(hw_reg, mscr,
+                                         (mxc_fec_reg_read(hw_reg, mscr) & ~0x7e) |
+                                         (((ipg_clk + 499999) / 2500000 / 2) << 1));
+       if (net_debug) diag_printf("mscr set to %08lx for ipg_clk %ld\n",
+                                  mxc_fec_reg_read(hw_reg, mscr), ipg_clk);
+
+       mxc_fec_reg_write(hw_reg, emrbr, 2048 - 16);
+       mxc_fec_reg_write(hw_reg, erdsr, hal_virt_to_phy((unsigned long)dev->rx_bd));
+       mxc_fec_reg_write(hw_reg, etdsr, hal_virt_to_phy((unsigned long)dev->tx_bd));
+
+       /* must be done before enabling the MII gasket
+        * (otherwise MIIGSK_ENR_READY will never assert)
+        */
+       mxc_fec_reg_write(hw_reg, ecr, mxc_fec_reg_read(hw_reg, ecr) | FEC_ETHER_EN);
 }
 
 static void mxc_fec_phy_status(mxc_fec_priv_t *dev, unsigned short value, bool show)
@@ -641,7 +761,7 @@ static void mxc_fec_phy_status(mxc_fec_priv_t *dev, unsigned short value, bool s
                return;
        }
        if (dev->status & FEC_STATUS_LINK_ON) {
-               diag_printf("FEC: [ %s ] [ %s ]:\n", 
+               diag_printf("FEC: [ %s ] [ %s ]:\n",
                            (dev->status & FEC_STATUS_FULL_DPLX) ? "FULL_DUPLEX" : "HALF_DUPLEX",
                            (dev->status & FEC_STATUS_100M) ? "100 Mbps" : "10 Mbps");
        } else {
@@ -651,13 +771,15 @@ static void mxc_fec_phy_status(mxc_fec_priv_t *dev, unsigned short value, bool s
 
 #ifndef CYGPKG_DEVS_ETH_PHY
 /*!
- * This function initialize PHY
+ * This function initializes the PHY
  */
 static bool
 mxc_fec_phy_init(mxc_fec_priv_t *dev)
 {
+#if 1
        unsigned short value = 0;
-       unsigned long timeout=FEC_COMMON_TIMEOUT;
+       unsigned long timeout = FEC_COMMON_TIMEOUT;
+
        /*Reset PHY*/
        mxc_fec_mii_write(dev->hw_reg, dev->phy_addr, PHY_CTRL_REG, PHY_CTRL_RESET);
        while (timeout--) {
@@ -665,7 +787,7 @@ mxc_fec_phy_init(mxc_fec_priv_t *dev)
                        return false;
                }
 
-               if(!(value & PHY_CTRL_RESET)) {
+               if (!(value & PHY_CTRL_RESET)) {
                        if (net_debug) diag_printf("%s: FEC reset completed\n", __FUNCTION__);
                        break;
                }
@@ -682,7 +804,7 @@ mxc_fec_phy_init(mxc_fec_priv_t *dev)
        id = (value & PHY_ID1_MASK) << PHY_ID1_SHIFT;
        mxc_fec_mii_read(dev->hw_reg, dev->phy_addr, PHY_IDENTIFY_2, &value);
        id |= (value & PHY_ID2_MASK) << PHY_ID2_SHIFT;
-       ifid == 0 || id == 0xffffffff) {
+       if (id == 0 || id == 0xffffffff) {
                diag_printf("FEC could not identify PHY: ID=%08lx\n", id);
                return false;
        }
@@ -700,9 +822,100 @@ mxc_fec_phy_init(mxc_fec_priv_t *dev)
                hal_delay_us(FEC_MII_TICK);
        }
        mxc_fec_mii_read(dev->hw_reg, dev->phy_addr, PHY_MODE_REG, &value);
-       value &= ~(PHY_LED_SEL);
+       value &= ~PHY_LED_SEL;
        mxc_fec_mii_write(dev->hw_reg, dev->phy_addr, PHY_MODE_REG, value);
+#else
+       unsigned long value = 0;
+       unsigned long id = 0, timeout = 50;
+
+       mxc_fec_mii_read(dev->hw_reg, dev->phy_addr, PHY_IDENTIFY_1, &value);
+       id = (value & PHY_ID1_MASK) << PHY_ID1_SHIFT;
+       mxc_fec_mii_read(dev->hw_reg, dev->phy_addr, PHY_IDENTIFY_2, &value);
+       id |= (value & PHY_ID2_MASK) << PHY_ID2_SHIFT;
+
+       switch (id) {
+       case 0x00540088:
+               break;
+       case 0x00007C0C:
+               break;
+       default:
+               diag_printf("[Warning] FEC not connect right PHY: ID=%lx\n", id);
+       }
+
+       mxc_fec_mii_write(dev->hw_reg, dev->phy_addr, PHY_CTRL_REG, PHY_CTRL_AUTO_NEG|PHY_CTRL_FULL_DPLX);
+
+#ifdef CYGPKG_HAL_ARM_MX27ADS
+       mxc_fec_mii_read(dev->hw_reg, dev->phy_addr, PHY_MODE_REG, &value);
+       value &= ~PHY_LED_SEL;
+       mxc_fec_mii_write(dev->hw_reg, dev->phy_addr, PHY_MODE_REG, value);
+#endif
+
+#if defined(CYGPKG_HAL_ARM_MX51) || defined (CYGPKG_HAL_ARM_MX25_3STACK) || defined (CYGPKG_HAL_ARM_MX35_3STACK) || defined (CYGPKG_HAL_ARM_MX27_3STACK)
+       mxc_fec_mii_read(dev->hw_reg, dev->phy_addr, PHY_AUTO_NEG_EXP_REG, &value);
+       /* Wait for packet to arrive */
+       while (((value & PHY_AUTO_NEG_NEW_PAGE) == 0) && (timeout != 0)) {
+               hal_delay_us(100);
+               mxc_fec_mii_read(dev->hw_reg, dev->phy_addr, PHY_AUTO_NEG_EXP_REG, &value);
+               timeout--;
+       }
+       /* Check if link is capable of auto-negotiation */
+       if ((value & PHY_AUTO_NEG_CAP) == 1) {
+               mxc_fec_mii_read(dev->hw_reg, dev->phy_addr, PHY_INT_SRC_REG, &value);
+               timeout = 50;
+               /* Wait for auto-negotiation to complete */
+               while (((value & PHY_INT_AUTO_NEG) == 0) && (timeout != 0)) {
+                       hal_delay_us(100);
+                       mxc_fec_mii_read(dev->hw_reg, dev->phy_addr, PHY_INT_SRC_REG, &value);
+                       timeout--;
+               }
+       }
+#endif
+       mxc_fec_mii_read(dev->hw_reg, dev->phy_addr, PHY_STATUS_REG, &value);
+       if (value & PHY_STATUS_LINK_ST) {
+               dev->status |= FEC_STATUS_LINK_ON;
+       } else {
+               dev->status &= ~FEC_STATUS_LINK_ON;
+       }
+
+#ifdef CYGPKG_HAL_ARM_MX27ADS
+       mxc_fec_mii_read(dev->hw_reg, dev->phy_addr, PHY_DIAG_REG, &value);
+       if (value & PHY_DIAG_DPLX) {
+               dev->status |= FEC_STATUS_FULL_DPLX;
+       } else {
+               dev->status &= ~FEC_STATUS_FULL_DPLX;
+       }
+       if (value & PHY_DIAG_DPLX) {
+               dev->status |= FEC_STATUS_100M;
+        } else {
+               dev->status &= ~FEC_STATUS_100M;
+       }
+#endif
+
+#if defined(CYGPKG_HAL_ARM_MX51) || defined (CYGPKG_HAL_ARM_MX25_3STACK) || defined (CYGPKG_HAL_ARM_MX35_3STACK)
+       mxc_fec_mii_read(dev->hw_reg, dev->phy_addr, PHY_AUTO_NEG_REG, &value);
+       if (value & PHY_AUTO_10BASET) {
+               dev->status &= ~FEC_STATUS_100M;
+               if (value & PHY_AUTO_10BASET_DPLX) {
+                       dev->status |= FEC_STATUS_FULL_DPLX;
+               } else {
+                       dev->status &= ~FEC_STATUS_FULL_DPLX;
+               }
+       }
 
+       if (value & PHY_AUTO_100BASET) {
+               dev->status |= FEC_STATUS_100M;
+               if (value & PHY_AUTO_100BASET_DPLX) {
+                       dev->status |= FEC_STATUS_FULL_DPLX;
+               } else {
+                       dev->status &= ~FEC_STATUS_FULL_DPLX;
+               }
+       }
+#endif
+       diag_printf("FEC: [ %s ] [ %s ] [ %s ]:\n",
+               (dev->status&FEC_STATUS_FULL_DPLX)?"FULL_DUPLEX":"HALF_DUPLEX",
+               (dev->status&FEC_STATUS_LINK_ON)?"connected":"disconnected",
+               (dev->status&FEC_STATUS_100M)?"100M bps":"10M bps");
+#endif
        return true;
 }
 
@@ -743,7 +956,7 @@ static int mxc_fec_discover_phy(mxc_fec_priv_t *fep, unsigned char def_addr)
        }
        if (id == 0) {
                /* Disable MII */
-               fep->hw_reg->mscr = 0;
+               fep->mxc_fec_reg_write(hw_reg, mscr, 0);
                ret = -1;
        }
 
@@ -760,7 +973,7 @@ void mxc_fec_phy_reset(void)
        unsigned long timeout=FEC_COMMON_TIMEOUT;
        mxc_fec_priv_t *dev = &mxc_fec_private;
 
-       /*Reset PHY*/
+       /* Reset PHY */
        if (net_debug) diag_printf("%s\n", __FUNCTION__);
 
        _eth_phy_write(dev->phy, PHY_CTRL_REG, dev->phy->phy_addr, PHY_CTRL_RESET);
@@ -769,7 +982,7 @@ void mxc_fec_phy_reset(void)
                        return;
                }
 
-               if(!(value & PHY_CTRL_RESET)) {
+               if (!(value & PHY_CTRL_RESET)) {
                        if (net_debug) diag_printf("%s: FEC reset completed\n", __FUNCTION__);
                        break;
                }
@@ -801,36 +1014,47 @@ void mxc_fec_phy_write(int reg, int unit, unsigned short data)
        mxc_fec_mii_write(mxc_fec_private.hw_reg, unit, reg, data);
 }
 
-/*! This function initializes the FEC driver. 
+/*! This function initializes the FEC driver.
  * It is called by net_init in net module of RedBoot during RedBoot init
  */
-static bool 
+static bool
 mxc_fec_init(struct cyg_netdevtab_entry *tab)
 {
-       struct eth_drv_sc * sc = tab ? tab->device_instance : NULL;
-       mxc_fec_priv_t * private;
-       char eth_add_local[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+       struct eth_drv_sc *sc = tab ? tab->device_instance : NULL;
+       mxc_fec_priv_t *private;
+       unsigned char eth_add_local[ETHER_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+       int ok = 0;
 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
        cyg_bool set_esa;
-       int ok;
-
-       /* Get MAC address */
-       ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
-                                        "fec_esa", &set_esa, CONFIG_BOOL);
-       if (ok && set_esa) {
-               CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
-                                           "fec_esa_data", eth_add_local, CONFIG_ESA);
-       }
 #endif
+
        if (net_debug)  diag_printf("%s:\n", __FUNCTION__);
-       if (sc == NULL){
+       if (sc == NULL) {
                diag_printf("%s: no driver attached\n", __FUNCTION__);
                return false;
-       } 
-       
+       }
+
        private = MXC_FEC_PRIVATE(sc);
        if (private == NULL) {
-               private = MXC_FEC_PRIVATE(sc) = &mxc_fec_private;
+               private = &mxc_fec_private;
+       }
+       if (private->provide_esa) {
+               ok = private->provide_esa(eth_add_local);
+       }
+#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
+       if (!ok) {
+               /* Get MAC address from fconfig */
+               ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
+                                                                                "fec_esa", &set_esa, CONFIG_BOOL);
+               if (ok && set_esa) {
+                       CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,
+                                                                               "fec_esa_data", eth_add_local, CONFIG_ESA);
+               }
+       }
+#endif
+       if (!ok) {
+               diag_printf("No ESA provided via fuses or RedBoot config\n");
+               return false;
        }
 
        private->hw_reg = (void *)SOC_FEC_BASE;
@@ -854,21 +1078,21 @@ mxc_fec_init(struct cyg_netdevtab_entry *tab)
        }
        private->phy_addr = ok;
        mxc_fec_phy_init(private);
-#endif 
-       /*TODO:: initialize System Resource : irq, timer */
+#endif
+       /* TODO:: initialize System Resource : irq, timer */
 
        sc->funs->eth_drv->init(sc, eth_add_local);
        mxc_fec_phy_status(private, _eth_phy_state(private->phy), true);
-    
-       return true;
+
+       return true;
 }
 
 #ifndef CYGPKG_DEVS_ETH_PHY
 /*!
- * Global variable which defines the FEC driver, 
+ * Global variable which defines the FEC driver,
  */
 ETH_DRV_SC(mxc_fec_sc,
-          &mxc_fec_private, // Driver specific data
+           &mxc_fec_private, // Driver specific data
            mxc_fec_name,
            mxc_fec_start,
            mxc_fec_stop,
@@ -887,4 +1111,5 @@ NETDEVTAB_ENTRY(mxc_fec_netdev,
                 mxc_fec_name,
                 mxc_fec_init,
                 &mxc_fec_sc);
-#endif
+
+#endif // CYGPKG_DEVS_ETH_PHY