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