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