greth.c 17.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
/* Gaisler.com GRETH 10/100/1000 Ethernet MAC driver
 *
 * Driver use polling mode (no Interrupt)
 *
 * (C) Copyright 2007
 * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

27 28
/* #define DEBUG */

29 30 31
#include <common.h>
#include <command.h>
#include <net.h>
32
#include <netdev.h>
33 34 35 36 37 38 39 40 41 42 43 44
#include <malloc.h>
#include <asm/processor.h>
#include <ambapp.h>
#include <asm/leon.h>

#include "greth.h"

/* Default to 3s timeout on autonegotiation */
#ifndef GRETH_PHY_TIMEOUT_MS
#define GRETH_PHY_TIMEOUT_MS 3000
#endif

45 46 47 48 49 50 51
/* Default to PHY adrress 0 not not specified */
#ifdef CONFIG_SYS_GRLIB_GRETH_PHYADDR
#define GRETH_PHY_ADR_DEFAULT CONFIG_SYS_GRLIB_GRETH_PHYADDR
#else
#define GRETH_PHY_ADR_DEFAULT 0
#endif

52 53 54
/* ByPass Cache when reading regs */
#define GRETH_REGLOAD(addr)		SPARC_NOCACHE_READ(addr)
/* Write-through cache ==> no bypassing needed on writes */
55
#define GRETH_REGSAVE(addr,data) (*(volatile unsigned int *)(addr) = (data))
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
#define GRETH_REGORIN(addr,data) GRETH_REGSAVE(addr,GRETH_REGLOAD(addr)|data)
#define GRETH_REGANDIN(addr,data) GRETH_REGSAVE(addr,GRETH_REGLOAD(addr)&data)

#define GRETH_RXBD_CNT 4
#define GRETH_TXBD_CNT 1

#define GRETH_RXBUF_SIZE 1540
#define GRETH_BUF_ALIGN 4
#define GRETH_RXBUF_EFF_SIZE \
	( (GRETH_RXBUF_SIZE&~(GRETH_BUF_ALIGN-1))+GRETH_BUF_ALIGN )

typedef struct {
	greth_regs *regs;
	int irq;
	struct eth_device *dev;

	/* Hardware info */
	unsigned char phyaddr;
	int gbit_mac;

	/* Current operating Mode */
	int gb;			/* GigaBit */
	int fd;			/* Full Duplex */
	int sp;			/* 10/100Mbps speed (1=100,0=10) */
	int auto_neg;		/* Auto negotiate done */

	unsigned char hwaddr[6];	/* MAC Address */

	/* Descriptors */
	greth_bd *rxbd_base, *rxbd_max;
	greth_bd *txbd_base, *txbd_max;

	greth_bd *rxbd_curr;

	/* rx buffers in rx descriptors */
	void *rxbuf_base;	/* (GRETH_RXBUF_SIZE+ALIGNBYTES) * GRETH_RXBD_CNT */

	/* unused for gbit_mac, temp buffer for sending packets with unligned
	 * start.
	 * Pointer to packet allocated with malloc.
	 */
	void *txbuf;

	struct {
		/* rx status */
		unsigned int rx_packets,
		    rx_crc_errors, rx_frame_errors, rx_length_errors, rx_errors;

		/* tx stats */
		unsigned int tx_packets,
		    tx_latecol_errors,
		    tx_underrun_errors, tx_limit_errors, tx_errors;
	} stats;
} greth_priv;

/* Read MII register 'addr' from core 'regs' */
112
static int read_mii(int phyaddr, int regaddr, volatile greth_regs * regs)
113 114 115 116
{
	while (GRETH_REGLOAD(&regs->mdio) & GRETH_MII_BUSY) {
	}

117
	GRETH_REGSAVE(&regs->mdio, ((phyaddr & 0x1F) << 11) | ((regaddr & 0x1F) << 6) | 2);
118 119 120 121 122 123 124 125 126 127 128

	while (GRETH_REGLOAD(&regs->mdio) & GRETH_MII_BUSY) {
	}

	if (!(GRETH_REGLOAD(&regs->mdio) & GRETH_MII_NVALID)) {
		return (GRETH_REGLOAD(&regs->mdio) >> 16) & 0xFFFF;
	} else {
		return -1;
	}
}

