123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 |
- /*
- * (C) Copyright 2014
- * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
- #include <common.h>
- #include <command.h>
- #include <console.h>
- #include <gdsys_fpga.h>
- enum {
- STATE_TX_PACKET_BUILDING = 1<<0,
- STATE_TX_TRANSMITTING = 1<<1,
- STATE_TX_BUFFER_FULL = 1<<2,
- STATE_TX_ERR = 1<<3,
- STATE_RECEIVE_TIMEOUT = 1<<4,
- STATE_PROC_RX_STORE_TIMEOUT = 1<<5,
- STATE_PROC_RX_RECEIVE_TIMEOUT = 1<<6,
- STATE_RX_DIST_ERR = 1<<7,
- STATE_RX_LENGTH_ERR = 1<<8,
- STATE_RX_FRAME_CTR_ERR = 1<<9,
- STATE_RX_FCS_ERR = 1<<10,
- STATE_RX_PACKET_DROPPED = 1<<11,
- STATE_RX_DATA_LAST = 1<<12,
- STATE_RX_DATA_FIRST = 1<<13,
- STATE_RX_DATA_AVAILABLE = 1<<15,
- };
- enum {
- CTRL_PROC_RECEIVE_ENABLE = 1<<12,
- CTRL_FLUSH_TRANSMIT_BUFFER = 1<<15,
- };
- enum {
- IRQ_CPU_TRANSMITBUFFER_FREE_STATUS = 1<<5,
- IRQ_CPU_PACKET_TRANSMITTED_EVENT = 1<<6,
- IRQ_NEW_CPU_PACKET_RECEIVED_EVENT = 1<<7,
- IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS = 1<<8,
- };
- struct io_generic_packet {
- u16 target_address;
- u16 source_address;
- u8 packet_type;
- u8 bc;
- u16 packet_length;
- } __attribute__((__packed__));
- unsigned long long rx_ctr;
- unsigned long long tx_ctr;
- unsigned long long err_ctr;
- static void io_check_status(unsigned int fpga, u16 status, bool silent)
- {
- u16 mask = STATE_RX_DIST_ERR | STATE_RX_LENGTH_ERR |
- STATE_RX_FRAME_CTR_ERR | STATE_RX_FCS_ERR |
- STATE_RX_PACKET_DROPPED | STATE_TX_ERR;
- if (!(status & mask)) {
- FPGA_SET_REG(fpga, ep.rx_tx_status, status);
- return;
- }
- err_ctr++;
- FPGA_SET_REG(fpga, ep.rx_tx_status, status);
- if (silent)
- return;
- if (status & STATE_RX_PACKET_DROPPED)
- printf("RX_PACKET_DROPPED, status %04x\n", status);
- if (status & STATE_RX_DIST_ERR)
- printf("RX_DIST_ERR\n");
- if (status & STATE_RX_LENGTH_ERR)
- printf("RX_LENGTH_ERR\n");
- if (status & STATE_RX_FRAME_CTR_ERR)
- printf("RX_FRAME_CTR_ERR\n");
- if (status & STATE_RX_FCS_ERR)
- printf("RX_FCS_ERR\n");
- if (status & STATE_TX_ERR)
- printf("TX_ERR\n");
- }
- static void io_send(unsigned int fpga, unsigned int size)
- {
- unsigned int k;
- struct io_generic_packet packet = {
- .source_address = 1,
- .packet_type = 1,
- .packet_length = size,
- };
- u16 *p = (u16 *)&packet;
- for (k = 0; k < sizeof(packet) / 2; ++k)
- FPGA_SET_REG(fpga, ep.transmit_data, *p++);
- for (k = 0; k < (size + 1) / 2; ++k)
- FPGA_SET_REG(fpga, ep.transmit_data, k);
- FPGA_SET_REG(fpga, ep.rx_tx_control,
- CTRL_PROC_RECEIVE_ENABLE | CTRL_FLUSH_TRANSMIT_BUFFER);
- tx_ctr++;
- }
- static void io_receive(unsigned int fpga)
- {
- unsigned int k = 0;
- u16 rx_tx_status;
- FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
- while (rx_tx_status & STATE_RX_DATA_AVAILABLE) {
- u16 rx;
- if (rx_tx_status & STATE_RX_DATA_LAST)
- rx_ctr++;
- FPGA_GET_REG(fpga, ep.receive_data, &rx);
- FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
- ++k;
- }
- }
- static void io_reflect(unsigned int fpga)
- {
- u16 buffer[128];
- unsigned int k = 0;
- unsigned int n;
- u16 rx_tx_status;
- FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
- while (rx_tx_status & STATE_RX_DATA_AVAILABLE) {
- FPGA_GET_REG(fpga, ep.receive_data, &buffer[k++]);
- if (rx_tx_status & STATE_RX_DATA_LAST)
- break;
- FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
- }
- if (!k)
- return;
- for (n = 0; n < k; ++n)
- FPGA_SET_REG(fpga, ep.transmit_data, buffer[n]);
- FPGA_SET_REG(fpga, ep.rx_tx_control,
- CTRL_PROC_RECEIVE_ENABLE | CTRL_FLUSH_TRANSMIT_BUFFER);
- tx_ctr++;
- }
- /*
- * FPGA io-endpoint reflector
- *
- * Syntax:
- * ioreflect {fpga} {reportrate}
- */
- int do_ioreflect(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
- {
- unsigned int fpga;
- unsigned int rate = 0;
- unsigned long long last_seen = 0;
- if (argc < 2)
- return CMD_RET_USAGE;
- fpga = simple_strtoul(argv[1], NULL, 10);
- /*
- * If another parameter, it is the report rate in packets.
- */
- if (argc > 2)
- rate = simple_strtoul(argv[2], NULL, 10);
- /* enable receive path */
- FPGA_SET_REG(fpga, ep.rx_tx_control, CTRL_PROC_RECEIVE_ENABLE);
- /* set device address to dummy 1*/
- FPGA_SET_REG(fpga, ep.device_address, 1);
- rx_ctr = 0; tx_ctr = 0; err_ctr = 0;
- while (1) {
- u16 top_int;
- u16 rx_tx_status;
- FPGA_GET_REG(fpga, top_interrupt, &top_int);
- FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
- io_check_status(fpga, rx_tx_status, true);
- if ((top_int & IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS) &&
- (top_int & IRQ_CPU_TRANSMITBUFFER_FREE_STATUS))
- io_reflect(fpga);
- if (rate) {
- if (!(tx_ctr % rate) && (tx_ctr != last_seen))
- printf("refl %llu, err %llu\n", tx_ctr,
- err_ctr);
- last_seen = tx_ctr;
- }
- if (ctrlc())
- break;
- }
- return 0;
- }
- /*
- * FPGA io-endpoint looptest
- *
- * Syntax:
- * ioloop {fpga} {size} {rate}
- */
- #define DISP_LINE_LEN 16
- int do_ioloop(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
- {
- unsigned int fpga;
- unsigned int size;
- unsigned int rate = 0;
- if (argc < 3)
- return CMD_RET_USAGE;
- /*
- * FPGA is specified since argc > 2
- */
- fpga = simple_strtoul(argv[1], NULL, 10);
- /*
- * packet size is specified since argc > 2
- */
- size = simple_strtoul(argv[2], NULL, 10);
- /*
- * If another parameter, it is the test rate in packets per second.
- */
- if (argc > 3)
- rate = simple_strtoul(argv[3], NULL, 10);
- /* enable receive path */
- FPGA_SET_REG(fpga, ep.rx_tx_control, CTRL_PROC_RECEIVE_ENABLE);
- /* set device address to dummy 1*/
- FPGA_SET_REG(fpga, ep.device_address, 1);
- rx_ctr = 0; tx_ctr = 0; err_ctr = 0;
- while (1) {
- u16 top_int;
- u16 rx_tx_status;
- FPGA_GET_REG(fpga, top_interrupt, &top_int);
- FPGA_GET_REG(fpga, ep.rx_tx_status, &rx_tx_status);
- io_check_status(fpga, rx_tx_status, false);
- if (top_int & IRQ_CPU_TRANSMITBUFFER_FREE_STATUS)
- io_send(fpga, size);
- if (top_int & IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS)
- io_receive(fpga);
- if (rate) {
- if (ctrlc())
- break;
- udelay(1000000 / rate);
- if (!(tx_ctr % rate))
- printf("d %lld, tx %llu, rx %llu, err %llu\n",
- tx_ctr - rx_ctr, tx_ctr, rx_ctr,
- err_ctr);
- }
- }
- return 0;
- }
- U_BOOT_CMD(
- ioloop, 4, 0, do_ioloop,
- "fpga io-endpoint looptest",
- "fpga packetsize [packets/sec]"
- );
- U_BOOT_CMD(
- ioreflect, 3, 0, do_ioreflect,
- "fpga io-endpoint reflector",
- "fpga reportrate"
- );
|