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