uboot/drivers/net/mvgbe.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2009
   3 * Marvell Semiconductor <www.marvell.com>
   4 * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
   5 *
   6 * (C) Copyright 2003
   7 * Ingo Assmus <ingo.assmus@keymile.com>
   8 *
   9 * based on - Driver for MV64360X ethernet ports
  10 * Copyright (C) 2002 rabeeh@galileo.co.il
  11 *
  12 * See file CREDITS for list of people who contributed to this
  13 * project.
  14 *
  15 * This program is free software; you can redistribute it and/or
  16 * modify it under the terms of the GNU General Public License as
  17 * published by the Free Software Foundation; either version 2 of
  18 * the License, or (at your option) any later version.
  19 *
  20 * This program is distributed in the hope that it will be useful,
  21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23 * GNU General Public License for more details.
  24 *
  25 * You should have received a copy of the GNU General Public License
  26 * along with this program; if not, write to the Free Software
  27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  28 * MA 02110-1301 USA
  29 */
  30
  31#include <common.h>
  32#include <net.h>
  33#include <malloc.h>
  34#include <miiphy.h>
  35#include <asm/io.h>
  36#include <asm/errno.h>
  37#include <asm/types.h>
  38#include <asm/system.h>
  39#include <asm/byteorder.h>
  40#include <asm/arch/cpu.h>
  41
  42#if defined(CONFIG_KIRKWOOD)
  43#include <asm/arch/kirkwood.h>
  44#elif defined(CONFIG_ORION5X)
  45#include <asm/arch/orion5x.h>
  46#endif
  47
  48#include "mvgbe.h"
  49
  50DECLARE_GLOBAL_DATA_PTR;
  51
  52#define MV_PHY_ADR_REQUEST 0xee
  53#define MVGBE_SMI_REG (((struct mvgbe_registers *)MVGBE0_BASE)->smi)
  54
  55#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
  56/*
  57 * smi_reg_read - miiphy_read callback function.
  58 *
  59 * Returns 16bit phy register value, or 0xffff on error
  60 */
  61static int smi_reg_read(const char *devname, u8 phy_adr, u8 reg_ofs, u16 * data)
  62{
  63        struct eth_device *dev = eth_get_dev_by_name(devname);
  64        struct mvgbe_device *dmvgbe = to_mvgbe(dev);
  65        struct mvgbe_registers *regs = dmvgbe->regs;
  66        u32 smi_reg;
  67        u32 timeout;
  68
  69        /* Phyadr read request */
  70        if (phy_adr == MV_PHY_ADR_REQUEST &&
  71                        reg_ofs == MV_PHY_ADR_REQUEST) {
  72                /* */
  73                *data = (u16) (MVGBE_REG_RD(regs->phyadr) & PHYADR_MASK);
  74                return 0;
  75        }
  76        /* check parameters */
  77        if (phy_adr > PHYADR_MASK) {
  78                printf("Err..(%s) Invalid PHY address %d\n",
  79                        __FUNCTION__, phy_adr);
  80                return -EFAULT;
  81        }
  82        if (reg_ofs > PHYREG_MASK) {
  83                printf("Err..(%s) Invalid register offset %d\n",
  84                        __FUNCTION__, reg_ofs);
  85                return -EFAULT;
  86        }
  87
  88        timeout = MVGBE_PHY_SMI_TIMEOUT;
  89        /* wait till the SMI is not busy */
  90        do {
  91                /* read smi register */
  92                smi_reg = MVGBE_REG_RD(MVGBE_SMI_REG);
  93                if (timeout-- == 0) {
  94                        printf("Err..(%s) SMI busy timeout\n", __FUNCTION__);
  95                        return -EFAULT;
  96                }
  97        } while (smi_reg & MVGBE_PHY_SMI_BUSY_MASK);
  98
  99        /* fill the phy address and regiser offset and read opcode */
 100        smi_reg = (phy_adr << MVGBE_PHY_SMI_DEV_ADDR_OFFS)
 101                | (reg_ofs << MVGBE_SMI_REG_ADDR_OFFS)
 102                | MVGBE_PHY_SMI_OPCODE_READ;
 103
 104        /* write the smi register */
 105        MVGBE_REG_WR(MVGBE_SMI_REG, smi_reg);
 106
 107        /*wait till read value is ready */
 108        timeout = MVGBE_PHY_SMI_TIMEOUT;
 109
 110        do {
 111                /* read smi register */
 112                smi_reg = MVGBE_REG_RD(MVGBE_SMI_REG);
 113                if (timeout-- == 0) {
 114                        printf("Err..(%s) SMI read ready timeout\n",
 115                                __FUNCTION__);
 116                        return -EFAULT;
 117                }
 118        } while (!(smi_reg & MVGBE_PHY_SMI_READ_VALID_MASK));
 119
 120        /* Wait for the data to update in the SMI register */
 121        for (timeout = 0; timeout < MVGBE_PHY_SMI_TIMEOUT; timeout++)
 122                ;
 123
 124        *data = (u16) (MVGBE_REG_RD(MVGBE_SMI_REG) & MVGBE_PHY_SMI_DATA_MASK);
 125
 126        debug("%s:(adr %d, off %d) value= %04x\n", __FUNCTION__, phy_adr,
 127                reg_ofs, *data);
 128
 129        return 0;
 130}
 131
 132/*
 133 * smi_reg_write - imiiphy_write callback function.
 134 *
 135 * Returns 0 if write succeed, -EINVAL on bad parameters
 136 * -ETIME on timeout
 137 */
 138static int smi_reg_write(const char *devname, u8 phy_adr, u8 reg_ofs, u16 data)
 139{
 140        struct eth_device *dev = eth_get_dev_by_name(devname);
 141        struct mvgbe_device *dmvgbe = to_mvgbe(dev);
 142        struct mvgbe_registers *regs = dmvgbe->regs;
 143        u32 smi_reg;
 144        u32 timeout;
 145
 146        /* Phyadr write request*/
 147        if (phy_adr == MV_PHY_ADR_REQUEST &&
 148                        reg_ofs == MV_PHY_ADR_REQUEST) {
 149                MVGBE_REG_WR(regs->phyadr, data);
 150                return 0;
 151        }
 152
 153        /* check parameters */
 154        if (phy_adr > PHYADR_MASK) {
 155                printf("Err..(%s) Invalid phy address\n", __FUNCTION__);
 156                return -EINVAL;
 157        }
 158        if (reg_ofs > PHYREG_MASK) {
 159                printf("Err..(%s) Invalid register offset\n", __FUNCTION__);
 160                return -EINVAL;
 161        }
 162
 163        /* wait till the SMI is not busy */
 164        timeout = MVGBE_PHY_SMI_TIMEOUT;
 165        do {
 166                /* read smi register */
 167                smi_reg = MVGBE_REG_RD(MVGBE_SMI_REG);
 168                if (timeout-- == 0) {
 169                        printf("Err..(%s) SMI busy timeout\n", __FUNCTION__);
 170                        return -ETIME;
 171                }
 172        } while (smi_reg & MVGBE_PHY_SMI_BUSY_MASK);
 173
 174        /* fill the phy addr and reg offset and write opcode and data */
 175        smi_reg = (data << MVGBE_PHY_SMI_DATA_OFFS);
 176        smi_reg |= (phy_adr << MVGBE_PHY_SMI_DEV_ADDR_OFFS)
 177                | (reg_ofs << MVGBE_SMI_REG_ADDR_OFFS);
 178        smi_reg &= ~MVGBE_PHY_SMI_OPCODE_READ;
 179
 180        /* write the smi register */
 181        MVGBE_REG_WR(MVGBE_SMI_REG, smi_reg);
 182
 183        return 0;
 184}
 185#endif
 186
 187/* Stop and checks all queues */
 188static void stop_queue(u32 * qreg)
 189{
 190        u32 reg_data;
 191
 192        reg_data = readl(qreg);
 193
 194        if (reg_data & 0xFF) {
 195                /* Issue stop command for active channels only */
 196                writel((reg_data << 8), qreg);
 197
 198                /* Wait for all queue activity to terminate. */
 199                do {
 200                        /*
 201                         * Check port cause register that all queues
 202                         * are stopped
 203                         */
 204                        reg_data = readl(qreg);
 205                }
 206                while (reg_data & 0xFF);
 207        }
 208}
 209
 210/*
 211 * set_access_control - Config address decode parameters for Ethernet unit
 212 *
 213 * This function configures the address decode parameters for the Gigabit
 214 * Ethernet Controller according the given parameters struct.
 215 *
 216 * @regs        Register struct pointer.
 217 * @param       Address decode parameter struct.
 218 */
 219static void set_access_control(struct mvgbe_registers *regs,
 220                                struct mvgbe_winparam *param)
 221{
 222        u32 access_prot_reg;
 223
 224        /* Set access control register */
 225        access_prot_reg = MVGBE_REG_RD(regs->epap);
 226        /* clear window permission */
 227        access_prot_reg &= (~(3 << (param->win * 2)));
 228        access_prot_reg |= (param->access_ctrl << (param->win * 2));
 229        MVGBE_REG_WR(regs->epap, access_prot_reg);
 230
 231        /* Set window Size reg (SR) */
 232        MVGBE_REG_WR(regs->barsz[param->win].size,
 233                        (((param->size / 0x10000) - 1) << 16));
 234
 235        /* Set window Base address reg (BA) */
 236        MVGBE_REG_WR(regs->barsz[param->win].bar,
 237                        (param->target | param->attrib | param->base_addr));
 238        /* High address remap reg (HARR) */
 239        if (param->win < 4)
 240                MVGBE_REG_WR(regs->ha_remap[param->win], param->high_addr);
 241
 242        /* Base address enable reg (BARER) */
 243        if (param->enable == 1)
 244                MVGBE_REG_BITS_RESET(regs->bare, (1 << param->win));
 245        else
 246                MVGBE_REG_BITS_SET(regs->bare, (1 << param->win));
 247}
 248
 249static void set_dram_access(struct mvgbe_registers *regs)
 250{
 251        struct mvgbe_winparam win_param;
 252        int i;
 253
 254        for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
 255                /* Set access parameters for DRAM bank i */
 256                win_param.win = i;      /* Use Ethernet window i */
 257                /* Window target - DDR */
 258                win_param.target = MVGBE_TARGET_DRAM;
 259                /* Enable full access */
 260                win_param.access_ctrl = EWIN_ACCESS_FULL;
 261                win_param.high_addr = 0;
 262                /* Get bank base and size */
 263                win_param.base_addr = gd->bd->bi_dram[i].start;
 264                win_param.size = gd->bd->bi_dram[i].size;
 265                if (win_param.size == 0)
 266                        win_param.enable = 0;
 267                else
 268                        win_param.enable = 1;   /* Enable the access */
 269
 270                /* Enable DRAM bank */
 271                switch (i) {
 272                case 0:
 273                        win_param.attrib = EBAR_DRAM_CS0;
 274                        break;
 275                case 1:
 276                        win_param.attrib = EBAR_DRAM_CS1;
 277                        break;
 278                case 2:
 279                        win_param.attrib = EBAR_DRAM_CS2;
 280                        break;
 281                case 3:
 282                        win_param.attrib = EBAR_DRAM_CS3;
 283                        break;
 284                default:
 285                        /* invalid bank, disable access */
 286                        win_param.enable = 0;
 287                        win_param.attrib = 0;
 288                        break;
 289                }
 290                /* Set the access control for address window(EPAPR) RD/WR */
 291                set_access_control(regs, &win_param);
 292        }
 293}
 294
 295/*
 296 * port_init_mac_tables - Clear all entrance in the UC, SMC and OMC tables
 297 *
 298 * Go through all the DA filter tables (Unicast, Special Multicast & Other
 299 * Multicast) and set each entry to 0.
 300 */
 301static void port_init_mac_tables(struct mvgbe_registers *regs)
 302{
 303        int table_index;
 304
 305        /* Clear DA filter unicast table (Ex_dFUT) */
 306        for (table_index = 0; table_index < 4; ++table_index)
 307                MVGBE_REG_WR(regs->dfut[table_index], 0);
 308
 309        for (table_index = 0; table_index < 64; ++table_index) {
 310                /* Clear DA filter special multicast table (Ex_dFSMT) */
 311                MVGBE_REG_WR(regs->dfsmt[table_index], 0);
 312                /* Clear DA filter other multicast table (Ex_dFOMT) */
 313                MVGBE_REG_WR(regs->dfomt[table_index], 0);
 314        }
 315}
 316
 317/*
 318 * port_uc_addr - This function Set the port unicast address table
 319 *
 320 * This function locates the proper entry in the Unicast table for the
 321 * specified MAC nibble and sets its properties according to function
 322 * parameters.
 323 * This function add/removes MAC addresses from the port unicast address
 324 * table.
 325 *
 326 * @uc_nibble   Unicast MAC Address last nibble.
 327 * @option      0 = Add, 1 = remove address.
 328 *
 329 * RETURN: 1 if output succeeded. 0 if option parameter is invalid.
 330 */
 331static int port_uc_addr(struct mvgbe_registers *regs, u8 uc_nibble,
 332                        int option)
 333{
 334        u32 unicast_reg;
 335        u32 tbl_offset;
 336        u32 reg_offset;
 337
 338        /* Locate the Unicast table entry */
 339        uc_nibble = (0xf & uc_nibble);
 340        /* Register offset from unicast table base */
 341        tbl_offset = (uc_nibble / 4);
 342        /* Entry offset within the above register */
 343        reg_offset = uc_nibble % 4;
 344
 345        switch (option) {
 346        case REJECT_MAC_ADDR:
 347                /*
 348                 * Clear accepts frame bit at specified unicast
 349                 * DA table entry
 350                 */
 351                unicast_reg = MVGBE_REG_RD(regs->dfut[tbl_offset]);
 352                unicast_reg &= (0xFF << (8 * reg_offset));
 353                MVGBE_REG_WR(regs->dfut[tbl_offset], unicast_reg);
 354                break;
 355        case ACCEPT_MAC_ADDR:
 356                /* Set accepts frame bit at unicast DA filter table entry */
 357                unicast_reg = MVGBE_REG_RD(regs->dfut[tbl_offset]);
 358                unicast_reg &= (0xFF << (8 * reg_offset));
 359                unicast_reg |= ((0x01 | (RXUQ << 1)) << (8 * reg_offset));
 360                MVGBE_REG_WR(regs->dfut[tbl_offset], unicast_reg);
 361                break;
 362        default:
 363                return 0;
 364        }
 365        return 1;
 366}
 367
 368/*
 369 * port_uc_addr_set - This function Set the port Unicast address.
 370 */
 371static void port_uc_addr_set(struct mvgbe_registers *regs, u8 * p_addr)
 372{
 373        u32 mac_h;
 374        u32 mac_l;
 375
 376        mac_l = (p_addr[4] << 8) | (p_addr[5]);
 377        mac_h = (p_addr[0] << 24) | (p_addr[1] << 16) | (p_addr[2] << 8) |
 378                (p_addr[3] << 0);
 379
 380        MVGBE_REG_WR(regs->macal, mac_l);
 381        MVGBE_REG_WR(regs->macah, mac_h);
 382
 383        /* Accept frames of this address */
 384        port_uc_addr(regs, p_addr[5], ACCEPT_MAC_ADDR);
 385}
 386
 387/*
 388 * mvgbe_init_rx_desc_ring - Curve a Rx chain desc list and buffer in memory.
 389 */
 390static void mvgbe_init_rx_desc_ring(struct mvgbe_device *dmvgbe)
 391{
 392        struct mvgbe_rxdesc *p_rx_desc;
 393        int i;
 394
 395        /* initialize the Rx descriptors ring */
 396        p_rx_desc = dmvgbe->p_rxdesc;
 397        for (i = 0; i < RINGSZ; i++) {
 398                p_rx_desc->cmd_sts =
 399                        MVGBE_BUFFER_OWNED_BY_DMA | MVGBE_RX_EN_INTERRUPT;
 400                p_rx_desc->buf_size = PKTSIZE_ALIGN;
 401                p_rx_desc->byte_cnt = 0;
 402                p_rx_desc->buf_ptr = dmvgbe->p_rxbuf + i * PKTSIZE_ALIGN;
 403                if (i == (RINGSZ - 1))
 404                        p_rx_desc->nxtdesc_p = dmvgbe->p_rxdesc;
 405                else {
 406                        p_rx_desc->nxtdesc_p = (struct mvgbe_rxdesc *)
 407                                ((u32) p_rx_desc + MV_RXQ_DESC_ALIGNED_SIZE);
 408                        p_rx_desc = p_rx_desc->nxtdesc_p;
 409                }
 410        }
 411        dmvgbe->p_rxdesc_curr = dmvgbe->p_rxdesc;
 412}
 413
 414static int mvgbe_init(struct eth_device *dev)
 415{
 416        struct mvgbe_device *dmvgbe = to_mvgbe(dev);
 417        struct mvgbe_registers *regs = dmvgbe->regs;
 418#if (defined (CONFIG_MII) || defined (CONFIG_CMD_MII)) \
 419         && defined (CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
 420        int i;
 421#endif
 422        /* setup RX rings */
 423        mvgbe_init_rx_desc_ring(dmvgbe);
 424
 425        /* Clear the ethernet port interrupts */
 426        MVGBE_REG_WR(regs->ic, 0);
 427        MVGBE_REG_WR(regs->ice, 0);
 428        /* Unmask RX buffer and TX end interrupt */
 429        MVGBE_REG_WR(regs->pim, INT_CAUSE_UNMASK_ALL);
 430        /* Unmask phy and link status changes interrupts */
 431        MVGBE_REG_WR(regs->peim, INT_CAUSE_UNMASK_ALL_EXT);
 432
 433        set_dram_access(regs);
 434        port_init_mac_tables(regs);
 435        port_uc_addr_set(regs, dmvgbe->dev.enetaddr);
 436
 437        /* Assign port configuration and command. */
 438        MVGBE_REG_WR(regs->pxc, PRT_CFG_VAL);
 439        MVGBE_REG_WR(regs->pxcx, PORT_CFG_EXTEND_VALUE);
 440        MVGBE_REG_WR(regs->psc0, PORT_SERIAL_CONTROL_VALUE);
 441
 442        /* Assign port SDMA configuration */
 443        MVGBE_REG_WR(regs->sdc, PORT_SDMA_CFG_VALUE);
 444        MVGBE_REG_WR(regs->tqx[0].qxttbc, QTKNBKT_DEF_VAL);
 445        MVGBE_REG_WR(regs->tqx[0].tqxtbc,
 446                (QMTBS_DEF_VAL << 16) | QTKNRT_DEF_VAL);
 447        /* Turn off the port/RXUQ bandwidth limitation */
 448        MVGBE_REG_WR(regs->pmtu, 0);
 449
 450        /* Set maximum receive buffer to 9700 bytes */
 451        MVGBE_REG_WR(regs->psc0, MVGBE_MAX_RX_PACKET_9700BYTE
 452                        | (MVGBE_REG_RD(regs->psc0) & MRU_MASK));
 453
 454        /* Enable port initially */
 455        MVGBE_REG_BITS_SET(regs->psc0, MVGBE_SERIAL_PORT_EN);
 456
 457        /*
 458         * Set ethernet MTU for leaky bucket mechanism to 0 - this will
 459         * disable the leaky bucket mechanism .
 460         */
 461        MVGBE_REG_WR(regs->pmtu, 0);
 462
 463        /* Assignment of Rx CRDB of given RXUQ */
 464        MVGBE_REG_WR(regs->rxcdp[RXUQ], (u32) dmvgbe->p_rxdesc_curr);
 465        /* ensure previous write is done before enabling Rx DMA */
 466        isb();
 467        /* Enable port Rx. */
 468        MVGBE_REG_WR(regs->rqc, (1 << RXUQ));
 469
 470#if (defined (CONFIG_MII) || defined (CONFIG_CMD_MII)) \
 471         && defined (CONFIG_SYS_FAULT_ECHO_LINK_DOWN)
 472        /* Wait up to 5s for the link status */
 473        for (i = 0; i < 5; i++) {
 474                u16 phyadr;
 475
 476                miiphy_read(dev->name, MV_PHY_ADR_REQUEST,
 477                                MV_PHY_ADR_REQUEST, &phyadr);
 478                /* Return if we get link up */
 479                if (miiphy_link(dev->name, phyadr))
 480                        return 0;
 481                udelay(1000000);
 482        }
 483
 484        printf("No link on %s\n", dev->name);
 485        return -1;
 486#endif
 487        return 0;
 488}
 489
 490static int mvgbe_halt(struct eth_device *dev)
 491{
 492        struct mvgbe_device *dmvgbe = to_mvgbe(dev);
 493        struct mvgbe_registers *regs = dmvgbe->regs;
 494
 495        /* Disable all gigE address decoder */
 496        MVGBE_REG_WR(regs->bare, 0x3f);
 497
 498        stop_queue(&regs->tqc);
 499        stop_queue(&regs->rqc);
 500
 501        /* Disable port */
 502        MVGBE_REG_BITS_RESET(regs->psc0, MVGBE_SERIAL_PORT_EN);
 503        /* Set port is not reset */
 504        MVGBE_REG_BITS_RESET(regs->psc1, 1 << 4);
 505#ifdef CONFIG_SYS_MII_MODE
 506        /* Set MMI interface up */
 507        MVGBE_REG_BITS_RESET(regs->psc1, 1 << 3);
 508#endif
 509        /* Disable & mask ethernet port interrupts */
 510        MVGBE_REG_WR(regs->ic, 0);
 511        MVGBE_REG_WR(regs->ice, 0);
 512        MVGBE_REG_WR(regs->pim, 0);
 513        MVGBE_REG_WR(regs->peim, 0);
 514
 515        return 0;
 516}
 517
 518static int mvgbe_write_hwaddr(struct eth_device *dev)
 519{
 520        struct mvgbe_device *dmvgbe = to_mvgbe(dev);
 521        struct mvgbe_registers *regs = dmvgbe->regs;
 522
 523        /* Programs net device MAC address after initialization */
 524        port_uc_addr_set(regs, dmvgbe->dev.enetaddr);
 525        return 0;
 526}
 527
 528static int mvgbe_send(struct eth_device *dev, void *dataptr, int datasize)
 529{
 530        struct mvgbe_device *dmvgbe = to_mvgbe(dev);
 531        struct mvgbe_registers *regs = dmvgbe->regs;
 532        struct mvgbe_txdesc *p_txdesc = dmvgbe->p_txdesc;
 533        void *p = (void *)dataptr;
 534        u32 cmd_sts;
 535        u32 txuq0_reg_addr;
 536
 537        /* Copy buffer if it's misaligned */
 538        if ((u32) dataptr & 0x07) {
 539                if (datasize > PKTSIZE_ALIGN) {
 540                        printf("Non-aligned data too large (%d)\n",
 541                                        datasize);
 542                        return -1;
 543                }
 544
 545                memcpy(dmvgbe->p_aligned_txbuf, p, datasize);
 546                p = dmvgbe->p_aligned_txbuf;
 547        }
 548
 549        p_txdesc->cmd_sts = MVGBE_ZERO_PADDING | MVGBE_GEN_CRC;
 550        p_txdesc->cmd_sts |= MVGBE_TX_FIRST_DESC | MVGBE_TX_LAST_DESC;
 551        p_txdesc->cmd_sts |= MVGBE_BUFFER_OWNED_BY_DMA;
 552        p_txdesc->cmd_sts |= MVGBE_TX_EN_INTERRUPT;
 553        p_txdesc->buf_ptr = (u8 *) p;
 554        p_txdesc->byte_cnt = datasize;
 555
 556        /* Set this tc desc as zeroth TXUQ */
 557        txuq0_reg_addr = (u32)&regs->tcqdp[TXUQ];
 558        writel((u32) p_txdesc, txuq0_reg_addr);
 559
 560        /* ensure tx desc writes above are performed before we start Tx DMA */
 561        isb();
 562
 563        /* Apply send command using zeroth TXUQ */
 564        MVGBE_REG_WR(regs->tqc, (1 << TXUQ));
 565
 566        /*
 567         * wait for packet xmit completion
 568         */
 569        cmd_sts = readl(&p_txdesc->cmd_sts);
 570        while (cmd_sts & MVGBE_BUFFER_OWNED_BY_DMA) {
 571                /* return fail if error is detected */
 572                if ((cmd_sts & (MVGBE_ERROR_SUMMARY | MVGBE_TX_LAST_FRAME)) ==
 573                                (MVGBE_ERROR_SUMMARY | MVGBE_TX_LAST_FRAME) &&
 574                                cmd_sts & (MVGBE_UR_ERROR | MVGBE_RL_ERROR)) {
 575                        printf("Err..(%s) in xmit packet\n", __FUNCTION__);
 576                        return -1;
 577                }
 578                cmd_sts = readl(&p_txdesc->cmd_sts);
 579        };
 580        return 0;
 581}
 582
 583static int mvgbe_recv(struct eth_device *dev)
 584{
 585        struct mvgbe_device *dmvgbe = to_mvgbe(dev);
 586        struct mvgbe_rxdesc *p_rxdesc_curr = dmvgbe->p_rxdesc_curr;
 587        u32 cmd_sts;
 588        u32 timeout = 0;
 589        u32 rxdesc_curr_addr;
 590
 591        /* wait untill rx packet available or timeout */
 592        do {
 593                if (timeout < MVGBE_PHY_SMI_TIMEOUT)
 594                        timeout++;
 595                else {
 596                        debug("%s time out...\n", __FUNCTION__);
 597                        return -1;
 598                }
 599        } while (readl(&p_rxdesc_curr->cmd_sts) & MVGBE_BUFFER_OWNED_BY_DMA);
 600
 601        if (p_rxdesc_curr->byte_cnt != 0) {
 602                debug("%s: Received %d byte Packet @ 0x%x (cmd_sts= %08x)\n",
 603                        __FUNCTION__, (u32) p_rxdesc_curr->byte_cnt,
 604                        (u32) p_rxdesc_curr->buf_ptr,
 605                        (u32) p_rxdesc_curr->cmd_sts);
 606        }
 607
 608        /*
 609         * In case received a packet without first/last bits on
 610         * OR the error summary bit is on,
 611         * the packets needs to be dropeed.
 612         */
 613        cmd_sts = readl(&p_rxdesc_curr->cmd_sts);
 614
 615        if ((cmd_sts &
 616                (MVGBE_RX_FIRST_DESC | MVGBE_RX_LAST_DESC))
 617                != (MVGBE_RX_FIRST_DESC | MVGBE_RX_LAST_DESC)) {
 618
 619                printf("Err..(%s) Dropping packet spread on"
 620                        " multiple descriptors\n", __FUNCTION__);
 621
 622        } else if (cmd_sts & MVGBE_ERROR_SUMMARY) {
 623
 624                printf("Err..(%s) Dropping packet with errors\n",
 625                        __FUNCTION__);
 626
 627        } else {
 628                /* !!! call higher layer processing */
 629                debug("%s: Sending Received packet to"
 630                        " upper layer (NetReceive)\n", __FUNCTION__);
 631
 632                /* let the upper layer handle the packet */
 633                NetReceive((p_rxdesc_curr->buf_ptr + RX_BUF_OFFSET),
 634                        (int)(p_rxdesc_curr->byte_cnt - RX_BUF_OFFSET));
 635        }
 636        /*
 637         * free these descriptors and point next in the ring
 638         */
 639        p_rxdesc_curr->cmd_sts =
 640                MVGBE_BUFFER_OWNED_BY_DMA | MVGBE_RX_EN_INTERRUPT;
 641        p_rxdesc_curr->buf_size = PKTSIZE_ALIGN;
 642        p_rxdesc_curr->byte_cnt = 0;
 643
 644        rxdesc_curr_addr = (u32)&dmvgbe->p_rxdesc_curr;
 645        writel((unsigned)p_rxdesc_curr->nxtdesc_p, rxdesc_curr_addr);
 646
 647        return 0;
 648}
 649
 650int mvgbe_initialize(bd_t *bis)
 651{
 652        struct mvgbe_device *dmvgbe;
 653        struct eth_device *dev;
 654        int devnum;
 655        u8 used_ports[MAX_MVGBE_DEVS] = CONFIG_MVGBE_PORTS;
 656
 657        for (devnum = 0; devnum < MAX_MVGBE_DEVS; devnum++) {
 658                /*skip if port is configured not to use */
 659                if (used_ports[devnum] == 0)
 660                        continue;
 661
 662                dmvgbe = malloc(sizeof(struct mvgbe_device));
 663
 664                if (!dmvgbe)
 665                        goto error1;
 666
 667                memset(dmvgbe, 0, sizeof(struct mvgbe_device));
 668
 669                dmvgbe->p_rxdesc =
 670                        (struct mvgbe_rxdesc *)memalign(PKTALIGN,
 671                        MV_RXQ_DESC_ALIGNED_SIZE*RINGSZ + 1);
 672
 673                if (!dmvgbe->p_rxdesc)
 674                        goto error2;
 675
 676                dmvgbe->p_rxbuf = (u8 *) memalign(PKTALIGN,
 677                        RINGSZ*PKTSIZE_ALIGN + 1);
 678
 679                if (!dmvgbe->p_rxbuf)
 680                        goto error3;
 681
 682                dmvgbe->p_aligned_txbuf = memalign(8, PKTSIZE_ALIGN);
 683
 684                if (!dmvgbe->p_aligned_txbuf)
 685                        goto error4;
 686
 687                dmvgbe->p_txdesc = (struct mvgbe_txdesc *) memalign(
 688                        PKTALIGN, sizeof(struct mvgbe_txdesc) + 1);
 689
 690                if (!dmvgbe->p_txdesc) {
 691                        free(dmvgbe->p_aligned_txbuf);
 692error4:
 693                        free(dmvgbe->p_rxbuf);
 694error3:
 695                        free(dmvgbe->p_rxdesc);
 696error2:
 697                        free(dmvgbe);
 698error1:
 699                        printf("Err.. %s Failed to allocate memory\n",
 700                                __FUNCTION__);
 701                        return -1;
 702                }
 703
 704                dev = &dmvgbe->dev;
 705
 706                /* must be less than sizeof(dev->name) */
 707                sprintf(dev->name, "egiga%d", devnum);
 708
 709                switch (devnum) {
 710                case 0:
 711                        dmvgbe->regs = (void *)MVGBE0_BASE;
 712                        break;
 713#if defined(MVGBE1_BASE)
 714                case 1:
 715                        dmvgbe->regs = (void *)MVGBE1_BASE;
 716                        break;
 717#endif
 718                default:        /* this should never happen */
 719                        printf("Err..(%s) Invalid device number %d\n",
 720                                __FUNCTION__, devnum);
 721                        return -1;
 722                }
 723
 724                dev->init = (void *)mvgbe_init;
 725                dev->halt = (void *)mvgbe_halt;
 726                dev->send = (void *)mvgbe_send;
 727                dev->recv = (void *)mvgbe_recv;
 728                dev->write_hwaddr = (void *)mvgbe_write_hwaddr;
 729
 730                eth_register(dev);
 731
 732#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
 733                miiphy_register(dev->name, smi_reg_read, smi_reg_write);
 734                /* Set phy address of the port */
 735                miiphy_write(dev->name, MV_PHY_ADR_REQUEST,
 736                                MV_PHY_ADR_REQUEST, PHY_BASE_ADR + devnum);
 737#endif
 738        }
 739        return 0;
 740}
 741