4xx_enet.c 51.7 KB
Newer Older
W
wdenk 已提交
1 2
/*-----------------------------------------------------------------------------+
 *
3 4 5 6 7 8
 *	 This source code has been made available to you by IBM on an AS-IS
 *	 basis.	 Anyone receiving this source is licensed under IBM
 *	 copyrights to use it in any way he or she deems fit, including
 *	 copying it, modifying it, compiling it, and redistributing it either
 *	 with or without modifications.	 No license under IBM patents or
 *	 patent applications is to be implied by the copyright license.
W
wdenk 已提交
9
 *
10 11 12
 *	 Any user of this software should understand that IBM cannot provide
 *	 technical support for this software and will not be responsible for
 *	 any consequences resulting from the use of this software.
W
wdenk 已提交
13
 *
14 15 16
 *	 Any person who transfers this source code or any derivative work
 *	 must include the IBM copyright notice, this paragraph, and the
 *	 preceding two paragraphs in the transferred software.
W
wdenk 已提交
17
 *
18 19
 *	 COPYRIGHT   I B M   CORPORATION 1995
 *	 LICENSED MATERIAL  -  PROGRAM PROPERTY OF I B M
W
wdenk 已提交
20 21 22
 *-----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------+
 *
23
 *  File Name:	enetemac.c
W
wdenk 已提交
24
 *
25
 *  Function:	Device driver for the ethernet EMAC3 macro on the 405GP.
W
wdenk 已提交
26
 *
27
 *  Author:	Mark Wisner
W
wdenk 已提交
28 29 30
 *
 *  Change Activity-
 *
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
 *  Date	Description of Change					    BY
 *  ---------	---------------------					    ---
 *  05-May-99	Created							    MKW
 *  27-Jun-99	Clean up						    JWB
 *  16-Jul-99	Added MAL error recovery and better IP packet handling	    MKW
 *  29-Jul-99	Added Full duplex support				    MKW
 *  06-Aug-99	Changed names for Mal CR reg				    MKW
 *  23-Aug-99	Turned off SYE when running at 10Mbs			    MKW
 *  24-Aug-99	Marked descriptor empty after call_xlc			    MKW
 *  07-Sep-99	Set MAL RX buffer size reg to ENET_MAX_MTU_ALIGNED / 16	    MCG
 *		to avoid chaining maximum sized packets. Push starting
 *		RX descriptor address up to the next cache line boundary.
 *  16-Jan-00	Added support for booting with IP of 0x0		    MKW
 *  15-Mar-00	Updated enetInit() to enable broadcast addresses in the
 *		EMAC_RXM register.					    JWB
 *  12-Mar-01	anne-sophie.harnois@nextream.fr
 *		 - Variables are compatible with those already defined in
 *		  include/net.h
 *		- Receive buffer descriptor ring is used to send buffers
 *		  to the user
 *		- Info print about send/received/handled packet number if
 *		  INFO_405_ENET is set
 *  17-Apr-01	stefan.roese@esd-electronics.com
 *		- MAL reset in "eth_halt" included
 *		- Enet speed and duplex output now in one line
 *  08-May-01	stefan.roese@esd-electronics.com
 *		- MAL error handling added (eth_init called again)
 *  13-Nov-01	stefan.roese@esd-electronics.com
 *		- Set IST bit in EMAC_M1 reg upon 100MBit or full duplex
 *  04-Jan-02	stefan.roese@esd-electronics.com
 *		- Wait for PHY auto negotiation to complete added
 *  06-Feb-02	stefan.roese@esd-electronics.com
 *		- Bug fixed in waiting for auto negotiation to complete
 *  26-Feb-02	stefan.roese@esd-electronics.com
 *		- rx and tx buffer descriptors now allocated (no fixed address
 *		  used anymore)
 *  17-Jun-02	stefan.roese@esd-electronics.com
 *		- MAL error debug printf 'M' removed (rx de interrupt may
 *		  occur upon many incoming packets with only 4 rx buffers).
W
wdenk 已提交
70
 *-----------------------------------------------------------------------------*
71 72 73 74 75 76 77
 *  17-Nov-03	travis.sawyer@sandburst.com
 *		- ported from 405gp_enet.c to utilized upto 4 EMAC ports
 *		  in the 440GX.	 This port should work with the 440GP
 *		  (2 EMACs) also
 *  15-Aug-05	sr@denx.de
 *		- merged 405gp_enet.c and 440gx_enet.c to generic 4xx_enet.c
		  now handling all 4xx cpu's.
W
wdenk 已提交
78 79 80 81 82 83
 *-----------------------------------------------------------------------------*/

#include <config.h>
#include <common.h>
#include <net.h>
#include <asm/processor.h>
84
#include <asm/io.h>
85 86
#include <asm/cache.h>
#include <asm/mmu.h>
W
wdenk 已提交
87
#include <commproc.h>
88 89
#include <ppc4xx.h>
#include <ppc4xx_enet.h>
W
wdenk 已提交
90 91 92 93 94
#include <405_mal.h>
#include <miiphy.h>
#include <malloc.h>
#include "vecnum.h"

95
/*
W
Wolfgang Denk 已提交
96
 * Only compile for platform with AMCC EMAC ethernet controller and
97 98 99
 * network support enabled.
 * Remark: CONFIG_405 describes Xilinx PPC405 FPGA without EMAC controller!
 */
100
#if defined(CONFIG_CMD_NET) && !defined(CONFIG_405) && !defined(CONFIG_IOP480)
101

102
#if !(defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
103 104
#error "CONFIG_MII has to be defined!"
#endif
W
wdenk 已提交
105

106 107 108 109
#if defined(CONFIG_NETCONSOLE) && !defined(CONFIG_NET_MULTI)
#error "CONFIG_NET_MULTI has to be defined for NetConsole"
#endif

110
#define EMAC_RESET_TIMEOUT 1000 /* 1000 ms reset timeout */
111
#define PHY_AUTONEGOTIATE_TIMEOUT 5000	/* 5000 ms autonegotiate timeout */
W
wdenk 已提交
112 113 114 115 116 117

/* Ethernet Transmit and Receive Buffers */
/* AS.HARNOIS
 * In the same way ENET_MAX_MTU and ENET_MAX_MTU_ALIGNED are set from
 * PKTSIZE and PKTSIZE_ALIGN (include/net.h)
 */
118
#define ENET_MAX_MTU	       PKTSIZE
W
wdenk 已提交
119 120 121 122 123 124 125 126 127
#define ENET_MAX_MTU_ALIGNED   PKTSIZE_ALIGN

/*-----------------------------------------------------------------------------+
 * Defines for MAL/EMAC interrupt conditions as reported in the UIC (Universal
 * Interrupt Controller).
 *-----------------------------------------------------------------------------*/
#define MAL_UIC_ERR ( UIC_MAL_SERR | UIC_MAL_TXDE  | UIC_MAL_RXDE)
#define MAL_UIC_DEF  (UIC_MAL_RXEOB | MAL_UIC_ERR)
#define EMAC_UIC_DEF UIC_ENET
128 129
#define EMAC_UIC_DEF1 UIC_ENET1
#define SEL_UIC_DEF(p) (p ? UIC_ENET1 : UIC_ENET )
W
wdenk 已提交
130

131
#undef INFO_4XX_ENET
W
wdenk 已提交
132

133 134
#define BI_PHYMODE_NONE	 0
#define BI_PHYMODE_ZMII	 1
W
wdenk 已提交
135
#define BI_PHYMODE_RGMII 2
136 137 138
#define BI_PHYMODE_GMII  3
#define BI_PHYMODE_RTBI  4
#define BI_PHYMODE_TBI   5
S
Stefan Roese 已提交
139 140
#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
    defined(CONFIG_405EX)
141 142 143
#define BI_PHYMODE_SMII  6
#define BI_PHYMODE_MII   7
#endif
W
wdenk 已提交
144

145
#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
S
Stefan Roese 已提交
146 147
    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
    defined(CONFIG_405EX)
148 149
#define SDR0_MFR_ETH_CLK_SEL_V(n)	((0x01<<27) / (n+1))
#endif
150

W
wdenk 已提交
151 152 153 154 155 156
/*-----------------------------------------------------------------------------+
 * Global variables. TX and RX descriptors and buffers.
 *-----------------------------------------------------------------------------*/
/* IER globals */
static uint32_t mal_ier;

157
#if !defined(CONFIG_NET_MULTI)
158
struct eth_device *emac0_dev = NULL;
159 160
#endif

161 162 163
/*
 * Get count of EMAC devices (doesn't have to be the max. possible number
 * supported by the cpu)
164 165 166 167
 *
 * CONFIG_BOARD_EMAC_COUNT added so now a "dynamic" way to configure the
 * EMAC count is possible. As it is needed for the Kilauea/Haleakala
 * 405EX/405EXr eval board, using the same binary.
168
 */
169 170 171
#if defined(CONFIG_BOARD_EMAC_COUNT)
#define LAST_EMAC_NUM	board_emac_count()
#else /* CONFIG_BOARD_EMAC_COUNT */
172 173 174 175 176 177 178 179 180
#if defined(CONFIG_HAS_ETH3)
#define LAST_EMAC_NUM	4
#elif defined(CONFIG_HAS_ETH2)
#define LAST_EMAC_NUM	3
#elif defined(CONFIG_HAS_ETH1)
#define LAST_EMAC_NUM	2
#else
#define LAST_EMAC_NUM	1
#endif
181
#endif /* CONFIG_BOARD_EMAC_COUNT */
182

183 184 185 186 187
/* normal boards start with EMAC0 */
#if !defined(CONFIG_EMAC_NR_START)
#define CONFIG_EMAC_NR_START	0
#endif

S
Stefan Roese 已提交
188 189 190 191 192 193
#if defined(CONFIG_405EX) || defined(CONFIG_440EPX)
#define ETH_IRQ_NUM(dev)	(VECNUM_ETH0 + ((dev)))
#else
#define ETH_IRQ_NUM(dev)	(VECNUM_ETH0 + ((dev) * 2))
#endif

194 195 196 197
#define MAL_RX_DESC_SIZE	2048
#define MAL_TX_DESC_SIZE	2048
#define MAL_ALLOC_SIZE		(MAL_TX_DESC_SIZE + MAL_RX_DESC_SIZE)

W
wdenk 已提交
198 199 200 201 202 203 204 205 206 207 208
/*-----------------------------------------------------------------------------+
 * Prototypes and externals.
 *-----------------------------------------------------------------------------*/
static void enet_rcv (struct eth_device *dev, unsigned long malisr);

int enetInt (struct eth_device *dev);
static void mal_err (struct eth_device *dev, unsigned long isr,
		     unsigned long uic, unsigned long maldef,
		     unsigned long mal_errr);
static void emac_err (struct eth_device *dev, unsigned long isr);

