diff options
Diffstat (limited to 'lib_blackfin')
| -rw-r--r-- | lib_blackfin/Makefile | 22 | ||||
| -rw-r--r-- | lib_blackfin/bf533_linux.c | 35 | ||||
| -rw-r--r-- | lib_blackfin/bf533_string.c | 183 | ||||
| -rw-r--r-- | lib_blackfin/blackfin_board.h | 2 | ||||
| -rw-r--r-- | lib_blackfin/board.c | 248 | ||||
| -rw-r--r-- | lib_blackfin/cache.c | 29 | ||||
| -rw-r--r-- | lib_blackfin/memcmp.S | 109 | ||||
| -rw-r--r-- | lib_blackfin/memcpy.S | 130 | ||||
| -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, 1501 insertions, 174 deletions
| diff --git a/lib_blackfin/Makefile b/lib_blackfin/Makefile index de7114b80ae..41714736574 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 @@ -27,23 +27,21 @@  include $(TOPDIR)/config.mk -LIB	= $(obj)lib$(ARCH).a +LIB	= lib$(ARCH).a -SOBJS	= +AOBJS	= 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 +OBJS	= $(AOBJS) $(COBJS) -SRCS 	:= $(SOBJS:.o=.S) $(COBJS:.o=.c) -OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS)) - -$(LIB):	$(obj).depend $(OBJS) -	$(AR) $(ARFLAGS) $@ $(OBJS) +$(LIB):	.depend $(OBJS) +	$(AR) cr $@ $(OBJS)  ######################################################################### -# defines $(obj).depend target -include $(SRCTREE)/rules.mk +.depend:	Makefile $(AOBJS:.o=.S) $(COBJS:.o=.c) +		$(CC) -M $(CFLAGS) $(AOBJS:.o=.S) $(COBJS:.o=.c) > $@ -sinclude $(obj).depend +sinclude .depend  ######################################################################### 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..1d0aeb6f7f5 100644 --- a/lib_blackfin/bf533_string.c +++ b/lib_blackfin/bf533_string.c @@ -28,9 +28,14 @@  #include <common.h>  #include <asm/setup.h>  #include <asm/page.h> -#include <asm/cpu/defBF533.h> +#include <config.h> +#include <asm/blackfin.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 +43,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 +61,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 +79,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 +100,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 +126,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); +	__builtin_bfin_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); -		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..7c6a1e93c6d 100644 --- a/lib_blackfin/board.c +++ b/lib_blackfin/board.c @@ -32,21 +32,79 @@  #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 +#ifdef DEBUG +#define pr_debug(fmt,arg...)  printf(fmt,##arg) +#else +static inline int +    __attribute__ ((format(printf, 1, 2))) pr_debug(const char *fmt, ...) +{ +	return 0; +} +#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 +117,7 @@ void *sbrk(ptrdiff_t increment)  	}  	mem_malloc_brk = new; -	return ((void *) old); +	return ((void *)old);  }  static int display_banner(void) @@ -78,17 +136,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 +164,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 +179,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 +259,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 +284,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++) { +		pr_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 +338,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 +362,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 +399,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 +431,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 +450,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..a80fe3dd04a --- /dev/null +++ b/lib_blackfin/memcpy.S @@ -0,0 +1,130 @@ +/* + * 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 */ | 
