• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
io_check_status(uint fpga,u16 status,enum status_print_type type)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
io_check_status(struct udevice * dev,enum status_print_type type)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
io_send(uint fpga,uint size)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
io_send(struct udevice * dev,uint size)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
io_receive(uint fpga)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
io_receive(struct udevice * dev)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
io_reflect(uint fpga)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
io_reflect(struct udevice * dev)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  */
do_ioreflect(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])267 int do_ioreflect(cmd_tbl_t *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  */
do_ioreflect(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])324 int do_ioreflect(cmd_tbl_t *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  */
do_ioloop(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])377 int do_ioloop(cmd_tbl_t *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  */
do_ioloop(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])443 int do_ioloop(cmd_tbl_t *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
do_iodev(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])504 int do_iodev(cmd_tbl_t *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 */
582