uboot/board/gdsys/common/cmd_ioloop.c
<<
>>
Prefs
   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 = simple_strtoul(argv[1], NULL, 10);
 279
 280        /*
 281         * If another parameter, it is the report rate in packets.
 282         */
 283        if (argc > 2)
 284                rate = simple_strtoul(argv[2], NULL, 10);
 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 = simple_strtoul(argv[1], NULL, 10);
 392
 393        /*
 394         * packet size is specified since argc > 2
 395         */
 396        size = simple_strtoul(argv[2], NULL, 10);
 397
 398        /*
 399         * If another parameter, it is the test rate in packets per second.
 400         */
 401        if (argc > 3)
 402                rate = simple_strtoul(argv[3], NULL, 10);
 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 = simple_strtoul(argv[2], NULL, 10);
 467
 468        /*
 469         * If another parameter, it is the test rate in packets per second.
 470         */
 471        if (argc > 2)
 472                rate = simple_strtoul(argv[3], NULL, 10);
 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 = simple_strtoul(argv[1], NULL, 10);
 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