]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/net/fec_mxc.c
FEC: Abstract access to fec->eth in MII operations
[karo-tx-uboot.git] / drivers / net / fec_mxc.c
1 /*
2  * (C) Copyright 2009 Ilya Yanok, Emcraft Systems Ltd <yanok@emcraft.com>
3  * (C) Copyright 2008,2009 Eric Jarrige <eric.jarrige@armadeus.org>
4  * (C) Copyright 2008 Armadeus Systems nc
5  * (C) Copyright 2007 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
6  * (C) Copyright 2007 Pengutronix, Juergen Beisert <j.beisert@pengutronix.de>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 #include <common.h>
25 #include <malloc.h>
26 #include <net.h>
27 #include <miiphy.h>
28 #include "fec_mxc.h"
29
30 #include <asm/arch/clock.h>
31 #include <asm/arch/imx-regs.h>
32 #include <asm/io.h>
33 #include <asm/errno.h>
34
35 DECLARE_GLOBAL_DATA_PTR;
36
37 #ifndef CONFIG_MII
38 #error "CONFIG_MII has to be defined!"
39 #endif
40
41 #ifndef CONFIG_FEC_XCV_TYPE
42 #define CONFIG_FEC_XCV_TYPE     MII100
43 #endif
44
45 #undef DEBUG
46
47 struct nbuf {
48         uint8_t data[1500];     /**< actual data */
49         int length;             /**< actual length */
50         int used;               /**< buffer in use or not */
51         uint8_t head[16];       /**< MAC header(6 + 6 + 2) + 2(aligned) */
52 };
53
54 struct fec_priv gfec = {
55         .eth       = (struct ethernet_regs *)IMX_FEC_BASE,
56         .xcv_type  = MII100,
57         .rbd_base  = NULL,
58         .rbd_index = 0,
59         .tbd_base  = NULL,
60         .tbd_index = 0,
61         .bd        = NULL,
62         .rdb_ptr   = NULL,
63         .base_ptr  = NULL,
64 };
65
66 /*
67  * MII-interface related functions
68  */
69 static int fec_miiphy_read(const char *dev, uint8_t phyAddr, uint8_t regAddr,
70                 uint16_t *retVal)
71 {
72         struct eth_device *edev = eth_get_dev_by_name(dev);
73         struct fec_priv *fec = (struct fec_priv *)edev->priv;
74         struct ethernet_regs *eth = fec->eth;
75
76         uint32_t reg;           /* convenient holder for the PHY register */
77         uint32_t phy;           /* convenient holder for the PHY */
78         uint32_t start;
79
80         /*
81          * reading from any PHY's register is done by properly
82          * programming the FEC's MII data register.
83          */
84         writel(FEC_IEVENT_MII, &eth->ievent);
85         reg = regAddr << FEC_MII_DATA_RA_SHIFT;
86         phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
87
88         writel(FEC_MII_DATA_ST | FEC_MII_DATA_OP_RD | FEC_MII_DATA_TA |
89                         phy | reg, &eth->mii_data);
90
91         /*
92          * wait for the related interrupt
93          */
94         start = get_timer(0);
95         while (!(readl(&eth->ievent) & FEC_IEVENT_MII)) {
96                 if (get_timer(start) > (CONFIG_SYS_HZ / 1000)) {
97                         printf("Read MDIO failed...\n");
98                         return -1;
99                 }
100         }
101
102         /*
103          * clear mii interrupt bit
104          */
105         writel(FEC_IEVENT_MII, &eth->ievent);
106
107         /*
108          * it's now safe to read the PHY's register
109          */
110         *retVal = readl(&eth->mii_data);
111         debug("fec_miiphy_read: phy: %02x reg:%02x val:%#x\n", phyAddr,
112                         regAddr, *retVal);
113         return 0;
114 }
115
116 static void fec_mii_setspeed(struct fec_priv *fec)
117 {
118         /*
119          * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock
120          * and do not drop the Preamble.
121          */
122         writel((((imx_get_fecclk() / 1000000) + 2) / 5) << 1,
123                         &fec->eth->mii_speed);
124         debug("fec_init: mii_speed %#lx\n",
125                         readl(&fec->eth->mii_speed));
126 }
127 static int fec_miiphy_write(const char *dev, uint8_t phyAddr, uint8_t regAddr,
128                 uint16_t data)
129 {
130         struct eth_device *edev = eth_get_dev_by_name(dev);
131         struct fec_priv *fec = (struct fec_priv *)edev->priv;
132         struct ethernet_regs *eth = fec->eth;
133
134         uint32_t reg;           /* convenient holder for the PHY register */
135         uint32_t phy;           /* convenient holder for the PHY */
136         uint32_t start;
137
138         reg = regAddr << FEC_MII_DATA_RA_SHIFT;
139         phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
140
141         writel(FEC_MII_DATA_ST | FEC_MII_DATA_OP_WR |
142                 FEC_MII_DATA_TA | phy | reg | data, &eth->mii_data);
143
144         /*
145          * wait for the MII interrupt
146          */
147         start = get_timer(0);
148         while (!(readl(&eth->ievent) & FEC_IEVENT_MII)) {
149                 if (get_timer(start) > (CONFIG_SYS_HZ / 1000)) {
150                         printf("Write MDIO failed...\n");
151                         return -1;
152                 }
153         }
154
155         /*
156          * clear MII interrupt bit
157          */
158         writel(FEC_IEVENT_MII, &eth->ievent);
159         debug("fec_miiphy_write: phy: %02x reg:%02x val:%#x\n", phyAddr,
160                         regAddr, data);
161
162         return 0;
163 }
164
165 static int miiphy_restart_aneg(struct eth_device *dev)
166 {
167         /*
168          * Wake up from sleep if necessary
169          * Reset PHY, then delay 300ns
170          */
171 #ifdef CONFIG_MX27
172         miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, MII_DCOUNTER, 0x00FF);
173 #endif
174         miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, MII_BMCR,
175                         BMCR_RESET);
176         udelay(1000);
177
178         /*
179          * Set the auto-negotiation advertisement register bits
180          */
181         miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, MII_ADVERTISE,
182                         LPA_100FULL | LPA_100HALF | LPA_10FULL |
183                         LPA_10HALF | PHY_ANLPAR_PSB_802_3);
184         miiphy_write(dev->name, CONFIG_FEC_MXC_PHYADDR, MII_BMCR,
185                         BMCR_ANENABLE | BMCR_ANRESTART);
186
187         return 0;
188 }
189
190 static int miiphy_wait_aneg(struct eth_device *dev)
191 {
192         uint32_t start;
193         uint16_t status;
194
195         /*
196          * Wait for AN completion
197          */
198         start = get_timer(0);
199         do {
200                 if (get_timer(start) > (CONFIG_SYS_HZ * 5)) {
201                         printf("%s: Autonegotiation timeout\n", dev->name);
202                         return -1;
203                 }
204
205                 if (miiphy_read(dev->name, CONFIG_FEC_MXC_PHYADDR,
206                                         MII_BMSR, &status)) {
207                         printf("%s: Autonegotiation failed. status: 0x%04x\n",
208                                         dev->name, status);
209                         return -1;
210                 }
211         } while (!(status & BMSR_LSTATUS));
212
213         return 0;
214 }
215 static int fec_rx_task_enable(struct fec_priv *fec)
216 {
217         writel(1 << 24, &fec->eth->r_des_active);
218         return 0;
219 }
220
221 static int fec_rx_task_disable(struct fec_priv *fec)
222 {
223         return 0;
224 }
225
226 static int fec_tx_task_enable(struct fec_priv *fec)
227 {
228         writel(1 << 24, &fec->eth->x_des_active);
229         return 0;
230 }
231
232 static int fec_tx_task_disable(struct fec_priv *fec)
233 {
234         return 0;
235 }
236
237 /**
238  * Initialize receive task's buffer descriptors
239  * @param[in] fec all we know about the device yet
240  * @param[in] count receive buffer count to be allocated
241  * @param[in] size size of each receive buffer
242  * @return 0 on success
243  *
244  * For this task we need additional memory for the data buffers. And each
245  * data buffer requires some alignment. Thy must be aligned to a specific
246  * boundary each (DB_DATA_ALIGNMENT).
247  */
248 static int fec_rbd_init(struct fec_priv *fec, int count, int size)
249 {
250         int ix;
251         uint32_t p = 0;
252
253         /* reserve data memory and consider alignment */
254         if (fec->rdb_ptr == NULL)
255                 fec->rdb_ptr = malloc(size * count + DB_DATA_ALIGNMENT);
256         p = (uint32_t)fec->rdb_ptr;
257         if (!p) {
258                 puts("fec_mxc: not enough malloc memory\n");
259                 return -ENOMEM;
260         }
261         memset((void *)p, 0, size * count + DB_DATA_ALIGNMENT);
262         p += DB_DATA_ALIGNMENT-1;
263         p &= ~(DB_DATA_ALIGNMENT-1);
264
265         for (ix = 0; ix < count; ix++) {
266                 writel(p, &fec->rbd_base[ix].data_pointer);
267                 p += size;
268                 writew(FEC_RBD_EMPTY, &fec->rbd_base[ix].status);
269                 writew(0, &fec->rbd_base[ix].data_length);
270         }
271         /*
272          * mark the last RBD to close the ring
273          */
274         writew(FEC_RBD_WRAP | FEC_RBD_EMPTY, &fec->rbd_base[ix - 1].status);
275         fec->rbd_index = 0;
276
277         return 0;
278 }
279
280 /**
281  * Initialize transmit task's buffer descriptors
282  * @param[in] fec all we know about the device yet
283  *
284  * Transmit buffers are created externally. We only have to init the BDs here.\n
285  * Note: There is a race condition in the hardware. When only one BD is in
286  * use it must be marked with the WRAP bit to use it for every transmitt.
287  * This bit in combination with the READY bit results into double transmit
288  * of each data buffer. It seems the state machine checks READY earlier then
289  * resetting it after the first transfer.
290  * Using two BDs solves this issue.
291  */
292 static void fec_tbd_init(struct fec_priv *fec)
293 {
294         writew(0x0000, &fec->tbd_base[0].status);
295         writew(FEC_TBD_WRAP, &fec->tbd_base[1].status);
296         fec->tbd_index = 0;
297 }
298
299 /**
300  * Mark the given read buffer descriptor as free
301  * @param[in] last 1 if this is the last buffer descriptor in the chain, else 0
302  * @param[in] pRbd buffer descriptor to mark free again
303  */
304 static void fec_rbd_clean(int last, struct fec_bd *pRbd)
305 {
306         /*
307          * Reset buffer descriptor as empty
308          */
309         if (last)
310                 writew(FEC_RBD_WRAP | FEC_RBD_EMPTY, &pRbd->status);
311         else
312                 writew(FEC_RBD_EMPTY, &pRbd->status);
313         /*
314          * no data in it
315          */
316         writew(0, &pRbd->data_length);
317 }
318
319 static int fec_get_hwaddr(struct eth_device *dev, unsigned char *mac)
320 {
321         imx_get_mac_from_fuse(mac);
322         return !is_valid_ether_addr(mac);
323 }
324
325 static int fec_set_hwaddr(struct eth_device *dev)
326 {
327         uchar *mac = dev->enetaddr;
328         struct fec_priv *fec = (struct fec_priv *)dev->priv;
329
330         writel(0, &fec->eth->iaddr1);
331         writel(0, &fec->eth->iaddr2);
332         writel(0, &fec->eth->gaddr1);
333         writel(0, &fec->eth->gaddr2);
334
335         /*
336          * Set physical address
337          */
338         writel((mac[0] << 24) + (mac[1] << 16) + (mac[2] << 8) + mac[3],
339                         &fec->eth->paddr1);
340         writel((mac[4] << 24) + (mac[5] << 16) + 0x8808, &fec->eth->paddr2);
341
342         return 0;
343 }
344
345 /**
346  * Start the FEC engine
347  * @param[in] dev Our device to handle
348  */
349 static int fec_open(struct eth_device *edev)
350 {
351         struct fec_priv *fec = (struct fec_priv *)edev->priv;
352
353         debug("fec_open: fec_open(dev)\n");
354         /* full-duplex, heartbeat disabled */
355         writel(1 << 2, &fec->eth->x_cntrl);
356         fec->rbd_index = 0;
357
358         /*
359          * Enable FEC-Lite controller
360          */
361         writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_ETHER_EN,
362                 &fec->eth->ecntrl);
363 #if defined(CONFIG_MX25) || defined(CONFIG_MX53)
364         udelay(100);
365         /*
366          * setup the MII gasket for RMII mode
367          */
368
369         /* disable the gasket */
370         writew(0, &fec->eth->miigsk_enr);
371
372         /* wait for the gasket to be disabled */
373         while (readw(&fec->eth->miigsk_enr) & MIIGSK_ENR_READY)
374                 udelay(2);
375
376         /* configure gasket for RMII, 50 MHz, no loopback, and no echo */
377         writew(MIIGSK_CFGR_IF_MODE_RMII, &fec->eth->miigsk_cfgr);
378
379         /* re-enable the gasket */
380         writew(MIIGSK_ENR_EN, &fec->eth->miigsk_enr);
381
382         /* wait until MII gasket is ready */
383         int max_loops = 10;
384         while ((readw(&fec->eth->miigsk_enr) & MIIGSK_ENR_READY) == 0) {
385                 if (--max_loops <= 0) {
386                         printf("WAIT for MII Gasket ready timed out\n");
387                         break;
388                 }
389         }
390 #endif
391
392         miiphy_wait_aneg(edev);
393         miiphy_speed(edev->name, CONFIG_FEC_MXC_PHYADDR);
394         miiphy_duplex(edev->name, CONFIG_FEC_MXC_PHYADDR);
395
396         /*
397          * Enable SmartDMA receive task
398          */
399         fec_rx_task_enable(fec);
400
401         udelay(100000);
402         return 0;
403 }
404
405 static int fec_init(struct eth_device *dev, bd_t* bd)
406 {
407         uint32_t base;
408         struct fec_priv *fec = (struct fec_priv *)dev->priv;
409         uint32_t rcntrl;
410
411         /* Initialize MAC address */
412         fec_set_hwaddr(dev);
413
414         /*
415          * reserve memory for both buffer descriptor chains at once
416          * Datasheet forces the startaddress of each chain is 16 byte
417          * aligned
418          */
419         if (fec->base_ptr == NULL)
420                 fec->base_ptr = malloc((2 + FEC_RBD_NUM) *
421                                 sizeof(struct fec_bd) + DB_ALIGNMENT);
422         base = (uint32_t)fec->base_ptr;
423         if (!base) {
424                 puts("fec_mxc: not enough malloc memory\n");
425                 return -ENOMEM;
426         }
427         memset((void *)base, 0, (2 + FEC_RBD_NUM) *
428                         sizeof(struct fec_bd) + DB_ALIGNMENT);
429         base += (DB_ALIGNMENT-1);
430         base &= ~(DB_ALIGNMENT-1);
431
432         fec->rbd_base = (struct fec_bd *)base;
433
434         base += FEC_RBD_NUM * sizeof(struct fec_bd);
435
436         fec->tbd_base = (struct fec_bd *)base;
437
438         /*
439          * Set interrupt mask register
440          */
441         writel(0x00000000, &fec->eth->imask);
442
443         /*
444          * Clear FEC-Lite interrupt event register(IEVENT)
445          */
446         writel(0xffffffff, &fec->eth->ievent);
447
448
449         /*
450          * Set FEC-Lite receive control register(R_CNTRL):
451          */
452
453         /* Start with frame length = 1518, common for all modes. */
454         rcntrl = PKTSIZE << FEC_RCNTRL_MAX_FL_SHIFT;
455         if (fec->xcv_type == SEVENWIRE)
456                 rcntrl |= FEC_RCNTRL_FCE;
457         else if (fec->xcv_type == RMII)
458                 rcntrl |= FEC_RCNTRL_RMII;
459         else    /* MII mode */
460                 rcntrl |= FEC_RCNTRL_FCE | FEC_RCNTRL_MII_MODE;
461
462         writel(rcntrl, &fec->eth->r_cntrl);
463
464         if (fec->xcv_type == MII10 || fec->xcv_type == MII100)
465                 fec_mii_setspeed(fec);
466
467         /*
468          * Set Opcode/Pause Duration Register
469          */
470         writel(0x00010020, &fec->eth->op_pause);        /* FIXME 0xffff0020; */
471         writel(0x2, &fec->eth->x_wmrk);
472         /*
473          * Set multicast address filter
474          */
475         writel(0x00000000, &fec->eth->gaddr1);
476         writel(0x00000000, &fec->eth->gaddr2);
477
478
479         /* clear MIB RAM */
480         long *mib_ptr = (long *)(IMX_FEC_BASE + 0x200);
481         while (mib_ptr <= (long *)(IMX_FEC_BASE + 0x2FC))
482                 *mib_ptr++ = 0;
483
484         /* FIFO receive start register */
485         writel(0x520, &fec->eth->r_fstart);
486
487         /* size and address of each buffer */
488         writel(FEC_MAX_PKT_SIZE, &fec->eth->emrbr);
489         writel((uint32_t)fec->tbd_base, &fec->eth->etdsr);
490         writel((uint32_t)fec->rbd_base, &fec->eth->erdsr);
491
492         /*
493          * Initialize RxBD/TxBD rings
494          */
495         if (fec_rbd_init(fec, FEC_RBD_NUM, FEC_MAX_PKT_SIZE) < 0) {
496                 free(fec->base_ptr);
497                 fec->base_ptr = NULL;
498                 return -ENOMEM;
499         }
500         fec_tbd_init(fec);
501
502
503         if (fec->xcv_type != SEVENWIRE)
504                 miiphy_restart_aneg(dev);
505
506         fec_open(dev);
507         return 0;
508 }
509
510 /**
511  * Halt the FEC engine
512  * @param[in] dev Our device to handle
513  */
514 static void fec_halt(struct eth_device *dev)
515 {
516         struct fec_priv *fec = &gfec;
517         int counter = 0xffff;
518
519         /*
520          * issue graceful stop command to the FEC transmitter if necessary
521          */
522         writel(FEC_TCNTRL_GTS | readl(&fec->eth->x_cntrl),
523                         &fec->eth->x_cntrl);
524
525         debug("eth_halt: wait for stop regs\n");
526         /*
527          * wait for graceful stop to register
528          */
529         while ((counter--) && (!(readl(&fec->eth->ievent) & FEC_IEVENT_GRA)))
530                 udelay(1);
531
532         /*
533          * Disable SmartDMA tasks
534          */
535         fec_tx_task_disable(fec);
536         fec_rx_task_disable(fec);
537
538         /*
539          * Disable the Ethernet Controller
540          * Note: this will also reset the BD index counter!
541          */
542         writel(readl(&fec->eth->ecntrl) & ~FEC_ECNTRL_ETHER_EN,
543                         &fec->eth->ecntrl);
544         fec->rbd_index = 0;
545         fec->tbd_index = 0;
546         debug("eth_halt: done\n");
547 }
548
549 /**
550  * Transmit one frame
551  * @param[in] dev Our ethernet device to handle
552  * @param[in] packet Pointer to the data to be transmitted
553  * @param[in] length Data count in bytes
554  * @return 0 on success
555  */
556 static int fec_send(struct eth_device *dev, volatile void* packet, int length)
557 {
558         unsigned int status;
559
560         /*
561          * This routine transmits one frame.  This routine only accepts
562          * 6-byte Ethernet addresses.
563          */
564         struct fec_priv *fec = (struct fec_priv *)dev->priv;
565
566         /*
567          * Check for valid length of data.
568          */
569         if ((length > 1500) || (length <= 0)) {
570                 printf("Payload (%d) too large\n", length);
571                 return -1;
572         }
573
574         /*
575          * Setup the transmit buffer
576          * Note: We are always using the first buffer for transmission,
577          * the second will be empty and only used to stop the DMA engine
578          */
579         writew(length, &fec->tbd_base[fec->tbd_index].data_length);
580         writel((uint32_t)packet, &fec->tbd_base[fec->tbd_index].data_pointer);
581         /*
582          * update BD's status now
583          * This block:
584          * - is always the last in a chain (means no chain)
585          * - should transmitt the CRC
586          * - might be the last BD in the list, so the address counter should
587          *   wrap (-> keep the WRAP flag)
588          */
589         status = readw(&fec->tbd_base[fec->tbd_index].status) & FEC_TBD_WRAP;
590         status |= FEC_TBD_LAST | FEC_TBD_TC | FEC_TBD_READY;
591         writew(status, &fec->tbd_base[fec->tbd_index].status);
592
593         /*
594          * Enable SmartDMA transmit task
595          */
596         fec_tx_task_enable(fec);
597
598         /*
599          * wait until frame is sent .
600          */
601         while (readw(&fec->tbd_base[fec->tbd_index].status) & FEC_TBD_READY) {
602                 udelay(1);
603         }
604         debug("fec_send: status 0x%x index %d\n",
605                         readw(&fec->tbd_base[fec->tbd_index].status),
606                         fec->tbd_index);
607         /* for next transmission use the other buffer */
608         if (fec->tbd_index)
609                 fec->tbd_index = 0;
610         else
611                 fec->tbd_index = 1;
612
613         return 0;
614 }
615
616 /**
617  * Pull one frame from the card
618  * @param[in] dev Our ethernet device to handle
619  * @return Length of packet read
620  */
621 static int fec_recv(struct eth_device *dev)
622 {
623         struct fec_priv *fec = (struct fec_priv *)dev->priv;
624         struct fec_bd *rbd = &fec->rbd_base[fec->rbd_index];
625         unsigned long ievent;
626         int frame_length, len = 0;
627         struct nbuf *frame;
628         uint16_t bd_status;
629         uchar buff[FEC_MAX_PKT_SIZE];
630
631         /*
632          * Check if any critical events have happened
633          */
634         ievent = readl(&fec->eth->ievent);
635         writel(ievent, &fec->eth->ievent);
636         debug("fec_recv: ievent 0x%x\n", ievent);
637         if (ievent & FEC_IEVENT_BABR) {
638                 fec_halt(dev);
639                 fec_init(dev, fec->bd);
640                 printf("some error: 0x%08lx\n", ievent);
641                 return 0;
642         }
643         if (ievent & FEC_IEVENT_HBERR) {
644                 /* Heartbeat error */
645                 writel(0x00000001 | readl(&fec->eth->x_cntrl),
646                                 &fec->eth->x_cntrl);
647         }
648         if (ievent & FEC_IEVENT_GRA) {
649                 /* Graceful stop complete */
650                 if (readl(&fec->eth->x_cntrl) & 0x00000001) {
651                         fec_halt(dev);
652                         writel(~0x00000001 & readl(&fec->eth->x_cntrl),
653                                         &fec->eth->x_cntrl);
654                         fec_init(dev, fec->bd);
655                 }
656         }
657
658         /*
659          * ensure reading the right buffer status
660          */
661         bd_status = readw(&rbd->status);
662         debug("fec_recv: status 0x%x\n", bd_status);
663
664         if (!(bd_status & FEC_RBD_EMPTY)) {
665                 if ((bd_status & FEC_RBD_LAST) && !(bd_status & FEC_RBD_ERR) &&
666                         ((readw(&rbd->data_length) - 4) > 14)) {
667                         /*
668                          * Get buffer address and size
669                          */
670                         frame = (struct nbuf *)readl(&rbd->data_pointer);
671                         frame_length = readw(&rbd->data_length) - 4;
672                         /*
673                          *  Fill the buffer and pass it to upper layers
674                          */
675                         memcpy(buff, frame->data, frame_length);
676                         NetReceive(buff, frame_length);
677                         len = frame_length;
678                 } else {
679                         if (bd_status & FEC_RBD_ERR)
680                                 printf("error frame: 0x%08lx 0x%08x\n",
681                                                 (ulong)rbd->data_pointer,
682                                                 bd_status);
683                 }
684                 /*
685                  * free the current buffer, restart the engine
686                  * and move forward to the next buffer
687                  */
688                 fec_rbd_clean(fec->rbd_index == (FEC_RBD_NUM - 1) ? 1 : 0, rbd);
689                 fec_rx_task_enable(fec);
690                 fec->rbd_index = (fec->rbd_index + 1) % FEC_RBD_NUM;
691         }
692         debug("fec_recv: stop\n");
693
694         return len;
695 }
696
697 static int fec_probe(bd_t *bd)
698 {
699         struct eth_device *edev;
700         struct fec_priv *fec = &gfec;
701         unsigned char ethaddr[6];
702
703         /* create and fill edev struct */
704         edev = (struct eth_device *)malloc(sizeof(struct eth_device));
705         if (!edev) {
706                 puts("fec_mxc: not enough malloc memory\n");
707                 return -ENOMEM;
708         }
709         memset(edev, 0, sizeof(*edev));
710         edev->priv = fec;
711         edev->init = fec_init;
712         edev->send = fec_send;
713         edev->recv = fec_recv;
714         edev->halt = fec_halt;
715         edev->write_hwaddr = fec_set_hwaddr;
716
717         fec->eth = (struct ethernet_regs *)IMX_FEC_BASE;
718         fec->bd = bd;
719
720         fec->xcv_type = CONFIG_FEC_XCV_TYPE;
721
722         /* Reset chip. */
723         writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_RESET, &fec->eth->ecntrl);
724         while (readl(&fec->eth->ecntrl) & FEC_ECNTRL_RESET)
725                 udelay(10);
726
727         /*
728          * Set interrupt mask register
729          */
730         writel(0x00000000, &fec->eth->imask);
731
732         /*
733          * Clear FEC-Lite interrupt event register(IEVENT)
734          */
735         writel(0xffffffff, &fec->eth->ievent);
736
737         /*
738          * Set FEC-Lite receive control register(R_CNTRL):
739          */
740         /*
741          * Frame length=1518; MII mode;
742          */
743         writel((PKTSIZE << FEC_RCNTRL_MAX_FL_SHIFT) | FEC_RCNTRL_FCE |
744                 FEC_RCNTRL_MII_MODE, &fec->eth->r_cntrl);
745         fec_mii_setspeed(fec);
746
747         sprintf(edev->name, "FEC");
748
749         miiphy_register(edev->name, fec_miiphy_read, fec_miiphy_write);
750
751         eth_register(edev);
752
753         if (fec_get_hwaddr(edev, ethaddr) == 0) {
754                 printf("got MAC address from fuse: %pM\n", ethaddr);
755                 memcpy(edev->enetaddr, ethaddr, 6);
756         }
757
758         return 0;
759 }
760
761 int fecmxc_initialize(bd_t *bd)
762 {
763         int lout = 1;
764
765         debug("eth_init: fec_probe(bd)\n");
766         lout = fec_probe(bd);
767
768         return lout;
769 }