M
Marian Balakowicz 已提交
209 210 211 212 213
extern int phy_setup_aneg (char *devname, unsigned char addr);
extern int emac4xx_miiphy_read (char *devname, unsigned char addr,
		unsigned char reg, unsigned short *value);
extern int emac4xx_miiphy_write (char *devname, unsigned char addr,
		unsigned char reg, unsigned short value);
214

215 216
int board_emac_count(void);

W
wdenk 已提交
217
/*-----------------------------------------------------------------------------+
218
| ppc_4xx_eth_halt
W
wdenk 已提交
219 220
| Disable MAL channel, and EMACn
+-----------------------------------------------------------------------------*/
221
static void ppc_4xx_eth_halt (struct eth_device *dev)
W
wdenk 已提交
222
{
223
	EMAC_4XX_HW_PST hw_p = dev->priv;
W
wdenk 已提交
224
	uint32_t failsafe = 10000;
S
Stefan Roese 已提交
225 226 227
#if defined(CONFIG_440SPE) || \
    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
    defined(CONFIG_405EX)
228 229
	unsigned long mfr;
#endif
W
wdenk 已提交
230

231
	out_be32((void *)EMAC_IER + hw_p->hw_addr, 0x00000000);	/* disable emac interrupts */
W
wdenk 已提交
232 233 234

	/* 1st reset MAL channel */
	/* Note: writing a 0 to a channel has no effect */
235 236 237
#if defined(CONFIG_405EP) || defined(CONFIG_440EP) || defined(CONFIG_440GR)
	mtdcr (maltxcarr, (MAL_CR_MMSR >> (hw_p->devnum * 2)));
#else
W
wdenk 已提交
238
	mtdcr (maltxcarr, (MAL_CR_MMSR >> hw_p->devnum));
239
#endif
W
wdenk 已提交
240 241 242
	mtdcr (malrxcarr, (MAL_CR_MMSR >> hw_p->devnum));

	/* wait for reset */
243
	while (mfdcr (malrxcasr) & (MAL_CR_MMSR >> hw_p->devnum)) {
W
wdenk 已提交
244 245 246 247 248 249 250
		udelay (1000);	/* Delay 1 MS so as not to hammer the register */
		failsafe--;
		if (failsafe == 0)
			break;
	}

	/* EMAC RESET */
S
Stefan Roese 已提交
251 252 253
#if defined(CONFIG_440SPE) || \
    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
    defined(CONFIG_405EX)
254 255
	/* provide clocks for EMAC internal loopback  */
	mfsdr (sdr_mfr, mfr);
256
	mfr |= SDR0_MFR_ETH_CLK_SEL_V(hw_p->devnum);
257 258 259
	mtsdr(sdr_mfr, mfr);
#endif

260
	out_be32((void *)EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST);
W
wdenk 已提交
261

S
Stefan Roese 已提交
262 263 264
#if defined(CONFIG_440SPE) || \
    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
    defined(CONFIG_405EX)
265 266
	/* remove clocks for EMAC internal loopback  */
	mfsdr (sdr_mfr, mfr);
267
	mfr &= ~SDR0_MFR_ETH_CLK_SEL_V(hw_p->devnum);
268 269 270 271
	mtsdr(sdr_mfr, mfr);
#endif


272
#ifndef CONFIG_NETCONSOLE
273
	hw_p->print_speed = 1;	/* print speed message again next time */
274
#endif
275

W
wdenk 已提交
276 277 278
	return;
}

279
#if defined (CONFIG_440GX)
280
int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis)
W
wdenk 已提交
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
{
	unsigned long pfc1;
	unsigned long zmiifer;
	unsigned long rmiifer;

	mfsdr(sdr_pfc1, pfc1);
	pfc1 = SDR0_PFC1_EPS_DECODE(pfc1);

	zmiifer = 0;
	rmiifer = 0;

	switch (pfc1) {
	case 1:
		zmiifer |= ZMII_FER_RMII << ZMII_FER_V(0);
		zmiifer |= ZMII_FER_RMII << ZMII_FER_V(1);
		zmiifer |= ZMII_FER_RMII << ZMII_FER_V(2);
		zmiifer |= ZMII_FER_RMII << ZMII_FER_V(3);
		bis->bi_phymode[0] = BI_PHYMODE_ZMII;
		bis->bi_phymode[1] = BI_PHYMODE_ZMII;
		bis->bi_phymode[2] = BI_PHYMODE_ZMII;
		bis->bi_phymode[3] = BI_PHYMODE_ZMII;
		break;
	case 2:
304 305 306 307
		zmiifer |= ZMII_FER_SMII << ZMII_FER_V(0);
		zmiifer |= ZMII_FER_SMII << ZMII_FER_V(1);
		zmiifer |= ZMII_FER_SMII << ZMII_FER_V(2);
		zmiifer |= ZMII_FER_SMII << ZMII_FER_V(3);
W
wdenk 已提交
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362
		bis->bi_phymode[0] = BI_PHYMODE_ZMII;
		bis->bi_phymode[1] = BI_PHYMODE_ZMII;
		bis->bi_phymode[2] = BI_PHYMODE_ZMII;
		bis->bi_phymode[3] = BI_PHYMODE_ZMII;
		break;
	case 3:
		zmiifer |= ZMII_FER_RMII << ZMII_FER_V(0);
		rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(2);
		bis->bi_phymode[0] = BI_PHYMODE_ZMII;
		bis->bi_phymode[1] = BI_PHYMODE_NONE;
		bis->bi_phymode[2] = BI_PHYMODE_RGMII;
		bis->bi_phymode[3] = BI_PHYMODE_NONE;
		break;
	case 4:
		zmiifer |= ZMII_FER_SMII << ZMII_FER_V(0);
		zmiifer |= ZMII_FER_SMII << ZMII_FER_V(1);
		rmiifer |= RGMII_FER_RGMII << RGMII_FER_V (2);
		rmiifer |= RGMII_FER_RGMII << RGMII_FER_V (3);
		bis->bi_phymode[0] = BI_PHYMODE_ZMII;
		bis->bi_phymode[1] = BI_PHYMODE_ZMII;
		bis->bi_phymode[2] = BI_PHYMODE_RGMII;
		bis->bi_phymode[3] = BI_PHYMODE_RGMII;
		break;
	case 5:
		zmiifer |= ZMII_FER_SMII << ZMII_FER_V (0);
		zmiifer |= ZMII_FER_SMII << ZMII_FER_V (1);
		zmiifer |= ZMII_FER_SMII << ZMII_FER_V (2);
		rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(3);
		bis->bi_phymode[0] = BI_PHYMODE_ZMII;
		bis->bi_phymode[1] = BI_PHYMODE_ZMII;
		bis->bi_phymode[2] = BI_PHYMODE_ZMII;
		bis->bi_phymode[3] = BI_PHYMODE_RGMII;
		break;
	case 6:
		zmiifer |= ZMII_FER_SMII << ZMII_FER_V (0);
		zmiifer |= ZMII_FER_SMII << ZMII_FER_V (1);
		rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(2);
		bis->bi_phymode[0] = BI_PHYMODE_ZMII;
		bis->bi_phymode[1] = BI_PHYMODE_ZMII;
		bis->bi_phymode[2] = BI_PHYMODE_RGMII;
		break;
	case 0:
	default:
		zmiifer = ZMII_FER_MII << ZMII_FER_V(devnum);
		rmiifer = 0x0;
		bis->bi_phymode[0] = BI_PHYMODE_ZMII;
		bis->bi_phymode[1] = BI_PHYMODE_ZMII;
		bis->bi_phymode[2] = BI_PHYMODE_ZMII;
		bis->bi_phymode[3] = BI_PHYMODE_ZMII;
		break;
	}

	/* Ensure we setup mdio for this devnum and ONLY this devnum */
	zmiifer |= (ZMII_FER_MDI) << ZMII_FER_V(devnum);

363 364
	out_be32((void *)ZMII_FER, zmiifer);
	out_be32((void *)RGMII_FER, rmiifer);
W
wdenk 已提交
365 366 367

	return ((int)pfc1);
}
368
#endif	/* CONFIG_440_GX */
W
wdenk 已提交
369

370 371 372 373
#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis)
{
	unsigned long zmiifer=0x0;
374
	unsigned long pfc1;
375

376 377 378
	mfsdr(sdr_pfc1, pfc1);
	pfc1 &= SDR0_PFC1_SELECT_MASK;

379
	switch (pfc1) {
380
	case SDR0_PFC1_SELECT_CONFIG_2:
381
		/* 1 x GMII port */
382 383
		out_be32((void *)ZMII_FER, 0x00);
		out_be32((void *)RGMII_FER, 0x00000037);
384 385 386
		bis->bi_phymode[0] = BI_PHYMODE_GMII;
		bis->bi_phymode[1] = BI_PHYMODE_NONE;
		break;
387
	case SDR0_PFC1_SELECT_CONFIG_4:
388
		/* 2 x RGMII ports */
389 390
		out_be32((void *)ZMII_FER, 0x00);
		out_be32((void *)RGMII_FER, 0x00000055);
391 392 393
		bis->bi_phymode[0] = BI_PHYMODE_RGMII;
		bis->bi_phymode[1] = BI_PHYMODE_RGMII;
		break;
394
	case SDR0_PFC1_SELECT_CONFIG_6:
395
		/* 2 x SMII ports */
396 397 398 399
		out_be32((void *)ZMII_FER,
			 ((ZMII_FER_SMII) << ZMII_FER_V(0)) |
			 ((ZMII_FER_SMII) << ZMII_FER_V(1)));
		out_be32((void *)RGMII_FER, 0x00000000);
400 401 402 403 404
		bis->bi_phymode[0] = BI_PHYMODE_SMII;
		bis->bi_phymode[1] = BI_PHYMODE_SMII;
		break;
	case SDR0_PFC1_SELECT_CONFIG_1_2:
		/* only 1 x MII supported */
405 406
		out_be32((void *)ZMII_FER, (ZMII_FER_MII) << ZMII_FER_V(0));
		out_be32((void *)RGMII_FER, 0x00000000);
407 408
		bis->bi_phymode[0] = BI_PHYMODE_MII;
		bis->bi_phymode[1] = BI_PHYMODE_NONE;
409 410 411 412 413 414
		break;
	default:
		break;
	}

	/* Ensure we setup mdio for this devnum and ONLY this devnum */
415
	zmiifer = in_be32((void *)ZMII_FER);
416
	zmiifer |= (ZMII_FER_MDI) << ZMII_FER_V(devnum);
417
	out_be32((void *)ZMII_FER, zmiifer);
418 419 420 421 422

	return ((int)0x0);
}
#endif	/* CONFIG_440EPX */

