uboot/drivers/net/greth.c
<<
>>
Prefs
   1/* Gaisler.com GRETH 10/100/1000 Ethernet MAC driver
   2 *
   3 * Driver use polling mode (no Interrupt)
   4 *
   5 * (C) Copyright 2007
   6 * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com
   7 *
   8 * See file CREDITS for list of people who contributed to this
   9 * project.
  10 *
  11 * This program is free software; you can redistribute it and/or
  12 * modify it under the terms of the GNU General Public License as
  13 * published by the Free Software Foundation; either version 2 of
  14 * the License, or (at your option) any later version.
  15 *
  16 * This program is distributed in the hope that it will be useful,
  17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19 * GNU General Public License for more details.
  20 *
  21 * You should have received a copy of the GNU General Public License
  22 * along with this program; if not, write to the Free Software
  23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  24 * MA 02111-1307 USA
  25 */
  26
  27/* #define DEBUG */
  28
  29#include <common.h>
  30#include <command.h>
  31#include <net.h>
  32#include <netdev.h>
  33#include <malloc.h>
  34#include <asm/processor.h>
  35#include <ambapp.h>
  36#include <asm/leon.h>
  37
  38#include "greth.h"
  39
  40/* Default to 3s timeout on autonegotiation */
  41#ifndef GRETH_PHY_TIMEOUT_MS
  42#define GRETH_PHY_TIMEOUT_MS 3000
  43#endif
  44
  45/* Default to PHY adrress 0 not not specified */
  46#ifdef CONFIG_SYS_GRLIB_GRETH_PHYADDR
  47#define GRETH_PHY_ADR_DEFAULT CONFIG_SYS_GRLIB_GRETH_PHYADDR
  48#else
  49#define GRETH_PHY_ADR_DEFAULT 0
  50#endif
  51
  52/* ByPass Cache when reading regs */
  53#define GRETH_REGLOAD(addr)             SPARC_NOCACHE_READ(addr)
  54/* Write-through cache ==> no bypassing needed on writes */
  55#define GRETH_REGSAVE(addr,data) (*(volatile unsigned int *)(addr) = (data))
  56#define GRETH_REGORIN(addr,data) GRETH_REGSAVE(addr,GRETH_REGLOAD(addr)|data)
  57#define GRETH_REGANDIN(addr,data) GRETH_REGSAVE(addr,GRETH_REGLOAD(addr)&data)
  58
  59#define GRETH_RXBD_CNT 4
  60#define GRETH_TXBD_CNT 1
  61
  62#define GRETH_RXBUF_SIZE 1540
  63#define GRETH_BUF_ALIGN 4
  64#define GRETH_RXBUF_EFF_SIZE \
  65        ( (GRETH_RXBUF_SIZE&~(GRETH_BUF_ALIGN-1))+GRETH_BUF_ALIGN )
  66
  67typedef struct {
  68        greth_regs *regs;
  69        int irq;
  70        struct eth_device *dev;
  71
  72        /* Hardware info */
  73        unsigned char phyaddr;
  74        int gbit_mac;
  75
  76        /* Current operating Mode */
  77        int gb;                 /* GigaBit */
  78        int fd;                 /* Full Duplex */
  79        int sp;                 /* 10/100Mbps speed (1=100,0=10) */
  80        int auto_neg;           /* Auto negotiate done */
  81
  82        unsigned char hwaddr[6];        /* MAC Address */
  83
  84        /* Descriptors */
  85        greth_bd *rxbd_base, *rxbd_max;
  86        greth_bd *txbd_base, *txbd_max;
  87
  88        greth_bd *rxbd_curr;
  89
  90        /* rx buffers in rx descriptors */
  91        void *rxbuf_base;       /* (GRETH_RXBUF_SIZE+ALIGNBYTES) * GRETH_RXBD_CNT */
  92
  93        /* unused for gbit_mac, temp buffer for sending packets with unligned
  94         * start.
  95         * Pointer to packet allocated with malloc.
  96         */
  97        void *txbuf;
  98
  99        struct {
 100                /* rx status */
 101                unsigned int rx_packets,
 102                    rx_crc_errors, rx_frame_errors, rx_length_errors, rx_errors;
 103
 104                /* tx stats */
 105                unsigned int tx_packets,
 106                    tx_latecol_errors,
 107                    tx_underrun_errors, tx_limit_errors, tx_errors;
 108        } stats;
 109} greth_priv;
 110
 111/* Read MII register 'addr' from core 'regs' */
 112static int read_mii(int phyaddr, int regaddr, volatile greth_regs * regs)
 113{
 114        while (GRETH_REGLOAD(&regs->mdio) & GRETH_MII_BUSY) {
 115        }
 116
 117        GRETH_REGSAVE(&regs->mdio, ((phyaddr & 0x1F) << 11) | ((regaddr & 0x1F) << 6) | 2);
 118
 119        while (GRETH_REGLOAD(&regs->mdio) & GRETH_MII_BUSY) {
 120        }
 121
 122        if (!(GRETH_REGLOAD(&regs->mdio) & GRETH_MII_NVALID)) {
 123                return (GRETH_REGLOAD(&regs->mdio) >> 16) & 0xFFFF;
 124        } else {
 125                return -1;
 126        }
 127}
 128
 129static void write_mii(int phyaddr, int regaddr, int data, volatile greth_regs * regs)
 130{
 131        while (GRETH_REGLOAD(&regs->mdio) & GRETH_MII_BUSY) {
 132        }
 133
 134        GRETH_REGSAVE(&regs->mdio,
 135                      ((data & 0xFFFF) << 16) | ((phyaddr & 0x1F) << 11) |
 136                      ((regaddr & 0x1F) << 6) | 1);
 137
 138        while (GRETH_REGLOAD(&regs->mdio) & GRETH_MII_BUSY) {
 139        }
 140
 141}
 142
 143/* init/start hardware and allocate descriptor buffers for rx side
 144 *
 145 */
 146int greth_init(struct eth_device *dev, bd_t * bis)
 147{
 148        int i;
 149
 150        greth_priv *greth = dev->priv;
 151        greth_regs *regs = greth->regs;
 152
 153        debug("greth_init\n");
 154
 155        /* Reset core */
 156        GRETH_REGSAVE(&regs->control, (GRETH_RESET | (greth->gb << 8) |
 157                (greth->sp << 7) | (greth->fd << 4)));
 158
 159        /* Wait for Reset to complete */
 160        while ( GRETH_REGLOAD(&regs->control) & GRETH_RESET) ;
 161
 162        GRETH_REGSAVE(&regs->control,
 163                ((greth->gb << 8) | (greth->sp << 7) | (greth->fd << 4)));
 164
 165        if (!greth->rxbd_base) {
 166
 167                /* allocate descriptors */
 168                greth->rxbd_base = (greth_bd *)
 169                    memalign(0x1000, GRETH_RXBD_CNT * sizeof(greth_bd));
 170                greth->txbd_base = (greth_bd *)
 171                    memalign(0x1000, GRETH_TXBD_CNT * sizeof(greth_bd));
 172
 173                /* allocate buffers to all descriptors  */
 174                greth->rxbuf_base =
 175                    malloc(GRETH_RXBUF_EFF_SIZE * GRETH_RXBD_CNT);
 176        }
 177
 178        /* initate rx decriptors */
 179        for (i = 0; i < GRETH_RXBD_CNT; i++) {
 180                greth->rxbd_base[i].addr = (unsigned int)
 181                    greth->rxbuf_base + (GRETH_RXBUF_EFF_SIZE * i);
 182                /* enable desciptor & set wrap bit if last descriptor */
 183                if (i >= (GRETH_RXBD_CNT - 1)) {
 184                        greth->rxbd_base[i].stat = GRETH_BD_EN | GRETH_BD_WR;
 185                } else {
 186                        greth->rxbd_base[i].stat = GRETH_BD_EN;
 187                }
 188        }
 189
 190        /* initiate indexes */
 191        greth->rxbd_curr = greth->rxbd_base;
 192        greth->rxbd_max = greth->rxbd_base + (GRETH_RXBD_CNT - 1);
 193        greth->txbd_max = greth->txbd_base + (GRETH_TXBD_CNT - 1);
 194        /*
 195         * greth->txbd_base->addr = 0;
 196         * greth->txbd_base->stat = GRETH_BD_WR;
 197         */
 198
 199        /* initate tx decriptors */
 200        for (i = 0; i < GRETH_TXBD_CNT; i++) {
 201                greth->txbd_base[i].addr = 0;
 202                /* enable desciptor & set wrap bit if last descriptor */
 203                if (i >= (GRETH_TXBD_CNT - 1)) {
 204                        greth->txbd_base[i].stat = GRETH_BD_WR;
 205                } else {
 206                        greth->txbd_base[i].stat = 0;
 207                }
 208        }
 209
 210        /**** SET HARDWARE REGS ****/
 211
 212        /* Set pointer to tx/rx descriptor areas */
 213        GRETH_REGSAVE(&regs->rx_desc_p, (unsigned int)&greth->rxbd_base[0]);
 214        GRETH_REGSAVE(&regs->tx_desc_p, (unsigned int)&greth->txbd_base[0]);
 215
 216        /* Enable Transmitter, GRETH will now scan descriptors for packets
 217         * to transmitt */
 218        debug("greth_init: enabling receiver\n");
 219        GRETH_REGORIN(&regs->control, GRETH_RXEN);
 220
 221        return 0;
 222}
 223
 224/* Initiate PHY to a relevant speed
 225 * return:
 226 *  - 0 = success
 227 *  - 1 = timeout/fail
 228 */
 229int greth_init_phy(greth_priv * dev, bd_t * bis)
 230{
 231        greth_regs *regs = dev->regs;
 232        int tmp, tmp1, tmp2, i;
 233        unsigned int start, timeout;
 234        int phyaddr = GRETH_PHY_ADR_DEFAULT;
 235
 236#ifndef CONFIG_SYS_GRLIB_GRETH_PHYADDR
 237        /* If BSP doesn't provide a hardcoded PHY address the driver will
 238         * try to autodetect PHY address by stopping the search on the first
 239         * PHY address which has REG0 implemented.
 240         */
 241        for (i=0; i<32; i++) {
 242                tmp = read_mii(i, 0, regs);
 243                if ( (tmp != 0) && (tmp != 0xffff) ) {
 244                        phyaddr = i;
 245                        break;
 246                }
 247        }
 248#endif
 249
 250        /* Save PHY Address */
 251        dev->phyaddr = phyaddr;
 252
 253        debug("GRETH PHY ADDRESS: %d\n", phyaddr);
 254
 255        /* X msecs to ticks */
 256        timeout = usec2ticks(GRETH_PHY_TIMEOUT_MS * 1000);
 257
 258        /* Get system timer0 current value
 259         * Total timeout is 5s
 260         */
 261        start = get_timer(0);
 262
 263        /* get phy control register default values */
 264
 265        while ((tmp = read_mii(phyaddr, 0, regs)) & 0x8000) {
 266                if (get_timer(start) > timeout) {
 267                        debug("greth_init_phy: PHY read 1 failed\n");
 268                        return 1;       /* Fail */
 269                }
 270        }
 271
 272        /* reset PHY and wait for completion */
 273        write_mii(phyaddr, 0, 0x8000 | tmp, regs);
 274
 275        while (((tmp = read_mii(phyaddr, 0, regs))) & 0x8000) {
 276                if (get_timer(start) > timeout) {
 277                        debug("greth_init_phy: PHY read 2 failed\n");
 278                        return 1;       /* Fail */
 279                }
 280        }
 281
 282        /* Check if PHY is autoneg capable and then determine operating
 283         * mode, otherwise force it to 10 Mbit halfduplex
 284         */
 285        dev->gb = 0;
 286        dev->fd = 0;
 287        dev->sp = 0;
 288        dev->auto_neg = 0;
 289        if (!((tmp >> 12) & 1)) {
 290                write_mii(phyaddr, 0, 0, regs);
 291        } else {
 292                /* wait for auto negotiation to complete and then check operating mode */
 293                dev->auto_neg = 1;
 294                i = 0;
 295                while (!(((tmp = read_mii(phyaddr, 1, regs)) >> 5) & 1)) {
 296                        if (get_timer(start) > timeout) {
 297                                printf("Auto negotiation timed out. "
 298                                       "Selecting default config\n");
 299                                tmp = read_mii(phyaddr, 0, regs);
 300                                dev->gb = ((tmp >> 6) & 1)
 301                                    && !((tmp >> 13) & 1);
 302                                dev->sp = !((tmp >> 6) & 1)
 303                                    && ((tmp >> 13) & 1);
 304                                dev->fd = (tmp >> 8) & 1;
 305                                goto auto_neg_done;
 306                        }
 307                }
 308                if ((tmp >> 8) & 1) {
 309                        tmp1 = read_mii(phyaddr, 9, regs);
 310                        tmp2 = read_mii(phyaddr, 10, regs);
 311                        if ((tmp1 & GRETH_MII_EXTADV_1000FD) &&
 312                            (tmp2 & GRETH_MII_EXTPRT_1000FD)) {
 313                                dev->gb = 1;
 314                                dev->fd = 1;
 315                        }
 316                        if ((tmp1 & GRETH_MII_EXTADV_1000HD) &&
 317                            (tmp2 & GRETH_MII_EXTPRT_1000HD)) {
 318                                dev->gb = 1;
 319                                dev->fd = 0;
 320                        }
 321                }
 322                if ((dev->gb == 0) || ((dev->gb == 1) && (dev->gbit_mac == 0))) {
 323                        tmp1 = read_mii(phyaddr, 4, regs);
 324                        tmp2 = read_mii(phyaddr, 5, regs);
 325                        if ((tmp1 & GRETH_MII_100TXFD) &&
 326                            (tmp2 & GRETH_MII_100TXFD)) {
 327                                dev->sp = 1;
 328                                dev->fd = 1;
 329                        }
 330                        if ((tmp1 & GRETH_MII_100TXHD) &&
 331                            (tmp2 & GRETH_MII_100TXHD)) {
 332                                dev->sp = 1;
 333                                dev->fd = 0;
 334                        }
 335                        if ((tmp1 & GRETH_MII_10FD) && (tmp2 & GRETH_MII_10FD)) {
 336                                dev->fd = 1;
 337                        }
 338                        if ((dev->gb == 1) && (dev->gbit_mac == 0)) {
 339                                dev->gb = 0;
 340                                dev->fd = 0;
 341                                write_mii(phyaddr, 0, dev->sp << 13, regs);
 342                        }
 343                }
 344
 345        }
 346      auto_neg_done:
 347        debug("%s GRETH Ethermac at [0x%x] irq %d. Running \
 348                %d Mbps %s duplex\n", dev->gbit_mac ? "10/100/1000" : "10/100", (unsigned int)(regs), (unsigned int)(dev->irq), dev->gb ? 1000 : (dev->sp ? 100 : 10), dev->fd ? "full" : "half");
 349        /* Read out PHY info if extended registers are available */
 350        if (tmp & 1) {
 351                tmp1 = read_mii(phyaddr, 2, regs);
 352                tmp2 = read_mii(phyaddr, 3, regs);
 353                tmp1 = (tmp1 << 6) | ((tmp2 >> 10) & 0x3F);
 354                tmp = tmp2 & 0xF;
 355
 356                tmp2 = (tmp2 >> 4) & 0x3F;
 357                debug("PHY: Vendor %x   Device %x    Revision %d\n", tmp1,
 358                       tmp2, tmp);
 359        } else {
 360                printf("PHY info not available\n");
 361        }
 362
 363        /* set speed and duplex bits in control register */
 364        GRETH_REGORIN(&regs->control,
 365                      (dev->gb << 8) | (dev->sp << 7) | (dev->fd << 4));
 366
 367        return 0;
 368}
 369
 370void greth_halt(struct eth_device *dev)
 371{
 372        greth_priv *greth;
 373        greth_regs *regs;
 374        int i;
 375
 376        debug("greth_halt\n");
 377
 378        if (!dev || !dev->priv)
 379                return;
 380
 381        greth = dev->priv;
 382        regs = greth->regs;
 383
 384        if (!regs)
 385                return;
 386
 387        /* disable receiver/transmitter by clearing the enable bits */
 388        GRETH_REGANDIN(&regs->control, ~(GRETH_RXEN | GRETH_TXEN));
 389
 390        /* reset rx/tx descriptors */
 391        if (greth->rxbd_base) {
 392                for (i = 0; i < GRETH_RXBD_CNT; i++) {
 393                        greth->rxbd_base[i].stat =
 394                            (i >= (GRETH_RXBD_CNT - 1)) ? GRETH_BD_WR : 0;
 395                }
 396        }
 397
 398        if (greth->txbd_base) {
 399                for (i = 0; i < GRETH_TXBD_CNT; i++) {
 400                        greth->txbd_base[i].stat =
 401                            (i >= (GRETH_TXBD_CNT - 1)) ? GRETH_BD_WR : 0;
 402                }
 403        }
 404}
 405
 406int greth_send(struct eth_device *dev, void *eth_data, int data_length)
 407{
 408        greth_priv *greth = dev->priv;
 409        greth_regs *regs = greth->regs;
 410        greth_bd *txbd;
 411        void *txbuf;
 412        unsigned int status;
 413
 414        debug("greth_send\n");
 415
 416        /* send data, wait for data to be sent, then return */
 417        if (((unsigned int)eth_data & (GRETH_BUF_ALIGN - 1))
 418            && !greth->gbit_mac) {
 419                /* data not aligned as needed by GRETH 10/100, solve this by allocating 4 byte aligned buffer
 420                 * and copy data to before giving it to GRETH.
 421                 */
 422                if (!greth->txbuf) {
 423                        greth->txbuf = malloc(GRETH_RXBUF_SIZE);
 424                }
 425
 426                txbuf = greth->txbuf;
 427
 428                /* copy data info buffer */
 429                memcpy((char *)txbuf, (char *)eth_data, data_length);
 430
 431                /* keep buffer to next time */
 432        } else {
 433                txbuf = (void *)eth_data;
 434        }
 435        /* get descriptor to use, only 1 supported... hehe easy */
 436        txbd = greth->txbd_base;
 437
 438        /* setup descriptor to wrap around to it self */
 439        txbd->addr = (unsigned int)txbuf;
 440        txbd->stat = GRETH_BD_EN | GRETH_BD_WR | data_length;
 441
 442        /* Remind Core which descriptor to use when sending */
 443        GRETH_REGSAVE(&regs->tx_desc_p, (unsigned int)txbd);
 444
 445        /* initate send by enabling transmitter */
 446        GRETH_REGORIN(&regs->control, GRETH_TXEN);
 447
 448        /* Wait for data to be sent */
 449        while ((status = GRETH_REGLOAD(&txbd->stat)) & GRETH_BD_EN) {
 450                ;
 451        }
 452
 453        /* was the packet transmitted succesfully? */
 454        if (status & GRETH_TXBD_ERR_AL) {
 455                greth->stats.tx_limit_errors++;
 456        }
 457
 458        if (status & GRETH_TXBD_ERR_UE) {
 459                greth->stats.tx_underrun_errors++;
 460        }
 461
 462        if (status & GRETH_TXBD_ERR_LC) {
 463                greth->stats.tx_latecol_errors++;
 464        }
 465
 466        if (status &
 467            (GRETH_TXBD_ERR_LC | GRETH_TXBD_ERR_UE | GRETH_TXBD_ERR_AL)) {
 468                /* any error */
 469                greth->stats.tx_errors++;
 470                return -1;
 471        }
 472
 473        /* bump tx packet counter */
 474        greth->stats.tx_packets++;
 475
 476        /* return succefully */
 477        return 0;
 478}
 479
 480int greth_recv(struct eth_device *dev)
 481{
 482        greth_priv *greth = dev->priv;
 483        greth_regs *regs = greth->regs;
 484        greth_bd *rxbd;
 485        unsigned int status, len = 0, bad;
 486        char *d;
 487        int enable = 0;
 488        int i;
 489
 490        /* Receive One packet only, but clear as many error packets as there are
 491         * available.
 492         */
 493        {
 494                /* current receive descriptor */
 495                rxbd = greth->rxbd_curr;
 496
 497                /* get status of next received packet */
 498                status = GRETH_REGLOAD(&rxbd->stat);
 499
 500                bad = 0;
 501
 502                /* stop if no more packets received */
 503                if (status & GRETH_BD_EN) {
 504                        goto done;
 505                }
 506
 507                debug("greth_recv: packet 0x%x, 0x%x, len: %d\n",
 508                       (unsigned int)rxbd, status, status & GRETH_BD_LEN);
 509
 510                /* Check status for errors.
 511                 */
 512                if (status & GRETH_RXBD_ERR_FT) {
 513                        greth->stats.rx_length_errors++;
 514                        bad = 1;
 515                }
 516                if (status & (GRETH_RXBD_ERR_AE | GRETH_RXBD_ERR_OE)) {
 517                        greth->stats.rx_frame_errors++;
 518                        bad = 1;
 519                }
 520                if (status & GRETH_RXBD_ERR_CRC) {
 521                        greth->stats.rx_crc_errors++;
 522                        bad = 1;
 523                }
 524                if (bad) {
 525                        greth->stats.rx_errors++;
 526                        printf
 527                            ("greth_recv: Bad packet (%d, %d, %d, 0x%08x, %d)\n",
 528                             greth->stats.rx_length_errors,
 529                             greth->stats.rx_frame_errors,
 530                             greth->stats.rx_crc_errors, status,
 531                             greth->stats.rx_packets);
 532                        /* print all rx descriptors */
 533                        for (i = 0; i < GRETH_RXBD_CNT; i++) {
 534                                printf("[%d]: Stat=0x%lx, Addr=0x%lx\n", i,
 535                                       GRETH_REGLOAD(&greth->rxbd_base[i].stat),
 536                                       GRETH_REGLOAD(&greth->rxbd_base[i].addr));
 537                        }
 538                } else {
 539                        /* Process the incoming packet. */
 540                        len = status & GRETH_BD_LEN;
 541                        d = (char *)rxbd->addr;
 542
 543                        debug
 544                            ("greth_recv: new packet, length: %d. data: %x %x %x %x %x %x %x %x\n",
 545                             len, d[0], d[1], d[2], d[3], d[4], d[5], d[6],
 546                             d[7]);
 547
 548                        /* flush all data cache to make sure we're not reading old packet data */
 549                        sparc_dcache_flush_all();
 550
 551                        /* pass packet on to network subsystem */
 552                        NetReceive((void *)d, len);
 553
 554                        /* bump stats counters */
 555                        greth->stats.rx_packets++;
 556
 557                        /* bad is now 0 ==> will stop loop */
 558                }
 559
 560                /* reenable descriptor to receive more packet with this descriptor, wrap around if needed */
 561                rxbd->stat =
 562                    GRETH_BD_EN |
 563                    (((unsigned int)greth->rxbd_curr >=
 564                      (unsigned int)greth->rxbd_max) ? GRETH_BD_WR : 0);
 565                enable = 1;
 566
 567                /* increase index */
 568                greth->rxbd_curr =
 569                    ((unsigned int)greth->rxbd_curr >=
 570                     (unsigned int)greth->rxbd_max) ? greth->
 571                    rxbd_base : (greth->rxbd_curr + 1);
 572
 573        }
 574
 575        if (enable) {
 576                GRETH_REGORIN(&regs->control, GRETH_RXEN);
 577        }
 578      done:
 579        /* return positive length of packet or 0 if non received */
 580        return len;
 581}
 582
 583void greth_set_hwaddr(greth_priv * greth, unsigned char *mac)
 584{
 585        /* save new MAC address */
 586        greth->dev->enetaddr[0] = greth->hwaddr[0] = mac[0];
 587        greth->dev->enetaddr[1] = greth->hwaddr[1] = mac[1];
 588        greth->dev->enetaddr[2] = greth->hwaddr[2] = mac[2];
 589        greth->dev->enetaddr[3] = greth->hwaddr[3] = mac[3];
 590        greth->dev->enetaddr[4] = greth->hwaddr[4] = mac[4];
 591        greth->dev->enetaddr[5] = greth->hwaddr[5] = mac[5];
 592        greth->regs->esa_msb = (mac[0] << 8) | mac[1];
 593        greth->regs->esa_lsb =
 594            (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5];
 595
 596        debug("GRETH: New MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n",
 597               mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
 598}
 599
 600int greth_initialize(bd_t * bis)
 601{
 602        greth_priv *greth;
 603        ambapp_apbdev apbdev;
 604        struct eth_device *dev;
 605        int i;
 606        char *addr_str, *end;
 607        unsigned char addr[6];
 608
 609        debug("Scanning for GRETH\n");
 610
 611        /* Find Device & IRQ via AMBA Plug&Play information */
 612        if (ambapp_apb_first(VENDOR_GAISLER, GAISLER_ETHMAC, &apbdev) != 1) {
 613                return -1;      /* GRETH not found */
 614        }
 615
 616        greth = (greth_priv *) malloc(sizeof(greth_priv));
 617        dev = (struct eth_device *)malloc(sizeof(struct eth_device));
 618        memset(dev, 0, sizeof(struct eth_device));
 619        memset(greth, 0, sizeof(greth_priv));
 620
 621        greth->regs = (greth_regs *) apbdev.address;
 622        greth->irq = apbdev.irq;
 623        debug("Found GRETH at %p, irq %d\n", greth->regs, greth->irq);
 624        dev->priv = (void *)greth;
 625        dev->iobase = (unsigned int)greth->regs;
 626        dev->init = greth_init;
 627        dev->halt = greth_halt;
 628        dev->send = greth_send;
 629        dev->recv = greth_recv;
 630        greth->dev = dev;
 631
 632        /* Reset Core */
 633        GRETH_REGSAVE(&greth->regs->control, GRETH_RESET);
 634
 635        /* Wait for core to finish reset cycle */
 636        while (GRETH_REGLOAD(&greth->regs->control) & GRETH_RESET) ;
 637
 638        /* Get the phy address which assumed to have been set
 639           correctly with the reset value in hardware */
 640        greth->phyaddr = (GRETH_REGLOAD(&greth->regs->mdio) >> 11) & 0x1F;
 641
 642        /* Check if mac is gigabit capable */
 643        greth->gbit_mac = (GRETH_REGLOAD(&greth->regs->control) >> 27) & 1;
 644
 645        /* Make descriptor string */
 646        if (greth->gbit_mac) {
 647                sprintf(dev->name, "GRETH_10/100/GB");
 648        } else {
 649                sprintf(dev->name, "GRETH_10/100");
 650        }
 651
 652        /* initiate PHY, select speed/duplex depending on connected PHY */
 653        if (greth_init_phy(greth, bis)) {
 654                /* Failed to init PHY (timedout) */
 655                debug("GRETH[%p]: Failed to init PHY\n", greth->regs);
 656                return -1;
 657        }
 658
 659        /* Register Device to EtherNet subsystem  */
 660        eth_register(dev);
 661
 662        /* Get MAC address */
 663        if ((addr_str = getenv("ethaddr")) != NULL) {
 664                for (i = 0; i < 6; i++) {
 665                        addr[i] =
 666                            addr_str ? simple_strtoul(addr_str, &end, 16) : 0;
 667                        if (addr_str) {
 668                                addr_str = (*end) ? end + 1 : end;
 669                        }
 670                }
 671        } else {
 672                /* HW Address not found in environment, Set default HW address */
 673                addr[0] = GRETH_HWADDR_0;       /* MSB */
 674                addr[1] = GRETH_HWADDR_1;
 675                addr[2] = GRETH_HWADDR_2;
 676                addr[3] = GRETH_HWADDR_3;
 677                addr[4] = GRETH_HWADDR_4;
 678                addr[5] = GRETH_HWADDR_5;       /* LSB */
 679        }
 680
 681        /* set and remember MAC address */
 682        greth_set_hwaddr(greth, addr);
 683
 684        debug("GRETH[%p]: Initialized successfully\n", greth->regs);
 685        return 0;
 686}
 687