129
static void write_mii(int phyaddr, int regaddr, int data, volatile greth_regs * regs)
130 131 132 133 134
{
	while (GRETH_REGLOAD(&regs->mdio) & GRETH_MII_BUSY) {
	}

	GRETH_REGSAVE(&regs->mdio,
135 136
		      ((data & 0xFFFF) << 16) | ((phyaddr & 0x1F) << 11) |
		      ((regaddr & 0x1F) << 6) | 1);
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151

	while (GRETH_REGLOAD(&regs->mdio) & GRETH_MII_BUSY) {
	}

}

/* init/start hardware and allocate descriptor buffers for rx side
 *
 */
int greth_init(struct eth_device *dev, bd_t * bis)
{
	int i;

	greth_priv *greth = dev->priv;
	greth_regs *regs = greth->regs;
152 153

	debug("greth_init\n");
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207

	if (!greth->rxbd_base) {

		/* allocate descriptors */
		greth->rxbd_base = (greth_bd *)
		    memalign(0x1000, GRETH_RXBD_CNT * sizeof(greth_bd));
		greth->txbd_base = (greth_bd *)
		    memalign(0x1000, GRETH_RXBD_CNT * sizeof(greth_bd));

		/* allocate buffers to all descriptors  */
		greth->rxbuf_base =
		    malloc(GRETH_RXBUF_EFF_SIZE * GRETH_RXBD_CNT);
	}

	/* initate rx decriptors */
	for (i = 0; i < GRETH_RXBD_CNT; i++) {
		greth->rxbd_base[i].addr = (unsigned int)
		    greth->rxbuf_base + (GRETH_RXBUF_EFF_SIZE * i);
		/* enable desciptor & set wrap bit if last descriptor */
		if (i >= (GRETH_RXBD_CNT - 1)) {
			greth->rxbd_base[i].stat = GRETH_BD_EN | GRETH_BD_WR;
		} else {
			greth->rxbd_base[i].stat = GRETH_BD_EN;
		}
	}

	/* initiate indexes */
	greth->rxbd_curr = greth->rxbd_base;
	greth->rxbd_max = greth->rxbd_base + (GRETH_RXBD_CNT - 1);
	greth->txbd_max = greth->txbd_base + (GRETH_TXBD_CNT - 1);
	/*
	 * greth->txbd_base->addr = 0;
	 * greth->txbd_base->stat = GRETH_BD_WR;
	 */

	/* initate tx decriptors */
	for (i = 0; i < GRETH_TXBD_CNT; i++) {
		greth->txbd_base[i].addr = 0;
		/* enable desciptor & set wrap bit if last descriptor */
		if (i >= (GRETH_RXBD_CNT - 1)) {
			greth->txbd_base[i].stat = GRETH_BD_WR;
		} else {
			greth->txbd_base[i].stat = 0;
		}
	}

	/**** SET HARDWARE REGS ****/

	/* Set pointer to tx/rx descriptor areas */
	GRETH_REGSAVE(&regs->rx_desc_p, (unsigned int)&greth->rxbd_base[0]);
	GRETH_REGSAVE(&regs->tx_desc_p, (unsigned int)&greth->txbd_base[0]);

	/* Enable Transmitter, GRETH will now scan descriptors for packets
	 * to transmitt */
208
	debug("greth_init: enabling receiver\n");
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
	GRETH_REGORIN(&regs->control, GRETH_RXEN);

	return 0;
}

/* Initiate PHY to a relevant speed
 * return:
 *  - 0 = success
 *  - 1 = timeout/fail
 */
