blob: 753b2be0c511ba78bc36632961c781d90de90d74 [file] [log] [blame]
wdenkba56f622004-02-06 23:19:44 +00001/*-----------------------------------------------------------------------------+
2 *
Wolfgang Denk265817c2005-09-25 00:53:22 +02003 * This source code has been made available to you by IBM on an AS-IS
4 * basis. Anyone receiving this source is licensed under IBM
5 * copyrights to use it in any way he or she deems fit, including
6 * copying it, modifying it, compiling it, and redistributing it either
7 * with or without modifications. No license under IBM patents or
8 * patent applications is to be implied by the copyright license.
wdenkba56f622004-02-06 23:19:44 +00009 *
Wolfgang Denk265817c2005-09-25 00:53:22 +020010 * Any user of this software should understand that IBM cannot provide
11 * technical support for this software and will not be responsible for
12 * any consequences resulting from the use of this software.
wdenkba56f622004-02-06 23:19:44 +000013 *
Wolfgang Denk265817c2005-09-25 00:53:22 +020014 * Any person who transfers this source code or any derivative work
15 * must include the IBM copyright notice, this paragraph, and the
16 * preceding two paragraphs in the transferred software.
wdenkba56f622004-02-06 23:19:44 +000017 *
Wolfgang Denk265817c2005-09-25 00:53:22 +020018 * COPYRIGHT I B M CORPORATION 1995
19 * LICENSED MATERIAL - PROGRAM PROPERTY OF I B M
wdenkba56f622004-02-06 23:19:44 +000020 *-----------------------------------------------------------------------------*/
21/*-----------------------------------------------------------------------------+
22 *
Wolfgang Denk265817c2005-09-25 00:53:22 +020023 * File Name: enetemac.c
wdenkba56f622004-02-06 23:19:44 +000024 *
Wolfgang Denk265817c2005-09-25 00:53:22 +020025 * Function: Device driver for the ethernet EMAC3 macro on the 405GP.
wdenkba56f622004-02-06 23:19:44 +000026 *
Wolfgang Denk265817c2005-09-25 00:53:22 +020027 * Author: Mark Wisner
wdenkba56f622004-02-06 23:19:44 +000028 *
29 * Change Activity-
30 *
Wolfgang Denk265817c2005-09-25 00:53:22 +020031 * Date Description of Change BY
32 * --------- --------------------- ---
33 * 05-May-99 Created MKW
34 * 27-Jun-99 Clean up JWB
35 * 16-Jul-99 Added MAL error recovery and better IP packet handling MKW
36 * 29-Jul-99 Added Full duplex support MKW
37 * 06-Aug-99 Changed names for Mal CR reg MKW
38 * 23-Aug-99 Turned off SYE when running at 10Mbs MKW
39 * 24-Aug-99 Marked descriptor empty after call_xlc MKW
40 * 07-Sep-99 Set MAL RX buffer size reg to ENET_MAX_MTU_ALIGNED / 16 MCG
41 * to avoid chaining maximum sized packets. Push starting
42 * RX descriptor address up to the next cache line boundary.
43 * 16-Jan-00 Added support for booting with IP of 0x0 MKW
44 * 15-Mar-00 Updated enetInit() to enable broadcast addresses in the
45 * EMAC_RXM register. JWB
46 * 12-Mar-01 anne-sophie.harnois@nextream.fr
47 * - Variables are compatible with those already defined in
48 * include/net.h
49 * - Receive buffer descriptor ring is used to send buffers
50 * to the user
51 * - Info print about send/received/handled packet number if
52 * INFO_405_ENET is set
53 * 17-Apr-01 stefan.roese@esd-electronics.com
54 * - MAL reset in "eth_halt" included
55 * - Enet speed and duplex output now in one line
56 * 08-May-01 stefan.roese@esd-electronics.com
57 * - MAL error handling added (eth_init called again)
58 * 13-Nov-01 stefan.roese@esd-electronics.com
59 * - Set IST bit in EMAC_M1 reg upon 100MBit or full duplex
60 * 04-Jan-02 stefan.roese@esd-electronics.com
61 * - Wait for PHY auto negotiation to complete added
62 * 06-Feb-02 stefan.roese@esd-electronics.com
63 * - Bug fixed in waiting for auto negotiation to complete
64 * 26-Feb-02 stefan.roese@esd-electronics.com
65 * - rx and tx buffer descriptors now allocated (no fixed address
66 * used anymore)
67 * 17-Jun-02 stefan.roese@esd-electronics.com
68 * - MAL error debug printf 'M' removed (rx de interrupt may
69 * occur upon many incoming packets with only 4 rx buffers).
wdenkba56f622004-02-06 23:19:44 +000070 *-----------------------------------------------------------------------------*
Wolfgang Denk265817c2005-09-25 00:53:22 +020071 * 17-Nov-03 travis.sawyer@sandburst.com
72 * - ported from 405gp_enet.c to utilized upto 4 EMAC ports
73 * in the 440GX. This port should work with the 440GP
74 * (2 EMACs) also
75 * 15-Aug-05 sr@denx.de
76 * - merged 405gp_enet.c and 440gx_enet.c to generic 4xx_enet.c
77 now handling all 4xx cpu's.
wdenkba56f622004-02-06 23:19:44 +000078 *-----------------------------------------------------------------------------*/
79
80#include <config.h>
wdenkba56f622004-02-06 23:19:44 +000081#include <common.h>
82#include <net.h>
83#include <asm/processor.h>
wdenkba56f622004-02-06 23:19:44 +000084#include <commproc.h>
Stefan Roesed6c61aa2005-08-16 18:18:00 +020085#include <ppc4xx.h>
86#include <ppc4xx_enet.h>
wdenkba56f622004-02-06 23:19:44 +000087#include <405_mal.h>
88#include <miiphy.h>
89#include <malloc.h>
90#include "vecnum.h"
91
Stefan Roesed6c61aa2005-08-16 18:18:00 +020092/*
Wolfgang Denk0c8721a2005-09-23 11:05:55 +020093 * Only compile for platform with AMCC EMAC ethernet controller and
Stefan Roesed6c61aa2005-08-16 18:18:00 +020094 * network support enabled.
95 * Remark: CONFIG_405 describes Xilinx PPC405 FPGA without EMAC controller!
96 */
97#if (CONFIG_COMMANDS & CFG_CMD_NET) && !defined(CONFIG_405) && !defined(CONFIG_IOP480)
98
99#if !(defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII))
100#error "CONFIG_MII has to be defined!"
101#endif
wdenkba56f622004-02-06 23:19:44 +0000102
Stefan Roese1e25f952005-10-20 16:34:28 +0200103#if defined(CONFIG_NETCONSOLE) && !defined(CONFIG_NET_MULTI)
104#error "CONFIG_NET_MULTI has to be defined for NetConsole"
105#endif
106
Wolfgang Denk265817c2005-09-25 00:53:22 +0200107#define EMAC_RESET_TIMEOUT 1000 /* 1000 ms reset timeout */
wdenkba56f622004-02-06 23:19:44 +0000108#define PHY_AUTONEGOTIATE_TIMEOUT 4000 /* 4000 ms autonegotiate timeout */
109
wdenkba56f622004-02-06 23:19:44 +0000110/* Ethernet Transmit and Receive Buffers */
111/* AS.HARNOIS
112 * In the same way ENET_MAX_MTU and ENET_MAX_MTU_ALIGNED are set from
113 * PKTSIZE and PKTSIZE_ALIGN (include/net.h)
114 */
Wolfgang Denk265817c2005-09-25 00:53:22 +0200115#define ENET_MAX_MTU PKTSIZE
wdenkba56f622004-02-06 23:19:44 +0000116#define ENET_MAX_MTU_ALIGNED PKTSIZE_ALIGN
117
wdenkba56f622004-02-06 23:19:44 +0000118/*-----------------------------------------------------------------------------+
119 * Defines for MAL/EMAC interrupt conditions as reported in the UIC (Universal
120 * Interrupt Controller).
121 *-----------------------------------------------------------------------------*/
122#define MAL_UIC_ERR ( UIC_MAL_SERR | UIC_MAL_TXDE | UIC_MAL_RXDE)
123#define MAL_UIC_DEF (UIC_MAL_RXEOB | MAL_UIC_ERR)
124#define EMAC_UIC_DEF UIC_ENET
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200125#define EMAC_UIC_DEF1 UIC_ENET1
126#define SEL_UIC_DEF(p) (p ? UIC_ENET1 : UIC_ENET )
wdenkba56f622004-02-06 23:19:44 +0000127
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200128#undef INFO_4XX_ENET
wdenkba56f622004-02-06 23:19:44 +0000129
Wolfgang Denk265817c2005-09-25 00:53:22 +0200130#define BI_PHYMODE_NONE 0
131#define BI_PHYMODE_ZMII 1
wdenk3c74e322004-02-22 23:46:08 +0000132#define BI_PHYMODE_RGMII 2
133
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200134
wdenkba56f622004-02-06 23:19:44 +0000135/*-----------------------------------------------------------------------------+
136 * Global variables. TX and RX descriptors and buffers.
137 *-----------------------------------------------------------------------------*/
138/* IER globals */
139static uint32_t mal_ier;
140
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200141#if !defined(CONFIG_NET_MULTI)
Stefan Roese4f92ac32005-10-10 17:43:58 +0200142struct eth_device *emac0_dev = NULL;
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200143#endif
144
Stefan Roese1e25f952005-10-20 16:34:28 +0200145/*
146 * Get count of EMAC devices (doesn't have to be the max. possible number
147 * supported by the cpu)
148 */
149#if defined(CONFIG_HAS_ETH3)
150#define LAST_EMAC_NUM 4
151#elif defined(CONFIG_HAS_ETH2)
152#define LAST_EMAC_NUM 3
153#elif defined(CONFIG_HAS_ETH1)
154#define LAST_EMAC_NUM 2
155#else
156#define LAST_EMAC_NUM 1
157#endif
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200158
wdenkba56f622004-02-06 23:19:44 +0000159/*-----------------------------------------------------------------------------+
160 * Prototypes and externals.
161 *-----------------------------------------------------------------------------*/
162static void enet_rcv (struct eth_device *dev, unsigned long malisr);
163
164int enetInt (struct eth_device *dev);
165static void mal_err (struct eth_device *dev, unsigned long isr,
166 unsigned long uic, unsigned long maldef,
167 unsigned long mal_errr);
168static void emac_err (struct eth_device *dev, unsigned long isr);
169
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200170
wdenkba56f622004-02-06 23:19:44 +0000171/*-----------------------------------------------------------------------------+
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200172| ppc_4xx_eth_halt
wdenkba56f622004-02-06 23:19:44 +0000173| Disable MAL channel, and EMACn
wdenkba56f622004-02-06 23:19:44 +0000174+-----------------------------------------------------------------------------*/
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200175static void ppc_4xx_eth_halt (struct eth_device *dev)
wdenkba56f622004-02-06 23:19:44 +0000176{
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200177 EMAC_4XX_HW_PST hw_p = dev->priv;
wdenkba56f622004-02-06 23:19:44 +0000178 uint32_t failsafe = 10000;
179
180 out32 (EMAC_IER + hw_p->hw_addr, 0x00000000); /* disable emac interrupts */
181
182 /* 1st reset MAL channel */
183 /* Note: writing a 0 to a channel has no effect */
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200184#if defined(CONFIG_405EP) || defined(CONFIG_440EP) || defined(CONFIG_440GR)
185 mtdcr (maltxcarr, (MAL_CR_MMSR >> (hw_p->devnum * 2)));
186#else
wdenkba56f622004-02-06 23:19:44 +0000187 mtdcr (maltxcarr, (MAL_CR_MMSR >> hw_p->devnum));
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200188#endif
wdenkba56f622004-02-06 23:19:44 +0000189 mtdcr (malrxcarr, (MAL_CR_MMSR >> hw_p->devnum));
190
191 /* wait for reset */
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200192 while (mfdcr (malrxcasr) & (MAL_CR_MMSR >> hw_p->devnum)) {
wdenkba56f622004-02-06 23:19:44 +0000193 udelay (1000); /* Delay 1 MS so as not to hammer the register */
194 failsafe--;
195 if (failsafe == 0)
196 break;
wdenkba56f622004-02-06 23:19:44 +0000197 }
198
199 /* EMAC RESET */
200 out32 (EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST);
201
Stefan Roesea93316c2005-10-18 19:17:12 +0200202#ifndef CONFIG_NETCONSOLE
Stefan Roesec157d8e2005-08-01 16:41:48 +0200203 hw_p->print_speed = 1; /* print speed message again next time */
Stefan Roesea93316c2005-10-18 19:17:12 +0200204#endif
Stefan Roesec157d8e2005-08-01 16:41:48 +0200205
wdenkba56f622004-02-06 23:19:44 +0000206 return;
207}
208
209extern int phy_setup_aneg (unsigned char addr);
210extern int miiphy_reset (unsigned char addr);
211
Stefan Roese846b0dd2005-08-08 12:42:22 +0200212#if defined (CONFIG_440GX)
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200213int ppc_4xx_eth_setup_bridge(int devnum, bd_t * bis)
wdenk855a4962004-03-14 18:23:55 +0000214{
215 unsigned long pfc1;
216 unsigned long zmiifer;
217 unsigned long rmiifer;
218
219 mfsdr(sdr_pfc1, pfc1);
220 pfc1 = SDR0_PFC1_EPS_DECODE(pfc1);
221
222 zmiifer = 0;
223 rmiifer = 0;
224
225 switch (pfc1) {
226 case 1:
227 zmiifer |= ZMII_FER_RMII << ZMII_FER_V(0);
228 zmiifer |= ZMII_FER_RMII << ZMII_FER_V(1);
229 zmiifer |= ZMII_FER_RMII << ZMII_FER_V(2);
230 zmiifer |= ZMII_FER_RMII << ZMII_FER_V(3);
231 bis->bi_phymode[0] = BI_PHYMODE_ZMII;
232 bis->bi_phymode[1] = BI_PHYMODE_ZMII;
233 bis->bi_phymode[2] = BI_PHYMODE_ZMII;
234 bis->bi_phymode[3] = BI_PHYMODE_ZMII;
235 break;
236 case 2:
237 zmiifer = ZMII_FER_SMII << ZMII_FER_V(0);
238 zmiifer = ZMII_FER_SMII << ZMII_FER_V(1);
239 zmiifer = ZMII_FER_SMII << ZMII_FER_V(2);
240 zmiifer = ZMII_FER_SMII << ZMII_FER_V(3);
241 bis->bi_phymode[0] = BI_PHYMODE_ZMII;
242 bis->bi_phymode[1] = BI_PHYMODE_ZMII;
243 bis->bi_phymode[2] = BI_PHYMODE_ZMII;
244 bis->bi_phymode[3] = BI_PHYMODE_ZMII;
245 break;
246 case 3:
247 zmiifer |= ZMII_FER_RMII << ZMII_FER_V(0);
248 rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(2);
249 bis->bi_phymode[0] = BI_PHYMODE_ZMII;
250 bis->bi_phymode[1] = BI_PHYMODE_NONE;
251 bis->bi_phymode[2] = BI_PHYMODE_RGMII;
252 bis->bi_phymode[3] = BI_PHYMODE_NONE;
253 break;
254 case 4:
255 zmiifer |= ZMII_FER_SMII << ZMII_FER_V(0);
256 zmiifer |= ZMII_FER_SMII << ZMII_FER_V(1);
257 rmiifer |= RGMII_FER_RGMII << RGMII_FER_V (2);
258 rmiifer |= RGMII_FER_RGMII << RGMII_FER_V (3);
259 bis->bi_phymode[0] = BI_PHYMODE_ZMII;
260 bis->bi_phymode[1] = BI_PHYMODE_ZMII;
261 bis->bi_phymode[2] = BI_PHYMODE_RGMII;
262 bis->bi_phymode[3] = BI_PHYMODE_RGMII;
263 break;
264 case 5:
265 zmiifer |= ZMII_FER_SMII << ZMII_FER_V (0);
266 zmiifer |= ZMII_FER_SMII << ZMII_FER_V (1);
267 zmiifer |= ZMII_FER_SMII << ZMII_FER_V (2);
268 rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(3);
269 bis->bi_phymode[0] = BI_PHYMODE_ZMII;
270 bis->bi_phymode[1] = BI_PHYMODE_ZMII;
271 bis->bi_phymode[2] = BI_PHYMODE_ZMII;
272 bis->bi_phymode[3] = BI_PHYMODE_RGMII;
273 break;
274 case 6:
275 zmiifer |= ZMII_FER_SMII << ZMII_FER_V (0);
276 zmiifer |= ZMII_FER_SMII << ZMII_FER_V (1);
277 rmiifer |= RGMII_FER_RGMII << RGMII_FER_V(2);
wdenk855a4962004-03-14 18:23:55 +0000278 bis->bi_phymode[0] = BI_PHYMODE_ZMII;
279 bis->bi_phymode[1] = BI_PHYMODE_ZMII;
280 bis->bi_phymode[2] = BI_PHYMODE_RGMII;
wdenk855a4962004-03-14 18:23:55 +0000281 break;
282 case 0:
283 default:
284 zmiifer = ZMII_FER_MII << ZMII_FER_V(devnum);
285 rmiifer = 0x0;
286 bis->bi_phymode[0] = BI_PHYMODE_ZMII;
287 bis->bi_phymode[1] = BI_PHYMODE_ZMII;
288 bis->bi_phymode[2] = BI_PHYMODE_ZMII;
289 bis->bi_phymode[3] = BI_PHYMODE_ZMII;
290 break;
291 }
292
293 /* Ensure we setup mdio for this devnum and ONLY this devnum */
294 zmiifer |= (ZMII_FER_MDI) << ZMII_FER_V(devnum);
295
296 out32 (ZMII_FER, zmiifer);
297 out32 (RGMII_FER, rmiifer);
298
299 return ((int)pfc1);
300
301}
302#endif
303
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200304static int ppc_4xx_eth_init (struct eth_device *dev, bd_t * bis)
wdenkba56f622004-02-06 23:19:44 +0000305{
Stefan Roeseb79316f2005-08-15 12:31:23 +0200306 int i, j;
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200307 unsigned long reg = 0;
wdenkba56f622004-02-06 23:19:44 +0000308 unsigned long msr;
309 unsigned long speed;
310 unsigned long duplex;
311 unsigned long failsafe;
312 unsigned mode_reg;
313 unsigned short devnum;
314 unsigned short reg_short;
Stefan Roese846b0dd2005-08-08 12:42:22 +0200315#if defined(CONFIG_440GX)
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200316 sys_info_t sysinfo;
wdenk855a4962004-03-14 18:23:55 +0000317 int ethgroup;
Stefan Roesec157d8e2005-08-01 16:41:48 +0200318#endif
wdenkba56f622004-02-06 23:19:44 +0000319
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200320 EMAC_4XX_HW_PST hw_p = dev->priv;
wdenkba56f622004-02-06 23:19:44 +0000321
322 /* before doing anything, figure out if we have a MAC address */
323 /* if not, bail */
Stefan Roese4f92ac32005-10-10 17:43:58 +0200324 if (memcmp (dev->enetaddr, "\0\0\0\0\0\0", 6) == 0) {
325 printf("ERROR: ethaddr not set!\n");
wdenkba56f622004-02-06 23:19:44 +0000326 return -1;
Stefan Roese4f92ac32005-10-10 17:43:58 +0200327 }
wdenkba56f622004-02-06 23:19:44 +0000328
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200329#if defined(CONFIG_440GX)
wdenkba56f622004-02-06 23:19:44 +0000330 /* Need to get the OPB frequency so we can access the PHY */
331 get_sys_info (&sysinfo);
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200332#endif
wdenkba56f622004-02-06 23:19:44 +0000333
wdenkba56f622004-02-06 23:19:44 +0000334 msr = mfmsr ();
335 mtmsr (msr & ~(MSR_EE)); /* disable interrupts */
336
337 devnum = hw_p->devnum;
338
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200339#ifdef INFO_4XX_ENET
wdenkba56f622004-02-06 23:19:44 +0000340 /* AS.HARNOIS
341 * We should have :
Wolfgang Denk265817c2005-09-25 00:53:22 +0200342 * hw_p->stats.pkts_handled <= hw_p->stats.pkts_rx <= hw_p->stats.pkts_handled+PKTBUFSRX
wdenkba56f622004-02-06 23:19:44 +0000343 * In the most cases hw_p->stats.pkts_handled = hw_p->stats.pkts_rx, but it
344 * is possible that new packets (without relationship with
345 * current transfer) have got the time to arrived before
346 * netloop calls eth_halt
347 */
348 printf ("About preceeding transfer (eth%d):\n"
349 "- Sent packet number %d\n"
350 "- Received packet number %d\n"
351 "- Handled packet number %d\n",
352 hw_p->devnum,
353 hw_p->stats.pkts_tx,
354 hw_p->stats.pkts_rx, hw_p->stats.pkts_handled);
355
356 hw_p->stats.pkts_tx = 0;
357 hw_p->stats.pkts_rx = 0;
358 hw_p->stats.pkts_handled = 0;
359#endif
360
Wolfgang Denk265817c2005-09-25 00:53:22 +0200361 hw_p->tx_err_index = 0; /* Transmit Error Index for tx_err_log */
362 hw_p->rx_err_index = 0; /* Receive Error Index for rx_err_log */
wdenkba56f622004-02-06 23:19:44 +0000363
364 hw_p->rx_slot = 0; /* MAL Receive Slot */
365 hw_p->rx_i_index = 0; /* Receive Interrupt Queue Index */
366 hw_p->rx_u_index = 0; /* Receive User Queue Index */
367
368 hw_p->tx_slot = 0; /* MAL Transmit Slot */
369 hw_p->tx_i_index = 0; /* Transmit Interrupt Queue Index */
370 hw_p->tx_u_index = 0; /* Transmit User Queue Index */
371
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200372#if defined(CONFIG_440)
wdenkba56f622004-02-06 23:19:44 +0000373 /* set RMII mode */
374 /* NOTE: 440GX spec states that mode is mutually exclusive */
375 /* NOTE: Therefore, disable all other EMACS, since we handle */
376 /* NOTE: only one emac at a time */
377 reg = 0;
378 out32 (ZMII_FER, 0);
379 udelay (100);
wdenkba56f622004-02-06 23:19:44 +0000380
Stefan Roese846b0dd2005-08-08 12:42:22 +0200381#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
Wolfgang Denk265817c2005-09-25 00:53:22 +0200382 out32 (ZMII_FER, (ZMII_FER_RMII | ZMII_FER_MDI) << ZMII_FER_V (devnum));
Stefan Roese846b0dd2005-08-08 12:42:22 +0200383#elif defined(CONFIG_440GX)
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200384 ethgroup = ppc_4xx_eth_setup_bridge(devnum, bis);
Stefan Roese4a3cd9e2005-09-07 16:21:12 +0200385#elif defined(CONFIG_440GP)
386 /* set RMII mode */
387 out32 (ZMII_FER, ZMII_RMII | ZMII_MDI0);
wdenk0e6d7982004-03-14 00:07:33 +0000388#else
389 if ((devnum == 0) || (devnum == 1)) {
390 out32 (ZMII_FER, (ZMII_FER_SMII | ZMII_FER_MDI) << ZMII_FER_V (devnum));
391 }
392 else { /* ((devnum == 2) || (devnum == 3)) */
393 out32 (ZMII_FER, ZMII_FER_MDI << ZMII_FER_V (devnum));
wdenkba56f622004-02-06 23:19:44 +0000394 out32 (RGMII_FER, ((RGMII_FER_RGMII << RGMII_FER_V (2)) |
395 (RGMII_FER_RGMII << RGMII_FER_V (3))));
wdenk0e6d7982004-03-14 00:07:33 +0000396 }
397#endif
Stefan Roesec57c7982005-08-11 17:56:56 +0200398
wdenk0e6d7982004-03-14 00:07:33 +0000399 out32 (ZMII_SSR, ZMII_SSR_SP << ZMII_SSR_V(devnum));
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200400#endif /* defined(CONFIG_440) */
401
wdenk0e6d7982004-03-14 00:07:33 +0000402 __asm__ volatile ("eieio");
403
404 /* reset emac so we have access to the phy */
405
406 out32 (EMAC_M0 + hw_p->hw_addr, EMAC_M0_SRST);
wdenkba56f622004-02-06 23:19:44 +0000407 __asm__ volatile ("eieio");
408
409 failsafe = 1000;
410 while ((in32 (EMAC_M0 + hw_p->hw_addr) & (EMAC_M0_SRST)) && failsafe) {
411 udelay (1000);
412 failsafe--;
413 }
414
Stefan Roese846b0dd2005-08-08 12:42:22 +0200415#if defined(CONFIG_440GX)
wdenkba56f622004-02-06 23:19:44 +0000416 /* Whack the M1 register */
417 mode_reg = 0x0;
418 mode_reg &= ~0x00000038;
419 if (sysinfo.freqOPB <= 50000000);
420 else if (sysinfo.freqOPB <= 66666667)
421 mode_reg |= EMAC_M1_OBCI_66;
422 else if (sysinfo.freqOPB <= 83333333)
423 mode_reg |= EMAC_M1_OBCI_83;
424 else if (sysinfo.freqOPB <= 100000000)
425 mode_reg |= EMAC_M1_OBCI_100;
426 else
427 mode_reg |= EMAC_M1_OBCI_GT100;
428
429 out32 (EMAC_M1 + hw_p->hw_addr, mode_reg);
Stefan Roese846b0dd2005-08-08 12:42:22 +0200430#endif /* defined(CONFIG_440GX) */
wdenkba56f622004-02-06 23:19:44 +0000431
432 /* wait for PHY to complete auto negotiation */
433 reg_short = 0;
434#ifndef CONFIG_CS8952_PHY
435 switch (devnum) {
436 case 0:
437 reg = CONFIG_PHY_ADDR;
438 break;
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200439#if defined (CONFIG_PHY1_ADDR)
wdenkba56f622004-02-06 23:19:44 +0000440 case 1:
441 reg = CONFIG_PHY1_ADDR;
442 break;
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200443#endif
Stefan Roese846b0dd2005-08-08 12:42:22 +0200444#if defined (CONFIG_440GX)
wdenkba56f622004-02-06 23:19:44 +0000445 case 2:
446 reg = CONFIG_PHY2_ADDR;
447 break;
448 case 3:
449 reg = CONFIG_PHY3_ADDR;
450 break;
451#endif
452 default:
453 reg = CONFIG_PHY_ADDR;
454 break;
455 }
456
wdenk3c74e322004-02-22 23:46:08 +0000457 bis->bi_phynum[devnum] = reg;
458
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200459#if defined(CONFIG_PHY_RESET)
wdenka06752e2004-09-29 22:43:59 +0000460 /*
461 * Reset the phy, only if its the first time through
462 * otherwise, just check the speeds & feeds
463 */
464 if (hw_p->first_init == 0) {
465 miiphy_reset (reg);
wdenkba56f622004-02-06 23:19:44 +0000466
Stefan Roese846b0dd2005-08-08 12:42:22 +0200467#if defined(CONFIG_440GX)
wdenk0e6d7982004-03-14 00:07:33 +0000468#if defined(CONFIG_CIS8201_PHY)
wdenkfc1cfcd2004-04-25 15:41:35 +0000469 /*
Stefan Roese17f50f222005-08-04 17:09:16 +0200470 * Cicada 8201 PHY needs to have an extended register whacked
471 * for RGMII mode.
wdenkfc1cfcd2004-04-25 15:41:35 +0000472 */
Stefan Roese17f50f222005-08-04 17:09:16 +0200473 if ( ((devnum == 2) || (devnum ==3)) && (4 == ethgroup) ) {
Stefan Roeseb79316f2005-08-15 12:31:23 +0200474#if defined(CONFIG_CIS8201_SHORT_ETCH)
475 miiphy_write (reg, 23, 0x1300);
476#else
477 miiphy_write (reg, 23, 0x1000);
478#endif
Stefan Roese17f50f222005-08-04 17:09:16 +0200479 /*
480 * Vitesse VSC8201/Cicada CIS8201 errata:
481 * Interoperability problem with Intel 82547EI phys
482 * This work around (provided by Vitesse) changes
483 * the default timer convergence from 8ms to 12ms
484 */
485 miiphy_write (reg, 0x1f, 0x2a30);
486 miiphy_write (reg, 0x08, 0x0200);
487 miiphy_write (reg, 0x1f, 0x52b5);
488 miiphy_write (reg, 0x02, 0x0004);
489 miiphy_write (reg, 0x01, 0x0671);
490 miiphy_write (reg, 0x00, 0x8fae);
491 miiphy_write (reg, 0x1f, 0x2a30);
492 miiphy_write (reg, 0x08, 0x0000);
493 miiphy_write (reg, 0x1f, 0x0000);
494 /* end Vitesse/Cicada errata */
495 }
wdenk0e6d7982004-03-14 00:07:33 +0000496#endif
wdenk855a4962004-03-14 18:23:55 +0000497#endif
wdenka06752e2004-09-29 22:43:59 +0000498 /* Start/Restart autonegotiation */
499 phy_setup_aneg (reg);
500 udelay (1000);
501 }
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200502#endif /* defined(CONFIG_PHY_RESET) */
wdenkba56f622004-02-06 23:19:44 +0000503
504 miiphy_read (reg, PHY_BMSR, &reg_short);
505
506 /*
wdenk0e6d7982004-03-14 00:07:33 +0000507 * Wait if PHY is capable of autonegotiation and autonegotiation is not complete
wdenkba56f622004-02-06 23:19:44 +0000508 */
509 if ((reg_short & PHY_BMSR_AUTN_ABLE)
510 && !(reg_short & PHY_BMSR_AUTN_COMP)) {
511 puts ("Waiting for PHY auto negotiation to complete");
512 i = 0;
513 while (!(reg_short & PHY_BMSR_AUTN_COMP)) {
514 /*
515 * Timeout reached ?
516 */
517 if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
518 puts (" TIMEOUT !\n");
519 break;
520 }
521
522 if ((i++ % 1000) == 0) {
523 putc ('.');
524 }
525 udelay (1000); /* 1 ms */
526 miiphy_read (reg, PHY_BMSR, &reg_short);
527
528 }
529 puts (" done\n");
530 udelay (500000); /* another 500 ms (results in faster booting) */
531 }
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200532#endif /* #ifndef CONFIG_CS8952_PHY */
533
wdenkba56f622004-02-06 23:19:44 +0000534 speed = miiphy_speed (reg);
535 duplex = miiphy_duplex (reg);
536
537 if (hw_p->print_speed) {
538 hw_p->print_speed = 0;
539 printf ("ENET Speed is %d Mbps - %s duplex connection\n",
540 (int) speed, (duplex == HALF) ? "HALF" : "FULL");
541 }
542
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200543#if defined(CONFIG_440)
Stefan Roese846b0dd2005-08-08 12:42:22 +0200544#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
Stefan Roesec157d8e2005-08-01 16:41:48 +0200545 mfsdr(sdr_mfr, reg);
546 if (speed == 100) {
547 reg = (reg & ~SDR0_MFR_ZMII_MODE_MASK) | SDR0_MFR_ZMII_MODE_RMII_100M;
548 } else {
549 reg = (reg & ~SDR0_MFR_ZMII_MODE_MASK) | SDR0_MFR_ZMII_MODE_RMII_10M;
550 }
551 mtsdr(sdr_mfr, reg);
552#endif
Stefan Roesec57c7982005-08-11 17:56:56 +0200553
wdenkba56f622004-02-06 23:19:44 +0000554 /* Set ZMII/RGMII speed according to the phy link speed */
555 reg = in32 (ZMII_SSR);
wdenk855a4962004-03-14 18:23:55 +0000556 if ( (speed == 100) || (speed == 1000) )
wdenkba56f622004-02-06 23:19:44 +0000557 out32 (ZMII_SSR, reg | (ZMII_SSR_SP << ZMII_SSR_V (devnum)));
558 else
Stefan Roesec57c7982005-08-11 17:56:56 +0200559 out32 (ZMII_SSR, reg & (~(ZMII_SSR_SP << ZMII_SSR_V (devnum))));
wdenkba56f622004-02-06 23:19:44 +0000560
561 if ((devnum == 2) || (devnum == 3)) {
562 if (speed == 1000)
563 reg = (RGMII_SSR_SP_1000MBPS << RGMII_SSR_V (devnum));
564 else if (speed == 100)
565 reg = (RGMII_SSR_SP_100MBPS << RGMII_SSR_V (devnum));
566 else
567 reg = (RGMII_SSR_SP_10MBPS << RGMII_SSR_V (devnum));
568
569 out32 (RGMII_SSR, reg);
570 }
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200571#endif /* defined(CONFIG_440) */
wdenkba56f622004-02-06 23:19:44 +0000572
573 /* set the Mal configuration reg */
Stefan Roese846b0dd2005-08-08 12:42:22 +0200574#if defined(CONFIG_440GX)
Stefan Roese17f50f222005-08-04 17:09:16 +0200575 mtdcr (malmcr, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA |
576 MAL_CR_PLBLT_DEFAULT | MAL_CR_EOPIE | 0x00330000);
577#else
578 mtdcr (malmcr, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA | MAL_CR_PLBLT_DEFAULT);
wdenkba56f622004-02-06 23:19:44 +0000579 /* Errata 1.12: MAL_1 -- Disable MAL bursting */
Stefan Roese17f50f222005-08-04 17:09:16 +0200580 if (get_pvr() == PVR_440GP_RB) {
581 mtdcr (malmcr, mfdcr(malmcr) & ~MAL_CR_PLBB);
582 }
583#endif
wdenkba56f622004-02-06 23:19:44 +0000584
585 /* Free "old" buffers */
586 if (hw_p->alloc_tx_buf)
587 free (hw_p->alloc_tx_buf);
588 if (hw_p->alloc_rx_buf)
589 free (hw_p->alloc_rx_buf);
590
591 /*
592 * Malloc MAL buffer desciptors, make sure they are
593 * aligned on cache line boundary size
594 * (401/403/IOP480 = 16, 405 = 32)
595 * and doesn't cross cache block boundaries.
596 */
597 hw_p->alloc_tx_buf =
598 (mal_desc_t *) malloc ((sizeof (mal_desc_t) * NUM_TX_BUFF) +
599 ((2 * CFG_CACHELINE_SIZE) - 2));
Stefan Roeseb79316f2005-08-15 12:31:23 +0200600 if (NULL == hw_p->alloc_tx_buf)
601 return -1;
wdenkba56f622004-02-06 23:19:44 +0000602 if (((int) hw_p->alloc_tx_buf & CACHELINE_MASK) != 0) {
603 hw_p->tx =
604 (mal_desc_t *) ((int) hw_p->alloc_tx_buf +
605 CFG_CACHELINE_SIZE -
606 ((int) hw_p->
607 alloc_tx_buf & CACHELINE_MASK));
608 } else {
609 hw_p->tx = hw_p->alloc_tx_buf;
610 }
611
612 hw_p->alloc_rx_buf =
613 (mal_desc_t *) malloc ((sizeof (mal_desc_t) * NUM_RX_BUFF) +
614 ((2 * CFG_CACHELINE_SIZE) - 2));
Stefan Roeseb79316f2005-08-15 12:31:23 +0200615 if (NULL == hw_p->alloc_rx_buf) {
616 free(hw_p->alloc_tx_buf);
617 hw_p->alloc_tx_buf = NULL;
618 return -1;
619 }
620
wdenkba56f622004-02-06 23:19:44 +0000621 if (((int) hw_p->alloc_rx_buf & CACHELINE_MASK) != 0) {
622 hw_p->rx =
623 (mal_desc_t *) ((int) hw_p->alloc_rx_buf +
624 CFG_CACHELINE_SIZE -
625 ((int) hw_p->
626 alloc_rx_buf & CACHELINE_MASK));
627 } else {
628 hw_p->rx = hw_p->alloc_rx_buf;
629 }
630
631 for (i = 0; i < NUM_TX_BUFF; i++) {
632 hw_p->tx[i].ctrl = 0;
633 hw_p->tx[i].data_len = 0;
Stefan Roeseb79316f2005-08-15 12:31:23 +0200634 if (hw_p->first_init == 0) {
wdenkba56f622004-02-06 23:19:44 +0000635 hw_p->txbuf_ptr =
636 (char *) malloc (ENET_MAX_MTU_ALIGNED);
Stefan Roeseb79316f2005-08-15 12:31:23 +0200637 if (NULL == hw_p->txbuf_ptr) {
638 free(hw_p->alloc_rx_buf);
639 free(hw_p->alloc_tx_buf);
640 hw_p->alloc_rx_buf = NULL;
641 hw_p->alloc_tx_buf = NULL;
642 for(j = 0; j < i; j++) {
643 free(hw_p->tx[i].data_ptr);
644 hw_p->tx[i].data_ptr = NULL;
645 }
646 }
647 }
wdenkba56f622004-02-06 23:19:44 +0000648 hw_p->tx[i].data_ptr = hw_p->txbuf_ptr;
649 if ((NUM_TX_BUFF - 1) == i)
650 hw_p->tx[i].ctrl |= MAL_TX_CTRL_WRAP;
651 hw_p->tx_run[i] = -1;
652#if 0
653 printf ("TX_BUFF %d @ 0x%08lx\n", i,
654 (ulong) hw_p->tx[i].data_ptr);
655#endif
656 }
657
658 for (i = 0; i < NUM_RX_BUFF; i++) {
659 hw_p->rx[i].ctrl = 0;
660 hw_p->rx[i].data_len = 0;
Wolfgang Denk265817c2005-09-25 00:53:22 +0200661 /* rx[i].data_ptr = (char *) &rx_buff[i]; */
wdenkba56f622004-02-06 23:19:44 +0000662 hw_p->rx[i].data_ptr = (char *) NetRxPackets[i];
663 if ((NUM_RX_BUFF - 1) == i)
664 hw_p->rx[i].ctrl |= MAL_RX_CTRL_WRAP;
665 hw_p->rx[i].ctrl |= MAL_RX_CTRL_EMPTY | MAL_RX_CTRL_INTR;
666 hw_p->rx_ready[i] = -1;
667#if 0
668 printf ("RX_BUFF %d @ 0x%08lx\n", i, (ulong) rx[i].data_ptr);
669#endif
670 }
671
672 reg = 0x00000000;
673
674 reg |= dev->enetaddr[0]; /* set high address */
675 reg = reg << 8;
676 reg |= dev->enetaddr[1];
677
678 out32 (EMAC_IAH + hw_p->hw_addr, reg);
679
680 reg = 0x00000000;
681 reg |= dev->enetaddr[2]; /* set low address */
682 reg = reg << 8;
683 reg |= dev->enetaddr[3];
684 reg = reg << 8;
685 reg |= dev->enetaddr[4];
686 reg = reg << 8;
687 reg |= dev->enetaddr[5];
688
689 out32 (EMAC_IAL + hw_p->hw_addr, reg);
690
691 switch (devnum) {
692 case 1:
693 /* setup MAL tx & rx channel pointers */
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200694#if defined (CONFIG_405EP) || defined (CONFIG_440EP) || defined (CONFIG_440GR)
Stefan Roesec157d8e2005-08-01 16:41:48 +0200695 mtdcr (maltxctp2r, hw_p->tx);
696#else
wdenkba56f622004-02-06 23:19:44 +0000697 mtdcr (maltxctp1r, hw_p->tx);
Stefan Roesec157d8e2005-08-01 16:41:48 +0200698#endif
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200699#if defined(CONFIG_440)
Stefan Roesec157d8e2005-08-01 16:41:48 +0200700 mtdcr (maltxbattr, 0x0);
wdenkba56f622004-02-06 23:19:44 +0000701 mtdcr (malrxbattr, 0x0);
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200702#endif
wdenkba56f622004-02-06 23:19:44 +0000703 mtdcr (malrxctp1r, hw_p->rx);
704 /* set RX buffer size */
705 mtdcr (malrcbs1, ENET_MAX_MTU_ALIGNED / 16);
706 break;
Stefan Roese846b0dd2005-08-08 12:42:22 +0200707#if defined (CONFIG_440GX)
wdenkba56f622004-02-06 23:19:44 +0000708 case 2:
709 /* setup MAL tx & rx channel pointers */
710 mtdcr (maltxbattr, 0x0);
wdenkba56f622004-02-06 23:19:44 +0000711 mtdcr (malrxbattr, 0x0);
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200712 mtdcr (maltxctp2r, hw_p->tx);
wdenkba56f622004-02-06 23:19:44 +0000713 mtdcr (malrxctp2r, hw_p->rx);
714 /* set RX buffer size */
715 mtdcr (malrcbs2, ENET_MAX_MTU_ALIGNED / 16);
716 break;
717 case 3:
718 /* setup MAL tx & rx channel pointers */
719 mtdcr (maltxbattr, 0x0);
720 mtdcr (maltxctp3r, hw_p->tx);
721 mtdcr (malrxbattr, 0x0);
722 mtdcr (malrxctp3r, hw_p->rx);
723 /* set RX buffer size */
724 mtdcr (malrcbs3, ENET_MAX_MTU_ALIGNED / 16);
725 break;
Stefan Roesec57c7982005-08-11 17:56:56 +0200726#endif /* CONFIG_440GX */
wdenkba56f622004-02-06 23:19:44 +0000727 case 0:
728 default:
729 /* setup MAL tx & rx channel pointers */
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200730#if defined(CONFIG_440)
wdenkba56f622004-02-06 23:19:44 +0000731 mtdcr (maltxbattr, 0x0);
wdenkba56f622004-02-06 23:19:44 +0000732 mtdcr (malrxbattr, 0x0);
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200733#endif
734 mtdcr (maltxctp0r, hw_p->tx);
wdenkba56f622004-02-06 23:19:44 +0000735 mtdcr (malrxctp0r, hw_p->rx);
736 /* set RX buffer size */
737 mtdcr (malrcbs0, ENET_MAX_MTU_ALIGNED / 16);
738 break;
739 }
740
741 /* Enable MAL transmit and receive channels */
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200742#if defined(CONFIG_405EP) || defined(CONFIG_440EP) || defined(CONFIG_440GR)
Stefan Roesec157d8e2005-08-01 16:41:48 +0200743 mtdcr (maltxcasr, (MAL_TXRX_CASR >> (hw_p->devnum*2)));
744#else
wdenkba56f622004-02-06 23:19:44 +0000745 mtdcr (maltxcasr, (MAL_TXRX_CASR >> hw_p->devnum));
Stefan Roesec157d8e2005-08-01 16:41:48 +0200746#endif
wdenkba56f622004-02-06 23:19:44 +0000747 mtdcr (malrxcasr, (MAL_TXRX_CASR >> hw_p->devnum));
748
749 /* set transmit enable & receive enable */
750 out32 (EMAC_M0 + hw_p->hw_addr, EMAC_M0_TXE | EMAC_M0_RXE);
751
752 /* set receive fifo to 4k and tx fifo to 2k */
753 mode_reg = in32 (EMAC_M1 + hw_p->hw_addr);
754 mode_reg |= EMAC_M1_RFS_4K | EMAC_M1_TX_FIFO_2K;
755
756 /* set speed */
wdenk855a4962004-03-14 18:23:55 +0000757 if (speed == _1000BASET)
758 mode_reg = mode_reg | EMAC_M1_MF_1000MBPS | EMAC_M1_IST;
759 else if (speed == _100BASET)
wdenkba56f622004-02-06 23:19:44 +0000760 mode_reg = mode_reg | EMAC_M1_MF_100MBPS | EMAC_M1_IST;
761 else
762 mode_reg = mode_reg & ~0x00C00000; /* 10 MBPS */
763 if (duplex == FULL)
764 mode_reg = mode_reg | 0x80000000 | EMAC_M1_IST;
765
766 out32 (EMAC_M1 + hw_p->hw_addr, mode_reg);
767
768 /* Enable broadcast and indvidual address */
769 /* TBS: enabling runts as some misbehaved nics will send runts */
770 out32 (EMAC_RXM + hw_p->hw_addr, EMAC_RMR_BAE | EMAC_RMR_IAE);
771
772 /* we probably need to set the tx mode1 reg? maybe at tx time */
773
774 /* set transmit request threshold register */
775 out32 (EMAC_TRTR + hw_p->hw_addr, 0x18000000); /* 256 byte threshold */
776
Wolfgang Denk265817c2005-09-25 00:53:22 +0200777 /* set receive low/high water mark register */
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200778#if defined(CONFIG_440)
wdenkba56f622004-02-06 23:19:44 +0000779 /* 440GP has a 64 byte burst length */
780 out32 (EMAC_RX_HI_LO_WMARK + hw_p->hw_addr, 0x80009000);
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200781#else
782 /* 405s have a 16 byte burst length */
783 out32 (EMAC_RX_HI_LO_WMARK + hw_p->hw_addr, 0x0f002000);
784#endif /* defined(CONFIG_440) */
wdenkba56f622004-02-06 23:19:44 +0000785 out32 (EMAC_TXM1 + hw_p->hw_addr, 0xf8640000);
786
787 /* Set fifo limit entry in tx mode 0 */
788 out32 (EMAC_TXM0 + hw_p->hw_addr, 0x00000003);
789 /* Frame gap set */
790 out32 (EMAC_I_FRAME_GAP_REG + hw_p->hw_addr, 0x00000008);
791
792 /* Set EMAC IER */
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200793 hw_p->emac_ier = EMAC_ISR_PTLE | EMAC_ISR_BFCS | EMAC_ISR_ORE | EMAC_ISR_IRE;
wdenkba56f622004-02-06 23:19:44 +0000794 if (speed == _100BASET)
795 hw_p->emac_ier = hw_p->emac_ier | EMAC_ISR_SYE;
796
797 out32 (EMAC_ISR + hw_p->hw_addr, 0xffffffff); /* clear pending interrupts */
798 out32 (EMAC_IER + hw_p->hw_addr, hw_p->emac_ier);
799
800 if (hw_p->first_init == 0) {
801 /*
802 * Connect interrupt service routines
803 */
wdenkba56f622004-02-06 23:19:44 +0000804 irq_install_handler (VECNUM_ETH0 + (hw_p->devnum * 2),
805 (interrupt_handler_t *) enetInt, dev);
806 }
wdenkba56f622004-02-06 23:19:44 +0000807
808 mtmsr (msr); /* enable interrupts again */
809
810 hw_p->bis = bis;
811 hw_p->first_init = 1;
812
813 return (1);
814}
815
816
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200817static int ppc_4xx_eth_send (struct eth_device *dev, volatile void *ptr,
wdenkba56f622004-02-06 23:19:44 +0000818 int len)
819{
820 struct enet_frame *ef_ptr;
821 ulong time_start, time_now;
822 unsigned long temp_txm0;
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200823 EMAC_4XX_HW_PST hw_p = dev->priv;
wdenkba56f622004-02-06 23:19:44 +0000824
825 ef_ptr = (struct enet_frame *) ptr;
826
827 /*-----------------------------------------------------------------------+
828 * Copy in our address into the frame.
829 *-----------------------------------------------------------------------*/
830 (void) memcpy (ef_ptr->source_addr, dev->enetaddr, ENET_ADDR_LENGTH);
831
832 /*-----------------------------------------------------------------------+
833 * If frame is too long or too short, modify length.
834 *-----------------------------------------------------------------------*/
835 /* TBS: where does the fragment go???? */
836 if (len > ENET_MAX_MTU)
837 len = ENET_MAX_MTU;
838
839 /* memcpy ((void *) &tx_buff[tx_slot], (const void *) ptr, len); */
840 memcpy ((void *) hw_p->txbuf_ptr, (const void *) ptr, len);
841
842 /*-----------------------------------------------------------------------+
843 * set TX Buffer busy, and send it
844 *-----------------------------------------------------------------------*/
845 hw_p->tx[hw_p->tx_slot].ctrl = (MAL_TX_CTRL_LAST |
846 EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP) &
847 ~(EMAC_TX_CTRL_ISA | EMAC_TX_CTRL_RSA);
848 if ((NUM_TX_BUFF - 1) == hw_p->tx_slot)
849 hw_p->tx[hw_p->tx_slot].ctrl |= MAL_TX_CTRL_WRAP;
850
851 hw_p->tx[hw_p->tx_slot].data_len = (short) len;
852 hw_p->tx[hw_p->tx_slot].ctrl |= MAL_TX_CTRL_READY;
853
854 __asm__ volatile ("eieio");
855
856 out32 (EMAC_TXM0 + hw_p->hw_addr,
857 in32 (EMAC_TXM0 + hw_p->hw_addr) | EMAC_TXM0_GNP0);
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200858#ifdef INFO_4XX_ENET
wdenkba56f622004-02-06 23:19:44 +0000859 hw_p->stats.pkts_tx++;
860#endif
861
862 /*-----------------------------------------------------------------------+
863 * poll unitl the packet is sent and then make sure it is OK
864 *-----------------------------------------------------------------------*/
865 time_start = get_timer (0);
866 while (1) {
867 temp_txm0 = in32 (EMAC_TXM0 + hw_p->hw_addr);
868 /* loop until either TINT turns on or 3 seconds elapse */
869 if ((temp_txm0 & EMAC_TXM0_GNP0) != 0) {
870 /* transmit is done, so now check for errors
871 * If there is an error, an interrupt should
872 * happen when we return
873 */
874 time_now = get_timer (0);
875 if ((time_now - time_start) > 3000) {
876 return (-1);
877 }
878 } else {
879 return (len);
880 }
881 }
882}
883
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200884#if defined (CONFIG_440)
wdenkba56f622004-02-06 23:19:44 +0000885
886int enetInt (struct eth_device *dev)
887{
888 int serviced;
889 int rc = -1; /* default to not us */
890 unsigned long mal_isr;
891 unsigned long emac_isr = 0;
892 unsigned long mal_rx_eob;
893 unsigned long my_uic0msr, my_uic1msr;
894
Stefan Roese846b0dd2005-08-08 12:42:22 +0200895#if defined(CONFIG_440GX)
wdenkba56f622004-02-06 23:19:44 +0000896 unsigned long my_uic2msr;
897#endif
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200898 EMAC_4XX_HW_PST hw_p;
wdenkba56f622004-02-06 23:19:44 +0000899
900 /*
901 * Because the mal is generic, we need to get the current
902 * eth device
903 */
Stefan Roesed6c61aa2005-08-16 18:18:00 +0200904#if defined(CONFIG_NET_MULTI)
905 dev = eth_get_dev();
906#else
907 dev = emac0_dev;
908#endif
wdenkba56f622004-02-06 23:19:44 +0000909
910 hw_p = dev->priv;
911
912
913 /* enter loop that stays in interrupt code until nothing to service */
914 do {
915 serviced = 0;
916
917 my_uic0msr = mfdcr (uic0msr);
918 my_uic1msr = mfdcr (uic1msr);
Stefan Roese846b0dd2005-08-08 12:42:22 +0200919#if defined(CONFIG_440GX)
wdenkba56f622004-02-06 23:19:44 +0000920 my_uic2msr = mfdcr (uic2msr);
921#endif
922 if (!(my_uic0msr & (UIC_MRE | UIC_MTE))
923 && !(my_uic1msr &
924 (UIC_ETH0 | UIC_ETH1 | UIC_MS | UIC_MTDE |
925 UIC_MRDE))) {
926 /* not for us */
927 return (rc);
928 }
Stefan Roese846b0dd2005-08-08 12:42:22 +0200929#if defined (CONFIG_440GX)
wdenkba56f622004-02-06 23:19:44 +0000930 if (!(my_uic0msr & (UIC_MRE | UIC_MTE))
931 && !(my_uic2msr & (UIC_ETH2 | UIC_ETH3))) {
932 /* not for us */
933 return (rc);
934 }
935#endif
936 /* get and clear controller status interrupts */
937 /* look at Mal and EMAC interrupts */
938 if ((my_uic0msr & (UIC_MRE | UIC_MTE))
939 || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
940 /* we have a MAL interrupt */
941 mal_isr = mfdcr (malesr);
942 /* look for mal error */
943 if (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE)) {
944 mal_err (dev, mal_isr, my_uic0msr,
945 MAL_UIC_DEF, MAL_UIC_ERR);
946 serviced = 1;
947 rc = 0;
948 }
949 }
950
951 /* port by port dispatch of emac interrupts */
952 if (hw_p->devnum == 0) {
953 if (UIC_ETH0 & my_uic1msr) { /* look for EMAC errors */
954 emac_isr = in32 (EMAC_ISR + hw_p->hw_addr);
955 if ((hw_p->emac_ier & emac_isr) != 0) {
956 emac_err (dev, emac_isr);
957 serviced = 1;
958 rc = 0;
959 }
960 }
961 if ((hw_p->emac_ier & emac_isr)
962 || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
963 mtdcr (uic0sr, UIC_MRE | UIC_MTE); /* Clear */
964 mtdcr (uic1sr, UIC_ETH0 | UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
965 return (rc); /* we had errors so get out */
966 }
967 }
968
969 if (hw_p->devnum == 1) {
970 if (UIC_ETH1 & my_uic1msr) { /* look for EMAC errors */
971 emac_isr = in32 (EMAC_ISR + hw_p->hw_addr);
972 if ((hw_p->emac_ier & emac_isr) != 0) {
973 emac_err (dev, emac_isr);
974 serviced = 1;
975 rc = 0;
976 }
977 }
978 if ((hw_p->emac_ier & emac_isr)
979 || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
980 mtdcr (uic0sr, UIC_MRE | UIC_MTE); /* Clear */
981 mtdcr (uic1sr, UIC_ETH1 | UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
982 return (rc); /* we had errors so get out */
983 }
984 }
Stefan Roese846b0dd2005-08-08 12:42:22 +0200985#if defined (CONFIG_440GX)
wdenkba56f622004-02-06 23:19:44 +0000986 if (hw_p->devnum == 2) {
987 if (UIC_ETH2 & my_uic2msr) { /* look for EMAC errors */
988 emac_isr = in32 (EMAC_ISR + hw_p->hw_addr);
989 if ((hw_p->emac_ier & emac_isr) != 0) {
990 emac_err (dev, emac_isr);
991 serviced = 1;
992 rc = 0;
993 }
994 }
995 if ((hw_p->emac_ier & emac_isr)
996 || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
997 mtdcr (uic0sr, UIC_MRE | UIC_MTE); /* Clear */
998 mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
999 mtdcr (uic2sr, UIC_ETH2);
1000 return (rc); /* we had errors so get out */
1001 }
1002 }
1003
1004 if (hw_p->devnum == 3) {
1005 if (UIC_ETH3 & my_uic2msr) { /* look for EMAC errors */
1006 emac_isr = in32 (EMAC_ISR + hw_p->hw_addr);
1007 if ((hw_p->emac_ier & emac_isr) != 0) {
1008 emac_err (dev, emac_isr);
1009 serviced = 1;
1010 rc = 0;
1011 }
1012 }
1013 if ((hw_p->emac_ier & emac_isr)
1014 || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) {
1015 mtdcr (uic0sr, UIC_MRE | UIC_MTE); /* Clear */
1016 mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
1017 mtdcr (uic2sr, UIC_ETH3);
1018 return (rc); /* we had errors so get out */
1019 }
1020 }
Stefan Roese846b0dd2005-08-08 12:42:22 +02001021#endif /* CONFIG_440GX */
wdenkba56f622004-02-06 23:19:44 +00001022 /* handle MAX TX EOB interrupt from a tx */
1023 if (my_uic0msr & UIC_MTE) {
1024 mal_rx_eob = mfdcr (maltxeobisr);
1025 mtdcr (maltxeobisr, mal_rx_eob);
1026 mtdcr (uic0sr, UIC_MTE);
1027 }
1028 /* handle MAL RX EOB interupt from a receive */
wdenkfc1cfcd2004-04-25 15:41:35 +00001029 /* check for EOB on valid channels */
wdenkba56f622004-02-06 23:19:44 +00001030 if (my_uic0msr & UIC_MRE) {
1031 mal_rx_eob = mfdcr (malrxeobisr);
Wolfgang Denk265817c2005-09-25 00:53:22 +02001032 if ((mal_rx_eob & (0x80000000 >> hw_p->devnum)) != 0) { /* call emac routine for channel x */
wdenkba56f622004-02-06 23:19:44 +00001033 /* clear EOB
1034 mtdcr(malrxeobisr, mal_rx_eob); */
1035 enet_rcv (dev, emac_isr);
1036 /* indicate that we serviced an interrupt */
1037 serviced = 1;
1038 rc = 0;
1039 }
1040 }
1041 mtdcr (uic0sr, UIC_MRE); /* Clear */
1042 mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */
1043 switch (hw_p->devnum) {
1044 case 0:
1045 mtdcr (uic1sr, UIC_ETH0);
1046 break;
1047 case 1:
1048 mtdcr (uic1sr, UIC_ETH1);
1049 break;
Stefan Roese846b0dd2005-08-08 12:42:22 +02001050#if defined (CONFIG_440GX)
wdenkba56f622004-02-06 23:19:44 +00001051 case 2:
1052 mtdcr (uic2sr, UIC_ETH2);
1053 break;
1054 case 3:
1055 mtdcr (uic2sr, UIC_ETH3);
1056 break;
Stefan Roese846b0dd2005-08-08 12:42:22 +02001057#endif /* CONFIG_440GX */
wdenkba56f622004-02-06 23:19:44 +00001058 default:
1059 break;
1060 }
1061 } while (serviced);
1062
1063 return (rc);
1064}
1065
Stefan Roesed6c61aa2005-08-16 18:18:00 +02001066#else /* CONFIG_440 */
1067
1068int enetInt (struct eth_device *dev)
1069{
1070 int serviced;
1071 int rc = -1; /* default to not us */
1072 unsigned long mal_isr;
1073 unsigned long emac_isr = 0;
1074 unsigned long mal_rx_eob;
1075 unsigned long my_uicmsr;
1076
1077 EMAC_4XX_HW_PST hw_p;
1078
1079 /*
1080 * Because the mal is generic, we need to get the current
1081 * eth device
1082 */
1083#if defined(CONFIG_NET_MULTI)
1084 dev = eth_get_dev();
1085#else
1086 dev = emac0_dev;
1087#endif
1088
1089 hw_p = dev->priv;
1090
1091 /* enter loop that stays in interrupt code until nothing to service */
1092 do {
1093 serviced = 0;
1094
1095 my_uicmsr = mfdcr (uicmsr);
1096
1097 if ((my_uicmsr & (MAL_UIC_DEF | EMAC_UIC_DEF)) == 0) { /* not for us */
1098 return (rc);
1099 }
1100 /* get and clear controller status interrupts */
1101 /* look at Mal and EMAC interrupts */
1102 if ((MAL_UIC_DEF & my_uicmsr) != 0) { /* we have a MAL interrupt */
1103 mal_isr = mfdcr (malesr);
1104 /* look for mal error */
1105 if ((my_uicmsr & MAL_UIC_ERR) != 0) {
1106 mal_err (dev, mal_isr, my_uicmsr, MAL_UIC_DEF, MAL_UIC_ERR);
1107 serviced = 1;
1108 rc = 0;
1109 }
1110 }
1111
1112 /* port by port dispatch of emac interrupts */
1113
1114 if ((SEL_UIC_DEF(hw_p->devnum) & my_uicmsr) != 0) { /* look for EMAC errors */
1115 emac_isr = in32 (EMAC_ISR + hw_p->hw_addr);
1116 if ((hw_p->emac_ier & emac_isr) != 0) {
1117 emac_err (dev, emac_isr);
1118 serviced = 1;
1119 rc = 0;
1120 }
1121 }
1122 if (((hw_p->emac_ier & emac_isr) != 0) || ((MAL_UIC_ERR & my_uicmsr) != 0)) {
1123 mtdcr (uicsr, MAL_UIC_DEF | SEL_UIC_DEF(hw_p->devnum)); /* Clear */
1124 return (rc); /* we had errors so get out */
1125 }
1126
1127 /* handle MAX TX EOB interrupt from a tx */
1128 if (my_uicmsr & UIC_MAL_TXEOB) {
1129 mal_rx_eob = mfdcr (maltxeobisr);
1130 mtdcr (maltxeobisr, mal_rx_eob);
1131 mtdcr (uicsr, UIC_MAL_TXEOB);
1132 }
1133 /* handle MAL RX EOB interupt from a receive */
1134 /* check for EOB on valid channels */
1135 if (my_uicmsr & UIC_MAL_RXEOB)
1136 {
1137 mal_rx_eob = mfdcr (malrxeobisr);
Wolfgang Denk265817c2005-09-25 00:53:22 +02001138 if ((mal_rx_eob & (0x80000000 >> hw_p->devnum)) != 0) { /* call emac routine for channel x */
Stefan Roesed6c61aa2005-08-16 18:18:00 +02001139 /* clear EOB
1140 mtdcr(malrxeobisr, mal_rx_eob); */
1141 enet_rcv (dev, emac_isr);
1142 /* indicate that we serviced an interrupt */
1143 serviced = 1;
1144 rc = 0;
1145 }
1146 }
1147 mtdcr (uicsr, MAL_UIC_DEF|EMAC_UIC_DEF|EMAC_UIC_DEF1); /* Clear */
1148 }
1149 while (serviced);
1150
1151 return (rc);
1152}
1153
1154#endif /* CONFIG_440 */
1155
wdenkba56f622004-02-06 23:19:44 +00001156/*-----------------------------------------------------------------------------+
1157 * MAL Error Routine
1158 *-----------------------------------------------------------------------------*/
1159static void mal_err (struct eth_device *dev, unsigned long isr,
1160 unsigned long uic, unsigned long maldef,
1161 unsigned long mal_errr)
1162{
Stefan Roesed6c61aa2005-08-16 18:18:00 +02001163 EMAC_4XX_HW_PST hw_p = dev->priv;
wdenkba56f622004-02-06 23:19:44 +00001164
1165 mtdcr (malesr, isr); /* clear interrupt */
1166
1167 /* clear DE interrupt */
1168 mtdcr (maltxdeir, 0xC0000000);
1169 mtdcr (malrxdeir, 0x80000000);
1170
Stefan Roesed6c61aa2005-08-16 18:18:00 +02001171#ifdef INFO_4XX_ENET
Wolfgang Denk265817c2005-09-25 00:53:22 +02001172 printf ("\nMAL error occured.... ISR = %lx UIC = = %lx MAL_DEF = %lx MAL_ERR= %lx \n", isr, uic, maldef, mal_errr);
wdenkba56f622004-02-06 23:19:44 +00001173#endif
1174
1175 eth_init (hw_p->bis); /* start again... */
1176}
1177
1178/*-----------------------------------------------------------------------------+
1179 * EMAC Error Routine
1180 *-----------------------------------------------------------------------------*/
1181static void emac_err (struct eth_device *dev, unsigned long isr)
1182{
Stefan Roesed6c61aa2005-08-16 18:18:00 +02001183 EMAC_4XX_HW_PST hw_p = dev->priv;
wdenkba56f622004-02-06 23:19:44 +00001184
1185 printf ("EMAC%d error occured.... ISR = %lx\n", hw_p->devnum, isr);
1186 out32 (EMAC_ISR + hw_p->hw_addr, isr);
1187}
1188
1189/*-----------------------------------------------------------------------------+
1190 * enet_rcv() handles the ethernet receive data
1191 *-----------------------------------------------------------------------------*/
1192static void enet_rcv (struct eth_device *dev, unsigned long malisr)
1193{
1194 struct enet_frame *ef_ptr;
1195 unsigned long data_len;
1196 unsigned long rx_eob_isr;
Stefan Roesed6c61aa2005-08-16 18:18:00 +02001197 EMAC_4XX_HW_PST hw_p = dev->priv;
wdenkba56f622004-02-06 23:19:44 +00001198
1199 int handled = 0;
1200 int i;
1201 int loop_count = 0;
1202
1203 rx_eob_isr = mfdcr (malrxeobisr);
1204 if ((0x80000000 >> hw_p->devnum) & rx_eob_isr) {
1205 /* clear EOB */
1206 mtdcr (malrxeobisr, rx_eob_isr);
1207
1208 /* EMAC RX done */
1209 while (1) { /* do all */
1210 i = hw_p->rx_slot;
1211
1212 if ((MAL_RX_CTRL_EMPTY & hw_p->rx[i].ctrl)
1213 || (loop_count >= NUM_RX_BUFF))
1214 break;
1215 loop_count++;
1216 hw_p->rx_slot++;
1217 if (NUM_RX_BUFF == hw_p->rx_slot)
1218 hw_p->rx_slot = 0;
1219 handled++;
1220 data_len = (unsigned long) hw_p->rx[i].data_len; /* Get len */
1221 if (data_len) {
1222 if (data_len > ENET_MAX_MTU) /* Check len */
1223 data_len = 0;
1224 else {
1225 if (EMAC_RX_ERRORS & hw_p->rx[i].ctrl) { /* Check Errors */
1226 data_len = 0;
1227 hw_p->stats.rx_err_log[hw_p->
1228 rx_err_index]
1229 = hw_p->rx[i].ctrl;
1230 hw_p->rx_err_index++;
1231 if (hw_p->rx_err_index ==
1232 MAX_ERR_LOG)
1233 hw_p->rx_err_index =
1234 0;
wdenkfc1cfcd2004-04-25 15:41:35 +00001235 } /* emac_erros */
wdenkba56f622004-02-06 23:19:44 +00001236 } /* data_len < max mtu */
wdenkfc1cfcd2004-04-25 15:41:35 +00001237 } /* if data_len */
wdenkba56f622004-02-06 23:19:44 +00001238 if (!data_len) { /* no data */
1239 hw_p->rx[i].ctrl |= MAL_RX_CTRL_EMPTY; /* Free Recv Buffer */
1240
1241 hw_p->stats.data_len_err++; /* Error at Rx */
1242 }
1243
1244 /* !data_len */
1245 /* AS.HARNOIS */
1246 /* Check if user has already eaten buffer */
1247 /* if not => ERROR */
1248 else if (hw_p->rx_ready[hw_p->rx_i_index] != -1) {
1249 if (hw_p->is_receiving)
1250 printf ("ERROR : Receive buffers are full!\n");
1251 break;
1252 } else {
1253 hw_p->stats.rx_frames++;
1254 hw_p->stats.rx += data_len;
1255 ef_ptr = (struct enet_frame *) hw_p->rx[i].
1256 data_ptr;
Stefan Roesed6c61aa2005-08-16 18:18:00 +02001257#ifdef INFO_4XX_ENET
wdenkba56f622004-02-06 23:19:44 +00001258 hw_p->stats.pkts_rx++;
1259#endif
1260 /* AS.HARNOIS
1261 * use ring buffer
1262 */
1263 hw_p->rx_ready[hw_p->rx_i_index] = i;
1264 hw_p->rx_i_index++;
1265 if (NUM_RX_BUFF == hw_p->rx_i_index)
1266 hw_p->rx_i_index = 0;
1267
wdenkba56f622004-02-06 23:19:44 +00001268 /* AS.HARNOIS
1269 * free receive buffer only when
1270 * buffer has been handled (eth_rx)
1271 rx[i].ctrl |= MAL_RX_CTRL_EMPTY;
1272 */
1273 } /* if data_len */
1274 } /* while */
1275 } /* if EMACK_RXCHL */
1276}
1277
1278
Stefan Roesed6c61aa2005-08-16 18:18:00 +02001279static int ppc_4xx_eth_rx (struct eth_device *dev)
wdenkba56f622004-02-06 23:19:44 +00001280{
1281 int length;
1282 int user_index;
1283 unsigned long msr;
Stefan Roesed6c61aa2005-08-16 18:18:00 +02001284 EMAC_4XX_HW_PST hw_p = dev->priv;
wdenkba56f622004-02-06 23:19:44 +00001285
Wolfgang Denk265817c2005-09-25 00:53:22 +02001286 hw_p->is_receiving = 1; /* tell driver */
wdenkba56f622004-02-06 23:19:44 +00001287
1288 for (;;) {
1289 /* AS.HARNOIS
1290 * use ring buffer and
1291 * get index from rx buffer desciptor queue
1292 */
1293 user_index = hw_p->rx_ready[hw_p->rx_u_index];
1294 if (user_index == -1) {
1295 length = -1;
1296 break; /* nothing received - leave for() loop */
1297 }
1298
1299 msr = mfmsr ();
1300 mtmsr (msr & ~(MSR_EE));
1301
1302 length = hw_p->rx[user_index].data_len;
1303
1304 /* Pass the packet up to the protocol layers. */
Wolfgang Denk265817c2005-09-25 00:53:22 +02001305 /* NetReceive(NetRxPackets[rxIdx], length - 4); */
1306 /* NetReceive(NetRxPackets[i], length); */
wdenkba56f622004-02-06 23:19:44 +00001307 NetReceive (NetRxPackets[user_index], length - 4);
1308 /* Free Recv Buffer */
1309 hw_p->rx[user_index].ctrl |= MAL_RX_CTRL_EMPTY;
1310 /* Free rx buffer descriptor queue */
1311 hw_p->rx_ready[hw_p->rx_u_index] = -1;
1312 hw_p->rx_u_index++;
1313 if (NUM_RX_BUFF == hw_p->rx_u_index)
1314 hw_p->rx_u_index = 0;
1315
Stefan Roesed6c61aa2005-08-16 18:18:00 +02001316#ifdef INFO_4XX_ENET
wdenkba56f622004-02-06 23:19:44 +00001317 hw_p->stats.pkts_handled++;
1318#endif
1319
1320 mtmsr (msr); /* Enable IRQ's */
1321 }
1322
Wolfgang Denk265817c2005-09-25 00:53:22 +02001323 hw_p->is_receiving = 0; /* tell driver */
wdenkba56f622004-02-06 23:19:44 +00001324
1325 return length;
1326}
1327
Stefan Roesed6c61aa2005-08-16 18:18:00 +02001328int ppc_4xx_eth_initialize (bd_t * bis)
wdenkba56f622004-02-06 23:19:44 +00001329{
1330 static int virgin = 0;
wdenkba56f622004-02-06 23:19:44 +00001331 struct eth_device *dev;
1332 int eth_num = 0;
Stefan Roesed6c61aa2005-08-16 18:18:00 +02001333 EMAC_4XX_HW_PST hw = NULL;
wdenkba56f622004-02-06 23:19:44 +00001334
Stefan Roese846b0dd2005-08-08 12:42:22 +02001335#if defined(CONFIG_440GX)
Stefan Roesec157d8e2005-08-01 16:41:48 +02001336 unsigned long pfc1;
1337
wdenkba56f622004-02-06 23:19:44 +00001338 mfsdr (sdr_pfc1, pfc1);
1339 pfc1 &= ~(0x01e00000);
1340 pfc1 |= 0x01200000;
1341 mtsdr (sdr_pfc1, pfc1);
Stefan Roesec157d8e2005-08-01 16:41:48 +02001342#endif
wdenk3c74e322004-02-22 23:46:08 +00001343 /* set phy num and mode */
1344 bis->bi_phynum[0] = CONFIG_PHY_ADDR;
Stefan Roesec157d8e2005-08-01 16:41:48 +02001345#if defined(CONFIG_PHY1_ADDR)
wdenk3c74e322004-02-22 23:46:08 +00001346 bis->bi_phynum[1] = CONFIG_PHY1_ADDR;
Stefan Roesec157d8e2005-08-01 16:41:48 +02001347#endif
Stefan Roese846b0dd2005-08-08 12:42:22 +02001348#if defined(CONFIG_440GX)
wdenk3c74e322004-02-22 23:46:08 +00001349 bis->bi_phynum[2] = CONFIG_PHY2_ADDR;
1350 bis->bi_phynum[3] = CONFIG_PHY3_ADDR;
1351 bis->bi_phymode[0] = 0;
1352 bis->bi_phymode[1] = 0;
1353 bis->bi_phymode[2] = 2;
1354 bis->bi_phymode[3] = 2;
wdenkba56f622004-02-06 23:19:44 +00001355
Stefan Roese846b0dd2005-08-08 12:42:22 +02001356#if defined (CONFIG_440GX)
Stefan Roesed6c61aa2005-08-16 18:18:00 +02001357 ppc_4xx_eth_setup_bridge(0, bis);
wdenka06752e2004-09-29 22:43:59 +00001358#endif
Stefan Roesec157d8e2005-08-01 16:41:48 +02001359#endif
wdenka06752e2004-09-29 22:43:59 +00001360
Stefan Roese1e25f952005-10-20 16:34:28 +02001361 for (eth_num = 0; eth_num < LAST_EMAC_NUM; eth_num++) {
wdenkba56f622004-02-06 23:19:44 +00001362
1363 /* See if we can actually bring up the interface, otherwise, skip it */
1364 switch (eth_num) {
wdenke2ffd592004-12-31 09:32:47 +00001365 default: /* fall through */
wdenkba56f622004-02-06 23:19:44 +00001366 case 0:
wdenk3c74e322004-02-22 23:46:08 +00001367 if (memcmp (bis->bi_enetaddr, "\0\0\0\0\0\0", 6) == 0) {
1368 bis->bi_phymode[eth_num] = BI_PHYMODE_NONE;
wdenkba56f622004-02-06 23:19:44 +00001369 continue;
wdenk3c74e322004-02-22 23:46:08 +00001370 }
wdenkba56f622004-02-06 23:19:44 +00001371 break;
wdenke2ffd592004-12-31 09:32:47 +00001372#ifdef CONFIG_HAS_ETH1
wdenkba56f622004-02-06 23:19:44 +00001373 case 1:
wdenk3c74e322004-02-22 23:46:08 +00001374 if (memcmp (bis->bi_enet1addr, "\0\0\0\0\0\0", 6) == 0) {
1375 bis->bi_phymode[eth_num] = BI_PHYMODE_NONE;
wdenkba56f622004-02-06 23:19:44 +00001376 continue;
wdenk3c74e322004-02-22 23:46:08 +00001377 }
wdenkba56f622004-02-06 23:19:44 +00001378 break;
wdenke2ffd592004-12-31 09:32:47 +00001379#endif
1380#ifdef CONFIG_HAS_ETH2
wdenkba56f622004-02-06 23:19:44 +00001381 case 2:
wdenk3c74e322004-02-22 23:46:08 +00001382 if (memcmp (bis->bi_enet2addr, "\0\0\0\0\0\0", 6) == 0) {
1383 bis->bi_phymode[eth_num] = BI_PHYMODE_NONE;
wdenkba56f622004-02-06 23:19:44 +00001384 continue;
wdenk3c74e322004-02-22 23:46:08 +00001385 }
wdenkba56f622004-02-06 23:19:44 +00001386 break;
wdenke2ffd592004-12-31 09:32:47 +00001387#endif
1388#ifdef CONFIG_HAS_ETH3
wdenkba56f622004-02-06 23:19:44 +00001389 case 3:
wdenk3c74e322004-02-22 23:46:08 +00001390 if (memcmp (bis->bi_enet3addr, "\0\0\0\0\0\0", 6) == 0) {
1391 bis->bi_phymode[eth_num] = BI_PHYMODE_NONE;
wdenkba56f622004-02-06 23:19:44 +00001392 continue;
wdenk3c74e322004-02-22 23:46:08 +00001393 }
wdenkba56f622004-02-06 23:19:44 +00001394 break;
wdenke2ffd592004-12-31 09:32:47 +00001395#endif
wdenkba56f622004-02-06 23:19:44 +00001396 }
1397
1398 /* Allocate device structure */
1399 dev = (struct eth_device *) malloc (sizeof (*dev));
1400 if (dev == NULL) {
Stefan Roesed6c61aa2005-08-16 18:18:00 +02001401 printf ("ppc_4xx_eth_initialize: "
wdenk3f85ce22004-02-23 16:11:30 +00001402 "Cannot allocate eth_device %d\n", eth_num);
wdenkba56f622004-02-06 23:19:44 +00001403 return (-1);
1404 }
wdenkb2532ef2005-06-20 10:17:34 +00001405 memset(dev, 0, sizeof(*dev));
wdenkba56f622004-02-06 23:19:44 +00001406
1407 /* Allocate our private use data */
Stefan Roesed6c61aa2005-08-16 18:18:00 +02001408 hw = (EMAC_4XX_HW_PST) malloc (sizeof (*hw));
wdenkba56f622004-02-06 23:19:44 +00001409 if (hw == NULL) {
Stefan Roesed6c61aa2005-08-16 18:18:00 +02001410 printf ("ppc_4xx_eth_initialize: "
wdenk3f85ce22004-02-23 16:11:30 +00001411 "Cannot allocate private hw data for eth_device %d",
wdenkba56f622004-02-06 23:19:44 +00001412 eth_num);
1413 free (dev);
1414 return (-1);
1415 }
wdenkb2532ef2005-06-20 10:17:34 +00001416 memset(hw, 0, sizeof(*hw));
wdenkba56f622004-02-06 23:19:44 +00001417
1418 switch (eth_num) {
wdenke2ffd592004-12-31 09:32:47 +00001419 default: /* fall through */
wdenkba56f622004-02-06 23:19:44 +00001420 case 0:
1421 hw->hw_addr = 0;
1422 memcpy (dev->enetaddr, bis->bi_enetaddr, 6);
1423 break;
wdenke2ffd592004-12-31 09:32:47 +00001424#ifdef CONFIG_HAS_ETH1
wdenkba56f622004-02-06 23:19:44 +00001425 case 1:
1426 hw->hw_addr = 0x100;
1427 memcpy (dev->enetaddr, bis->bi_enet1addr, 6);
1428 break;
wdenke2ffd592004-12-31 09:32:47 +00001429#endif
1430#ifdef CONFIG_HAS_ETH2
wdenkba56f622004-02-06 23:19:44 +00001431 case 2:
1432 hw->hw_addr = 0x400;
1433 memcpy (dev->enetaddr, bis->bi_enet2addr, 6);
1434 break;
wdenke2ffd592004-12-31 09:32:47 +00001435#endif
1436#ifdef CONFIG_HAS_ETH3
wdenkba56f622004-02-06 23:19:44 +00001437 case 3:
1438 hw->hw_addr = 0x600;
1439 memcpy (dev->enetaddr, bis->bi_enet3addr, 6);
1440 break;
wdenke2ffd592004-12-31 09:32:47 +00001441#endif
wdenkba56f622004-02-06 23:19:44 +00001442 }
1443
1444 hw->devnum = eth_num;
Stefan Roesec157d8e2005-08-01 16:41:48 +02001445 hw->print_speed = 1;
wdenkba56f622004-02-06 23:19:44 +00001446
Stefan Roesed6c61aa2005-08-16 18:18:00 +02001447 sprintf (dev->name, "ppc_4xx_eth%d", eth_num);
wdenkba56f622004-02-06 23:19:44 +00001448 dev->priv = (void *) hw;
Stefan Roesed6c61aa2005-08-16 18:18:00 +02001449 dev->init = ppc_4xx_eth_init;
1450 dev->halt = ppc_4xx_eth_halt;
1451 dev->send = ppc_4xx_eth_send;
1452 dev->recv = ppc_4xx_eth_rx;
wdenkba56f622004-02-06 23:19:44 +00001453
1454 if (0 == virgin) {
1455 /* set the MAL IER ??? names may change with new spec ??? */
1456 mal_ier =
1457 MAL_IER_DE | MAL_IER_NE | MAL_IER_TE |
1458 MAL_IER_OPBE | MAL_IER_PLBE;
1459 mtdcr (malesr, 0xffffffff); /* clear pending interrupts */
1460 mtdcr (maltxdeir, 0xffffffff); /* clear pending interrupts */
1461 mtdcr (malrxdeir, 0xffffffff); /* clear pending interrupts */
1462 mtdcr (malier, mal_ier);
1463
1464 /* install MAL interrupt handler */
1465 irq_install_handler (VECNUM_MS,
1466 (interrupt_handler_t *) enetInt,
1467 dev);
1468 irq_install_handler (VECNUM_MTE,
1469 (interrupt_handler_t *) enetInt,
1470 dev);
1471 irq_install_handler (VECNUM_MRE,
1472 (interrupt_handler_t *) enetInt,
1473 dev);
1474 irq_install_handler (VECNUM_TXDE,
1475 (interrupt_handler_t *) enetInt,
1476 dev);
1477 irq_install_handler (VECNUM_RXDE,
1478 (interrupt_handler_t *) enetInt,
1479 dev);
1480 virgin = 1;
1481 }
1482
Stefan Roesed6c61aa2005-08-16 18:18:00 +02001483#if defined(CONFIG_NET_MULTI)
wdenkba56f622004-02-06 23:19:44 +00001484 eth_register (dev);
Stefan Roesed6c61aa2005-08-16 18:18:00 +02001485#else
1486 emac0_dev = dev;
1487#endif
wdenkba56f622004-02-06 23:19:44 +00001488
1489 } /* end for each supported device */
1490 return (1);
1491}
Stefan Roesed6c61aa2005-08-16 18:18:00 +02001492
1493
1494#if !defined(CONFIG_NET_MULTI)
1495void eth_halt (void) {
1496 if (emac0_dev) {
1497 ppc_4xx_eth_halt(emac0_dev);
1498 free(emac0_dev);
1499 emac0_dev = NULL;
1500 }
1501}
1502
1503int eth_init (bd_t *bis)
1504{
1505 ppc_4xx_eth_initialize(bis);
Stefan Roese4f92ac32005-10-10 17:43:58 +02001506 if (emac0_dev) {
1507 return ppc_4xx_eth_init(emac0_dev, bis);
1508 } else {
1509 printf("ERROR: ethaddr not set!\n");
1510 return -1;
1511 }
Stefan Roesed6c61aa2005-08-16 18:18:00 +02001512}
1513
1514int eth_send(volatile void *packet, int length)
1515{
Stefan Roesed6c61aa2005-08-16 18:18:00 +02001516 return (ppc_4xx_eth_send(emac0_dev, packet, length));
1517}
1518
1519int eth_rx(void)
1520{
1521 return (ppc_4xx_eth_rx(emac0_dev));
1522}
1523#endif /* !defined(CONFIG_NET_MULTI) */
1524
1525#endif /* #if (CONFIG_COMMANDS & CFG_CMD_NET) */