1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * (C) Copyright 2014
3*4882a593Smuzhiyun * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <common.h>
9*4882a593Smuzhiyun #include <command.h>
10*4882a593Smuzhiyun #include <console.h>
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <gdsys_fpga.h>
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun enum {
15*4882a593Smuzhiyun STATE_TX_PACKET_BUILDING = 1<<0,
16*4882a593Smuzhiyun STATE_TX_TRANSMITTING = 1<<1,
17*4882a593Smuzhiyun STATE_TX_BUFFER_FULL = 1<<2,
18*4882a593Smuzhiyun STATE_TX_ERR = 1<<3,
19*4882a593Smuzhiyun STATE_RECEIVE_TIMEOUT = 1<<4,
20*4882a593Smuzhiyun STATE_PROC_RX_STORE_TIMEOUT = 1<<5,
21*4882a593Smuzhiyun STATE_PROC_RX_RECEIVE_TIMEOUT = 1<<6,
22*4882a593Smuzhiyun STATE_RX_DIST_ERR = 1<<7,
23*4882a593Smuzhiyun STATE_RX_LENGTH_ERR = 1<<8,
24*4882a593Smuzhiyun STATE_RX_FRAME_CTR_ERR = 1<<9,
25*4882a593Smuzhiyun STATE_RX_FCS_ERR = 1<<10,
26*4882a593Smuzhiyun STATE_RX_PACKET_DROPPED = 1<<11,
27*4882a593Smuzhiyun STATE_RX_DATA_LAST = 1<<12,
28*4882a593Smuzhiyun STATE_RX_DATA_FIRST = 1<<13,
29*4882a593Smuzhiyun STATE_RX_DATA_AVAILABLE = 1<<15,
30*4882a593Smuzhiyun };
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun enum {
33*4882a593Smuzhiyun CTRL_PROC_RECEIVE_ENABLE = 1<<12,
34*4882a593Smuzhiyun CTRL_FLUSH_TRANSMIT_BUFFER = 1<<15,
35*4882a593Smuzhiyun };
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun enum {
38*4882a593Smuzhiyun IRQ_CPU_TRANSMITBUFFER_FREE_STATUS = 1<<5,
39*4882a593Smuzhiyun IRQ_CPU_PACKET_TRANSMITTED_EVENT = 1<<6,
40*4882a593Smuzhiyun IRQ_NEW_CPU_PACKET_RECEIVED_EVENT = 1<<7,
41*4882a593Smuzhiyun IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS = 1<<8,
42*4882a593Smuzhiyun };
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun struct io_generic_packet {
45*4882a593Smuzhiyun u16 target_address;
46*4882a593Smuzhiyun u16 source_address;
47*4882a593Smuzhiyun u8 packet_type;
48*4882a593Smuzhiyun u8 bc;
49*4882a593Smuzhiyun u16 packet_length;
50*4882a593Smuzhiyun } __attribute__((__packed__));
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun unsigned long long rx_ctr;
53*4882a593Smuzhiyun unsigned long long tx_ctr;
54*4882a593Smuzhiyun unsigned long long err_ctr;
55*4882a593Smuzhiyun
io_check_status(unsigned int fpga,u16 status,bool silent)56*4882a593Smuzhiyun static void io_check_status(unsigned int fpga, u16 status, bool silent)
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun u16 mask = STATE_RX_DIST_ERR | STATE_RX_LENGTH_ERR |
59*4882a593Smuzhiyun STATE_RX_FRAME_CTR_ERR | STATE_RX_FCS_ERR |
60*4882a593Smuzhiyun STATE_RX_PACKET_DROPPED | STATE_TX_ERR;
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun if (!(status & mask)) {
63*4882a593Smuzhiyun FPGA_SET_REG(fpga, ep.rx_tx_status, status);
64*4882a593Smuzhiyun return;
65*4882a593Smuzhiyun }
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun err_ctr++;
68*4882a593Smuzhiyun FPGA_SET_REG(fpga, ep.rx_tx_status, status);
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun if (silent)
71*4882a593Smuzhiyun return;
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun if (status & STATE_RX_PACKET_DROPPED)
74*4882a593Smuzhiyun printf("RX_PACKET_DROPPED, status %04x\n", status);
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun if (status & STATE_RX_DIST_ERR)
77*4882a593Smuzhiyun printf("RX_DIST_ERR\n");
78*4882a593Smuzhiyun if (status & STATE_RX_LENGTH_ERR)
79*4882a593Smuzhiyun printf("RX_LENGTH_ERR\n");
80*4882a593Smuzhiyun if (status & STATE_RX_FRAME_CTR_ERR)
81*4882a593Smuzhiyun printf("RX_FRAME_CTR_ERR\n");
82*4882a593Smuzhiyun if (status & STATE_RX_FCS_ERR)
83*4882a593Smuzhiyun printf("RX_FCS_ERR\n");
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun if (status & STATE_TX_ERR)
86*4882a593Smuzhiyun printf("TX_ERR\n");
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun
io_send(unsigned int fpga,unsigned int size)89*4882a593Smuzhiyun static void io_send(unsigned int fpga, unsigned int size)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun unsigned int k;
92*4882a593Smuzhiyun struct io_generic_packet packet = {
93*4882a593Smuzhiyun .source_address = 1,
94*4882a593Smuzhiyun .packet_type = 1,
95*4882a593Smuzhiyun .packet_length = size,
96*4882a593Smuzhiyun };
97*4882a593Smuzhiyun u16 *p = (u16 *)&packet;
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun for (k = 0; k < sizeof(packet) / 2; ++k)
100*4882a593Smuzhiyun FPGA_SET_REG(fpga, ep.transmit_data, *p++);
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun for (k = 0; k < (size + 1) / 2; ++k)
103*4882a593Smuzhiyun FPGA_SET_REG(fpga, ep.transmit_data, k);
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun FPGA_SET_REG(fpga, ep.rx_tx_control,
106*4882a593Smuzhiyun CTRL_PROC_RECEIVE_ENABLE | CTRL_FLUSH_TRANSMIT_BUFFER);
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun tx_ctr++;
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun
io_receive(unsigned int fpga)111*4882a593Smuzhiyun static void io_receive(unsigned int fpga)
112*4882a593Smuzhiyun {
113*4882a593Smuzhiyun unsigned int k = 0;
114*4882a593Smuzhiyun u16 rx_tx_status;
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun while (rx_tx_status & STATE_RX_DATA_AVAILABLE) {
119*4882a593Smuzhiyun u16 rx;
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun if (rx_tx_status & STATE_RX_DATA_LAST)
122*4882a593Smuzhiyun rx_ctr++;
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun FPGA_GET_REG(fpga, ep.receive_data, &rx);
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun ++k;
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun
io_reflect(unsigned int fpga)132*4882a593Smuzhiyun static void io_reflect(unsigned int fpga)
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun u16 buffer[128];
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun unsigned int k = 0;
137*4882a593Smuzhiyun unsigned int n;
138*4882a593Smuzhiyun u16 rx_tx_status;
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun while (rx_tx_status & STATE_RX_DATA_AVAILABLE) {
143*4882a593Smuzhiyun FPGA_GET_REG(fpga, ep.receive_data, &buffer[k++]);
144*4882a593Smuzhiyun if (rx_tx_status & STATE_RX_DATA_LAST)
145*4882a593Smuzhiyun break;
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun if (!k)
151*4882a593Smuzhiyun return;
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun for (n = 0; n < k; ++n)
154*4882a593Smuzhiyun FPGA_SET_REG(fpga, ep.transmit_data, buffer[n]);
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun FPGA_SET_REG(fpga, ep.rx_tx_control,
157*4882a593Smuzhiyun CTRL_PROC_RECEIVE_ENABLE | CTRL_FLUSH_TRANSMIT_BUFFER);
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun tx_ctr++;
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun /*
163*4882a593Smuzhiyun * FPGA io-endpoint reflector
164*4882a593Smuzhiyun *
165*4882a593Smuzhiyun * Syntax:
166*4882a593Smuzhiyun * ioreflect {fpga} {reportrate}
167*4882a593Smuzhiyun */
do_ioreflect(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])168*4882a593Smuzhiyun int do_ioreflect(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
169*4882a593Smuzhiyun {
170*4882a593Smuzhiyun unsigned int fpga;
171*4882a593Smuzhiyun unsigned int rate = 0;
172*4882a593Smuzhiyun unsigned long long last_seen = 0;
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun if (argc < 2)
175*4882a593Smuzhiyun return CMD_RET_USAGE;
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun fpga = simple_strtoul(argv[1], NULL, 10);
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun /*
180*4882a593Smuzhiyun * If another parameter, it is the report rate in packets.
181*4882a593Smuzhiyun */
182*4882a593Smuzhiyun if (argc > 2)
183*4882a593Smuzhiyun rate = simple_strtoul(argv[2], NULL, 10);
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun /* enable receive path */
186*4882a593Smuzhiyun FPGA_SET_REG(fpga, ep.rx_tx_control, CTRL_PROC_RECEIVE_ENABLE);
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun /* set device address to dummy 1*/
189*4882a593Smuzhiyun FPGA_SET_REG(fpga, ep.device_address, 1);
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun rx_ctr = 0; tx_ctr = 0; err_ctr = 0;
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun while (1) {
194*4882a593Smuzhiyun u16 top_int;
195*4882a593Smuzhiyun u16 rx_tx_status;
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun FPGA_GET_REG(fpga, top_interrupt, &top_int);
198*4882a593Smuzhiyun FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun io_check_status(fpga, rx_tx_status, true);
201*4882a593Smuzhiyun if ((top_int & IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS) &&
202*4882a593Smuzhiyun (top_int & IRQ_CPU_TRANSMITBUFFER_FREE_STATUS))
203*4882a593Smuzhiyun io_reflect(fpga);
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun if (rate) {
206*4882a593Smuzhiyun if (!(tx_ctr % rate) && (tx_ctr != last_seen))
207*4882a593Smuzhiyun printf("refl %llu, err %llu\n", tx_ctr,
208*4882a593Smuzhiyun err_ctr);
209*4882a593Smuzhiyun last_seen = tx_ctr;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun if (ctrlc())
213*4882a593Smuzhiyun break;
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun return 0;
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun /*
220*4882a593Smuzhiyun * FPGA io-endpoint looptest
221*4882a593Smuzhiyun *
222*4882a593Smuzhiyun * Syntax:
223*4882a593Smuzhiyun * ioloop {fpga} {size} {rate}
224*4882a593Smuzhiyun */
225*4882a593Smuzhiyun #define DISP_LINE_LEN 16
do_ioloop(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])226*4882a593Smuzhiyun int do_ioloop(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
227*4882a593Smuzhiyun {
228*4882a593Smuzhiyun unsigned int fpga;
229*4882a593Smuzhiyun unsigned int size;
230*4882a593Smuzhiyun unsigned int rate = 0;
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun if (argc < 3)
233*4882a593Smuzhiyun return CMD_RET_USAGE;
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun /*
236*4882a593Smuzhiyun * FPGA is specified since argc > 2
237*4882a593Smuzhiyun */
238*4882a593Smuzhiyun fpga = simple_strtoul(argv[1], NULL, 10);
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun /*
241*4882a593Smuzhiyun * packet size is specified since argc > 2
242*4882a593Smuzhiyun */
243*4882a593Smuzhiyun size = simple_strtoul(argv[2], NULL, 10);
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun /*
246*4882a593Smuzhiyun * If another parameter, it is the test rate in packets per second.
247*4882a593Smuzhiyun */
248*4882a593Smuzhiyun if (argc > 3)
249*4882a593Smuzhiyun rate = simple_strtoul(argv[3], NULL, 10);
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun /* enable receive path */
252*4882a593Smuzhiyun FPGA_SET_REG(fpga, ep.rx_tx_control, CTRL_PROC_RECEIVE_ENABLE);
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun /* set device address to dummy 1*/
255*4882a593Smuzhiyun FPGA_SET_REG(fpga, ep.device_address, 1);
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun rx_ctr = 0; tx_ctr = 0; err_ctr = 0;
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun while (1) {
260*4882a593Smuzhiyun u16 top_int;
261*4882a593Smuzhiyun u16 rx_tx_status;
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun FPGA_GET_REG(fpga, top_interrupt, &top_int);
264*4882a593Smuzhiyun FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun io_check_status(fpga, rx_tx_status, false);
267*4882a593Smuzhiyun if (top_int & IRQ_CPU_TRANSMITBUFFER_FREE_STATUS)
268*4882a593Smuzhiyun io_send(fpga, size);
269*4882a593Smuzhiyun if (top_int & IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS)
270*4882a593Smuzhiyun io_receive(fpga);
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun if (rate) {
273*4882a593Smuzhiyun if (ctrlc())
274*4882a593Smuzhiyun break;
275*4882a593Smuzhiyun udelay(1000000 / rate);
276*4882a593Smuzhiyun if (!(tx_ctr % rate))
277*4882a593Smuzhiyun printf("d %lld, tx %llu, rx %llu, err %llu\n",
278*4882a593Smuzhiyun tx_ctr - rx_ctr, tx_ctr, rx_ctr,
279*4882a593Smuzhiyun err_ctr);
280*4882a593Smuzhiyun }
281*4882a593Smuzhiyun }
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun return 0;
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun U_BOOT_CMD(
287*4882a593Smuzhiyun ioloop, 4, 0, do_ioloop,
288*4882a593Smuzhiyun "fpga io-endpoint looptest",
289*4882a593Smuzhiyun "fpga packetsize [packets/sec]"
290*4882a593Smuzhiyun );
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun U_BOOT_CMD(
293*4882a593Smuzhiyun ioreflect, 3, 0, do_ioreflect,
294*4882a593Smuzhiyun "fpga io-endpoint reflector",
295*4882a593Smuzhiyun "fpga reportrate"
296*4882a593Smuzhiyun );
297