]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - post/cpu/ppc4xx/ether.c
ppc4xx/POST: Change ethernet test loop count to a default of 10
[karo-tx-uboot.git] / post / cpu / ppc4xx / ether.c
1 /*
2  * (C) Copyright 2007
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * Author: Igor Lisitsin <igor@emcraft.com>
6  *
7  * See file CREDITS for list of people who contributed to this
8  * project.
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License as
12  * published by the Free Software Foundation; either version 2 of
13  * the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23  * MA 02111-1307 USA
24  */
25
26 #include <common.h>
27
28 /*
29  * Ethernet test
30  *
31  * The Ethernet Media Access Controllers (EMAC) are tested in the
32  * internal loopback mode.
33  * The controllers are configured accordingly and several packets
34  * are transmitted. The configurable test parameters are:
35  *   MIN_PACKET_LENGTH - minimum size of packet to transmit
36  *   MAX_PACKET_LENGTH - maximum size of packet to transmit
37  *   CONFIG_SYS_POST_ETH_LOOPS - Number of test loops. Each loop
38  *     is tested with a different frame length. Starting with
39  *     MAX_PACKET_LENGTH and going down to MIN_PACKET_LENGTH.
40  *     Defaults to 10 and can be overriden in the board config header.
41  */
42
43 #include <post.h>
44
45 #if CONFIG_POST & CONFIG_SYS_POST_ETHER
46
47 #include <asm/cache.h>
48 #include <asm/io.h>
49 #include <asm/processor.h>
50 #include <asm/ppc4xx-mal.h>
51 #include <asm/ppc4xx-emac.h>
52 #include <malloc.h>
53
54 DECLARE_GLOBAL_DATA_PTR;
55
56 /*
57  * Get count of EMAC devices (doesn't have to be the max. possible number
58  * supported by the cpu)
59  *
60  * CONFIG_BOARD_EMAC_COUNT added so now a "dynamic" way to configure the
61  * EMAC count is possible. As it is needed for the Kilauea/Haleakala
62  * 405EX/405EXr eval board, using the same binary.
63  */
64 #if defined(CONFIG_BOARD_EMAC_COUNT)
65 #define LAST_EMAC_NUM   board_emac_count()
66 #else /* CONFIG_BOARD_EMAC_COUNT */
67 #if defined(CONFIG_HAS_ETH3)
68 #define LAST_EMAC_NUM   4
69 #elif defined(CONFIG_HAS_ETH2)
70 #define LAST_EMAC_NUM   3
71 #elif defined(CONFIG_HAS_ETH1)
72 #define LAST_EMAC_NUM   2
73 #else
74 #define LAST_EMAC_NUM   1
75 #endif
76 #endif /* CONFIG_BOARD_EMAC_COUNT */
77
78 #if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
79 #define SDR0_MFR_ETH_CLK_SEL_V(n)       ((0x01<<27) / (n+1))
80 #endif
81
82 #define MIN_PACKET_LENGTH       64
83 #define MAX_PACKET_LENGTH       1514
84 #ifndef CONFIG_SYS_POST_ETH_LOOPS
85 #define CONFIG_SYS_POST_ETH_LOOPS       10
86 #endif
87 #define PACKET_INCR     ((MAX_PACKET_LENGTH - MIN_PACKET_LENGTH) / \
88                          CONFIG_SYS_POST_ETH_LOOPS)
89
90 static volatile mal_desc_t tx __cacheline_aligned;
91 static volatile mal_desc_t rx __cacheline_aligned;
92 static char *tx_buf;
93 static char *rx_buf;
94
95 int board_emac_count(void);
96
97 static void ether_post_init (int devnum, int hw_addr)
98 {
99         int i;
100 #if defined(CONFIG_440GX) || \
101     defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
102     defined(CONFIG_440SP) || defined(CONFIG_440SPE)
103         unsigned mode_reg;
104         sys_info_t sysinfo;
105 #endif
106 #if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || defined(CONFIG_440SPE)
107         unsigned long mfr;
108 #endif
109
110 #if defined(CONFIG_440GX) || \
111     defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
112     defined(CONFIG_440SP) || defined(CONFIG_440SPE)
113         /* Need to get the OPB frequency so we can access the PHY */
114         get_sys_info (&sysinfo);
115 #endif
116
117 #if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
118         /* provide clocks for EMAC internal loopback  */
119         mfsdr (SDR0_MFR, mfr);
120         mfr |= SDR0_MFR_ETH_CLK_SEL_V(devnum);
121         mtsdr (SDR0_MFR, mfr);
122         sync ();
123 #endif
124         /* reset emac */
125         out_be32 ((void*)(EMAC0_MR0 + hw_addr), EMAC_MR0_SRST);
126         sync ();
127
128         for (i = 0;; i++) {
129                 if (!(in_be32 ((void*)(EMAC0_MR0 + hw_addr)) & EMAC_MR0_SRST))
130                         break;
131                 if (i >= 1000) {
132                         printf ("Timeout resetting EMAC\n");
133                         break;
134                 }
135                 udelay (1000);
136         }
137 #if defined(CONFIG_440GX) || \
138     defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
139     defined(CONFIG_440SP) || defined(CONFIG_440SPE)
140         /* Whack the M1 register */
141         mode_reg = 0x0;
142         if (sysinfo.freqOPB <= 50000000);
143         else if (sysinfo.freqOPB <= 66666667)
144                 mode_reg |= EMAC_MR1_OBCI_66;
145         else if (sysinfo.freqOPB <= 83333333)
146                 mode_reg |= EMAC_MR1_OBCI_83;
147         else if (sysinfo.freqOPB <= 100000000)
148                 mode_reg |= EMAC_MR1_OBCI_100;
149         else
150                 mode_reg |= EMAC_MR1_OBCI_GT100;
151
152         out_be32 ((void*)(EMAC0_MR1 + hw_addr), mode_reg);
153
154 #endif /* defined(CONFIG_440GX) || defined(CONFIG_440SP) */
155
156         /* set the Mal configuration reg */
157 #if defined(CONFIG_440GX) || \
158     defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
159     defined(CONFIG_440SP) || defined(CONFIG_440SPE)
160         mtdcr (MAL0_CFG, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA |
161                MAL_CR_PLBLT_DEFAULT | 0x00330000);
162 #else
163         mtdcr (MAL0_CFG, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA | MAL_CR_PLBLT_DEFAULT);
164         /* Errata 1.12: MAL_1 -- Disable MAL bursting */
165         if (get_pvr() == PVR_440GP_RB) {
166                 mtdcr (MAL0_CFG, mfdcr(MAL0_CFG) & ~MAL_CR_PLBB);
167         }
168 #endif
169         /* setup buffer descriptors */
170         tx.ctrl = MAL_TX_CTRL_WRAP;
171         tx.data_len = 0;
172         tx.data_ptr = (char*)L1_CACHE_ALIGN((u32)tx_buf);
173
174         rx.ctrl = MAL_TX_CTRL_WRAP | MAL_RX_CTRL_EMPTY;
175         rx.data_len = 0;
176         rx.data_ptr = (char*)L1_CACHE_ALIGN((u32)rx_buf);
177         flush_dcache_range((u32)&rx, (u32)&rx + sizeof(mal_desc_t));
178         flush_dcache_range((u32)&tx, (u32)&tx + sizeof(mal_desc_t));
179
180         switch (devnum) {
181         case 1:
182                 /* setup MAL tx & rx channel pointers */
183 #if defined (CONFIG_405EP) || defined (CONFIG_440EP) || defined (CONFIG_440GR)
184                 mtdcr (MAL0_TXCTP2R, &tx);
185 #else
186                 mtdcr (MAL0_TXCTP1R, &tx);
187 #endif
188 #if defined(CONFIG_440)
189                 mtdcr (MAL0_TXBADDR, 0x0);
190                 mtdcr (MAL0_RXBADDR, 0x0);
191 #endif
192                 mtdcr (MAL0_RXCTP1R, &rx);
193                 /* set RX buffer size */
194                 mtdcr (MAL0_RCBS1, PKTSIZE_ALIGN / 16);
195                 break;
196         case 0:
197         default:
198                 /* setup MAL tx & rx channel pointers */
199 #if defined(CONFIG_440)
200                 mtdcr (MAL0_TXBADDR, 0x0);
201                 mtdcr (MAL0_RXBADDR, 0x0);
202 #endif
203                 mtdcr (MAL0_TXCTP0R, &tx);
204                 mtdcr (MAL0_RXCTP0R, &rx);
205                 /* set RX buffer size */
206                 mtdcr (MAL0_RCBS0, PKTSIZE_ALIGN / 16);
207                 break;
208         }
209
210         /* Enable MAL transmit and receive channels */
211 #if defined(CONFIG_405EP) || defined(CONFIG_440EP) || defined(CONFIG_440GR)
212         mtdcr (MAL0_TXCASR, (MAL_TXRX_CASR >> (devnum*2)));
213 #else
214         mtdcr (MAL0_TXCASR, (MAL_TXRX_CASR >> devnum));
215 #endif
216         mtdcr (MAL0_RXCASR, (MAL_TXRX_CASR >> devnum));
217
218         /* set internal loopback mode */
219 #ifdef CONFIG_SYS_POST_ETHER_EXT_LOOPBACK
220         out_be32 ((void*)(EMAC0_MR1 + hw_addr), EMAC_MR1_FDE | 0 |
221                   EMAC_MR1_RFS_4K | EMAC_MR1_TX_FIFO_2K |
222                   EMAC_MR1_MF_100MBPS | EMAC_MR1_IST |
223                   in_be32 ((void*)(EMAC0_MR1 + hw_addr)));
224 #else
225         out_be32 ((void*)(EMAC0_MR1 + hw_addr), EMAC_MR1_FDE | EMAC_MR1_ILE |
226                   EMAC_MR1_RFS_4K | EMAC_MR1_TX_FIFO_2K |
227                   EMAC_MR1_MF_100MBPS | EMAC_MR1_IST |
228                   in_be32 ((void*)(EMAC0_MR1 + hw_addr)));
229 #endif
230
231         /* set transmit enable & receive enable */
232         out_be32 ((void*)(EMAC0_MR0 + hw_addr), EMAC_MR0_TXE | EMAC_MR0_RXE);
233
234         /* enable broadcast address */
235         out_be32 ((void*)(EMAC0_RXM + hw_addr), EMAC_RMR_BAE);
236
237         /* set transmit request threshold register */
238         out_be32 ((void*)(EMAC0_TRTR + hw_addr), 0x18000000);   /* 256 byte threshold */
239
240         /* set receive  low/high water mark register */
241 #if defined(CONFIG_440)
242         /* 440s has a 64 byte burst length */
243         out_be32 ((void*)(EMAC0_RX_HI_LO_WMARK + hw_addr), 0x80009000);
244 #else
245         /* 405s have a 16 byte burst length */
246         out_be32 ((void*)(EMAC0_RX_HI_LO_WMARK + hw_addr), 0x0f002000);
247 #endif /* defined(CONFIG_440) */
248         out_be32 ((void*)(EMAC0_TMR1 + hw_addr), 0xf8640000);
249
250         /* Set fifo limit entry in tx mode 0 */
251         out_be32 ((void*)(EMAC0_TMR0 + hw_addr), 0x00000003);
252         /* Frame gap set */
253         out_be32 ((void*)(EMAC0_I_FRAME_GAP_REG + hw_addr), 0x00000008);
254         sync ();
255 }
256
257 static void ether_post_halt (int devnum, int hw_addr)
258 {
259         int i = 0;
260 #if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
261         unsigned long mfr;
262 #endif
263
264         /* 1st reset MAL channel */
265         /* Note: writing a 0 to a channel has no effect */
266 #if defined(CONFIG_405EP) || defined(CONFIG_440EP) || defined(CONFIG_440GR)
267         mtdcr (MAL0_TXCARR, MAL_TXRX_CASR >> (devnum * 2));
268 #else
269         mtdcr (MAL0_TXCARR, MAL_TXRX_CASR >> devnum);
270 #endif
271         mtdcr (MAL0_RXCARR, MAL_TXRX_CASR >> devnum);
272
273         /* wait for reset */
274         while (mfdcr (MAL0_RXCASR) & (MAL_TXRX_CASR >> devnum)) {
275                 if (i++ >= 1000)
276                         break;
277                 udelay (1000);
278         }
279         /* emac reset */
280         out_be32 ((void*)(EMAC0_MR0 + hw_addr), EMAC_MR0_SRST);
281
282 #if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
283         /* remove clocks for EMAC internal loopback  */
284         mfsdr (SDR0_MFR, mfr);
285         mfr &= ~SDR0_MFR_ETH_CLK_SEL_V(devnum);
286         mtsdr (SDR0_MFR, mfr);
287 #endif
288 }
289
290 static void ether_post_send (int devnum, int hw_addr, void *packet, int length)
291 {
292         int i = 0;
293
294         while (tx.ctrl & MAL_TX_CTRL_READY) {
295                 if (i++ > 100) {
296                         printf ("TX timeout\n");
297                         return;
298                 }
299                 udelay (1000);
300                 invalidate_dcache_range((u32)&tx, (u32)&tx + sizeof(mal_desc_t));
301         }
302         tx.ctrl = MAL_TX_CTRL_READY | MAL_TX_CTRL_WRAP | MAL_TX_CTRL_LAST |
303                 EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP;
304         tx.data_len = length;
305         memcpy (tx.data_ptr, packet, length);
306         flush_dcache_range((u32)&tx, (u32)&tx + sizeof(mal_desc_t));
307         flush_dcache_range((u32)tx.data_ptr, (u32)tx.data_ptr + length);
308         sync ();
309
310         out_be32 ((void*)(EMAC0_TMR0 + hw_addr), in_be32 ((void*)(EMAC0_TMR0 + hw_addr)) | EMAC_TMR0_GNP0);
311         sync ();
312 }
313
314 static int ether_post_recv (int devnum, int hw_addr, void *packet, int max_length)
315 {
316         int length;
317         int i = 0;
318
319         while (rx.ctrl & MAL_RX_CTRL_EMPTY) {
320                 if (i++ > 100) {
321                         printf ("RX timeout\n");
322                         return 0;
323                 }
324                 udelay (1000);
325                 invalidate_dcache_range((u32)&rx, (u32)&rx + sizeof(mal_desc_t));
326         }
327         length = rx.data_len - 4;
328         if (length <= max_length) {
329                 invalidate_dcache_range((u32)rx.data_ptr, (u32)rx.data_ptr + length);
330                 memcpy(packet, rx.data_ptr, length);
331         }
332         sync ();
333
334         rx.ctrl |= MAL_RX_CTRL_EMPTY;
335         flush_dcache_range((u32)&rx, (u32)&rx + sizeof(mal_desc_t));
336         sync ();
337
338         return length;
339 }
340
341   /*
342    * Test routines
343    */
344
345 static void packet_fill (char *packet, int length)
346 {
347         char c = (char) length;
348         int i;
349
350         /* set up ethernet header */
351         memset (packet, 0xff, 14);
352
353         for (i = 14; i < length; i++) {
354                 packet[i] = c++;
355         }
356 }
357
358 static int packet_check (char *packet, int length)
359 {
360         char c = (char) length;
361         int i;
362
363         for (i = 14; i < length; i++) {
364                 if (packet[i] != c++)
365                         return -1;
366         }
367
368         return 0;
369 }
370
371         char packet_send[MAX_PACKET_LENGTH];
372         char packet_recv[MAX_PACKET_LENGTH];
373 static int test_ctlr (int devnum, int hw_addr)
374 {
375         int res = -1;
376         int length;
377         int l;
378
379         ether_post_init (devnum, hw_addr);
380
381         for (l = MAX_PACKET_LENGTH; l >= MIN_PACKET_LENGTH;
382              l -= PACKET_INCR) {
383                 packet_fill (packet_send, l);
384
385                 ether_post_send (devnum, hw_addr, packet_send, l);
386
387                 length = ether_post_recv (devnum, hw_addr, packet_recv,
388                                           sizeof (packet_recv));
389
390                 if (length != l || packet_check (packet_recv, length) < 0) {
391                         goto Done;
392                 }
393         }
394
395         res = 0;
396
397 Done:
398
399         ether_post_halt (devnum, hw_addr);
400
401         if (res != 0) {
402                 post_log ("EMAC%d test failed\n", devnum);
403         }
404
405         return res;
406 }
407
408 int ether_post_test (int flags)
409 {
410         int res = 0;
411         int i;
412
413         /* Allocate tx & rx packet buffers */
414         tx_buf = malloc (PKTSIZE_ALIGN + CONFIG_SYS_CACHELINE_SIZE);
415         rx_buf = malloc (PKTSIZE_ALIGN + CONFIG_SYS_CACHELINE_SIZE);
416
417         if (!tx_buf || !rx_buf) {
418                 printf ("Failed to allocate packet buffers\n");
419                 res = -1;
420                 goto out_free;
421         }
422
423         for (i = 0; i < LAST_EMAC_NUM; i++) {
424                 if (test_ctlr (i, i*0x100))
425                         res = -1;
426         }
427
428 out_free:
429         free (tx_buf);
430         free (rx_buf);
431
432         return res;
433 }
434
435 #endif /* CONFIG_POST & CONFIG_SYS_POST_ETHER */