cmd_ioloop.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. /*
  2. * (C) Copyright 2014
  3. * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
  4. *
  5. * SPDX-License-Identifier: GPL-2.0+
  6. */
  7. #include <common.h>
  8. #include <command.h>
  9. #include <console.h>
  10. #include <gdsys_fpga.h>
  11. enum {
  12. STATE_TX_PACKET_BUILDING = 1<<0,
  13. STATE_TX_TRANSMITTING = 1<<1,
  14. STATE_TX_BUFFER_FULL = 1<<2,
  15. STATE_TX_ERR = 1<<3,
  16. STATE_RECEIVE_TIMEOUT = 1<<4,
  17. STATE_PROC_RX_STORE_TIMEOUT = 1<<5,
  18. STATE_PROC_RX_RECEIVE_TIMEOUT = 1<<6,
  19. STATE_RX_DIST_ERR = 1<<7,
  20. STATE_RX_LENGTH_ERR = 1<<8,
  21. STATE_RX_FRAME_CTR_ERR = 1<<9,
  22. STATE_RX_FCS_ERR = 1<<10,
  23. STATE_RX_PACKET_DROPPED = 1<<11,
  24. STATE_RX_DATA_LAST = 1<<12,
  25. STATE_RX_DATA_FIRST = 1<<13,
  26. STATE_RX_DATA_AVAILABLE = 1<<15,
  27. };
  28. enum {
  29. CTRL_PROC_RECEIVE_ENABLE = 1<<12,
  30. CTRL_FLUSH_TRANSMIT_BUFFER = 1<<15,
  31. };
  32. enum {
  33. IRQ_CPU_TRANSMITBUFFER_FREE_STATUS = 1<<5,
  34. IRQ_CPU_PACKET_TRANSMITTED_EVENT = 1<<6,
  35. IRQ_NEW_CPU_PACKET_RECEIVED_EVENT = 1<<7,
  36. IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS = 1<<8,
  37. };
  38. struct io_generic_packet {
  39. u16 target_address;
  40. u16 source_address;
  41. u8 packet_type;
  42. u8 bc;
  43. u16 packet_length;
  44. } __attribute__((__packed__));
  45. unsigned long long rx_ctr;
  46. unsigned long long tx_ctr;
  47. unsigned long long err_ctr;
  48. static void io_check_status(unsigned int fpga, u16 status, bool silent)
  49. {
  50. u16 mask = STATE_RX_DIST_ERR | STATE_RX_LENGTH_ERR |
  51. STATE_RX_FRAME_CTR_ERR | STATE_RX_FCS_ERR |
  52. STATE_RX_PACKET_DROPPED | STATE_TX_ERR;
  53. if (!(status & mask)) {
  54. FPGA_SET_REG(fpga, ep.rx_tx_status, status);
  55. return;
  56. }
  57. err_ctr++;
  58. FPGA_SET_REG(fpga, ep.rx_tx_status, status);
  59. if (silent)
  60. return;
  61. if (status & STATE_RX_PACKET_DROPPED)
  62. printf("RX_PACKET_DROPPED, status %04x\n", status);
  63. if (status & STATE_RX_DIST_ERR)
  64. printf("RX_DIST_ERR\n");
  65. if (status & STATE_RX_LENGTH_ERR)
  66. printf("RX_LENGTH_ERR\n");
  67. if (status & STATE_RX_FRAME_CTR_ERR)
  68. printf("RX_FRAME_CTR_ERR\n");
  69. if (status & STATE_RX_FCS_ERR)
  70. printf("RX_FCS_ERR\n");
  71. if (status & STATE_TX_ERR)
  72. printf("TX_ERR\n");
  73. }
  74. static void io_send(unsigned int fpga, unsigned int size)
  75. {
  76. unsigned int k;
  77. struct io_generic_packet packet = {
  78. .source_address = 1,
  79. .packet_type = 1,
  80. .packet_length = size,
  81. };
  82. u16 *p = (u16 *)&packet;
  83. for (k = 0; k < sizeof(packet) / 2; ++k)
  84. FPGA_SET_REG(fpga, ep.transmit_data, *p++);
  85. for (k = 0; k < (size + 1) / 2; ++k)
  86. FPGA_SET_REG(fpga, ep.transmit_data, k);
  87. FPGA_SET_REG(fpga, ep.rx_tx_control,
  88. CTRL_PROC_RECEIVE_ENABLE | CTRL_FLUSH_TRANSMIT_BUFFER);
  89. tx_ctr++;
  90. }
  91. static void io_receive(unsigned int fpga)
  92. {
  93. unsigned int k = 0;
  94. u16 rx_tx_status;
  95. FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
  96. while (rx_tx_status & STATE_RX_DATA_AVAILABLE) {
  97. u16 rx;
  98. if (rx_tx_status & STATE_RX_DATA_LAST)
  99. rx_ctr++;
  100. FPGA_GET_REG(fpga, ep.receive_data, &rx);
  101. FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
  102. ++k;
  103. }
  104. }
  105. static void io_reflect(unsigned int fpga)
  106. {
  107. u16 buffer[128];
  108. unsigned int k = 0;
  109. unsigned int n;
  110. u16 rx_tx_status;
  111. FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
  112. while (rx_tx_status & STATE_RX_DATA_AVAILABLE) {
  113. FPGA_GET_REG(fpga, ep.receive_data, &buffer[k++]);
  114. if (rx_tx_status & STATE_RX_DATA_LAST)
  115. break;
  116. FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
  117. }
  118. if (!k)
  119. return;
  120. for (n = 0; n < k; ++n)
  121. FPGA_SET_REG(fpga, ep.transmit_data, buffer[n]);
  122. FPGA_SET_REG(fpga, ep.rx_tx_control,
  123. CTRL_PROC_RECEIVE_ENABLE | CTRL_FLUSH_TRANSMIT_BUFFER);
  124. tx_ctr++;
  125. }
  126. /*
  127. * FPGA io-endpoint reflector
  128. *
  129. * Syntax:
  130. * ioreflect {fpga} {reportrate}
  131. */
  132. int do_ioreflect(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  133. {
  134. unsigned int fpga;
  135. unsigned int rate = 0;
  136. unsigned long long last_seen = 0;
  137. if (argc < 2)
  138. return CMD_RET_USAGE;
  139. fpga = simple_strtoul(argv[1], NULL, 10);
  140. /*
  141. * If another parameter, it is the report rate in packets.
  142. */
  143. if (argc > 2)
  144. rate = simple_strtoul(argv[2], NULL, 10);
  145. /* enable receive path */
  146. FPGA_SET_REG(fpga, ep.rx_tx_control, CTRL_PROC_RECEIVE_ENABLE);
  147. /* set device address to dummy 1*/
  148. FPGA_SET_REG(fpga, ep.device_address, 1);
  149. rx_ctr = 0; tx_ctr = 0; err_ctr = 0;
  150. while (1) {
  151. u16 top_int;
  152. u16 rx_tx_status;
  153. FPGA_GET_REG(fpga, top_interrupt, &top_int);
  154. FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
  155. io_check_status(fpga, rx_tx_status, true);
  156. if ((top_int & IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS) &&
  157. (top_int & IRQ_CPU_TRANSMITBUFFER_FREE_STATUS))
  158. io_reflect(fpga);
  159. if (rate) {
  160. if (!(tx_ctr % rate) && (tx_ctr != last_seen))
  161. printf("refl %llu, err %llu\n", tx_ctr,
  162. err_ctr);
  163. last_seen = tx_ctr;
  164. }
  165. if (ctrlc())
  166. break;
  167. }
  168. return 0;
  169. }
  170. /*
  171. * FPGA io-endpoint looptest
  172. *
  173. * Syntax:
  174. * ioloop {fpga} {size} {rate}
  175. */
  176. #define DISP_LINE_LEN 16
  177. int do_ioloop(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  178. {
  179. unsigned int fpga;
  180. unsigned int size;
  181. unsigned int rate = 0;
  182. if (argc < 3)
  183. return CMD_RET_USAGE;
  184. /*
  185. * FPGA is specified since argc > 2
  186. */
  187. fpga = simple_strtoul(argv[1], NULL, 10);
  188. /*
  189. * packet size is specified since argc > 2
  190. */
  191. size = simple_strtoul(argv[2], NULL, 10);
  192. /*
  193. * If another parameter, it is the test rate in packets per second.
  194. */
  195. if (argc > 3)
  196. rate = simple_strtoul(argv[3], NULL, 10);
  197. /* enable receive path */
  198. FPGA_SET_REG(fpga, ep.rx_tx_control, CTRL_PROC_RECEIVE_ENABLE);
  199. /* set device address to dummy 1*/
  200. FPGA_SET_REG(fpga, ep.device_address, 1);
  201. rx_ctr = 0; tx_ctr = 0; err_ctr = 0;
  202. while (1) {
  203. u16 top_int;
  204. u16 rx_tx_status;
  205. FPGA_GET_REG(fpga, top_interrupt, &top_int);
  206. FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
  207. io_check_status(fpga, rx_tx_status, false);
  208. if (top_int & IRQ_CPU_TRANSMITBUFFER_FREE_STATUS)
  209. io_send(fpga, size);
  210. if (top_int & IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS)
  211. io_receive(fpga);
  212. if (rate) {
  213. if (ctrlc())
  214. break;
  215. udelay(1000000 / rate);
  216. if (!(tx_ctr % rate))
  217. printf("d %lld, tx %llu, rx %llu, err %llu\n",
  218. tx_ctr - rx_ctr, tx_ctr, rx_ctr,
  219. err_ctr);
  220. }
  221. }
  222. return 0;
  223. }
  224. U_BOOT_CMD(
  225. ioloop, 4, 0, do_ioloop,
  226. "fpga io-endpoint looptest",
  227. "fpga packetsize [packets/sec]"
  228. );
  229. U_BOOT_CMD(
  230. ioreflect, 3, 0, do_ioreflect,
  231. "fpga io-endpoint reflector",
  232. "fpga reportrate"
  233. );