mirror of
https://github.com/brain-hackers/u-boot-brain
synced 2024-09-08 13:53:21 +09:00
![Simon Glass](/assets/img/avatar_default.png)
This uclass is intended to provide a way to obtain information about a U-Boot board. But the concept of a U-Boot 'board' is the whole system, not just one circuit board, meaning that 'board' is something of a misnomer for this uclass. In addition, the name 'board' is a bit overused in U-Boot and we want to use the same uclass to provide SMBIOS information. The obvious name is 'system' but that is so vague as to be meaningless. Use 'sysinfo' instead, since this uclass is aimed at providing information on the system. Rename everything accordingly. Note: Due to the patch delta caused by the symbol renames, this patch shows some renamed files as being deleted in one place and created in another. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
586 lines
12 KiB
C
586 lines
12 KiB
C
// 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 */
|