S
Stefan Roese 已提交
423 424 425 426 427 428 429 430 431 432 433 434
#if defined(CONFIG_405EX)
int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis)
{
	u32 gmiifer = 0;

	/*
	 * Right now only 2*RGMII is supported. Please extend when needed.
	 * sr - 2007-09-19
	 */
	switch (1) {
	case 1:
		/* 2 x RGMII ports */
435
		out_be32((void *)RGMII_FER, 0x00000055);
S
Stefan Roese 已提交
436 437 438 439 440 441 442 443 444 445 446
		bis->bi_phymode[0] = BI_PHYMODE_RGMII;
		bis->bi_phymode[1] = BI_PHYMODE_RGMII;
		break;
	case 2:
		/* 2 x SMII ports */
		break;
	default:
		break;
	}

	/* Ensure we setup mdio for this devnum and ONLY this devnum */
447
	gmiifer = in_be32((void *)RGMII_FER);
S
Stefan Roese 已提交
448
	gmiifer |= (1 << (19-devnum));
449
	out_be32((void *)RGMII_FER, gmiifer);
S
Stefan Roese 已提交
450 451 452 453 454

	return ((int)0x0);
}
#endif  /* CONFIG_405EX */

455 456 457 458 459 460
static inline void *malloc_aligned(u32 size, u32 align)
{
	return (void *)(((u32)malloc(size + align) + align - 1) &
			~(align - 1));
}

461
static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
W
wdenk 已提交
462
{
463
	int i;
464
	unsigned long reg = 0;
W
wdenk 已提交
465 466 467 468 469 470 471
	unsigned long msr;
	unsigned long speed;
	unsigned long duplex;
	unsigned long failsafe;
	unsigned mode_reg;
	unsigned short devnum;
	unsigned short reg_short;
472 473
#if defined(CONFIG_440GX) || \
    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
S
Stefan Roese 已提交
474 475
    defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
    defined(CONFIG_405EX)
476
	sys_info_t sysinfo;
477
#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
S
Stefan Roese 已提交
478 479
    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
    defined(CONFIG_405EX)
480 481
	int ethgroup = -1;
#endif
482
#endif
483
#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
S
Stefan Roese 已提交
484 485
    defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
    defined(CONFIG_405EX)
486 487
	unsigned long mfr;
#endif
488 489
	u32 bd_cached;
	u32 bd_uncached = 0;
490

491
	EMAC_4XX_HW_PST hw_p = dev->priv;
W
wdenk 已提交
492 493 494

	/* before doing anything, figure out if we have a MAC address */
	/* if not, bail */
495 496
	if (memcmp (dev->enetaddr, "\0\0\0\0\0\0", 6) == 0) {
		printf("ERROR: ethaddr not set!\n");
W
wdenk 已提交
497
		return -1;
498
	}
W
wdenk 已提交
499

500 501
#if defined(CONFIG_440GX) || \
    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
S
Stefan Roese 已提交
502 503
    defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
    defined(CONFIG_405EX)
W
wdenk 已提交
504 505
	/* Need to get the OPB frequency so we can access the PHY */
	get_sys_info (&sysinfo);
506
#endif
W
wdenk 已提交
507 508 509 510 511 512

	msr = mfmsr ();
	mtmsr (msr & ~(MSR_EE));	/* disable interrupts */

	devnum = hw_p->devnum;

513
#ifdef INFO_4XX_ENET
W
wdenk 已提交
514 515
	/* AS.HARNOIS
	 * We should have :
516
	 * hw_p->stats.pkts_handled <=	hw_p->stats.pkts_rx <= hw_p->stats.pkts_handled+PKTBUFSRX
W
wdenk 已提交
517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532
	 * In the most cases hw_p->stats.pkts_handled = hw_p->stats.pkts_rx, but it
	 * is possible that new packets (without relationship with
	 * current transfer) have got the time to arrived before
	 * netloop calls eth_halt
	 */
	printf ("About preceeding transfer (eth%d):\n"
		"- Sent packet number %d\n"
		"- Received packet number %d\n"
		"- Handled packet number %d\n",
		hw_p->devnum,
		hw_p->stats.pkts_tx,
		hw_p->stats.pkts_rx, hw_p->stats.pkts_handled);

	hw_p->stats.pkts_tx = 0;
	hw_p->stats.pkts_rx = 0;
	hw_p->stats.pkts_handled = 0;
533
	hw_p->print_speed = 1;	/* print speed message again next time */
W
wdenk 已提交
534 535
#endif

536 537
	hw_p->tx_err_index = 0; /* Transmit Error Index for tx_err_log */
	hw_p->rx_err_index = 0; /* Receive Error Index for rx_err_log */
W
wdenk 已提交
538 539 540 541 542 543 544 545 546

	hw_p->rx_slot = 0;	/* MAL Receive Slot */
	hw_p->rx_i_index = 0;	/* Receive Interrupt Queue Index */
	hw_p->rx_u_index = 0;	/* Receive User Queue Index */

	hw_p->tx_slot = 0;	/* MAL Transmit Slot */
	hw_p->tx_i_index = 0;	/* Transmit Interrupt Queue Index */
	hw_p->tx_u_index = 0;	/* Transmit User Queue Index */

547
#if defined(CONFIG_440) && !defined(CONFIG_440SP) && !defined(CONFIG_440SPE)
W
wdenk 已提交
548 549 550 551 552
	/* set RMII mode */
	/* NOTE: 440GX spec states that mode is mutually exclusive */
	/* NOTE: Therefore, disable all other EMACS, since we handle */
	/* NOTE: only one emac at a time */
	reg = 0;
553
	out_be32((void *)ZMII_FER, 0);
W
wdenk 已提交
554 555
	udelay (100);

556
#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
557
	out_be32((void *)ZMII_FER, (ZMII_FER_RMII | ZMII_FER_MDI) << ZMII_FER_V (devnum));
558
#elif defined(CONFIG_440GX) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
559
	ethgroup = ppc_4xx_eth_setup_bridge(devnum, bis);
560 561
#elif defined(CONFIG_440GP)
	/* set RMII mode */
562
	out_be32((void *)ZMII_FER, ZMII_RMII | ZMII_MDI0);
W
wdenk 已提交
563 564
#else
	if ((devnum == 0) || (devnum == 1)) {
565
		out_be32((void *)ZMII_FER, (ZMII_FER_SMII | ZMII_FER_MDI) << ZMII_FER_V (devnum));
566
	} else { /* ((devnum == 2) || (devnum == 3)) */
567 568 569
		out_be32((void *)ZMII_FER, ZMII_FER_MDI << ZMII_FER_V (devnum));
		out_be32((void *)RGMII_FER, ((RGMII_FER_RGMII << RGMII_FER_V (2)) |
					     (RGMII_FER_RGMII << RGMII_FER_V (3))));
W
wdenk 已提交
570 571
	}
#endif
572

573
	out_be32((void *)ZMII_SSR, ZMII_SSR_SP << ZMII_SSR_V(devnum));
574
#endif /* defined(CONFIG_440) && !defined(CONFIG_440SP) */
S
Stefan Roese 已提交
575 576 577
#if defined(CONFIG_405EX)
	ethgroup = ppc_4xx_eth_setup_bridge(devnum, bis);
#endif
578

W
wdenk 已提交
579 580 581
	__asm__ volatile ("eieio");

	/* reset emac so we have access to the phy */
S
Stefan Roese 已提交
582 583 584
#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
    defined(CONFIG_405EX)
585 586
	/* provide clocks for EMAC internal loopback  */
	mfsdr (sdr_mfr, mfr);
587
	mfr |= SDR0_MFR_ETH_CLK_SEL_V(devnum);
588 589
	mtsdr(sdr_mfr, mfr);
#endif
W
wdenk 已提交
590

591
	out_be32((void *)EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST);
W
wdenk 已提交
592 593

	failsafe = 1000;
594
	while ((in_be32((void *)EMAC_M0 + hw_p->hw_addr) & (EMAC_M0_SRST)) && failsafe) {
W
wdenk 已提交
595 596 597
		udelay (1000);
		failsafe--;
	}
598 599
	if (failsafe <= 0)
		printf("\nProblem resetting EMAC!\n");
W
wdenk 已提交
600

S
Stefan Roese 已提交
601 602 603
#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
    defined(CONFIG_405EX)
604 605
	/* remove clocks for EMAC internal loopback  */
	mfsdr (sdr_mfr, mfr);
606
	mfr &= ~SDR0_MFR_ETH_CLK_SEL_V(devnum);
607 608 609
	mtsdr(sdr_mfr, mfr);
#endif

610 611
#if defined(CONFIG_440GX) || \
    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
S
Stefan Roese 已提交
612 613
    defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
    defined(CONFIG_405EX)
W
wdenk 已提交
614 615 616 617 618 619 620 621 622 623 624 625 626
	/* Whack the M1 register */
	mode_reg = 0x0;
	mode_reg &= ~0x00000038;
	if (sysinfo.freqOPB <= 50000000);
	else if (sysinfo.freqOPB <= 66666667)
		mode_reg |= EMAC_M1_OBCI_66;
	else if (sysinfo.freqOPB <= 83333333)
		mode_reg |= EMAC_M1_OBCI_83;
	else if (sysinfo.freqOPB <= 100000000)
		mode_reg |= EMAC_M1_OBCI_100;
	else
		mode_reg |= EMAC_M1_OBCI_GT100;

627
	out_be32((void *)EMAC_M1 + hw_p->hw_addr, mode_reg);
628
#endif /* defined(CONFIG_440GX) || defined(CONFIG_440SP) */
W
wdenk 已提交
629 630 631 632 633 634 635 636

	/* wait for PHY to complete auto negotiation */
	reg_short = 0;
#ifndef CONFIG_CS8952_PHY
	switch (devnum) {
	case 0:
		reg = CONFIG_PHY_ADDR;
		break;
637
#if defined (CONFIG_PHY1_ADDR)
W
wdenk 已提交
638 639 640
	case 1:
		reg = CONFIG_PHY1_ADDR;
		break;
641
#endif
642
#if defined (CONFIG_440GX)
W
wdenk 已提交
643 644 645 646 647 648 649 650 651 652 653 654
	case 2:
		reg = CONFIG_PHY2_ADDR;
		break;
	case 3:
		reg = CONFIG_PHY3_ADDR;
		break;
#endif
	default:
		reg = CONFIG_PHY_ADDR;
		break;
	}

W
wdenk 已提交
655 656
	bis->bi_phynum[devnum] = reg;

657
#if defined(CONFIG_PHY_RESET)
W
wdenk 已提交
658 659 660 661 662
	/*
	 * Reset the phy, only if its the first time through
	 * otherwise, just check the speeds & feeds
	 */
	if (hw_p->first_init == 0) {
663
#if defined(CONFIG_M88E1111_PHY)
664 665 666 667 668
		miiphy_write (dev->name, reg, 0x14, 0x0ce3);
		miiphy_write (dev->name, reg, 0x18, 0x4101);
		miiphy_write (dev->name, reg, 0x09, 0x0e00);
		miiphy_write (dev->name, reg, 0x04, 0x01e1);
#endif
M
Marian Balakowicz 已提交
669
		miiphy_reset (dev->name, reg);
W
wdenk 已提交
670

671 672
#if defined(CONFIG_440GX) || \
    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
S
Stefan Roese 已提交
673 674
    defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
    defined(CONFIG_405EX)
675

W
wdenk 已提交
676
#if defined(CONFIG_CIS8201_PHY)
677
		/*
678 679
		 * Cicada 8201 PHY needs to have an extended register whacked
		 * for RGMII mode.
680
		 */
681
		if (((devnum == 2) || (devnum == 3)) && (4 == ethgroup)) {
682
#if defined(CONFIG_CIS8201_SHORT_ETCH)
M
Marian Balakowicz 已提交
683
			miiphy_write (dev->name, reg, 23, 0x1300);
684
#else
M
Marian Balakowicz 已提交
685
			miiphy_write (dev->name, reg, 23, 0x1000);
686
#endif
687 688 689 690 691 692
			/*
			 * Vitesse VSC8201/Cicada CIS8201 errata:
			 * Interoperability problem with Intel 82547EI phys
			 * This work around (provided by Vitesse) changes
			 * the default timer convergence from 8ms to 12ms
			 */
M
Marian Balakowicz 已提交
693 694 695 696 697 698 699 700 701
			miiphy_write (dev->name, reg, 0x1f, 0x2a30);
			miiphy_write (dev->name, reg, 0x08, 0x0200);
			miiphy_write (dev->name, reg, 0x1f, 0x52b5);
			miiphy_write (dev->name, reg, 0x02, 0x0004);
			miiphy_write (dev->name, reg, 0x01, 0x0671);
			miiphy_write (dev->name, reg, 0x00, 0x8fae);
			miiphy_write (dev->name, reg, 0x1f, 0x2a30);
			miiphy_write (dev->name, reg, 0x08, 0x0000);
			miiphy_write (dev->name, reg, 0x1f, 0x0000);
702 703
			/* end Vitesse/Cicada errata */
		}
W
wdenk 已提交
704
#endif
705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724

#if defined(CONFIG_ET1011C_PHY)
		/*
		 * Agere ET1011c PHY needs to have an extended register whacked
		 * for RGMII mode.
		 */
		if (((devnum == 2) || (devnum ==3)) && (4 == ethgroup)) {
			miiphy_read (dev->name, reg, 0x16, &reg_short);
			reg_short &= ~(0x7);
			reg_short |= 0x6;	/* RGMII DLL Delay*/
			miiphy_write (dev->name, reg, 0x16, reg_short);

			miiphy_read (dev->name, reg, 0x17, &reg_short);
			reg_short &= ~(0x40);
			miiphy_write (dev->name, reg, 0x17, reg_short);

			miiphy_write(dev->name, reg, 0x1c, 0x74f0);
		}
#endif

W
wdenk 已提交
725
#endif
W
wdenk 已提交
726
		/* Start/Restart autonegotiation */
M
Marian Balakowicz 已提交
727
		phy_setup_aneg (dev->name, reg);
W
wdenk 已提交
728 729
		udelay (1000);
	}
730
#endif /* defined(CONFIG_PHY_RESET) */
W
wdenk 已提交
731

M
Marian Balakowicz 已提交
732
	miiphy_read (dev->name, reg, PHY_BMSR, &reg_short);
W
wdenk 已提交
733 734

	/*
W
wdenk 已提交
735
	 * Wait if PHY is capable of autonegotiation and autonegotiation is not complete
W
wdenk 已提交
736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753
	 */
	if ((reg_short & PHY_BMSR_AUTN_ABLE)
	    && !(reg_short & PHY_BMSR_AUTN_COMP)) {
		puts ("Waiting for PHY auto negotiation to complete");
		i = 0;
		while (!(reg_short & PHY_BMSR_AUTN_COMP)) {
			/*
			 * Timeout reached ?
			 */
			if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
				puts (" TIMEOUT !\n");
				break;
			}

			if ((i++ % 1000) == 0) {
				putc ('.');
			}
			udelay (1000);	/* 1 ms */
M
Marian Balakowicz 已提交
754
			miiphy_read (dev->name, reg, PHY_BMSR, &reg_short);
W
wdenk 已提交
755 756 757 758 759

		}
		puts (" done\n");
		udelay (500000);	/* another 500 ms (results in faster booting) */
	}
