aboutsummaryrefslogtreecommitdiffstats
path: root/roms/u-boot/board/gdsys/common/cmd_ioloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'roms/u-boot/board/gdsys/common/cmd_ioloop.c')
-rw-r--r--roms/u-boot/board/gdsys/common/cmd_ioloop.c585
1 files changed, 585 insertions, 0 deletions
diff --git a/roms/u-boot/board/gdsys/common/cmd_ioloop.c b/roms/u-boot/board/gdsys/common/cmd_ioloop.c
new file mode 100644
index 000000000..658756d98
--- /dev/null
+++ b/roms/u-boot/board/gdsys/common/cmd_ioloop.c
@@ -0,0 +1,585 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2014
+ * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
+ */
+
+#include <common.h>
+#include <command.h>
+#include <console.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+
+#include <gdsys_fpga.h>
+
+#ifndef CONFIG_GDSYS_LEGACY_DRIVERS
+#include <dm.h>
+#include <misc.h>
+#include <regmap.h>
+#include <sysinfo.h>
+
+#include "../../../drivers/misc/gdsys_soc.h"
+#include "../../../drivers/misc/gdsys_ioep.h"
+#include "../../../drivers/misc/ihs_fpga.h"
+
+const int HEADER_WORDS = sizeof(struct io_generic_packet) / 2;
+#endif /* !CONFIG_GDSYS_LEGACY_DRIVERS */
+
+enum status_print_type {
+ STATUS_LOUD = 0,
+ STATUS_SILENT = 1,
+};
+
+#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
+enum {
+ STATE_TX_PACKET_BUILDING = BIT(0),
+ STATE_TX_TRANSMITTING = BIT(1),
+ STATE_TX_BUFFER_FULL = BIT(2),
+ STATE_TX_ERR = BIT(3),
+ STATE_RECEIVE_TIMEOUT = BIT(4),
+ STATE_PROC_RX_STORE_TIMEOUT = BIT(5),
+ STATE_PROC_RX_RECEIVE_TIMEOUT = BIT(6),
+ STATE_RX_DIST_ERR = BIT(7),
+ STATE_RX_LENGTH_ERR = BIT(8),
+ STATE_RX_FRAME_CTR_ERR = BIT(9),
+ STATE_RX_FCS_ERR = BIT(10),
+ STATE_RX_PACKET_DROPPED = BIT(11),
+ STATE_RX_DATA_LAST = BIT(12),
+ STATE_RX_DATA_FIRST = BIT(13),
+ STATE_RX_DATA_AVAILABLE = BIT(15),
+};
+
+enum {
+ IRQ_CPU_TRANSMITBUFFER_FREE_STATUS = BIT(5),
+ IRQ_CPU_PACKET_TRANSMITTED_EVENT = BIT(6),
+ IRQ_NEW_CPU_PACKET_RECEIVED_EVENT = BIT(7),
+ IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS = BIT(8),
+};
+
+enum {
+ CTRL_PROC_RECEIVE_ENABLE = BIT(12),
+ CTRL_FLUSH_TRANSMIT_BUFFER = BIT(15),
+};
+
+struct io_generic_packet {
+ u16 target_address;
+ u16 source_address;
+ u8 packet_type;
+ u8 bc;
+ u16 packet_length;
+} __attribute__((__packed__));
+#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
+
+unsigned long long rx_ctr;
+unsigned long long tx_ctr;
+unsigned long long err_ctr;
+#ifndef CONFIG_GDSYS_LEGACY_DRIVERS
+struct udevice *dev;
+#endif /* !CONFIG_GDSYS_LEGACY_DRIVERS */
+
+#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
+static void io_check_status(uint fpga, u16 status, enum status_print_type type)
+{
+ 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 (type == STATUS_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");
+}
+#else
+static void io_check_status(struct udevice *dev, enum status_print_type type)
+{
+ u16 status = 0;
+ int ret;
+
+ ret = misc_call(dev, 0, NULL, 0, &status, 0);
+ if (!ret)
+ return;
+
+ err_ctr++;
+
+ if (type != STATUS_LOUD)
+ 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");
+}
+#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
+
+#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
+static void io_send(uint fpga, uint size)
+{
+ uint 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++;
+}
+#else
+static void io_send(struct udevice *dev, uint size)
+{
+ uint k;
+ u16 buffer[HEADER_WORDS + 128];
+ struct io_generic_packet header = {
+ .source_address = 1,
+ .packet_type = 1,
+ .packet_length = size,
+ };
+ const uint words = (size + 1) / 2;
+
+ memcpy(buffer, &header, 2 * HEADER_WORDS);
+ for (k = 0; k < words; ++k)
+ buffer[k + HEADER_WORDS] = (2 * k + 1) + ((2 * k) << 8);
+
+ misc_write(dev, 0, buffer, HEADER_WORDS + words);
+
+ tx_ctr++;
+}
+#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
+
+#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
+static void io_receive(uint fpga)
+{
+ 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);
+ }
+}
+#else
+static void io_receive(struct udevice *dev)
+{
+ u16 buffer[HEADER_WORDS + 128];
+
+ if (!misc_read(dev, 0, buffer, 0))
+ rx_ctr++;
+}
+#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
+
+#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
+static void io_reflect(uint fpga)
+{
+ u16 buffer[128];
+
+ uint k = 0;
+ uint 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++;
+}
+#else
+static void io_reflect(struct udevice *dev)
+{
+ u16 buffer[HEADER_WORDS + 128];
+ struct io_generic_packet *header;
+
+ if (misc_read(dev, 0, buffer, 0))
+ return;
+
+ header = (struct io_generic_packet *)&buffer;
+
+ misc_write(dev, 0, buffer, HEADER_WORDS + header->packet_length);
+}
+#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
+
+#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
+/*
+ * FPGA io-endpoint reflector
+ *
+ * Syntax:
+ * ioreflect {fpga} {reportrate}
+ */
+int do_ioreflect(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ uint fpga;
+ uint 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, STATUS_SILENT);
+ 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;
+}
+#else
+/*
+ * FPGA io-endpoint reflector
+ *
+ * Syntax:
+ * ioreflect {reportrate}
+ */
+int do_ioreflect(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct udevice *fpga;
+ struct regmap *map;
+ uint rate = 0;
+ unsigned long long last_seen = 0;
+
+ if (!dev) {
+ printf("No device selected\n");
+ return 1;
+ }
+
+ gdsys_soc_get_fpga(dev, &fpga);
+ regmap_init_mem(dev_ofnode(dev), &map);
+
+ /* Enable receive path */
+ misc_set_enabled(dev, true);
+
+ rx_ctr = 0; tx_ctr = 0; err_ctr = 0;
+
+ while (1) {
+ uint top_int;
+
+ ihs_fpga_get(map, top_interrupt, &top_int);
+ io_check_status(dev, STATUS_SILENT);
+ if ((top_int & IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS) &&
+ (top_int & IRQ_CPU_TRANSMITBUFFER_FREE_STATUS))
+ io_reflect(dev);
+
+ 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;
+}
+#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
+
+#define DISP_LINE_LEN 16
+
+#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
+/*
+ * FPGA io-endpoint looptest
+ *
+ * Syntax:
+ * ioloop {fpga} {size} {rate}
+ */
+int do_ioloop(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ uint fpga;
+ uint size;
+ uint 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, STATUS_LOUD);
+ 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 %llu, tx %llu, rx %llu, err %llu\n",
+ tx_ctr - rx_ctr, tx_ctr, rx_ctr,
+ err_ctr);
+ }
+ }
+
+ return 0;
+}
+#else
+/*
+ * FPGA io-endpoint looptest
+ *
+ * Syntax:
+ * ioloop {size} {rate}
+ */
+int do_ioloop(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ uint size;
+ uint rate = 0;
+ struct udevice *fpga;
+ struct regmap *map;
+
+ if (!dev) {
+ printf("No device selected\n");
+ return 1;
+ }
+
+ gdsys_soc_get_fpga(dev, &fpga);
+ regmap_init_mem(dev_ofnode(dev), &map);
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ /*
+ * packet size is specified since argc > 1
+ */
+ size = simple_strtoul(argv[2], NULL, 10);
+
+ /*
+ * If another parameter, it is the test rate in packets per second.
+ */
+ if (argc > 2)
+ rate = simple_strtoul(argv[3], NULL, 10);
+
+ /* Enable receive path */
+ misc_set_enabled(dev, true);
+
+ rx_ctr = 0; tx_ctr = 0; err_ctr = 0;
+
+ while (1) {
+ uint top_int;
+
+ if (ctrlc())
+ break;
+
+ ihs_fpga_get(map, top_interrupt, &top_int);
+
+ io_check_status(dev, STATUS_LOUD);
+ if (top_int & IRQ_CPU_TRANSMITBUFFER_FREE_STATUS)
+ io_send(dev, size);
+ if (top_int & IRQ_CPU_RECEIVE_DATA_AVAILABLE_STATUS)
+ io_receive(dev);
+
+ if (rate) {
+ udelay(1000000 / rate);
+ if (!(tx_ctr % rate))
+ printf("d %llu, tx %llu, rx %llu, err %llu\n",
+ tx_ctr - rx_ctr, tx_ctr, rx_ctr,
+ err_ctr);
+ }
+ }
+ return 0;
+}
+#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */
+
+#ifndef CONFIG_GDSYS_LEGACY_DRIVERS
+int do_iodev(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct udevice *ioep = NULL;
+ struct udevice *sysinfo;
+ char name[8];
+ int ret;
+
+ if (sysinfo_get(&sysinfo))
+ return CMD_RET_FAILURE;
+
+ if (argc > 1) {
+ int i = simple_strtoul(argv[1], NULL, 10);
+
+ snprintf(name, sizeof(name), "ioep%d", i);
+
+ ret = uclass_get_device_by_phandle(UCLASS_MISC, sysinfo, name,
+ &ioep);
+
+ if (ret || !ioep) {
+ printf("Invalid IOEP %d\n", i);
+ return CMD_RET_FAILURE;
+ }
+
+ dev = ioep;
+ } else {
+ int i = 0;
+
+ while (1) {
+ snprintf(name, sizeof(name), "ioep%d", i);
+
+ ret = uclass_get_device_by_phandle(UCLASS_MISC, sysinfo,
+ name, &ioep);
+
+ if (ret || !ioep)
+ break;
+
+ printf("IOEP %d:\t%s\n", i++, ioep->name);
+ }
+
+ if (dev)
+ printf("\nSelected IOEP: %s\n", dev->name);
+ else
+ puts("\nNo IOEP selected.\n");
+ }
+
+ return 0;
+}
+#endif /* !CONFIG_GDSYS_LEGACY_DRIVERS */
+
+#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
+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"
+);
+#else
+U_BOOT_CMD(
+ ioloop, 3, 0, do_ioloop,
+ "fpga io-endpoint looptest",
+ "packetsize [packets/sec]"
+);
+
+U_BOOT_CMD(
+ ioreflect, 2, 0, do_ioreflect,
+ "fpga io-endpoint reflector",
+ "reportrate"
+);
+
+U_BOOT_CMD(
+ iodev, 2, 0, do_iodev,
+ "fpga io-endpoint listing/selection",
+ "[ioep device to select]"
+);
+#endif /* CONFIG_GDSYS_LEGACY_DRIVERS */