
Add a comman to debug the IHS FPGA's bus.
Signed-off-by: Mario Six mario.six@gdsys.cc ---
cmd/Kconfig | 5 ++ cmd/Makefile | 1 + cmd/ihs_fpga.c | 269 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 275 insertions(+) create mode 100644 cmd/ihs_fpga.c
diff --git a/cmd/Kconfig b/cmd/Kconfig index 4bbe9d435c..6d13c681cb 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -753,6 +753,11 @@ config CMD_SATA Attachment, where AT refers to an IBM AT (Advanced Technology) computer released in 1984.
+config CMD_IHS_FPGA + bool "fpga" + help + Enable the GDSYS IHS FPGA command for accessing the FPGA's regisers. + config CMD_IHS_AXI bool "axi" help diff --git a/cmd/Makefile b/cmd/Makefile index 0baaf76b47..79abe8f877 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -145,6 +145,7 @@ obj-$(CONFIG_CMD_GPT) += gpt.o obj-$(CONFIG_CMD_ETHSW) += ethsw.o
obj-$(CONFIG_CMD_IHS_AXI) += ihs_axi.o +obj-$(CONFIG_CMD_IHS_FPGA) += ihs_fpga.o
# Power obj-$(CONFIG_CMD_PMIC) += pmic.o diff --git a/cmd/ihs_fpga.c b/cmd/ihs_fpga.c new file mode 100644 index 0000000000..6d0c599d96 --- /dev/null +++ b/cmd/ihs_fpga.c @@ -0,0 +1,269 @@ +/* + * (C) Copyright 2017 + * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc + * + * based on the fpgad command, which is + * + * (C) Copyright 2013 + * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <command.h> +#include <console.h> +#include <ihs_fpga.h> + +static struct udevice *fpga_cur; +static uint dp_last_addr; +static uint dp_last_length = 0x40; + +static void show_fpga(struct udevice *fpga) +{ + struct udevice *dev; + + printf("Bus %d:\t%s", fpga->req_seq, fpga->name); + if (device_active(fpga)) + printf(" (active %d)", fpga->seq); + printf("\n"); + for (device_find_first_child(fpga, &dev); + dev; + device_find_next_child(&dev)) { + //struct dm_i2c_chip *chip = dev_get_parent_platdata(dev); + + //printf(" %02x: %s, offset len %x, flags %x\n", + //chip->chip_addr, dev->name, chip->offset_len, + //chip->flags); + printf(" %s\n", dev->name); + } +} + +static int do_fpga_show_fpga(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + if (argc == 1) { + /* show all FPGAs */ + struct udevice *fpga; + struct uclass *uc; + int ret; + + ret = uclass_get(UCLASS_IHS_FPGA, &uc); + if (ret) + return CMD_RET_FAILURE; + uclass_foreach_dev(fpga, uc) + show_fpga(fpga); + } else { + int i; + + /* show specific fpga */ + i = simple_strtoul(argv[1], NULL, 10); + + struct udevice *fpga; + int ret; + + ret = uclass_get_device_by_seq(UCLASS_IHS_FPGA, i, &fpga); + if (ret) { + printf("Invalid fpga %d: err=%d\n", i, ret); + return CMD_RET_FAILURE; + } + show_fpga(fpga); + } + + return 0; +} + +static int cmd_fpga_set_fpga_num(unsigned int fpganum) +{ + struct udevice *fpga; + int ret; + + ret = uclass_get_device_by_seq(UCLASS_IHS_FPGA, fpganum, &fpga); + if (ret) { + debug("%s: No fpga %d\n", __func__, fpganum); + return ret; + } + fpga_cur = fpga; + + return 0; +} + +static int fpga_get_cur_fpga(struct udevice **fpgap) +{ + if (!fpga_cur) { + puts("No fpga selected\n"); + return -ENODEV; + } + *fpgap = fpga_cur; + + return 0; +} + +static int do_fpga_fpga_num(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + int ret = 0; + int fpga_no; + + if (argc == 1) { + /* querying current setting */ + struct udevice *fpga; + + if (!fpga_get_cur_fpga(&fpga)) + fpga_no = fpga->seq; + else + fpga_no = -1; + printf("Current fpga is %d\n", fpga_no); + } else { + fpga_no = simple_strtoul(argv[1], NULL, 10); + printf("Setting fpga to %d\n", fpga_no); + + ret = cmd_fpga_set_fpga_num(fpga_no); + + if (ret) + printf("Failure changing fpga number (%d)\n", ret); + } + + return ret ? CMD_RET_FAILURE : 0; +} + +#define DISP_LINE_LEN 16 + +int do_fpga_md(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + unsigned int k; + ulong addr, length; + int rc = 0; + u16 linebuf[DISP_LINE_LEN / sizeof(u16)]; + ulong nbytes; + + /* + * We use the last specified parameters, unless new ones are + * entered. + */ + addr = dp_last_addr; + length = dp_last_length; + + if (argc < 2) + return CMD_RET_USAGE; + + if (!fpga_cur) { + puts("No fpga selected\n"); + return -ENODEV; + } + + if ((flag & CMD_FLAG_REPEAT) == 0) { + /* + * Address is specified since argc > 3 + */ + addr = simple_strtoul(argv[1], NULL, 16); + + /* + * If another parameter, it is the length to display. + * Length is the number of objects, not number of bytes. + */ + if (argc > 2) + length = simple_strtoul(argv[2], NULL, 16); + } + + nbytes = length * sizeof(u16); + do { + ulong linebytes = (nbytes > DISP_LINE_LEN) ? + DISP_LINE_LEN : nbytes; + + for (k = 0; k < linebytes / sizeof(u16); ++k) + linebuf[k] = fpga_in_le16(fpga_cur, + addr / sizeof(u16) + k); + + print_buffer(addr, (void *)linebuf, sizeof(u16), + linebytes / sizeof(u16), + DISP_LINE_LEN / sizeof(u16)); + if (rc) + break; + + nbytes -= linebytes; + addr += linebytes; + if (ctrlc()) { + rc = 1; + break; + } + } while (nbytes > 0); + + dp_last_addr = addr; + dp_last_length = length; + + return rc; +} + +static int do_fpga_mw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + u16 writeval; + ulong addr, count; + + if ((argc < 3) || (argc > 4)) + return CMD_RET_USAGE; + + if (!fpga_cur) { + puts("No fpga selected\n"); + return -ENODEV; + } + + /* Address is specified since argc > 3 */ + addr = simple_strtoul(argv[1], NULL, 16); + + /* Get the value to write. */ + writeval = simple_strtoul(argv[2], NULL, 16); + + /* Count ? */ + if (argc == 4) + count = simple_strtoul(argv[3], NULL, 16); + else + count = 1; + + while (count-- > 0) + fpga_out_le16(fpga_cur, + addr / sizeof(u16) + count, + writeval); + + return 0; +} + +static cmd_tbl_t cmd_fpga_sub[] = { + U_BOOT_CMD_MKENT(show, 1, 1, do_fpga_show_fpga, "", ""), + U_BOOT_CMD_MKENT(dev, 1, 1, do_fpga_fpga_num, "", ""), + U_BOOT_CMD_MKENT(md, 3, 1, do_fpga_md, "", ""), + U_BOOT_CMD_MKENT(mw, 4, 1, do_fpga_mw, "", ""), +}; + +static int do_ihs_fpga(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + cmd_tbl_t *c; + + if (argc < 2) + return CMD_RET_USAGE; + + /* Strip off leading 'fpga' command argument */ + argc--; + argv++; + + c = find_cmd_tbl(argv[0], &cmd_fpga_sub[0], ARRAY_SIZE(cmd_fpga_sub)); + + if (c) + return c->cmd(cmdtp, flag, argc, argv); + else + return CMD_RET_USAGE; +} + +static char fpga_help_text[] = + "show - show FPGA info\n" + "fpga dev [dev] - show or set current FPGA\n" + "fpga md address [# of objects] - read from FPGA device\n" + "fpga mw address value [count] - write to FPGA device (fill)\n"; + +U_BOOT_CMD( + fpga, 7, 1, do_ihs_fpga, + "FPGA sub-system", + fpga_help_text +);