diff options
Diffstat (limited to 'lib_blackfin')
-rw-r--r-- | lib_blackfin/Makefile | 6 | ||||
-rw-r--r-- | lib_blackfin/bf533_linux.c | 35 | ||||
-rw-r--r-- | lib_blackfin/bf533_string.c | 184 | ||||
-rw-r--r-- | lib_blackfin/blackfin_board.h | 2 | ||||
-rw-r--r-- | lib_blackfin/board.c | 238 | ||||
-rw-r--r-- | lib_blackfin/cache.c | 29 | ||||
-rw-r--r-- | lib_blackfin/memcmp.S | 109 | ||||
-rw-r--r-- | lib_blackfin/memcpy.S | 127 | ||||
-rw-r--r-- | lib_blackfin/memmove.S | 102 | ||||
-rw-r--r-- | lib_blackfin/memset.S | 103 | ||||
-rw-r--r-- | lib_blackfin/muldi3.c | 24 | ||||
-rw-r--r-- | lib_blackfin/post.c | 435 | ||||
-rw-r--r-- | lib_blackfin/tests.c | 253 |
13 files changed, 1482 insertions, 165 deletions
diff --git a/lib_blackfin/Makefile b/lib_blackfin/Makefile index de7114b80ae..ac786626f71 100644 --- a/lib_blackfin/Makefile +++ b/lib_blackfin/Makefile @@ -3,7 +3,7 @@ # # Copyright (c) 2005 blackfin.uclinux.org # -# (C) Copyright 2000-2006 +# (C) Copyright 2000-2004 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. # # See file CREDITS for list of people who contributed to this @@ -29,9 +29,9 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(ARCH).a -SOBJS = +SOBJS = memcpy.o memcmp.o memset.o memmove.o -COBJS = board.o bf533_linux.o bf533_string.o cache.o muldi3.o +COBJS = post.o tests.o board.o bf533_linux.o bf533_string.o cache.o muldi3.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/lib_blackfin/bf533_linux.c b/lib_blackfin/bf533_linux.c index 88b4da29df9..1b0d90ae67f 100644 --- a/lib_blackfin/bf533_linux.c +++ b/lib_blackfin/bf533_linux.c @@ -43,20 +43,21 @@ #define SHOW_BOOT_PROGRESS(arg) #endif -#define CMD_LINE_ADDR 0xFF900000 /* L1 scratchpad */ +#define CMD_LINE_ADDR 0xFF900000 /* L1 scratchpad */ #ifdef SHARED_RESOURCES - extern void swap_to(int device_id); +extern void swap_to(int device_id); #endif +extern image_header_t header; +extern void flush_instruction_cache(void); +extern void flush_data_cache(void); static char *make_command_line(void); -extern image_header_t header; -extern int do_reset(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]); void do_bootm_linux(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[], ulong addr, ulong * len_ptr, int verify) { - int (*appl)(char *cmdline); + int (*appl) (char *cmdline); char *cmdline; #ifdef SHARED_RESOURCES @@ -66,26 +67,26 @@ void do_bootm_linux(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[], appl = (int (*)(char *))ntohl(header.ih_ep); printf("Starting Kernel at = %x\n", appl); cmdline = make_command_line(); - if(icache_status()){ + if (icache_status()) { flush_instruction_cache(); icache_disable(); - } - if(dcache_status()){ + } + if (dcache_status()) { flush_data_cache(); dcache_disable(); - } - (*appl)(cmdline); + } + (*appl) (cmdline); } char *make_command_line(void) { - char *dest = (char *) CMD_LINE_ADDR; - char *bootargs; + char *dest = (char *)CMD_LINE_ADDR; + char *bootargs; - if ( (bootargs = getenv("bootargs")) == NULL ) - return NULL; + if ((bootargs = getenv("bootargs")) == NULL) + return NULL; - strncpy(dest, bootargs, 0x1000); - dest[0xfff] = 0; - return dest; + strncpy(dest, bootargs, 0x1000); + dest[0xfff] = 0; + return dest; } diff --git a/lib_blackfin/bf533_string.c b/lib_blackfin/bf533_string.c index c8b1a3a9833..85b115076af 100644 --- a/lib_blackfin/bf533_string.c +++ b/lib_blackfin/bf533_string.c @@ -28,9 +28,15 @@ #include <common.h> #include <asm/setup.h> #include <asm/page.h> -#include <asm/cpu/defBF533.h> +#include <config.h> +#include <asm/blackfin.h> +#include <asm/io.h> -void *dma_memcpy(void *,const void *,size_t); +extern void blackfin_icache_flush_range(const void *, const void *); +extern void blackfin_dcache_flush_range(const void *, const void *); +extern void *memcpy_ASM(void *dest, const void *src, size_t count); + +void *dma_memcpy(void *, const void *, size_t); char *strcpy(char *dest, const char *src) { @@ -38,11 +44,11 @@ char *strcpy(char *dest, const char *src) char temp = 0; __asm__ __volatile__ - ("1:\t%2 = B [%1++] (Z);\n\t" - "B [%0++] = %2;\n\t" - "CC = %2;\n\t" - "if cc jump 1b (bp);\n":"=a"(dest), "=a"(src), "=d"(temp) - :"0"(dest), "1"(src), "2"(temp):"memory"); + ("1:\t%2 = B [%1++] (Z);\n\t" + "B [%0++] = %2;\n\t" + "CC = %2;\n\t" + "if cc jump 1b (bp);\n":"=a"(dest), "=a"(src), "=d"(temp) + :"0"(dest), "1"(src), "2"(temp):"memory"); return xdest; } @@ -56,16 +62,16 @@ char *strncpy(char *dest, const char *src, size_t n) return xdest; __asm__ __volatile__ - ("1:\t%3 = B [%1++] (Z);\n\t" - "B [%0++] = %3;\n\t" - "CC = %3;\n\t" - "if ! cc jump 2f;\n\t" - "%2 += -1;\n\t" - "CC = %2 == 0;\n\t" - "if ! cc jump 1b (bp);\n" - "2:\n":"=a"(dest), "=a"(src), "=da"(n), "=d"(temp) - :"0"(dest), "1"(src), "2"(n), "3"(temp) - :"memory"); + ("1:\t%3 = B [%1++] (Z);\n\t" + "B [%0++] = %3;\n\t" + "CC = %3;\n\t" + "if ! cc jump 2f;\n\t" + "%2 += -1;\n\t" + "CC = %2 == 0;\n\t" + "if ! cc jump 1b (bp);\n" + "2:\n":"=a"(dest), "=a"(src), "=da"(n), "=d"(temp) + :"0"(dest), "1"(src), "2"(n), "3"(temp) + :"memory"); return xdest; } @@ -74,18 +80,16 @@ int strcmp(const char *cs, const char *ct) { char __res1, __res2; - __asm__ - ("1:\t%2 = B[%0++] (Z);\n\t" /* get *cs */ - "%3 = B[%1++] (Z);\n\t" /* get *ct */ - "CC = %2 == %3;\n\t" /* compare a byte */ - "if ! cc jump 2f;\n\t" /* not equal, break out */ - "CC = %2;\n\t" /* at end of cs? */ + __asm__("1:\t%2 = B[%0++] (Z);\n\t" /* get *cs */ + "%3 = B[%1++] (Z);\n\t" /* get *ct */ + "CC = %2 == %3;\n\t" /* compare a byte */ + "if ! cc jump 2f;\n\t" /* not equal, break out */ + "CC = %2;\n\t" /* at end of cs? */ "if cc jump 1b (bp);\n\t" /* no, keep going */ - "jump.s 3f;\n" /* strings are equal */ - "2:\t%2 = %2 - %3;\n" /* *cs - *ct */ - "3:\n": "=a"(cs), "=a"(ct), "=d"(__res1), - "=d"(__res2) - : "0"(cs), "1"(ct)); + "jump.s 3f;\n" /* strings are equal */ + "2:\t%2 = %2 - %3;\n" /* *cs - *ct */ + "3:\n": "=a"(cs), "=a"(ct), "=d"(__res1), "=d"(__res2) + : "0"(cs), "1"(ct)); return __res1; } @@ -97,20 +101,19 @@ int strncmp(const char *cs, const char *ct, size_t count) if (!count) return 0; - __asm__ - ("1:\t%3 = B[%0++] (Z);\n\t" /* get *cs */ - "%4 = B[%1++] (Z);\n\t" /* get *ct */ - "CC = %3 == %4;\n\t" /* compare a byte */ - "if ! cc jump 3f;\n\t" /* not equal, break out */ - "CC = %3;\n\t" /* at end of cs? */ - "if ! cc jump 4f;\n\t" /* yes, all done */ - "%2 += -1;\n\t" /* no, adjust count */ + __asm__("1:\t%3 = B[%0++] (Z);\n\t" /* get *cs */ + "%4 = B[%1++] (Z);\n\t" /* get *ct */ + "CC = %3 == %4;\n\t" /* compare a byte */ + "if ! cc jump 3f;\n\t" /* not equal, break out */ + "CC = %3;\n\t" /* at end of cs? */ + "if ! cc jump 4f;\n\t" /* yes, all done */ + "%2 += -1;\n\t" /* no, adjust count */ "CC = %2 == 0;\n\t" "if ! cc jump 1b;\n" /* more to do, keep going */ - "2:\t%3 = 0;\n\t" /* strings are equal */ + "2:\t%3 = 0;\n\t" /* strings are equal */ "jump.s 4f;\n" "3:\t%3 = %3 - %4;\n" /* *cs - *ct */ - "4:": "=a"(cs), "=a"(ct), "=da"(count), "=d"(__res1), + "4:": "=a"(cs), "=a"(ct), "=da"(count), "=d"(__res1), "=d"(__res2) - : "0"(cs), "1"(ct), "2"(count)); + : "0"(cs), "1"(ct), "2"(count)); return __res1; } @@ -124,62 +127,65 @@ int strncmp(const char *cs, const char *ct, size_t count) * You should not use this function to access IO space, use memcpy_toio() * or memcpy_fromio() instead. */ -void * memcpy(void * dest,const void *src,size_t count) +void *memcpy(void *dest, const void *src, size_t count) { - char *tmp = (char *) dest, *s = (char *) src; - -/* Turn off the cache, if destination in the L1 memory */ - if ( (tmp >= (char *)L1_ISRAM) && (tmp < (char *)L1_ISRAM_END) - || (tmp >= (char *)DATA_BANKA_SRAM) && (tmp < DATA_BANKA_SRAM_END) - || (tmp >= (char *)DATA_BANKB_SRAM) && (tmp < DATA_BANKB_SRAM_END) ){ - if(icache_status()){ - blackfin_icache_flush_range(src, src+count); - icache_disable(); - } - if(dcache_status()){ - blackfin_dcache_flush_range(src, src+count); - dcache_disable(); - } - dma_memcpy(dest,src,count); - }else{ - while(count--) - *tmp++ = *s++; + char *tmp = (char *)dest, *s = (char *)src; + + /* L1_ISRAM can only be accessed via dma */ + if ((tmp >= (char *)L1_ISRAM) && (tmp < (char *)L1_ISRAM_END)) { + /* L1 is the destination */ + dma_memcpy(dest, src, count); + + if (icache_status()) { + blackfin_icache_flush_range(src, src + count); + } + } else if ((s >= (char *)L1_ISRAM) && (s < (char *)L1_ISRAM_END)) { + /* L1 is the source */ + dma_memcpy(dest, src, count); + + if (icache_status()) { + blackfin_icache_flush_range(dest, dest + count); + } + if (dcache_status()) { + blackfin_dcache_flush_range(dest, dest + count); + } + } else { + memcpy_ASM(dest, src, count); } return dest; } -void *dma_memcpy(void * dest,const void *src,size_t count) +void *dma_memcpy(void *dest, const void *src, size_t count) { - - *pMDMA_D0_IRQ_STATUS = DMA_DONE | DMA_ERR; - - /* Copy sram functions from sdram to sram */ - /* Setup destination start address */ - *pMDMA_D0_START_ADDR = (volatile void **)dest; - /* Setup destination xcount */ - *pMDMA_D0_X_COUNT = count ; - /* Setup destination xmodify */ - *pMDMA_D0_X_MODIFY = 1; - - /* Setup Source start address */ - *pMDMA_S0_START_ADDR = (volatile void **)src; - /* Setup Source xcount */ - *pMDMA_S0_X_COUNT = count; - /* Setup Source xmodify */ - *pMDMA_S0_X_MODIFY = 1; - - /* Enable source DMA */ - *pMDMA_S0_CONFIG = (DMAEN); - asm("ssync;"); - - *pMDMA_D0_CONFIG = ( WNR | DMAEN); - - while(*pMDMA_D0_IRQ_STATUS & DMA_RUN){ - *pMDMA_D0_IRQ_STATUS |= (DMA_DONE | DMA_ERR); - } + *pMDMA_D0_IRQ_STATUS = DMA_DONE | DMA_ERR; + + /* Copy sram functions from sdram to sram */ + /* Setup destination start address */ + *pMDMA_D0_START_ADDR = (volatile void **)dest; + /* Setup destination xcount */ + *pMDMA_D0_X_COUNT = count; + /* Setup destination xmodify */ + *pMDMA_D0_X_MODIFY = 1; + + /* Setup Source start address */ + *pMDMA_S0_START_ADDR = (volatile void **)src; + /* Setup Source xcount */ + *pMDMA_S0_X_COUNT = count; + /* Setup Source xmodify */ + *pMDMA_S0_X_MODIFY = 1; + + /* Enable source DMA */ + *pMDMA_S0_CONFIG = (DMAEN); + sync(); + + *pMDMA_D0_CONFIG = (WNR | DMAEN); + + while (*pMDMA_D0_IRQ_STATUS & DMA_RUN) { *pMDMA_D0_IRQ_STATUS |= (DMA_DONE | DMA_ERR); + } + *pMDMA_D0_IRQ_STATUS |= (DMA_DONE | DMA_ERR); - dest += count; - src += count; - return dest; + dest += count; + src += count; + return dest; } diff --git a/lib_blackfin/blackfin_board.h b/lib_blackfin/blackfin_board.h index 31c16a20fe1..e0b96da875d 100644 --- a/lib_blackfin/blackfin_board.h +++ b/lib_blackfin/blackfin_board.h @@ -28,6 +28,8 @@ #ifndef __BLACKFIN_BOARD_H__ #define __BLACKFIN_BOARD_H__ +#include <version.h> + extern void timer_init(void); extern void init_IRQ(void); extern void rtc_init(void); diff --git a/lib_blackfin/board.c b/lib_blackfin/board.c index d9dc2b6d0cf..1a0a2826c06 100644 --- a/lib_blackfin/board.c +++ b/lib_blackfin/board.c @@ -32,21 +32,69 @@ #include <version.h> #include <net.h> #include <environment.h> +#include <i2c.h> #include "blackfin_board.h" +#include <asm/cplb.h> #include "../drivers/smc91111.h" -DECLARE_GLOBAL_DATA_PTR; +#if defined(CONFIG_BF537)&&defined(CONFIG_POST) +#include <post.h> +int post_flag; +#endif +#ifndef CFG_NO_FLASH extern flash_info_t flash_info[]; +#endif + +static inline u_long get_vco(void) +{ + u_long msel; + u_long vco; + msel = (*pPLL_CTL >> 9) & 0x3F; + if (0 == msel) + msel = 64; + + vco = CONFIG_CLKIN_HZ; + vco >>= (1 & *pPLL_CTL); /* DF bit */ + vco = msel * vco; + return vco; +} + +/*Get the Core clock*/ +u_long get_cclk(void) +{ + u_long csel, ssel; + if (*pPLL_STAT & 0x1) + return CONFIG_CLKIN_HZ; + + ssel = *pPLL_DIV; + csel = ((ssel >> 4) & 0x03); + ssel &= 0xf; + if (ssel && ssel < (1 << csel)) /* SCLK > CCLK */ + return get_vco() / ssel; + return get_vco() >> csel; +} + +/* Get the System clock */ +u_long get_sclk(void) +{ + u_long ssel; + + if (*pPLL_STAT & 0x1) + return CONFIG_CLKIN_HZ; + + ssel = (*pPLL_DIV & 0xf); + + return get_vco() / ssel; +} static void mem_malloc_init(void) { mem_malloc_start = CFG_MALLOC_BASE; mem_malloc_end = (CFG_MALLOC_BASE + CFG_MALLOC_LEN); mem_malloc_brk = mem_malloc_start; - memset((void *) mem_malloc_start, 0, - mem_malloc_end - mem_malloc_start); + memset((void *)mem_malloc_start, 0, mem_malloc_end - mem_malloc_start); } void *sbrk(ptrdiff_t increment) @@ -59,7 +107,7 @@ void *sbrk(ptrdiff_t increment) } mem_malloc_brk = new; - return ((void *) old); + return ((void *)old); } static int display_banner(void) @@ -78,17 +126,20 @@ static void display_flash_config(ulong size) static int init_baudrate(void) { - uchar tmp[64]; + DECLARE_GLOBAL_DATA_PTR; + + char tmp[64]; int i = getenv_r("baudrate", tmp, sizeof(tmp)); gd->bd->bi_baudrate = gd->baudrate = (i > 0) - ? (int) simple_strtoul(tmp, NULL, 10) - : CONFIG_BAUDRATE; + ? (int)simple_strtoul(tmp, NULL, 10) + : CONFIG_BAUDRATE; return (0); } #ifdef DEBUG static void display_global_data(void) { + DECLARE_GLOBAL_DATA_PTR; bd_t *bd; bd = gd->bd; printf("--flags:%x\n", gd->flags); @@ -103,12 +154,10 @@ static void display_global_data(void) printf("---bi_baudrate:%x\n", bd->bi_baudrate); printf("---bi_ip_addr:%x\n", bd->bi_ip_addr); printf("---bi_enetaddr:%x %x %x %x %x %x\n", - bd->bi_enetaddr[0], - bd->bi_enetaddr[1], - bd->bi_enetaddr[2], - bd->bi_enetaddr[3], - bd->bi_enetaddr[4], - bd->bi_enetaddr[5]); + bd->bi_enetaddr[0], + bd->bi_enetaddr[1], + bd->bi_enetaddr[2], + bd->bi_enetaddr[3], bd->bi_enetaddr[4], bd->bi_enetaddr[5]); printf("---bi_arch_number:%x\n", bd->bi_arch_number); printf("---bi_boot_params:%x\n", bd->bi_boot_params); printf("---bi_memstart:%x\n", bd->bi_memstart); @@ -120,6 +169,71 @@ static void display_global_data(void) } #endif +/* we cover everything with 4 meg pages, and need an extra for L1 */ +unsigned int icplb_table[page_descriptor_table_size][2]; +unsigned int dcplb_table[page_descriptor_table_size][2]; + +void init_cplbtables(void) +{ + int i, j; + + j = 0; + icplb_table[j][0] = 0xFFA00000; + icplb_table[j][1] = L1_IMEMORY; + j++; + + for (i = 0; i <= CONFIG_MEM_SIZE / 4; i++) { + icplb_table[j][0] = (i * 4 * 1024 * 1024); + if (i * 4 * 1024 * 1024 <= CFG_MONITOR_BASE + && (i + 1) * 4 * 1024 * 1024 >= CFG_MONITOR_BASE) { + icplb_table[j][1] = SDRAM_IKERNEL; + } else { + icplb_table[j][1] = SDRAM_IGENERIC; + } + j++; + } +#if defined(CONFIG_BF561) + /* Async Memory space */ + for (i = 0; i < 3; i++) { + icplb_table[j++][0] = 0x20000000 + i * 4 * 1024 * 1024; + icplb_table[j++][1] = SDRAM_IGENERIC; + } +#else + icplb_table[j][0] = 0x20000000; + icplb_table[j][1] = SDRAM_IGENERIC; +#endif + j = 0; + dcplb_table[j][0] = 0xFF800000; + dcplb_table[j][1] = L1_DMEMORY; + j++; + + for (i = 0; i < CONFIG_MEM_SIZE / 4; i++) { + dcplb_table[j][0] = (i * 4 * 1024 * 1024); + if (i * 4 * 1024 * 1024 <= CFG_MONITOR_BASE + && (i + 1) * 4 * 1024 * 1024 >= CFG_MONITOR_BASE) { + dcplb_table[j][1] = SDRAM_DKERNEL; + } else { + dcplb_table[j][1] = SDRAM_DGENERIC; + } + j++; + } + +#if defined(CONFIG_BF561) + /* MAC space */ + dcplb_table[j++][0] = CONFIG_ASYNC_EBIU_BASE; + dcplb_table[j++][1] = SDRAM_EBIU; + + /* Flash space */ + for (i = 0; i < 2; i++) { + dcplb_table[j++][0] = 0x20000000 + i * 4 * 1024 * 1024; + dcplb_table[j++][1] = SDRAM_EBIU; + } +#else + dcplb_table[j][0] = 0x20000000; + dcplb_table[j][1] = SDRAM_EBIU; +#endif +} + /* * All attempts to come up with a "common" initialization sequence * that works for all boards and architectures failed: some of the @@ -135,20 +249,24 @@ static void display_global_data(void) void board_init_f(ulong bootflag) { + DECLARE_GLOBAL_DATA_PTR; ulong addr; bd_t *bd; + int i; + + init_cplbtables(); gd = (gd_t *) (CFG_GBL_DATA_ADDR); - memset((void *) gd, 0, sizeof(gd_t)); + memset((void *)gd, 0, sizeof(gd_t)); /* Board data initialization */ addr = (CFG_GBL_DATA_ADDR + sizeof(gd_t)); /* Align to 4 byte boundary */ addr &= ~(4 - 1); - bd = (bd_t*)addr; + bd = (bd_t *) addr; gd->bd = bd; - memset((void *) bd, 0, sizeof(bd_t)); + memset((void *)bd, 0, sizeof(bd_t)); /* Initialize */ init_IRQ(); @@ -156,21 +274,51 @@ void board_init_f(ulong bootflag) init_baudrate(); /* initialze baudrate settings */ serial_init(); /* serial communications setup */ console_init_f(); +#ifdef CONFIG_ICACHE_ON + icache_enable(); +#endif +#ifdef CONFIG_DCACHE_ON + dcache_enable(); +#endif display_banner(); /* say that we are here */ + + for (i = 0; i < page_descriptor_table_size; i++) { + debug + ("data (%02i)= 0x%08x : 0x%08x intr = 0x%08x : 0x%08x\n", + i, dcplb_table[i][0], dcplb_table[i][1], icplb_table[i][0], + icplb_table[i][1]); + } + checkboard(); #if defined(CONFIG_RTC_BF533) && (CONFIG_COMMANDS & CFG_CMD_DATE) rtc_init(); #endif timer_init(); - printf("Clock: VCO: %lu MHz, Core: %lu MHz, System: %lu MHz\n", \ - CONFIG_VCO_HZ/1000000, CONFIG_CCLK_HZ/1000000, CONFIG_SCLK_HZ/1000000); + printf("Clock: VCO: %lu MHz, Core: %lu MHz, System: %lu MHz\n", + get_vco() / 1000000, get_cclk() / 1000000, get_sclk() / 1000000); printf("SDRAM: "); print_size(initdram(0), "\n"); +#if defined(CONFIG_BF537)&&defined(CONFIG_POST) + post_init_f(); + post_bootmode_init(); + post_run(NULL, POST_ROM | post_bootmode_get(0)); +#endif board_init_r((gd_t *) gd, 0x20000010); } +#if defined(CONFIG_SOFT_I2C) || defined(CONFIG_HARD_I2C) +static int init_func_i2c(void) +{ + puts("I2C: "); + i2c_init(CFG_I2C_SPEED, CFG_I2C_SLAVE); + puts("ready\n"); + return (0); +} +#endif + void board_init_r(gd_t * id, ulong dest_addr) { + DECLARE_GLOBAL_DATA_PTR; ulong size; extern void malloc_bin_reloc(void); char *s, *e; @@ -180,12 +328,18 @@ void board_init_r(gd_t * id, ulong dest_addr) gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */ bd = gd->bd; -#if CONFIG_STAMP +#if defined(CONFIG_BF537) && defined(CONFIG_POST) + post_output_backlog(); + post_reloc(); +#endif + +#if (CONFIG_STAMP || CONFIG_BF537 || CONFIG_EZKIT561) && !defined(CFG_NO_FLASH) /* There are some other pointer constants we must deal with */ /* configure available FLASH banks */ size = flash_init(); display_flash_config(size); - flash_protect(FLAG_PROTECT_SET, CFG_FLASH_BASE, CFG_FLASH_BASE + 0x1ffff, &flash_info[0]); + flash_protect(FLAG_PROTECT_SET, CFG_FLASH_BASE, + CFG_FLASH_BASE + 0x1ffff, &flash_info[0]); bd->bi_flashstart = CFG_FLASH_BASE; bd->bi_flashsize = size; bd->bi_flashoffset = 0; @@ -198,6 +352,13 @@ void board_init_r(gd_t * id, ulong dest_addr) mem_malloc_init(); malloc_bin_reloc(); +#ifdef CONFIG_SPI +# if ! defined(CFG_ENV_IS_IN_EEPROM) + spi_init_f(); +# endif + spi_init_r(); +#endif + /* relocate environment function pointers etc. */ env_relocate(); @@ -228,18 +389,30 @@ void board_init_r(gd_t * id, ulong dest_addr) copy_filename(BootFile, s, sizeof(BootFile)); } #endif + +#if (CONFIG_COMMANDS & CFG_CMD_NAND) + puts("NAND: "); + nand_init(); /* go init the NAND */ +#endif + #if defined(CONFIG_MISC_INIT_R) /* miscellaneous platform dependent initialisations */ misc_init_r(); #endif +#if ((BFIN_CPU == ADSP_BF537) || (BFIN_CPU == ADSP_BF536)) + printf("Net: "); + eth_initialize(bd); +#endif + #ifdef CONFIG_DRIVER_SMC91111 #ifdef SHARED_RESOURCES /* Switch to Ethernet */ swap_to(ETHERNET); #endif - if ( (SMC_inw(BANK_SELECT) & UPPER_BYTE_MASK) != SMC_IDENT ) { - printf("ERROR: Can't find SMC91111 at address %x\n", SMC_BASE_ADDRESS); + if ((SMC_inw(BANK_SELECT) & UPPER_BYTE_MASK) != SMC_IDENT) { + printf("ERROR: Can't find SMC91111 at address %x\n", + SMC_BASE_ADDRESS); } else { printf("Net: SMC91111 at 0x%08X\n", SMC_BASE_ADDRESS); } @@ -248,12 +421,17 @@ void board_init_r(gd_t * id, ulong dest_addr) swap_to(FLASH); #endif #endif -#ifdef CONFIG_SOFT_I2C +#if defined(CONFIG_SOFT_I2C) || defined(CONFIG_HARD_I2C) init_func_i2c(); #endif #ifdef DEBUG - display_global_data(void); + display_global_data(); +#endif + +#if defined(CONFIG_BF537) && defined(CONFIG_POST) + if (post_flag) + post_run(NULL, POST_RAM | post_bootmode_get(0)); #endif /* main_loop() can return to retry autoboot, if so just run it again. */ @@ -262,18 +440,8 @@ void board_init_r(gd_t * id, ulong dest_addr) } } -#ifdef CONFIG_SOFT_I2C -static int init_func_i2c (void) -{ - puts ("I2C: "); - i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE); - puts ("ready\n"); - return (0); -} -#endif - void hang(void) { puts("### ERROR ### Please RESET the board ###\n"); - for (;;); + for (;;) ; } diff --git a/lib_blackfin/cache.c b/lib_blackfin/cache.c index 847278d226e..a15914b1098 100644 --- a/lib_blackfin/cache.c +++ b/lib_blackfin/cache.c @@ -26,15 +26,26 @@ */ /* for now: just dummy functions to satisfy the linker */ -extern void blackfin_icache_range (unsigned long *, unsigned long *); -extern void blackfin_dcache_range (unsigned long *, unsigned long *); -void flush_cache (unsigned long dummy1, unsigned long dummy2) +#include <config.h> +#include <common.h> +#include <asm/blackfin.h> + +extern void blackfin_icache_flush_range(unsigned long, unsigned long); +extern void blackfin_dcache_flush_range(unsigned long, unsigned long); + +void flush_cache(unsigned long dummy1, unsigned long dummy2) { - if (icache_status ()) { - blackfin_icache_flush_range (dummy1, dummy1 + dummy2); - } - if (dcache_status ()) { - blackfin_dcache_flush_range (dummy1, dummy1 + dummy2); - } + if ((dummy1 >= L1_ISRAM) && (dummy1 < L1_ISRAM_END)) + return; + if ((dummy1 >= DATA_BANKA_SRAM) && (dummy1 < DATA_BANKA_SRAM_END)) + return; + if ((dummy1 >= DATA_BANKB_SRAM) && (dummy1 < DATA_BANKB_SRAM_END)) + return; + + if (icache_status()) + blackfin_icache_flush_range(dummy1, dummy1 + dummy2); + if (dcache_status()) + blackfin_dcache_flush_range(dummy1, dummy1 + dummy2); + return; } diff --git a/lib_blackfin/memcmp.S b/lib_blackfin/memcmp.S new file mode 100644 index 00000000000..fcea5b3daf6 --- /dev/null +++ b/lib_blackfin/memcmp.S @@ -0,0 +1,109 @@ +/* + * File: arch/blackfin/lib/memcmp.S + * Based on: + * Author: + * + * Created: + * Description: + * + * Rev: $Id: memcmp.S 2386 2006-11-01 04:57:26Z magicyang $ + * + * Modified: + * Copyright 2004-2006 Analog Devices Inc. + * + * Bugs: Enter bugs at http://blackfin.uclinux.org/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see the file COPYING, or write + * to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +.align 2 + +/* + * C Library function MEMCMP + * R0 = First Address + * R1 = Second Address + * R2 = count + * Favours word aligned data. + */ + +.globl _memcmp; +_memcmp: + I1 = P3; + P0 = R0; /* P0 = s1 address */ + P3 = R1; /* P3 = s2 Address */ + P2 = R2 ; /* P2 = count */ + CC = R2 <= 7(IU); + IF CC JUMP .Ltoo_small; + I0 = R1; /* s2 */ + R1 = R1 | R0; /* OR addresses together */ + R1 <<= 30; /* check bottom two bits */ + CC = AZ; /* AZ set if zero. */ + IF !CC JUMP .Lbytes ; /* Jump if addrs not aligned. */ + + P1 = P2 >> 2; /* count = n/4 */ + R3 = 3; + R2 = R2 & R3; /* remainder */ + P2 = R2; /* set remainder */ + + LSETUP (.Lquad_loop_s , .Lquad_loop_e) LC0=P1; +.Lquad_loop_s: + NOP; + R0 = [P0++]; + R1 = [I0++]; + CC = R0 == R1; + IF !CC JUMP .Lquad_different; +.Lquad_loop_e: + NOP; + + P3 = I0; /* s2 */ +.Ltoo_small: + CC = P2 == 0; /* Check zero count*/ + IF CC JUMP .Lfinished; /* very unlikely*/ + +.Lbytes: + LSETUP (.Lbyte_loop_s , .Lbyte_loop_e) LC0=P2; +.Lbyte_loop_s: + R1 = B[P3++](Z); /* *s2 */ + R0 = B[P0++](Z); /* *s1 */ + CC = R0 == R1; + IF !CC JUMP .Ldifferent; +.Lbyte_loop_e: + NOP; + +.Ldifferent: + R0 = R0 - R1; + P3 = I1; + RTS; + +.Lquad_different: +/* We've read two quads which don't match. + * Can't just compare them, because we're + * a little-endian machine, so the MSBs of + * the regs occur at later addresses in the + * string. + * Arrange to re-read those two quads again, + * byte-by-byte. + */ + P0 += -4; /* back up to the start of the */ + P3 = I0; /* quads, and increase the*/ + P2 += 4; /* remainder count*/ + P3 += -4; + JUMP .Lbytes; + +.Lfinished: + R0 = 0; + P3 = I1; + RTS; diff --git a/lib_blackfin/memcpy.S b/lib_blackfin/memcpy.S new file mode 100644 index 00000000000..a73ff90712e --- /dev/null +++ b/lib_blackfin/memcpy.S @@ -0,0 +1,127 @@ +/* + * File: arch/blackfin/lib/memcpy.S + * Based on: + * Author: + * + * Created: + * Description: internal version of memcpy(), issued by the compiler + * to copy blocks of data around. + * This is really memmove() - it has to be able to deal with + * possible overlaps, because that ambiguity is when the compiler + * gives up and calls a function. We have our own, internal version + * so that we get something we trust, even if the user has redefined + * the normal symbol. + * Rev: $Id: memcpy.S 2775 2007-02-21 13:58:44Z hennerich $ + * + * Modified: + * Copyright 2004-2006 Analog Devices Inc. + * + * Bugs: Enter bugs at http://blackfin.uclinux.org/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see the file COPYING, or write + * to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +.align 2 + +.globl _memcpy_ASM; +_memcpy_ASM: + CC = R2 <= 0; /* length not positive?*/ + IF CC JUMP .L_P1L2147483647; /* Nothing to do */ + + P0 = R0 ; /* dst*/ + P1 = R1 ; /* src*/ + P2 = R2 ; /* length */ + + /* check for overlapping data */ + CC = R1 < R0; /* src < dst */ + IF !CC JUMP .Lno_overlap; + R3 = R1 + R2; + CC = R0 < R3; /* and dst < src+len */ + IF CC JUMP .Lhas_overlap; + +.Lno_overlap: + /* Check for aligned data.*/ + + R3 = R1 | R0; + R0 = 0x3; + R3 = R3 & R0; + CC = R3; /* low bits set on either address? */ + IF CC JUMP .Lnot_aligned; + + /* Both addresses are word-aligned, so we can copy + at least part of the data using word copies.*/ + P2 = P2 >> 2; + CC = P2 <= 2; + IF !CC JUMP .Lmore_than_seven; + /* less than eight bytes... */ + P2 = R2; + LSETUP(.Lthree_start, .Lthree_end) LC0=P2; + R0 = R1; /* setup src address for return */ +.Lthree_start: + R3 = B[P1++] (X); +.Lthree_end: + B[P0++] = R3; + + RTS; + +.Lmore_than_seven: + /* There's at least eight bytes to copy. */ + P2 += -1; /* because we unroll one iteration */ + LSETUP(.Lword_loop, .Lword_loop) LC0=P2; + R0 = R1; + I1 = P1; + R3 = [I1++]; +.Lword_loop: + MNOP || [P0++] = R3 || R3 = [I1++]; + + [P0++] = R3; + /* Any remaining bytes to copy? */ + R3 = 0x3; + R3 = R2 & R3; + CC = R3 == 0; + P1 = I1; /* in case there's something left, */ + IF !CC JUMP .Lbytes_left; + RTS; +.Lbytes_left: P2 = R3; +.Lnot_aligned: + /* From here, we're copying byte-by-byte. */ + LSETUP (.Lbyte_start , .Lbyte_end) LC0=P2; + R0 = R1; /* Save src address for return */ +.Lbyte_start: + R1 = B[P1++] (X); +.Lbyte_end: + B[P0++] = R1; + +.L_P1L2147483647: + RTS; + +.Lhas_overlap: +/* Need to reverse the copying, because the + * dst would clobber the src. + * Don't bother to work out alignment for + * the reverse case. + */ + R0 = R1; /* save src for later. */ + P0 = P0 + P2; + P0 += -1; + P1 = P1 + P2; + P1 += -1; + LSETUP(.Lover_start, .Lover_end) LC0=P2; +.Lover_start: + R1 = B[P1--] (X); +.Lover_end: + B[P0--] = R1; + + RTS; diff --git a/lib_blackfin/memmove.S b/lib_blackfin/memmove.S new file mode 100644 index 00000000000..79558f951e5 --- /dev/null +++ b/lib_blackfin/memmove.S @@ -0,0 +1,102 @@ +/* + * File: arch/blackfin/lib/memmove.S + * Based on: + * Author: + * + * Created: + * Description: + * + * Rev: $Id: memmove.S 2205 2006-09-23 07:53:49Z vapier $ + * + * Modified: + * Copyright 2004-2006 Analog Devices Inc. + * + * Bugs: Enter bugs at http://blackfin.uclinux.org/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see the file COPYING, or write + * to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +.align 2 + +/* + * C Library function MEMMOVE + * R0 = To Address (leave unchanged to form result) + * R1 = From Address + * R2 = count + * Data may overlap + */ + +.globl _memmove; +_memmove: + I1 = P3; + P0 = R0; /* P0 = To address */ + P3 = R1; /* P3 = From Address */ + P2 = R2 ; /* P2 = count */ + CC = P2 == 0; /* Check zero count*/ + IF CC JUMP .Lfinished; /* very unlikely */ + + CC = R1 < R0 (IU); /* From < To */ + IF !CC JUMP .Lno_overlap; + R3 = R1 + R2; + CC = R0 <= R3 (IU); /* (From+len) >= To */ + IF CC JUMP .Loverlap; +.Lno_overlap: + R3 = 11; + CC = R2 <= R3; + IF CC JUMP .Lbytes; + R3 = R1 | R0; /* OR addresses together */ + R3 <<= 30; /* check bottom two bits */ + CC = AZ; /* AZ set if zero.*/ + IF !CC JUMP .Lbytes ; /* Jump if addrs not aligned.*/ + + I0 = P3; + P1 = P2 >> 2; /* count = n/4 */ + P1 += -1; + R3 = 3; + R2 = R2 & R3; /* remainder */ + P2 = R2; /* set remainder */ + R1 = [I0++]; + + LSETUP (.Lquad_loop , .Lquad_loop) LC0=P1; +.Lquad_loop: MNOP || [P0++] = R1 || R1 = [I0++]; + [P0++] = R1; + + CC = P2 == 0; /* any remaining bytes? */ + P3 = I0; /* Ammend P3 to updated ptr. */ + IF !CC JUMP .Lbytes; + P3 = I1; + RTS; + +.Lbytes: LSETUP (.Lbyte2_s , .Lbyte2_e) LC0=P2; +.Lbyte2_s: R1 = B[P3++](Z); +.Lbyte2_e: B[P0++] = R1; + +.Lfinished: P3 = I1; + RTS; + +.Loverlap: + P2 += -1; + P0 = P0 + P2; + P3 = P3 + P2; + R1 = B[P3--] (Z); + CC = P2 == 0; + IF CC JUMP .Lno_loop; + LSETUP (.Lol_s, .Lol_e) LC0 = P2; +.Lol_s: B[P0--] = R1; +.Lol_e: R1 = B[P3--] (Z); +.Lno_loop: B[P0] = R1; + P3 = I1; + RTS; diff --git a/lib_blackfin/memset.S b/lib_blackfin/memset.S new file mode 100644 index 00000000000..7e6ee198eb7 --- /dev/null +++ b/lib_blackfin/memset.S @@ -0,0 +1,103 @@ +/* + * File: arch/blackfin/lib/memset.S + * Based on: + * Author: + * + * Created: + * Description: + * + * Rev: $Id: memset.S 2769 2007-02-19 16:45:53Z hennerich $ + * + * Modified: + * Copyright 2004-2006 Analog Devices Inc. + * + * Bugs: Enter bugs at http://blackfin.uclinux.org/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see the file COPYING, or write + * to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +.align 2 + +/* + * C Library function MEMSET + * R0 = address (leave unchanged to form result) + * R1 = filler byte + * R2 = count + * Favours word aligned data. + */ + +.globl _memset; +_memset: + P0 = R0 ; /* P0 = address */ + P2 = R2 ; /* P2 = count */ + R3 = R0 + R2; /* end */ + CC = R2 <= 7(IU); + IF CC JUMP .Ltoo_small; + R1 = R1.B (Z); /* R1 = fill char */ + R2 = 3; + R2 = R0 & R2; /* addr bottom two bits */ + CC = R2 == 0; /* AZ set if zero. */ + IF !CC JUMP .Lforce_align ; /* Jump if addr not aligned. */ + +.Laligned: + P1 = P2 >> 2; /* count = n/4 */ + R2 = R1 << 8; /* create quad filler */ + R2.L = R2.L + R1.L(NS); + R2.H = R2.L + R1.H(NS); + P2 = R3; + + LSETUP (.Lquad_loop , .Lquad_loop) LC0=P1; +.Lquad_loop: + [P0++] = R2; + + CC = P0 == P2; + IF !CC JUMP .Lbytes_left; + RTS; + +.Lbytes_left: + R2 = R3; /* end point */ + R3 = P0; /* current position */ + R2 = R2 - R3; /* bytes left */ + P2 = R2; + +.Ltoo_small: + CC = P2 == 0; /* Check zero count */ + IF CC JUMP .Lfinished; /* Unusual */ + +.Lbytes: + LSETUP (.Lbyte_loop , .Lbyte_loop) LC0=P2; +.Lbyte_loop: + B[P0++] = R1; + +.Lfinished: + RTS; + +.Lforce_align: + CC = BITTST (R0, 0); /* odd byte */ + R0 = 4; + R0 = R0 - R2; + P1 = R0; + R0 = P0; /* Recover return address */ + IF !CC JUMP .Lskip1; + B[P0++] = R1; +.Lskip1: + CC = R2 <= 2; /* 2 bytes */ + P2 -= P1; /* reduce count */ + IF !CC JUMP .Laligned; + B[P0++] = R1; + B[P0++] = R1; + JUMP .Laligned; diff --git a/lib_blackfin/muldi3.c b/lib_blackfin/muldi3.c index 1fc34e3d932..da55711dd74 100644 --- a/lib_blackfin/muldi3.c +++ b/lib_blackfin/muldi3.c @@ -64,29 +64,29 @@ do { \ __w.ll; }) #endif -typedef unsigned int USItype __attribute__ ((mode (SI))); -typedef int SItype __attribute__ ((mode (SI))); -typedef int DItype __attribute__ ((mode (DI))); -typedef int word_type __attribute__ ((mode (__word__))); +typedef unsigned int USItype __attribute__ ((mode(SI))); +typedef int SItype __attribute__ ((mode(SI))); +typedef int DItype __attribute__ ((mode(DI))); +typedef int word_type __attribute__ ((mode(__word__))); -struct DIstruct {SItype low, high;}; -typedef union -{ +struct DIstruct { + SItype low, high; +}; +typedef union { struct DIstruct s; DItype ll; } DIunion; -DItype __muldi3 (DItype u, DItype v) +DItype __muldi3(DItype u, DItype v) { DIunion w; DIunion uu, vv; - uu.ll = u, - vv.ll = v; + uu.ll = u, vv.ll = v; /* panic("kernel panic for __muldi3"); */ - w.ll = __umulsidi3 (uu.s.low, vv.s.low); + w.ll = __umulsidi3(uu.s.low, vv.s.low); w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high - + (USItype) uu.s.high * (USItype) vv.s.low); + + (USItype) uu.s.high * (USItype) vv.s.low); return w.ll; } diff --git a/lib_blackfin/post.c b/lib_blackfin/post.c new file mode 100644 index 00000000000..0e76026adf1 --- /dev/null +++ b/lib_blackfin/post.c @@ -0,0 +1,435 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <console.h> +#include <watchdog.h> +#include <post.h> + +#ifdef CONFIG_LOGBUFFER +#include <logbuff.h> +#endif + +#ifdef CONFIG_POST + +#define POST_MAX_NUMBER 32 + +#define BOOTMODE_MAGIC 0xDEAD0000 + +int post_init_f(void) +{ + DECLARE_GLOBAL_DATA_PTR; + + int res = 0; + unsigned int i; + + for (i = 0; i < post_list_size; i++) { + struct post_test *test = post_list + i; + + if (test->init_f && test->init_f()) { + res = -1; + } + } + + gd->post_init_f_time = post_time_ms(0); + if (!gd->post_init_f_time) { + printf + ("post/post.c: post_time_ms seems not to be implemented\n"); + } + + return res; +} + +void post_bootmode_init(void) +{ + DECLARE_GLOBAL_DATA_PTR; + int bootmode = post_bootmode_get(0); + int newword; + + if (post_hotkeys_pressed() && !(bootmode & POST_POWERTEST)) { + newword = BOOTMODE_MAGIC | POST_SLOWTEST; + } else if (bootmode == 0) { + newword = BOOTMODE_MAGIC | POST_POWERON; + } else if (bootmode == POST_POWERON || bootmode == POST_SLOWTEST) { + newword = BOOTMODE_MAGIC | POST_NORMAL; + } else { + /* Use old value */ + newword = post_word_load() & ~POST_COLDBOOT; + } + + if (bootmode == 0) { + /* We are booting after power-on */ + newword |= POST_COLDBOOT; + } + + post_word_store(newword); + + /* Reset activity record */ + gd->post_log_word = 0; +} + +int post_bootmode_get(unsigned int *last_test) +{ + unsigned long word = post_word_load(); + int bootmode; + + if ((word & 0xFFFF0000) != BOOTMODE_MAGIC) { + return 0; + } + + bootmode = word & 0x7F; + + if (last_test && (bootmode & POST_POWERTEST)) { + *last_test = (word >> 8) & 0xFF; + } + + return bootmode; +} + +/* POST tests run before relocation only mark status bits .... */ +static void post_log_mark_start(unsigned long testid) +{ + DECLARE_GLOBAL_DATA_PTR; + gd->post_log_word |= (testid) << 16; +} + +static void post_log_mark_succ(unsigned long testid) +{ + DECLARE_GLOBAL_DATA_PTR; + gd->post_log_word |= testid; +} + +/* ... and the messages are output once we are relocated */ +void post_output_backlog(void) +{ + DECLARE_GLOBAL_DATA_PTR; + int j; + + for (j = 0; j < post_list_size; j++) { + if (gd->post_log_word & (post_list[j].testid << 16)) { + post_log("POST %s ", post_list[j].cmd); + if (gd->post_log_word & post_list[j].testid) + post_log("PASSED\n"); + else { + post_log("FAILED\n"); +#ifdef CONFIG_SHOW_BOOT_PROGRESS + show_boot_progress(-31); +#endif + } + } + } +} + +static void post_bootmode_test_on(unsigned int last_test) +{ + unsigned long word = post_word_load(); + + word |= POST_POWERTEST; + + word |= (last_test & 0xFF) << 8; + + post_word_store(word); +} + +static void post_bootmode_test_off(void) +{ + unsigned long word = post_word_load(); + + word &= ~POST_POWERTEST; + + post_word_store(word); +} + +static void post_get_flags(int *test_flags) +{ + int flag[] = { POST_POWERON, POST_NORMAL, POST_SLOWTEST }; + char *var[] = { "post_poweron", "post_normal", "post_slowtest" }; + int varnum = sizeof(var) / sizeof(var[0]); + char list[128]; /* long enough for POST list */ + char *name; + char *s; + int last; + int i, j; + + for (j = 0; j < post_list_size; j++) { + test_flags[j] = post_list[j].flags; + } + + for (i = 0; i < varnum; i++) { + if (getenv_r(var[i], list, sizeof(list)) <= 0) + continue; + + for (j = 0; j < post_list_size; j++) { + test_flags[j] &= ~flag[i]; + } + + last = 0; + name = list; + while (!last) { + while (*name && *name == ' ') + name++; + if (*name == 0) + break; + s = name + 1; + while (*s && *s != ' ') + s++; + if (*s == 0) + last = 1; + else + *s = 0; + + for (j = 0; j < post_list_size; j++) { + if (strcmp(post_list[j].cmd, name) == 0) { + test_flags[j] |= flag[i]; + break; + } + } + + if (j == post_list_size) { + printf("No such test: %s\n", name); + } + + name = s + 1; + } + } + + for (j = 0; j < post_list_size; j++) { + if (test_flags[j] & POST_POWERON) { + test_flags[j] |= POST_SLOWTEST; + } + } +} + +static int post_run_single(struct post_test *test, + int test_flags, int flags, unsigned int i) +{ + if ((flags & test_flags & POST_ALWAYS) && + (flags & test_flags & POST_MEM)) { + WATCHDOG_RESET(); + + if (!(flags & POST_REBOOT)) { + if ((test_flags & POST_REBOOT) + && !(flags & POST_MANUAL)) { + post_bootmode_test_on(i); + } + + if (test_flags & POST_PREREL) + post_log_mark_start(test->testid); + else + post_log("POST %s ", test->cmd); + } + + if (test_flags & POST_PREREL) { + if ((*test->test) (flags) == 0) + post_log_mark_succ(test->testid); + } else { + if ((*test->test) (flags) != 0) { + post_log("FAILED\n"); +#ifdef CONFIG_SHOW_BOOT_PROGRESS + show_boot_progress(-32); +#endif + } else + post_log("PASSED\n"); + } + + if ((test_flags & POST_REBOOT) && !(flags & POST_MANUAL)) { + post_bootmode_test_off(); + } + + return 0; + } else { + return -1; + } +} + +int post_run(char *name, int flags) +{ + unsigned int i; + int test_flags[POST_MAX_NUMBER]; + + post_get_flags(test_flags); + + if (name == NULL) { + unsigned int last; + + if (post_bootmode_get(&last) & POST_POWERTEST) { + if (last < post_list_size && + (flags & test_flags[last] & POST_ALWAYS) && + (flags & test_flags[last] & POST_MEM)) { + + post_run_single(post_list + last, + test_flags[last], + flags | POST_REBOOT, last); + + for (i = last + 1; i < post_list_size; i++) { + post_run_single(post_list + i, + test_flags[i], + flags, i); + } + } + } else { + for (i = 0; i < post_list_size; i++) { + post_run_single(post_list + i, + test_flags[i], flags, i); + } + } + + return 0; + } else { + for (i = 0; i < post_list_size; i++) { + if (strcmp(post_list[i].cmd, name) == 0) + break; + } + + if (i < post_list_size) { + return post_run_single(post_list + i, + test_flags[i], flags, i); + } else { + return -1; + } + } +} + +static int post_info_single(struct post_test *test, int full) +{ + if (test->flags & POST_MANUAL) { + if (full) + printf("%s - %s\n" + " %s\n", test->cmd, test->name, test->desc); + else + printf(" %-15s - %s\n", test->cmd, test->name); + + return 0; + } else { + return -1; + } +} + +int post_info(char *name) +{ + unsigned int i; + + if (name == NULL) { + for (i = 0; i < post_list_size; i++) { + post_info_single(post_list + i, 0); + } + + return 0; + } else { + for (i = 0; i < post_list_size; i++) { + if (strcmp(post_list[i].cmd, name) == 0) + break; + } + + if (i < post_list_size) { + return post_info_single(post_list + i, 1); + } else { + return -1; + } + } +} + +int post_log(char *format, ...) +{ + va_list args; + uint i; + char printbuffer[CFG_PBSIZE]; + + va_start(args, format); + + /* For this to work, printbuffer must be larger than + * anything we ever want to print. + */ + i = vsprintf(printbuffer, format, args); + va_end(args); + +#ifdef CONFIG_LOGBUFFER + /* Send to the logbuffer */ + logbuff_log(printbuffer); +#else + /* Send to the stdout file */ + puts(printbuffer); +#endif + + return 0; +} + +void post_reloc(void) +{ + DECLARE_GLOBAL_DATA_PTR; + + unsigned int i; + + /* + * We have to relocate the test table manually + */ + for (i = 0; i < post_list_size; i++) { + ulong addr; + struct post_test *test = post_list + i; + + if (test->name) { + addr = (ulong) (test->name) + gd->reloc_off; + test->name = (char *)addr; + } + + if (test->cmd) { + addr = (ulong) (test->cmd) + gd->reloc_off; + test->cmd = (char *)addr; + } + + if (test->desc) { + addr = (ulong) (test->desc) + gd->reloc_off; + test->desc = (char *)addr; + } + + if (test->test) { + addr = (ulong) (test->test) + gd->reloc_off; + test->test = (int (*)(int flags))addr; + } + + if (test->init_f) { + addr = (ulong) (test->init_f) + gd->reloc_off; + test->init_f = (int (*)(void))addr; + } + + if (test->reloc) { + addr = (ulong) (test->reloc) + gd->reloc_off; + test->reloc = (void (*)(void))addr; + + test->reloc(); + } + } +} + +/* + * Some tests (e.g. SYSMON) need the time when post_init_f started, + * but we cannot use get_timer() at this point. + * + * On PowerPC we implement it using the timebase register. + */ +unsigned long post_time_ms(unsigned long base) +{ + return (unsigned long)get_ticks() / (get_tbclk() / CFG_HZ) - base; +} + +#endif /* CONFIG_POST */ diff --git a/lib_blackfin/tests.c b/lib_blackfin/tests.c new file mode 100644 index 00000000000..051649d2329 --- /dev/null +++ b/lib_blackfin/tests.c @@ -0,0 +1,253 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * Be sure to mark tests to be run before relocation as such with the + * CFG_POST_PREREL flag so that logging is done correctly if the + * logbuffer support is enabled. + */ + +#include <common.h> +#include <config.h> +#ifdef CONFIG_POST + +#include <post.h> +#define CFG_POST_FLASH 0x00004000 +#define CFG_POST_LED 0x00008000 +#define CFG_POST_BUTTON 0x00010000 + +extern int cache_post_test(int flags); +extern int watchdog_post_test(int flags); +extern int i2c_post_test(int flags); +extern int rtc_post_test(int flags); +extern int memory_post_test(int flags); +extern int cpu_post_test(int flags); +extern int uart_post_test(int flags); +extern int ether_post_test(int flags); +extern int spi_post_test(int flags); +extern int usb_post_test(int flags); +extern int spr_post_test(int flags); +extern int sysmon_post_test(int flags); +extern int dsp_post_test(int flags); +extern int codec_post_test(int flags); + +extern int sysmon_init_f(void); + +extern void sysmon_reloc(void); + +extern int flash_post_test(int flags); +extern int led_post_test(int flags); +extern int button_post_test(int flags); + +struct post_test post_list[] = { +#if CONFIG_POST & CFG_POST_CACHE + { + "Cache test", + "cache", + "This test verifies the CPU cache operation.", + POST_RAM | POST_ALWAYS, + &cache_post_test, + NULL, + NULL, + CFG_POST_CACHE}, +#endif +#if CONFIG_POST & CFG_POST_WATCHDOG + { + "Watchdog timer test", + "watchdog", + "This test checks the watchdog timer.", + POST_RAM | POST_POWERON | POST_SLOWTEST | POST_MANUAL | POST_REBOOT, + &watchdog_post_test, + NULL, + NULL, + CFG_POST_WATCHDOG}, +#endif +#if CONFIG_POST & CFG_POST_I2C + { + "I2C test", + "i2c", + "This test verifies the I2C operation.", + POST_RAM | POST_ALWAYS, + &i2c_post_test, + NULL, + NULL, + CFG_POST_I2C}, +#endif +#if CONFIG_POST & CFG_POST_RTC + { + "RTC test", + "rtc", + "This test verifies the RTC operation.", + POST_RAM | POST_SLOWTEST | POST_MANUAL, + &rtc_post_test, + NULL, + NULL, + CFG_POST_RTC}, +#endif +#if CONFIG_POST & CFG_POST_MEMORY + { + "Memory test", + "memory", + "This test checks RAM.", + POST_ROM | POST_POWERON | POST_SLOWTEST | POST_PREREL, + &memory_post_test, + NULL, + NULL, + CFG_POST_MEMORY}, +#endif +#if CONFIG_POST & CFG_POST_CPU + { + "CPU test", + "cpu", + "This test verifies the arithmetic logic unit of" " CPU.", + POST_RAM | POST_ALWAYS, + &cpu_post_test, + NULL, + NULL, + CFG_POST_CPU}, +#endif +#if CONFIG_POST & CFG_POST_UART + { + "UART test", + "uart", + "This test verifies the UART operation.", + POST_RAM | POST_SLOWTEST | POST_MANUAL, + &uart_post_test, + NULL, + NULL, + CFG_POST_UART}, +#endif +#if CONFIG_POST & CFG_POST_ETHER + { + "ETHERNET test", + "ethernet", + "This test verifies the ETHERNET operation.", + POST_RAM | POST_ALWAYS | POST_MANUAL, + ðer_post_test, + NULL, + NULL, + CFG_POST_ETHER}, +#endif +#if CONFIG_POST & CFG_POST_SPI + { + "SPI test", + "spi", + "This test verifies the SPI operation.", + POST_RAM | POST_ALWAYS | POST_MANUAL, + &spi_post_test, + NULL, + NULL, + CFG_POST_SPI}, +#endif +#if CONFIG_POST & CFG_POST_USB + { + "USB test", + "usb", + "This test verifies the USB operation.", + POST_RAM | POST_ALWAYS | POST_MANUAL, + &usb_post_test, + NULL, + NULL, + CFG_POST_USB}, +#endif +#if CONFIG_POST & CFG_POST_SPR + { + "SPR test", + "spr", + "This test checks SPR contents.", + POST_ROM | POST_ALWAYS | POST_PREREL, + &spr_post_test, + NULL, + NULL, + CFG_POST_SPR}, +#endif +#if CONFIG_POST & CFG_POST_SYSMON + { + "SYSMON test", + "sysmon", + "This test monitors system hardware.", + POST_RAM | POST_ALWAYS, + &sysmon_post_test, + &sysmon_init_f, + &sysmon_reloc, + CFG_POST_SYSMON}, +#endif +#if CONFIG_POST & CFG_POST_DSP + { + "DSP test", + "dsp", + "This test checks any connected DSP(s).", + POST_RAM | POST_MANUAL, + &dsp_post_test, + NULL, + NULL, + CFG_POST_DSP}, +#endif +#if CONFIG_POST & CFG_POST_CODEC + { + "CODEC test", + "codec", + "This test checks any connected codec(s).", + POST_RAM | POST_MANUAL, + &codec_post_test, + NULL, + NULL, + CFG_POST_CODEC}, +#endif +#if CONFIG_POST & CFG_POST_FLASH + { + "FLASH test", + "flash", + "This test checks flash.", + POST_RAM | POST_ALWAYS | POST_MANUAL, + &flash_post_test, + NULL, + NULL, + CFG_POST_FLASH}, +#endif +#if CONFIG_POST & CFG_POST_LED + { + "LED test", + "LED", + "This test checks LED ", + POST_RAM | POST_ALWAYS | POST_MANUAL, + &led_post_test, + NULL, + NULL, + CFG_POST_LED}, +#endif +#if CONFIG_POST & CFG_POST_BUTTON + { + "Button test", + "button", + "This test checks Button ", + POST_RAM | POST_ALWAYS | POST_MANUAL, + &button_post_test, + NULL, + NULL, + CFG_POST_BUTTON}, +#endif + +}; + +unsigned int post_list_size = sizeof(post_list) / sizeof(struct post_test); + +#endif /* CONFIG_POST */ |