760 761
#endif /* #ifndef CONFIG_CS8952_PHY */

M
Marian Balakowicz 已提交
762 763
	speed = miiphy_speed (dev->name, reg);
	duplex = miiphy_duplex (dev->name, reg);
W
wdenk 已提交
764 765 766

	if (hw_p->print_speed) {
		hw_p->print_speed = 0;
767 768 769
		printf ("ENET Speed is %d Mbps - %s duplex connection (EMAC%d)\n",
			(int) speed, (duplex == HALF) ? "HALF" : "FULL",
			hw_p->devnum);
W
wdenk 已提交
770 771
	}

772 773
#if defined(CONFIG_440) && !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \
    !defined(CONFIG_440EPX) && !defined(CONFIG_440GRX)
774
#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
775 776 777 778 779 780 781 782
	mfsdr(sdr_mfr, reg);
	if (speed == 100) {
		reg = (reg & ~SDR0_MFR_ZMII_MODE_MASK) | SDR0_MFR_ZMII_MODE_RMII_100M;
	} else {
		reg = (reg & ~SDR0_MFR_ZMII_MODE_MASK) | SDR0_MFR_ZMII_MODE_RMII_10M;
	}
	mtsdr(sdr_mfr, reg);
#endif
783

W
wdenk 已提交
784
	/* Set ZMII/RGMII speed according to the phy link speed */
785
	reg = in_be32((void *)ZMII_SSR);
W
wdenk 已提交
786
	if ( (speed == 100) || (speed == 1000) )
787
		out_be32((void *)ZMII_SSR, reg | (ZMII_SSR_SP << ZMII_SSR_V (devnum)));
W
wdenk 已提交
788
	else
789
		out_be32((void *)ZMII_SSR, reg & (~(ZMII_SSR_SP << ZMII_SSR_V (devnum))));
W
wdenk 已提交
790 791 792 793 794 795

	if ((devnum == 2) || (devnum == 3)) {
		if (speed == 1000)
			reg = (RGMII_SSR_SP_1000MBPS << RGMII_SSR_V (devnum));
		else if (speed == 100)
			reg = (RGMII_SSR_SP_100MBPS << RGMII_SSR_V (devnum));
796
		else if (speed == 10)
W
wdenk 已提交
797
			reg = (RGMII_SSR_SP_10MBPS << RGMII_SSR_V (devnum));
798 799 800 801
		else {
			printf("Error in RGMII Speed\n");
			return -1;
		}
802
		out_be32((void *)RGMII_SSR, reg);
W
wdenk 已提交
803
	}
804
#endif /* defined(CONFIG_440) && !defined(CONFIG_440SP) */
W
wdenk 已提交
805

S
Stefan Roese 已提交
806 807
#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
    defined(CONFIG_405EX)
808 809 810 811 812 813 814 815 816 817
	if (speed == 1000)
		reg = (RGMII_SSR_SP_1000MBPS << RGMII_SSR_V (devnum));
	else if (speed == 100)
		reg = (RGMII_SSR_SP_100MBPS << RGMII_SSR_V (devnum));
	else if (speed == 10)
		reg = (RGMII_SSR_SP_10MBPS << RGMII_SSR_V (devnum));
	else {
		printf("Error in RGMII Speed\n");
		return -1;
	}
818
	out_be32((void *)RGMII_SSR, reg);
819 820
#endif

W
wdenk 已提交
821
	/* set the Mal configuration reg */
822 823
#if defined(CONFIG_440GX) || \
    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
S
Stefan Roese 已提交
824 825
    defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
    defined(CONFIG_405EX)
826 827 828 829
	mtdcr (malmcr, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA |
	       MAL_CR_PLBLT_DEFAULT | MAL_CR_EOPIE | 0x00330000);
#else
	mtdcr (malmcr, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA | MAL_CR_PLBLT_DEFAULT);
W
wdenk 已提交
830
	/* Errata 1.12: MAL_1 -- Disable MAL bursting */
831 832 833 834
	if (get_pvr() == PVR_440GP_RB) {
		mtdcr (malmcr, mfdcr(malmcr) & ~MAL_CR_PLBB);
	}
#endif
W
wdenk 已提交
835 836 837 838 839 840 841

	/*
	 * Malloc MAL buffer desciptors, make sure they are
	 * aligned on cache line boundary size
	 * (401/403/IOP480 = 16, 405 = 32)
	 * and doesn't cross cache block boundaries.
	 */
842 843
	if (hw_p->first_init == 0) {
		debug("*** Allocating descriptor memory ***\n");
W
wdenk 已提交
844

845 846 847 848 849
		bd_cached = (u32)malloc_aligned(MAL_ALLOC_SIZE, 4096);
		if (!bd_cached) {
			printf("%s: Error allocating MAL descriptor buffers!\n");
			return -1;
		}
850

851
#ifdef CONFIG_4xx_DCACHE
852
		flush_dcache_range(bd_cached, bd_cached + MAL_ALLOC_SIZE);
853 854 855 856 857 858 859 860 861 862 863
		bd_uncached = bis->bi_memsize;
		program_tlb(bd_cached, bd_uncached, MAL_ALLOC_SIZE,
			    TLB_WORD2_I_ENABLE);
#else
		bd_uncached = bd_cached;
#endif
		hw_p->tx_phys = bd_cached;
		hw_p->rx_phys = bd_cached + MAL_TX_DESC_SIZE;
		hw_p->tx = (mal_desc_t *)(bd_uncached);
		hw_p->rx = (mal_desc_t *)(bd_uncached + MAL_TX_DESC_SIZE);
		debug("hw_p->tx=%08x, hw_p->rx=%08x\n", hw_p->tx, hw_p->rx);
W
wdenk 已提交
864 865 866 867 868
	}

	for (i = 0; i < NUM_TX_BUFF; i++) {
		hw_p->tx[i].ctrl = 0;
		hw_p->tx[i].data_len = 0;
869 870 871
		if (hw_p->first_init == 0)
			hw_p->txbuf_ptr = malloc_aligned(MAL_ALLOC_SIZE,
							 L1_CACHE_BYTES);
W
wdenk 已提交
872 873 874 875
		hw_p->tx[i].data_ptr = hw_p->txbuf_ptr;
		if ((NUM_TX_BUFF - 1) == i)
			hw_p->tx[i].ctrl |= MAL_TX_CTRL_WRAP;
		hw_p->tx_run[i] = -1;
876
		debug("TX_BUFF %d @ 0x%08lx\n", i, (u32)hw_p->tx[i].data_ptr);
W
wdenk 已提交
877 878 879 880 881
	}

	for (i = 0; i < NUM_RX_BUFF; i++) {
		hw_p->rx[i].ctrl = 0;
		hw_p->rx[i].data_len = 0;
882
		hw_p->rx[i].data_ptr = (char *)NetRxPackets[i];
W
wdenk 已提交
883 884 885 886
		if ((NUM_RX_BUFF - 1) == i)
			hw_p->rx[i].ctrl |= MAL_RX_CTRL_WRAP;
		hw_p->rx[i].ctrl |= MAL_RX_CTRL_EMPTY | MAL_RX_CTRL_INTR;
		hw_p->rx_ready[i] = -1;
887
		debug("RX_BUFF %d @ 0x%08lx\n", i, (u32)hw_p->rx[i].data_ptr);
W
wdenk 已提交
888 889 890 891 892 893 894 895
	}

	reg = 0x00000000;

	reg |= dev->enetaddr[0];	/* set high address */
	reg = reg << 8;
	reg |= dev->enetaddr[1];