int greth_init_phy(greth_priv * dev, bd_t * bis)
{
	greth_regs *regs = dev->regs;
	int tmp, tmp1, tmp2, i;
	unsigned int start, timeout;
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
	int phyaddr = GRETH_PHY_ADR_DEFAULT;

#ifndef CONFIG_SYS_GRLIB_GRETH_PHYADDR
	/* If BSP doesn't provide a hardcoded PHY address the driver will
	 * try to autodetect PHY address by stopping the search on the first
	 * PHY address which has REG0 implemented.
	 */
	for (i=0; i<32; i++) {
		tmp = read_mii(i, 0, regs);
		if ( (tmp != 0) && (tmp != 0xffff) ) {
			phyaddr = i;
			break;
		}
	}
#endif

	/* Save PHY Address */
	dev->phyaddr = phyaddr;

	debug("GRETH PHY ADDRESS: %d\n", phyaddr);
244 245 246 247 248 249 250 251 252 253 254

	/* X msecs to ticks */
	timeout = usec2ticks(GRETH_PHY_TIMEOUT_MS * 1000);

	/* Get system timer0 current value
	 * Total timeout is 5s
	 */
	start = get_timer(0);

	/* get phy control register default values */

255 256 257
	while ((tmp = read_mii(phyaddr, 0, regs)) & 0x8000) {
		if (get_timer(start) > timeout) {
			debug("greth_init_phy: PHY read 1 failed\n");
258
			return 1;	/* Fail */
259
		}
260 261 262
	}

	/* reset PHY and wait for completion */
263
	write_mii(phyaddr, 0, 0x8000 | tmp, regs);
264

265 266 267
	while (((tmp = read_mii(phyaddr, 0, regs))) & 0x8000) {
		if (get_timer(start) > timeout) {
			debug("greth_init_phy: PHY read 2 failed\n");
268
			return 1;	/* Fail */
269
		}
270 271 272 273 274 275 276 277 278 279
	}

	/* Check if PHY is autoneg capable and then determine operating
	 * mode, otherwise force it to 10 Mbit halfduplex
	 */
	dev->gb = 0;
	dev->fd = 0;
	dev->sp = 0;
	dev->auto_neg = 0;
	if (!((tmp >> 12) & 1)) {
280
		write_mii(phyaddr, 0, 0, regs);
281 282 283 284
	} else {
		/* wait for auto negotiation to complete and then check operating mode */
		dev->auto_neg = 1;
		i = 0;
285
		while (!(((tmp = read_mii(phyaddr, 1, regs)) >> 5) & 1)) {
286 287 288
			if (get_timer(start) > timeout) {
				printf("Auto negotiation timed out. "
				       "Selecting default config\n");
289
				tmp = read_mii(phyaddr, 0, regs);
290 291 292 293 294 295 296 297 298
				dev->gb = ((tmp >> 6) & 1)
				    && !((tmp >> 13) & 1);
				dev->sp = !((tmp >> 6) & 1)
				    && ((tmp >> 13) & 1);
				dev->fd = (tmp >> 8) & 1;
				goto auto_neg_done;
			}
		}
		if ((tmp >> 8) & 1) {
299 300
			tmp1 = read_mii(phyaddr, 9, regs);
			tmp2 = read_mii(phyaddr, 10, regs);
301 302 303 304 305 306 307 308 309 310 311 312
			if ((tmp1 & GRETH_MII_EXTADV_1000FD) &&
			    (tmp2 & GRETH_MII_EXTPRT_1000FD)) {
				dev->gb = 1;
				dev->fd = 1;
			}
			if ((tmp1 & GRETH_MII_EXTADV_1000HD) &&
			    (tmp2 & GRETH_MII_EXTPRT_1000HD)) {
				dev->gb = 1;
				dev->fd = 0;
			}
		}
		if ((dev->gb == 0) || ((dev->gb == 1) && (dev->gbit_mac == 0))) {
313 314
			tmp1 = read_mii(phyaddr, 4, regs);
			tmp2 = read_mii(phyaddr, 5, regs);
315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
			if ((tmp1 & GRETH_MII_100TXFD) &&
			    (tmp2 & GRETH_MII_100TXFD)) {
				dev->sp = 1;
				dev->fd = 1;
			}
			if ((tmp1 & GRETH_MII_100TXHD) &&
			    (tmp2 & GRETH_MII_100TXHD)) {
				dev->sp = 1;
				dev->fd = 0;
			}
			if ((tmp1 & GRETH_MII_10FD) && (tmp2 & GRETH_MII_10FD)) {
				dev->fd = 1;
			}
			if ((dev->gb == 1) && (dev->gbit_mac == 0)) {
				dev->gb = 0;
				dev->fd = 0;
331
				write_mii(phyaddr, 0, dev->sp << 13, regs);
332 333 334 335 336
			}
		}

	}
      auto_neg_done:
337
	debug("%s GRETH Ethermac at [0x%x] irq %d. Running \
338 339 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");
	/* Read out PHY info if extended registers are available */
	if (tmp & 1) {
341 342
		tmp1 = read_mii(phyaddr, 2, regs);
		tmp2 = read_mii(phyaddr, 3, regs);
343 344 345 346
		tmp1 = (tmp1 << 6) | ((tmp2 >> 10) & 0x3F);
		tmp = tmp2 & 0xF;

		tmp2 = (tmp2 >> 4) & 0x3F;
347
		debug("PHY: Vendor %x   Device %x    Revision %d\n", tmp1,
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364
		       tmp2, tmp);
	} else {
		printf("PHY info not available\n");
	}

	/* set speed and duplex bits in control register */
	GRETH_REGORIN(&regs->control,
		      (dev->gb << 8) | (dev->sp << 7) | (dev->fd << 4));

	return 0;
}

