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 <sysinfo.h>
20
21#include "../../../drivers/misc/gdsys_soc.h"
22#include "../../../drivers/misc/gdsys_ioep.h"
23#include "../../../drivers/misc/ihs_fpga.h"
24
25const int HEADER_WORDS = sizeof(struct io_generic_packet) / 2;
26#endif /* !CONFIG_GDSYS_LEGACY_DRIVERS */
27
28enum status_print_type {
29	STATUS_LOUD = 0,
30	STATUS_SILENT = 1,
31};
32
33#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
34enum {
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
52enum {
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
59enum {
60	CTRL_PROC_RECEIVE_ENABLE = BIT(12),
61	CTRL_FLUSH_TRANSMIT_BUFFER = BIT(15),
62};
63
64struct 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
73unsigned long long rx_ctr;
74unsigned long long tx_ctr;
75unsigned long long err_ctr;
76#ifndef CONFIG_GDSYS_LEGACY_DRIVERS
77struct udevice *dev;
78#endif /* !CONFIG_GDSYS_LEGACY_DRIVERS */
79
80#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
81static 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
114static 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
146static 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
168static 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
190static 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
208static 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
218static 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
248static 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 */
269int 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 = dectoul(argv[1], NULL);
279
280	/*
281	 * If another parameter, it is the report rate in packets.
282	 */
283	if (argc > 2)
284		rate = dectoul(argv[2], NULL);
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 */
326int 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 */
379int 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 = dectoul(argv[1], NULL);
392
393	/*
394	 * packet size is specified since argc > 2
395	 */
396	size = dectoul(argv[2], NULL);
397
398	/*
399	 * If another parameter, it is the test rate in packets per second.
400	 */
401	if (argc > 3)
402		rate = dectoul(argv[3], NULL);
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 */
445int 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 = dectoul(argv[2], NULL);
467
468	/*
469	 * If another parameter, it is the test rate in packets per second.
470	 */
471	if (argc > 2)
472		rate = dectoul(argv[3], NULL);
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
506int do_iodev(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
507{
508	struct udevice *ioep = NULL;
509	struct udevice *sysinfo;
510	char name[8];
511	int ret;
512
513	if (sysinfo_get(&sysinfo))
514		return CMD_RET_FAILURE;
515
516	if (argc > 1) {
517		int i = dectoul(argv[1], NULL);
518
519		snprintf(name, sizeof(name), "ioep%d", i);
520
521		ret = uclass_get_device_by_phandle(UCLASS_MISC, sysinfo, name,
522						   &ioep);
523
524		if (ret || !ioep) {
525			printf("Invalid IOEP %d\n", i);
526			return CMD_RET_FAILURE;
527		}
528
529		dev = ioep;
530	} else {
531		int i = 0;
532
533		while (1) {
534			snprintf(name, sizeof(name), "ioep%d", i);
535
536			ret = uclass_get_device_by_phandle(UCLASS_MISC, sysinfo,
537							   name, &ioep);
538
539			if (ret || !ioep)
540				break;
541
542			printf("IOEP %d:\t%s\n", i++, ioep->name);
543		}
544
545		if (dev)
546			printf("\nSelected IOEP: %s\n", dev->name);
547		else
548			puts("\nNo IOEP selected.\n");
549	}
550
551	return 0;
552}
553#endif /* !CONFIG_GDSYS_LEGACY_DRIVERS */
554
555#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
556U_BOOT_CMD(
557	ioloop,	4,	0,	do_ioloop,
558	"fpga io-endpoint looptest",
559	"fpga packetsize [packets/sec]"
560);
561
562U_BOOT_CMD(
563	ioreflect, 3,	0,	do_ioreflect,
564	"fpga io-endpoint reflector",
565	"fpga reportrate"
566);
567#else
568U_BOOT_CMD(
569	ioloop,	3,	0,	do_ioloop,
570	"fpga io-endpoint looptest",
571	"packetsize [packets/sec]"
572);
573
574U_BOOT_CMD(
575	ioreflect, 2,	0,	do_ioreflect,
576	"fpga io-endpoint reflector",
577	"reportrate"
578);
579
580U_BOOT_CMD(
581	iodev, 2,	0,	do_iodev,
582	"fpga io-endpoint listing/selection",
583	"[ioep device to select]"
584);
585#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
586