ether.c 10 KB

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