896
	out_be32((void *)EMAC_IAH + hw_p->hw_addr, reg);
W
wdenk 已提交
897 898 899 900 901 902 903 904 905 906

	reg = 0x00000000;
	reg |= dev->enetaddr[2];	/* set low address  */
	reg = reg << 8;
	reg |= dev->enetaddr[3];
	reg = reg << 8;
	reg |= dev->enetaddr[4];
	reg = reg << 8;
	reg |= dev->enetaddr[5];

907
	out_be32((void *)EMAC_IAL + hw_p->hw_addr, reg);
W
wdenk 已提交
908 909 910 911

	switch (devnum) {
	case 1:
		/* setup MAL tx & rx channel pointers */
912
#if defined (CONFIG_405EP) || defined (CONFIG_440EP) || defined (CONFIG_440GR)
913
		mtdcr (maltxctp2r, hw_p->tx_phys);
914
#else
915
		mtdcr (maltxctp1r, hw_p->tx_phys);
916
#endif
917
#if defined(CONFIG_440)
918
		mtdcr (maltxbattr, 0x0);
W
wdenk 已提交
919
		mtdcr (malrxbattr, 0x0);
920
#endif
921
		mtdcr (malrxctp1r, hw_p->rx_phys);
W
wdenk 已提交
922 923 924
		/* set RX buffer size */
		mtdcr (malrcbs1, ENET_MAX_MTU_ALIGNED / 16);
		break;
925
#if defined (CONFIG_440GX)
W
wdenk 已提交
926 927 928 929
	case 2:
		/* setup MAL tx & rx channel pointers */
		mtdcr (maltxbattr, 0x0);
		mtdcr (malrxbattr, 0x0);
930 931
		mtdcr (maltxctp2r, hw_p->tx_phys);
		mtdcr (malrxctp2r, hw_p->rx_phys);
W
wdenk 已提交
932 933 934 935 936 937
		/* set RX buffer size */
		mtdcr (malrcbs2, ENET_MAX_MTU_ALIGNED / 16);
		break;
	case 3:
		/* setup MAL tx & rx channel pointers */
		mtdcr (maltxbattr, 0x0);
938
		mtdcr (maltxctp3r, hw_p->tx_phys);
W
wdenk 已提交
939
		mtdcr (malrxbattr, 0x0);
940
		mtdcr (malrxctp3r, hw_p->rx_phys);
W
wdenk 已提交
941 942 943
		/* set RX buffer size */
		mtdcr (malrcbs3, ENET_MAX_MTU_ALIGNED / 16);
		break;
944
#endif /* CONFIG_440GX */
W
wdenk 已提交
945 946 947
	case 0:
	default:
		/* setup MAL tx & rx channel pointers */
948
#if defined(CONFIG_440)
W
wdenk 已提交
949 950
		mtdcr (maltxbattr, 0x0);
		mtdcr (malrxbattr, 0x0);
951
#endif
952 953
		mtdcr (maltxctp0r, hw_p->tx_phys);
		mtdcr (malrxctp0r, hw_p->rx_phys);
W
wdenk 已提交
954 955 956 957 958 959
		/* set RX buffer size */
		mtdcr (malrcbs0, ENET_MAX_MTU_ALIGNED / 16);
		break;
	}

	/* Enable MAL transmit and receive channels */
960
#if defined(CONFIG_405EP) || defined(CONFIG_440EP) || defined(CONFIG_440GR)
961 962
	mtdcr (maltxcasr, (MAL_TXRX_CASR >> (hw_p->devnum*2)));
#else
W
wdenk 已提交
963
	mtdcr (maltxcasr, (MAL_TXRX_CASR >> hw_p->devnum));
964
#endif
W
wdenk 已提交
965 966 967
	mtdcr (malrxcasr, (MAL_TXRX_CASR >> hw_p->devnum));

	/* set transmit enable & receive enable */
968
	out_be32((void *)EMAC_M0 + hw_p->hw_addr, EMAC_M0_TXE | EMAC_M0_RXE);
W
wdenk 已提交
969 970

	/* set receive fifo to 4k and tx fifo to 2k */
971
	mode_reg = in_be32((void *)EMAC_M1 + hw_p->hw_addr);
W
wdenk 已提交
972 973 974
	mode_reg |= EMAC_M1_RFS_4K | EMAC_M1_TX_FIFO_2K;

	/* set speed */
975
	if (speed == _1000BASET) {
S
Stefan Roese 已提交
976 977
#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
    defined(CONFIG_440SP) || defined(CONFIG_440SPE)
978
		unsigned long pfc1;
979

980 981 982 983
		mfsdr (sdr_pfc1, pfc1);
		pfc1 |= SDR0_PFC1_EM_1000;
		mtsdr (sdr_pfc1, pfc1);
#endif
W
wdenk 已提交
984
		mode_reg = mode_reg | EMAC_M1_MF_1000MBPS | EMAC_M1_IST;
985
	} else if (speed == _100BASET)
W
wdenk 已提交
986 987 988 989 990 991
		mode_reg = mode_reg | EMAC_M1_MF_100MBPS | EMAC_M1_IST;
	else
		mode_reg = mode_reg & ~0x00C00000;	/* 10 MBPS */
	if (duplex == FULL)
		mode_reg = mode_reg | 0x80000000 | EMAC_M1_IST;

992
	out_be32((void *)EMAC_M1 + hw_p->hw_addr, mode_reg);
W
wdenk 已提交
993 994 995

	/* Enable broadcast and indvidual address */
	/* TBS: enabling runts as some misbehaved nics will send runts */
996
	out_be32((void *)EMAC_RXM + hw_p->hw_addr, EMAC_RMR_BAE | EMAC_RMR_IAE);
W
wdenk 已提交
997 998 999 1000

	/* we probably need to set the tx mode1 reg? maybe at tx time */

	/* set transmit request threshold register */
1001
	out_be32((void *)EMAC_TRTR + hw_p->hw_addr, 0x18000000);	/* 256 byte threshold */
W
wdenk 已提交
1002

1003
	/* set receive	low/high water mark register */
1004
#if defined(CONFIG_440)
1005
	/* 440s has a 64 byte burst length */
1006
	out_be32((void *)EMAC_RX_HI_LO_WMARK + hw_p->hw_addr, 0x80009000);
1007 1008
#else
	/* 405s have a 16 byte burst length */
1009
	out_be32((void *)EMAC_RX_HI_LO_WMARK + hw_p->hw_addr, 0x0f002000);
1010
#endif /* defined(CONFIG_440) */
1011
	out_be32((void *)EMAC_TXM1 + hw_p->hw_addr, 0xf8640000);
W
wdenk 已提交
1012 1013

	/* Set fifo limit entry in tx mode 0 */
1014
	out_be32((void *)EMAC_TXM0 + hw_p->hw_addr, 0x00000003);
W
wdenk 已提交
1015
	/* Frame gap set */
1016
	out_be32((void *)EMAC_I_FRAME_GAP_REG + hw_p->hw_addr, 0x00000008);
W
wdenk 已提交
1017 1018

	/* Set EMAC IER */
1019
	hw_p->emac_ier = EMAC_ISR_PTLE | EMAC_ISR_BFCS | EMAC_ISR_ORE | EMAC_ISR_IRE;
W
wdenk 已提交
1020 1021 1022
	if (speed == _100BASET)
		hw_p->emac_ier = hw_p->emac_ier | EMAC_ISR_SYE;

1023 1024
	out_be32((void *)EMAC_ISR + hw_p->hw_addr, 0xffffffff);	/* clear pending interrupts */
	out_be32((void *)EMAC_IER + hw_p->hw_addr, hw_p->emac_ier);
W
wdenk 已提交
1025 1026 1027 1028 1029

	if (hw_p->first_init == 0) {
		/*
		 * Connect interrupt service routines
		 */
S
Stefan Roese 已提交
1030 1031
		irq_install_handler(ETH_IRQ_NUM(hw_p->devnum),
				    (interrupt_handler_t *) enetInt, dev);
W
wdenk 已提交
1032 1033 1034 1035 1036 1037 1038
	}

	mtmsr (msr);		/* enable interrupts again */

	hw_p->bis = bis;
	hw_p->first_init = 1;

1039
	return 0;
W
wdenk 已提交
1040 1041 1042
}