void greth_halt(struct eth_device *dev)
{
	greth_priv *greth;
	greth_regs *regs;
	int i;
365 366 367

	debug("greth_halt\n");

368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402
	if (!dev || !dev->priv)
		return;

	greth = dev->priv;
	regs = greth->regs;

	if (!regs)
		return;

	/* disable receiver/transmitter by clearing the enable bits */
	GRETH_REGANDIN(&regs->control, ~(GRETH_RXEN | GRETH_TXEN));

	/* reset rx/tx descriptors */
	if (greth->rxbd_base) {
		for (i = 0; i < GRETH_RXBD_CNT; i++) {
			greth->rxbd_base[i].stat =
			    (i >= (GRETH_RXBD_CNT - 1)) ? GRETH_BD_WR : 0;
		}
	}

	if (greth->txbd_base) {
		for (i = 0; i < GRETH_TXBD_CNT; i++) {
			greth->txbd_base[i].stat =
			    (i >= (GRETH_TXBD_CNT - 1)) ? GRETH_BD_WR : 0;
		}
	}
}

int greth_send(struct eth_device *dev, volatile void *eth_data, int data_length)
{
	greth_priv *greth = dev->priv;
	greth_regs *regs = greth->regs;
	greth_bd *txbd;
	void *txbuf;
	unsigned int status;
403 404 405

	debug("greth_send\n");

406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478
	/* send data, wait for data to be sent, then return */
	if (((unsigned int)eth_data & (GRETH_BUF_ALIGN - 1))
	    && !greth->gbit_mac) {
		/* data not aligned as needed by GRETH 10/100, solve this by allocating 4 byte aligned buffer
		 * and copy data to before giving it to GRETH.
		 */
		if (!greth->txbuf) {
			greth->txbuf = malloc(GRETH_RXBUF_SIZE);
		}

		txbuf = greth->txbuf;

		/* copy data info buffer */
		memcpy((char *)txbuf, (char *)eth_data, data_length);

		/* keep buffer to next time */
	} else {
		txbuf = (void *)eth_data;
	}
	/* get descriptor to use, only 1 supported... hehe easy */
	txbd = greth->txbd_base;

	/* setup descriptor to wrap around to it self */
	txbd->addr = (unsigned int)txbuf;
	txbd->stat = GRETH_BD_EN | GRETH_BD_WR | data_length;

	/* Remind Core which descriptor to use when sending */
	GRETH_REGSAVE(&regs->tx_desc_p, (unsigned int)txbd);

	/* initate send by enabling transmitter */
	GRETH_REGORIN(&regs->control, GRETH_TXEN);

	/* Wait for data to be sent */
	while ((status = GRETH_REGLOAD(&txbd->stat)) & GRETH_BD_EN) {
		;
	}

	/* was the packet transmitted succesfully? */
	if (status & GRETH_TXBD_ERR_AL) {
		greth->stats.tx_limit_errors++;
	}

	if (status & GRETH_TXBD_ERR_UE) {
		greth->stats.tx_underrun_errors++;
	}

	if (status & GRETH_TXBD_ERR_LC) {
		greth->stats.tx_latecol_errors++;
	}

	if (status &
	    (GRETH_TXBD_ERR_LC | GRETH_TXBD_ERR_UE | GRETH_TXBD_ERR_AL)) {
		/* any error */
		greth->stats.tx_errors++;
		return -1;
	}

	/* bump tx packet counter */
	greth->stats.tx_packets++;

	/* return succefully */
	return 0;
}

