From 4087bc88cebec75c432a7fe9f6afb545b0919831 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 4 Feb 2008 19:26:54 -0500 Subject: fix building on Blackfin as the assembler supports the .set syntax, not the = syntax, for assigning symbols Signed-off-by: Mike Frysinger --- common/environment.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'common') diff --git a/common/environment.c b/common/environment.c index 24257f7..3b9914f 100644 --- a/common/environment.c +++ b/common/environment.c @@ -70,11 +70,16 @@ /* * Macros to generate global absolutes. */ +#if defined(__bfin__) +# define GEN_SET_VALUE(name, value) asm (".set " GEN_SYMNAME(name) ", " GEN_VALUE(value)) +#else +# define GEN_SET_VALUE(name, value) asm (GEN_SYMNAME(name) " = " GEN_VALUE(value)) +#endif #define GEN_SYMNAME(str) SYM_CHAR #str #define GEN_VALUE(str) #str #define GEN_ABS(name, value) \ asm (".globl " GEN_SYMNAME(name)); \ - asm (GEN_SYMNAME(name) " = " GEN_VALUE(value)) + GEN_SET_VALUE(name, value) /* * Macros to transform values -- cgit v1.1 From 8dc48d71a4be753ea9f84956cd33600de35fad04 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 4 Feb 2008 19:26:55 -0500 Subject: add Blackfin-specific bdinfo command Signed-off-by: Mike Frysinger --- common/cmd_bdinfo.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'common') diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c index c28a155..3a4dbcf 100644 --- a/common/cmd_bdinfo.c +++ b/common/cmd_bdinfo.c @@ -273,6 +273,37 @@ int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) return 0; } +#elif defined(CONFIG_BLACKFIN) + +int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int i; + bd_t *bd = gd->bd; + + printf("U-Boot = %s\n", bd->bi_r_version); + printf("CPU = %s\n", bd->bi_cpu); + printf("Board = %s\n", bd->bi_board_name); + printf("VCO = %lu MHz\n", bd->bi_vco / 1000000); + printf("CCLK = %lu MHz\n", bd->bi_cclk / 1000000); + printf("SCLK = %lu MHz\n", bd->bi_sclk / 1000000); + + print_num("boot_params", (ulong)bd->bi_boot_params); + print_num("memstart", (ulong)bd->bi_memstart); + print_num("memsize", (ulong)bd->bi_memsize); + print_num("flashstart", (ulong)bd->bi_flashstart); + print_num("flashsize", (ulong)bd->bi_flashsize); + print_num("flashoffset", (ulong)bd->bi_flashoffset); + + puts("ethaddr ="); + for (i = 0; i < 6; ++i) + printf("%c%02X", i ? ':' : ' ', bd->bi_enetaddr[i]); + puts("\nip_addr = "); + print_IPaddr(bd->bi_ip_addr); + printf("\nbaudrate = %d bps\n", bd->bi_baudrate); + + return 0; +} + #else /* ! PPC, which leaves MIPS */ int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) -- cgit v1.1 From 97c26e006d2fa6d4e1560933ee6f385d8b8908b9 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 4 Feb 2008 19:26:56 -0500 Subject: add Blackfin-specific reginfo command Signed-off-by: Mike Frysinger --- common/cmd_reginfo.c | 45 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) (limited to 'common') diff --git a/common/cmd_reginfo.c b/common/cmd_reginfo.c index bb6aa30..980664d 100644 --- a/common/cmd_reginfo.c +++ b/common/cmd_reginfo.c @@ -329,16 +329,53 @@ int do_reginfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) *(volatile ulong*)MPC5XXX_SDRAM_CS0CFG); printf ("\tSDRAMCS1: %08X\n", *(volatile ulong*)MPC5XXX_SDRAM_CS1CFG); + +#elif defined(CONFIG_BLACKFIN) + puts("\nSystem Configuration registers\n"); + + puts("\nPLL Registers\n"); + printf("\tPLL_DIV: 0x%04x PLL_CTL: 0x%04x\n", + bfin_read_PLL_DIV(), bfin_read_PLL_CTL()); + printf("\tPLL_STAT: 0x%04x PLL_LOCKCNT: 0x%04x\n", + bfin_read_PLL_STAT(), bfin_read_PLL_LOCKCNT()); + printf("\tVR_CTL: 0x%04x\n", bfin_read_VR_CTL()); + + puts("\nEBIU AMC Registers\n"); + printf("\tEBIU_AMGCTL: 0x%04x\n", bfin_read_EBIU_AMGCTL()); + printf("\tEBIU_AMBCTL0: 0x%08x EBIU_AMBCTL1: 0x%08x\n", + bfin_read_EBIU_AMBCTL0(), bfin_read_EBIU_AMBCTL1()); +# ifdef EBIU_MODE + printf("\tEBIU_MBSCTL: 0x%08x EBIU_ARBSTAT: 0x%08x\n", + bfin_read_EBIU_MBSCTL(), bfin_read_EBIU_ARBSTAT()); + printf("\tEBIU_MODE: 0x%08x EBIU_FCTL: 0x%08x\n", + bfin_read_EBIU_MODE(), bfin_read_EBIU_FCTL()); +# endif + +# ifdef EBIU_RSTCTL + puts("\nEBIU DDR Registers\n"); + printf("\tEBIU_DDRCTL0: 0x%08x EBIU_DDRCTL1: 0x%08x\n", + bfin_read_EBIU_DDRCTL0(), bfin_read_EBIU_DDRCTL1()); + printf("\tEBIU_DDRCTL2: 0x%08x EBIU_DDRCTL3: 0x%08x\n", + bfin_read_EBIU_DDRCTL2(), bfin_read_EBIU_DDRCTL3()); + printf("\tEBIU_DDRQUE: 0x%08x EBIU_RSTCTL 0x%04x\n", + bfin_read_EBIU_DDRQUE(), bfin_read_EBIU_RSTCTL()); + printf("\tEBIU_ERRADD: 0x%08x EBIU_ERRMST: 0x%04x\n", + bfin_read_EBIU_ERRADD(), bfin_read_EBIU_ERRMST()); +# else + puts("\nEBIU SDC Registers\n"); + printf("\tEBIU_SDRRC: 0x%04x EBIU_SDBCTL: 0x%04x\n", + bfin_read_EBIU_SDRRC(), bfin_read_EBIU_SDBCTL()); + printf("\tEBIU_SDSTAT: 0x%04x EBIU_SDGCTL: 0x%08x\n", + bfin_read_EBIU_SDSTAT(), bfin_read_EBIU_SDGCTL()); +# endif + #endif /* CONFIG_MPC5200 */ return 0; } /**************************************************/ -#if ( defined(CONFIG_8xx) || defined(CONFIG_405GP) || \ - defined(CONFIG_405EP) || defined(CONFIG_MPC5200) ) && \ - defined(CONFIG_CMD_REGINFO) - +#if defined(CONFIG_CMD_REGINFO) U_BOOT_CMD( reginfo, 2, 1, do_reginfo, "reginfo - print register information\n", -- cgit v1.1 From 4c727c77e43872d3a1d1f76a949fcb3f26a38788 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 4 Feb 2008 19:26:56 -0500 Subject: add support for memory commands with Blackfin L1 instruction memory Signed-off-by: Mike Frysinger --- common/cmd_mem.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) (limited to 'common') diff --git a/common/cmd_mem.c b/common/cmd_mem.c index a994211..d080810 100644 --- a/common/cmd_mem.c +++ b/common/cmd_mem.c @@ -154,9 +154,32 @@ int do_mem_md ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) } } while (nbytes > 0); #else - /* Print the lines. */ - print_buffer(addr, (void*)addr, size, length, DISP_LINE_LEN/size); - addr += size*length; + +# if defined(CONFIG_BLACKFIN) + /* See if we're trying to display L1 inst */ + if (addr_bfin_on_chip_mem(addr)) { + char linebuf[DISP_LINE_LEN]; + ulong linebytes, nbytes = length * size; + do { + linebytes = (nbytes > DISP_LINE_LEN) ? DISP_LINE_LEN : nbytes; + memcpy(linebuf, (void *)addr, linebytes); + print_buffer(addr, linebuf, size, linebytes/size, DISP_LINE_LEN/size); + + nbytes -= linebytes; + addr += linebytes; + if (ctrlc()) { + rc = 1; + break; + } + } while (nbytes > 0); + } else +# endif + + { + /* Print the lines. */ + print_buffer(addr, (void*)addr, size, length, DISP_LINE_LEN/size); + addr += size*length; + } #endif dp_last_addr = addr; @@ -308,6 +331,13 @@ int do_mem_cmp (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) } #endif +#ifdef CONFIG_BLACKFIN + if (addr_bfin_on_chip_mem(addr1) || addr_bfin_on_chip_mem(addr2)) { + puts ("Comparison with L1 instruction memory not supported.\n\r"); + return 0; + } +#endif + ngood = 0; while (count-- > 0) { @@ -478,6 +508,14 @@ int do_mem_cp ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) } #endif +#ifdef CONFIG_BLACKFIN + /* See if we're copying to/from L1 inst */ + if (addr_bfin_on_chip_mem(dest) || addr_bfin_on_chip_mem(addr)) { + memcpy((void *)dest, (void *)addr, count * size); + return 0; + } +#endif + while (count-- > 0) { if (size == 4) *((ulong *)dest) = *((ulong *)addr); @@ -1006,6 +1044,13 @@ mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char *argv[]) } #endif +#ifdef CONFIG_BLACKFIN + if (addr_bfin_on_chip_mem(addr)) { + puts ("Can't modify L1 instruction in place. Use cp instead.\n\r"); + return 0; + } +#endif + /* Print the address, followed by value. Then accept input for * the next value. A non-converted value exits. */ -- cgit v1.1 From d0b01a246d0a351bc7dce1d0c9cf6aebdf6d7505 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 4 Feb 2008 19:26:57 -0500 Subject: interface to Blackfin on-chip One-Time-Programmable memory Signed-off-by: Mike Frysinger --- common/Makefile | 1 + common/cmd_otp.c | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 164 insertions(+) create mode 100644 common/cmd_otp.c (limited to 'common') diff --git a/common/Makefile b/common/Makefile index fbfa536..3cdab37 100644 --- a/common/Makefile +++ b/common/Makefile @@ -76,6 +76,7 @@ COBJS-y += cmd_nand.o COBJS-$(CONFIG_CMD_NET) += cmd_net.o COBJS-y += cmd_nvedit.o COBJS-y += cmd_onenand.o +COBJS-$(CONFIG_CMD_OTP) += cmd_otp.o ifdef CONFIG_PCI COBJS-$(CONFIG_CMD_PCI) += cmd_pci.o endif diff --git a/common/cmd_otp.c b/common/cmd_otp.c new file mode 100644 index 0000000..825fa34 --- /dev/null +++ b/common/cmd_otp.c @@ -0,0 +1,163 @@ +/* + * cmd_otp.c - interface to Blackfin on-chip One-Time-Programmable memory + * + * Copyright (c) 2007-2008 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +/* There are 512 128-bit "pages" (0x000 to 0x1FF). + * The pages are accessable as 64-bit "halfpages" (an upper and lower half). + * The pages are not part of the memory map. There is an OTP controller which + * handles scanning in/out of bits. While access is done through OTP MMRs, + * the bootrom provides C-callable helper functions to handle the interaction. + */ + +#include +#include +#include + +#ifdef CONFIG_CMD_OTP + +#include +#include + +static const char *otp_strerror(uint32_t err) +{ + switch (err) { + case 0: return "no error"; + case OTP_WRITE_ERROR: return "OTP fuse write error"; + case OTP_READ_ERROR: return "OTP fuse read error"; + case OTP_ACC_VIO_ERROR: return "invalid OTP address"; + case OTP_DATA_MULT_ERROR: return "multiple bad bits detected"; + case OTP_ECC_MULT_ERROR: return "error in ECC bits"; + case OTP_PREV_WR_ERROR: return "space already written"; + case OTP_DATA_SB_WARN: return "single bad bit in half page"; + case OTP_ECC_SB_WARN: return "single bad bit in ECC"; + default: return "unknown error"; + } +} + +#define lowup(x) ((x) % 2 ? "upper" : "lower") + +int do_otp(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + bool force = false; + if (!strcmp(argv[1], "--force")) { + force = true; + argv[1] = argv[0]; + argv++; + --argc; + } + + uint32_t (*otp_func)(uint32_t page, uint32_t flags, uint64_t *page_content); + if (!strcmp(argv[1], "read")) + otp_func = otp_read; + else if (!strcmp(argv[1], "write")) + otp_func = otp_write; + else { + usage: + printf("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + uint64_t *addr = (uint64_t *)simple_strtoul(argv[2], NULL, 16); + uint32_t page = simple_strtoul(argv[3], NULL, 16); + uint32_t flags, ret; + size_t i, count; + ulong half; + + if (argc > 4) + count = simple_strtoul(argv[4], NULL, 16); + else + count = 2; + + if (argc > 5) { + half = simple_strtoul(argv[5], NULL, 16); + if (half != 0 && half != 1) { + puts("Error: 'half' can only be '0' or '1'\n"); + goto usage; + } + } else + half = 0; + + /* do to the nature of OTP, make sure users are sure */ + if (!force && otp_func == otp_write) { + printf( + "Writing one time programmable memory\n" + "Make sure your operating voltages and temperature are within spec\n" + " source address: 0x%p\n" + " OTP destination: %s page 0x%03X - %s page 0x%03X\n" + " number to write: %ld halfpages\n" + " type \"YES\" (no quotes) to confirm: ", + addr, + lowup(half), page, + lowup(half + count - 1), page + (half + count - 1) / 2, + half + count + ); + + i = 0; + while (1) { + if (tstc()) { + const char exp_ans[] = "YES\r"; + char c; + putc(c = getc()); + if (exp_ans[i++] != c) { + printf(" Aborting\n"); + return 1; + } else if (!exp_ans[i]) { + puts("\n"); + break; + } + } + } + + /* Only supported in newer silicon ... enable writing */ +#if (0) + otp_command(OTP_INIT, ...); +#else + *pOTP_TIMING = 0x32149485; +#endif + } + + printf("OTP memory %s: addr 0x%08lx page 0x%03X count %ld ... ", + argv[1], addr, page, count); + + ret = 0; + for (i = half; i < count + half; ++i) { + flags = (i % 2) ? OTP_UPPER_HALF : OTP_LOWER_HALF; + ret = otp_func(page, flags, addr); + if (ret & 0x1) + break; + else if (ret) + puts("W"); + else + puts("."); + ++addr; + if (i % 2) + ++page; + } + if (ret & 0x1) + printf("\nERROR at page 0x%03X (%s-halfpage): 0x%03X: %s\n", + page, lowup(i), ret, otp_strerror(ret)); + else + puts(" done\n"); + + if (otp_func == otp_write) + /* Only supported in newer silicon ... disable writing */ +#if (0) + otp_command(OTP_INIT, ...); +#else + *pOTP_TIMING = 0x1485; +#endif + + return ret; +} + +U_BOOT_CMD(otp, 6, 0, do_otp, + "otp - One-Time-Programmable sub-system\n", + "read [count] [half]\n" + "otp write [--force] [count] [half]\n" + " - read/write 'count' half-pages starting at page 'page' (offset 'half')\n"); + +#endif -- cgit v1.1 From 30942b18b66f35f2ceedab39af10e9eccaa943cc Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 4 Feb 2008 19:26:57 -0500 Subject: new command for displaying strings at specified memory locations Signed-off-by: Mike Frysinger --- common/Makefile | 1 + common/cmd_strings.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 common/cmd_strings.c (limited to 'common') diff --git a/common/Makefile b/common/Makefile index 3cdab37..a88d1ef 100644 --- a/common/Makefile +++ b/common/Makefile @@ -87,6 +87,7 @@ COBJS-$(CONFIG_CMD_REISER) += cmd_reiser.o COBJS-y += cmd_sata.o COBJS-$(CONFIG_CMD_SCSI) += cmd_scsi.o COBJS-$(CONFIG_CMD_SPI) += cmd_spi.o +COBJS-$(CONFIG_CMD_STRINGS) += cmd_strings.o COBJS-$(CONFIG_CMD_TERMINAL) += cmd_terminal.o COBJS-$(CONFIG_CMD_UNIVERSE) += cmd_universe.o COBJS-$(CONFIG_CMD_USB) += cmd_usb.o diff --git a/common/cmd_strings.c b/common/cmd_strings.c new file mode 100644 index 0000000..bbf56a0 --- /dev/null +++ b/common/cmd_strings.c @@ -0,0 +1,49 @@ +/* + * cmd_strings.c - just like `strings` command + * + * Copyright (c) 2008 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include + +#ifdef CONFIG_CFG_STRINGS + +static char *start_addr, *last_addr; + +int do_strings(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + if (argc == 1) { + printf("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + if ((flag & CMD_FLAG_REPEAT) == 0) { + start_addr = (char *)simple_strtoul(argv[1], NULL, 16); + if (argc > 2) + last_addr = (char *)simple_strtoul(argv[2], NULL, 16); + else + last_addr = (char *)-1; + } + + char *addr = start_addr; + do { + printf("%s\n", addr); + addr += strlen(addr) + 1; + } while (addr[0] && addr < last_addr); + + last_addr = addr + (last_addr - start_addr); + start_addr = addr; + + return 0; +} + +U_BOOT_CMD(strings, 3, 1, do_strings, + "strings - display strings\n", + " [byte count]\n" + " - display strings at for at least [byte count] or first double NUL\n"); + +#endif -- cgit v1.1