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