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