1043
static int ppc_4xx_eth_send (struct eth_device *dev, volatile void *ptr,
W
wdenk 已提交
1044 1045 1046 1047 1048
			      int len)
{
	struct enet_frame *ef_ptr;
	ulong time_start, time_now;
	unsigned long temp_txm0;
1049
	EMAC_4XX_HW_PST hw_p = dev->priv;
W
wdenk 已提交
1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066

	ef_ptr = (struct enet_frame *) ptr;

	/*-----------------------------------------------------------------------+
	 *  Copy in our address into the frame.
	 *-----------------------------------------------------------------------*/
	(void) memcpy (ef_ptr->source_addr, dev->enetaddr, ENET_ADDR_LENGTH);

	/*-----------------------------------------------------------------------+
	 * If frame is too long or too short, modify length.
	 *-----------------------------------------------------------------------*/
	/* TBS: where does the fragment go???? */
	if (len > ENET_MAX_MTU)
		len = ENET_MAX_MTU;

	/*   memcpy ((void *) &tx_buff[tx_slot], (const void *) ptr, len); */
	memcpy ((void *) hw_p->txbuf_ptr, (const void *) ptr, len);
1067
	flush_dcache_range((u32)hw_p->txbuf_ptr, (u32)hw_p->txbuf_ptr + len);
W
wdenk 已提交
1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082

	/*-----------------------------------------------------------------------+
	 * set TX Buffer busy, and send it
	 *-----------------------------------------------------------------------*/
	hw_p->tx[hw_p->tx_slot].ctrl = (MAL_TX_CTRL_LAST |
					EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP) &
		~(EMAC_TX_CTRL_ISA | EMAC_TX_CTRL_RSA);
	if ((NUM_TX_BUFF - 1) == hw_p->tx_slot)
		hw_p->tx[hw_p->tx_slot].ctrl |= MAL_TX_CTRL_WRAP;

	hw_p->tx[hw_p->tx_slot].data_len = (short) len;
	hw_p->tx[hw_p->tx_slot].ctrl |= MAL_TX_CTRL_READY;

	__asm__ volatile ("eieio");

1083 1084
	out_be32((void *)EMAC_TXM0 + hw_p->hw_addr,
		 in_be32((void *)EMAC_TXM0 + hw_p->hw_addr) | EMAC_TXM0_GNP0);
1085
#ifdef INFO_4XX_ENET
W
wdenk 已提交
1086 1087 1088 1089 1090 1091 1092 1093
	hw_p->stats.pkts_tx++;
#endif

	/*-----------------------------------------------------------------------+
	 * poll unitl the packet is sent and then make sure it is OK
	 *-----------------------------------------------------------------------*/
	time_start = get_timer (0);
	while (1) {
1094
		temp_txm0 = in_be32((void *)EMAC_TXM0 + hw_p->hw_addr);
W
wdenk 已提交
1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110
		/* loop until either TINT turns on or 3 seconds elapse */
		if ((temp_txm0 & EMAC_TXM0_GNP0) != 0) {
			/* transmit is done, so now check for errors
			 * If there is an error, an interrupt should
			 * happen when we return
			 */
			time_now = get_timer (0);
			if ((time_now - time_start) > 3000) {
				return (-1);
			}
		} else {
			return (len);
		}
	}
}

1111

S
Stefan Roese 已提交
1112
#if defined (CONFIG_440) || defined(CONFIG_405EX)
W
wdenk 已提交
1113

1114
#if defined(CONFIG_440SP) || defined(CONFIG_440SPE)
1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125
/*
 * Hack: On 440SP all enet irq sources are located on UIC1
 * Needs some cleanup. --sr
 */
#define UIC0MSR		uic1msr
#define UIC0SR		uic1sr
#else
#define UIC0MSR		uic0msr
#define UIC0SR		uic0sr
#endif

S
Stefan Roese 已提交
1126 1127
#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
    defined(CONFIG_405EX)
1128 1129 1130 1131 1132 1133 1134
#define UICMSR_ETHX	uic0msr
#define UICSR_ETHX	uic0sr
#else
#define UICMSR_ETHX	uic1msr
#define UICSR_ETHX	uic1sr
#endif

W
wdenk 已提交
1135 1136 1137 1138 1139 1140 1141 1142
int enetInt (struct eth_device *dev)
{
	int serviced;
	int rc = -1;		/* default to not us */
	unsigned long mal_isr;
	unsigned long emac_isr = 0;
	unsigned long mal_rx_eob;
	unsigned long my_uic0msr, my_uic1msr;
1143
	unsigned long my_uicmsr_ethx;
W
wdenk 已提交
1144

1145
#if defined(CONFIG_440GX)
W
wdenk 已提交
1146 1147
	unsigned long my_uic2msr;
#endif
1148
	EMAC_4XX_HW_PST hw_p;
W
wdenk 已提交
1149 1150 1151 1152 1153

	/*
	 * Because the mal is generic, we need to get the current
	 * eth device
	 */
1154 1155 1156 1157 1158
#if defined(CONFIG_NET_MULTI)
	dev = eth_get_dev();
#else
	dev = emac0_dev;
#endif
W
wdenk 已提交
1159 1160 1161 1162 1163 1164 1165

	hw_p = dev->priv;

	/* enter loop that stays in interrupt code until nothing to service */
	do {
		serviced = 0;

1166
		my_uic0msr = mfdcr (UIC0MSR);
W
wdenk 已提交
1167
		my_uic1msr = mfdcr (uic1msr);
1168
#if defined(CONFIG_440GX)
W
wdenk 已提交
1169 1170
		my_uic2msr = mfdcr (uic2msr);
#endif
1171 1172
		my_uicmsr_ethx = mfdcr (UICMSR_ETHX);

W
wdenk 已提交
1173
		if (!(my_uic0msr & (UIC_MRE | UIC_MTE))
1174 1175
		    && !(my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))
		    && !(my_uicmsr_ethx & (UIC_ETH0 | UIC_ETH1))) {
W
wdenk 已提交
1176 1177 1178
			/* not for us */
			return (rc);
		}
1179
#if defined (CONFIG_440GX)
W
wdenk 已提交
1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193
		if (!(my_uic0msr & (UIC_MRE | UIC_MTE))
		    && !(my_uic2msr & (UIC_ETH2 | UIC_ETH3))) {
			/* not for us */
			return (rc);
		}
#endif
		/* get and clear controller status interrupts */
		/* look at Mal and EMAC interrupts */
		if ((my_uic0msr & (UIC_MRE | UIC_MTE))
		    || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
			/* we have a MAL interrupt */
			mal_isr = mfdcr (malesr);
			/* look for mal error */
			if (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE)) {
1194
				mal_err (dev, mal_isr, my_uic1msr, MAL_UIC_DEF, MAL_UIC_ERR);
W
wdenk 已提交
1195 1196 1197 1198 1199 1200 1201
				serviced = 1;
				rc = 0;
			}
		}

		/* port by port dispatch of emac interrupts */
		if (hw_p->devnum == 0) {
1202
			if (UIC_ETH0 & my_uicmsr_ethx) {	/* look for EMAC errors */
1203
				emac_isr = in_be32((void *)EMAC_ISR + hw_p->hw_addr);
W
wdenk 已提交
1204 1205 1206 1207 1208 1209 1210 1211
				if ((hw_p->emac_ier & emac_isr) != 0) {
					emac_err (dev, emac_isr);
					serviced = 1;
					rc = 0;
				}
			}
			if ((hw_p->emac_ier & emac_isr)
			    || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
1212
				mtdcr (UIC0SR, UIC_MRE | UIC_MTE);	/* Clear */
1213 1214
				mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE);	/* Clear */
				mtdcr (UICSR_ETHX, UIC_ETH0); /* Clear */
W
wdenk 已提交
1215 1216 1217 1218
				return (rc);	/* we had errors so get out */
			}
		}

1219
#if !defined(CONFIG_440SP)
W
wdenk 已提交
1220
		if (hw_p->devnum == 1) {
1221
			if (UIC_ETH1 & my_uicmsr_ethx) {	/* look for EMAC errors */
1222
				emac_isr = in_be32((void *)EMAC_ISR + hw_p->hw_addr);
W
wdenk 已提交
1223 1224 1225 1226 1227 1228 1229 1230
				if ((hw_p->emac_ier & emac_isr) != 0) {
					emac_err (dev, emac_isr);
					serviced = 1;
					rc = 0;
				}
			}
			if ((hw_p->emac_ier & emac_isr)
			    || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
1231
				mtdcr (UIC0SR, UIC_MRE | UIC_MTE);	/* Clear */
1232 1233
				mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
				mtdcr (UICSR_ETHX, UIC_ETH1); /* Clear */
W
wdenk 已提交
1234 1235 1236
				return (rc);	/* we had errors so get out */
			}
		}
1237
#if defined (CONFIG_440GX)
W
wdenk 已提交
1238 1239
		if (hw_p->devnum == 2) {
			if (UIC_ETH2 & my_uic2msr) {	/* look for EMAC errors */
1240
				emac_isr = in_be32((void *)EMAC_ISR + hw_p->hw_addr);
W
wdenk 已提交
1241 1242 1243 1244 1245 1246 1247 1248
				if ((hw_p->emac_ier & emac_isr) != 0) {
					emac_err (dev, emac_isr);
					serviced = 1;
					rc = 0;
				}
			}
			if ((hw_p->emac_ier & emac_isr)
			    || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
1249
				mtdcr (UIC0SR, UIC_MRE | UIC_MTE);	/* Clear */
W
wdenk 已提交
1250 1251 1252 1253 1254 1255 1256 1257
				mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE);	/* Clear */
				mtdcr (uic2sr, UIC_ETH2);
				return (rc);	/* we had errors so get out */
			}
		}

		if (hw_p->devnum == 3) {
			if (UIC_ETH3 & my_uic2msr) {	/* look for EMAC errors */
1258
				emac_isr = in_be32((void *)EMAC_ISR + hw_p->hw_addr);
W
wdenk 已提交
1259 1260 1261 1262 1263 1264 1265 1266
				if ((hw_p->emac_ier & emac_isr) != 0) {
					emac_err (dev, emac_isr);
					serviced = 1;
					rc = 0;
				}
			}
			if ((hw_p->emac_ier & emac_isr)
			    || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
1267
				mtdcr (UIC0SR, UIC_MRE | UIC_MTE);	/* Clear */
W
wdenk 已提交
1268 1269 1270 1271 1272
				mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE);	/* Clear */
				mtdcr (uic2sr, UIC_ETH3);
				return (rc);	/* we had errors so get out */
			}
		}
1273
#endif /* CONFIG_440GX */
1274 1275
#endif /* !CONFIG_440SP */

W
wdenk 已提交
1276 1277 1278 1279
		/* handle MAX TX EOB interrupt from a tx */
		if (my_uic0msr & UIC_MTE) {
			mal_rx_eob = mfdcr (maltxeobisr);
			mtdcr (maltxeobisr, mal_rx_eob);
1280
			mtdcr (UIC0SR, UIC_MTE);
W
wdenk 已提交
1281 1282
		}
		/* handle MAL RX EOB  interupt from a receive */
1283
		/* check for EOB on valid channels	      */
W
wdenk 已提交
1284 1285
		if (my_uic0msr & UIC_MRE) {
			mal_rx_eob = mfdcr (malrxeobisr);
1286
			if ((mal_rx_eob & (0x80000000 >> hw_p->devnum)) != 0) { /* call emac routine for channel x */
W
wdenk 已提交
1287 1288 1289 1290 1291 1292 1293 1294
				/* clear EOB
				   mtdcr(malrxeobisr, mal_rx_eob); */
				enet_rcv (dev, emac_isr);
				/* indicate that we serviced an interrupt */
				serviced = 1;
				rc = 0;
			}
		}
1295 1296

		mtdcr (UIC0SR, UIC_MRE);	/* Clear */
