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