summaryrefslogtreecommitdiff
path: root/lib_blackfin
diff options
context:
space:
mode:
Diffstat (limited to 'lib_blackfin')
-rw-r--r--lib_blackfin/Makefile4
-rw-r--r--lib_blackfin/bf533_linux.c35
-rw-r--r--lib_blackfin/bf533_string.c184
-rw-r--r--lib_blackfin/blackfin_board.h2
-rw-r--r--lib_blackfin/board.c238
-rw-r--r--lib_blackfin/cache.c29
-rw-r--r--lib_blackfin/memcmp.S109
-rw-r--r--lib_blackfin/memcpy.S127
-rw-r--r--lib_blackfin/memmove.S102
-rw-r--r--lib_blackfin/memset.S103
-rw-r--r--lib_blackfin/muldi3.c24
-rw-r--r--lib_blackfin/post.c435
-rw-r--r--lib_blackfin/tests.c253
13 files changed, 1481 insertions, 164 deletions
diff --git a/lib_blackfin/Makefile b/lib_blackfin/Makefile
index de7114b..3197fe1 100644
--- a/lib_blackfin/Makefile
+++ b/lib_blackfin/Makefile
@@ -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 88b4da2..1b0d90a 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 c8b1a3a..85b1150 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 31c16a2..e0b96da 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 d9dc2b6..1a0a282 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 847278d..a15914b 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 0000000..fcea5b3
--- /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 0000000..a73ff90
--- /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 0000000..79558f9
--- /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 0000000..7e6ee19
--- /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 1fc34e3..da55711 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 0000000..0e76026
--- /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 0000000..051649d
--- /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,
+ &ether_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 */