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