uboot/board/gdsys/common/cmd_ioloop.c
<<
>>
Prefs
   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
  13enum {
  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
  31enum {
  32        CTRL_PROC_RECEIVE_ENABLE = 1<<12,
  33        CTRL_FLUSH_TRANSMIT_BUFFER = 1<<15,
  34};
  35
  36enum {
  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
  43struct 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
  51unsigned long long rx_ctr;
  52unsigned long long tx_ctr;
  53unsigned long long err_ctr;
  54
  55static 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
  88static 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
 110static 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
 131static 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 */
 167int 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
 225int 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
 285U_BOOT_CMD(
 286        ioloop, 4,      0,      do_ioloop,
 287        "fpga io-endpoint looptest",
 288        "fpga packetsize [packets/sec]"
 289);
 290
 291U_BOOT_CMD(
 292        ioreflect, 3,   0,      do_ioreflect,
 293        "fpga io-endpoint reflector",
 294        "fpga reportrate"
 295);
 296