int greth_recv(struct eth_device *dev)
{
	greth_priv *greth = dev->priv;
	greth_regs *regs = greth->regs;
	greth_bd *rxbd;
	unsigned int status, len = 0, bad;
	unsigned char *d;
	int enable = 0;
	int i;
479

480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495
	/* Receive One packet only, but clear as many error packets as there are
	 * available.
	 */
	{
		/* current receive descriptor */
		rxbd = greth->rxbd_curr;

		/* get status of next received packet */
		status = GRETH_REGLOAD(&rxbd->stat);

		bad = 0;

		/* stop if no more packets received */
		if (status & GRETH_BD_EN) {
			goto done;
		}
496 497

		debug("greth_recv: packet 0x%lx, 0x%lx, len: %d\n",
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525
		       (unsigned int)rxbd, status, status & GRETH_BD_LEN);

		/* Check status for errors.
		 */
		if (status & GRETH_RXBD_ERR_FT) {
			greth->stats.rx_length_errors++;
			bad = 1;
		}
		if (status & (GRETH_RXBD_ERR_AE | GRETH_RXBD_ERR_OE)) {
			greth->stats.rx_frame_errors++;
			bad = 1;
		}
		if (status & GRETH_RXBD_ERR_CRC) {
			greth->stats.rx_crc_errors++;
			bad = 1;
		}
		if (bad) {
			greth->stats.rx_errors++;
			printf
			    ("greth_recv: Bad packet (%d, %d, %d, 0x%08x, %d)\n",
			     greth->stats.rx_length_errors,
			     greth->stats.rx_frame_errors,
			     greth->stats.rx_crc_errors, status,
			     greth->stats.rx_packets);
			/* print all rx descriptors */
			for (i = 0; i < GRETH_RXBD_CNT; i++) {
				printf("[%d]: Stat=0x%lx, Addr=0x%lx\n", i,
				       GRETH_REGLOAD(&greth->rxbd_base[i].stat),
526
				       GRETH_REGLOAD(&greth->rxbd_base[i].addr));
527 528 529 530 531
			}
		} else {
			/* Process the incoming packet. */
			len = status & GRETH_BD_LEN;
			d = (char *)rxbd->addr;
532 533

			debug
534 535 536
			    ("greth_recv: new packet, length: %d. data: %x %x %x %x %x %x %x %x\n",
			     len, d[0], d[1], d[2], d[3], d[4], d[5], d[6],
			     d[7]);
537

538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562
			/* flush all data cache to make sure we're not reading old packet data */
			sparc_dcache_flush_all();

			/* pass packet on to network subsystem */
			NetReceive((void *)d, len);

			/* bump stats counters */
			greth->stats.rx_packets++;

			/* bad is now 0 ==> will stop loop */
		}

		/* reenable descriptor to receive more packet with this descriptor, wrap around if needed */
		rxbd->stat =
		    GRETH_BD_EN |
		    (((unsigned int)greth->rxbd_curr >=
		      (unsigned int)greth->rxbd_max) ? GRETH_BD_WR : 0);
		enable = 1;

		/* increase index */
		greth->rxbd_curr =
		    ((unsigned int)greth->rxbd_curr >=
		     (unsigned int)greth->rxbd_max) ? greth->
		    rxbd_base : (greth->rxbd_curr + 1);

563
	}
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584

	if (enable) {
		GRETH_REGORIN(&regs->control, GRETH_RXEN);
	}
      done:
	/* return positive length of packet or 0 if non recieved */
	return len;
}

