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#include <linux/bitops.h> 11#include <linux/delay.h> 12 13#include <gdsys_fpga.h> 14 15#ifndef CONFIG_GDSYS_LEGACY_DRIVERS 16#include <dm.h> 17#include <misc.h> 18#include <regmap.h> 19#include <sysinfo.h> 20 21#include "../../../drivers/misc/gdsys_soc.h" 22#include "../../../drivers/misc/gdsys_ioep.h" 23#include "../../../drivers/misc/ihs_fpga.h" 24 25const int HEADER_WORDS = sizeof(struct io_generic_packet) / 2; 26#endif /* !CONFIG_GDSYS_LEGACY_DRIVERS */ 27 28enum status_print_type { 29 STATUS_LOUD = 0, 30 STATUS_SILENT = 1, 31}; 32 33#ifdef CONFIG_GDSYS_LEGACY_DRIVERS 34enum { 35 STATE_TX_PACKET_BUILDING = BIT(0), 36 STATE_TX_TRANSMITTING = BIT(1), 37 STATE_TX_BUFFER_FULL = BIT(2), 38 STATE_TX_ERR = BIT(3), 39 STATE_RECEIVE_TIMEOUT = BIT(4), 40 STATE_PROC_RX_STORE_TIMEOUT = BIT(5), 41 STATE_PROC_RX_RECEIVE_TIMEOUT = BIT(6), 42 STATE_RX_DIST_ERR = BIT(7), 43 STATE_RX_LENGTH_ERR = BIT(8), 44 STATE_RX_FRAME_CTR_ERR = BIT(9), 45 STATE_RX_FCS_ERR = BIT(10), 46 STATE_RX_PACKET_DROPPED = BIT(11), 47 STATE_RX_DATA_LAST = BIT(12), 48 STATE_RX_DATA_FIRST = BIT(13), 49 STATE_RX_DATA_AVAILABLE = BIT(15), 50}; 51 52enum { 53 IRQ_CPU_TRANSMITBUFFER_FREE_STATUS = BIT(5), 54 IRQ_CPU_PACKET_TRANSMITTED_EVENT = BIT(6), 55 IRQ_NEW_CPU_PACKET_RECEIVED_EVENT = BIT(7), 56 IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS = BIT(8), 57}; 58 59enum { 60 CTRL_PROC_RECEIVE_ENABLE = BIT(12), 61 CTRL_FLUSH_TRANSMIT_BUFFER = BIT(15), 62}; 63 64struct io_generic_packet { 65 u16 target_address; 66 u16 source_address; 67 u8 packet_type; 68 u8 bc; 69 u16 packet_length; 70} __attribute__((__packed__)); 71#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */ 72 73unsigned long long rx_ctr; 74unsigned long long tx_ctr; 75unsigned long long err_ctr; 76#ifndef CONFIG_GDSYS_LEGACY_DRIVERS 77struct udevice *dev; 78#endif /* !CONFIG_GDSYS_LEGACY_DRIVERS */ 79 80#ifdef CONFIG_GDSYS_LEGACY_DRIVERS 81static void io_check_status(uint fpga, u16 status, enum status_print_type type) 82{ 83 u16 mask = STATE_RX_DIST_ERR | STATE_RX_LENGTH_ERR | 84 STATE_RX_FRAME_CTR_ERR | STATE_RX_FCS_ERR | 85 STATE_RX_PACKET_DROPPED | STATE_TX_ERR; 86 87 if (!(status & mask)) { 88 FPGA_SET_REG(fpga, ep.rx_tx_status, status); 89 return; 90 } 91 92 err_ctr++; 93 FPGA_SET_REG(fpga, ep.rx_tx_status, status); 94 95 if (type == STATUS_SILENT) 96 return; 97 98 if (status & STATE_RX_PACKET_DROPPED) 99 printf("RX_PACKET_DROPPED, status %04x\n", status); 100 101 if (status & STATE_RX_DIST_ERR) 102 printf("RX_DIST_ERR\n"); 103 if (status & STATE_RX_LENGTH_ERR) 104 printf("RX_LENGTH_ERR\n"); 105 if (status & STATE_RX_FRAME_CTR_ERR) 106 printf("RX_FRAME_CTR_ERR\n"); 107 if (status & STATE_RX_FCS_ERR) 108 printf("RX_FCS_ERR\n"); 109 110 if (status & STATE_TX_ERR) 111 printf("TX_ERR\n"); 112} 113#else 114static void io_check_status(struct udevice *dev, enum status_print_type type) 115{ 116 u16 status = 0; 117 int ret; 118 119 ret = misc_call(dev, 0, NULL, 0, &status, 0); 120 if (!ret) 121 return; 122 123 err_ctr++; 124 125 if (type != STATUS_LOUD) 126 return; 127 128 if (status & STATE_RX_PACKET_DROPPED) 129 printf("RX_PACKET_DROPPED, status %04x\n", status); 130 131 if (status & STATE_RX_DIST_ERR) 132 printf("RX_DIST_ERR\n"); 133 if (status & STATE_RX_LENGTH_ERR) 134 printf("RX_LENGTH_ERR\n"); 135 if (status & STATE_RX_FRAME_CTR_ERR) 136 printf("RX_FRAME_CTR_ERR\n"); 137 if (status & STATE_RX_FCS_ERR) 138 printf("RX_FCS_ERR\n"); 139 140 if (status & STATE_TX_ERR) 141 printf("TX_ERR\n"); 142} 143#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */ 144 145#ifdef CONFIG_GDSYS_LEGACY_DRIVERS 146static void io_send(uint fpga, uint size) 147{ 148 uint k; 149 struct io_generic_packet packet = { 150 .source_address = 1, 151 .packet_type = 1, 152 .packet_length = size, 153 }; 154 u16 *p = (u16 *)&packet; 155 156 for (k = 0; k < sizeof(packet) / 2; ++k) 157 FPGA_SET_REG(fpga, ep.transmit_data, *p++); 158 159 for (k = 0; k < (size + 1) / 2; ++k) 160 FPGA_SET_REG(fpga, ep.transmit_data, k); 161 162 FPGA_SET_REG(fpga, ep.rx_tx_control, 163 CTRL_PROC_RECEIVE_ENABLE | CTRL_FLUSH_TRANSMIT_BUFFER); 164 165 tx_ctr++; 166} 167#else 168static void io_send(struct udevice *dev, uint size) 169{ 170 uint k; 171 u16 buffer[HEADER_WORDS + 128]; 172 struct io_generic_packet header = { 173 .source_address = 1, 174 .packet_type = 1, 175 .packet_length = size, 176 }; 177 const uint words = (size + 1) / 2; 178 179 memcpy(buffer, &header, 2 * HEADER_WORDS); 180 for (k = 0; k < words; ++k) 181 buffer[k + HEADER_WORDS] = (2 * k + 1) + ((2 * k) << 8); 182 183 misc_write(dev, 0, buffer, HEADER_WORDS + words); 184 185 tx_ctr++; 186} 187#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */ 188 189#ifdef CONFIG_GDSYS_LEGACY_DRIVERS 190static void io_receive(uint fpga) 191{ 192 u16 rx_tx_status; 193 194 FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status); 195 196 while (rx_tx_status & STATE_RX_DATA_AVAILABLE) { 197 u16 rx; 198 199 if (rx_tx_status & STATE_RX_DATA_LAST) 200 rx_ctr++; 201 202 FPGA_GET_REG(fpga, ep.receive_data, &rx); 203 204 FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status); 205 } 206} 207#else 208static void io_receive(struct udevice *dev) 209{ 210 u16 buffer[HEADER_WORDS + 128]; 211 212 if (!misc_read(dev, 0, buffer, 0)) 213 rx_ctr++; 214} 215#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */ 216 217#ifdef CONFIG_GDSYS_LEGACY_DRIVERS 218static void io_reflect(uint fpga) 219{ 220 u16 buffer[128]; 221 222 uint k = 0; 223 uint n; 224 u16 rx_tx_status; 225 226 FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status); 227 228 while (rx_tx_status & STATE_RX_DATA_AVAILABLE) { 229 FPGA_GET_REG(fpga, ep.receive_data, &buffer[k++]); 230 if (rx_tx_status & STATE_RX_DATA_LAST) 231 break; 232 233 FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status); 234 } 235 236 if (!k) 237 return; 238 239 for (n = 0; n < k; ++n) 240 FPGA_SET_REG(fpga, ep.transmit_data, buffer[n]); 241 242 FPGA_SET_REG(fpga, ep.rx_tx_control, 243 CTRL_PROC_RECEIVE_ENABLE | CTRL_FLUSH_TRANSMIT_BUFFER); 244 245 tx_ctr++; 246} 247#else 248static void io_reflect(struct udevice *dev) 249{ 250 u16 buffer[HEADER_WORDS + 128]; 251 struct io_generic_packet *header; 252 253 if (misc_read(dev, 0, buffer, 0)) 254 return; 255 256 header = (struct io_generic_packet *)&buffer; 257 258 misc_write(dev, 0, buffer, HEADER_WORDS + header->packet_length); 259} 260#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */ 261 262#ifdef CONFIG_GDSYS_LEGACY_DRIVERS 263/* 264 * FPGA io-endpoint reflector 265 * 266 * Syntax: 267 * ioreflect {fpga} {reportrate} 268 */ 269int do_ioreflect(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) 270{ 271 uint fpga; 272 uint rate = 0; 273 unsigned long long last_seen = 0; 274 275 if (argc < 2) 276 return CMD_RET_USAGE; 277 278 fpga = dectoul(argv[1], NULL); 279 280 /* 281 * If another parameter, it is the report rate in packets. 282 */ 283 if (argc > 2) 284 rate = dectoul(argv[2], NULL); 285 286 /* Enable receive path */ 287 FPGA_SET_REG(fpga, ep.rx_tx_control, CTRL_PROC_RECEIVE_ENABLE); 288 289 /* Set device address to dummy 1*/ 290 FPGA_SET_REG(fpga, ep.device_address, 1); 291 292 rx_ctr = 0; tx_ctr = 0; err_ctr = 0; 293 294 while (1) { 295 u16 top_int; 296 u16 rx_tx_status; 297 298 FPGA_GET_REG(fpga, top_interrupt, &top_int); 299 FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status); 300 301 io_check_status(fpga, rx_tx_status, STATUS_SILENT); 302 if ((top_int & IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS) && 303 (top_int & IRQ_CPU_TRANSMITBUFFER_FREE_STATUS)) 304 io_reflect(fpga); 305 306 if (rate) { 307 if (!(tx_ctr % rate) && (tx_ctr != last_seen)) 308 printf("refl %llu, err %llu\n", tx_ctr, 309 err_ctr); 310 last_seen = tx_ctr; 311 } 312 313 if (ctrlc()) 314 break; 315 } 316 317 return 0; 318} 319#else 320/* 321 * FPGA io-endpoint reflector 322 * 323 * Syntax: 324 * ioreflect {reportrate} 325 */ 326int do_ioreflect(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) 327{ 328 struct udevice *fpga; 329 struct regmap *map; 330 uint rate = 0; 331 unsigned long long last_seen = 0; 332 333 if (!dev) { 334 printf("No device selected\n"); 335 return 1; 336 } 337 338 gdsys_soc_get_fpga(dev, &fpga); 339 regmap_init_mem(dev_ofnode(dev), &map); 340 341 /* Enable receive path */ 342 misc_set_enabled(dev, true); 343 344 rx_ctr = 0; tx_ctr = 0; err_ctr = 0; 345 346 while (1) { 347 uint top_int; 348 349 ihs_fpga_get(map, top_interrupt, &top_int); 350 io_check_status(dev, STATUS_SILENT); 351 if ((top_int & IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS) && 352 (top_int & IRQ_CPU_TRANSMITBUFFER_FREE_STATUS)) 353 io_reflect(dev); 354 355 if (rate) { 356 if (!(tx_ctr % rate) && (tx_ctr != last_seen)) 357 printf("refl %llu, err %llu\n", tx_ctr, 358 err_ctr); 359 last_seen = tx_ctr; 360 } 361 362 if (ctrlc()) 363 break; 364 } 365 366 return 0; 367} 368#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */ 369 370#define DISP_LINE_LEN 16 371 372#ifdef CONFIG_GDSYS_LEGACY_DRIVERS 373/* 374 * FPGA io-endpoint looptest 375 * 376 * Syntax: 377 * ioloop {fpga} {size} {rate} 378 */ 379int do_ioloop(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) 380{ 381 uint fpga; 382 uint size; 383 uint rate = 0; 384 385 if (argc < 3) 386 return CMD_RET_USAGE; 387 388 /* 389 * FPGA is specified since argc > 2 390 */ 391 fpga = dectoul(argv[1], NULL); 392 393 /* 394 * packet size is specified since argc > 2 395 */ 396 size = dectoul(argv[2], NULL); 397 398 /* 399 * If another parameter, it is the test rate in packets per second. 400 */ 401 if (argc > 3) 402 rate = dectoul(argv[3], NULL); 403 404 /* enable receive path */ 405 FPGA_SET_REG(fpga, ep.rx_tx_control, CTRL_PROC_RECEIVE_ENABLE); 406 407 /* set device address to dummy 1*/ 408 FPGA_SET_REG(fpga, ep.device_address, 1); 409 410 rx_ctr = 0; tx_ctr = 0; err_ctr = 0; 411 412 while (1) { 413 u16 top_int; 414 u16 rx_tx_status; 415 416 FPGA_GET_REG(fpga, top_interrupt, &top_int); 417 FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status); 418 419 io_check_status(fpga, rx_tx_status, STATUS_LOUD); 420 if (top_int & IRQ_CPU_TRANSMITBUFFER_FREE_STATUS) 421 io_send(fpga, size); 422 if (top_int & IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS) 423 io_receive(fpga); 424 425 if (rate) { 426 if (ctrlc()) 427 break; 428 udelay(1000000 / rate); 429 if (!(tx_ctr % rate)) 430 printf("d %llu, tx %llu, rx %llu, err %llu\n", 431 tx_ctr - rx_ctr, tx_ctr, rx_ctr, 432 err_ctr); 433 } 434 } 435 436 return 0; 437} 438#else 439/* 440 * FPGA io-endpoint looptest 441 * 442 * Syntax: 443 * ioloop {size} {rate} 444 */ 445int do_ioloop(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) 446{ 447 uint size; 448 uint rate = 0; 449 struct udevice *fpga; 450 struct regmap *map; 451 452 if (!dev) { 453 printf("No device selected\n"); 454 return 1; 455 } 456 457 gdsys_soc_get_fpga(dev, &fpga); 458 regmap_init_mem(dev_ofnode(dev), &map); 459 460 if (argc < 2) 461 return CMD_RET_USAGE; 462 463 /* 464 * packet size is specified since argc > 1 465 */ 466 size = dectoul(argv[2], NULL); 467 468 /* 469 * If another parameter, it is the test rate in packets per second. 470 */ 471 if (argc > 2) 472 rate = dectoul(argv[3], NULL); 473 474 /* Enable receive path */ 475 misc_set_enabled(dev, true); 476 477 rx_ctr = 0; tx_ctr = 0; err_ctr = 0; 478 479 while (1) { 480 uint top_int; 481 482 if (ctrlc()) 483 break; 484 485 ihs_fpga_get(map, top_interrupt, &top_int); 486 487 io_check_status(dev, STATUS_LOUD); 488 if (top_int & IRQ_CPU_TRANSMITBUFFER_FREE_STATUS) 489 io_send(dev, size); 490 if (top_int & IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS) 491 io_receive(dev); 492 493 if (rate) { 494 udelay(1000000 / rate); 495 if (!(tx_ctr % rate)) 496 printf("d %llu, tx %llu, rx %llu, err %llu\n", 497 tx_ctr - rx_ctr, tx_ctr, rx_ctr, 498 err_ctr); 499 } 500 } 501 return 0; 502} 503#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */ 504 505#ifndef CONFIG_GDSYS_LEGACY_DRIVERS 506int do_iodev(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) 507{ 508 struct udevice *ioep = NULL; 509 struct udevice *sysinfo; 510 char name[8]; 511 int ret; 512 513 if (sysinfo_get(&sysinfo)) 514 return CMD_RET_FAILURE; 515 516 if (argc > 1) { 517 int i = dectoul(argv[1], NULL); 518 519 snprintf(name, sizeof(name), "ioep%d", i); 520 521 ret = uclass_get_device_by_phandle(UCLASS_MISC, sysinfo, name, 522 &ioep); 523 524 if (ret || !ioep) { 525 printf("Invalid IOEP %d\n", i); 526 return CMD_RET_FAILURE; 527 } 528 529 dev = ioep; 530 } else { 531 int i = 0; 532 533 while (1) { 534 snprintf(name, sizeof(name), "ioep%d", i); 535 536 ret = uclass_get_device_by_phandle(UCLASS_MISC, sysinfo, 537 name, &ioep); 538 539 if (ret || !ioep) 540 break; 541 542 printf("IOEP %d:\t%s\n", i++, ioep->name); 543 } 544 545 if (dev) 546 printf("\nSelected IOEP: %s\n", dev->name); 547 else 548 puts("\nNo IOEP selected.\n"); 549 } 550 551 return 0; 552} 553#endif /* !CONFIG_GDSYS_LEGACY_DRIVERS */ 554 555#ifdef CONFIG_GDSYS_LEGACY_DRIVERS 556U_BOOT_CMD( 557 ioloop, 4, 0, do_ioloop, 558 "fpga io-endpoint looptest", 559 "fpga packetsize [packets/sec]" 560); 561 562U_BOOT_CMD( 563 ioreflect, 3, 0, do_ioreflect, 564 "fpga io-endpoint reflector", 565 "fpga reportrate" 566); 567#else 568U_BOOT_CMD( 569 ioloop, 3, 0, do_ioloop, 570 "fpga io-endpoint looptest", 571 "packetsize [packets/sec]" 572); 573 574U_BOOT_CMD( 575 ioreflect, 2, 0, do_ioreflect, 576 "fpga io-endpoint reflector", 577 "reportrate" 578); 579 580U_BOOT_CMD( 581 iodev, 2, 0, do_iodev, 582 "fpga io-endpoint listing/selection", 583 "[ioep device to select]" 584); 585#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */ 586