1 /*
2  * (C) Copyright 2003-2010
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * This file is based on mpc4200fec.c,
6  * (C) Copyright Motorola, Inc., 2000
7  */
8 
9 #include <common.h>
10 #include <mpc8220.h>
11 #include <malloc.h>
12 #include <net.h>
13 #include <miiphy.h>
14 #include "dma.h"
15 #include "fec.h"
16 
17 #undef  DEBUG
18 #if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
19     defined(CONFIG_MPC8220_FEC)
20 
21 #if !(defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
22 #error "CONFIG_MII has to be defined!"
23 #endif
24 
25 #ifdef DEBUG
26 static void tfifo_print (char *devname, mpc8220_fec_priv * fec);
27 static void rfifo_print (char *devname, mpc8220_fec_priv * fec);
28 #endif /* DEBUG */
29 
30 typedef struct {
31 	u8 data[1500];		/* actual data */
32 	int length;		/* actual length */
33 	int used;		/* buffer in use or not */
34 	u8 head[16];		/* MAC header(6 + 6 + 2) + 2(aligned) */
35 } NBUF;
36 
37 int fec8220_miiphy_read (char *devname, u8 phyAddr, u8 regAddr, u16 * retVal);
38 int fec8220_miiphy_write (char *devname, u8 phyAddr, u8 regAddr, u16 data);
39 
40 /********************************************************************/
41 #ifdef DEBUG
mpc8220_fec_phydump(char * devname)42 static void mpc8220_fec_phydump (char *devname)
43 {
44 	u16 phyStatus, i;
45 	u8 phyAddr = CONFIG_PHY_ADDR;
46 	u8 reg_mask[] = {
47 #if CONFIG_PHY_TYPE == 0x79c874 /* AMD Am79C874 */
48 		/* regs to print: 0...7, 16...19, 21, 23, 24 */
49 		1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
50 		1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
51 #else
52 		/* regs to print: 0...8, 16...20 */
53 		1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
54 		1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
55 #endif
56 	};
57 
58 	for (i = 0; i < 32; i++) {
59 		if (reg_mask[i]) {
60 			miiphy_read (devname, phyAddr, i, &phyStatus);
61 			printf ("Mii reg %d: 0x%04x\n", i, phyStatus);
62 		}
63 	}
64 }
65 #endif
66 
67 /********************************************************************/
mpc8220_fec_rbd_init(mpc8220_fec_priv * fec)68 static int mpc8220_fec_rbd_init (mpc8220_fec_priv * fec)
69 {
70 	int ix;
71 	char *data;
72 	static int once = 0;
73 
74 	for (ix = 0; ix < FEC_RBD_NUM; ix++) {
75 		if (!once) {
76 			data = (char *) malloc (FEC_MAX_PKT_SIZE);
77 			if (data == NULL) {
78 				printf ("RBD INIT FAILED\n");
79 				return -1;
80 			}
81 			fec->rbdBase[ix].dataPointer = (u32) data;
82 		}
83 		fec->rbdBase[ix].status = FEC_RBD_EMPTY;
84 		fec->rbdBase[ix].dataLength = 0;
85 	}
86 	once++;
87 
88 	/*
89 	 * have the last RBD to close the ring
90 	 */
91 	fec->rbdBase[ix - 1].status |= FEC_RBD_WRAP;
92 	fec->rbdIndex = 0;
93 
94 	return 0;
95 }
96 
97 /********************************************************************/
mpc8220_fec_tbd_init(mpc8220_fec_priv * fec)98 static void mpc8220_fec_tbd_init (mpc8220_fec_priv * fec)
99 {
100 	int ix;
101 
102 	for (ix = 0; ix < FEC_TBD_NUM; ix++) {
103 		fec->tbdBase[ix].status = 0;
104 	}
105 
106 	/*
107 	 * Have the last TBD to close the ring
108 	 */
109 	fec->tbdBase[ix - 1].status |= FEC_TBD_WRAP;
110 
111 	/*
112 	 * Initialize some indices
113 	 */
114 	fec->tbdIndex = 0;
115 	fec->usedTbdIndex = 0;
116 	fec->cleanTbdNum = FEC_TBD_NUM;
117 }
118 
119 /********************************************************************/
mpc8220_fec_rbd_clean(mpc8220_fec_priv * fec,FEC_RBD * pRbd)120 static void mpc8220_fec_rbd_clean (mpc8220_fec_priv * fec, FEC_RBD * pRbd)
121 {
122 	/*
123 	 * Reset buffer descriptor as empty
124 	 */
125 	if ((fec->rbdIndex) == (FEC_RBD_NUM - 1))
126 		pRbd->status = (FEC_RBD_WRAP | FEC_RBD_EMPTY);
127 	else
128 		pRbd->status = FEC_RBD_EMPTY;
129 
130 	pRbd->dataLength = 0;
131 
132 	/*
133 	 * Now, we have an empty RxBD, restart the SmartDMA receive task
134 	 */
135 	DMA_TASK_ENABLE (FEC_RECV_TASK_NO);
136 
137 	/*
138 	 * Increment BD count
139 	 */
140 	fec->rbdIndex = (fec->rbdIndex + 1) % FEC_RBD_NUM;
141 }
142 
143 /********************************************************************/
mpc8220_fec_tbd_scrub(mpc8220_fec_priv * fec)144 static void mpc8220_fec_tbd_scrub (mpc8220_fec_priv * fec)
145 {
146 	FEC_TBD *pUsedTbd;
147 
148 #ifdef DEBUG
149 	printf ("tbd_scrub: fec->cleanTbdNum = %d, fec->usedTbdIndex = %d\n",
150 		fec->cleanTbdNum, fec->usedTbdIndex);
151 #endif
152 
153 	/*
154 	 * process all the consumed TBDs
155 	 */
156 	while (fec->cleanTbdNum < FEC_TBD_NUM) {
157 		pUsedTbd = &fec->tbdBase[fec->usedTbdIndex];
158 		if (pUsedTbd->status & FEC_TBD_READY) {
159 #ifdef DEBUG
160 			printf ("Cannot clean TBD %d, in use\n",
161 				fec->cleanTbdNum);
162 #endif
163 			return;
164 		}
165 
166 		/*
167 		 * clean this buffer descriptor
168 		 */
169 		if (fec->usedTbdIndex == (FEC_TBD_NUM - 1))
170 			pUsedTbd->status = FEC_TBD_WRAP;
171 		else
172 			pUsedTbd->status = 0;
173 
174 		/*
175 		 * update some indeces for a correct handling of the TBD ring
176 		 */
177 		fec->cleanTbdNum++;
178 		fec->usedTbdIndex = (fec->usedTbdIndex + 1) % FEC_TBD_NUM;
179 	}
180 }
181 
182 /********************************************************************/
mpc8220_fec_set_hwaddr(mpc8220_fec_priv * fec,char * mac)183 static void mpc8220_fec_set_hwaddr (mpc8220_fec_priv * fec, char *mac)
184 {
185 	u8 currByte;		/* byte for which to compute the CRC */
186 	int byte;		/* loop - counter */
187 	int bit;		/* loop - counter */
188 	u32 crc = 0xffffffff;	/* initial value */
189 
190 	/*
191 	 * The algorithm used is the following:
192 	 * we loop on each of the six bytes of the provided address,
193 	 * and we compute the CRC by left-shifting the previous
194 	 * value by one position, so that each bit in the current
195 	 * byte of the address may contribute the calculation. If
196 	 * the latter and the MSB in the CRC are different, then
197 	 * the CRC value so computed is also ex-ored with the
198 	 * "polynomium generator". The current byte of the address
199 	 * is also shifted right by one bit at each iteration.
200 	 * This is because the CRC generatore in hardware is implemented
201 	 * as a shift-register with as many ex-ores as the radixes
202 	 * in the polynomium. This suggests that we represent the
203 	 * polynomiumm itself as a 32-bit constant.
204 	 */
205 	for (byte = 0; byte < 6; byte++) {
206 		currByte = mac[byte];
207 		for (bit = 0; bit < 8; bit++) {
208 			if ((currByte & 0x01) ^ (crc & 0x01)) {
209 				crc >>= 1;
210 				crc = crc ^ 0xedb88320;
211 			} else {
212 				crc >>= 1;
213 			}
214 			currByte >>= 1;
215 		}
216 	}
217 
218 	crc = crc >> 26;
219 
220 	/*
221 	 * Set individual hash table register
222 	 */
223 	if (crc >= 32) {
224 		fec->eth->iaddr1 = (1 << (crc - 32));
225 		fec->eth->iaddr2 = 0;
226 	} else {
227 		fec->eth->iaddr1 = 0;
228 		fec->eth->iaddr2 = (1 << crc);
229 	}
230 
231 	/*
232 	 * Set physical address
233 	 */
234 	fec->eth->paddr1 =
235 		(mac[0] << 24) + (mac[1] << 16) + (mac[2] << 8) + mac[3];
236 	fec->eth->paddr2 = (mac[4] << 24) + (mac[5] << 16) + 0x8808;
237 }
238 
239 /********************************************************************/
mpc8220_fec_init(struct eth_device * dev,bd_t * bis)240 static int mpc8220_fec_init (struct eth_device *dev, bd_t * bis)
241 {
242 	mpc8220_fec_priv *fec = (mpc8220_fec_priv *) dev->priv;
243 	struct mpc8220_dma *dma = (struct mpc8220_dma *) MMAP_DMA;
244 	const u8 phyAddr = CONFIG_PHY_ADDR;	/* Only one PHY */
245 
246 #ifdef DEBUG
247 	printf ("mpc8220_fec_init... Begin\n");
248 #endif
249 
250 	/*
251 	 * Initialize RxBD/TxBD rings
252 	 */
253 	mpc8220_fec_rbd_init (fec);
254 	mpc8220_fec_tbd_init (fec);
255 
256 	/*
257 	 * Set up Pin Muxing for FEC 1
258 	 */
259 	*(vu_long *) MMAP_PCFG = 0;
260 	*(vu_long *) (MMAP_PCFG + 4) = 0;
261 	/*
262 	 * Clear FEC-Lite interrupt event register(IEVENT)
263 	 */
264 	fec->eth->ievent = 0xffffffff;
265 
266 	/*
267 	 * Set interrupt mask register
268 	 */
269 	fec->eth->imask = 0x00000000;
270 
271 	/*
272 	 * Set FEC-Lite receive control register(R_CNTRL):
273 	 */
274 	if (fec->xcv_type == SEVENWIRE) {
275 		/*
276 		 * Frame length=1518; 7-wire mode
277 		 */
278 		fec->eth->r_cntrl = 0x05ee0020; /*0x05ee0000;FIXME */
279 	} else {
280 		/*
281 		 * Frame length=1518; MII mode;
282 		 */
283 		fec->eth->r_cntrl = 0x05ee0024; /*0x05ee0004;FIXME */
284 	}
285 
286 	fec->eth->x_cntrl = 0x00000000; /* half-duplex, heartbeat disabled */
287 	if (fec->xcv_type != SEVENWIRE) {
288 		/*
289 		 * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock
290 		 * and do not drop the Preamble.
291 		 */
292 		/* tbd - rtm */
293 		/*fec->eth->mii_speed = (((gd->ipb_clk >> 20) / 5) << 1); */
294 		/* No MII for 7-wire mode */
295 		fec->eth->mii_speed = 0x00000030;
296 	}
297 
298 	/*
299 	 * Set Opcode/Pause Duration Register
300 	 */
301 	fec->eth->op_pause = 0x00010020;	/*FIXME0xffff0020; */
302 
303 	/*
304 	 * Set Rx FIFO alarm and granularity value
305 	 */
306 	fec->eth->rfifo_cntrl = 0x0c000000;
307 	fec->eth->rfifo_alarm = 0x0000030c;
308 #ifdef DEBUG
309 	if (fec->eth->rfifo_status & 0x00700000) {
310 		printf ("mpc8220_fec_init() RFIFO error\n");
311 	}
312 #endif
313 
314 	/*
315 	 * Set Tx FIFO granularity value
316 	 */
317 	/*fec->eth->tfifo_cntrl = 0x0c000000; */ /*tbd - rtm */
318 	fec->eth->tfifo_cntrl = 0x0e000000;
319 #ifdef DEBUG
320 	printf ("tfifo_status: 0x%08x\n", fec->eth->tfifo_status);
321 	printf ("tfifo_alarm: 0x%08x\n", fec->eth->tfifo_alarm);
322 #endif
323 
324 	/*
325 	 * Set transmit fifo watermark register(X_WMRK), default = 64
326 	 */
327 	fec->eth->tfifo_alarm = 0x00000080;
328 	fec->eth->x_wmrk = 0x2;
329 
330 	/*
331 	 * Set individual address filter for unicast address
332 	 * and set physical address registers.
333 	 */
334 	mpc8220_fec_set_hwaddr (fec, (char *)(dev->enetaddr));
335 
336 	/*
337 	 * Set multicast address filter
338 	 */
339 	fec->eth->gaddr1 = 0x00000000;
340 	fec->eth->gaddr2 = 0x00000000;
341 
342 	/*
343 	 * Turn ON cheater FSM: ????
344 	 */
345 	fec->eth->xmit_fsm = 0x03000000;
346 
347 #if 1
348 /*#if defined(CONFIG_MPC5200)*/
349 	/*
350 	 * Turn off COMM bus prefetch in the MGT5200 BestComm. It doesn't
351 	 * work w/ the current receive task.
352 	 */
353 	dma->PtdCntrl |= 0x00000001;
354 #endif
355 
356 	/*
357 	 * Set priority of different initiators
358 	 */
359 	dma->IPR0 = 7;		/* always */
360 	dma->IPR3 = 6;		/* Eth RX */
361 	dma->IPR4 = 5;		/* Eth Tx */
362 
363 	/*
364 	 * Clear SmartDMA task interrupt pending bits
365 	 */
366 	DMA_CLEAR_IEVENT (FEC_RECV_TASK_NO);
367 
368 	/*
369 	 * Initialize SmartDMA parameters stored in SRAM
370 	 */
371 	*(int *) FEC_TBD_BASE = (int) fec->tbdBase;
372 	*(int *) FEC_RBD_BASE = (int) fec->rbdBase;
373 	*(int *) FEC_TBD_NEXT = (int) fec->tbdBase;
374 	*(int *) FEC_RBD_NEXT = (int) fec->rbdBase;
375 
376 	if (fec->xcv_type != SEVENWIRE) {
377 		/*
378 		 * Initialize PHY(LXT971A):
379 		 *
380 		 *   Generally, on power up, the LXT971A reads its configuration
381 		 *   pins to check for forced operation, If not cofigured for
382 		 *   forced operation, it uses auto-negotiation/parallel detection
383 		 *   to automatically determine line operating conditions.
384 		 *   If the PHY device on the other side of the link supports
385 		 *   auto-negotiation, the LXT971A auto-negotiates with it
386 		 *   using Fast Link Pulse(FLP) Bursts. If the PHY partner does not
387 		 *   support auto-negotiation, the LXT971A automatically detects
388 		 *   the presence of either link pulses(10Mbps PHY) or Idle
389 		 *   symbols(100Mbps) and sets its operating conditions accordingly.
390 		 *
391 		 *   When auto-negotiation is controlled by software, the following
392 		 *   steps are recommended.
393 		 *
394 		 * Note:
395 		 *   The physical address is dependent on hardware configuration.
396 		 *
397 		 */
398 		int timeout = 1;
399 		u16 phyStatus;
400 
401 		/*
402 		 * Reset PHY, then delay 300ns
403 		 */
404 		miiphy_write (dev->name, phyAddr, 0x0, 0x8000);
405 		udelay (1000);
406 
407 		if (fec->xcv_type == MII10) {
408 			/*
409 			 * Force 10Base-T, FDX operation
410 			 */
411 #ifdef DEBUG
412 			printf ("Forcing 10 Mbps ethernet link... ");
413 #endif
414 			miiphy_read (dev->name, phyAddr, 0x1, &phyStatus);
415 			/*
416 			   miiphy_write(fec, phyAddr, 0x0, 0x0100);
417 			 */
418 			miiphy_write (dev->name, phyAddr, 0x0, 0x0180);
419 
420 			timeout = 20;
421 			do {	/* wait for link status to go down */
422 				udelay (10000);
423 				if ((timeout--) == 0) {
424 #ifdef DEBUG
425 					printf ("hmmm, should not have waited...");
426 #endif
427 					break;
428 				}
429 				miiphy_read (dev->name, phyAddr, 0x1, &phyStatus);
430 #ifdef DEBUG
431 				printf ("=");
432 #endif
433 			} while ((phyStatus & 0x0004)); /* !link up */
434 
435 			timeout = 1000;
436 			do {	/* wait for link status to come back up */
437 				udelay (10000);
438 				if ((timeout--) == 0) {
439 					printf ("failed. Link is down.\n");
440 					break;
441 				}
442 				miiphy_read (dev->name, phyAddr, 0x1, &phyStatus);
443 #ifdef DEBUG
444 				printf ("+");
445 #endif
446 			} while (!(phyStatus & 0x0004));	/* !link up */
447 
448 #ifdef DEBUG
449 			printf ("done.\n");
450 #endif
451 		} else {	/* MII100 */
452 			/*
453 			 * Set the auto-negotiation advertisement register bits
454 			 */
455 			miiphy_write (dev->name, phyAddr, 0x4, 0x01e1);
456 
457 			/*
458 			 * Set MDIO bit 0.12 = 1(&& bit 0.9=1?) to enable auto-negotiation
459 			 */
460 			miiphy_write (dev->name, phyAddr, 0x0, 0x1200);
461 
462 			/*
463 			 * Wait for AN completion
464 			 */
465 			timeout = 5000;
466 			do {
467 				udelay (1000);
468 
469 				if ((timeout--) == 0) {
470 #ifdef DEBUG
471 					printf ("PHY auto neg 0 failed...\n");
472 #endif
473 					return -1;
474 				}
475 
476 				if (miiphy_read (dev->name, phyAddr, 0x1, &phyStatus) !=
477 				    0) {
478 #ifdef DEBUG
479 					printf ("PHY auto neg 1 failed 0x%04x...\n", phyStatus);
480 #endif
481 					return -1;
482 				}
483 			} while (!(phyStatus & 0x0004));
484 
485 #ifdef DEBUG
486 			printf ("PHY auto neg complete! \n");
487 #endif
488 		}
489 
490 	}
491 
492 	/*
493 	 * Enable FEC-Lite controller
494 	 */
495 	fec->eth->ecntrl |= 0x00000006;
496 
497 #ifdef DEBUG
498 	if (fec->xcv_type != SEVENWIRE)
499 		mpc8220_fec_phydump (dev->name);
500 #endif
501 
502 	/*
503 	 * Enable SmartDMA receive task
504 	 */
505 	DMA_TASK_ENABLE (FEC_RECV_TASK_NO);
506 
507 #ifdef DEBUG
508 	printf ("mpc8220_fec_init... Done \n");
509 #endif
510 
511 	return 1;
512 }
513 
514 /********************************************************************/
mpc8220_fec_halt(struct eth_device * dev)515 static void mpc8220_fec_halt (struct eth_device *dev)
516 {
517 	mpc8220_fec_priv *fec = (mpc8220_fec_priv *) dev->priv;
518 	int counter = 0xffff;
519 
520 #ifdef DEBUG
521 	if (fec->xcv_type != SEVENWIRE)
522 		mpc8220_fec_phydump (dev->name);
523 #endif
524 
525 	/*
526 	 * mask FEC chip interrupts
527 	 */
528 	fec->eth->imask = 0;
529 
530 	/*
531 	 * issue graceful stop command to the FEC transmitter if necessary
532 	 */
533 	fec->eth->x_cntrl |= 0x00000001;
534 
535 	/*
536 	 * wait for graceful stop to register
537 	 */
538 	while ((counter--) && (!(fec->eth->ievent & 0x10000000)));
539 
540 	/*
541 	 * Disable SmartDMA tasks
542 	 */
543 	DMA_TASK_DISABLE (FEC_XMIT_TASK_NO);
544 	DMA_TASK_DISABLE (FEC_RECV_TASK_NO);
545 
546 	/*
547 	 * Disable the Ethernet Controller
548 	 */
549 	fec->eth->ecntrl &= 0xfffffffd;
550 
551 	/*
552 	 * Clear FIFO status registers
553 	 */
554 	fec->eth->rfifo_status &= 0x00700000;
555 	fec->eth->tfifo_status &= 0x00700000;
556 
557 	fec->eth->reset_cntrl = 0x01000000;
558 
559 	/*
560 	 * Issue a reset command to the FEC chip
561 	 */
562 	fec->eth->ecntrl |= 0x1;
563 
564 	/*
565 	 * wait at least 16 clock cycles
566 	 */
567 	udelay (10);
568 
569 #ifdef DEBUG
570 	printf ("Ethernet task stopped\n");
571 #endif
572 }
573 
574 #ifdef DEBUG
575 /********************************************************************/
576 
tfifo_print(char * devname,mpc8220_fec_priv * fec)577 static void tfifo_print (char *devname, mpc8220_fec_priv * fec)
578 {
579 	u16 phyAddr = CONFIG_PHY_ADDR;
580 	u16 phyStatus;
581 
582 	if ((fec->eth->tfifo_lrf_ptr != fec->eth->tfifo_lwf_ptr)
583 	    || (fec->eth->tfifo_rdptr != fec->eth->tfifo_wrptr)) {
584 
585 		miiphy_read (devname, phyAddr, 0x1, &phyStatus);
586 		printf ("\nphyStatus: 0x%04x\n", phyStatus);
587 		printf ("ecntrl:   0x%08x\n", fec->eth->ecntrl);
588 		printf ("ievent:   0x%08x\n", fec->eth->ievent);
589 		printf ("x_status: 0x%08x\n", fec->eth->x_status);
590 		printf ("tfifo: status	0x%08x\n", fec->eth->tfifo_status);
591 
592 		printf ("	control 0x%08x\n", fec->eth->tfifo_cntrl);
593 		printf ("	lrfp	0x%08x\n", fec->eth->tfifo_lrf_ptr);
594 		printf ("	lwfp	0x%08x\n", fec->eth->tfifo_lwf_ptr);
595 		printf ("	alarm	0x%08x\n", fec->eth->tfifo_alarm);
596 		printf ("	readptr 0x%08x\n", fec->eth->tfifo_rdptr);
597 		printf ("	writptr 0x%08x\n", fec->eth->tfifo_wrptr);
598 	}
599 }
600 
rfifo_print(char * devname,mpc8220_fec_priv * fec)601 static void rfifo_print (char *devname, mpc8220_fec_priv * fec)
602 {
603 	u16 phyAddr = CONFIG_PHY_ADDR;
604 	u16 phyStatus;
605 
606 	if ((fec->eth->rfifo_lrf_ptr != fec->eth->rfifo_lwf_ptr)
607 	    || (fec->eth->rfifo_rdptr != fec->eth->rfifo_wrptr)) {
608 
609 		miiphy_read (devname, phyAddr, 0x1, &phyStatus);
610 		printf ("\nphyStatus: 0x%04x\n", phyStatus);
611 		printf ("ecntrl:   0x%08x\n", fec->eth->ecntrl);
612 		printf ("ievent:   0x%08x\n", fec->eth->ievent);
613 		printf ("x_status: 0x%08x\n", fec->eth->x_status);
614 		printf ("rfifo: status	0x%08x\n", fec->eth->rfifo_status);
615 
616 		printf ("	control 0x%08x\n", fec->eth->rfifo_cntrl);
617 		printf ("	lrfp	0x%08x\n", fec->eth->rfifo_lrf_ptr);
618 		printf ("	lwfp	0x%08x\n", fec->eth->rfifo_lwf_ptr);
619 		printf ("	alarm	0x%08x\n", fec->eth->rfifo_alarm);
620 		printf ("	readptr 0x%08x\n", fec->eth->rfifo_rdptr);
621 		printf ("	writptr 0x%08x\n", fec->eth->rfifo_wrptr);
622 	}
623 }
624 #endif /* DEBUG */
625 
626 /********************************************************************/
627 
mpc8220_fec_send(struct eth_device * dev,volatile void * eth_data,int data_length)628 static int mpc8220_fec_send (struct eth_device *dev, volatile void *eth_data,
629 			     int data_length)
630 {
631 	/*
632 	 * This routine transmits one frame.  This routine only accepts
633 	 * 6-byte Ethernet addresses.
634 	 */
635 	mpc8220_fec_priv *fec = (mpc8220_fec_priv *) dev->priv;
636 	FEC_TBD *pTbd;
637 
638 #ifdef DEBUG
639 	printf ("tbd status: 0x%04x\n", fec->tbdBase[0].status);
640 	tfifo_print (dev->name, fec);
641 #endif
642 
643 	/*
644 	 * Clear Tx BD ring at first
645 	 */
646 	mpc8220_fec_tbd_scrub (fec);
647 
648 	/*
649 	 * Check for valid length of data.
650 	 */
651 	if ((data_length > 1500) || (data_length <= 0)) {
652 		return -1;
653 	}
654 
655 	/*
656 	 * Check the number of vacant TxBDs.
657 	 */
658 	if (fec->cleanTbdNum < 1) {
659 #ifdef DEBUG
660 		printf ("No available TxBDs ...\n");
661 #endif
662 		return -1;
663 	}
664 
665 	/*
666 	 * Get the first TxBD to send the mac header
667 	 */
668 	pTbd = &fec->tbdBase[fec->tbdIndex];
669 	pTbd->dataLength = data_length;
670 	pTbd->dataPointer = (u32) eth_data;
671 	pTbd->status |= FEC_TBD_LAST | FEC_TBD_TC | FEC_TBD_READY;
672 	fec->tbdIndex = (fec->tbdIndex + 1) % FEC_TBD_NUM;
673 
674 #ifdef DEBUG
675 	printf ("DMA_TASK_ENABLE, fec->tbdIndex = %d \n", fec->tbdIndex);
676 #endif
677 
678 	/*
679 	 * Kick the MII i/f
680 	 */
681 	if (fec->xcv_type != SEVENWIRE) {
682 		u16 phyStatus;
683 
684 		miiphy_read (dev->name, 0, 0x1, &phyStatus);
685 	}
686 
687 	/*
688 	 * Enable SmartDMA transmit task
689 	 */
690 
691 #ifdef DEBUG
692 	tfifo_print (dev->name, fec);
693 #endif
694 
695 	DMA_TASK_ENABLE (FEC_XMIT_TASK_NO);
696 
697 #ifdef DEBUG
698 	tfifo_print (dev->name, fec);
699 #endif
700 
701 #ifdef DEBUG
702 	printf ("+");
703 #endif
704 
705 	fec->cleanTbdNum -= 1;
706 
707 #ifdef DEBUG
708 	printf ("smartDMA ethernet Tx task enabled\n");
709 #endif
710 	/*
711 	 * wait until frame is sent .
712 	 */
713 	while (pTbd->status & FEC_TBD_READY) {
714 		udelay (10);
715 #ifdef DEBUG
716 		printf ("TDB status = %04x\n", pTbd->status);
717 #endif
718 	}
719 
720 	return 0;
721 }
722 
723 
724 /********************************************************************/
mpc8220_fec_recv(struct eth_device * dev)725 static int mpc8220_fec_recv (struct eth_device *dev)
726 {
727 	/*
728 	 * This command pulls one frame from the card
729 	 */
730 	mpc8220_fec_priv *fec = (mpc8220_fec_priv *) dev->priv;
731 	FEC_RBD *pRbd = &fec->rbdBase[fec->rbdIndex];
732 	unsigned long ievent;
733 	int frame_length, len = 0;
734 	NBUF *frame;
735 
736 #ifdef DEBUG
737 	printf ("mpc8220_fec_recv %d Start...\n", fec->rbdIndex);
738 	printf ("-");
739 #endif
740 
741 	/*
742 	 * Check if any critical events have happened
743 	 */
744 	ievent = fec->eth->ievent;
745 	fec->eth->ievent = ievent;
746 	if (ievent & 0x20060000) {
747 		/* BABT, Rx/Tx FIFO errors */
748 		mpc8220_fec_halt (dev);
749 		mpc8220_fec_init (dev, NULL);
750 		return 0;
751 	}
752 	if (ievent & 0x80000000) {
753 		/* Heartbeat error */
754 		fec->eth->x_cntrl |= 0x00000001;
755 	}
756 	if (ievent & 0x10000000) {
757 		/* Graceful stop complete */
758 		if (fec->eth->x_cntrl & 0x00000001) {
759 			mpc8220_fec_halt (dev);
760 			fec->eth->x_cntrl &= ~0x00000001;
761 			mpc8220_fec_init (dev, NULL);
762 		}
763 	}
764 
765 	if (!(pRbd->status & FEC_RBD_EMPTY)) {
766 		if ((pRbd->status & FEC_RBD_LAST)
767 		    && !(pRbd->status & FEC_RBD_ERR)
768 		    && ((pRbd->dataLength - 4) > 14)) {
769 
770 			/*
771 			 * Get buffer address and size
772 			 */
773 			frame = (NBUF *) pRbd->dataPointer;
774 			frame_length = pRbd->dataLength - 4;
775 
776 #if (0)
777 			{
778 				int i;
779 
780 				printf ("recv data hdr:");
781 				for (i = 0; i < 14; i++)
782 					printf ("%x ", *(frame->head + i));
783 				printf ("\n");
784 			}
785 #endif
786 			/*
787 			 *  Fill the buffer and pass it to upper layers
788 			 */
789 /*			memcpy(buff, frame->head, 14);
790 			memcpy(buff + 14, frame->data, frame_length);*/
791 			NetReceive ((volatile uchar *) pRbd->dataPointer,
792 				    frame_length);
793 			len = frame_length;
794 		}
795 		/*
796 		 * Reset buffer descriptor as empty
797 		 */
798 		mpc8220_fec_rbd_clean (fec, pRbd);
799 	}
800 	DMA_CLEAR_IEVENT (FEC_RECV_TASK_NO);
801 	return len;
802 }
803 
804 
805 /********************************************************************/
mpc8220_fec_initialize(bd_t * bis)806 int mpc8220_fec_initialize (bd_t * bis)
807 {
808 	mpc8220_fec_priv *fec;
809 
810 #ifdef CONFIG_HAS_ETH1
811 	mpc8220_fec_priv *fec2;
812 #endif
813 	struct eth_device *dev;
814 	char *tmp, *end;
815 	char env_enetaddr[6];
816 
817 #ifdef CONFIG_HAS_ETH1
818 	char env_enet1addr[6];
819 #endif
820 	int i;
821 
822 	fec = (mpc8220_fec_priv *) malloc (sizeof (*fec));
823 	dev = (struct eth_device *) malloc (sizeof (*dev));
824 	memset (dev, 0, sizeof *dev);
825 
826 	fec->eth = (ethernet_regs *) MMAP_FEC1;
827 #ifdef CONFIG_HAS_ETH1
828 	fec2 = (mpc8220_fec_priv *) malloc (sizeof (*fec));
829 	fec2->eth = (ethernet_regs *) MMAP_FEC2;
830 #endif
831 	fec->tbdBase = (FEC_TBD *) FEC_BD_BASE;
832 	fec->rbdBase =
833 		(FEC_RBD *) (FEC_BD_BASE + FEC_TBD_NUM * sizeof (FEC_TBD));
834 	fec->xcv_type = MII100;
835 
836 	dev->priv = (void *) fec;
837 	dev->iobase = MMAP_FEC1;
838 	dev->init = mpc8220_fec_init;
839 	dev->halt = mpc8220_fec_halt;
840 	dev->send = mpc8220_fec_send;
841 	dev->recv = mpc8220_fec_recv;
842 
843 	sprintf (dev->name, "FEC ETHERNET");
844 	eth_register (dev);
845 
846 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
847 	miiphy_register (dev->name,
848 			fec8220_miiphy_read, fec8220_miiphy_write);
849 #endif
850 
851 	/*
852 	 * Try to set the mac address now. The fec mac address is
853 	 * a garbage after reset. When not using fec for booting
854 	 * the Linux fec driver will try to work with this garbage.
855 	 */
856 	tmp = getenv ("ethaddr");
857 	if (tmp) {
858 		for (i = 0; i < 6; i++) {
859 			env_enetaddr[i] =
860 				tmp ? simple_strtoul (tmp, &end, 16) : 0;
861 			if (tmp)
862 				tmp = (*end) ? end + 1 : end;
863 		}
864 		mpc8220_fec_set_hwaddr (fec, env_enetaddr);
865 	}
866 #ifdef CONFIG_HAS_ETH1
867 	tmp = getenv ("eth1addr");
868 	if (tmp) {
869 		for (i = 0; i < 6; i++) {
870 			env_enet1addr[i] =
871 				tmp ? simple_strtoul (tmp, &end, 16) : 0;
872 			if (tmp)
873 				tmp = (*end) ? end + 1 : end;
874 		}
875 		mpc8220_fec_set_hwaddr (fec2, env_enet1addr);
876 	}
877 #endif
878 
879 	return 1;
880 }
881 
882 /* MII-interface related functions */
883 /********************************************************************/
fec8220_miiphy_read(char * devname,u8 phyAddr,u8 regAddr,u16 * retVal)884 int fec8220_miiphy_read (char *devname, u8 phyAddr, u8 regAddr, u16 * retVal)
885 {
886 	ethernet_regs *eth = (ethernet_regs *) MMAP_FEC1;
887 	u32 reg;		/* convenient holder for the PHY register */
888 	u32 phy;		/* convenient holder for the PHY */
889 	int timeout = 0xffff;
890 
891 	/*
892 	 * reading from any PHY's register is done by properly
893 	 * programming the FEC's MII data register.
894 	 */
895 	reg = regAddr << FEC_MII_DATA_RA_SHIFT;
896 	phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
897 
898 	eth->mii_data =
899 		(FEC_MII_DATA_ST | FEC_MII_DATA_OP_RD | FEC_MII_DATA_TA | phy
900 		 | reg);
901 
902 	/*
903 	 * wait for the related interrupt
904 	 */
905 	while ((timeout--) && (!(eth->ievent & 0x00800000)));
906 
907 	if (timeout == 0) {
908 #ifdef DEBUG
909 		printf ("Read MDIO failed...\n");
910 #endif
911 		return -1;
912 	}
913 
914 	/*
915 	 * clear mii interrupt bit
916 	 */
917 	eth->ievent = 0x00800000;
918 
919 	/*
920 	 * it's now safe to read the PHY's register
921 	 */
922 	*retVal = (u16) eth->mii_data;
923 
924 	return 0;
925 }
926 
927 /********************************************************************/
fec8220_miiphy_write(char * devname,u8 phyAddr,u8 regAddr,u16 data)928 int fec8220_miiphy_write (char *devname, u8 phyAddr, u8 regAddr, u16 data)
929 {
930 	ethernet_regs *eth = (ethernet_regs *) MMAP_FEC1;
931 	u32 reg;		/* convenient holder for the PHY register */
932 	u32 phy;		/* convenient holder for the PHY */
933 	int timeout = 0xffff;
934 
935 	reg = regAddr << FEC_MII_DATA_RA_SHIFT;
936 	phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
937 
938 	eth->mii_data = (FEC_MII_DATA_ST | FEC_MII_DATA_OP_WR |
939 			 FEC_MII_DATA_TA | phy | reg | data);
940 
941 	/*
942 	 * wait for the MII interrupt
943 	 */
944 	while ((timeout--) && (!(eth->ievent & 0x00800000)));
945 
946 	if (timeout == 0) {
947 #ifdef DEBUG
948 		printf ("Write MDIO failed...\n");
949 #endif
950 		return -1;
951 	}
952 
953 	/*
954 	 * clear MII interrupt bit
955 	 */
956 	eth->ievent = 0x00800000;
957 
958 	return 0;
959 }
960 
961 #endif /* CONFIG_MPC8220_FEC */
962