ether.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  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. #include <common.h>
  26. /*
  27. * Ethernet test
  28. *
  29. * The Ethernet Media Access Controllers (EMAC) are tested in the
  30. * internal loopback mode.
  31. * The controllers are configured accordingly and several packets
  32. * are transmitted. The configurable test parameters are:
  33. * MIN_PACKET_LENGTH - minimum size of packet to transmit
  34. * MAX_PACKET_LENGTH - maximum size of packet to transmit
  35. * TEST_NUM - number of tests
  36. */
  37. #include <post.h>
  38. #if CONFIG_POST & CONFIG_SYS_POST_ETHER
  39. #include <asm/cache.h>
  40. #include <asm/io.h>
  41. #include <asm/processor.h>
  42. #include <405_mal.h>
  43. #include <ppc4xx_enet.h>
  44. #include <malloc.h>
  45. DECLARE_GLOBAL_DATA_PTR;
  46. /*
  47. * Get count of EMAC devices (doesn't have to be the max. possible number
  48. * supported by the cpu)
  49. *
  50. * CONFIG_BOARD_EMAC_COUNT added so now a "dynamic" way to configure the
  51. * EMAC count is possible. As it is needed for the Kilauea/Haleakala
  52. * 405EX/405EXr eval board, using the same binary.
  53. */
  54. #if defined(CONFIG_BOARD_EMAC_COUNT)
  55. #define LAST_EMAC_NUM board_emac_count()
  56. #else /* CONFIG_BOARD_EMAC_COUNT */
  57. #if defined(CONFIG_HAS_ETH3)
  58. #define LAST_EMAC_NUM 4
  59. #elif defined(CONFIG_HAS_ETH2)
  60. #define LAST_EMAC_NUM 3
  61. #elif defined(CONFIG_HAS_ETH1)
  62. #define LAST_EMAC_NUM 2
  63. #else
  64. #define LAST_EMAC_NUM 1
  65. #endif
  66. #endif /* CONFIG_BOARD_EMAC_COUNT */
  67. #if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
  68. #define SDR0_MFR_ETH_CLK_SEL_V(n) ((0x01<<27) / (n+1))
  69. #endif
  70. #define MIN_PACKET_LENGTH 64
  71. #define MAX_PACKET_LENGTH 256
  72. #define TEST_NUM 1
  73. static volatile mal_desc_t tx __cacheline_aligned;
  74. static volatile mal_desc_t rx __cacheline_aligned;
  75. static char *tx_buf;
  76. static char *rx_buf;
  77. int board_emac_count(void);
  78. static void ether_post_init (int devnum, int hw_addr)
  79. {
  80. int i;
  81. #if defined(CONFIG_440GX) || \
  82. defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
  83. defined(CONFIG_440SP) || defined(CONFIG_440SPE)
  84. unsigned mode_reg;
  85. sys_info_t sysinfo;
  86. #endif
  87. #if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || defined(CONFIG_440SPE)
  88. unsigned long mfr;
  89. #endif
  90. #if defined(CONFIG_440GX) || \
  91. defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
  92. defined(CONFIG_440SP) || defined(CONFIG_440SPE)
  93. /* Need to get the OPB frequency so we can access the PHY */
  94. get_sys_info (&sysinfo);
  95. #endif
  96. #if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
  97. /* provide clocks for EMAC internal loopback */
  98. mfsdr (sdr_mfr, mfr);
  99. mfr |= SDR0_MFR_ETH_CLK_SEL_V(devnum);
  100. mtsdr (sdr_mfr, mfr);
  101. sync ();
  102. #endif
  103. /* reset emac */
  104. out_be32 ((void*)(EMAC_M0 + hw_addr), EMAC_M0_SRST);
  105. sync ();
  106. for (i = 0;; i++) {
  107. if (!(in_be32 ((void*)(EMAC_M0 + hw_addr)) & EMAC_M0_SRST))
  108. break;
  109. if (i >= 1000) {
  110. printf ("Timeout resetting EMAC\n");
  111. break;
  112. }
  113. udelay (1000);
  114. }
  115. #if defined(CONFIG_440GX) || \
  116. defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
  117. defined(CONFIG_440SP) || defined(CONFIG_440SPE)
  118. /* Whack the M1 register */
  119. mode_reg = 0x0;
  120. if (sysinfo.freqOPB <= 50000000);
  121. else if (sysinfo.freqOPB <= 66666667)
  122. mode_reg |= EMAC_M1_OBCI_66;
  123. else if (sysinfo.freqOPB <= 83333333)
  124. mode_reg |= EMAC_M1_OBCI_83;
  125. else if (sysinfo.freqOPB <= 100000000)
  126. mode_reg |= EMAC_M1_OBCI_100;
  127. else
  128. mode_reg |= EMAC_M1_OBCI_GT100;
  129. out_be32 ((void*)(EMAC_M1 + hw_addr), mode_reg);
  130. #endif /* defined(CONFIG_440GX) || defined(CONFIG_440SP) */
  131. /* set the Mal configuration reg */
  132. #if defined(CONFIG_440GX) || \
  133. defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
  134. defined(CONFIG_440SP) || defined(CONFIG_440SPE)
  135. mtdcr (malmcr, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA |
  136. MAL_CR_PLBLT_DEFAULT | 0x00330000);
  137. #else
  138. mtdcr (malmcr, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA | MAL_CR_PLBLT_DEFAULT);
  139. /* Errata 1.12: MAL_1 -- Disable MAL bursting */
  140. if (get_pvr() == PVR_440GP_RB) {
  141. mtdcr (malmcr, mfdcr(malmcr) & ~MAL_CR_PLBB);
  142. }
  143. #endif
  144. /* setup buffer descriptors */
  145. tx.ctrl = MAL_TX_CTRL_WRAP;
  146. tx.data_len = 0;
  147. tx.data_ptr = (char*)L1_CACHE_ALIGN((u32)tx_buf);
  148. rx.ctrl = MAL_TX_CTRL_WRAP | MAL_RX_CTRL_EMPTY;
  149. rx.data_len = 0;
  150. rx.data_ptr = (char*)L1_CACHE_ALIGN((u32)rx_buf);
  151. flush_dcache_range((u32)&rx, (u32)&rx + sizeof(mal_desc_t));
  152. flush_dcache_range((u32)&tx, (u32)&tx + sizeof(mal_desc_t));
  153. switch (devnum) {
  154. case 1:
  155. /* setup MAL tx & rx channel pointers */
  156. #if defined (CONFIG_405EP) || defined (CONFIG_440EP) || defined (CONFIG_440GR)
  157. mtdcr (maltxctp2r, &tx);
  158. #else
  159. mtdcr (maltxctp1r, &tx);
  160. #endif
  161. #if defined(CONFIG_440)
  162. mtdcr (maltxbattr, 0x0);
  163. mtdcr (malrxbattr, 0x0);
  164. #endif
  165. mtdcr (malrxctp1r, &rx);
  166. /* set RX buffer size */
  167. mtdcr (malrcbs1, PKTSIZE_ALIGN / 16);
  168. break;
  169. case 0:
  170. default:
  171. /* setup MAL tx & rx channel pointers */
  172. #if defined(CONFIG_440)
  173. mtdcr (maltxbattr, 0x0);
  174. mtdcr (malrxbattr, 0x0);
  175. #endif
  176. mtdcr (maltxctp0r, &tx);
  177. mtdcr (malrxctp0r, &rx);
  178. /* set RX buffer size */
  179. mtdcr (malrcbs0, PKTSIZE_ALIGN / 16);
  180. break;
  181. }
  182. /* Enable MAL transmit and receive channels */
  183. #if defined(CONFIG_405EP) || defined(CONFIG_440EP) || defined(CONFIG_440GR)
  184. mtdcr (maltxcasr, (MAL_TXRX_CASR >> (devnum*2)));
  185. #else
  186. mtdcr (maltxcasr, (MAL_TXRX_CASR >> devnum));
  187. #endif
  188. mtdcr (malrxcasr, (MAL_TXRX_CASR >> devnum));
  189. /* set internal loopback mode */
  190. #ifdef CONFIG_SYS_POST_ETHER_EXT_LOOPBACK
  191. out_be32 ((void*)(EMAC_M1 + hw_addr), EMAC_M1_FDE | 0 |
  192. EMAC_M1_RFS_4K | EMAC_M1_TX_FIFO_2K |
  193. EMAC_M1_MF_100MBPS | EMAC_M1_IST |
  194. in_be32 ((void*)(EMAC_M1 + hw_addr)));
  195. #else
  196. out_be32 ((void*)(EMAC_M1 + hw_addr), EMAC_M1_FDE | EMAC_M1_ILE |
  197. EMAC_M1_RFS_4K | EMAC_M1_TX_FIFO_2K |
  198. EMAC_M1_MF_100MBPS | EMAC_M1_IST |
  199. in_be32 ((void*)(EMAC_M1 + hw_addr)));
  200. #endif
  201. /* set transmit enable & receive enable */
  202. out_be32 ((void*)(EMAC_M0 + hw_addr), EMAC_M0_TXE | EMAC_M0_RXE);
  203. /* enable broadcast address */
  204. out_be32 ((void*)(EMAC_RXM + hw_addr), EMAC_RMR_BAE);
  205. /* set transmit request threshold register */
  206. out_be32 ((void*)(EMAC_TRTR + hw_addr), 0x18000000); /* 256 byte threshold */
  207. /* set receive low/high water mark register */
  208. #if defined(CONFIG_440)
  209. /* 440s has a 64 byte burst length */
  210. out_be32 ((void*)(EMAC_RX_HI_LO_WMARK + hw_addr), 0x80009000);
  211. #else
  212. /* 405s have a 16 byte burst length */
  213. out_be32 ((void*)(EMAC_RX_HI_LO_WMARK + hw_addr), 0x0f002000);
  214. #endif /* defined(CONFIG_440) */
  215. out_be32 ((void*)(EMAC_TXM1 + hw_addr), 0xf8640000);
  216. /* Set fifo limit entry in tx mode 0 */
  217. out_be32 ((void*)(EMAC_TXM0 + hw_addr), 0x00000003);
  218. /* Frame gap set */
  219. out_be32 ((void*)(EMAC_I_FRAME_GAP_REG + hw_addr), 0x00000008);
  220. sync ();
  221. }
  222. static void ether_post_halt (int devnum, int hw_addr)
  223. {
  224. int i = 0;
  225. #if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
  226. unsigned long mfr;
  227. #endif
  228. /* 1st reset MAL channel */
  229. /* Note: writing a 0 to a channel has no effect */
  230. #if defined(CONFIG_405EP) || defined(CONFIG_440EP) || defined(CONFIG_440GR)
  231. mtdcr (maltxcarr, MAL_TXRX_CASR >> (devnum * 2));
  232. #else
  233. mtdcr (maltxcarr, MAL_TXRX_CASR >> devnum);
  234. #endif
  235. mtdcr (malrxcarr, MAL_TXRX_CASR >> devnum);
  236. /* wait for reset */
  237. while (mfdcr (malrxcasr) & (MAL_TXRX_CASR >> devnum)) {
  238. if (i++ >= 1000)
  239. break;
  240. udelay (1000);
  241. }
  242. /* emac reset */
  243. out_be32 ((void*)(EMAC_M0 + hw_addr), EMAC_M0_SRST);
  244. #if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
  245. /* remove clocks for EMAC internal loopback */
  246. mfsdr (sdr_mfr, mfr);
  247. mfr &= ~SDR0_MFR_ETH_CLK_SEL_V(devnum);
  248. mtsdr (sdr_mfr, mfr);
  249. #endif
  250. }
  251. static void ether_post_send (int devnum, int hw_addr, void *packet, int length)
  252. {
  253. int i = 0;
  254. while (tx.ctrl & MAL_TX_CTRL_READY) {
  255. if (i++ > 100) {
  256. printf ("TX timeout\n");
  257. return;
  258. }
  259. udelay (1000);
  260. invalidate_dcache_range((u32)&tx, (u32)&tx + sizeof(mal_desc_t));
  261. }
  262. tx.ctrl = MAL_TX_CTRL_READY | MAL_TX_CTRL_WRAP | MAL_TX_CTRL_LAST |
  263. EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP;
  264. tx.data_len = length;
  265. memcpy (tx.data_ptr, packet, length);
  266. flush_dcache_range((u32)&tx, (u32)&tx + sizeof(mal_desc_t));
  267. flush_dcache_range((u32)tx.data_ptr, (u32)tx.data_ptr + length);
  268. sync ();
  269. out_be32 ((void*)(EMAC_TXM0 + hw_addr), in_be32 ((void*)(EMAC_TXM0 + hw_addr)) | EMAC_TXM0_GNP0);
  270. sync ();
  271. }
  272. static int ether_post_recv (int devnum, int hw_addr, void *packet, int max_length)
  273. {
  274. int length;
  275. int i = 0;
  276. while (rx.ctrl & MAL_RX_CTRL_EMPTY) {
  277. if (i++ > 100) {
  278. printf ("RX timeout\n");
  279. return 0;
  280. }
  281. udelay (1000);
  282. invalidate_dcache_range((u32)&rx, (u32)&rx + sizeof(mal_desc_t));
  283. }
  284. length = rx.data_len - 4;
  285. if (length <= max_length) {
  286. invalidate_dcache_range((u32)rx.data_ptr, (u32)rx.data_ptr + length);
  287. memcpy(packet, rx.data_ptr, length);
  288. }
  289. sync ();
  290. rx.ctrl |= MAL_RX_CTRL_EMPTY;
  291. flush_dcache_range((u32)&rx, (u32)&rx + sizeof(mal_desc_t));
  292. sync ();
  293. return length;
  294. }
  295. /*
  296. * Test routines
  297. */
  298. static void packet_fill (char *packet, int length)
  299. {
  300. char c = (char) length;
  301. int i;
  302. /* set up ethernet header */
  303. memset (packet, 0xff, 14);
  304. for (i = 14; i < length; i++) {
  305. packet[i] = c++;
  306. }
  307. }
  308. static int packet_check (char *packet, int length)
  309. {
  310. char c = (char) length;
  311. int i;
  312. for (i = 14; i < length; i++) {
  313. if (packet[i] != c++)
  314. return -1;
  315. }
  316. return 0;
  317. }
  318. static int test_ctlr (int devnum, int hw_addr)
  319. {
  320. int res = -1;
  321. char packet_send[MAX_PACKET_LENGTH];
  322. char packet_recv[MAX_PACKET_LENGTH];
  323. int length;
  324. int i;
  325. int l;
  326. ether_post_init (devnum, hw_addr);
  327. for (i = 0; i < TEST_NUM; i++) {
  328. for (l = MIN_PACKET_LENGTH; l <= MAX_PACKET_LENGTH; l++) {
  329. packet_fill (packet_send, l);
  330. ether_post_send (devnum, hw_addr, packet_send, l);
  331. length = ether_post_recv (devnum, hw_addr, packet_recv,
  332. sizeof (packet_recv));
  333. if (length != l || packet_check (packet_recv, length) < 0) {
  334. goto Done;
  335. }
  336. }
  337. }
  338. res = 0;
  339. Done:
  340. ether_post_halt (devnum, hw_addr);
  341. if (res != 0) {
  342. post_log ("EMAC%d test failed\n", devnum);
  343. }
  344. return res;
  345. }
  346. int ether_post_test (int flags)
  347. {
  348. int res = 0;
  349. int i;
  350. /* Allocate tx & rx packet buffers */
  351. tx_buf = malloc (PKTSIZE_ALIGN + CONFIG_SYS_CACHELINE_SIZE);
  352. rx_buf = malloc (PKTSIZE_ALIGN + CONFIG_SYS_CACHELINE_SIZE);
  353. if (!tx_buf || !rx_buf) {
  354. printf ("Failed to allocate packet buffers\n");
  355. res = -1;
  356. goto out_free;
  357. }
  358. for (i = 0; i < LAST_EMAC_NUM; i++) {
  359. if (test_ctlr (i, i*0x100))
  360. res = -1;
  361. }
  362. out_free:
  363. free (tx_buf);
  364. free (rx_buf);
  365. return res;
  366. }
  367. #endif /* CONFIG_POST & CONFIG_SYS_POST_ETHER */