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