cmd_ioloop.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2014
  4. * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
  5. */
  6. #include <common.h>
  7. #include <command.h>
  8. #include <console.h>
  9. #include <linux/bitops.h>
  10. #include <linux/delay.h>
  11. #include <gdsys_fpga.h>
  12. #ifndef CONFIG_GDSYS_LEGACY_DRIVERS
  13. #include <dm.h>
  14. #include <misc.h>
  15. #include <regmap.h>
  16. #include <sysinfo.h>
  17. #include "../../../drivers/misc/gdsys_soc.h"
  18. #include "../../../drivers/misc/gdsys_ioep.h"
  19. #include "../../../drivers/misc/ihs_fpga.h"
  20. const int HEADER_WORDS = sizeof(struct io_generic_packet) / 2;
  21. #endif /* !CONFIG_GDSYS_LEGACY_DRIVERS */
  22. enum status_print_type {
  23. STATUS_LOUD = 0,
  24. STATUS_SILENT = 1,
  25. };
  26. #ifdef CONFIG_GDSYS_LEGACY_DRIVERS
  27. enum {
  28. STATE_TX_PACKET_BUILDING = BIT(0),
  29. STATE_TX_TRANSMITTING = BIT(1),
  30. STATE_TX_BUFFER_FULL = BIT(2),
  31. STATE_TX_ERR = BIT(3),
  32. STATE_RECEIVE_TIMEOUT = BIT(4),
  33. STATE_PROC_RX_STORE_TIMEOUT = BIT(5),
  34. STATE_PROC_RX_RECEIVE_TIMEOUT = BIT(6),
  35. STATE_RX_DIST_ERR = BIT(7),
  36. STATE_RX_LENGTH_ERR = BIT(8),
  37. STATE_RX_FRAME_CTR_ERR = BIT(9),
  38. STATE_RX_FCS_ERR = BIT(10),
  39. STATE_RX_PACKET_DROPPED = BIT(11),
  40. STATE_RX_DATA_LAST = BIT(12),
  41. STATE_RX_DATA_FIRST = BIT(13),
  42. STATE_RX_DATA_AVAILABLE = BIT(15),
  43. };
  44. enum {
  45. IRQ_CPU_TRANSMITBUFFER_FREE_STATUS = BIT(5),
  46. IRQ_CPU_PACKET_TRANSMITTED_EVENT = BIT(6),
  47. IRQ_NEW_CPU_PACKET_RECEIVED_EVENT = BIT(7),
  48. IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS = BIT(8),
  49. };
  50. enum {
  51. CTRL_PROC_RECEIVE_ENABLE = BIT(12),
  52. CTRL_FLUSH_TRANSMIT_BUFFER = BIT(15),
  53. };
  54. struct io_generic_packet {
  55. u16 target_address;
  56. u16 source_address;
  57. u8 packet_type;
  58. u8 bc;
  59. u16 packet_length;
  60. } __attribute__((__packed__));
  61. #endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
  62. unsigned long long rx_ctr;
  63. unsigned long long tx_ctr;
  64. unsigned long long err_ctr;
  65. #ifndef CONFIG_GDSYS_LEGACY_DRIVERS
  66. struct udevice *dev;
  67. #endif /* !CONFIG_GDSYS_LEGACY_DRIVERS */
  68. #ifdef CONFIG_GDSYS_LEGACY_DRIVERS
  69. static void io_check_status(uint fpga, u16 status, enum status_print_type type)
  70. {
  71. u16 mask = STATE_RX_DIST_ERR | STATE_RX_LENGTH_ERR |
  72. STATE_RX_FRAME_CTR_ERR | STATE_RX_FCS_ERR |
  73. STATE_RX_PACKET_DROPPED | STATE_TX_ERR;
  74. if (!(status & mask)) {
  75. FPGA_SET_REG(fpga, ep.rx_tx_status, status);
  76. return;
  77. }
  78. err_ctr++;
  79. FPGA_SET_REG(fpga, ep.rx_tx_status, status);
  80. if (type == STATUS_SILENT)
  81. return;
  82. if (status & STATE_RX_PACKET_DROPPED)
  83. printf("RX_PACKET_DROPPED, status %04x\n", status);
  84. if (status & STATE_RX_DIST_ERR)
  85. printf("RX_DIST_ERR\n");
  86. if (status & STATE_RX_LENGTH_ERR)
  87. printf("RX_LENGTH_ERR\n");
  88. if (status & STATE_RX_FRAME_CTR_ERR)
  89. printf("RX_FRAME_CTR_ERR\n");
  90. if (status & STATE_RX_FCS_ERR)
  91. printf("RX_FCS_ERR\n");
  92. if (status & STATE_TX_ERR)
  93. printf("TX_ERR\n");
  94. }
  95. #else
  96. static void io_check_status(struct udevice *dev, enum status_print_type type)
  97. {
  98. u16 status = 0;
  99. int ret;
  100. ret = misc_call(dev, 0, NULL, 0, &status, 0);
  101. if (!ret)
  102. return;
  103. err_ctr++;
  104. if (type != STATUS_LOUD)
  105. return;
  106. if (status & STATE_RX_PACKET_DROPPED)
  107. printf("RX_PACKET_DROPPED, status %04x\n", status);
  108. if (status & STATE_RX_DIST_ERR)
  109. printf("RX_DIST_ERR\n");
  110. if (status & STATE_RX_LENGTH_ERR)
  111. printf("RX_LENGTH_ERR\n");
  112. if (status & STATE_RX_FRAME_CTR_ERR)
  113. printf("RX_FRAME_CTR_ERR\n");
  114. if (status & STATE_RX_FCS_ERR)
  115. printf("RX_FCS_ERR\n");
  116. if (status & STATE_TX_ERR)
  117. printf("TX_ERR\n");
  118. }
  119. #endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
  120. #ifdef CONFIG_GDSYS_LEGACY_DRIVERS
  121. static void io_send(uint fpga, uint size)
  122. {
  123. uint k;
  124. struct io_generic_packet packet = {
  125. .source_address = 1,
  126. .packet_type = 1,
  127. .packet_length = size,
  128. };
  129. u16 *p = (u16 *)&packet;
  130. for (k = 0; k < sizeof(packet) / 2; ++k)
  131. FPGA_SET_REG(fpga, ep.transmit_data, *p++);
  132. for (k = 0; k < (size + 1) / 2; ++k)
  133. FPGA_SET_REG(fpga, ep.transmit_data, k);
  134. FPGA_SET_REG(fpga, ep.rx_tx_control,
  135. CTRL_PROC_RECEIVE_ENABLE | CTRL_FLUSH_TRANSMIT_BUFFER);
  136. tx_ctr++;
  137. }
  138. #else
  139. static void io_send(struct udevice *dev, uint size)
  140. {
  141. uint k;
  142. u16 buffer[HEADER_WORDS + 128];
  143. struct io_generic_packet header = {
  144. .source_address = 1,
  145. .packet_type = 1,
  146. .packet_length = size,
  147. };
  148. const uint words = (size + 1) / 2;
  149. memcpy(buffer, &header, 2 * HEADER_WORDS);
  150. for (k = 0; k < words; ++k)
  151. buffer[k + HEADER_WORDS] = (2 * k + 1) + ((2 * k) << 8);
  152. misc_write(dev, 0, buffer, HEADER_WORDS + words);
  153. tx_ctr++;
  154. }
  155. #endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
  156. #ifdef CONFIG_GDSYS_LEGACY_DRIVERS
  157. static void io_receive(uint fpga)
  158. {
  159. u16 rx_tx_status;
  160. FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
  161. while (rx_tx_status & STATE_RX_DATA_AVAILABLE) {
  162. u16 rx;
  163. if (rx_tx_status & STATE_RX_DATA_LAST)
  164. rx_ctr++;
  165. FPGA_GET_REG(fpga, ep.receive_data, &rx);
  166. FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
  167. }
  168. }
  169. #else
  170. static void io_receive(struct udevice *dev)
  171. {
  172. u16 buffer[HEADER_WORDS + 128];
  173. if (!misc_read(dev, 0, buffer, 0))
  174. rx_ctr++;
  175. }
  176. #endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
  177. #ifdef CONFIG_GDSYS_LEGACY_DRIVERS
  178. static void io_reflect(uint fpga)
  179. {
  180. u16 buffer[128];
  181. uint k = 0;
  182. uint n;
  183. u16 rx_tx_status;
  184. FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
  185. while (rx_tx_status & STATE_RX_DATA_AVAILABLE) {
  186. FPGA_GET_REG(fpga, ep.receive_data, &buffer[k++]);
  187. if (rx_tx_status & STATE_RX_DATA_LAST)
  188. break;
  189. FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
  190. }
  191. if (!k)
  192. return;
  193. for (n = 0; n < k; ++n)
  194. FPGA_SET_REG(fpga, ep.transmit_data, buffer[n]);
  195. FPGA_SET_REG(fpga, ep.rx_tx_control,
  196. CTRL_PROC_RECEIVE_ENABLE | CTRL_FLUSH_TRANSMIT_BUFFER);
  197. tx_ctr++;
  198. }
  199. #else
  200. static void io_reflect(struct udevice *dev)
  201. {
  202. u16 buffer[HEADER_WORDS + 128];
  203. struct io_generic_packet *header;
  204. if (misc_read(dev, 0, buffer, 0))
  205. return;
  206. header = (struct io_generic_packet *)&buffer;
  207. misc_write(dev, 0, buffer, HEADER_WORDS + header->packet_length);
  208. }
  209. #endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
  210. #ifdef CONFIG_GDSYS_LEGACY_DRIVERS
  211. /*
  212. * FPGA io-endpoint reflector
  213. *
  214. * Syntax:
  215. * ioreflect {fpga} {reportrate}
  216. */
  217. int do_ioreflect(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
  218. {
  219. uint fpga;
  220. uint rate = 0;
  221. unsigned long long last_seen = 0;
  222. if (argc < 2)
  223. return CMD_RET_USAGE;
  224. fpga = dectoul(argv[1], NULL);
  225. /*
  226. * If another parameter, it is the report rate in packets.
  227. */
  228. if (argc > 2)
  229. rate = dectoul(argv[2], NULL);
  230. /* Enable receive path */
  231. FPGA_SET_REG(fpga, ep.rx_tx_control, CTRL_PROC_RECEIVE_ENABLE);
  232. /* Set device address to dummy 1*/
  233. FPGA_SET_REG(fpga, ep.device_address, 1);
  234. rx_ctr = 0; tx_ctr = 0; err_ctr = 0;
  235. while (1) {
  236. u16 top_int;
  237. u16 rx_tx_status;
  238. FPGA_GET_REG(fpga, top_interrupt, &top_int);
  239. FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
  240. io_check_status(fpga, rx_tx_status, STATUS_SILENT);
  241. if ((top_int & IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS) &&
  242. (top_int & IRQ_CPU_TRANSMITBUFFER_FREE_STATUS))
  243. io_reflect(fpga);
  244. if (rate) {
  245. if (!(tx_ctr % rate) && (tx_ctr != last_seen))
  246. printf("refl %llu, err %llu\n", tx_ctr,
  247. err_ctr);
  248. last_seen = tx_ctr;
  249. }
  250. if (ctrlc())
  251. break;
  252. }
  253. return 0;
  254. }
  255. #else
  256. /*
  257. * FPGA io-endpoint reflector
  258. *
  259. * Syntax:
  260. * ioreflect {reportrate}
  261. */
  262. int do_ioreflect(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
  263. {
  264. struct udevice *fpga;
  265. struct regmap *map;
  266. uint rate = 0;
  267. unsigned long long last_seen = 0;
  268. if (!dev) {
  269. printf("No device selected\n");
  270. return 1;
  271. }
  272. gdsys_soc_get_fpga(dev, &fpga);
  273. regmap_init_mem(dev_ofnode(dev), &map);
  274. /* Enable receive path */
  275. misc_set_enabled(dev, true);
  276. rx_ctr = 0; tx_ctr = 0; err_ctr = 0;
  277. while (1) {
  278. uint top_int;
  279. ihs_fpga_get(map, top_interrupt, &top_int);
  280. io_check_status(dev, STATUS_SILENT);
  281. if ((top_int & IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS) &&
  282. (top_int & IRQ_CPU_TRANSMITBUFFER_FREE_STATUS))
  283. io_reflect(dev);
  284. if (rate) {
  285. if (!(tx_ctr % rate) && (tx_ctr != last_seen))
  286. printf("refl %llu, err %llu\n", tx_ctr,
  287. err_ctr);
  288. last_seen = tx_ctr;
  289. }
  290. if (ctrlc())
  291. break;
  292. }
  293. return 0;
  294. }
  295. #endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
  296. #define DISP_LINE_LEN 16
  297. #ifdef CONFIG_GDSYS_LEGACY_DRIVERS
  298. /*
  299. * FPGA io-endpoint looptest
  300. *
  301. * Syntax:
  302. * ioloop {fpga} {size} {rate}
  303. */
  304. int do_ioloop(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
  305. {
  306. uint fpga;
  307. uint size;
  308. uint rate = 0;
  309. if (argc < 3)
  310. return CMD_RET_USAGE;
  311. /*
  312. * FPGA is specified since argc > 2
  313. */
  314. fpga = dectoul(argv[1], NULL);
  315. /*
  316. * packet size is specified since argc > 2
  317. */
  318. size = dectoul(argv[2], NULL);
  319. /*
  320. * If another parameter, it is the test rate in packets per second.
  321. */
  322. if (argc > 3)
  323. rate = dectoul(argv[3], NULL);
  324. /* enable receive path */
  325. FPGA_SET_REG(fpga, ep.rx_tx_control, CTRL_PROC_RECEIVE_ENABLE);
  326. /* set device address to dummy 1*/
  327. FPGA_SET_REG(fpga, ep.device_address, 1);
  328. rx_ctr = 0; tx_ctr = 0; err_ctr = 0;
  329. while (1) {
  330. u16 top_int;
  331. u16 rx_tx_status;
  332. FPGA_GET_REG(fpga, top_interrupt, &top_int);
  333. FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
  334. io_check_status(fpga, rx_tx_status, STATUS_LOUD);
  335. if (top_int & IRQ_CPU_TRANSMITBUFFER_FREE_STATUS)
  336. io_send(fpga, size);
  337. if (top_int & IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS)
  338. io_receive(fpga);
  339. if (rate) {
  340. if (ctrlc())
  341. break;
  342. udelay(1000000 / rate);
  343. if (!(tx_ctr % rate))
  344. printf("d %llu, tx %llu, rx %llu, err %llu\n",
  345. tx_ctr - rx_ctr, tx_ctr, rx_ctr,
  346. err_ctr);
  347. }
  348. }
  349. return 0;
  350. }
  351. #else
  352. /*
  353. * FPGA io-endpoint looptest
  354. *
  355. * Syntax:
  356. * ioloop {size} {rate}
  357. */
  358. int do_ioloop(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
  359. {
  360. uint size;
  361. uint rate = 0;
  362. struct udevice *fpga;
  363. struct regmap *map;
  364. if (!dev) {
  365. printf("No device selected\n");
  366. return 1;
  367. }
  368. gdsys_soc_get_fpga(dev, &fpga);
  369. regmap_init_mem(dev_ofnode(dev), &map);
  370. if (argc < 2)
  371. return CMD_RET_USAGE;
  372. /*
  373. * packet size is specified since argc > 1
  374. */
  375. size = dectoul(argv[2], NULL);
  376. /*
  377. * If another parameter, it is the test rate in packets per second.
  378. */
  379. if (argc > 2)
  380. rate = dectoul(argv[3], NULL);
  381. /* Enable receive path */
  382. misc_set_enabled(dev, true);
  383. rx_ctr = 0; tx_ctr = 0; err_ctr = 0;
  384. while (1) {
  385. uint top_int;
  386. if (ctrlc())
  387. break;
  388. ihs_fpga_get(map, top_interrupt, &top_int);
  389. io_check_status(dev, STATUS_LOUD);
  390. if (top_int & IRQ_CPU_TRANSMITBUFFER_FREE_STATUS)
  391. io_send(dev, size);
  392. if (top_int & IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS)
  393. io_receive(dev);
  394. if (rate) {
  395. udelay(1000000 / rate);
  396. if (!(tx_ctr % rate))
  397. printf("d %llu, tx %llu, rx %llu, err %llu\n",
  398. tx_ctr - rx_ctr, tx_ctr, rx_ctr,
  399. err_ctr);
  400. }
  401. }
  402. return 0;
  403. }
  404. #endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
  405. #ifndef CONFIG_GDSYS_LEGACY_DRIVERS
  406. int do_iodev(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
  407. {
  408. struct udevice *ioep = NULL;
  409. struct udevice *sysinfo;
  410. char name[8];
  411. int ret;
  412. if (sysinfo_get(&sysinfo))
  413. return CMD_RET_FAILURE;
  414. if (argc > 1) {
  415. int i = dectoul(argv[1], NULL);
  416. snprintf(name, sizeof(name), "ioep%d", i);
  417. ret = uclass_get_device_by_phandle(UCLASS_MISC, sysinfo, name,
  418. &ioep);
  419. if (ret || !ioep) {
  420. printf("Invalid IOEP %d\n", i);
  421. return CMD_RET_FAILURE;
  422. }
  423. dev = ioep;
  424. } else {
  425. int i = 0;
  426. while (1) {
  427. snprintf(name, sizeof(name), "ioep%d", i);
  428. ret = uclass_get_device_by_phandle(UCLASS_MISC, sysinfo,
  429. name, &ioep);
  430. if (ret || !ioep)
  431. break;
  432. printf("IOEP %d:\t%s\n", i++, ioep->name);
  433. }
  434. if (dev)
  435. printf("\nSelected IOEP: %s\n", dev->name);
  436. else
  437. puts("\nNo IOEP selected.\n");
  438. }
  439. return 0;
  440. }
  441. #endif /* !CONFIG_GDSYS_LEGACY_DRIVERS */
  442. #ifdef CONFIG_GDSYS_LEGACY_DRIVERS
  443. U_BOOT_CMD(
  444. ioloop, 4, 0, do_ioloop,
  445. "fpga io-endpoint looptest",
  446. "fpga packetsize [packets/sec]"
  447. );
  448. U_BOOT_CMD(
  449. ioreflect, 3, 0, do_ioreflect,
  450. "fpga io-endpoint reflector",
  451. "fpga reportrate"
  452. );
  453. #else
  454. U_BOOT_CMD(
  455. ioloop, 3, 0, do_ioloop,
  456. "fpga io-endpoint looptest",
  457. "packetsize [packets/sec]"
  458. );
  459. U_BOOT_CMD(
  460. ioreflect, 2, 0, do_ioreflect,
  461. "fpga io-endpoint reflector",
  462. "reportrate"
  463. );
  464. U_BOOT_CMD(
  465. iodev, 2, 0, do_iodev,
  466. "fpga io-endpoint listing/selection",
  467. "[ioep device to select]"
  468. );
  469. #endif /* CONFIG_GDSYS_LEGACY_DRIVERS */