xref: /openbmc/u-boot/drivers/net/mcffec.c (revision 844fb498)
1 /*
2  * (C) Copyright 2000-2004
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * (C) Copyright 2007 Freescale Semiconductor, Inc.
6  * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
7  *
8  * SPDX-License-Identifier:	GPL-2.0+
9  */
10 
11 #include <common.h>
12 #include <environment.h>
13 #include <malloc.h>
14 
15 #include <command.h>
16 #include <net.h>
17 #include <netdev.h>
18 #include <miiphy.h>
19 
20 #include <asm/fec.h>
21 #include <asm/immap.h>
22 
23 #undef	ET_DEBUG
24 #undef	MII_DEBUG
25 
26 /* Ethernet Transmit and Receive Buffers */
27 #define DBUF_LENGTH		1520
28 #define TX_BUF_CNT		2
29 #define PKT_MAXBUF_SIZE		1518
30 #define PKT_MINBUF_SIZE		64
31 #define PKT_MAXBLR_SIZE		1520
32 #define LAST_PKTBUFSRX		PKTBUFSRX - 1
33 #define BD_ENET_RX_W_E		(BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY)
34 #define BD_ENET_TX_RDY_LST	(BD_ENET_TX_READY | BD_ENET_TX_LAST)
35 
36 DECLARE_GLOBAL_DATA_PTR;
37 
38 struct fec_info_s fec_info[] = {
39 #ifdef CONFIG_SYS_FEC0_IOBASE
40 	{
41 	 0,			/* index */
42 	 CONFIG_SYS_FEC0_IOBASE,	/* io base */
43 	 CONFIG_SYS_FEC0_PINMUX,	/* gpio pin muxing */
44 	 CONFIG_SYS_FEC0_MIIBASE,	/* mii base */
45 	 -1,			/* phy_addr */
46 	 0,			/* duplex and speed */
47 	 0,			/* phy name */
48 	 0,			/* phyname init */
49 	 0,			/* RX BD */
50 	 0,			/* TX BD */
51 	 0,			/* rx Index */
52 	 0,			/* tx Index */
53 	 0,			/* tx buffer */
54 	 0,			/* initialized flag */
55 	 (struct fec_info_s *)-1,
56 	 },
57 #endif
58 #ifdef CONFIG_SYS_FEC1_IOBASE
59 	{
60 	 1,			/* index */
61 	 CONFIG_SYS_FEC1_IOBASE,	/* io base */
62 	 CONFIG_SYS_FEC1_PINMUX,	/* gpio pin muxing */
63 	 CONFIG_SYS_FEC1_MIIBASE,	/* mii base */
64 	 -1,			/* phy_addr */
65 	 0,			/* duplex and speed */
66 	 0,			/* phy name */
67 	 0,			/* phy name init */
68 #ifdef CONFIG_SYS_FEC_BUF_USE_SRAM
69 	 (cbd_t *)DBUF_LENGTH,	/* RX BD */
70 #else
71 	 0,			/* RX BD */
72 #endif
73 	 0,			/* TX BD */
74 	 0,			/* rx Index */
75 	 0,			/* tx Index */
76 	 0,			/* tx buffer */
77 	 0,			/* initialized flag */
78 	 (struct fec_info_s *)-1,
79 	 }
80 #endif
81 };
82 
83 int fec_recv(struct eth_device *dev);
84 int fec_init(struct eth_device *dev, bd_t * bd);
85 void fec_halt(struct eth_device *dev);
86 void fec_reset(struct eth_device *dev);
87 
88 void setFecDuplexSpeed(volatile fec_t * fecp, bd_t * bd, int dup_spd)
89 {
90 	if ((dup_spd >> 16) == FULL) {
91 		/* Set maximum frame length */
92 		fecp->rcr = FEC_RCR_MAX_FL(PKT_MAXBUF_SIZE) | FEC_RCR_MII_MODE |
93 		    FEC_RCR_PROM | 0x100;
94 		fecp->tcr = FEC_TCR_FDEN;
95 	} else {
96 		/* Half duplex mode */
97 		fecp->rcr = FEC_RCR_MAX_FL(PKT_MAXBUF_SIZE) |
98 		    FEC_RCR_MII_MODE | FEC_RCR_DRT;
99 		fecp->tcr &= ~FEC_TCR_FDEN;
100 	}
101 
102 	if ((dup_spd & 0xFFFF) == _100BASET) {
103 #ifdef CONFIG_MCF5445x
104 		fecp->rcr &= ~0x200;	/* disabled 10T base */
105 #endif
106 #ifdef MII_DEBUG
107 		printf("100Mbps\n");
108 #endif
109 		bd->bi_ethspeed = 100;
110 	} else {
111 #ifdef CONFIG_MCF5445x
112 		fecp->rcr |= 0x200;	/* enabled 10T base */
113 #endif
114 #ifdef MII_DEBUG
115 		printf("10Mbps\n");
116 #endif
117 		bd->bi_ethspeed = 10;
118 	}
119 }
120 
121 static int fec_send(struct eth_device *dev, void *packet, int length)
122 {
123 	struct fec_info_s *info = dev->priv;
124 	volatile fec_t *fecp = (fec_t *) (info->iobase);
125 	int j, rc;
126 	u16 phyStatus;
127 
128 	miiphy_read(dev->name, info->phy_addr, MII_BMSR, &phyStatus);
129 
130 	/* section 16.9.23.3
131 	 * Wait for ready
132 	 */
133 	j = 0;
134 	while ((info->txbd[info->txIdx].cbd_sc & BD_ENET_TX_READY) &&
135 	       (j < MCFFEC_TOUT_LOOP)) {
136 		udelay(1);
137 		j++;
138 	}
139 	if (j >= MCFFEC_TOUT_LOOP) {
140 		printf("TX not ready\n");
141 	}
142 
143 	info->txbd[info->txIdx].cbd_bufaddr = (uint) packet;
144 	info->txbd[info->txIdx].cbd_datlen = length;
145 	info->txbd[info->txIdx].cbd_sc |= BD_ENET_TX_RDY_LST;
146 
147 	/* Activate transmit Buffer Descriptor polling */
148 	fecp->tdar = 0x01000000;	/* Descriptor polling active    */
149 
150 #ifndef CONFIG_SYS_FEC_BUF_USE_SRAM
151 	/*
152 	 * FEC unable to initial transmit data packet.
153 	 * A nop will ensure the descriptor polling active completed.
154 	 * CF Internal RAM has shorter cycle access than DRAM. If use
155 	 * DRAM as Buffer descriptor and data, a nop is a must.
156 	 * Affect only V2 and V3.
157 	 */
158 	__asm__ ("nop");
159 
160 #endif
161 
162 #ifdef CONFIG_SYS_UNIFY_CACHE
163 	icache_invalid();
164 #endif
165 
166 	j = 0;
167 	while ((info->txbd[info->txIdx].cbd_sc & BD_ENET_TX_READY) &&
168 	       (j < MCFFEC_TOUT_LOOP)) {
169 		udelay(1);
170 		j++;
171 	}
172 	if (j >= MCFFEC_TOUT_LOOP) {
173 		printf("TX timeout\n");
174 	}
175 
176 #ifdef ET_DEBUG
177 	printf("%s[%d] %s: cycles: %d    status: %x  retry cnt: %d\n",
178 	       __FILE__, __LINE__, __FUNCTION__, j,
179 	       info->txbd[info->txIdx].cbd_sc,
180 	       (info->txbd[info->txIdx].cbd_sc & 0x003C) >> 2);
181 #endif
182 
183 	/* return only status bits */
184 	rc = (info->txbd[info->txIdx].cbd_sc & BD_ENET_TX_STATS);
185 	info->txIdx = (info->txIdx + 1) % TX_BUF_CNT;
186 
187 	return rc;
188 }
189 
190 int fec_recv(struct eth_device *dev)
191 {
192 	struct fec_info_s *info = dev->priv;
193 	volatile fec_t *fecp = (fec_t *) (info->iobase);
194 	int length;
195 
196 	for (;;) {
197 #ifndef CONFIG_SYS_FEC_BUF_USE_SRAM
198 #endif
199 #ifdef CONFIG_SYS_UNIFY_CACHE
200 		icache_invalid();
201 #endif
202 		/* section 16.9.23.2 */
203 		if (info->rxbd[info->rxIdx].cbd_sc & BD_ENET_RX_EMPTY) {
204 			length = -1;
205 			break;	/* nothing received - leave for() loop */
206 		}
207 
208 		length = info->rxbd[info->rxIdx].cbd_datlen;
209 
210 		if (info->rxbd[info->rxIdx].cbd_sc & 0x003f) {
211 			printf("%s[%d] err: %x\n",
212 			       __FUNCTION__, __LINE__,
213 			       info->rxbd[info->rxIdx].cbd_sc);
214 #ifdef ET_DEBUG
215 			printf("%s[%d] err: %x\n",
216 			       __FUNCTION__, __LINE__,
217 			       info->rxbd[info->rxIdx].cbd_sc);
218 #endif
219 		} else {
220 
221 			length -= 4;
222 			/* Pass the packet up to the protocol layers. */
223 			net_process_received_packet(net_rx_packets[info->rxIdx],
224 						    length);
225 
226 			fecp->eir |= FEC_EIR_RXF;
227 		}
228 
229 		/* Give the buffer back to the FEC. */
230 		info->rxbd[info->rxIdx].cbd_datlen = 0;
231 
232 		/* wrap around buffer index when necessary */
233 		if (info->rxIdx == LAST_PKTBUFSRX) {
234 			info->rxbd[PKTBUFSRX - 1].cbd_sc = BD_ENET_RX_W_E;
235 			info->rxIdx = 0;
236 		} else {
237 			info->rxbd[info->rxIdx].cbd_sc = BD_ENET_RX_EMPTY;
238 			info->rxIdx++;
239 		}
240 
241 		/* Try to fill Buffer Descriptors */
242 		fecp->rdar = 0x01000000;	/* Descriptor polling active    */
243 	}
244 
245 	return length;
246 }
247 
248 #ifdef ET_DEBUG
249 void dbgFecRegs(struct eth_device *dev)
250 {
251 	struct fec_info_s *info = dev->priv;
252 	volatile fec_t *fecp = (fec_t *) (info->iobase);
253 
254 	printf("=====\n");
255 	printf("ievent       %x - %x\n", (int)&fecp->eir, fecp->eir);
256 	printf("imask        %x - %x\n", (int)&fecp->eimr, fecp->eimr);
257 	printf("r_des_active %x - %x\n", (int)&fecp->rdar, fecp->rdar);
258 	printf("x_des_active %x - %x\n", (int)&fecp->tdar, fecp->tdar);
259 	printf("ecntrl       %x - %x\n", (int)&fecp->ecr, fecp->ecr);
260 	printf("mii_mframe   %x - %x\n", (int)&fecp->mmfr, fecp->mmfr);
261 	printf("mii_speed    %x - %x\n", (int)&fecp->mscr, fecp->mscr);
262 	printf("mii_ctrlstat %x - %x\n", (int)&fecp->mibc, fecp->mibc);
263 	printf("r_cntrl      %x - %x\n", (int)&fecp->rcr, fecp->rcr);
264 	printf("x_cntrl      %x - %x\n", (int)&fecp->tcr, fecp->tcr);
265 	printf("padr_l       %x - %x\n", (int)&fecp->palr, fecp->palr);
266 	printf("padr_u       %x - %x\n", (int)&fecp->paur, fecp->paur);
267 	printf("op_pause     %x - %x\n", (int)&fecp->opd, fecp->opd);
268 	printf("iadr_u       %x - %x\n", (int)&fecp->iaur, fecp->iaur);
269 	printf("iadr_l       %x - %x\n", (int)&fecp->ialr, fecp->ialr);
270 	printf("gadr_u       %x - %x\n", (int)&fecp->gaur, fecp->gaur);
271 	printf("gadr_l       %x - %x\n", (int)&fecp->galr, fecp->galr);
272 	printf("x_wmrk       %x - %x\n", (int)&fecp->tfwr, fecp->tfwr);
273 	printf("r_bound      %x - %x\n", (int)&fecp->frbr, fecp->frbr);
274 	printf("r_fstart     %x - %x\n", (int)&fecp->frsr, fecp->frsr);
275 	printf("r_drng       %x - %x\n", (int)&fecp->erdsr, fecp->erdsr);
276 	printf("x_drng       %x - %x\n", (int)&fecp->etdsr, fecp->etdsr);
277 	printf("r_bufsz      %x - %x\n", (int)&fecp->emrbr, fecp->emrbr);
278 
279 	printf("\n");
280 	printf("rmon_t_drop        %x - %x\n", (int)&fecp->rmon_t_drop,
281 	       fecp->rmon_t_drop);
282 	printf("rmon_t_packets     %x - %x\n", (int)&fecp->rmon_t_packets,
283 	       fecp->rmon_t_packets);
284 	printf("rmon_t_bc_pkt      %x - %x\n", (int)&fecp->rmon_t_bc_pkt,
285 	       fecp->rmon_t_bc_pkt);
286 	printf("rmon_t_mc_pkt      %x - %x\n", (int)&fecp->rmon_t_mc_pkt,
287 	       fecp->rmon_t_mc_pkt);
288 	printf("rmon_t_crc_align   %x - %x\n", (int)&fecp->rmon_t_crc_align,
289 	       fecp->rmon_t_crc_align);
290 	printf("rmon_t_undersize   %x - %x\n", (int)&fecp->rmon_t_undersize,
291 	       fecp->rmon_t_undersize);
292 	printf("rmon_t_oversize    %x - %x\n", (int)&fecp->rmon_t_oversize,
293 	       fecp->rmon_t_oversize);
294 	printf("rmon_t_frag        %x - %x\n", (int)&fecp->rmon_t_frag,
295 	       fecp->rmon_t_frag);
296 	printf("rmon_t_jab         %x - %x\n", (int)&fecp->rmon_t_jab,
297 	       fecp->rmon_t_jab);
298 	printf("rmon_t_col         %x - %x\n", (int)&fecp->rmon_t_col,
299 	       fecp->rmon_t_col);
300 	printf("rmon_t_p64         %x - %x\n", (int)&fecp->rmon_t_p64,
301 	       fecp->rmon_t_p64);
302 	printf("rmon_t_p65to127    %x - %x\n", (int)&fecp->rmon_t_p65to127,
303 	       fecp->rmon_t_p65to127);
304 	printf("rmon_t_p128to255   %x - %x\n", (int)&fecp->rmon_t_p128to255,
305 	       fecp->rmon_t_p128to255);
306 	printf("rmon_t_p256to511   %x - %x\n", (int)&fecp->rmon_t_p256to511,
307 	       fecp->rmon_t_p256to511);
308 	printf("rmon_t_p512to1023  %x - %x\n", (int)&fecp->rmon_t_p512to1023,
309 	       fecp->rmon_t_p512to1023);
310 	printf("rmon_t_p1024to2047 %x - %x\n", (int)&fecp->rmon_t_p1024to2047,
311 	       fecp->rmon_t_p1024to2047);
312 	printf("rmon_t_p_gte2048   %x - %x\n", (int)&fecp->rmon_t_p_gte2048,
313 	       fecp->rmon_t_p_gte2048);
314 	printf("rmon_t_octets      %x - %x\n", (int)&fecp->rmon_t_octets,
315 	       fecp->rmon_t_octets);
316 
317 	printf("\n");
318 	printf("ieee_t_drop      %x - %x\n", (int)&fecp->ieee_t_drop,
319 	       fecp->ieee_t_drop);
320 	printf("ieee_t_frame_ok  %x - %x\n", (int)&fecp->ieee_t_frame_ok,
321 	       fecp->ieee_t_frame_ok);
322 	printf("ieee_t_1col      %x - %x\n", (int)&fecp->ieee_t_1col,
323 	       fecp->ieee_t_1col);
324 	printf("ieee_t_mcol      %x - %x\n", (int)&fecp->ieee_t_mcol,
325 	       fecp->ieee_t_mcol);
326 	printf("ieee_t_def       %x - %x\n", (int)&fecp->ieee_t_def,
327 	       fecp->ieee_t_def);
328 	printf("ieee_t_lcol      %x - %x\n", (int)&fecp->ieee_t_lcol,
329 	       fecp->ieee_t_lcol);
330 	printf("ieee_t_excol     %x - %x\n", (int)&fecp->ieee_t_excol,
331 	       fecp->ieee_t_excol);
332 	printf("ieee_t_macerr    %x - %x\n", (int)&fecp->ieee_t_macerr,
333 	       fecp->ieee_t_macerr);
334 	printf("ieee_t_cserr     %x - %x\n", (int)&fecp->ieee_t_cserr,
335 	       fecp->ieee_t_cserr);
336 	printf("ieee_t_sqe       %x - %x\n", (int)&fecp->ieee_t_sqe,
337 	       fecp->ieee_t_sqe);
338 	printf("ieee_t_fdxfc     %x - %x\n", (int)&fecp->ieee_t_fdxfc,
339 	       fecp->ieee_t_fdxfc);
340 	printf("ieee_t_octets_ok %x - %x\n", (int)&fecp->ieee_t_octets_ok,
341 	       fecp->ieee_t_octets_ok);
342 
343 	printf("\n");
344 	printf("rmon_r_drop        %x - %x\n", (int)&fecp->rmon_r_drop,
345 	       fecp->rmon_r_drop);
346 	printf("rmon_r_packets     %x - %x\n", (int)&fecp->rmon_r_packets,
347 	       fecp->rmon_r_packets);
348 	printf("rmon_r_bc_pkt      %x - %x\n", (int)&fecp->rmon_r_bc_pkt,
349 	       fecp->rmon_r_bc_pkt);
350 	printf("rmon_r_mc_pkt      %x - %x\n", (int)&fecp->rmon_r_mc_pkt,
351 	       fecp->rmon_r_mc_pkt);
352 	printf("rmon_r_crc_align   %x - %x\n", (int)&fecp->rmon_r_crc_align,
353 	       fecp->rmon_r_crc_align);
354 	printf("rmon_r_undersize   %x - %x\n", (int)&fecp->rmon_r_undersize,
355 	       fecp->rmon_r_undersize);
356 	printf("rmon_r_oversize    %x - %x\n", (int)&fecp->rmon_r_oversize,
357 	       fecp->rmon_r_oversize);
358 	printf("rmon_r_frag        %x - %x\n", (int)&fecp->rmon_r_frag,
359 	       fecp->rmon_r_frag);
360 	printf("rmon_r_jab         %x - %x\n", (int)&fecp->rmon_r_jab,
361 	       fecp->rmon_r_jab);
362 	printf("rmon_r_p64         %x - %x\n", (int)&fecp->rmon_r_p64,
363 	       fecp->rmon_r_p64);
364 	printf("rmon_r_p65to127    %x - %x\n", (int)&fecp->rmon_r_p65to127,
365 	       fecp->rmon_r_p65to127);
366 	printf("rmon_r_p128to255   %x - %x\n", (int)&fecp->rmon_r_p128to255,
367 	       fecp->rmon_r_p128to255);
368 	printf("rmon_r_p256to511   %x - %x\n", (int)&fecp->rmon_r_p256to511,
369 	       fecp->rmon_r_p256to511);
370 	printf("rmon_r_p512to1023  %x - %x\n", (int)&fecp->rmon_r_p512to1023,
371 	       fecp->rmon_r_p512to1023);
372 	printf("rmon_r_p1024to2047 %x - %x\n", (int)&fecp->rmon_r_p1024to2047,
373 	       fecp->rmon_r_p1024to2047);
374 	printf("rmon_r_p_gte2048   %x - %x\n", (int)&fecp->rmon_r_p_gte2048,
375 	       fecp->rmon_r_p_gte2048);
376 	printf("rmon_r_octets      %x - %x\n", (int)&fecp->rmon_r_octets,
377 	       fecp->rmon_r_octets);
378 
379 	printf("\n");
380 	printf("ieee_r_drop      %x - %x\n", (int)&fecp->ieee_r_drop,
381 	       fecp->ieee_r_drop);
382 	printf("ieee_r_frame_ok  %x - %x\n", (int)&fecp->ieee_r_frame_ok,
383 	       fecp->ieee_r_frame_ok);
384 	printf("ieee_r_crc       %x - %x\n", (int)&fecp->ieee_r_crc,
385 	       fecp->ieee_r_crc);
386 	printf("ieee_r_align     %x - %x\n", (int)&fecp->ieee_r_align,
387 	       fecp->ieee_r_align);
388 	printf("ieee_r_macerr    %x - %x\n", (int)&fecp->ieee_r_macerr,
389 	       fecp->ieee_r_macerr);
390 	printf("ieee_r_fdxfc     %x - %x\n", (int)&fecp->ieee_r_fdxfc,
391 	       fecp->ieee_r_fdxfc);
392 	printf("ieee_r_octets_ok %x - %x\n", (int)&fecp->ieee_r_octets_ok,
393 	       fecp->ieee_r_octets_ok);
394 
395 	printf("\n\n\n");
396 }
397 #endif
398 
399 int fec_init(struct eth_device *dev, bd_t * bd)
400 {
401 	struct fec_info_s *info = dev->priv;
402 	volatile fec_t *fecp = (fec_t *) (info->iobase);
403 	int i;
404 	uchar ea[6];
405 
406 	fecpin_setclear(dev, 1);
407 
408 	fec_reset(dev);
409 
410 #if defined(CONFIG_CMD_MII) || defined (CONFIG_MII) || \
411 	defined (CONFIG_SYS_DISCOVER_PHY)
412 
413 	mii_init();
414 
415 	setFecDuplexSpeed(fecp, bd, info->dup_spd);
416 #else
417 #ifndef CONFIG_SYS_DISCOVER_PHY
418 	setFecDuplexSpeed(fecp, bd, (FECDUPLEX << 16) | FECSPEED);
419 #endif				/* ifndef CONFIG_SYS_DISCOVER_PHY */
420 #endif				/* CONFIG_CMD_MII || CONFIG_MII */
421 
422 	/* We use strictly polling mode only */
423 	fecp->eimr = 0;
424 
425 	/* Clear any pending interrupt */
426 	fecp->eir = 0xffffffff;
427 
428 	/* Set station address   */
429 	if ((u32) fecp == CONFIG_SYS_FEC0_IOBASE) {
430 #ifdef CONFIG_SYS_FEC1_IOBASE
431 		volatile fec_t *fecp1 = (fec_t *) (CONFIG_SYS_FEC1_IOBASE);
432 		eth_env_get_enetaddr("eth1addr", ea);
433 		fecp1->palr =
434 		    (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | (ea[3]);
435 		fecp1->paur = (ea[4] << 24) | (ea[5] << 16);
436 #endif
437 		eth_env_get_enetaddr("ethaddr", ea);
438 		fecp->palr =
439 		    (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | (ea[3]);
440 		fecp->paur = (ea[4] << 24) | (ea[5] << 16);
441 	} else {
442 #ifdef CONFIG_SYS_FEC0_IOBASE
443 		volatile fec_t *fecp0 = (fec_t *) (CONFIG_SYS_FEC0_IOBASE);
444 		eth_env_get_enetaddr("ethaddr", ea);
445 		fecp0->palr =
446 		    (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | (ea[3]);
447 		fecp0->paur = (ea[4] << 24) | (ea[5] << 16);
448 #endif
449 #ifdef CONFIG_SYS_FEC1_IOBASE
450 		eth_env_get_enetaddr("eth1addr", ea);
451 		fecp->palr =
452 		    (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | (ea[3]);
453 		fecp->paur = (ea[4] << 24) | (ea[5] << 16);
454 #endif
455 	}
456 
457 	/* Clear unicast address hash table */
458 	fecp->iaur = 0;
459 	fecp->ialr = 0;
460 
461 	/* Clear multicast address hash table */
462 	fecp->gaur = 0;
463 	fecp->galr = 0;
464 
465 	/* Set maximum receive buffer size. */
466 	fecp->emrbr = PKT_MAXBLR_SIZE;
467 
468 	/*
469 	 * Setup Buffers and Buffer Descriptors
470 	 */
471 	info->rxIdx = 0;
472 	info->txIdx = 0;
473 
474 	/*
475 	 * Setup Receiver Buffer Descriptors (13.14.24.18)
476 	 * Settings:
477 	 *     Empty, Wrap
478 	 */
479 	for (i = 0; i < PKTBUFSRX; i++) {
480 		info->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY;
481 		info->rxbd[i].cbd_datlen = 0;	/* Reset */
482 		info->rxbd[i].cbd_bufaddr = (uint) net_rx_packets[i];
483 	}
484 	info->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP;
485 
486 	/*
487 	 * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19)
488 	 * Settings:
489 	 *    Last, Tx CRC
490 	 */
491 	for (i = 0; i < TX_BUF_CNT; i++) {
492 		info->txbd[i].cbd_sc = BD_ENET_TX_LAST | BD_ENET_TX_TC;
493 		info->txbd[i].cbd_datlen = 0;	/* Reset */
494 		info->txbd[i].cbd_bufaddr = (uint) (&info->txbuf[0]);
495 	}
496 	info->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP;
497 
498 	/* Set receive and transmit descriptor base */
499 	fecp->erdsr = (unsigned int)(&info->rxbd[0]);
500 	fecp->etdsr = (unsigned int)(&info->txbd[0]);
501 
502 	/* Now enable the transmit and receive processing */
503 	fecp->ecr |= FEC_ECR_ETHER_EN;
504 
505 	/* And last, try to fill Rx Buffer Descriptors */
506 	fecp->rdar = 0x01000000;	/* Descriptor polling active    */
507 
508 	return 1;
509 }
510 
511 void fec_reset(struct eth_device *dev)
512 {
513 	struct fec_info_s *info = dev->priv;
514 	volatile fec_t *fecp = (fec_t *) (info->iobase);
515 	int i;
516 
517 	fecp->ecr = FEC_ECR_RESET;
518 	for (i = 0; (fecp->ecr & FEC_ECR_RESET) && (i < FEC_RESET_DELAY); ++i) {
519 		udelay(1);
520 	}
521 	if (i == FEC_RESET_DELAY) {
522 		printf("FEC_RESET_DELAY timeout\n");
523 	}
524 }
525 
526 void fec_halt(struct eth_device *dev)
527 {
528 	struct fec_info_s *info = dev->priv;
529 
530 	fec_reset(dev);
531 
532 	fecpin_setclear(dev, 0);
533 
534 	info->rxIdx = info->txIdx = 0;
535 	memset(info->rxbd, 0, PKTBUFSRX * sizeof(cbd_t));
536 	memset(info->txbd, 0, TX_BUF_CNT * sizeof(cbd_t));
537 	memset(info->txbuf, 0, DBUF_LENGTH);
538 }
539 
540 int mcffec_initialize(bd_t * bis)
541 {
542 	struct eth_device *dev;
543 	int i;
544 #ifdef CONFIG_SYS_FEC_BUF_USE_SRAM
545 	u32 tmp = CONFIG_SYS_INIT_RAM_ADDR + 0x1000;
546 #endif
547 
548 	for (i = 0; i < ARRAY_SIZE(fec_info); i++) {
549 
550 		dev =
551 		    (struct eth_device *)memalign(CONFIG_SYS_CACHELINE_SIZE,
552 						  sizeof *dev);
553 		if (dev == NULL)
554 			hang();
555 
556 		memset(dev, 0, sizeof(*dev));
557 
558 		sprintf(dev->name, "FEC%d", fec_info[i].index);
559 
560 		dev->priv = &fec_info[i];
561 		dev->init = fec_init;
562 		dev->halt = fec_halt;
563 		dev->send = fec_send;
564 		dev->recv = fec_recv;
565 
566 		/* setup Receive and Transmit buffer descriptor */
567 #ifdef CONFIG_SYS_FEC_BUF_USE_SRAM
568 		fec_info[i].rxbd = (cbd_t *)((u32)fec_info[i].rxbd + tmp);
569 		tmp = (u32)fec_info[i].rxbd;
570 		fec_info[i].txbd =
571 		    (cbd_t *)((u32)fec_info[i].txbd + tmp +
572 		    (PKTBUFSRX * sizeof(cbd_t)));
573 		tmp = (u32)fec_info[i].txbd;
574 		fec_info[i].txbuf =
575 		    (char *)((u32)fec_info[i].txbuf + tmp +
576 		    (CONFIG_SYS_TX_ETH_BUFFER * sizeof(cbd_t)));
577 		tmp = (u32)fec_info[i].txbuf;
578 #else
579 		fec_info[i].rxbd =
580 		    (cbd_t *) memalign(CONFIG_SYS_CACHELINE_SIZE,
581 				       (PKTBUFSRX * sizeof(cbd_t)));
582 		fec_info[i].txbd =
583 		    (cbd_t *) memalign(CONFIG_SYS_CACHELINE_SIZE,
584 				       (TX_BUF_CNT * sizeof(cbd_t)));
585 		fec_info[i].txbuf =
586 		    (char *)memalign(CONFIG_SYS_CACHELINE_SIZE, DBUF_LENGTH);
587 #endif
588 
589 #ifdef ET_DEBUG
590 		printf("rxbd %x txbd %x\n",
591 		       (int)fec_info[i].rxbd, (int)fec_info[i].txbd);
592 #endif
593 
594 		fec_info[i].phy_name = (char *)memalign(CONFIG_SYS_CACHELINE_SIZE, 32);
595 
596 		eth_register(dev);
597 
598 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
599 		int retval;
600 		struct mii_dev *mdiodev = mdio_alloc();
601 		if (!mdiodev)
602 			return -ENOMEM;
603 		strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
604 		mdiodev->read = mcffec_miiphy_read;
605 		mdiodev->write = mcffec_miiphy_write;
606 
607 		retval = mdio_register(mdiodev);
608 		if (retval < 0)
609 			return retval;
610 #endif
611 		if (i > 0)
612 			fec_info[i - 1].next = &fec_info[i];
613 	}
614 	fec_info[i - 1].next = &fec_info[0];
615 
616 	/* default speed */
617 	bis->bi_ethspeed = 10;
618 
619 	return 0;
620 }
621