]>
git.ipfire.org Git - people/ms/u-boot.git/blob - post/cpu/mpc8xx/ether.c
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5 * SPDX-License-Identifier: GPL-2.0+
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
23 #if CONFIG_POST & CONFIG_SYS_POST_ETHER
24 #if defined(CONFIG_8xx)
26 #elif defined(CONFIG_MPC8260)
27 #include <asm/cpm_8260.h>
29 #error "Apparently a bad configuration, please fix."
36 DECLARE_GLOBAL_DATA_PTR
;
38 #define MIN_PACKET_LENGTH 64
39 #define MAX_PACKET_LENGTH 256
44 extern void spi_init_f (void);
45 extern void spi_init_r (void);
47 /* The list of controllers to test */
48 #if defined(CONFIG_MPC823)
49 static int ctlr_list
[][2] = { {CTLR_SCC
, 1} };
51 static int ctlr_list
[][2] = { };
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
);
61 static char *ctlr_name
[1] = { "SCC" };
63 /* Ethernet Transmit and Receive Buffers */
64 #define DBUF_LENGTH 1520
70 static char txbuf
[DBUF_LENGTH
];
72 static uint rxIdx
; /* index of the current RX buffer */
73 static uint txIdx
; /* index of the current TX buffer */
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
81 typedef volatile struct CommonBufferDescriptor
{
82 cbd_t rxbd
[PKTBUFSRX
]; /* Rx BD */
83 cbd_t txbd
[TX_BUF_CNT
]; /* Tx BD */
92 static void scc_init (int scc_index
)
96 static int proff
[] = {
102 static unsigned int cpm_cr
[] = {
110 scc_enet_t
*pram_ptr
;
112 volatile immap_t
*immr
= (immap_t
*) CONFIG_SYS_IMMR
;
114 immr
->im_cpm
.cp_scc
[scc_index
].scc_gsmrl
&=
115 ~(SCC_GSMRL_ENR
| SCC_GSMRL_ENT
);
117 pram_ptr
= (scc_enet_t
*) & (immr
->im_cpm
.cp_dparam
[proff
[scc_index
]]);
122 rtx
= (RTXBD
*) (immr
->im_cpm
.cp_dpmem
+ CPM_SCC_BASE
);
126 #if (defined(PA_ENET_RXD) && defined(PA_ENET_TXD))
127 /* Configure port A pins for Txd and Rxd.
129 immr
->im_ioport
.iop_papar
|= (PA_ENET_RXD
| PA_ENET_TXD
);
130 immr
->im_ioport
.iop_padir
&= ~(PA_ENET_RXD
| PA_ENET_TXD
);
131 immr
->im_ioport
.iop_paodr
&= ~PA_ENET_TXD
;
132 #elif (defined(PB_ENET_RXD) && defined(PB_ENET_TXD))
133 /* Configure port B pins for Txd and Rxd.
135 immr
->im_cpm
.cp_pbpar
|= (PB_ENET_RXD
| PB_ENET_TXD
);
136 immr
->im_cpm
.cp_pbdir
&= ~(PB_ENET_RXD
| PB_ENET_TXD
);
137 immr
->im_cpm
.cp_pbodr
&= ~PB_ENET_TXD
;
139 #error Configuration Error: exactly ONE of PA_ENET_[RT]XD, PB_ENET_[RT]XD must be defined
142 #if defined(PC_ENET_LBK)
143 /* Configure port C pins to disable External Loopback
145 immr
->im_ioport
.iop_pcpar
&= ~PC_ENET_LBK
;
146 immr
->im_ioport
.iop_pcdir
|= PC_ENET_LBK
;
147 immr
->im_ioport
.iop_pcso
&= ~PC_ENET_LBK
;
148 immr
->im_ioport
.iop_pcdat
&= ~PC_ENET_LBK
; /* Disable Loopback */
149 #endif /* PC_ENET_LBK */
151 /* Configure port C pins to enable CLSN and RENA.
153 immr
->im_ioport
.iop_pcpar
&= ~(PC_ENET_CLSN
| PC_ENET_RENA
);
154 immr
->im_ioport
.iop_pcdir
&= ~(PC_ENET_CLSN
| PC_ENET_RENA
);
155 immr
->im_ioport
.iop_pcso
|= (PC_ENET_CLSN
| PC_ENET_RENA
);
157 /* Configure port A for TCLK and RCLK.
159 immr
->im_ioport
.iop_papar
|= (PA_ENET_TCLK
| PA_ENET_RCLK
);
160 immr
->im_ioport
.iop_padir
&= ~(PA_ENET_TCLK
| PA_ENET_RCLK
);
163 * Configure Serial Interface clock routing -- see section 16.7.5.3
164 * First, clear all SCC bits to zero, then set the ones we want.
167 immr
->im_cpm
.cp_sicr
&= ~SICR_ENET_MASK
;
168 immr
->im_cpm
.cp_sicr
|= SICR_ENET_CLKRT
;
171 * SCC2 receive clock is BRG2
172 * SCC2 transmit clock is BRG3
174 immr
->im_cpm
.cp_brgc2
= 0x0001000C;
175 immr
->im_cpm
.cp_brgc3
= 0x0001000C;
177 immr
->im_cpm
.cp_sicr
&= ~0x00003F00;
178 immr
->im_cpm
.cp_sicr
|= 0x00000a00;
183 * Initialize SDCR -- see section 16.9.23.7
184 * SDMA configuration register
186 immr
->im_siu_conf
.sc_sdcr
= 0x01;
190 * Setup SCC Ethernet Parameter RAM
193 pram_ptr
->sen_genscc
.scc_rfcr
= 0x18; /* Normal Operation and Mot byte ordering */
194 pram_ptr
->sen_genscc
.scc_tfcr
= 0x18; /* Mot byte ordering, Normal access */
196 pram_ptr
->sen_genscc
.scc_mrblr
= DBUF_LENGTH
; /* max. ET package len 1520 */
198 pram_ptr
->sen_genscc
.scc_rbase
= (unsigned int) (&rtx
->rxbd
[0]); /* Set RXBD tbl start at Dual Port */
199 pram_ptr
->sen_genscc
.scc_tbase
= (unsigned int) (&rtx
->txbd
[0]); /* Set TXBD tbl start at Dual Port */
202 * Setup Receiver Buffer Descriptors (13.14.24.18)
207 for (i
= 0; i
< PKTBUFSRX
; i
++) {
208 rtx
->rxbd
[i
].cbd_sc
= BD_ENET_RX_EMPTY
;
209 rtx
->rxbd
[i
].cbd_datlen
= 0; /* Reset */
210 rtx
->rxbd
[i
].cbd_bufaddr
= (uint
) net_rx_packets
[i
];
213 rtx
->rxbd
[PKTBUFSRX
- 1].cbd_sc
|= BD_ENET_RX_WRAP
;
216 * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19)
218 * Add PADs to Short FRAMES, Wrap, Last, Tx CRC
221 for (i
= 0; i
< TX_BUF_CNT
; i
++) {
222 rtx
->txbd
[i
].cbd_sc
=
223 (BD_ENET_TX_PAD
| BD_ENET_TX_LAST
| BD_ENET_TX_TC
);
224 rtx
->txbd
[i
].cbd_datlen
= 0; /* Reset */
225 rtx
->txbd
[i
].cbd_bufaddr
= (uint
) (&txbuf
[0]);
228 rtx
->txbd
[TX_BUF_CNT
- 1].cbd_sc
|= BD_ENET_TX_WRAP
;
231 * Enter Command: Initialize Rx Params for SCC
234 do { /* Spin until ready to issue command */
236 } while (immr
->im_cpm
.cp_cpcr
& CPM_CR_FLG
);
238 immr
->im_cpm
.cp_cpcr
=
239 ((CPM_CR_INIT_RX
<< 8) | (cpm_cr
[scc_index
] << 4) |
241 do { /* Spin until command processed */
243 } while (immr
->im_cpm
.cp_cpcr
& CPM_CR_FLG
);
246 * Ethernet Specific Parameter RAM
247 * see table 13-16, pg. 660,
248 * pg. 681 (example with suggested settings)
251 pram_ptr
->sen_cpres
= ~(0x0); /* Preset CRC */
252 pram_ptr
->sen_cmask
= 0xdebb20e3; /* Constant Mask for CRC */
253 pram_ptr
->sen_crcec
= 0x0; /* Error Counter CRC (unused) */
254 pram_ptr
->sen_alec
= 0x0; /* Alignment Error Counter (unused) */
255 pram_ptr
->sen_disfc
= 0x0; /* Discard Frame Counter (unused) */
256 pram_ptr
->sen_pads
= 0x8888; /* Short Frame PAD Characters */
258 pram_ptr
->sen_retlim
= 15; /* Retry Limit Threshold */
259 pram_ptr
->sen_maxflr
= 1518; /* MAX Frame Length Register */
260 pram_ptr
->sen_minflr
= 64; /* MIN Frame Length Register */
262 pram_ptr
->sen_maxd1
= DBUF_LENGTH
; /* MAX DMA1 Length Register */
263 pram_ptr
->sen_maxd2
= DBUF_LENGTH
; /* MAX DMA2 Length Register */
265 pram_ptr
->sen_gaddr1
= 0x0; /* Group Address Filter 1 (unused) */
266 pram_ptr
->sen_gaddr2
= 0x0; /* Group Address Filter 2 (unused) */
267 pram_ptr
->sen_gaddr3
= 0x0; /* Group Address Filter 3 (unused) */
268 pram_ptr
->sen_gaddr4
= 0x0; /* Group Address Filter 4 (unused) */
270 eth_getenv_enetaddr("ethaddr", ea
);
271 pram_ptr
->sen_paddrh
= (ea
[5] << 8) + ea
[4];
272 pram_ptr
->sen_paddrm
= (ea
[3] << 8) + ea
[2];
273 pram_ptr
->sen_paddrl
= (ea
[1] << 8) + ea
[0];
275 pram_ptr
->sen_pper
= 0x0; /* Persistence (unused) */
276 pram_ptr
->sen_iaddr1
= 0x0; /* Individual Address Filter 1 (unused) */
277 pram_ptr
->sen_iaddr2
= 0x0; /* Individual Address Filter 2 (unused) */
278 pram_ptr
->sen_iaddr3
= 0x0; /* Individual Address Filter 3 (unused) */
279 pram_ptr
->sen_iaddr4
= 0x0; /* Individual Address Filter 4 (unused) */
280 pram_ptr
->sen_taddrh
= 0x0; /* Tmp Address (MSB) (unused) */
281 pram_ptr
->sen_taddrm
= 0x0; /* Tmp Address (unused) */
282 pram_ptr
->sen_taddrl
= 0x0; /* Tmp Address (LSB) (unused) */
285 * Enter Command: Initialize Tx Params for SCC
288 do { /* Spin until ready to issue command */
290 } while (immr
->im_cpm
.cp_cpcr
& CPM_CR_FLG
);
292 immr
->im_cpm
.cp_cpcr
=
293 ((CPM_CR_INIT_TX
<< 8) | (cpm_cr
[scc_index
] << 4) |
295 do { /* Spin until command processed */
297 } while (immr
->im_cpm
.cp_cpcr
& CPM_CR_FLG
);
300 * Mask all Events in SCCM - we use polling mode
302 immr
->im_cpm
.cp_scc
[scc_index
].scc_sccm
= 0;
305 * Clear Events in SCCE -- Clear bits by writing 1's
308 immr
->im_cpm
.cp_scc
[scc_index
].scc_scce
= ~(0x0);
312 * Initialize GSMR High 32-Bits
313 * Settings: Normal Mode
316 immr
->im_cpm
.cp_scc
[scc_index
].scc_gsmrh
= 0;
319 * Initialize GSMR Low 32-Bits, but do not Enable Transmit/Receive
323 * TPP = Repeating 10's
328 immr
->im_cpm
.cp_scc
[scc_index
].scc_gsmrl
= (SCC_GSMRL_TCI
|
331 SCC_GSMRL_DIAG_LOOP
|
332 SCC_GSMRL_MODE_ENET
);
335 * Initialize the DSR -- see section 13.14.4 (pg. 513) v0.4
338 immr
->im_cpm
.cp_scc
[scc_index
].scc_dsr
= 0xd555;
341 * Initialize the PSMR
344 * NIB = Begin searching for SFD 22 bits after RENA
345 * LPB = Loopback Enable (Needed when FDE is set)
347 immr
->im_cpm
.cp_scc
[scc_index
].scc_psmr
= SCC_PSMR_ENCRC
|
348 SCC_PSMR_NIB22
| SCC_PSMR_LPB
;
351 * Set the ENT/ENR bits in the GSMR Low -- Enable Transmit/Receive
354 immr
->im_cpm
.cp_scc
[scc_index
].scc_gsmrl
|=
355 (SCC_GSMRL_ENR
| SCC_GSMRL_ENT
);
358 static void scc_halt (int scc_index
)
360 volatile immap_t
*immr
= (immap_t
*) CONFIG_SYS_IMMR
;
362 immr
->im_cpm
.cp_scc
[scc_index
].scc_gsmrl
&=
363 ~(SCC_GSMRL_ENR
| SCC_GSMRL_ENT
);
364 immr
->im_ioport
.iop_pcso
&= ~(PC_ENET_CLSN
| PC_ENET_RENA
);
367 static int scc_send (int index
, volatile void *packet
, int length
)
371 while ((rtx
->txbd
[txIdx
].cbd_sc
& BD_ENET_TX_READY
) && (j
< TOUT_LOOP
)) {
372 udelay (1); /* will also trigger Wd if needed */
376 printf ("TX not ready\n");
377 rtx
->txbd
[txIdx
].cbd_bufaddr
= (uint
) packet
;
378 rtx
->txbd
[txIdx
].cbd_datlen
= length
;
379 rtx
->txbd
[txIdx
].cbd_sc
|=
380 (BD_ENET_TX_READY
| BD_ENET_TX_LAST
| BD_ENET_TX_WRAP
);
381 while ((rtx
->txbd
[txIdx
].cbd_sc
& BD_ENET_TX_READY
) && (j
< TOUT_LOOP
)) {
382 udelay (1); /* will also trigger Wd if needed */
386 printf ("TX timeout\n");
387 i
= (rtx
->txbd
[txIdx
].
388 cbd_sc
& BD_ENET_TX_STATS
) /* return only status bits */ ;
392 static int scc_recv (int index
, void *packet
, int max_length
)
396 if (rtx
->rxbd
[rxIdx
].cbd_sc
& BD_ENET_RX_EMPTY
) {
397 goto Done
; /* nothing received */
400 if (!(rtx
->rxbd
[rxIdx
].cbd_sc
& 0x003f)) {
401 length
= rtx
->rxbd
[rxIdx
].cbd_datlen
- 4;
403 (void *)(net_rx_packets
[rxIdx
]),
404 length
< max_length
? length
: max_length
);
407 /* Give the buffer back to the SCC. */
408 rtx
->rxbd
[rxIdx
].cbd_datlen
= 0;
410 /* wrap around buffer index when necessary */
411 if ((rxIdx
+ 1) >= PKTBUFSRX
) {
412 rtx
->rxbd
[PKTBUFSRX
- 1].cbd_sc
=
413 (BD_ENET_RX_WRAP
| BD_ENET_RX_EMPTY
);
416 rtx
->rxbd
[rxIdx
].cbd_sc
= BD_ENET_RX_EMPTY
;
428 static void packet_fill (char *packet
, int length
)
430 char c
= (char) length
;
440 for (i
= 6; i
< length
; i
++) {
445 static int packet_check (char *packet
, int length
)
447 char c
= (char) length
;
450 for (i
= 6; i
< length
; i
++) {
451 if (packet
[i
] != c
++)
458 static int test_ctlr (int ctlr
, int index
)
461 char packet_send
[MAX_PACKET_LENGTH
];
462 char packet_recv
[MAX_PACKET_LENGTH
];
467 ctlr_proc
[ctlr
].init (index
);
469 for (i
= 0; i
< TEST_NUM
; i
++) {
470 for (l
= MIN_PACKET_LENGTH
; l
<= MAX_PACKET_LENGTH
; l
++) {
471 packet_fill (packet_send
, l
);
473 ctlr_proc
[ctlr
].send (index
, packet_send
, l
);
475 length
= ctlr_proc
[ctlr
].recv (index
, packet_recv
,
478 if (length
!= l
|| packet_check (packet_recv
, length
) < 0) {
488 ctlr_proc
[ctlr
].halt (index
);
491 * SCC2 Ethernet parameter RAM space overlaps
492 * the SPI parameter RAM space. So we need to restore
493 * the SPI configuration after SCC2 ethernet test.
495 #if defined(CONFIG_SPI)
496 if (ctlr
== CTLR_SCC
&& index
== 1) {
503 post_log ("ethernet %s%d test failed\n", ctlr_name
[ctlr
],
510 int ether_post_test (int flags
)
515 ctlr_proc
[CTLR_SCC
].init
= scc_init
;
516 ctlr_proc
[CTLR_SCC
].halt
= scc_halt
;
517 ctlr_proc
[CTLR_SCC
].send
= scc_send
;
518 ctlr_proc
[CTLR_SCC
].recv
= scc_recv
;
520 for (i
= 0; i
< ARRAY_SIZE(ctlr_list
); i
++) {
521 if (test_ctlr (ctlr_list
[i
][0], ctlr_list
[i
][1]) != 0) {
526 #if !defined(CONFIG_8xx_CONS_NONE)
527 serial_reinit_all ();
532 #endif /* CONFIG_POST & CONFIG_SYS_POST_ETHER */