]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/gdsys/common/cmd_ioloop.c
Merge branch 'master' of git://git.denx.de/u-boot-usb
[karo-tx-uboot.git] / board / gdsys / common / cmd_ioloop.c
1 /*
2  * (C) Copyright 2014
3  * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 #include <common.h>
9 #include <command.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
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
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
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
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  */
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
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 );