From fc2b8226c544977626795705e06e1e768e5dd847 Mon Sep 17 00:00:00 2001 From: Franck Jullien Date: Wed, 29 Apr 2020 21:33:51 +0200 Subject: [PATCH] bios: switch command handler to a modular format Command are now described with a structure. A pointer to this structure is placed in a dedicated linker section. --- litex/soc/software/bios/Makefile | 13 +- litex/soc/software/bios/command.h | 47 ++ litex/soc/software/bios/commands/cmd_bios.c | 125 +++++ litex/soc/software/bios/commands/cmd_boot.c | 59 +++ litex/soc/software/bios/commands/cmd_dram.c | 222 +++++++++ litex/soc/software/bios/commands/cmd_mdio.c | 132 +++++ .../software/bios/commands/cmd_mem_access.c | 137 ++++++ litex/soc/software/bios/commands/cmd_sdcard.c | 85 ++++ .../software/bios/commands/cmd_spi_flash.c | 75 +++ .../soc/software/bios/commands/cmd_usddrphy.c | 128 +++++ litex/soc/software/bios/helpers.c | 52 ++ litex/soc/software/bios/helpers.h | 2 + litex/soc/software/bios/linker.ld | 7 + litex/soc/software/bios/main.c | 451 +----------------- litex/soc/software/bios/sdram.c | 71 +-- litex/soc/software/bios/sdram.h | 8 +- 16 files changed, 1104 insertions(+), 510 deletions(-) create mode 100644 litex/soc/software/bios/command.h create mode 100644 litex/soc/software/bios/commands/cmd_bios.c create mode 100644 litex/soc/software/bios/commands/cmd_boot.c create mode 100644 litex/soc/software/bios/commands/cmd_dram.c create mode 100644 litex/soc/software/bios/commands/cmd_mdio.c create mode 100644 litex/soc/software/bios/commands/cmd_mem_access.c create mode 100644 litex/soc/software/bios/commands/cmd_sdcard.c create mode 100644 litex/soc/software/bios/commands/cmd_spi_flash.c create mode 100644 litex/soc/software/bios/commands/cmd_usddrphy.c diff --git a/litex/soc/software/bios/Makefile b/litex/soc/software/bios/Makefile index d48ab817..c80e0a13 100755 --- a/litex/soc/software/bios/Makefile +++ b/litex/soc/software/bios/Makefile @@ -16,7 +16,15 @@ OBJECTS = isr.o \ main.o \ boot-helper.o \ boot.o \ - helpers.o + helpers.o \ + cmd_bios.o \ + cmd_boot.o \ + cmd_dram.o \ + cmd_mdio.o \ + cmd_mem_access.o \ + cmd_sdcard.o \ + cmd_spi_flash.o \ + cmd_usddrphy.o ifdef TERM_NO_HIST CFLAGS += -DTERM_NO_HIST @@ -67,6 +75,9 @@ endif %.o: $(BIOS_DIRECTORY)/%.c $(compile) +%.o: $(BIOS_DIRECTORY)/commands/%.c + $(compile) + %.o: $(BIOS_DIRECTORY)/%.S $(assemble) diff --git a/litex/soc/software/bios/command.h b/litex/soc/software/bios/command.h new file mode 100644 index 00000000..24704389 --- /dev/null +++ b/litex/soc/software/bios/command.h @@ -0,0 +1,47 @@ +// This file is Copyright (c) 2020 Franck Jullien + +// SPDX-License-Identifier: BSD-Source-Code + +#ifndef __COMMAND_H__ +#define __COMMAND_H__ + +#define MAX_PARAM 8 + +#define MISC_CMDS 0 +#define SYSTEM_CMDS 1 +#define CACHE_CMDS 2 +#define BOOT_CMDS 3 +#define DRAM_CMDS 4 +#define MDIO_CMDS 5 +#define MEM_CMDS 6 +#define SD_CMDS 7 +#define SPIFLASH_CMDS 8 +#define DDR_CMDS 9 +#define NB_OF_GROUPS 10 + +typedef void (*cmd_handler)(int nb_params, char **params); + +struct command_struct { + void (*func)(int nb_params, char **params); + const char *name; + const char *help; + int group; +}; + +extern struct command_struct *const __bios_cmd_start[]; +extern struct command_struct *const __bios_cmd_end[]; + +#define define_command(cmd_name, handler, help_txt, group_id) \ + struct command_struct s_##cmd_name = { \ + .func = (cmd_handler)handler, \ + .name = #cmd_name, \ + .help = help_txt, \ + .group = group_id, \ + }; \ + const struct command_struct *__bios_cmd_##cmd_name __attribute__((__used__)) \ + __attribute__((__section__(".bios_cmd"))) = &s_##cmd_name + + +struct command_struct *command_dispatcher(char *command, int nb_params, char **params); + +#endif diff --git a/litex/soc/software/bios/commands/cmd_bios.c b/litex/soc/software/bios/commands/cmd_bios.c new file mode 100644 index 00000000..a5e70424 --- /dev/null +++ b/litex/soc/software/bios/commands/cmd_bios.c @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: BSD-Source-Code + +#include +#include + +#include +#include +#include +#include + +#include "../command.h" +#include "../helpers.h" + +/** + * Command "help" + * + * Print a list of available commands with their help text + * + */ +static void help_handler(int nb_params, char **params) +{ + struct command_struct * const *cmd; + int i, not_empty; + + puts("\nLiteX BIOS, available commands:\n"); + + for (i = 0; i < NB_OF_GROUPS; i++) { + not_empty = 0; + for (cmd = __bios_cmd_start; cmd != __bios_cmd_end; cmd++) { + if ((*cmd)->group == i) { + printf("%-16s - %s\n", (*cmd)->name, (*cmd)->help ? (*cmd)->help : "-"); + not_empty = 1; + } + } + if (not_empty) + printf("\n"); + } +} + +define_command(help, help_handler, "Print this help", MISC_CMDS); + +/** + * Command "ident" + * + * Print SoC identyifier if available + * + */ +static void ident_helper(int nb_params, char **params) +{ + char buffer[IDENT_SIZE]; + + get_ident(buffer); + printf("Ident: %s", *buffer ? buffer : "-"); +} + +define_command(ident, ident_helper, "Display identifier", SYSTEM_CMDS); + +/** + * Command "reboot" + * + * Reboot the system + * + */ +#ifdef CSR_CTRL_BASE +static void reboot(int nb_params, char **params) +{ + ctrl_reset_write(1); +} + +define_command(reboot, reboot, "Reset processor", SYSTEM_CMDS); +#endif + +/** + * Command "crc" + * + * Compute CRC32 over an address range + * + */ +static void crc(int nb_params, char **params) +{ + char *c; + unsigned int addr; + unsigned int length; + + if (nb_params < 2) { + printf("crc
"); + return; + } + + addr = strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect address"); + return; + } + + length = strtoul(params[1], &c, 0); + if (*c != 0) { + printf("Incorrect length"); + return; + } + + printf("CRC32: %08x", crc32((unsigned char *)addr, length)); +} + +define_command(crc, crc, "Compute CRC32 of a part of the address space", MISC_CMDS); + +/** + * Command "flush_cpu_dcache" + * + * Flush CPU data cache + * + */ + +define_command(flush_cpu_dcache, flush_cpu_dcache, "Flush CPU data cache", CACHE_CMDS); + +/** + * Command "flush_l2_cache" + * + * Flush L2 cache + * + */ +#ifdef CONFIG_L2_SIZE +define_command(flush_l2_cache, flush_l2_cache, "Flush L2 cache", CACHE_CMDS); +#endif + diff --git a/litex/soc/software/bios/commands/cmd_boot.c b/litex/soc/software/bios/commands/cmd_boot.c new file mode 100644 index 00000000..c9cb8a11 --- /dev/null +++ b/litex/soc/software/bios/commands/cmd_boot.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: BSD-Source-Code + +#include +#include + +#include + +#include "../command.h" +#include "../helpers.h" +#include "../boot.h" + +/** + * Command "flashboot" + * + * Boot software from flash + * + */ +#ifdef FLASH_BOOT_ADDRESS +define_command(flashboot, flashboot, "Boot from flash", BOOT_CMDS); +#endif + +/** + * Command "romboot" + * + * Boot software from embedded rom + * + */ +#ifdef ROM_BOOT_ADDRESS +define_command(romboot, romboot, "Boot from embedded rom", BOOT_CMDS); +#endif + +/** + * Command "serialboot" + * + * Boot software from serial interface + * + */ +define_command(serialboot, serialboot, "Boot via SFL", BOOT_CMDS); + +/** + * Command "netboot" + * + * Boot software from TFTP server + * + */ +#ifdef CSR_ETHMAC_BASE +define_command(netboot, netboot, "Boot via TFTP", BOOT_CMDS); +#endif + +/** + * Command "spisdcardboot" + * + * Boot software from SDcard + * + */ +#ifdef CSR_SPISDCARD_BASE +define_command(spisdcardboot, spisdcardboot, "Boot from SDCard via SPI hardware bitbang", BOOT_CMDS); +#endif + diff --git a/litex/soc/software/bios/commands/cmd_dram.c b/litex/soc/software/bios/commands/cmd_dram.c new file mode 100644 index 00000000..0d6fa1d4 --- /dev/null +++ b/litex/soc/software/bios/commands/cmd_dram.c @@ -0,0 +1,222 @@ +// SPDX-License-Identifier: BSD-Source-Code + +#include +#include + +#include + +#include "../command.h" +#include "../helpers.h" +#include "../sdram.h" + +/** + * Command "sdrrow" + * + * Precharge/Activate row + * + */ +#ifdef CSR_SDRAM_BASE +static void sdrrow_handler(int nb_params, char **params) +{ + char *c; + unsigned int row; + + if (nb_params < 1) { + sdrrow(0); + printf("Precharged"); + } + + row = strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect row"); + return; + } + + sdrrow(row); + printf("Activated row %d", row); +} +define_command(sdrrow, sdrrow_handler, "Precharge/Activate row", DRAM_CMDS); +#endif + +/** + * Command "sdrsw" + * + * Gives SDRAM control to SW + * + */ +#ifdef CSR_SDRAM_BASE +define_command(sdrsw, sdrsw, "Gives SDRAM control to SW", DRAM_CMDS); +#endif + +/** + * Command "sdrhw" + * + * Gives SDRAM control to HW + * + */ +#ifdef CSR_SDRAM_BASE +define_command(sdrhw, sdrhw, "Gives SDRAM control to HW", DRAM_CMDS); +#endif + +/** + * Command "sdrrdbuf" + * + * Dump SDRAM read buffer + * + */ +#ifdef CSR_SDRAM_BASE +static void sdrrdbuf_handler(int nb_params, char **params) +{ + sdrrdbuf(-1); +} + +define_command(sdrrdbuf, sdrrdbuf_handler, "Dump SDRAM read buffer", DRAM_CMDS); +#endif + +/** + * Command "sdrrd" + * + * Read SDRAM data + * + */ +#ifdef CSR_SDRAM_BASE +static void sdrrd_handler(int nb_params, char **params) +{ + unsigned int addr; + int dq; + char *c; + + if (nb_params < 1) { + printf("sdrrd
"); + return; + } + + addr = strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect address"); + return; + } + + if (nb_params < 2) + dq = -1; + else { + dq = strtoul(params[1], &c, 0); + if (*c != 0) { + printf("Incorrect DQ"); + return; + } + } + + sdrrd(addr, dq); +} + +define_command(sdrrd, sdrrd_handler, "Read SDRAM data", DRAM_CMDS); +#endif + +/** + * Command "sdrrderr" + * + * Print SDRAM read errors + * + */ +#ifdef CSR_SDRAM_BASE +static void sdrrderr_handler(int nb_params, char **params) +{ + int count; + char *c; + + if (nb_params < 1) { + printf("sdrrderr "); + return; + } + + count = strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect count"); + return; + } + + sdrrderr(count); +} + +define_command(sdrrderr, sdrrderr_handler, "Print SDRAM read errors", DRAM_CMDS); +#endif + +/** + * Command "sdrwr" + * + * Write SDRAM test data + * + */ +#ifdef CSR_SDRAM_BASE +static void sdrwr_handler(int nb_params, char **params) +{ + unsigned int addr; + char *c; + + if (nb_params < 1) { + printf("sdrwr
"); + return; + } + + addr = strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect address"); + return; + } + + sdrwr(addr); +} + +define_command(sdrwr, sdrwr_handler, "Write SDRAM test data", DRAM_CMDS); +#endif + +/** + * Command "sdrinit" + * + * Start SDRAM initialisation + * + */ +#if defined(CSR_SDRAM_BASE) && defined(CSR_DDRPHY_BASE) +define_command(sdrinit, sdrinit, "Start SDRAM initialisation", DRAM_CMDS); +#endif + +/** + * Command "sdrwlon" + * + * Write leveling ON + * + */ +#if defined(CSR_DDRPHY_BASE) && defined(SDRAM_PHY_WRITE_LEVELING_CAPABLE) && defined(CSR_SDRAM_BASE) +define_command(sdrwlon, sdrwlon, "Enable write leveling", DRAM_CMDS); +#endif + +/** + * Command "sdrwloff" + * + * Write leveling OFF + * + */ +#if defined(CSR_DDRPHY_BASE) && defined(SDRAM_PHY_WRITE_LEVELING_CAPABLE) && defined(CSR_SDRAM_BASE) +define_command(sdrwloff, sdrwloff, "Disable write leveling", DRAM_CMDS); +#endif + +/** + * Command "sdrlevel" + * + * Perform read/write leveling + * + */ +#if defined(CSR_DDRPHY_BASE) && defined(CSR_SDRAM_BASE) +define_command(sdrlevel, sdrlevel, "Perform read/write leveling", DRAM_CMDS); +#endif + +/** + * Command "memtest" + * + * Run a memory test + * + */ +#ifdef CSR_SDRAM_BASE +define_command(memtest, memtest, "Run a memory test", DRAM_CMDS); +#endif diff --git a/litex/soc/software/bios/commands/cmd_mdio.c b/litex/soc/software/bios/commands/cmd_mdio.c new file mode 100644 index 00000000..9d28c534 --- /dev/null +++ b/litex/soc/software/bios/commands/cmd_mdio.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: BSD-Source-Code + +#include +#include + +#include + +#include "../command.h" +#include "../helpers.h" + +/** + * Command "mdiow" + * + * Write MDIO register + * + */ +#ifdef CSR_ETHPHY_MDIO_W_ADDR +static void mdiow(int nb_params, char **params) +{ + char *c; + unsigned int phyadr2; + unsigned int reg2; + unsigned int val2; + + if (nb_params < 3) { + printf("mdiow "); + return; + } + + phyadr2 = strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect phyadr"); + return; + } + + reg2 = strtoul(params[1], &c, 0); + if (*c != 0) { + printf("Incorrect reg"); + return; + } + + val2 = strtoul(params[2], &c, 0); + if (*c != 0) { + printf("Incorrect val"); + return; + } + + mdio_write(phyadr2, reg2, val2); +} + +define_command(mdiow, mdiow, "Write MDIO register", MDIO_CMDS); +#endif + +/** + * Command "mdior" + * + * Read MDIO register + * + */ +#ifdef CSR_ETHPHY_MDIO_W_ADDR +static void mdior(int nb_params, char **params) +{ + char *c; + unsigned int phyadr2; + unsigned int reg2; + unsigned int val; + + if (nb_params < 2) { + printf("mdior "); + return; + } + + phyadr2 = strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect phyadr"); + return; + } + + reg2 = strtoul(params[1], &c, 0); + if (*c != 0) { + printf("Incorrect reg"); + return; + } + + val = mdio_read(phyadr2, reg2); + printf("Reg %d: 0x%04x", reg2, val); +} + +define_command(mdior, mdior, "Read MDIO register", MDIO_CMDS); +#endif + +/** + * Command "mdiod" + * + * Dump MDIO registers + * + */ +#ifdef CSR_ETHPHY_MDIO_W_ADDR +static void mdiod(int nb_params, char **params) +{ + char *c; + unsigned int phyadr; + unsigned int count; + unsigned int val; + int i; + + if (nb_params < 2) { + printf("mdiod "); + return; + } + + phyadr = strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect phyadr"); + return; + } + + count = strtoul(params[1], &c, 0); + if (*c != 0) { + printf("Incorrect count"); + return; + } + + printf("MDIO dump @0x%x:\n", phyadr); + for (i = 0; i < count; i++) { + val = mdio_read(phyadr, i); + printf("reg %d: 0x%04x", i, val); + } +} + +define_command(mdiod, mdiod, "Dump MDIO registers", MDIO_CMDS); +#endif diff --git a/litex/soc/software/bios/commands/cmd_mem_access.c b/litex/soc/software/bios/commands/cmd_mem_access.c new file mode 100644 index 00000000..8c63d4c4 --- /dev/null +++ b/litex/soc/software/bios/commands/cmd_mem_access.c @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: BSD-Source-Code + +#include +#include + +#include "../command.h" +#include "../helpers.h" + +/** + * Command "mr" + * + * Memory read + * + */ +static void mr(int nb_params, char **params) +{ + char *c; + unsigned int *addr; + unsigned int length; + + if (nb_params < 1) { + printf("mr
[length]"); + return; + } + addr = (unsigned int *)strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect address"); + return; + } + if (nb_params == 1) { + length = 4; + } else { + length = strtoul(params[1], &c, 0); + if(*c != 0) { + printf("\nIncorrect length"); + return; + } + } + + dump_bytes(addr, length, (unsigned long)addr); +} + +define_command(mr, mr, "Read address space", MEM_CMDS); + +/** + * Command "mw" + * + * Memory write + * + */ +static void mw(int nb_params, char **params) +{ + char *c; + unsigned int *addr; + unsigned int value; + unsigned int count; + unsigned int i; + + if (nb_params < 2) { + printf("mw
[count]"); + return; + } + + addr = (unsigned int *)strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect address"); + return; + } + + value = strtoul(params[1], &c, 0); + if(*c != 0) { + printf("Incorrect value"); + return; + } + + if (nb_params == 2) { + count = 1; + } else { + count = strtoul(params[2], &c, 0); + if(*c != 0) { + printf("Incorrect count"); + return; + } + } + + for (i = 0; i < count; i++) + *addr++ = value; +} + +define_command(mw, mw, "Write address space", MEM_CMDS); + +/** + * Command "mc" + * + * Memory copy + * + */ +static void mc(int nb_params, char **params) +{ + char *c; + unsigned int *dstaddr; + unsigned int *srcaddr; + unsigned int count; + unsigned int i; + + if (nb_params < 2) { + printf("mc [count]"); + return; + } + + dstaddr = (unsigned int *)strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect destination address"); + return; + } + + srcaddr = (unsigned int *)strtoul(params[1], &c, 0); + if (*c != 0) { + printf("Incorrect source address"); + return; + } + + if (nb_params == 2) { + count = 1; + } else { + count = strtoul(params[2], &c, 0); + if (*c != 0) { + printf("Incorrect count"); + return; + } + } + + for (i = 0; i < count; i++) + *dstaddr++ = *srcaddr++; +} + +define_command(mc, mc, "Copy address space", MEM_CMDS); diff --git a/litex/soc/software/bios/commands/cmd_sdcard.c b/litex/soc/software/bios/commands/cmd_sdcard.c new file mode 100644 index 00000000..96f9fe64 --- /dev/null +++ b/litex/soc/software/bios/commands/cmd_sdcard.c @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: BSD-Source-Code + +#include +#include + +#include + +#include "../command.h" +#include "../helpers.h" +#include "../sdcard.h" + +/** + * Command "sdclk" + * + * Configure SDcard clock frequency + * + */ +#ifdef CSR_SDCORE_BASE +static void sdclk(int nb_params, char **params) +{ + unsigned int frequ; + char *c; + + if (nb_params < 1) { + printf("sdclk "); + return; + } + + frequ = strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect frequency"); + return; + } + + sdclk_set_clk(frequ); +} + +struct command_struct cmd_sdclk = +{ + .func = sdclk, + .name = "sdclk", + .help = "SDCard set clk frequency (Mhz)", +}; + +define_command(sdclk, sdclk, "SDCard set clk frequency (Mhz)", SD_CMDS); +#endif + +/** + * Command "sdinit" + * + * Initialize SDcard + * + */ +#ifdef CSR_SDCORE_BASE +define_command(sdinit, sdinit, "SDCard initialization", SD_CMDS); +#endif + +/** + * Command "sdtest" + * + * Perform SDcard access tests + * + */ +#ifdef CSR_SDCORE_BASE +static void sdtest(int nb_params, char **params) +{ + unsigned int loops; + char *c; + + if (nb_params < 1) { + printf("sdtest "); + return; + } + + loops = strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect number of loops"); + return; + } + + sdcard_test(loops); +} + +define_command(sdtest, sdtest, "SDCard test", SD_CMDS); +#endif diff --git a/litex/soc/software/bios/commands/cmd_spi_flash.c b/litex/soc/software/bios/commands/cmd_spi_flash.c new file mode 100644 index 00000000..e607a89d --- /dev/null +++ b/litex/soc/software/bios/commands/cmd_spi_flash.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: BSD-Source-Code + +#include +#include + +#include + +#include "../command.h" +#include "../helpers.h" + +/** + * Command "fw" + * + * Write data from a memory buffer to SPI flash + * + */ +#if (defined CSR_SPIFLASH_BASE && defined SPIFLASH_PAGE_SIZE) +static void fw(int nb_params, char **params) +{ + char *c; + unsigned int addr; + unsigned int value; + unsigned int count; + unsigned int i; + + if (nb_params < 2) { + printf("fw [count]"); + return; + } + + addr = strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect offset"); + return; + } + + value = strtoul(params[1], &c, 0); + if (*c != 0) { + printf("Incorrect value"); + return; + } + + if (nb_params == 2) { + count = 1; + } else { + count = strtoul(count, &c, 0); + if (*c != 0) { + printf("Incorrect count"); + return; + } + } + + for (i = 0; i < count; i++) + write_to_flash(addr + i * 4, (unsigned char *)&value, 4); +} + +define_command(fw, fw, "Write to flash", SPIFLASH_CMDS); +#endif + +/** + * Command "fe" + * + * Flash erase + * + */ +#if (defined CSR_SPIFLASH_BASE && defined SPIFLASH_PAGE_SIZE) +static void fe(int nb_params, char **params) +{ + erase_flash(); + printf("Flash erased\n"); +} + +define_command(fe, fe, "Erase whole flash", SPIFLASH_CMDS); +#endif + diff --git a/litex/soc/software/bios/commands/cmd_usddrphy.c b/litex/soc/software/bios/commands/cmd_usddrphy.c new file mode 100644 index 00000000..69c62fad --- /dev/null +++ b/litex/soc/software/bios/commands/cmd_usddrphy.c @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: BSD-Source-Code + +#include +#include + +#include + +#include "../command.h" +#include "../helpers.h" +#include "../sdram.h" + +/** + * Command "sdram_cdly" + * + * Set SDRAM clk/cmd delay + * + */ +#ifdef USDDRPHY_DEBUG +static void sdram_cdly(int nb_params, char **params) +{ + unsigned int delay; + char *c; + + if (nb_params < 1) { + printf("sdram_cdly "); + return; + } + + delay = strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect delay"); + return; + } + + ddrphy_cdly(delay); +} + +define_command(sdram_cdly, sdram_cdly, "Set SDRAM clk/cmd delay", DDR_CMDS); +#endif + +/** + * Command "sdram_cdly" + * + * Run SDRAM calibration + * + */ +#ifdef USDDRPHY_DEBUG +define_command(sdram_cal, sdram_cal, "Run SDRAM calibration", DDR_CMDS); +#endif + +/** + * Command "sdram_mpr" + * + * Read SDRAM MPR + * + */ +#ifdef USDDRPHY_DEBUG +define_command(sdram_mpr, sdram_mpr, "Read SDRAM MPR", DDR_CMDS); +#endif + + +/** + * Command "sdram_mrwr" + * + * Write SDRAM mode registers + * + */ +#ifdef USDDRPHY_DEBUG +static void sdram_mrwr(int nb_params, char **params) +{ + unsigned int reg; + unsigned int value; + char *c; + + if (nb_params < 2) { + printf("sdram_mrwr "); + return; + } + + reg = strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect register value"); + return; + } + + value = strtoul(params[1], &c, 0); + if (*c != 0) { + printf("Incorrect value"); + return; + } + + sdrsw(); + printf("Writing 0x%04x to SDRAM mode register %d\n", value, reg); + sdrmrwr(reg, value); + sdrhw(); +} + +define_command(sdram_mrwr, sdram_mrwr, "Write SDRAM mode registers", DDR_CMDS); +#endif + +/** + * Command "sdram_cdly_scan" + * + * Enable/disable cdly scan + * + */ +#ifdef USDDRPHY_DEBUG +static void sdram_cdly_scan(int nb_params, char **params) +{ + unsigned int value; + char *c; + + if (nb_params < 1) { + printf("sdram_cdly_scan "); + return; + } + + value = strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect value"); + return; + } + + sdr_cdly_scan(value); +} + +define_command(sdram_cdly_scan, sdram_cdly_scan, "Enable/disable cdly scan", DDR_CMDS); +#endif diff --git a/litex/soc/software/bios/helpers.c b/litex/soc/software/bios/helpers.c index 21eb6e1f..535dd61b 100644 --- a/litex/soc/software/bios/helpers.c +++ b/litex/soc/software/bios/helpers.c @@ -9,6 +9,7 @@ #include "readline.h" #include "helpers.h" +#include "command.h" extern unsigned int _ftext, _edata; @@ -74,3 +75,54 @@ void crcbios(void) printf(" The system will continue, but expect problems.\n"); } } + +int get_param(char *buf, char **cmd, char **params) +{ + int nb_param = 0; + int i; + + for (i = 0; i < MAX_PARAM; i++) + params[i] = NULL; + + *cmd = buf; + + while ((*buf != ' ') && (*buf !=0)) + buf++; + + if (*buf == 0) + return nb_param; + + *buf++ = 0; + + while (1) { + while ((*buf == ' ') && (*buf !=0)) + buf++; + + + if (*buf == 0) + return nb_param; + + params[nb_param++] = buf; + + while ((*buf != ' ') && (*buf !=0)) + buf++; + + if (*buf == 0) + return nb_param; + *buf++ = 0; + } +} + +struct command_struct *command_dispatcher(char *command, int nb_params, char **params) +{ + struct command_struct * const *cmd; + + for (cmd = __bios_cmd_start; cmd != __bios_cmd_end; cmd++) { + if (!strcmp(command, (*cmd)->name)) { + (*cmd)->func(nb_params, params); + return (*cmd); + } + } + + return NULL; +} diff --git a/litex/soc/software/bios/helpers.h b/litex/soc/software/bios/helpers.h index 227dcd17..6f1f2dee 100644 --- a/litex/soc/software/bios/helpers.h +++ b/litex/soc/software/bios/helpers.h @@ -3,5 +3,7 @@ void dump_bytes(unsigned int *ptr, int count, unsigned long addr); void crcbios(void); +int get_param(char *buf, char **cmd, char **params); +struct command_struct *command_dispatcher(char *command, int nb_params, char **params); #endif diff --git a/litex/soc/software/bios/linker.ld b/litex/soc/software/bios/linker.ld index 7760e551..e0211a6b 100644 --- a/litex/soc/software/bios/linker.ld +++ b/litex/soc/software/bios/linker.ld @@ -26,6 +26,13 @@ SECTIONS _erodata = .; } > rom + .commands : + { + PROVIDE_HIDDEN (__bios_cmd_start = .); + KEEP(*(.bios_cmd)) + PROVIDE_HIDDEN (__bios_cmd_end = .); + } > rom + .data : { . = ALIGN(8); diff --git a/litex/soc/software/bios/main.c b/litex/soc/software/bios/main.c index 7f9187a3..e985dd5a 100644 --- a/litex/soc/software/bios/main.c +++ b/litex/soc/software/bios/main.c @@ -45,446 +45,7 @@ #include "boot.h" #include "readline.h" #include "helpers.h" - -/* General address space functions */ - -static void mr(char *startaddr, char *len) -{ - char *c; - unsigned int *addr; - unsigned int length; - - if(*startaddr == 0) { - printf("mr
[length]\n"); - return; - } - addr = (unsigned *)strtoul(startaddr, &c, 0); - if(*c != 0) { - printf("incorrect address\n"); - return; - } - if(*len == 0) { - length = 4; - } else { - length = strtoul(len, &c, 0); - if(*c != 0) { - printf("incorrect length\n"); - return; - } - } - - dump_bytes(addr, length, (unsigned long)addr); -} - -static void mw(char *addr, char *value, char *count) -{ - char *c; - unsigned int *addr2; - unsigned int value2; - unsigned int count2; - unsigned int i; - - if((*addr == 0) || (*value == 0)) { - printf("mw
[count]\n"); - return; - } - addr2 = (unsigned int *)strtoul(addr, &c, 0); - if(*c != 0) { - printf("incorrect address\n"); - return; - } - value2 = strtoul(value, &c, 0); - if(*c != 0) { - printf("incorrect value\n"); - return; - } - if(*count == 0) { - count2 = 1; - } else { - count2 = strtoul(count, &c, 0); - if(*c != 0) { - printf("incorrect count\n"); - return; - } - } - for (i=0;i [count]\n"); - return; - } - dstaddr2 = (unsigned int *)strtoul(dstaddr, &c, 0); - if(*c != 0) { - printf("incorrect destination address\n"); - return; - } - srcaddr2 = (unsigned int *)strtoul(srcaddr, &c, 0); - if(*c != 0) { - printf("incorrect source address\n"); - return; - } - if(*count == 0) { - count2 = 1; - } else { - count2 = strtoul(count, &c, 0); - if(*c != 0) { - printf("incorrect count\n"); - return; - } - } - for (i=0;i [count]\n"); - return; - } - addr2 = strtoul(addr, &c, 0); - if(*c != 0) { - printf("incorrect offset\n"); - return; - } - value2 = strtoul(value, &c, 0); - if(*c != 0) { - printf("incorrect value\n"); - return; - } - if(*count == 0) { - count2 = 1; - } else { - count2 = strtoul(count, &c, 0); - if(*c != 0) { - printf("incorrect count\n"); - return; - } - } - for (i=0;i \n"); - return; - } - phyadr2 = strtoul(phyadr, &c, 0); - if(*c != 0) { - printf("incorrect phyadr\n"); - return; - } - reg2 = strtoul(reg, &c, 0); - if(*c != 0) { - printf("incorrect reg\n"); - return; - } - val2 = strtoul(val, &c, 0); - if(*c != 0) { - printf("incorrect val\n"); - return; - } - mdio_write(phyadr2, reg2, val2); -} - -static void mdior(char *phyadr, char *reg) -{ - char *c; - unsigned int phyadr2; - unsigned int reg2; - unsigned int val; - - if((*phyadr == 0) || (*reg == 0)) { - printf("mdior \n"); - return; - } - phyadr2 = strtoul(phyadr, &c, 0); - if(*c != 0) { - printf("incorrect phyadr\n"); - return; - } - reg2 = strtoul(reg, &c, 0); - if(*c != 0) { - printf("incorrect reg\n"); - return; - } - val = mdio_read(phyadr2, reg2); - printf("reg %d: 0x%04x\n", reg2, val); -} - -static void mdiod(char *phyadr, char *count) -{ - char *c; - unsigned int phyadr2; - unsigned int count2; - unsigned int val; - int i; - - if((*phyadr == 0) || (*count == 0)) { - printf("mdiod \n"); - return; - } - phyadr2 = strtoul(phyadr, &c, 0); - if(*c != 0) { - printf("incorrect phyadr\n"); - return; - } - count2 = strtoul(count, &c, 0); - if(*c != 0) { - printf("incorrect count\n"); - return; - } - printf("MDIO dump @0x%x:\n", phyadr2); - for (i=0; i \n"); - return; - } - addr = (char *)strtoul(startaddr, &c, 0); - if(*c != 0) { - printf("incorrect address\n"); - return; - } - length = strtoul(len, &c, 0); - if(*c != 0) { - printf("incorrect length\n"); - return; - } - - printf("CRC32: %08x\n", crc32((unsigned char *)addr, length)); -} - -static void ident(void) -{ - char buffer[IDENT_SIZE]; - - get_ident(buffer); - printf("Ident: %s\n", buffer); -} - -/* Init + command line */ - -static void help(void) -{ - puts("LiteX BIOS, available commands:"); - puts("mr - read address space"); - puts("mw - write address space"); - puts("mc - copy address space"); -#if (defined CSR_SPIFLASH_BASE && defined SPIFLASH_PAGE_SIZE) - puts("fe - erase whole flash"); - puts("fw - write to flash"); - -#endif -#ifdef CSR_ETHPHY_MDIO_W_ADDR - puts("mdiow - write MDIO register"); - puts("mdior - read MDIO register"); - puts("mdiod - dump MDIO registers"); -#endif - puts(""); - puts("crc - compute CRC32 of a part of the address space"); - puts("ident - display identifier"); - puts(""); - puts("flush_cpu_dcache - flush CPU data cache"); -#ifdef CONFIG_L2_SIZE - puts("flush_l2_cache - flush L2 cache"); -#endif - puts(""); -#ifdef CSR_CTRL_BASE - puts("reboot - reset processor"); -#endif -#ifdef CSR_ETHMAC_BASE - puts("netboot - boot via TFTP"); -#endif - puts("serialboot - boot via SFL"); -#ifdef FLASH_BOOT_ADDRESS - puts("flashboot - boot from flash"); -#endif -#ifdef ROM_BOOT_ADDRESS - puts("romboot - boot from embedded rom"); -#endif - puts(""); -#ifdef CSR_SDRAM_BASE - puts("memtest - run a memory test"); -#endif - puts(""); -#ifdef CSR_SDCORE_BASE - puts("sdclk - SDCard set clk frequency (Mhz)"); - puts("sdinit - SDCard initialization"); - puts("sdtest - SDCard test"); -#endif -#ifdef USDDRPHY_DEBUG - puts(""); - puts("sdram_cdly value - Set SDRAM clk/cmd delay"); - puts("sdram_cal - run SDRAM calibration"); - puts("sdram_mpr - read SDRAM MPR"); - puts("sdram_mrwr reg value - write SDRAM mode registers"); - puts("sdram_cdly_scan enabled - enable/disable cdly scan"); -#endif -#ifdef CSR_SPISDCARD_BASE - puts("spisdcardboot - boot from SDCard via SPI hardware bitbang"); -#endif -} - -static char *get_token(char **str) -{ - char *c, *d; - - c = (char *)strchr(*str, ' '); - if(c == NULL) { - d = *str; - *str = *str+strlen(*str); - return d; - } - *c = 0; - d = *str; - *str = c+1; - return d; -} - -#ifdef CSR_CTRL_BASE -static void reboot(void) -{ - ctrl_reset_write(1); -} -#endif - -static void do_command(char *c) -{ - char *token; - - token = get_token(&c); - - if(strcmp(token, "mr") == 0) mr(get_token(&c), get_token(&c)); - else if(strcmp(token, "mw") == 0) mw(get_token(&c), get_token(&c), get_token(&c)); - else if(strcmp(token, "mc") == 0) mc(get_token(&c), get_token(&c), get_token(&c)); -#if (defined CSR_SPIFLASH_BASE && defined SPIFLASH_PAGE_SIZE) - else if(strcmp(token, "fw") == 0) fw(get_token(&c), get_token(&c), get_token(&c)); - else if(strcmp(token, "fe") == 0) fe(); -#endif -#ifdef CSR_ETHPHY_MDIO_W_ADDR - else if(strcmp(token, "mdiow") == 0) mdiow(get_token(&c), get_token(&c), get_token(&c)); - else if(strcmp(token, "mdior") == 0) mdior(get_token(&c), get_token(&c)); - else if(strcmp(token, "mdiod") == 0) mdiod(get_token(&c), get_token(&c)); -#endif - else if(strcmp(token, "crc") == 0) crc(get_token(&c), get_token(&c)); - else if(strcmp(token, "ident") == 0) ident(); - - else if(strcmp(token, "flush_cpu_dcache") == 0) flush_cpu_dcache(); -#ifdef CONFIG_L2_SIZE - else if(strcmp(token, "flush_l2_cache") == 0) flush_l2_cache(); -#endif - -#ifdef CSR_CTRL_BASE - else if(strcmp(token, "reboot") == 0) reboot(); -#endif -#ifdef FLASH_BOOT_ADDRESS - else if(strcmp(token, "flashboot") == 0) flashboot(); -#endif -#ifdef ROM_BOOT_ADDRESS - else if(strcmp(token, "romboot") == 0) romboot(); -#endif - else if(strcmp(token, "serialboot") == 0) serialboot(); -#ifdef CSR_ETHMAC_BASE - else if(strcmp(token, "netboot") == 0) netboot(); -#endif - - else if(strcmp(token, "help") == 0) help(); - -#ifdef CSR_SDRAM_BASE - else if(strcmp(token, "sdrrow") == 0) sdrrow(get_token(&c)); - else if(strcmp(token, "sdrsw") == 0) sdrsw(); - else if(strcmp(token, "sdrhw") == 0) sdrhw(); - else if(strcmp(token, "sdrrdbuf") == 0) sdrrdbuf(-1); - else if(strcmp(token, "sdrrd") == 0) sdrrd(get_token(&c), get_token(&c)); - else if(strcmp(token, "sdrrderr") == 0) sdrrderr(get_token(&c)); - else if(strcmp(token, "sdrwr") == 0) sdrwr(get_token(&c)); -#ifdef CSR_DDRPHY_BASE - else if(strcmp(token, "sdrinit") == 0) sdrinit(); -#ifdef SDRAM_PHY_WRITE_LEVELING_CAPABLE - else if(strcmp(token, "sdrwlon") == 0) sdrwlon(); - else if(strcmp(token, "sdrwloff") == 0) sdrwloff(); -#endif - else if(strcmp(token, "sdrlevel") == 0) sdrlevel(); -#endif - else if(strcmp(token, "memtest") == 0) memtest(); -#endif - -#ifdef CSR_SDCORE_BASE - else if(strcmp(token, "sdclk") == 0) sdclk_set_clk(atoi(get_token(&c))); - else if(strcmp(token, "sdinit") == 0) sdcard_init(); - else if(strcmp(token, "sdtest") == 0) sdcard_test(atoi(get_token(&c))); -#endif -#ifdef USDDRPHY_DEBUG - else if(strcmp(token, "sdram_cdly") == 0) - ddrphy_cdly(atoi(get_token(&c))); - else if(strcmp(token, "sdram_cal") == 0) - sdrcal(); - else if(strcmp(token, "sdram_mpr") == 0) - sdrmpr(); - else if(strcmp(token, "sdram_mrwr") == 0) { - unsigned int reg; - unsigned int value; - reg = atoi(get_token(&c)); - value = atoi(get_token(&c)); - sdrsw(); - printf("Writing 0x%04x to SDRAM mode register %d\n", value, reg); - sdrmrwr(reg, value); - sdrhw(); - } - else if(strcmp(token, "sdram_cdly_scan") == 0) { - unsigned int enabled; - enabled = atoi(get_token(&c)); - sdr_cdly_scan(enabled); - } -#endif -#ifdef CSR_SPISDCARD_BASE - else if(strcmp(token, "spisdcardboot") == 0) spisdcardboot(); -#endif - - else if(strcmp(token, "") != 0) - printf("Command not found\n"); -} +#include "command.h" static void boot_sequence(void) { @@ -511,7 +72,12 @@ static void boot_sequence(void) int main(int i, char **c) { char buffer[CMD_LINE_BUFFER_SIZE]; + char *params[MAX_PARAM]; + char *command; + struct command_struct *cmd; + int nb_params; int sdr_ok; + #ifdef CONFIG_CPU_HAS_INTERRUPT irq_setmask(0); irq_setie(1); @@ -600,7 +166,10 @@ int main(int i, char **c) readline(buffer, CMD_LINE_BUFFER_SIZE); if (buffer[0] != 0) { printf("\n"); - do_command(buffer); + nb_params = get_param(buffer, &command, params); + cmd = command_dispatcher(command, nb_params, params); + if (!cmd) + printf("Command not found"); } printf("\n%s", PROMPT); } diff --git a/litex/soc/software/bios/sdram.c b/litex/soc/software/bios/sdram.c index 513a1266..1e139d5d 100644 --- a/litex/soc/software/bios/sdram.c +++ b/litex/soc/software/bios/sdram.c @@ -78,28 +78,18 @@ void sdrhw(void) printf("SDRAM now under hardware control\n"); } -void sdrrow(char *_row) +void sdrrow(unsigned int row) { - char *c; - unsigned int row; - - if(*_row == 0) { + if(row == 0) { sdram_dfii_pi0_address_write(0x0000); sdram_dfii_pi0_baddress_write(0); command_p0(DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS); cdelay(15); - printf("Precharged\n"); } else { - row = strtoul(_row, &c, 0); - if(*c != 0) { - printf("incorrect row\n"); - return; - } sdram_dfii_pi0_address_write(row); sdram_dfii_pi0_baddress_write(0); command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CS); cdelay(15); - printf("Activated row %d\n", row); } } @@ -126,58 +116,23 @@ void sdrrdbuf(int dq) printf("\n"); } -void sdrrd(char *startaddr, char *dq) +void sdrrd(unsigned int addr, int dq) { - char *c; - unsigned int addr; - int _dq; - - if(*startaddr == 0) { - printf("sdrrd
\n"); - return; - } - addr = strtoul(startaddr, &c, 0); - if(*c != 0) { - printf("incorrect address\n"); - return; - } - if(*dq == 0) - _dq = -1; - else { - _dq = strtoul(dq, &c, 0); - if(*c != 0) { - printf("incorrect DQ\n"); - return; - } - } - sdram_dfii_pird_address_write(addr); sdram_dfii_pird_baddress_write(0); command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA); cdelay(15); - sdrrdbuf(_dq); + sdrrdbuf(dq); } -void sdrrderr(char *count) +void sdrrderr(int count) { int addr; - char *c; - int _count; int i, j, p; unsigned char prev_data[SDRAM_PHY_PHASES][DFII_PIX_DATA_BYTES]; unsigned char errs[SDRAM_PHY_PHASES][DFII_PIX_DATA_BYTES]; unsigned char new_data[DFII_PIX_DATA_BYTES]; - if(*count == 0) { - printf("sdrrderr \n"); - return; - } - _count = strtoul(count, &c, 0); - if(*c != 0) { - printf("incorrect count\n"); - return; - } - for(p=0;p\n"); - return; - } - addr = strtoul(startaddr, &c, 0); - if(*c != 0) { - printf("incorrect address\n"); - return; - } - for(p=0;p