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