void greth_set_hwaddr(greth_priv * greth, unsigned char *mac)
{
	/* save new MAC address */
	greth->dev->enetaddr[0] = greth->hwaddr[0] = mac[0];
	greth->dev->enetaddr[1] = greth->hwaddr[1] = mac[1];
	greth->dev->enetaddr[2] = greth->hwaddr[2] = mac[2];
	greth->dev->enetaddr[3] = greth->hwaddr[3] = mac[3];
	greth->dev->enetaddr[4] = greth->hwaddr[4] = mac[4];
	greth->dev->enetaddr[5] = greth->hwaddr[5] = mac[5];
	greth->regs->esa_msb = (mac[0] << 8) | mac[1];
	greth->regs->esa_lsb =
	    (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5];
585 586

	debug("GRETH: New MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n",
587 588 589 590 591 592 593 594 595 596 597
	       mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}

int greth_initialize(bd_t * bis)
{
	greth_priv *greth;
	ambapp_apbdev apbdev;
	struct eth_device *dev;
	int i;
	char *addr_str, *end;
	unsigned char addr[6];
598 599 600

	debug("Scanning for GRETH\n");

601 602 603 604 605 606 607 608 609 610 611 612
	/* Find Device & IRQ via AMBA Plug&Play information */
	if (ambapp_apb_first(VENDOR_GAISLER, GAISLER_ETHMAC, &apbdev) != 1) {
		return -1;	/* GRETH not found */
	}

	greth = (greth_priv *) malloc(sizeof(greth_priv));
	dev = (struct eth_device *)malloc(sizeof(struct eth_device));
	memset(dev, 0, sizeof(struct eth_device));
	memset(greth, 0, sizeof(greth_priv));

	greth->regs = (greth_regs *) apbdev.address;
	greth->irq = apbdev.irq;
613
	debug("Found GRETH at 0x%lx, irq %d\n", greth->regs, greth->irq);
614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644
	dev->priv = (void *)greth;
	dev->iobase = (unsigned int)greth->regs;
	dev->init = greth_init;
	dev->halt = greth_halt;
	dev->send = greth_send;
	dev->recv = greth_recv;
	greth->dev = dev;

	/* Reset Core */
	GRETH_REGSAVE(&greth->regs->control, GRETH_RESET);

	/* Wait for core to finish reset cycle */
	while (GRETH_REGLOAD(&greth->regs->control) & GRETH_RESET) ;

	/* Get the phy address which assumed to have been set
	   correctly with the reset value in hardware */
	greth->phyaddr = (GRETH_REGLOAD(&greth->regs->mdio) >> 11) & 0x1F;

	/* Check if mac is gigabit capable */
	greth->gbit_mac = (GRETH_REGLOAD(&greth->regs->control) >> 27) & 1;

	/* Make descriptor string */
	if (greth->gbit_mac) {
		sprintf(dev->name, "GRETH 10/100/GB");
	} else {
		sprintf(dev->name, "GRETH 10/100");
	}

	/* initiate PHY, select speed/duplex depending on connected PHY */
	if (greth_init_phy(greth, bis)) {
		/* Failed to init PHY (timedout) */
645
		debug("GRETH[0x%08x]: Failed to init PHY\n", greth->regs);
646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673
		return -1;
	}

	/* Register Device to EtherNet subsystem  */
	eth_register(dev);

	/* Get MAC address */
	if ((addr_str = getenv("ethaddr")) != NULL) {
		for (i = 0; i < 6; i++) {
			addr[i] =
			    addr_str ? simple_strtoul(addr_str, &end, 16) : 0;
			if (addr_str) {
				addr_str = (*end) ? end + 1 : end;
			}
		}
	} else {
		/* HW Address not found in environment, Set default HW address */
		addr[0] = GRETH_HWADDR_0;	/* MSB */
		addr[1] = GRETH_HWADDR_1;
		addr[2] = GRETH_HWADDR_2;
		addr[3] = GRETH_HWADDR_3;
		addr[4] = GRETH_HWADDR_4;
		addr[5] = GRETH_HWADDR_5;	/* LSB */
	}

	/* set and remember MAC address */
	greth_set_hwaddr(greth, addr);

674
	debug("GRETH[0x%08x]: Initialized successfully\n", greth->regs);
675
	return 0;
676
}