W
wdenk 已提交
1297 1298 1299
		mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE);	/* Clear */
		switch (hw_p->devnum) {
		case 0:
1300
			mtdcr (UICSR_ETHX, UIC_ETH0);
W
wdenk 已提交
1301 1302
			break;
		case 1:
1303
			mtdcr (UICSR_ETHX, UIC_ETH1);
W
wdenk 已提交
1304
			break;
1305
#if defined (CONFIG_440GX)
W
wdenk 已提交
1306 1307 1308 1309 1310 1311
		case 2:
			mtdcr (uic2sr, UIC_ETH2);
			break;
		case 3:
			mtdcr (uic2sr, UIC_ETH3);
			break;
1312
#endif /* CONFIG_440GX */
W
wdenk 已提交
1313 1314 1315 1316 1317 1318 1319 1320
		default:
			break;
		}
	} while (serviced);

	return (rc);
}

1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369
#else /* CONFIG_440 */

int enetInt (struct eth_device *dev)
{
	int serviced;
	int rc = -1;		/* default to not us */
	unsigned long mal_isr;
	unsigned long emac_isr = 0;
	unsigned long mal_rx_eob;
	unsigned long my_uicmsr;

	EMAC_4XX_HW_PST hw_p;

	/*
	 * Because the mal is generic, we need to get the current
	 * eth device
	 */
#if defined(CONFIG_NET_MULTI)
	dev = eth_get_dev();
#else
	dev = emac0_dev;
#endif

	hw_p = dev->priv;

	/* enter loop that stays in interrupt code until nothing to service */
	do {
		serviced = 0;

		my_uicmsr = mfdcr (uicmsr);

		if ((my_uicmsr & (MAL_UIC_DEF | EMAC_UIC_DEF)) == 0) {	/* not for us */
			return (rc);
		}
		/* get and clear controller status interrupts */
		/* look at Mal and EMAC interrupts */
		if ((MAL_UIC_DEF & my_uicmsr) != 0) {	/* we have a MAL interrupt */
			mal_isr = mfdcr (malesr);
			/* look for mal error */
			if ((my_uicmsr & MAL_UIC_ERR) != 0) {
				mal_err (dev, mal_isr, my_uicmsr, MAL_UIC_DEF, MAL_UIC_ERR);
				serviced = 1;
				rc = 0;
			}
		}

		/* port by port dispatch of emac interrupts */

		if ((SEL_UIC_DEF(hw_p->devnum) & my_uicmsr) != 0) {	/* look for EMAC errors */
1370
			emac_isr = in_be32((void *)EMAC_ISR + hw_p->hw_addr);
1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392
			if ((hw_p->emac_ier & emac_isr) != 0) {
				emac_err (dev, emac_isr);
				serviced = 1;
				rc = 0;
			}
		}
		if (((hw_p->emac_ier & emac_isr) != 0) || ((MAL_UIC_ERR & my_uicmsr) != 0)) {
			mtdcr (uicsr, MAL_UIC_DEF | SEL_UIC_DEF(hw_p->devnum)); /* Clear */
			return (rc);		/* we had errors so get out */
		}

		/* handle MAX TX EOB interrupt from a tx */
		if (my_uicmsr & UIC_MAL_TXEOB) {
			mal_rx_eob = mfdcr (maltxeobisr);
			mtdcr (maltxeobisr, mal_rx_eob);
			mtdcr (uicsr, UIC_MAL_TXEOB);
		}
		/* handle MAL RX EOB  interupt from a receive */
		/* check for EOB on valid channels	      */
		if (my_uicmsr & UIC_MAL_RXEOB)
		{
			mal_rx_eob = mfdcr (malrxeobisr);
1393
			if ((mal_rx_eob & (0x80000000 >> hw_p->devnum)) != 0) { /* call emac routine for channel x */
1394 1395 1396 1397 1398 1399 1400 1401 1402
				/* clear EOB
				 mtdcr(malrxeobisr, mal_rx_eob); */
				enet_rcv (dev, emac_isr);
				/* indicate that we serviced an interrupt */
				serviced = 1;
				rc = 0;
			}
		}
		mtdcr (uicsr, MAL_UIC_DEF|EMAC_UIC_DEF|EMAC_UIC_DEF1);	/* Clear */
S
Stefan Roese 已提交
1403 1404 1405
#if defined(CONFIG_405EZ)
		mtsdr (sdricintstat, SDR_ICRX_STAT | SDR_ICTX0_STAT | SDR_ICTX1_STAT);
#endif	/* defined(CONFIG_405EZ) */
1406 1407 1408 1409 1410 1411 1412 1413
	}
	while (serviced);

	return (rc);
}

#endif /* CONFIG_440 */

W
wdenk 已提交
1414 1415 1416 1417 1418 1419 1420
/*-----------------------------------------------------------------------------+
 *  MAL Error Routine
 *-----------------------------------------------------------------------------*/
static void mal_err (struct eth_device *dev, unsigned long isr,
		     unsigned long uic, unsigned long maldef,
		     unsigned long mal_errr)
{
1421
	EMAC_4XX_HW_PST hw_p = dev->priv;
W
wdenk 已提交
1422 1423 1424 1425 1426 1427 1428

	mtdcr (malesr, isr);	/* clear interrupt */

	/* clear DE interrupt */
	mtdcr (maltxdeir, 0xC0000000);
	mtdcr (malrxdeir, 0x80000000);

1429
#ifdef INFO_4XX_ENET
1430
	printf ("\nMAL error occured.... ISR = %lx UIC = = %lx	MAL_DEF = %lx  MAL_ERR= %lx \n", isr, uic, maldef, mal_errr);
W
wdenk 已提交
1431 1432 1433 1434 1435 1436 1437 1438 1439 1440
#endif

	eth_init (hw_p->bis);	/* start again... */
}

/*-----------------------------------------------------------------------------+
 *  EMAC Error Routine
 *-----------------------------------------------------------------------------*/
static void emac_err (struct eth_device *dev, unsigned long isr)
{
1441
	EMAC_4XX_HW_PST hw_p = dev->priv;
W
wdenk 已提交
1442 1443

	printf ("EMAC%d error occured.... ISR = %lx\n", hw_p->devnum, isr);
1444
	out_be32((void *)EMAC_ISR + hw_p->hw_addr, isr);
W
wdenk 已提交
1445 1446 1447 1448 1449 1450 1451 1452 1453 1454
}

/*-----------------------------------------------------------------------------+
 *  enet_rcv() handles the ethernet receive data
 *-----------------------------------------------------------------------------*/
static void enet_rcv (struct eth_device *dev, unsigned long malisr)
{
	struct enet_frame *ef_ptr;
	unsigned long data_len;
	unsigned long rx_eob_isr;
1455
	EMAC_4XX_HW_PST hw_p = dev->priv;
W
wdenk 已提交
1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472

	int handled = 0;
	int i;
	int loop_count = 0;

	rx_eob_isr = mfdcr (malrxeobisr);
	if ((0x80000000 >> hw_p->devnum) & rx_eob_isr) {
		/* clear EOB */
		mtdcr (malrxeobisr, rx_eob_isr);

		/* EMAC RX done */
		while (1) {	/* do all */
			i = hw_p->rx_slot;

			if ((MAL_RX_CTRL_EMPTY & hw_p->rx[i].ctrl)
			    || (loop_count >= NUM_RX_BUFF))
				break;
1473

W
wdenk 已提交
1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490
			loop_count++;
			handled++;
			data_len = (unsigned long) hw_p->rx[i].data_len;	/* Get len */
			if (data_len) {
				if (data_len > ENET_MAX_MTU)	/* Check len */
					data_len = 0;
				else {
					if (EMAC_RX_ERRORS & hw_p->rx[i].ctrl) {	/* Check Errors */
						data_len = 0;
						hw_p->stats.rx_err_log[hw_p->
								       rx_err_index]
							= hw_p->rx[i].ctrl;
						hw_p->rx_err_index++;
						if (hw_p->rx_err_index ==
						    MAX_ERR_LOG)
							hw_p->rx_err_index =
								0;
1491
					}	/* emac_erros */
W
wdenk 已提交
1492
				}	/* data_len < max mtu */
1493
			}	/* if data_len */
W
wdenk 已提交
1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512
			if (!data_len) {	/* no data */
				hw_p->rx[i].ctrl |= MAL_RX_CTRL_EMPTY;	/* Free Recv Buffer */

				hw_p->stats.data_len_err++;	/* Error at Rx */
			}

			/* !data_len */
			/* AS.HARNOIS */
			/* Check if user has already eaten buffer */
			/* if not => ERROR */
			else if (hw_p->rx_ready[hw_p->rx_i_index] != -1) {
				if (hw_p->is_receiving)
					printf ("ERROR : Receive buffers are full!\n");
				break;
			} else {
				hw_p->stats.rx_frames++;
				hw_p->stats.rx += data_len;
				ef_ptr = (struct enet_frame *) hw_p->rx[i].
					data_ptr;
1513
#ifdef INFO_4XX_ENET
W
wdenk 已提交
1514 1515 1516 1517 1518 1519 1520 1521 1522 1523
				hw_p->stats.pkts_rx++;
#endif
				/* AS.HARNOIS
				 * use ring buffer
				 */
				hw_p->rx_ready[hw_p->rx_i_index] = i;
				hw_p->rx_i_index++;
				if (NUM_RX_BUFF == hw_p->rx_i_index)
					hw_p->rx_i_index = 0;

1524 1525 1526 1527
				hw_p->rx_slot++;
				if (NUM_RX_BUFF == hw_p->rx_slot)
					hw_p->rx_slot = 0;

W
wdenk 已提交
1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538
				/*  AS.HARNOIS
				 * free receive buffer only when
				 * buffer has been handled (eth_rx)
				 rx[i].ctrl |= MAL_RX_CTRL_EMPTY;
				 */
			}	/* if data_len */
		}		/* while */
	}			/* if EMACK_RXCHL */
}


