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#include <console.h>
  11
  12#include <gdsys_fpga.h>
  13
  14enum {
  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
  32enum {
  33        CTRL_PROC_RECEIVE_ENABLE = 1<<12,
  34        CTRL_FLUSH_TRANSMIT_BUFFER = 1<<15,
  35};
  36
  37enum {
  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
  44struct 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
  52unsigned long long rx_ctr;
  53unsigned long long tx_ctr;
  54unsigned long long err_ctr;
  55
  56static 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
  89static 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
 111static 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
 132static 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 */
 168int 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
 226int 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
 286U_BOOT_CMD(
 287        ioloop, 4,      0,      do_ioloop,
 288        "fpga io-endpoint looptest",
 289        "fpga packetsize [packets/sec]"
 290);
 291
 292U_BOOT_CMD(
 293        ioreflect, 3,   0,      do_ioreflect,
 294        "fpga io-endpoint reflector",
 295        "fpga reportrate"
 296);
 297