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