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 ); 296