1539
static int ppc_4xx_eth_rx (struct eth_device *dev)
W
wdenk 已提交
1540 1541 1542 1543
{
	int length;
	int user_index;
	unsigned long msr;
1544
	EMAC_4XX_HW_PST hw_p = dev->priv;
W
wdenk 已提交
1545

1546
	hw_p->is_receiving = 1; /* tell driver */
W
wdenk 已提交
1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564

	for (;;) {
		/* AS.HARNOIS
		 * use ring buffer and
		 * get index from rx buffer desciptor queue
		 */
		user_index = hw_p->rx_ready[hw_p->rx_u_index];
		if (user_index == -1) {
			length = -1;
			break;	/* nothing received - leave for() loop */
		}

		msr = mfmsr ();
		mtmsr (msr & ~(MSR_EE));

		length = hw_p->rx[user_index].data_len;

		/* Pass the packet up to the protocol layers. */
1565 1566
		/*	 NetReceive(NetRxPackets[rxIdx], length - 4); */
		/*	 NetReceive(NetRxPackets[i], length); */
1567 1568
		invalidate_dcache_range((u32)hw_p->rx[user_index].data_ptr,
					(u32)hw_p->rx[user_index].data_ptr +
1569
					length - 4);
W
wdenk 已提交
1570 1571 1572 1573 1574 1575 1576 1577 1578
		NetReceive (NetRxPackets[user_index], length - 4);
		/* Free Recv Buffer */
		hw_p->rx[user_index].ctrl |= MAL_RX_CTRL_EMPTY;
		/* Free rx buffer descriptor queue */
		hw_p->rx_ready[hw_p->rx_u_index] = -1;
		hw_p->rx_u_index++;
		if (NUM_RX_BUFF == hw_p->rx_u_index)
			hw_p->rx_u_index = 0;

1579
#ifdef INFO_4XX_ENET
W
wdenk 已提交
1580 1581 1582 1583 1584 1585
		hw_p->stats.pkts_handled++;
#endif

		mtmsr (msr);	/* Enable IRQ's */
	}

1586
	hw_p->is_receiving = 0; /* tell driver */
W
wdenk 已提交
1587 1588 1589 1590

	return length;
}

1591
int ppc_4xx_eth_initialize (bd_t * bis)
W
wdenk 已提交
1592 1593 1594 1595
{
	static int virgin = 0;
	struct eth_device *dev;
	int eth_num = 0;
1596
	EMAC_4XX_HW_PST hw = NULL;
1597 1598
	u8 ethaddr[4 + CONFIG_EMAC_NR_START][6];
	u32 hw_addr[4];
W
wdenk 已提交
1599

1600
#if defined(CONFIG_440GX)
1601 1602
	unsigned long pfc1;

W
wdenk 已提交
1603 1604 1605 1606
	mfsdr (sdr_pfc1, pfc1);
	pfc1 &= ~(0x01e00000);
	pfc1 |= 0x01200000;
	mtsdr (sdr_pfc1, pfc1);
1607
#endif
1608

1609 1610 1611
	/* first clear all mac-addresses */
	for (eth_num = 0; eth_num < LAST_EMAC_NUM; eth_num++)
		memcpy(ethaddr[eth_num], "\0\0\0\0\0\0", 6);
W
wdenk 已提交
1612

1613
	for (eth_num = 0; eth_num < LAST_EMAC_NUM; eth_num++) {
W
wdenk 已提交
1614
		switch (eth_num) {
W
wdenk 已提交
1615
		default:		/* fall through */
W
wdenk 已提交
1616
		case 0:
1617 1618 1619
			memcpy(ethaddr[eth_num + CONFIG_EMAC_NR_START],
			       bis->bi_enetaddr, 6);
			hw_addr[eth_num] = 0x0;
W
wdenk 已提交
1620
			break;
W
wdenk 已提交
1621
#ifdef CONFIG_HAS_ETH1
W
wdenk 已提交
1622
		case 1:
1623 1624 1625
			memcpy(ethaddr[eth_num + CONFIG_EMAC_NR_START],
			       bis->bi_enet1addr, 6);
			hw_addr[eth_num] = 0x100;
W
wdenk 已提交
1626
			break;
W
wdenk 已提交
1627 1628
#endif
#ifdef CONFIG_HAS_ETH2
W
wdenk 已提交
1629
		case 2:
1630 1631 1632
			memcpy(ethaddr[eth_num + CONFIG_EMAC_NR_START],
			       bis->bi_enet2addr, 6);
			hw_addr[eth_num] = 0x400;
W
wdenk 已提交
1633
			break;
W
wdenk 已提交
1634 1635
#endif
#ifdef CONFIG_HAS_ETH3
W
wdenk 已提交
1636
		case 3:
1637 1638 1639
			memcpy(ethaddr[eth_num + CONFIG_EMAC_NR_START],
			       bis->bi_enet3addr, 6);
			hw_addr[eth_num] = 0x600;
W
wdenk 已提交
1640
			break;
W
wdenk 已提交
1641
#endif
W
wdenk 已提交
1642
		}
1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657
	}

	/* set phy num and mode */
	bis->bi_phynum[0] = CONFIG_PHY_ADDR;
	bis->bi_phymode[0] = 0;

#if defined(CONFIG_PHY1_ADDR)
	bis->bi_phynum[1] = CONFIG_PHY1_ADDR;
	bis->bi_phymode[1] = 0;
#endif
#if defined(CONFIG_440GX)
	bis->bi_phynum[2] = CONFIG_PHY2_ADDR;
	bis->bi_phynum[3] = CONFIG_PHY3_ADDR;
	bis->bi_phymode[2] = 2;
	bis->bi_phymode[3] = 2;
S
Stefan Roese 已提交
1658
#endif
1659

S
Stefan Roese 已提交
1660 1661 1662
#if defined(CONFIG_440GX) || \
    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
    defined(CONFIG_405EX)
1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674
	ppc_4xx_eth_setup_bridge(0, bis);
#endif

	for (eth_num = 0; eth_num < LAST_EMAC_NUM; eth_num++) {
		/*
		 * See if we can actually bring up the interface,
		 * otherwise, skip it
		 */
		if (memcmp (ethaddr[eth_num], "\0\0\0\0\0\0", 6) == 0) {
			bis->bi_phymode[eth_num] = BI_PHYMODE_NONE;
			continue;
		}
W
wdenk 已提交
1675 1676 1677 1678

		/* Allocate device structure */
		dev = (struct eth_device *) malloc (sizeof (*dev));
		if (dev == NULL) {
1679
			printf ("ppc_4xx_eth_initialize: "
W
wdenk 已提交
1680
				"Cannot allocate eth_device %d\n", eth_num);
W
wdenk 已提交
1681 1682
			return (-1);
		}
W
wdenk 已提交
1683
		memset(dev, 0, sizeof(*dev));
W
wdenk 已提交
1684 1685

		/* Allocate our private use data */
1686
		hw = (EMAC_4XX_HW_PST) malloc (sizeof (*hw));
W
wdenk 已提交
1687
		if (hw == NULL) {
1688
			printf ("ppc_4xx_eth_initialize: "
W
wdenk 已提交
1689
				"Cannot allocate private hw data for eth_device %d",
W
wdenk 已提交
1690 1691 1692 1693
				eth_num);
			free (dev);
			return (-1);
		}
W
wdenk 已提交
1694
		memset(hw, 0, sizeof(*hw));
W
wdenk 已提交
1695

1696 1697
		hw->hw_addr = hw_addr[eth_num];
		memcpy (dev->enetaddr, ethaddr[eth_num], 6);
W
wdenk 已提交
1698
		hw->devnum = eth_num;
1699
		hw->print_speed = 1;
W
wdenk 已提交
1700

1701
		sprintf (dev->name, "ppc_4xx_eth%d", eth_num - CONFIG_EMAC_NR_START);
W
wdenk 已提交
1702
		dev->priv = (void *) hw;
1703 1704 1705 1706
		dev->init = ppc_4xx_eth_init;
		dev->halt = ppc_4xx_eth_halt;
		dev->send = ppc_4xx_eth_send;
		dev->recv = ppc_4xx_eth_rx;
W
wdenk 已提交
1707 1708 1709

		if (0 == virgin) {
			/* set the MAL IER ??? names may change with new spec ??? */
S
Stefan Roese 已提交
1710 1711 1712
#if defined(CONFIG_440SPE) || \
    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
    defined(CONFIG_405EX)
1713 1714 1715 1716
			mal_ier =
				MAL_IER_PT | MAL_IER_PRE | MAL_IER_PWE |
				MAL_IER_DE | MAL_IER_OTE | MAL_IER_OE | MAL_IER_PE ;
#else
W
wdenk 已提交
1717 1718 1719
			mal_ier =
				MAL_IER_DE | MAL_IER_NE | MAL_IER_TE |
				MAL_IER_OPBE | MAL_IER_PLBE;
1720
#endif
W
wdenk 已提交
1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744
			mtdcr (malesr, 0xffffffff);	/* clear pending interrupts */
			mtdcr (maltxdeir, 0xffffffff);	/* clear pending interrupts */
			mtdcr (malrxdeir, 0xffffffff);	/* clear pending interrupts */
			mtdcr (malier, mal_ier);

			/* install MAL interrupt handler */
			irq_install_handler (VECNUM_MS,
					     (interrupt_handler_t *) enetInt,
					     dev);
			irq_install_handler (VECNUM_MTE,
					     (interrupt_handler_t *) enetInt,
					     dev);
			irq_install_handler (VECNUM_MRE,
					     (interrupt_handler_t *) enetInt,
					     dev);
			irq_install_handler (VECNUM_TXDE,
					     (interrupt_handler_t *) enetInt,
					     dev);
			irq_install_handler (VECNUM_RXDE,
					     (interrupt_handler_t *) enetInt,
					     dev);
			virgin = 1;
		}

1745
#if defined(CONFIG_NET_MULTI)
W
wdenk 已提交
1746
		eth_register (dev);
1747 1748 1749
#else
		emac0_dev = dev;
#endif
1750 1751

#if defined(CONFIG_NET_MULTI)
1752
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
M
Marian Balakowicz 已提交
1753
		miiphy_register (dev->name,
1754
				 emac4xx_miiphy_read, emac4xx_miiphy_write);
M
Marian Balakowicz 已提交
1755
#endif
1756
#endif
W
wdenk 已提交
1757
	}			/* end for each supported device */
1758 1759

	return 0;
W
wdenk 已提交
1760
}
1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773

#if !defined(CONFIG_NET_MULTI)
void eth_halt (void) {
	if (emac0_dev) {
		ppc_4xx_eth_halt(emac0_dev);
		free(emac0_dev);
		emac0_dev = NULL;
	}
}

int eth_init (bd_t *bis)
{
	ppc_4xx_eth_initialize(bis);
1774 1775 1776 1777 1778 1779
	if (emac0_dev) {
		return ppc_4xx_eth_init(emac0_dev, bis);
	} else {
		printf("ERROR: ethaddr not set!\n");
		return -1;
	}
1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790
}

int eth_send(volatile void *packet, int length)
{
	return (ppc_4xx_eth_send(emac0_dev, packet, length));
}

int eth_rx(void)
{
	return (ppc_4xx_eth_rx(emac0_dev));
}
M
Marian Balakowicz 已提交
1791 1792 1793

int emac4xx_miiphy_initialize (bd_t * bis)
{
1794
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
M
Marian Balakowicz 已提交
1795
	miiphy_register ("ppc_4xx_eth0",
1796
			 emac4xx_miiphy_read, emac4xx_miiphy_write);
M
Marian Balakowicz 已提交
1797 1798 1799 1800
#endif

	return 0;
}
1801 1802
#endif /* !defined(CONFIG_NET_MULTI) */

1803
#endif