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