uboot/cpu/arm926ejs/davinci/ether.c
<<
>>
Prefs
   1/*
   2 * Ethernet driver for TI TMS320DM644x (DaVinci) chips.
   3 *
   4 * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
   5 *
   6 * Parts shamelessly stolen from TI's dm644x_emac.c. Original copyright
   7 * follows:
   8 *
   9 * ----------------------------------------------------------------------------
  10 *
  11 * dm644x_emac.c
  12 *
  13 * TI DaVinci (DM644X) EMAC peripheral driver source for DV-EVM
  14 *
  15 * Copyright (C) 2005 Texas Instruments.
  16 *
  17 * ----------------------------------------------------------------------------
  18 *
  19 * This program is free software; you can redistribute it and/or modify
  20 * it under the terms of the GNU General Public License as published by
  21 * the Free Software Foundation; either version 2 of the License, or
  22 * (at your option) any later version.
  23 *
  24 * This program is distributed in the hope that it will be useful,
  25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  27 * GNU General Public License for more details.
  28 *
  29 *  You should have received a copy of the GNU General Public License
  30 *  along with this program; if not, write to the Free Software
  31 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  32 * ----------------------------------------------------------------------------
  33
  34 * Modifications:
  35 * ver. 1.0: Sep 2005, Anant Gole - Created EMAC version for uBoot.
  36 * ver  1.1: Nov 2005, Anant Gole - Extended the RX logic for multiple descriptors
  37 *
  38 */
  39#include <common.h>
  40#include <command.h>
  41#include <net.h>
  42#include <miiphy.h>
  43#include <asm/arch/emac_defs.h>
  44
  45#ifdef CONFIG_DRIVER_TI_EMAC
  46
  47#ifdef CONFIG_CMD_NET
  48
  49unsigned int    emac_dbg = 0;
  50#define debug_emac(fmt,args...) if (emac_dbg) printf(fmt,##args)
  51
  52/* Internal static functions */
  53static int davinci_eth_hw_init (void);
  54static int davinci_eth_open (void);
  55static int davinci_eth_close (void);
  56static int davinci_eth_send_packet (volatile void *packet, int length);
  57static int davinci_eth_rcv_packet (void);
  58static void davinci_eth_mdio_enable(void);
  59
  60static int gen_init_phy(int phy_addr);
  61static int gen_is_phy_connected(int phy_addr);
  62static int gen_get_link_speed(int phy_addr);
  63static int gen_auto_negotiate(int phy_addr);
  64
  65/* Wrappers exported to the U-Boot proper */
  66int eth_hw_init(void)
  67{
  68        return(davinci_eth_hw_init());
  69}
  70
  71int eth_init(bd_t * bd)
  72{
  73        return(davinci_eth_open());
  74}
  75
  76void eth_halt(void)
  77{
  78        davinci_eth_close();
  79}
  80
  81int eth_send(volatile void *packet, int length)
  82{
  83        return(davinci_eth_send_packet(packet, length));
  84}
  85
  86int eth_rx(void)
  87{
  88        return(davinci_eth_rcv_packet());
  89}
  90
  91void eth_mdio_enable(void)
  92{
  93        davinci_eth_mdio_enable();
  94}
  95/* End of wrappers */
  96
  97
  98static u_int8_t davinci_eth_mac_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
  99
 100/*
 101 * This function must be called before emac_open() if you want to override
 102 * the default mac address.
 103 */
 104void davinci_eth_set_mac_addr(const u_int8_t *addr)
 105{
 106        int i;
 107
 108        for (i = 0; i < sizeof (davinci_eth_mac_addr); i++) {
 109                davinci_eth_mac_addr[i] = addr[i];
 110        }
 111}
 112
 113/* EMAC Addresses */
 114static volatile emac_regs       *adap_emac = (emac_regs *)EMAC_BASE_ADDR;
 115static volatile ewrap_regs      *adap_ewrap = (ewrap_regs *)EMAC_WRAPPER_BASE_ADDR;
 116static volatile mdio_regs       *adap_mdio = (mdio_regs *)EMAC_MDIO_BASE_ADDR;
 117
 118/* EMAC descriptors */
 119static volatile emac_desc       *emac_rx_desc = (emac_desc *)(EMAC_WRAPPER_RAM_ADDR + EMAC_RX_DESC_BASE);
 120static volatile emac_desc       *emac_tx_desc = (emac_desc *)(EMAC_WRAPPER_RAM_ADDR + EMAC_TX_DESC_BASE);
 121static volatile emac_desc       *emac_rx_active_head = 0;
 122static volatile emac_desc       *emac_rx_active_tail = 0;
 123static int                      emac_rx_queue_active = 0;
 124
 125/* Receive packet buffers */
 126static unsigned char            emac_rx_buffers[EMAC_MAX_RX_BUFFERS * (EMAC_MAX_ETHERNET_PKT_SIZE + EMAC_PKT_ALIGN)];
 127
 128/* PHY address for a discovered PHY (0xff - not found) */
 129static volatile u_int8_t        active_phy_addr = 0xff;
 130
 131phy_t                           phy;
 132
 133static void davinci_eth_mdio_enable(void)
 134{
 135        u_int32_t       clkdiv;
 136
 137        clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1;
 138
 139        adap_mdio->CONTROL = (clkdiv & 0xff) |
 140                MDIO_CONTROL_ENABLE |
 141                MDIO_CONTROL_FAULT |
 142                MDIO_CONTROL_FAULT_ENABLE;
 143
 144        while (adap_mdio->CONTROL & MDIO_CONTROL_IDLE) {;}
 145}
 146
 147/*
 148 * Tries to find an active connected PHY. Returns 1 if address if found.
 149 * If no active PHY (or more than one PHY) found returns 0.
 150 * Sets active_phy_addr variable.
 151 */
 152static int davinci_eth_phy_detect(void)
 153{
 154        u_int32_t       phy_act_state;
 155        int             i;
 156
 157        active_phy_addr = 0xff;
 158
 159        if ((phy_act_state = adap_mdio->ALIVE) == 0)
 160                return(0);                              /* No active PHYs */
 161
 162        debug_emac("davinci_eth_phy_detect(), ALIVE = 0x%08x\n", phy_act_state);
 163
 164        for (i = 0; i < 32; i++) {
 165                if (phy_act_state & (1 << i)) {
 166                        if (phy_act_state & ~(1 << i))
 167                                return(0);              /* More than one PHY */
 168                        else {
 169                                active_phy_addr = i;
 170                                return(1);
 171                        }
 172                }
 173        }
 174
 175        return(0);      /* Just to make GCC happy */
 176}
 177
 178
 179/* Read a PHY register via MDIO inteface. Returns 1 on success, 0 otherwise */
 180int davinci_eth_phy_read(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t *data)
 181{
 182        int     tmp;
 183
 184        while (adap_mdio->USERACCESS0 & MDIO_USERACCESS0_GO) {;}
 185
 186        adap_mdio->USERACCESS0 = MDIO_USERACCESS0_GO |
 187                                MDIO_USERACCESS0_WRITE_READ |
 188                                ((reg_num & 0x1f) << 21) |
 189                                ((phy_addr & 0x1f) << 16);
 190
 191        /* Wait for command to complete */
 192        while ((tmp = adap_mdio->USERACCESS0) & MDIO_USERACCESS0_GO) {;}
 193
 194        if (tmp & MDIO_USERACCESS0_ACK) {
 195                *data = tmp & 0xffff;
 196                return(1);
 197        }
 198
 199        *data = -1;
 200        return(0);
 201}
 202
 203/* Write to a PHY register via MDIO inteface. Blocks until operation is complete. */
 204int davinci_eth_phy_write(u_int8_t phy_addr, u_int8_t reg_num, u_int16_t data)
 205{
 206
 207        while (adap_mdio->USERACCESS0 & MDIO_USERACCESS0_GO) {;}
 208
 209        adap_mdio->USERACCESS0 = MDIO_USERACCESS0_GO |
 210                                MDIO_USERACCESS0_WRITE_WRITE |
 211                                ((reg_num & 0x1f) << 21) |
 212                                ((phy_addr & 0x1f) << 16) |
 213                                (data & 0xffff);
 214
 215        /* Wait for command to complete */
 216        while (adap_mdio->USERACCESS0 & MDIO_USERACCESS0_GO) {;}
 217
 218        return(1);
 219}
 220
 221/* PHY functions for a generic PHY */
 222static int gen_init_phy(int phy_addr)
 223{
 224        int     ret = 1;
 225
 226        if (gen_get_link_speed(phy_addr)) {
 227                /* Try another time */
 228                ret = gen_get_link_speed(phy_addr);
 229        }
 230
 231        return(ret);
 232}
 233
 234static int gen_is_phy_connected(int phy_addr)
 235{
 236        u_int16_t       dummy;
 237
 238        return(davinci_eth_phy_read(phy_addr, PHY_PHYIDR1, &dummy));
 239}
 240
 241static int gen_get_link_speed(int phy_addr)
 242{
 243        u_int16_t       tmp;
 244
 245        if (davinci_eth_phy_read(phy_addr, MII_STATUS_REG, &tmp) && (tmp & 0x04))
 246                return(1);
 247
 248        return(0);
 249}
 250
 251static int gen_auto_negotiate(int phy_addr)
 252{
 253        u_int16_t       tmp;
 254
 255        if (!davinci_eth_phy_read(phy_addr, PHY_BMCR, &tmp))
 256                return(0);
 257
 258        /* Restart Auto_negotiation  */
 259        tmp |= PHY_BMCR_AUTON;
 260        davinci_eth_phy_write(phy_addr, PHY_BMCR, tmp);
 261
 262        /*check AutoNegotiate complete */
 263        udelay (10000);
 264        if (!davinci_eth_phy_read(phy_addr, PHY_BMSR, &tmp))
 265                return(0);
 266
 267        if (!(tmp & PHY_BMSR_AUTN_COMP))
 268                return(0);
 269
 270        return(gen_get_link_speed(phy_addr));
 271}
 272/* End of generic PHY functions */
 273
 274
 275#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
 276static int davinci_mii_phy_read(char *devname, unsigned char addr, unsigned char reg, unsigned short *value)
 277{
 278        return(davinci_eth_phy_read(addr, reg, value) ? 0 : 1);
 279}
 280
 281static int davinci_mii_phy_write(char *devname, unsigned char addr, unsigned char reg, unsigned short value)
 282{
 283        return(davinci_eth_phy_write(addr, reg, value) ? 0 : 1);
 284}
 285
 286int davinci_eth_miiphy_initialize(bd_t *bis)
 287{
 288        miiphy_register(phy.name, davinci_mii_phy_read, davinci_mii_phy_write);
 289
 290        return(1);
 291}
 292#endif
 293
 294/*
 295 * This function initializes the emac hardware. It does NOT initialize
 296 * EMAC modules power or pin multiplexors, that is done by board_init()
 297 * much earlier in bootup process. Returns 1 on success, 0 otherwise.
 298 */
 299static int davinci_eth_hw_init(void)
 300{
 301        u_int32_t       phy_id;
 302        u_int16_t       tmp;
 303        int             i;
 304
 305        davinci_eth_mdio_enable();
 306
 307        for (i = 0; i < 256; i++) {
 308                if (adap_mdio->ALIVE)
 309                        break;
 310                udelay(10);
 311        }
 312
 313        if (i >= 256) {
 314                printf("No ETH PHY detected!!!\n");
 315                return(0);
 316        }
 317
 318        /* Find if a PHY is connected and get it's address */
 319        if (!davinci_eth_phy_detect())
 320                return(0);
 321
 322        /* Get PHY ID and initialize phy_ops for a detected PHY */
 323        if (!davinci_eth_phy_read(active_phy_addr, PHY_PHYIDR1, &tmp)) {
 324                active_phy_addr = 0xff;
 325                return(0);
 326        }
 327
 328        phy_id = (tmp << 16) & 0xffff0000;
 329
 330        if (!davinci_eth_phy_read(active_phy_addr, PHY_PHYIDR2, &tmp)) {
 331                active_phy_addr = 0xff;
 332                return(0);
 333        }
 334
 335        phy_id |= tmp & 0x0000ffff;
 336
 337        switch (phy_id) {
 338                case PHY_LXT972:
 339                        sprintf(phy.name, "LXT972 @ 0x%02x", active_phy_addr);
 340                        phy.init = lxt972_init_phy;
 341                        phy.is_phy_connected = lxt972_is_phy_connected;
 342                        phy.get_link_speed = lxt972_get_link_speed;
 343                        phy.auto_negotiate = lxt972_auto_negotiate;
 344                        break;
 345                case PHY_DP83848:
 346                        sprintf(phy.name, "DP83848 @ 0x%02x", active_phy_addr);
 347                        phy.init = dp83848_init_phy;
 348                        phy.is_phy_connected = dp83848_is_phy_connected;
 349                        phy.get_link_speed = dp83848_get_link_speed;
 350                        phy.auto_negotiate = dp83848_auto_negotiate;
 351                        break;
 352                default:
 353                        sprintf(phy.name, "GENERIC @ 0x%02x", active_phy_addr);
 354                        phy.init = gen_init_phy;
 355                        phy.is_phy_connected = gen_is_phy_connected;
 356                        phy.get_link_speed = gen_get_link_speed;
 357                        phy.auto_negotiate = gen_auto_negotiate;
 358        }
 359
 360        printf("Ethernet PHY: %s\n", phy.name);
 361
 362        return(1);
 363}
 364
 365
 366/* Eth device open */
 367static int davinci_eth_open(void)
 368{
 369        dv_reg_p                addr;
 370        u_int32_t               clkdiv, cnt;
 371        volatile emac_desc      *rx_desc;
 372
 373        debug_emac("+ emac_open\n");
 374
 375        /* Reset EMAC module and disable interrupts in wrapper */
 376        adap_emac->SOFTRESET = 1;
 377        while (adap_emac->SOFTRESET != 0) {;}
 378        adap_ewrap->EWCTL = 0;
 379        for (cnt = 0; cnt < 5; cnt++) {
 380                clkdiv = adap_ewrap->EWCTL;
 381        }
 382
 383        rx_desc = emac_rx_desc;
 384
 385        adap_emac->TXCONTROL = 0x01;
 386        adap_emac->RXCONTROL = 0x01;
 387
 388        /* Set MAC Addresses & Init multicast Hash to 0 (disable any multicast receive) */
 389        /* Using channel 0 only - other channels are disabled */
 390        adap_emac->MACINDEX = 0;
 391        adap_emac->MACADDRHI =
 392                (davinci_eth_mac_addr[3] << 24) |
 393                (davinci_eth_mac_addr[2] << 16) |
 394                (davinci_eth_mac_addr[1] << 8)  |
 395                (davinci_eth_mac_addr[0]);
 396        adap_emac->MACADDRLO =
 397                (davinci_eth_mac_addr[5] << 8) |
 398                (davinci_eth_mac_addr[4]);
 399
 400        adap_emac->MACHASH1 = 0;
 401        adap_emac->MACHASH2 = 0;
 402
 403        /* Set source MAC address - REQUIRED */
 404        adap_emac->MACSRCADDRHI =
 405                (davinci_eth_mac_addr[3] << 24) |
 406                (davinci_eth_mac_addr[2] << 16) |
 407                (davinci_eth_mac_addr[1] << 8)  |
 408                (davinci_eth_mac_addr[0]);
 409        adap_emac->MACSRCADDRLO =
 410                (davinci_eth_mac_addr[4] << 8) |
 411                (davinci_eth_mac_addr[5]);
 412
 413        /* Set DMA 8 TX / 8 RX Head pointers to 0 */
 414        addr = &adap_emac->TX0HDP;
 415        for(cnt = 0; cnt < 16; cnt++)
 416                *addr++ = 0;
 417
 418        addr = &adap_emac->RX0HDP;
 419        for(cnt = 0; cnt < 16; cnt++)
 420                *addr++ = 0;
 421
 422        /* Clear Statistics (do this before setting MacControl register) */
 423        addr = &adap_emac->RXGOODFRAMES;
 424        for(cnt = 0; cnt < EMAC_NUM_STATS; cnt++)
 425                *addr++ = 0;
 426
 427        /* No multicast addressing */
 428        adap_emac->MACHASH1 = 0;
 429        adap_emac->MACHASH2 = 0;
 430
 431        /* Create RX queue and set receive process in place */
 432        emac_rx_active_head = emac_rx_desc;
 433        for (cnt = 0; cnt < EMAC_MAX_RX_BUFFERS; cnt++) {
 434                rx_desc->next = (u_int32_t)(rx_desc + 1);
 435                rx_desc->buffer = &emac_rx_buffers[cnt * (EMAC_MAX_ETHERNET_PKT_SIZE + EMAC_PKT_ALIGN)];
 436                rx_desc->buff_off_len = EMAC_MAX_ETHERNET_PKT_SIZE;
 437                rx_desc->pkt_flag_len = EMAC_CPPI_OWNERSHIP_BIT;
 438                rx_desc++;
 439        }
 440
 441        /* Set the last descriptor's "next" parameter to 0 to end the RX desc list */
 442        rx_desc--;
 443        rx_desc->next = 0;
 444        emac_rx_active_tail = rx_desc;
 445        emac_rx_queue_active = 1;
 446
 447        /* Enable TX/RX */
 448        adap_emac->RXMAXLEN = EMAC_MAX_ETHERNET_PKT_SIZE;
 449        adap_emac->RXBUFFEROFFSET = 0;
 450
 451        /* No fancy configs - Use this for promiscous for debug - EMAC_RXMBPENABLE_RXCAFEN_ENABLE */
 452        adap_emac->RXMBPENABLE = EMAC_RXMBPENABLE_RXBROADEN;
 453
 454        /* Enable ch 0 only */
 455        adap_emac->RXUNICASTSET = 0x01;
 456
 457        /* Enable MII interface and Full duplex mode */
 458        adap_emac->MACCONTROL = (EMAC_MACCONTROL_MIIEN_ENABLE | EMAC_MACCONTROL_FULLDUPLEX_ENABLE);
 459
 460        /* Init MDIO & get link state */
 461        clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1;
 462        adap_mdio->CONTROL = ((clkdiv & 0xff) | MDIO_CONTROL_ENABLE | MDIO_CONTROL_FAULT);
 463
 464        if (!phy.get_link_speed(active_phy_addr))
 465                return(0);
 466
 467        /* Start receive process */
 468        adap_emac->RX0HDP = (u_int32_t)emac_rx_desc;
 469
 470        debug_emac("- emac_open\n");
 471
 472        return(1);
 473}
 474
 475/* EMAC Channel Teardown */
 476static void davinci_eth_ch_teardown(int ch)
 477{
 478        dv_reg          dly = 0xff;
 479        dv_reg          cnt;
 480
 481        debug_emac("+ emac_ch_teardown\n");
 482
 483        if (ch == EMAC_CH_TX) {
 484                /* Init TX channel teardown */
 485                adap_emac->TXTEARDOWN = 1;
 486                for(cnt = 0; cnt != 0xfffffffc; cnt = adap_emac->TX0CP) {
 487                        /* Wait here for Tx teardown completion interrupt to occur
 488                         * Note: A task delay can be called here to pend rather than
 489                         * occupying CPU cycles - anyway it has been found that teardown
 490                         * takes very few cpu cycles and does not affect functionality */
 491                         dly--;
 492                         udelay(1);
 493                         if (dly == 0)
 494                                break;
 495                }
 496                adap_emac->TX0CP = cnt;
 497                adap_emac->TX0HDP = 0;
 498        } else {
 499                /* Init RX channel teardown */
 500                adap_emac->RXTEARDOWN = 1;
 501                for(cnt = 0; cnt != 0xfffffffc; cnt = adap_emac->RX0CP) {
 502                        /* Wait here for Rx teardown completion interrupt to occur
 503                         * Note: A task delay can be called here to pend rather than
 504                         * occupying CPU cycles - anyway it has been found that teardown
 505                         * takes very few cpu cycles and does not affect functionality */
 506                         dly--;
 507                         udelay(1);
 508                         if (dly == 0)
 509                                break;
 510                }
 511                adap_emac->RX0CP = cnt;
 512                adap_emac->RX0HDP = 0;
 513        }
 514
 515        debug_emac("- emac_ch_teardown\n");
 516}
 517
 518/* Eth device close */
 519static int davinci_eth_close(void)
 520{
 521        debug_emac("+ emac_close\n");
 522
 523        davinci_eth_ch_teardown(EMAC_CH_TX);    /* TX Channel teardown */
 524        davinci_eth_ch_teardown(EMAC_CH_RX);    /* RX Channel teardown */
 525
 526        /* Reset EMAC module and disable interrupts in wrapper */
 527        adap_emac->SOFTRESET = 1;
 528        adap_ewrap->EWCTL = 0;
 529
 530        debug_emac("- emac_close\n");
 531        return(1);
 532}
 533
 534static int tx_send_loop = 0;
 535
 536/*
 537 * This function sends a single packet on the network and returns
 538 * positive number (number of bytes transmitted) or negative for error
 539 */
 540static int davinci_eth_send_packet (volatile void *packet, int length)
 541{
 542        int ret_status = -1;
 543
 544        tx_send_loop = 0;
 545
 546        /* Return error if no link */
 547        if (!phy.get_link_speed (active_phy_addr)) {
 548                printf ("WARN: emac_send_packet: No link\n");
 549                return (ret_status);
 550        }
 551
 552        /* Check packet size and if < EMAC_MIN_ETHERNET_PKT_SIZE, pad it up */
 553        if (length < EMAC_MIN_ETHERNET_PKT_SIZE) {
 554                length = EMAC_MIN_ETHERNET_PKT_SIZE;
 555        }
 556
 557        /* Populate the TX descriptor */
 558        emac_tx_desc->next = 0;
 559        emac_tx_desc->buffer = (u_int8_t *) packet;
 560        emac_tx_desc->buff_off_len = (length & 0xffff);
 561        emac_tx_desc->pkt_flag_len = ((length & 0xffff) |
 562                                      EMAC_CPPI_SOP_BIT |
 563                                      EMAC_CPPI_OWNERSHIP_BIT |
 564                                      EMAC_CPPI_EOP_BIT);
 565        /* Send the packet */
 566        adap_emac->TX0HDP = (unsigned int) emac_tx_desc;
 567
 568        /* Wait for packet to complete or link down */
 569        while (1) {
 570                if (!phy.get_link_speed (active_phy_addr)) {
 571                        davinci_eth_ch_teardown (EMAC_CH_TX);
 572                        return (ret_status);
 573                }
 574                if (adap_emac->TXINTSTATRAW & 0x01) {
 575                        ret_status = length;
 576                        break;
 577                }
 578                tx_send_loop++;
 579        }
 580
 581        return (ret_status);
 582}
 583
 584/*
 585 * This function handles receipt of a packet from the network
 586 */
 587static int davinci_eth_rcv_packet (void)
 588{
 589        volatile emac_desc *rx_curr_desc;
 590        volatile emac_desc *curr_desc;
 591        volatile emac_desc *tail_desc;
 592        int status, ret = -1;
 593
 594        rx_curr_desc = emac_rx_active_head;
 595        status = rx_curr_desc->pkt_flag_len;
 596        if ((rx_curr_desc) && ((status & EMAC_CPPI_OWNERSHIP_BIT) == 0)) {
 597                if (status & EMAC_CPPI_RX_ERROR_FRAME) {
 598                        /* Error in packet - discard it and requeue desc */
 599                        printf ("WARN: emac_rcv_pkt: Error in packet\n");
 600                } else {
 601                        NetReceive (rx_curr_desc->buffer,
 602                                    (rx_curr_desc->buff_off_len & 0xffff));
 603                        ret = rx_curr_desc->buff_off_len & 0xffff;
 604                }
 605
 606                /* Ack received packet descriptor */
 607                adap_emac->RX0CP = (unsigned int) rx_curr_desc;
 608                curr_desc = rx_curr_desc;
 609                emac_rx_active_head =
 610                        (volatile emac_desc *) rx_curr_desc->next;
 611
 612                if (status & EMAC_CPPI_EOQ_BIT) {
 613                        if (emac_rx_active_head) {
 614                                adap_emac->RX0HDP =
 615                                        (unsigned int) emac_rx_active_head;
 616                        } else {
 617                                emac_rx_queue_active = 0;
 618                                printf ("INFO:emac_rcv_packet: RX Queue not active\n");
 619                        }
 620                }
 621
 622                /* Recycle RX descriptor */
 623                rx_curr_desc->buff_off_len = EMAC_MAX_ETHERNET_PKT_SIZE;
 624                rx_curr_desc->pkt_flag_len = EMAC_CPPI_OWNERSHIP_BIT;
 625                rx_curr_desc->next = 0;
 626
 627                if (emac_rx_active_head == 0) {
 628                        printf ("INFO: emac_rcv_pkt: active queue head = 0\n");
 629                        emac_rx_active_head = curr_desc;
 630                        emac_rx_active_tail = curr_desc;
 631                        if (emac_rx_queue_active != 0) {
 632                                adap_emac->RX0HDP =
 633                                        (unsigned int) emac_rx_active_head;
 634                                printf ("INFO: emac_rcv_pkt: active queue head = 0, HDP fired\n");
 635                                emac_rx_queue_active = 1;
 636                        }
 637                } else {
 638                        tail_desc = emac_rx_active_tail;
 639                        emac_rx_active_tail = curr_desc;
 640                        tail_desc->next = (unsigned int) curr_desc;
 641                        status = tail_desc->pkt_flag_len;
 642                        if (status & EMAC_CPPI_EOQ_BIT) {
 643                                adap_emac->RX0HDP = (unsigned int) curr_desc;
 644                                status &= ~EMAC_CPPI_EOQ_BIT;
 645                                tail_desc->pkt_flag_len = status;
 646                        }
 647                }
 648                return (ret);
 649        }
 650        return (0);
 651}
 652
 653#endif /* CONFIG_CMD_NET */
 654
 655#endif /* CONFIG_DRIVER_TI_EMAC */
 656