firmware: ti_sci: Update ti_sci_msg_req_reboot to include domain
[pandora-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 <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
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
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
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
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
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
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
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
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  */
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
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  */
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 };