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