]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/ixp/npe/npe.c
arm: Move cpu/$CPU to arch/arm/cpu/$CPU
[karo-tx-uboot.git] / arch / arm / cpu / ixp / npe / npe.c
1 /*
2  * (C) Copyright 2005-2006
3  * Stefan Roese, DENX Software Engineering, sr@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 #if 0
25 #define DEBUG           /* define for debug output */
26 #endif
27
28 #include <config.h>
29 #include <common.h>
30 #include <net.h>
31 #include <miiphy.h>
32 #include <malloc.h>
33 #include <asm/processor.h>
34 #include <asm/arch-ixp/ixp425.h>
35
36 #include <IxOsal.h>
37 #include <IxEthAcc.h>
38 #include <IxEthDB.h>
39 #include <IxNpeDl.h>
40 #include <IxQMgr.h>
41 #include <IxNpeMh.h>
42 #include <ix_ossl.h>
43 #include <IxFeatureCtrl.h>
44
45 #include <npe.h>
46
47 static IxQMgrDispatcherFuncPtr qDispatcherFunc = NULL;
48 static int npe_exists[NPE_NUM_PORTS];
49 static int npe_used[NPE_NUM_PORTS];
50
51 /* A little extra so we can align to cacheline. */
52 static u8 npe_alloc_pool[NPE_MEM_POOL_SIZE + CONFIG_SYS_CACHELINE_SIZE - 1];
53 static u8 *npe_alloc_end;
54 static u8 *npe_alloc_free;
55
56 static void *npe_alloc(int size)
57 {
58         static int count = 0;
59         void *p = NULL;
60
61         size = (size + (CONFIG_SYS_CACHELINE_SIZE-1)) & ~(CONFIG_SYS_CACHELINE_SIZE-1);
62         count++;
63
64         if ((npe_alloc_free + size) < npe_alloc_end) {
65                 p = npe_alloc_free;
66                 npe_alloc_free += size;
67         } else {
68                 printf("npe_alloc: failed (count=%d, size=%d)!\n", count, size);
69         }
70         return p;
71 }
72
73 /* Not interrupt safe! */
74 static void mbuf_enqueue(IX_OSAL_MBUF **q, IX_OSAL_MBUF *new)
75 {
76         IX_OSAL_MBUF *m = *q;
77
78         IX_OSAL_MBUF_NEXT_PKT_IN_CHAIN_PTR(new) = NULL;
79
80         if (m) {
81                 while(IX_OSAL_MBUF_NEXT_PKT_IN_CHAIN_PTR(m))
82                         m = IX_OSAL_MBUF_NEXT_PKT_IN_CHAIN_PTR(m);
83                 IX_OSAL_MBUF_NEXT_PKT_IN_CHAIN_PTR(m) = new;
84         } else
85                 *q = new;
86 }
87
88 /* Not interrupt safe! */
89 static IX_OSAL_MBUF *mbuf_dequeue(IX_OSAL_MBUF **q)
90 {
91         IX_OSAL_MBUF *m = *q;
92         if (m)
93                 *q = IX_OSAL_MBUF_NEXT_PKT_IN_CHAIN_PTR(m);
94         return m;
95 }
96
97 static void reset_tx_mbufs(struct npe* p_npe)
98 {
99         IX_OSAL_MBUF *m;
100         int i;
101
102         p_npe->txQHead = NULL;
103
104         for (i = 0; i < CONFIG_DEVS_ETH_INTEL_NPE_MAX_TX_DESCRIPTORS; i++) {
105                 m = &p_npe->tx_mbufs[i];
106
107                 memset(m, 0, sizeof(*m));
108
109                 IX_OSAL_MBUF_MDATA(m) = (void *)&p_npe->tx_pkts[i * NPE_PKT_SIZE];
110                 IX_OSAL_MBUF_MLEN(m) = IX_OSAL_MBUF_PKT_LEN(m) = NPE_PKT_SIZE;
111                 mbuf_enqueue(&p_npe->txQHead, m);
112         }
113 }
114
115 static void reset_rx_mbufs(struct npe* p_npe)
116 {
117         IX_OSAL_MBUF *m;
118         int i;
119
120         p_npe->rxQHead = NULL;
121
122         HAL_DCACHE_INVALIDATE(p_npe->rx_pkts, NPE_PKT_SIZE *
123                               CONFIG_DEVS_ETH_INTEL_NPE_MAX_RX_DESCRIPTORS);
124
125         for (i = 0; i < CONFIG_DEVS_ETH_INTEL_NPE_MAX_RX_DESCRIPTORS; i++) {
126                 m = &p_npe->rx_mbufs[i];
127
128                 memset(m, 0, sizeof(*m));
129
130                 IX_OSAL_MBUF_MDATA(m) = (void *)&p_npe->rx_pkts[i * NPE_PKT_SIZE];
131                 IX_OSAL_MBUF_MLEN(m) = IX_OSAL_MBUF_PKT_LEN(m) = NPE_PKT_SIZE;
132
133                 if(ixEthAccPortRxFreeReplenish(p_npe->eth_id, m) != IX_SUCCESS) {
134                         printf("ixEthAccPortRxFreeReplenish failed for port %d\n", p_npe->eth_id);
135                         break;
136                 }
137         }
138 }
139
140 static void init_rx_mbufs(struct npe* p_npe)
141 {
142         p_npe->rxQHead = NULL;
143
144         p_npe->rx_pkts = npe_alloc(NPE_PKT_SIZE *
145                                    CONFIG_DEVS_ETH_INTEL_NPE_MAX_RX_DESCRIPTORS);
146         if (p_npe->rx_pkts == NULL) {
147                 printf("alloc of packets failed.\n");
148                 return;
149         }
150
151         p_npe->rx_mbufs = (IX_OSAL_MBUF *)
152                 npe_alloc(sizeof(IX_OSAL_MBUF) *
153                           CONFIG_DEVS_ETH_INTEL_NPE_MAX_RX_DESCRIPTORS);
154         if (p_npe->rx_mbufs == NULL) {
155                 printf("alloc of mbufs failed.\n");
156                 return;
157         }
158
159         reset_rx_mbufs(p_npe);
160 }
161
162 static void init_tx_mbufs(struct npe* p_npe)
163 {
164         p_npe->tx_pkts = npe_alloc(NPE_PKT_SIZE *
165                                    CONFIG_DEVS_ETH_INTEL_NPE_MAX_TX_DESCRIPTORS);
166         if (p_npe->tx_pkts == NULL) {
167                 printf("alloc of packets failed.\n");
168                 return;
169         }
170
171         p_npe->tx_mbufs = (IX_OSAL_MBUF *)
172                 npe_alloc(sizeof(IX_OSAL_MBUF) *
173                           CONFIG_DEVS_ETH_INTEL_NPE_MAX_TX_DESCRIPTORS);
174         if (p_npe->tx_mbufs == NULL) {
175                 printf("alloc of mbufs failed.\n");
176                 return;
177         }
178
179         reset_tx_mbufs(p_npe);
180 }
181
182 /* Convert IX_ETH_PORT_n to IX_NPEMH_NPEID_NPEx */
183 static int __eth_to_npe(int eth_id)
184 {
185         switch(eth_id) {
186         case IX_ETH_PORT_1:
187                 return IX_NPEMH_NPEID_NPEB;
188
189         case IX_ETH_PORT_2:
190                 return IX_NPEMH_NPEID_NPEC;
191
192         case IX_ETH_PORT_3:
193                 return IX_NPEMH_NPEID_NPEA;
194         }
195         return 0;
196 }
197
198 /* Poll the CSR machinery. */
199 static void npe_poll(int eth_id)
200 {
201         if (qDispatcherFunc != NULL) {
202                 ixNpeMhMessagesReceive(__eth_to_npe(eth_id));
203                 (*qDispatcherFunc)(IX_QMGR_QUELOW_GROUP);
204         }
205 }
206
207 /* ethAcc RX callback */
208 static void npe_rx_callback(u32 cbTag, IX_OSAL_MBUF *m, IxEthAccPortId portid)
209 {
210         struct npe* p_npe = (struct npe *)cbTag;
211
212         if (IX_OSAL_MBUF_MLEN(m) > 0) {
213                 mbuf_enqueue(&p_npe->rxQHead, m);
214
215                 if (p_npe->rx_write == ((p_npe->rx_read-1) & (PKTBUFSRX-1))) {
216                         debug("Rx overflow: rx_write=%d rx_read=%d\n",
217                               p_npe->rx_write, p_npe->rx_read);
218                 } else {
219                         debug("Received message #%d (len=%d)\n", p_npe->rx_write,
220                               IX_OSAL_MBUF_MLEN(m));
221                         memcpy((void *)NetRxPackets[p_npe->rx_write], IX_OSAL_MBUF_MDATA(m),
222                                IX_OSAL_MBUF_MLEN(m));
223                         p_npe->rx_len[p_npe->rx_write] = IX_OSAL_MBUF_MLEN(m);
224                         p_npe->rx_write++;
225                         if (p_npe->rx_write == PKTBUFSRX)
226                                 p_npe->rx_write = 0;
227
228 #ifdef CONFIG_PRINT_RX_FRAMES
229                         {
230                                 u8 *ptr = IX_OSAL_MBUF_MDATA(m);
231                                 int i;
232
233                                 for (i=0; i<60; i++) {
234                                         debug("%02x ", *ptr++);
235                                 }
236                                 debug("\n");
237                         }
238 #endif
239                 }
240
241                 m = mbuf_dequeue(&p_npe->rxQHead);
242         } else {
243                 debug("Received frame with length 0!!!\n");
244                 m = mbuf_dequeue(&p_npe->rxQHead);
245         }
246
247         /* Now return mbuf to NPE */
248         IX_OSAL_MBUF_MLEN(m) = IX_OSAL_MBUF_PKT_LEN(m) = NPE_PKT_SIZE;
249         IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(m) = NULL;
250         IX_OSAL_MBUF_FLAGS(m) = 0;
251
252         if(ixEthAccPortRxFreeReplenish(p_npe->eth_id, m) != IX_SUCCESS) {
253                 debug("npe_rx_callback: Error returning mbuf.\n");
254         }
255 }
256
257 /* ethAcc TX callback */
258 static void npe_tx_callback(u32 cbTag, IX_OSAL_MBUF *m)
259 {
260         struct npe* p_npe = (struct npe *)cbTag;
261
262         debug("%s\n", __FUNCTION__);
263
264         IX_OSAL_MBUF_MLEN(m) = IX_OSAL_MBUF_PKT_LEN(m) = NPE_PKT_SIZE;
265         IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(m) = NULL;
266         IX_OSAL_MBUF_FLAGS(m) = 0;
267
268         mbuf_enqueue(&p_npe->txQHead, m);
269 }
270
271
272 static int npe_set_mac_address(struct eth_device *dev)
273 {
274         struct npe *p_npe = (struct npe *)dev->priv;
275         IxEthAccMacAddr npeMac;
276
277         debug("%s\n", __FUNCTION__);
278
279         /* Set MAC address */
280         memcpy(npeMac.macAddress, dev->enetaddr, 6);
281
282         if (ixEthAccPortUnicastMacAddressSet(p_npe->eth_id, &npeMac) != IX_ETH_ACC_SUCCESS) {
283                 printf("Error setting unicast address! %02x:%02x:%02x:%02x:%02x:%02x\n",
284                        npeMac.macAddress[0], npeMac.macAddress[1],
285                        npeMac.macAddress[2], npeMac.macAddress[3],
286                        npeMac.macAddress[4], npeMac.macAddress[5]);
287                 return 0;
288         }
289
290         return 1;
291 }
292
293 /* Boot-time CSR library initialization. */
294 static int npe_csr_load(void)
295 {
296         int i;
297
298         if (ixQMgrInit() != IX_SUCCESS) {
299                 debug("Error initialising queue manager!\n");
300                 return 0;
301         }
302
303         ixQMgrDispatcherLoopGet(&qDispatcherFunc);
304
305         if(ixNpeMhInitialize(IX_NPEMH_NPEINTERRUPTS_YES) != IX_SUCCESS) {
306                 printf("Error initialising NPE Message handler!\n");
307                 return 0;
308         }
309
310         if (npe_used[IX_ETH_PORT_1] && npe_exists[IX_ETH_PORT_1] &&
311             ixNpeDlNpeInitAndStart(IX_NPEDL_NPEIMAGE_NPEB_ETH_LEARN_FILTER_SPAN_FIREWALL_VLAN_QOS)
312             != IX_SUCCESS) {
313                 printf("Error downloading firmware to NPE-B!\n");
314                 return 0;
315         }
316
317         if (npe_used[IX_ETH_PORT_2] && npe_exists[IX_ETH_PORT_2] &&
318             ixNpeDlNpeInitAndStart(IX_NPEDL_NPEIMAGE_NPEC_ETH_LEARN_FILTER_SPAN_FIREWALL_VLAN_QOS)
319             != IX_SUCCESS) {
320                 printf("Error downloading firmware to NPE-C!\n");
321                 return 0;
322         }
323
324         /* don't need this for U-Boot */
325         ixFeatureCtrlSwConfigurationWrite(IX_FEATURECTRL_ETH_LEARNING, FALSE);
326
327         if (ixEthAccInit() != IX_ETH_ACC_SUCCESS) {
328                 printf("Error initialising Ethernet access driver!\n");
329                 return 0;
330         }
331
332         for (i = 0; i < IX_ETH_ACC_NUMBER_OF_PORTS; i++) {
333                 if (!npe_used[i] || !npe_exists[i])
334                         continue;
335                 if (ixEthAccPortInit(i) != IX_ETH_ACC_SUCCESS) {
336                         printf("Error initialising Ethernet port%d!\n", i);
337                 }
338                 if (ixEthAccTxSchedulingDisciplineSet(i, FIFO_NO_PRIORITY) != IX_ETH_ACC_SUCCESS) {
339                         printf("Error setting scheduling discipline for port %d.\n", i);
340                 }
341                 if (ixEthAccPortRxFrameAppendFCSDisable(i) != IX_ETH_ACC_SUCCESS) {
342                         printf("Error disabling RX FCS for port %d.\n", i);
343                 }
344                 if (ixEthAccPortTxFrameAppendFCSEnable(i) != IX_ETH_ACC_SUCCESS) {
345                         printf("Error enabling TX FCS for port %d.\n", i);
346                 }
347         }
348
349         return 1;
350 }
351
352 static int npe_init(struct eth_device *dev, bd_t * bis)
353 {
354         struct npe *p_npe = (struct npe *)dev->priv;
355         int i;
356         u16 reg_short;
357         int speed;
358         int duplex;
359
360         debug("%s: 1\n", __FUNCTION__);
361
362         miiphy_read (dev->name, p_npe->phy_no, PHY_BMSR, &reg_short);
363
364         /*
365          * Wait if PHY is capable of autonegotiation and autonegotiation is not complete
366          */
367         if ((reg_short & PHY_BMSR_AUTN_ABLE) && !(reg_short & PHY_BMSR_AUTN_COMP)) {
368                 puts ("Waiting for PHY auto negotiation to complete");
369                 i = 0;
370                 while (!(reg_short & PHY_BMSR_AUTN_COMP)) {
371                         /*
372                          * Timeout reached ?
373                          */
374                         if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
375                                 puts (" TIMEOUT !\n");
376                                 break;
377                         }
378
379                         if ((i++ % 1000) == 0) {
380                                 putc ('.');
381                                 miiphy_read (dev->name, p_npe->phy_no, PHY_BMSR, &reg_short);
382                         }
383                         udelay (1000);  /* 1 ms */
384                 }
385                 puts (" done\n");
386                 udelay (500000);        /* another 500 ms (results in faster booting) */
387         }
388
389         speed = miiphy_speed (dev->name, p_npe->phy_no);
390         duplex = miiphy_duplex (dev->name, p_npe->phy_no);
391
392         if (p_npe->print_speed) {
393                 p_npe->print_speed = 0;
394                 printf ("ENET Speed is %d Mbps - %s duplex connection\n",
395                         (int) speed, (duplex == HALF) ? "HALF" : "FULL");
396         }
397
398         npe_alloc_end = npe_alloc_pool + sizeof(npe_alloc_pool);
399         npe_alloc_free = (u8 *)(((unsigned)npe_alloc_pool +
400                                  CONFIG_SYS_CACHELINE_SIZE - 1) & ~(CONFIG_SYS_CACHELINE_SIZE - 1));
401
402         /* initialize mbuf pool */
403         init_rx_mbufs(p_npe);
404         init_tx_mbufs(p_npe);
405
406         if (ixEthAccPortRxCallbackRegister(p_npe->eth_id, npe_rx_callback,
407                                            (u32)p_npe) != IX_ETH_ACC_SUCCESS) {
408                 printf("can't register RX callback!\n");
409                 return -1;
410         }
411
412         if (ixEthAccPortTxDoneCallbackRegister(p_npe->eth_id, npe_tx_callback,
413                                                (u32)p_npe) != IX_ETH_ACC_SUCCESS) {
414                 printf("can't register TX callback!\n");
415                 return -1;
416         }
417
418         npe_set_mac_address(dev);
419
420         if (ixEthAccPortEnable(p_npe->eth_id) != IX_ETH_ACC_SUCCESS) {
421                 printf("can't enable port!\n");
422                 return -1;
423         }
424
425         p_npe->active = 1;
426
427         return 0;
428 }
429
430 #if 0 /* test-only: probably have to deal with it when booting linux (for a clean state) */
431 /* Uninitialize CSR library. */
432 static void npe_csr_unload(void)
433 {
434         ixEthAccUnload();
435         ixEthDBUnload();
436         ixNpeMhUnload();
437         ixQMgrUnload();
438 }
439
440 /* callback which is used by ethAcc to recover RX buffers when stopping */
441 static void npe_rx_stop_callback(u32 cbTag, IX_OSAL_MBUF *m, IxEthAccPortId portid)
442 {
443         debug("%s\n", __FUNCTION__);
444 }
445
446 /* callback which is used by ethAcc to recover TX buffers when stopping */
447 static void npe_tx_stop_callback(u32 cbTag, IX_OSAL_MBUF *m)
448 {
449         debug("%s\n", __FUNCTION__);
450 }
451 #endif
452
453 static void npe_halt(struct eth_device *dev)
454 {
455         struct npe *p_npe = (struct npe *)dev->priv;
456         int i;
457
458         debug("%s\n", __FUNCTION__);
459
460         /* Delay to give time for recovery of mbufs */
461         for (i = 0; i < 100; i++) {
462                 npe_poll(p_npe->eth_id);
463                 udelay(100);
464         }
465
466 #if 0 /* test-only: probably have to deal with it when booting linux (for a clean state) */
467         if (ixEthAccPortRxCallbackRegister(p_npe->eth_id, npe_rx_stop_callback,
468                                            (u32)p_npe) != IX_ETH_ACC_SUCCESS) {
469                 debug("Error registering rx callback!\n");
470         }
471
472         if (ixEthAccPortTxDoneCallbackRegister(p_npe->eth_id, npe_tx_stop_callback,
473                                                (u32)p_npe) != IX_ETH_ACC_SUCCESS) {
474                 debug("Error registering tx callback!\n");
475         }
476
477         if (ixEthAccPortDisable(p_npe->eth_id) != IX_ETH_ACC_SUCCESS) {
478                 debug("npe_stop: Error disabling NPEB!\n");
479         }
480
481         /* Delay to give time for recovery of mbufs */
482         for (i = 0; i < 100; i++) {
483                 npe_poll(p_npe->eth_id);
484                 udelay(10000);
485         }
486
487         /*
488          * For U-Boot only, we are probably launching Linux or other OS that
489          * needs a clean slate for its NPE library.
490          */
491 #if 0 /* test-only */
492         for (i = 0; i < IX_ETH_ACC_NUMBER_OF_PORTS; i++) {
493                 if (npe_used[i] && npe_exists[i])
494                         if (ixNpeDlNpeStopAndReset(__eth_to_npe(i)) != IX_SUCCESS)
495                                 printf("Failed to stop and reset NPE B.\n");
496         }
497 #endif
498
499 #endif
500         p_npe->active = 0;
501 }
502
503
504 static int npe_send(struct eth_device *dev, volatile void *packet, int len)
505 {
506         struct npe *p_npe = (struct npe *)dev->priv;
507         u8 *dest;
508         int err;
509         IX_OSAL_MBUF *m;
510
511         debug("%s\n", __FUNCTION__);
512         m = mbuf_dequeue(&p_npe->txQHead);
513         dest = IX_OSAL_MBUF_MDATA(m);
514         IX_OSAL_MBUF_PKT_LEN(m) = IX_OSAL_MBUF_MLEN(m) = len;
515         IX_OSAL_MBUF_NEXT_PKT_IN_CHAIN_PTR(m) = NULL;
516
517         memcpy(dest, (char *)packet, len);
518
519         if ((err = ixEthAccPortTxFrameSubmit(p_npe->eth_id, m, IX_ETH_ACC_TX_DEFAULT_PRIORITY))
520             != IX_ETH_ACC_SUCCESS) {
521                 printf("npe_send: Can't submit frame. err[%d]\n", err);
522                 mbuf_enqueue(&p_npe->txQHead, m);
523                 return 0;
524         }
525
526 #ifdef DEBUG_PRINT_TX_FRAMES
527         {
528                 u8 *ptr = IX_OSAL_MBUF_MDATA(m);
529                 int i;
530
531                 for (i=0; i<IX_OSAL_MBUF_MLEN(m); i++) {
532                         printf("%02x ", *ptr++);
533                 }
534                 printf(" (tx-len=%d)\n", IX_OSAL_MBUF_MLEN(m));
535         }
536 #endif
537
538         npe_poll(p_npe->eth_id);
539
540         return len;
541 }
542
543 static int npe_rx(struct eth_device *dev)
544 {
545         struct npe *p_npe = (struct npe *)dev->priv;
546
547         debug("%s\n", __FUNCTION__);
548         npe_poll(p_npe->eth_id);
549
550         debug("%s: rx_write=%d rx_read=%d\n", __FUNCTION__, p_npe->rx_write, p_npe->rx_read);
551         while (p_npe->rx_write != p_npe->rx_read) {
552                 debug("Reading message #%d\n", p_npe->rx_read);
553                 NetReceive(NetRxPackets[p_npe->rx_read], p_npe->rx_len[p_npe->rx_read]);
554                 p_npe->rx_read++;
555                 if (p_npe->rx_read == PKTBUFSRX)
556                         p_npe->rx_read = 0;
557         }
558
559         return 0;
560 }
561
562 int npe_initialize(bd_t * bis)
563 {
564         static int virgin = 0;
565         struct eth_device *dev;
566         int eth_num = 0;
567         struct npe *p_npe = NULL;
568         uchar enetaddr[6];
569
570         for (eth_num = 0; eth_num < CONFIG_SYS_NPE_NUMS; eth_num++) {
571
572                 /* See if we can actually bring up the interface, otherwise, skip it */
573 #ifdef CONFIG_HAS_ETH1
574                 if (eth_num == 1) {
575                         if (!eth_getenv_enetaddr("eth1addr", enetaddr))
576                                 continue;
577                 } else
578 #endif
579                         if (!eth_getenv_enetaddr("ethaddr", enetaddr))
580                                 continue;
581
582                 /* Allocate device structure */
583                 dev = (struct eth_device *)malloc(sizeof(*dev));
584                 if (dev == NULL) {
585                         printf ("%s: Cannot allocate eth_device %d\n", __FUNCTION__, eth_num);
586                         return -1;
587                 }
588                 memset(dev, 0, sizeof(*dev));
589
590                 /* Allocate our private use data */
591                 p_npe = (struct npe *)malloc(sizeof(struct npe));
592                 if (p_npe == NULL) {
593                         printf("%s: Cannot allocate private hw data for eth_device %d",
594                                __FUNCTION__, eth_num);
595                         free(dev);
596                         return -1;
597                 }
598                 memset(p_npe, 0, sizeof(struct npe));
599
600                 p_npe->eth_id = eth_num;
601                 memcpy(dev->enetaddr, enetaddr, 6);
602 #ifdef CONFIG_HAS_ETH1
603                 if (eth_num == 1)
604                         p_npe->phy_no = CONFIG_PHY1_ADDR;
605                 else
606 #endif
607                         p_npe->phy_no = CONFIG_PHY_ADDR;
608
609                 sprintf(dev->name, "NPE%d", eth_num);
610                 dev->priv = (void *)p_npe;
611                 dev->init = npe_init;
612                 dev->halt = npe_halt;
613                 dev->send = npe_send;
614                 dev->recv = npe_rx;
615
616                 p_npe->print_speed = 1;
617
618                 if (0 == virgin) {
619                         virgin = 1;
620
621                         if (ixFeatureCtrlDeviceRead() == IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X) {
622                                 switch (ixFeatureCtrlProductIdRead() & IX_FEATURE_CTRL_SILICON_STEPPING_MASK) {
623                                 case IX_FEATURE_CTRL_SILICON_TYPE_B0:
624                                         /*
625                                          * If it is B0 Silicon, we only enable port when its corresponding
626                                          * Eth Coprocessor is available.
627                                          */
628                                         if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH0) ==
629                                             IX_FEATURE_CTRL_COMPONENT_ENABLED)
630                                                 npe_exists[IX_ETH_PORT_1] = TRUE;
631
632                                         if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH1) ==
633                                             IX_FEATURE_CTRL_COMPONENT_ENABLED)
634                                                 npe_exists[IX_ETH_PORT_2] = TRUE;
635                                         break;
636                                 case IX_FEATURE_CTRL_SILICON_TYPE_A0:
637                                         /*
638                                          * If it is A0 Silicon, we enable both as both Eth Coprocessors
639                                          * are available.
640                                          */
641                                         npe_exists[IX_ETH_PORT_1] = TRUE;
642                                         npe_exists[IX_ETH_PORT_2] = TRUE;
643                                         break;
644                                 }
645                         } else if (ixFeatureCtrlDeviceRead() == IX_FEATURE_CTRL_DEVICE_TYPE_IXP46X) {
646                                 if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH0) ==
647                                     IX_FEATURE_CTRL_COMPONENT_ENABLED)
648                                         npe_exists[IX_ETH_PORT_1] = TRUE;
649
650                                 if (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH1) ==
651                                     IX_FEATURE_CTRL_COMPONENT_ENABLED)
652                                         npe_exists[IX_ETH_PORT_2] = TRUE;
653                         }
654
655                         npe_used[IX_ETH_PORT_1] = 1;
656                         npe_used[IX_ETH_PORT_2] = 1;
657
658                         npe_alloc_end = npe_alloc_pool + sizeof(npe_alloc_pool);
659                         npe_alloc_free = (u8 *)(((unsigned)npe_alloc_pool +
660                                                  CONFIG_SYS_CACHELINE_SIZE - 1)
661                                                 & ~(CONFIG_SYS_CACHELINE_SIZE - 1));
662
663                         if (!npe_csr_load())
664                                 return 0;
665                 }
666
667                 eth_register(dev);
668
669 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
670                 miiphy_register(dev->name, npe_miiphy_read, npe_miiphy_write);
671 #endif
672
673         }                       /* end for each supported device */
674
675         return 1;
676 }