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