diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/Makefile | 2 | ||||
-rw-r--r-- | common/cmd_bdinfo.c | 31 | ||||
-rw-r--r-- | common/cmd_mem.c | 78 | ||||
-rw-r--r-- | common/cmd_otp.c | 163 | ||||
-rw-r--r-- | common/cmd_reginfo.c | 52 | ||||
-rw-r--r-- | common/cmd_strings.c | 49 | ||||
-rw-r--r-- | common/environment.c | 7 | ||||
-rw-r--r-- | common/miiphyutil.c | 31 |
8 files changed, 365 insertions, 48 deletions
diff --git a/common/Makefile b/common/Makefile index fbfa536..a88d1ef 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 @@ -86,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_bdinfo.c b/common/cmd_bdinfo.c index 4e77461..bbb0192 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[]) diff --git a/common/cmd_mem.c b/common/cmd_mem.c index a994211..ed91f27 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); @@ -659,9 +697,10 @@ int do_mem_mtest (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) vu_long *addr, *start, *end; ulong val; ulong readback; + int rcode = 0; #if defined(CFG_ALT_MEMTEST) - vu_long addr_mask; + vu_long len; vu_long offset; vu_long test_offset; vu_long pattern; @@ -689,7 +728,6 @@ int do_mem_mtest (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) #else ulong incr; ulong pattern; - int rcode = 0; #endif if (argc > 1) { @@ -798,26 +836,19 @@ int do_mem_mtest (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) * all possible. * * Returns: 0 if the test succeeds, 1 if the test fails. - * - * ## NOTE ## Be sure to specify start and end - * addresses such that addr_mask has - * lots of bits set. For example an - * address range of 01000000 02000000 is - * bad while a range of 01000000 - * 01ffffff is perfect. */ - addr_mask = ((ulong)end - (ulong)start)/sizeof(vu_long); + len = ((ulong)end - (ulong)start)/sizeof(vu_long); pattern = (vu_long) 0xaaaaaaaa; anti_pattern = (vu_long) 0x55555555; - PRINTF("%s:%d: addr mask = 0x%.8lx\n", + PRINTF("%s:%d: length = 0x%.8lx\n", __FUNCTION__, __LINE__, - addr_mask); + len); /* * Write the default pattern at each of the * power-of-two offsets. */ - for (offset = 1; (offset & addr_mask) != 0; offset <<= 1) { + for (offset = 1; offset < len; offset <<= 1) { start[offset] = pattern; } @@ -827,7 +858,7 @@ int do_mem_mtest (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) test_offset = 0; start[test_offset] = anti_pattern; - for (offset = 1; (offset & addr_mask) != 0; offset <<= 1) { + for (offset = 1; offset < len; offset <<= 1) { temp = start[offset]; if (temp != pattern) { printf ("\nFAILURE: Address bit stuck high @ 0x%.8lx:" @@ -841,10 +872,10 @@ int do_mem_mtest (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) /* * Check for addr bits stuck low or shorted. */ - for (test_offset = 1; (test_offset & addr_mask) != 0; test_offset <<= 1) { + for (test_offset = 1; test_offset < len; test_offset <<= 1) { start[test_offset] = anti_pattern; - for (offset = 1; (offset & addr_mask) != 0; offset <<= 1) { + for (offset = 1; offset < len; offset <<= 1) { temp = start[offset]; if ((temp != pattern) && (offset != test_offset)) { printf ("\nFAILURE: Address bit stuck low or shorted @" @@ -954,8 +985,8 @@ int do_mem_mtest (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) } incr = -incr; } - return rcode; #endif + return rcode; } @@ -1006,6 +1037,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. */ 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 <config.h> +#include <common.h> +#include <command.h> + +#ifdef CONFIG_CMD_OTP + +#include <asm/blackfin.h> +#include <asm/mach-common/bits/otp.h> + +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 <addr> <page> [count] [half]\n" + "otp write [--force] <addr> <page> [count] [half]\n" + " - read/write 'count' half-pages starting at page 'page' (offset 'half')\n"); + +#endif diff --git a/common/cmd_reginfo.c b/common/cmd_reginfo.c index bb6aa30..dd808ed 100644 --- a/common/cmd_reginfo.c +++ b/common/cmd_reginfo.c @@ -31,6 +31,8 @@ #include <mpc5xx.h> #elif defined (CONFIG_MPC5200) #include <mpc5xxx.h> +#elif defined (CONFIG_MPC86xx) +extern void mpc86xx_reginfo(void); #endif int do_reginfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) @@ -329,16 +331,56 @@ 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); -#endif /* CONFIG_MPC5200 */ +#elif defined(CONFIG_MPC86xx) + mpc86xx_reginfo(); + +#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_BLACKFIN */ + 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", 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 <config.h> +#include <common.h> +#include <command.h> + +#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", + "<addr> [byte count]\n" + " - display strings at <addr> for at least [byte count] or first double NUL\n"); + +#endif 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 diff --git a/common/miiphyutil.c b/common/miiphyutil.c index 281f0b2..eac8275 100644 --- a/common/miiphyutil.c +++ b/common/miiphyutil.c @@ -36,7 +36,6 @@ #include <net.h> /* local debug macro */ -#define MII_DEBUG #undef MII_DEBUG #undef debug @@ -261,31 +260,25 @@ int miiphy_info (char *devname, unsigned char addr, unsigned int *oui, unsigned short tmp; if (miiphy_read (devname, addr, PHY_PHYIDR2, &tmp) != 0) { -#ifdef DEBUG - puts ("PHY ID register 2 read failed\n"); -#endif + debug ("PHY ID register 2 read failed\n"); return (-1); } reg = tmp; -#ifdef DEBUG - printf ("PHY_PHYIDR2 @ 0x%x = 0x%04x\n", addr, reg); -#endif + debug ("PHY_PHYIDR2 @ 0x%x = 0x%04x\n", addr, reg); + if (reg == 0xFFFF) { /* No physical device present at this address */ return (-1); } if (miiphy_read (devname, addr, PHY_PHYIDR1, &tmp) != 0) { -#ifdef DEBUG - puts ("PHY ID register 1 read failed\n"); -#endif + debug ("PHY ID register 1 read failed\n"); return (-1); } reg |= tmp << 16; -#ifdef DEBUG - printf ("PHY_PHYIDR[1,2] @ 0x%x = 0x%08x\n", addr, reg); -#endif + debug ("PHY_PHYIDR[1,2] @ 0x%x = 0x%08x\n", addr, reg); + *oui = (reg >> 10); *model = (unsigned char)((reg >> 4) & 0x0000003F); *rev = (unsigned char)(reg & 0x0000000F); @@ -304,15 +297,11 @@ int miiphy_reset (char *devname, unsigned char addr) int loop_cnt; if (miiphy_read (devname, addr, PHY_BMCR, ®) != 0) { -#ifdef DEBUG - printf ("PHY status read failed\n"); -#endif + debug ("PHY status read failed\n"); return (-1); } if (miiphy_write (devname, addr, PHY_BMCR, reg | 0x8000) != 0) { -#ifdef DEBUG - puts ("PHY reset failed\n"); -#endif + debug ("PHY reset failed\n"); return (-1); } #ifdef CONFIG_PHY_RESET_DELAY @@ -327,9 +316,7 @@ int miiphy_reset (char *devname, unsigned char addr) reg = 0x8000; while (((reg & 0x8000) != 0) && (loop_cnt++ < 1000000)) { if (miiphy_read (devname, addr, PHY_BMCR, ®) != 0) { -# ifdef DEBUG - puts ("PHY status read failed\n"); -# endif + debug ("PHY status read failed\n"); return (-1); } } |