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/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
  36DECLARE_GLOBAL_DATA_PTR;
  37
  38static 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
  76static 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
  89static 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
 125static 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
 275int 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
 374static 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
 440static 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
 492static 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
 507static 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 */
 518static 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
 573static 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 */
 586static 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
 603static const struct udevice_id mcffec_ids[] = {
 604        { .compatible = "fsl,mcf-fec" },
 605        { }
 606};
 607
 608U_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};
 619