]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - post/cpu/mpc8xx/ether.c
Merge git://git.denx.de/u-boot-arm
[karo-tx-uboot.git] / post / cpu / mpc8xx / ether.c
1 /*
2  * (C) Copyright 2002
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 #include <common.h>
9
10 /*
11  * Ethernet test
12  *
13  * The Serial Communication Controllers (SCC) listed in ctlr_list array below
14  * are tested in the loopback ethernet mode.
15  * The controllers are configured accordingly and several packets
16  * are transmitted. The configurable test parameters are:
17  *   MIN_PACKET_LENGTH - minimum size of packet to transmit
18  *   MAX_PACKET_LENGTH - maximum size of packet to transmit
19  *   TEST_NUM - number of tests
20  */
21
22 #include <post.h>
23 #if CONFIG_POST & CONFIG_SYS_POST_ETHER
24 #if defined(CONFIG_8xx)
25 #include <commproc.h>
26 #elif defined(CONFIG_MPC8260)
27 #include <asm/cpm_8260.h>
28 #else
29 #error "Apparently a bad configuration, please fix."
30 #endif
31
32 #include <command.h>
33 #include <net.h>
34 #include <serial.h>
35
36 DECLARE_GLOBAL_DATA_PTR;
37
38 #define MIN_PACKET_LENGTH       64
39 #define MAX_PACKET_LENGTH       256
40 #define TEST_NUM                1
41
42 #define CTLR_SCC 0
43
44 extern void spi_init_f (void);
45 extern void spi_init_r (void);
46
47 /* The list of controllers to test */
48 #if defined(CONFIG_MPC823)
49 static int ctlr_list[][2] = { {CTLR_SCC, 1} };
50 #else
51 static int ctlr_list[][2] = { };
52 #endif
53
54 static struct {
55         void (*init) (int index);
56         void (*halt) (int index);
57         int (*send) (int index, volatile void *packet, int length);
58         int (*recv) (int index, void *packet, int length);
59 } ctlr_proc[1];
60
61 static char *ctlr_name[1] = { "SCC" };
62
63 /* Ethernet Transmit and Receive Buffers */
64 #define DBUF_LENGTH  1520
65
66 #define TX_BUF_CNT 2
67
68 #define TOUT_LOOP 100
69
70 static char txbuf[DBUF_LENGTH];
71
72 static uint rxIdx;              /* index of the current RX buffer */
73 static uint txIdx;              /* index of the current TX buffer */
74
75 /*
76   * SCC Ethernet Tx and Rx buffer descriptors allocated at the
77   *  immr->udata_bd address on Dual-Port RAM
78   * Provide for Double Buffering
79   */
80
81 typedef volatile struct CommonBufferDescriptor {
82         cbd_t rxbd[PKTBUFSRX];          /* Rx BD */
83         cbd_t txbd[TX_BUF_CNT];         /* Tx BD */
84 } RTXBD;
85
86 static RTXBD *rtx;
87
88   /*
89    * SCC callbacks
90    */
91
92 static void scc_init (int scc_index)
93 {
94         uchar ea[6];
95
96         static int proff[] = {
97                                 PROFF_SCC1,
98                                 PROFF_SCC2,
99                                 PROFF_SCC3,
100                                 PROFF_SCC4,
101         };
102         static unsigned int cpm_cr[] = {
103                                 CPM_CR_CH_SCC1,
104                                 CPM_CR_CH_SCC2,
105                                 CPM_CR_CH_SCC3,
106                                 CPM_CR_CH_SCC4,
107         };
108
109         int i;
110         scc_enet_t *pram_ptr;
111
112         volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
113
114         immr->im_cpm.cp_scc[scc_index].scc_gsmrl &=
115                         ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
116
117 #if defined(CONFIG_FADS)
118 #if defined(CONFIG_MPC860T) || defined(CONFIG_MPC86xADS)
119         /* The FADS860T and MPC86xADS don't use the MODEM_EN or DATA_VOICE signals. */
120         *((uint *) BCSR4) &= ~BCSR4_ETHLOOP;
121         *((uint *) BCSR4) |= BCSR4_TFPLDL | BCSR4_TPSQEL;
122         *((uint *) BCSR1) &= ~BCSR1_ETHEN;
123 #else
124         *((uint *) BCSR4) &= ~(BCSR4_ETHLOOP | BCSR4_MODEM_EN);
125         *((uint *) BCSR4) |= BCSR4_TFPLDL | BCSR4_TPSQEL | BCSR4_DATA_VOICE;
126         *((uint *) BCSR1) &= ~BCSR1_ETHEN;
127 #endif
128 #endif
129
130         pram_ptr = (scc_enet_t *) & (immr->im_cpm.cp_dparam[proff[scc_index]]);
131
132         rxIdx = 0;
133         txIdx = 0;
134
135 #ifdef CONFIG_SYS_ALLOC_DPRAM
136         rtx = (RTXBD *) (immr->im_cpm.cp_dpmem +
137                                          dpram_alloc_align (sizeof (RTXBD), 8));
138 #else
139         rtx = (RTXBD *) (immr->im_cpm.cp_dpmem + CPM_SCC_BASE);
140 #endif
141
142 #if 0
143
144 #if (defined(PA_ENET_RXD) && defined(PA_ENET_TXD))
145         /* Configure port A pins for Txd and Rxd.
146          */
147         immr->im_ioport.iop_papar |= (PA_ENET_RXD | PA_ENET_TXD);
148         immr->im_ioport.iop_padir &= ~(PA_ENET_RXD | PA_ENET_TXD);
149         immr->im_ioport.iop_paodr &= ~PA_ENET_TXD;
150 #elif (defined(PB_ENET_RXD) && defined(PB_ENET_TXD))
151         /* Configure port B pins for Txd and Rxd.
152          */
153         immr->im_cpm.cp_pbpar |= (PB_ENET_RXD | PB_ENET_TXD);
154         immr->im_cpm.cp_pbdir &= ~(PB_ENET_RXD | PB_ENET_TXD);
155         immr->im_cpm.cp_pbodr &= ~PB_ENET_TXD;
156 #else
157 #error Configuration Error: exactly ONE of PA_ENET_[RT]XD, PB_ENET_[RT]XD must be defined
158 #endif
159
160 #if defined(PC_ENET_LBK)
161         /* Configure port C pins to disable External Loopback
162          */
163         immr->im_ioport.iop_pcpar &= ~PC_ENET_LBK;
164         immr->im_ioport.iop_pcdir |= PC_ENET_LBK;
165         immr->im_ioport.iop_pcso &= ~PC_ENET_LBK;
166         immr->im_ioport.iop_pcdat &= ~PC_ENET_LBK;      /* Disable Loopback */
167 #endif /* PC_ENET_LBK */
168
169         /* Configure port C pins to enable CLSN and RENA.
170          */
171         immr->im_ioport.iop_pcpar &= ~(PC_ENET_CLSN | PC_ENET_RENA);
172         immr->im_ioport.iop_pcdir &= ~(PC_ENET_CLSN | PC_ENET_RENA);
173         immr->im_ioport.iop_pcso |= (PC_ENET_CLSN | PC_ENET_RENA);
174
175         /* Configure port A for TCLK and RCLK.
176          */
177         immr->im_ioport.iop_papar |= (PA_ENET_TCLK | PA_ENET_RCLK);
178         immr->im_ioport.iop_padir &= ~(PA_ENET_TCLK | PA_ENET_RCLK);
179
180         /*
181          * Configure Serial Interface clock routing -- see section 16.7.5.3
182          * First, clear all SCC bits to zero, then set the ones we want.
183          */
184
185         immr->im_cpm.cp_sicr &= ~SICR_ENET_MASK;
186         immr->im_cpm.cp_sicr |= SICR_ENET_CLKRT;
187 #else
188         /*
189          * SCC2 receive clock is BRG2
190          * SCC2 transmit clock is BRG3
191          */
192         immr->im_cpm.cp_brgc2 = 0x0001000C;
193         immr->im_cpm.cp_brgc3 = 0x0001000C;
194
195         immr->im_cpm.cp_sicr &= ~0x00003F00;
196         immr->im_cpm.cp_sicr |=  0x00000a00;
197 #endif /* 0 */
198
199
200         /*
201          * Initialize SDCR -- see section 16.9.23.7
202          * SDMA configuration register
203          */
204         immr->im_siu_conf.sc_sdcr = 0x01;
205
206
207         /*
208          * Setup SCC Ethernet Parameter RAM
209          */
210
211         pram_ptr->sen_genscc.scc_rfcr = 0x18;   /* Normal Operation and Mot byte ordering */
212         pram_ptr->sen_genscc.scc_tfcr = 0x18;   /* Mot byte ordering, Normal access */
213
214         pram_ptr->sen_genscc.scc_mrblr = DBUF_LENGTH;   /* max. ET package len 1520 */
215
216         pram_ptr->sen_genscc.scc_rbase = (unsigned int) (&rtx->rxbd[0]);        /* Set RXBD tbl start at Dual Port */
217         pram_ptr->sen_genscc.scc_tbase = (unsigned int) (&rtx->txbd[0]);        /* Set TXBD tbl start at Dual Port */
218
219         /*
220          * Setup Receiver Buffer Descriptors (13.14.24.18)
221          * Settings:
222          *     Empty, Wrap
223          */
224
225         for (i = 0; i < PKTBUFSRX; i++) {
226                 rtx->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY;
227                 rtx->rxbd[i].cbd_datlen = 0;    /* Reset */
228                 rtx->rxbd[i].cbd_bufaddr = (uint) NetRxPackets[i];
229         }
230
231         rtx->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP;
232
233         /*
234          * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19)
235          * Settings:
236          *    Add PADs to Short FRAMES, Wrap, Last, Tx CRC
237          */
238
239         for (i = 0; i < TX_BUF_CNT; i++) {
240                 rtx->txbd[i].cbd_sc =
241                                 (BD_ENET_TX_PAD | BD_ENET_TX_LAST | BD_ENET_TX_TC);
242                 rtx->txbd[i].cbd_datlen = 0;    /* Reset */
243                 rtx->txbd[i].cbd_bufaddr = (uint) (&txbuf[0]);
244         }
245
246         rtx->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP;
247
248         /*
249          * Enter Command:  Initialize Rx Params for SCC
250          */
251
252         do {                            /* Spin until ready to issue command    */
253                 __asm__ ("eieio");
254         } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG);
255         /* Issue command */
256         immr->im_cpm.cp_cpcr =
257                         ((CPM_CR_INIT_RX << 8) | (cpm_cr[scc_index] << 4) |
258                          CPM_CR_FLG);
259         do {                            /* Spin until command processed     */
260                 __asm__ ("eieio");
261         } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG);
262
263         /*
264          * Ethernet Specific Parameter RAM
265          *     see table 13-16, pg. 660,
266          *     pg. 681 (example with suggested settings)
267          */
268
269         pram_ptr->sen_cpres = ~(0x0);   /* Preset CRC */
270         pram_ptr->sen_cmask = 0xdebb20e3;       /* Constant Mask for CRC */
271         pram_ptr->sen_crcec = 0x0;      /* Error Counter CRC (unused) */
272         pram_ptr->sen_alec = 0x0;       /* Alignment Error Counter (unused) */
273         pram_ptr->sen_disfc = 0x0;      /* Discard Frame Counter (unused) */
274         pram_ptr->sen_pads = 0x8888;    /* Short Frame PAD Characters */
275
276         pram_ptr->sen_retlim = 15;      /* Retry Limit Threshold */
277         pram_ptr->sen_maxflr = 1518;    /* MAX Frame Length Register */
278         pram_ptr->sen_minflr = 64;      /* MIN Frame Length Register */
279
280         pram_ptr->sen_maxd1 = DBUF_LENGTH;      /* MAX DMA1 Length Register */
281         pram_ptr->sen_maxd2 = DBUF_LENGTH;      /* MAX DMA2 Length Register */
282
283         pram_ptr->sen_gaddr1 = 0x0;     /* Group Address Filter 1 (unused) */
284         pram_ptr->sen_gaddr2 = 0x0;     /* Group Address Filter 2 (unused) */
285         pram_ptr->sen_gaddr3 = 0x0;     /* Group Address Filter 3 (unused) */
286         pram_ptr->sen_gaddr4 = 0x0;     /* Group Address Filter 4 (unused) */
287
288         eth_getenv_enetaddr("ethaddr", ea);
289         pram_ptr->sen_paddrh = (ea[5] << 8) + ea[4];
290         pram_ptr->sen_paddrm = (ea[3] << 8) + ea[2];
291         pram_ptr->sen_paddrl = (ea[1] << 8) + ea[0];
292
293         pram_ptr->sen_pper = 0x0;       /* Persistence (unused) */
294         pram_ptr->sen_iaddr1 = 0x0;     /* Individual Address Filter 1 (unused) */
295         pram_ptr->sen_iaddr2 = 0x0;     /* Individual Address Filter 2 (unused) */
296         pram_ptr->sen_iaddr3 = 0x0;     /* Individual Address Filter 3 (unused) */
297         pram_ptr->sen_iaddr4 = 0x0;     /* Individual Address Filter 4 (unused) */
298         pram_ptr->sen_taddrh = 0x0;     /* Tmp Address (MSB) (unused) */
299         pram_ptr->sen_taddrm = 0x0;     /* Tmp Address (unused) */
300         pram_ptr->sen_taddrl = 0x0;     /* Tmp Address (LSB) (unused) */
301
302         /*
303          * Enter Command:  Initialize Tx Params for SCC
304          */
305
306         do {                            /* Spin until ready to issue command    */
307                 __asm__ ("eieio");
308         } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG);
309         /* Issue command */
310         immr->im_cpm.cp_cpcr =
311                         ((CPM_CR_INIT_TX << 8) | (cpm_cr[scc_index] << 4) |
312                          CPM_CR_FLG);
313         do {                            /* Spin until command processed     */
314                 __asm__ ("eieio");
315         } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG);
316
317         /*
318          * Mask all Events in SCCM - we use polling mode
319          */
320         immr->im_cpm.cp_scc[scc_index].scc_sccm = 0;
321
322         /*
323          * Clear Events in SCCE -- Clear bits by writing 1's
324          */
325
326         immr->im_cpm.cp_scc[scc_index].scc_scce = ~(0x0);
327
328
329         /*
330          * Initialize GSMR High 32-Bits
331          * Settings:  Normal Mode
332          */
333
334         immr->im_cpm.cp_scc[scc_index].scc_gsmrh = 0;
335
336         /*
337          * Initialize GSMR Low 32-Bits, but do not Enable Transmit/Receive
338          * Settings:
339          *     TCI = Invert
340          *     TPL =  48 bits
341          *     TPP = Repeating 10's
342          *     LOOP = Loopback
343          *     MODE = Ethernet
344          */
345
346         immr->im_cpm.cp_scc[scc_index].scc_gsmrl = (SCC_GSMRL_TCI |
347                                                     SCC_GSMRL_TPL_48 |
348                                                     SCC_GSMRL_TPP_10 |
349                                                     SCC_GSMRL_DIAG_LOOP |
350                                                     SCC_GSMRL_MODE_ENET);
351
352         /*
353          * Initialize the DSR -- see section 13.14.4 (pg. 513) v0.4
354          */
355
356         immr->im_cpm.cp_scc[scc_index].scc_dsr = 0xd555;
357
358         /*
359          * Initialize the PSMR
360          * Settings:
361          *  CRC = 32-Bit CCITT
362          *  NIB = Begin searching for SFD 22 bits after RENA
363          *  LPB = Loopback Enable (Needed when FDE is set)
364          */
365         immr->im_cpm.cp_scc[scc_index].scc_psmr = SCC_PSMR_ENCRC |
366                         SCC_PSMR_NIB22 | SCC_PSMR_LPB;
367
368 #ifdef CONFIG_RPXCLASSIC
369         *((uchar *) BCSR0) &= ~BCSR0_ETHLPBK;
370         *((uchar *) BCSR0) |= (BCSR0_ETHEN | BCSR0_COLTEST | BCSR0_FULLDPLX);
371 #endif
372
373 #ifdef CONFIG_RPXLITE
374         *((uchar *) BCSR0) |= BCSR0_ETHEN;
375 #endif
376
377 #ifdef CONFIG_MBX
378         board_ether_init ();
379 #endif
380
381         /*
382          * Set the ENT/ENR bits in the GSMR Low -- Enable Transmit/Receive
383          */
384
385         immr->im_cpm.cp_scc[scc_index].scc_gsmrl |=
386                         (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
387
388         /*
389          * Work around transmit problem with first eth packet
390          */
391 #if defined (CONFIG_FADS)
392         udelay (10000);                         /* wait 10 ms */
393 #elif defined(CONFIG_RPXCLASSIC)
394         udelay (100000);                        /* wait 100 ms */
395 #endif
396 }
397
398 static void scc_halt (int scc_index)
399 {
400         volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
401
402         immr->im_cpm.cp_scc[scc_index].scc_gsmrl &=
403                         ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
404         immr->im_ioport.iop_pcso  &=  ~(PC_ENET_CLSN | PC_ENET_RENA);
405 }
406
407 static int scc_send (int index, volatile void *packet, int length)
408 {
409         int i, j = 0;
410
411         while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j < TOUT_LOOP)) {
412                 udelay (1);             /* will also trigger Wd if needed */
413                 j++;
414         }
415         if (j >= TOUT_LOOP)
416                 printf ("TX not ready\n");
417         rtx->txbd[txIdx].cbd_bufaddr = (uint) packet;
418         rtx->txbd[txIdx].cbd_datlen = length;
419         rtx->txbd[txIdx].cbd_sc |=
420                         (BD_ENET_TX_READY | BD_ENET_TX_LAST | BD_ENET_TX_WRAP);
421         while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j < TOUT_LOOP)) {
422                 udelay (1);             /* will also trigger Wd if needed */
423                 j++;
424         }
425         if (j >= TOUT_LOOP)
426                 printf ("TX timeout\n");
427         i = (rtx->txbd[txIdx].
428                  cbd_sc & BD_ENET_TX_STATS) /* return only status bits */ ;
429         return i;
430 }
431
432 static int scc_recv (int index, void *packet, int max_length)
433 {
434         int length = -1;
435
436         if (rtx->rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) {
437                 goto Done;              /* nothing received */
438         }
439
440         if (!(rtx->rxbd[rxIdx].cbd_sc & 0x003f)) {
441                 length = rtx->rxbd[rxIdx].cbd_datlen - 4;
442                 memcpy (packet,
443                                 (void *) (NetRxPackets[rxIdx]),
444                                 length < max_length ? length : max_length);
445         }
446
447         /* Give the buffer back to the SCC. */
448         rtx->rxbd[rxIdx].cbd_datlen = 0;
449
450         /* wrap around buffer index when necessary */
451         if ((rxIdx + 1) >= PKTBUFSRX) {
452                 rtx->rxbd[PKTBUFSRX - 1].cbd_sc =
453                                 (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY);
454                 rxIdx = 0;
455         } else {
456                 rtx->rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY;
457                 rxIdx++;
458         }
459
460 Done:
461         return length;
462 }
463
464   /*
465    * Test routines
466    */
467
468 static void packet_fill (char *packet, int length)
469 {
470         char c = (char) length;
471         int i;
472
473         packet[0] = 0xFF;
474         packet[1] = 0xFF;
475         packet[2] = 0xFF;
476         packet[3] = 0xFF;
477         packet[4] = 0xFF;
478         packet[5] = 0xFF;
479
480         for (i = 6; i < length; i++) {
481                 packet[i] = c++;
482         }
483 }
484
485 static int packet_check (char *packet, int length)
486 {
487         char c = (char) length;
488         int i;
489
490         for (i = 6; i < length; i++) {
491                 if (packet[i] != c++)
492                         return -1;
493         }
494
495         return 0;
496 }
497
498 static int test_ctlr (int ctlr, int index)
499 {
500         int res = -1;
501         char packet_send[MAX_PACKET_LENGTH];
502         char packet_recv[MAX_PACKET_LENGTH];
503         int length;
504         int i;
505         int l;
506
507         ctlr_proc[ctlr].init (index);
508
509         for (i = 0; i < TEST_NUM; i++) {
510                 for (l = MIN_PACKET_LENGTH; l <= MAX_PACKET_LENGTH; l++) {
511                         packet_fill (packet_send, l);
512
513                         ctlr_proc[ctlr].send (index, packet_send, l);
514
515                         length = ctlr_proc[ctlr].recv (index, packet_recv,
516                                                         MAX_PACKET_LENGTH);
517
518                         if (length != l || packet_check (packet_recv, length) < 0) {
519                                 goto Done;
520                         }
521                 }
522         }
523
524         res = 0;
525
526 Done:
527
528         ctlr_proc[ctlr].halt (index);
529
530         /*
531          * SCC2 Ethernet parameter RAM space overlaps
532          * the SPI parameter RAM space. So we need to restore
533          * the SPI configuration after SCC2 ethernet test.
534          */
535 #if defined(CONFIG_SPI)
536         if (ctlr == CTLR_SCC && index == 1) {
537                 spi_init_f ();
538                 spi_init_r ();
539         }
540 #endif
541
542         if (res != 0) {
543                 post_log ("ethernet %s%d test failed\n", ctlr_name[ctlr],
544                                   index + 1);
545         }
546
547         return res;
548 }
549
550 int ether_post_test (int flags)
551 {
552         int res = 0;
553         int i;
554
555         ctlr_proc[CTLR_SCC].init = scc_init;
556         ctlr_proc[CTLR_SCC].halt = scc_halt;
557         ctlr_proc[CTLR_SCC].send = scc_send;
558         ctlr_proc[CTLR_SCC].recv = scc_recv;
559
560         for (i = 0; i < ARRAY_SIZE(ctlr_list); i++) {
561                 if (test_ctlr (ctlr_list[i][0], ctlr_list[i][1]) != 0) {
562                         res = -1;
563                 }
564         }
565
566 #if !defined(CONFIG_8xx_CONS_NONE)
567         serial_reinit_all ();
568 #endif
569         return res;
570 }
571
572 #endif /* CONFIG_POST & CONFIG_SYS_POST_ETHER */