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