diff options
30 files changed, 1861 insertions, 113 deletions
| @@ -214,6 +214,8 @@ LIBS += drivers/sk98lin/libsk98lin.a  LIBS += post/libpost.a post/drivers/libpostdrivers.a  LIBS += $(shell if [ -d post/lib_$(ARCH) ]; then echo \  	"post/lib_$(ARCH)/libpost$(ARCH).a"; fi) +LIBS += $(shell if [ -d post/lib_$(ARCH)/fpu ]; then echo \ +	"post/lib_$(ARCH)/fpu/libpost$(ARCH)fpu.a"; fi)  LIBS += $(shell if [ -d post/cpu/$(CPU) ]; then echo \  	"post/cpu/$(CPU)/libpost$(CPU).a"; fi)  LIBS += $(shell if [ -d post/board/$(BOARDDIR) ]; then echo \ diff --git a/board/amcc/sequoia/sequoia.c b/board/amcc/sequoia/sequoia.c index b43765395..f82311768 100644 --- a/board/amcc/sequoia/sequoia.c +++ b/board/amcc/sequoia/sequoia.c @@ -25,7 +25,6 @@  #include <common.h>  #include <asm/processor.h>  #include <ppc440.h> -#include "sequoia.h"  DECLARE_GLOBAL_DATA_PTR; @@ -226,7 +225,7 @@ int misc_init_r(void)  	if (act == NULL || strcmp(act, "hostdev") == 0)	{  		/* SDR Setting */  		mfsdr(SDR0_PFC1, sdr0_pfc1); -		mfsdr(SDR0_USB0, usb2d0cr); +		mfsdr(SDR0_USB2D0CR, usb2d0cr);  		mfsdr(SDR0_USB2PHY0CR, usb2phy0cr);  		mfsdr(SDR0_USB2H0CR, usb2h0cr); @@ -254,7 +253,7 @@ int misc_init_r(void)  		sdr0_pfc1 = sdr0_pfc1 | SDR0_PFC1_UES_USB2D_SEL;		/*0*/  		mtsdr(SDR0_PFC1, sdr0_pfc1); -		mtsdr(SDR0_USB0, usb2d0cr); +		mtsdr(SDR0_USB2D0CR, usb2d0cr);  		mtsdr(SDR0_USB2PHY0CR, usb2phy0cr);  		mtsdr(SDR0_USB2H0CR, usb2h0cr); @@ -298,7 +297,7 @@ int misc_init_r(void)  		/* SDR Setting */  		mfsdr(SDR0_USB2PHY0CR, usb2phy0cr);  		mfsdr(SDR0_USB2H0CR, usb2h0cr); -		mfsdr(SDR0_USB0, usb2d0cr); +		mfsdr(SDR0_USB2D0CR, usb2d0cr);  		mfsdr(SDR0_PFC1, sdr0_pfc1);  		usb2phy0cr = usb2phy0cr &~SDR0_USB2PHY0CR_XOCLK_MASK; @@ -323,7 +322,7 @@ int misc_init_r(void)  		mtsdr(SDR0_USB2H0CR, usb2h0cr);  		mtsdr(SDR0_USB2PHY0CR, usb2phy0cr); -		mtsdr(SDR0_USB0, usb2d0cr); +		mtsdr(SDR0_USB2D0CR, usb2d0cr);  		mtsdr(SDR0_PFC1, sdr0_pfc1);  		/*clear resets*/ diff --git a/board/amcc/sequoia/sequoia.h b/board/amcc/sequoia/sequoia.h deleted file mode 100644 index 1d44b1646..000000000 --- a/board/amcc/sequoia/sequoia.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * (C) Copyright 2006 - * Stefan Roese, DENX Software Engineering, sr@denx.de. - * - * (C) Copyright 2006 - * Jacqueline Pira-Ferriol, AMCC/IBM, jpira-ferriol@fr.ibm.com - * Alain Saurel,            AMCC/IBM, alain.saurel@fr.ibm.com - * - * 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 - */ - - -/*----------------------------------------------------------------------------+ -  | EBC Configuration Register - EBC0_CFG -  +----------------------------------------------------------------------------*/ -/* External Bus Three-State Control */ -#define EBC0_CFG_EBTC_DRIVEN	    0x80000000 -/* Device-Paced Time-out Disable */ -#define EBC0_CFG_PTD_ENABLED	    0x00000000 -/* Ready Timeout Count */ -#define EBC0_CFG_RTC_MASK	    0x38000000 -#define EBC0_CFG_RTC_16PERCLK	    0x00000000 -#define EBC0_CFG_RTC_32PERCLK	    0x08000000 -#define EBC0_CFG_RTC_64PERCLK	    0x10000000 -#define EBC0_CFG_RTC_128PERCLK	    0x18000000 -#define EBC0_CFG_RTC_256PERCLK	    0x20000000 -#define EBC0_CFG_RTC_512PERCLK	    0x28000000 -#define EBC0_CFG_RTC_1024PERCLK	    0x30000000 -#define EBC0_CFG_RTC_2048PERCLK	    0x38000000 -/* External Master Priority Low */ -#define EBC0_CFG_EMPL_LOW	    0x00000000 -#define EBC0_CFG_EMPL_MEDIUM_LOW    0x02000000 -#define EBC0_CFG_EMPL_MEDIUM_HIGH   0x04000000 -#define EBC0_CFG_EMPL_HIGH	    0x06000000 -/* External Master Priority High */ -#define EBC0_CFG_EMPH_LOW	    0x00000000 -#define EBC0_CFG_EMPH_MEDIUM_LOW    0x00800000 -#define EBC0_CFG_EMPH_MEDIUM_HIGH   0x01000000 -#define EBC0_CFG_EMPH_HIGH	    0x01800000 -/* Chip Select Three-State Control */ -#define EBC0_CFG_CSTC_DRIVEN	    0x00400000 -/* Burst Prefetch */ -#define EBC0_CFG_BPF_ONEDW	    0x00000000 -#define EBC0_CFG_BPF_TWODW	    0x00100000 -#define EBC0_CFG_BPF_FOURDW	    0x00200000 -/* External Master Size */ -#define EBC0_CFG_EMS_8BIT	    0x00000000 -/* Power Management Enable */ -#define EBC0_CFG_PME_DISABLED	    0x00000000 -#define EBC0_CFG_PME_ENABLED	    0x00020000 -/* Power Management Timer */ -#define EBC0_CFG_PMT_ENCODE(n)		((((unsigned long)(n))&0x1F)<<12) - -#define SDR0_USB0                    0x0320     /* USB Control Register */ diff --git a/board/lwmon5/lwmon5.c b/board/lwmon5/lwmon5.c index d5b8f8c81..d91628475 100644 --- a/board/lwmon5/lwmon5.c +++ b/board/lwmon5/lwmon5.c @@ -19,9 +19,10 @@   */  #include <common.h> -#include <asm/processor.h>  #include <ppc440.h> +#include <asm/processor.h>  #include <asm/gpio.h> +#include <asm/io.h>  DECLARE_GLOBAL_DATA_PTR; @@ -220,6 +221,13 @@ int misc_init_r(void)  	udelay(500);  	gpio_write_bit(CFG_GPIO_LIME_RST, 1); +	/* Lime memory clock adjusted to 133MHz */ +	out_be32((void *)CFG_LIME_SDRAM_CLOCK, CFG_LIME_CLOCK_133MHZ); +	/* Wait untill time expired. Because of requirements in lime manual */ +	udelay(300); +	/* Write lime controller memory parameters */ +	out_be32((void *)CFG_LIME_MMR, CFG_LIME_MMR_VALUE); +  	/*  	 * Reset PHY's  	 */ @@ -229,13 +237,6 @@ int misc_init_r(void)  	gpio_write_bit(CFG_GPIO_PHY0_RST, 1);  	gpio_write_bit(CFG_GPIO_PHY1_RST, 1); -	/* -	 * Reset USB hub -	 */ -	gpio_write_bit(CFG_GPIO_HUB_RST, 0); -	udelay(100); -	gpio_write_bit(CFG_GPIO_HUB_RST, 1); -  	return 0;  } diff --git a/board/lwmon5/sdram.c b/board/lwmon5/sdram.c index 85811adad..9a4a8eea8 100644 --- a/board/lwmon5/sdram.c +++ b/board/lwmon5/sdram.c @@ -474,8 +474,27 @@ static void program_ecc(u32 start_address,  		blank_string(strlen(str));  	} else {  		/* ECC bit set method for cached memory */ +#if 1 /* test-only: will remove this define later, when ECC problems are solved! */ +		/* +		 * Some boards (like lwmon5) need to preserve the memory +		 * content upon ECC generation (for the log-buffer). +		 * Therefore we don't fill the memory with a pattern or +		 * just zero it, but write the same values back that are +		 * already in the memory cells. +		 */ +		address_increment = CFG_CACHELINE_SIZE; +		end_address = current_address + num_bytes; + +		current_address = start_address; +		while (current_address < end_address) { +			ppcDcbi(current_address); +			ppcDcbf(current_address); +			current_address += CFG_CACHELINE_SIZE; +		} +#else  		dcbz_area(start_address, num_bytes);  		dflush(); +#endif  	}  	sync(); @@ -518,6 +537,8 @@ long int initdram (int board_type)  {  	u32 val; +#if 0 /* test-only: will remove this define later, when ECC problems are solved! */ +	/* CL=3 */  	mtsdram(DDR0_02, 0x00000000);  	mtsdram(DDR0_00, 0x0000190A); @@ -558,6 +579,49 @@ long int initdram (int board_type)  	mtsdram(DDR0_43, 0x030A0200);  	mtsdram(DDR0_44, 0x00000003);  	mtsdram(DDR0_02, 0x00000001); /* Activate the denali core */ +#else +	/* CL=4 */ +	mtsdram(DDR0_02, 0x00000000); + +	mtsdram(DDR0_00, 0x0000190A); +	mtsdram(DDR0_01, 0x01000000); +	mtsdram(DDR0_03, 0x02040803); /* A suitable burst length was taken. CAS is right for our board */ + +	mtsdram(DDR0_04, 0x0B030300); +	mtsdram(DDR0_05, 0x02020308); +	mtsdram(DDR0_06, 0x0003C812); +	mtsdram(DDR0_07, 0x00090100); +	mtsdram(DDR0_08, 0x03c80001); +	mtsdram(DDR0_09, 0x00011D5F); +	mtsdram(DDR0_10, 0x00000300); +	mtsdram(DDR0_11, 0x000CC800); +	mtsdram(DDR0_12, 0x00000003); +	mtsdram(DDR0_14, 0x00000000); +	mtsdram(DDR0_17, 0x1e000000); +	mtsdram(DDR0_18, 0x1e1e1e1e); +	mtsdram(DDR0_19, 0x1e1e1e1e); +	mtsdram(DDR0_20, 0x0B0B0B0B); +	mtsdram(DDR0_21, 0x0B0B0B0B); +#ifdef CONFIG_DDR_ECC +	mtsdram(DDR0_22, 0x00267F0B | DDR0_22_CTRL_RAW_ECC_ENABLE); /* enable ECC       */ +#else +	mtsdram(DDR0_22, 0x00267F0B); +#endif + +	mtsdram(DDR0_23, 0x01000000); +	mtsdram(DDR0_24, 0x01010001); + +	mtsdram(DDR0_26, 0x2D93028A); +	mtsdram(DDR0_27, 0x0784682B); + +	mtsdram(DDR0_28, 0x00000080); +	mtsdram(DDR0_31, 0x00000000); +	mtsdram(DDR0_42, 0x01000008); + +	mtsdram(DDR0_43, 0x050A0200); +	mtsdram(DDR0_44, 0x00000005); +	mtsdram(DDR0_02, 0x00000001); /* Activate the denali core */ +#endif  	wait_for_dlllock(); diff --git a/cpu/ppc4xx/start.S b/cpu/ppc4xx/start.S index dfe813c3f..6086b6cea 100644 --- a/cpu/ppc4xx/start.S +++ b/cpu/ppc4xx/start.S @@ -1217,15 +1217,23 @@ mck_return:   * NOTE: currently the 440s run with dcache _disabled_ once relocated to DRAM,   * although for some cache-ralated calls stubs have to be provided to satisfy   * symbols resolution. + * Icache-related functions are used in POST framework.   *   */  #ifdef CONFIG_440         .globl  dcache_disable +       .globl  icache_disable	 +       .globl  icache_enable  dcache_disable: +icache_disable: +icache_enable:  	blr  	.globl	dcache_status +	.globl	icache_status  dcache_status: +icache_status: +	mr	r3,  0  	blr  #else  flush_dcache: diff --git a/include/configs/lwmon5.h b/include/configs/lwmon5.h index c6f67fee4..1d87c73c7 100644 --- a/include/configs/lwmon5.h +++ b/include/configs/lwmon5.h @@ -327,12 +327,24 @@  #define CFG_EBC_CFG		0xb8400000  /*----------------------------------------------------------------------- + * Graphics (Fujitsu Lime) + *----------------------------------------------------------------------*/ +/* SDRAM Clock frequency adjustment register */ +#define CFG_LIME_SDRAM_CLOCK	0xC1FC0000 +/* Lime Clock frequency is to set 133MHz */ +#define CFG_LIME_CLOCK_133MHZ	0x10000 + +/* SDRAM Parameter register */ +#define CFG_LIME_MMR		0xC1FCFFFC +/* SDRAM parameter value */ +#define CFG_LIME_MMR_VALUE	0x414FB7F2 + +/*-----------------------------------------------------------------------   * GPIO Setup   *----------------------------------------------------------------------*/  #define CFG_GPIO_PHY1_RST	12  #define CFG_GPIO_FLASH_WP	14  #define CFG_GPIO_PHY0_RST	22 -#define CFG_GPIO_HUB_RST	50  #define CFG_GPIO_WATCHDOG	58  #define CFG_GPIO_LIME_S		59  #define CFG_GPIO_LIME_RST	60 @@ -396,7 +408,7 @@  {GPIO1_BASE, GPIO_IN , GPIO_ALT1, GPIO_OUT_0}, /* GPIO47 UIC_IRQ(8)	DMA_ACK(0)	*/	\  {GPIO1_BASE, GPIO_IN , GPIO_ALT1, GPIO_OUT_0}, /* GPIO48 UIC_IRQ(9)	DMA_EOT/TC(0)	*/	\  {GPIO1_BASE, GPIO_OUT, GPIO_SEL , GPIO_OUT_1}, /* GPIO49  Unselect via TraceSelect Bit	*/	\ -{GPIO1_BASE, GPIO_OUT, GPIO_SEL , GPIO_OUT_0}, /* GPIO50  Unselect via TraceSelect Bit	*/	\ +{GPIO1_BASE, GPIO_IN,  GPIO_SEL , GPIO_OUT_0}, /* GPIO50  Unselect via TraceSelect Bit	*/	\  {GPIO1_BASE, GPIO_IN , GPIO_SEL , GPIO_OUT_0}, /* GPIO51  Unselect via TraceSelect Bit	*/	\  {GPIO1_BASE, GPIO_IN , GPIO_SEL , GPIO_OUT_0}, /* GPIO52  Unselect via TraceSelect Bit	*/	\  {GPIO1_BASE, GPIO_OUT, GPIO_SEL , GPIO_OUT_1}, /* GPIO53  Unselect via TraceSelect Bit	*/	\ diff --git a/include/configs/sequoia.h b/include/configs/sequoia.h index 44bc95551..32199929a 100644 --- a/include/configs/sequoia.h +++ b/include/configs/sequoia.h @@ -334,10 +334,14 @@  				 CFG_POST_CPU	   | \  				 CFG_POST_UART	   | \  				 CFG_POST_I2C	   | \ +				 CFG_POST_CACHE	   | \ +				 CFG_POST_FPU	   | \ +				 CFG_POST_ETHER	   | \  				 CFG_POST_SPR)  #define CFG_POST_WORD_ADDR	(CFG_GBL_DATA_OFFSET - 0x4)  #define CONFIG_LOGBUFFER +#define CFG_POST_CACHE_ADDR	0x10000000 /* free virtual address	*/  #define CFG_CONSOLE_IS_IN_ENV /* Otherwise it catches logbuffer as output */ diff --git a/include/ppc440.h b/include/ppc440.h index 76330f16a..93c10f120 100644 --- a/include/ppc440.h +++ b/include/ppc440.h @@ -282,7 +282,6 @@  #define sdr_sdstp3	0x4003  #endif	/* CONFIG_440GX */ -#ifdef CONFIG_440  /*----------------------------------------------------------------------------+  | Core Configuration/MMU configuration for 440 (CCR1 for 440x5 only).  +----------------------------------------------------------------------------*/ @@ -306,7 +305,6 @@  #define MMUCR_IULXE		0x00400000  #define MMUCR_STS		0x00100000  #define MMUCR_STID_MASK		0x000000FF -#endif /* CONFIG_440 */  #ifdef CONFIG_440SPE  #undef sdr_sdstp2 @@ -1025,7 +1023,7 @@  #endif /* defined(CONFIG_440EP) || defined(CONFIG_440GR) */  #if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) -#define SDR_USB2D0CR                 0x0320 +#define SDR0_USB2D0CR                 0x0320  #define   SDR0_USB2D0CR_USB2DEV_EBC_SEL_MASK   0x00000004    /* USB 2.0 Device/EBC Master Selection */  #define   SDR0_USB2D0CR_USB2DEV_SELECTION      0x00000004    /* USB 2.0 Device Selection */  #define   SDR0_USB2D0CR_EBC_SELECTION          0x00000000    /* EBC Selection */ @@ -1423,7 +1421,7 @@  #define uicvr  uic0vr  #define uicvcr uic0vcr -#if defined(CONFIG_440SPE) +#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX)  /*----------------------------------------------------------------------------+  | Clock / Power-on-reset DCR's.  +----------------------------------------------------------------------------*/ @@ -1492,9 +1490,11 @@  #define CPR0_OPBD_OPBDV0_DECODE(n)	((((((unsigned long)(n))>>24)-1)&0x03)+1)  #define CPR0_PERD			0xE0 +#if !defined(CONFIG_440EPX)  #define CPR0_PERD_PERDV0_MASK		0x03000000  #define CPR0_PERD_PERDV0_ENCODE(n)	((((unsigned long)(n))&0x03)<<24)  #define CPR0_PERD_PERDV0_DECODE(n)	((((((unsigned long)(n))>>24)-1)&0x03)+1) +#endif  #define CPR0_MALD			0x100  #define CPR0_MALD_MALDV0_MASK		0x03000000 diff --git a/post/cpu/mpc8xx/Makefile b/post/cpu/mpc8xx/Makefile index 9dd3f0fce..f871cbab6 100644 --- a/post/cpu/mpc8xx/Makefile +++ b/post/cpu/mpc8xx/Makefile @@ -24,6 +24,6 @@  LIB	= libpostmpc8xx.a  AOBJS	= cache_8xx.o -COBJS	= ether.o spr.o uart.o usb.o watchdog.o +COBJS	= cache.o ether.o spr.o uart.o usb.o watchdog.o  include $(TOPDIR)/post/rules.mk diff --git a/post/drivers/cache.c b/post/cpu/mpc8xx/cache.c index 501465c06..501465c06 100644 --- a/post/drivers/cache.c +++ b/post/cpu/mpc8xx/cache.c diff --git a/post/cpu/ppc4xx/Makefile b/post/cpu/ppc4xx/Makefile index 8e8ab5057..f1034dac2 100644 --- a/post/cpu/ppc4xx/Makefile +++ b/post/cpu/ppc4xx/Makefile @@ -23,6 +23,7 @@  LIB	= libpostppc4xx.a -COBJS	= fpu.o spr.o uart.o watchdog.o +AOBJS   = cache_4xx.o +COBJS	= cache.o ether.o fpu.o spr.o uart.o watchdog.o  include $(TOPDIR)/post/rules.mk diff --git a/post/cpu/ppc4xx/cache.c b/post/cpu/ppc4xx/cache.c new file mode 100644 index 000000000..e1f989ed9 --- /dev/null +++ b/post/cpu/ppc4xx/cache.c @@ -0,0 +1,114 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Igor Lisitsin <igor@emcraft.com> + * + * 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> + +/* Cache test + * + * This test verifies the CPU data and instruction cache using + * several test scenarios. + */ + +#ifdef CONFIG_POST + +#include <post.h> + +#if CONFIG_POST & CFG_POST_CACHE + +#include <asm/mmu.h> +#include <watchdog.h> + +#define CACHE_POST_SIZE	1024 + +void program_tlb(u32 phys_addr, u32 virt_addr, u32 size, u32 tlb_word2_i_value); + +int cache_post_test1 (int tlb, void *p, int size); +int cache_post_test2 (int tlb, void *p, int size); +int cache_post_test3 (int tlb, void *p, int size); +int cache_post_test4 (int tlb, void *p, int size); +int cache_post_test5 (int tlb, void *p, int size); +int cache_post_test6 (int tlb, void *p, int size); + +static int tlb = -1;		/* index to the victim TLB entry */ + +static unsigned char testarea[CACHE_POST_SIZE] +__attribute__((__aligned__(CACHE_POST_SIZE))); + +int cache_post_test (int flags) +{ +	void* virt = (void*)CFG_POST_CACHE_ADDR; +	int ints, i, res = 0; +	u32 word0; + +	if (tlb < 0) { +		/* +		 * Allocate a new TLB entry, since we are going to modify +		 * the write-through and caching inhibited storage attributes. +		 */ +		program_tlb((u32)testarea, (u32)virt, +			    CACHE_POST_SIZE, TLB_WORD2_I_ENABLE); + +		/* Find the TLB entry */ +		for (i = 0;; i++) { +			if (i >= PPC4XX_TLB_SIZE) { +				printf ("Failed to program tlb entry\n"); +				return -1; +			} +			word0 = mftlb1(i); +			if (TLB_WORD0_EPN_DECODE(word0) == (u32)virt) { +				tlb = i; +				break; +			} +		} +	} +	ints = disable_interrupts (); + +	WATCHDOG_RESET (); +	if (res == 0) +		res = cache_post_test1 (tlb, virt, CACHE_POST_SIZE); +	WATCHDOG_RESET (); +	if (res == 0) +		res = cache_post_test2 (tlb, virt, CACHE_POST_SIZE); +	WATCHDOG_RESET (); +	if (res == 0) +		res = cache_post_test3 (tlb, virt, CACHE_POST_SIZE); +	WATCHDOG_RESET (); +	if (res == 0) +		res = cache_post_test4 (tlb, virt, CACHE_POST_SIZE); +	WATCHDOG_RESET (); +	if (res == 0) +		res = cache_post_test5 (tlb, virt, CACHE_POST_SIZE); +	WATCHDOG_RESET (); +	if (res == 0) +		res = cache_post_test6 (tlb, virt, CACHE_POST_SIZE); + +	if (ints) +		enable_interrupts (); + +	return res; +} + +#endif /* CONFIG_POST & CFG_POST_CACHE */ +#endif /* CONFIG_POST */ diff --git a/post/cpu/ppc4xx/cache_4xx.S b/post/cpu/ppc4xx/cache_4xx.S new file mode 100644 index 000000000..785b8d60b --- /dev/null +++ b/post/cpu/ppc4xx/cache_4xx.S @@ -0,0 +1,448 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Igor Lisitsin <igor@emcraft.com> + * + * 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 <config.h> + +#ifdef CONFIG_POST + +#include <post.h> +#include <ppc_asm.tmpl> +#include <ppc_defs.h> +#include <asm/cache.h> +#include <asm/mmu.h> + +#if CONFIG_POST & CFG_POST_CACHE + +	.text + +/* void cache_post_disable (int tlb) + */ +cache_post_disable: +	tlbre	r0, r3, 0x0002 +	ori	r0, r0, TLB_WORD2_I_ENABLE@l +	tlbwe	r0, r3, 0x0002 +	sync +	isync +	blr + +/* void cache_post_wt (int tlb) + */ +cache_post_wt: +	tlbre	r0, r3, 0x0002 +	ori	r0, r0, TLB_WORD2_W_ENABLE@l +	andi.	r0, r0, ~TLB_WORD2_I_ENABLE@l +	tlbwe	r0, r3, 0x0002 +	sync +	isync +	blr + +/* void cache_post_wb (int tlb) + */ +cache_post_wb: +	tlbre	r0, r3, 0x0002 +	andi.	r0, r0, ~TLB_WORD2_W_ENABLE@l +	andi.	r0, r0, ~TLB_WORD2_I_ENABLE@l +	tlbwe	r0, r3, 0x0002 +	sync +	isync +	blr + +/* void cache_post_dinvalidate (void *p, int size) + */ +cache_post_dinvalidate: +	dcbi	r0, r3 +	addi	r3, r3, CFG_CACHELINE_SIZE +	subic.	r4, r4, CFG_CACHELINE_SIZE +	bgt	cache_post_dinvalidate +	sync +	blr + +/* void cache_post_dstore (void *p, int size) + */ +cache_post_dstore: +	dcbst	r0, r3 +	addi	r3, r3, CFG_CACHELINE_SIZE +	subic.	r4, r4, CFG_CACHELINE_SIZE +	bgt	cache_post_dstore +	sync +	blr + +/* void cache_post_dtouch (void *p, int size) + */ +cache_post_dtouch: +	dcbt	r0, r3 +	addi	r3, r3, CFG_CACHELINE_SIZE +	subic.	r4, r4, CFG_CACHELINE_SIZE +	bgt	cache_post_dtouch +	sync +	blr + +/* void cache_post_iinvalidate (void) + */ +cache_post_iinvalidate: +	iccci	r0, r0 +	sync +	blr + +/* void cache_post_memset (void *p, int val, int size) + */ +cache_post_memset: +	mtctr	r5 +1: +	stb	r4, 0(r3) +	addi	r3, r3, 1 +	bdnz	1b +	blr + +/* int cache_post_check (void *p, int size) + */ +cache_post_check: +	mtctr	r4 +1: +	lbz	r0, 0(r3) +	addi	r3, r3, 1 +	cmpwi	r0, 0xff +	bne	2f +	bdnz	1b +	li	r3, 0 +	blr +2: +	li	r3, -1 +	blr + +#define CACHE_POST_DISABLE()		\ +	mr	r3, r10;		\ +	bl	cache_post_disable + +#define CACHE_POST_WT()			\ +	mr	r3, r10;		\ +	bl	cache_post_wt + +#define CACHE_POST_WB()			\ +	mr	r3, r10;		\ +	bl	cache_post_wb + +#define CACHE_POST_DINVALIDATE()	\ +	mr	r3, r11;		\ +	mr	r4, r12;		\ +	bl	cache_post_dinvalidate + +#define CACHE_POST_DFLUSH()		\ +	mr	r3, r11;		\ +	mr	r4, r12;		\ +	bl	cache_post_dflush + +#define CACHE_POST_DSTORE()		\ +	mr	r3, r11;		\ +	mr	r4, r12;		\ +	bl	cache_post_dstore + +#define CACHE_POST_DTOUCH()		\ +	mr	r3, r11;		\ +	mr	r4, r12;		\ +	bl	cache_post_dtouch + +#define CACHE_POST_IINVALIDATE()	\ +	bl	cache_post_iinvalidate + +#define CACHE_POST_MEMSET(val)		\ +	mr	r3, r11;		\ +	li	r4, val;		\ +	mr	r5, r12;		\ +	bl	cache_post_memset + +#define CACHE_POST_CHECK()		\ +	mr	r3, r11;		\ +	mr	r4, r12;		\ +	bl	cache_post_check;	\ +	mr	r13, r3 + +/* + * Write and read 0xff pattern with caching enabled. + */ +	.global cache_post_test1 +cache_post_test1: +	mflr	r9 +	mr	r10, r3		/* tlb		*/ +	mr	r11, r4		/* p		*/ +	mr	r12, r5		/* size		*/ + +	CACHE_POST_WB() +	CACHE_POST_DINVALIDATE() + +	/* Write the negative pattern to the test area */ +	CACHE_POST_MEMSET(0xff) + +	/* Read the test area */ +	CACHE_POST_CHECK() + +	CACHE_POST_DINVALIDATE() +	CACHE_POST_DISABLE() + +	mr	r3, r13 +	mtlr	r9 +	blr + +/* + * Write zeroes with caching enabled. + * Write 0xff pattern with caching disabled. + * Read 0xff pattern with caching enabled. + */ +	.global cache_post_test2 +cache_post_test2: +	mflr	r9 +	mr	r10, r3		/* tlb		*/ +	mr	r11, r4		/* p		*/ +	mr	r12, r5		/* size		*/ + +	CACHE_POST_WB() +	CACHE_POST_DINVALIDATE() + +	/* Write the zero pattern to the test area */ +	CACHE_POST_MEMSET(0) + +	CACHE_POST_DINVALIDATE() +	CACHE_POST_DISABLE() + +	/* Write the negative pattern to the test area */ +	CACHE_POST_MEMSET(0xff) + +	CACHE_POST_WB() + +	/* Read the test area */ +	CACHE_POST_CHECK() + +	CACHE_POST_DINVALIDATE() +	CACHE_POST_DISABLE() + +	mr	r3, r13 +	mtlr	r9 +	blr + +/* + * Write-through mode test. + * Write zeroes, store the cache, write 0xff pattern. + * Invalidate the cache. + * Check that 0xff pattern is read. + */ +	.global cache_post_test3 +cache_post_test3: +	mflr	r9 +	mr	r10, r3		/* tlb		*/ +	mr	r11, r4		/* p		*/ +	mr	r12, r5		/* size		*/ + +	CACHE_POST_WT() +	CACHE_POST_DINVALIDATE() + +	/* Cache the test area */ +	CACHE_POST_DTOUCH() + +	/* Write the zero pattern to the test area */ +	CACHE_POST_MEMSET(0) + +	CACHE_POST_DSTORE() + +	/* Write the negative pattern to the test area */ +	CACHE_POST_MEMSET(0xff) + +	CACHE_POST_DINVALIDATE() +	CACHE_POST_DISABLE() + +	/* Read the test area */ +	CACHE_POST_CHECK() + +	mr	r3, r13 +	mtlr	r9 +	blr + +/* + * Write-back mode test. + * Write 0xff pattern, store the cache, write zeroes. + * Invalidate the cache. + * Check that 0xff pattern is read. + */ +	.global cache_post_test4 +cache_post_test4: +	mflr	r9 +	mr	r10, r3		/* tlb		*/ +	mr	r11, r4		/* p		*/ +	mr	r12, r5		/* size		*/ + +	CACHE_POST_WB() +	CACHE_POST_DINVALIDATE() + +	/* Cache the test area */ +	CACHE_POST_DTOUCH() + +	/* Write the negative pattern to the test area */ +	CACHE_POST_MEMSET(0xff) + +	CACHE_POST_DSTORE() + +	/* Write the zero pattern to the test area */ +	CACHE_POST_MEMSET(0) + +	CACHE_POST_DINVALIDATE() +	CACHE_POST_DISABLE() + +	/* Read the test area */ +	CACHE_POST_CHECK() + +	mr	r3, r13 +	mtlr	r9 +	blr + +/* + * Load the test instructions into the instruction cache. + * Replace the test instructions. + * Check that the original instructions are executed. + */ +	.global cache_post_test5 +cache_post_test5: +	mflr	r9 +	mr	r10, r3		/* tlb		*/ +	mr	r11, r4		/* p		*/ +	mr	r12, r5		/* size		*/ + +	CACHE_POST_WT() +	CACHE_POST_IINVALIDATE() + +	/* Compute r13 = cache_post_test_inst */ +	bl	cache_post_test5_reloc +cache_post_test5_reloc: +	mflr	r13 +	lis	r0, (cache_post_test_inst - cache_post_test5_reloc)@h +	ori	r0, r0, (cache_post_test_inst - cache_post_test5_reloc)@l +	add	r13, r13, r0 + +	/* Copy the test instructions to the test area */ +	lwz	r0, 0(r13) +	stw	r0, 0(r11) +	lwz	r0, 8(r13) +	stw	r0, 4(r11) +	sync + +	/* Invalidate the cache line */ +	icbi	r0, r11 +	sync +	isync + +	/* Execute the test instructions */ +	mtlr	r11 +	blrl + +	/* Replace the test instruction */ +	lwz	r0, 4(r13) +	stw	r0, 0(r11) +	sync + +	/* Do not invalidate the cache line */ +	isync + +	/* Execute the test instructions */ +	mtlr	r11 +	blrl +	mr	r13, r3 + +	CACHE_POST_IINVALIDATE() +	CACHE_POST_DINVALIDATE() +	CACHE_POST_DISABLE() + +	mr	r3, r13 +	mtlr	r9 +	blr + +/* + * Load the test instructions into the instruction cache. + * Replace the test instructions and invalidate the cache. + * Check that the replaced instructions are executed. + */ +	.global cache_post_test6 +cache_post_test6: +	mflr	r9 +	mr	r10, r3		/* tlb		*/ +	mr	r11, r4		/* p		*/ +	mr	r12, r5		/* size		*/ + +	CACHE_POST_WT() +	CACHE_POST_IINVALIDATE() + +	/* Compute r13 = cache_post_test_inst */ +	bl	cache_post_test6_reloc +cache_post_test6_reloc: +	mflr	r13 +	lis	r0, (cache_post_test_inst - cache_post_test6_reloc)@h +	ori	r0, r0, (cache_post_test_inst - cache_post_test6_reloc)@l +	add	r13, r13, r0 + +	/* Copy the test instructions to the test area */ +	lwz	r0, 4(r13) +	stw	r0, 0(r11) +	lwz	r0, 8(r13) +	stw	r0, 4(r11) +	sync + +	/* Invalidate the cache line */ +	icbi	r0, r11 +	sync +	isync + +	/* Execute the test instructions */ +	mtlr	r11 +	blrl + +	/* Replace the test instruction */ +	lwz	r0, 0(r13) +	stw	r0, 0(r11) +	sync + +	/* Invalidate the cache line */ +	icbi	r0, r11 +	sync +	isync + +	/* Execute the test instructions */ +	mtlr	r11 +	blrl +	mr	r13, r3 + +	CACHE_POST_IINVALIDATE() +	CACHE_POST_DINVALIDATE() +	CACHE_POST_DISABLE() + +	mr	r3, r13 +	mtlr	r9 +	blr + +/* Test instructions. + */	 +cache_post_test_inst: +	li	r3, 0 +	li	r3, -1 +	blr + +#endif /* CONFIG_POST & CFG_POST_CACHE */ +#endif /* CONFIG_POST */ diff --git a/post/cpu/ppc4xx/ether.c b/post/cpu/ppc4xx/ether.c new file mode 100644 index 000000000..391c815d7 --- /dev/null +++ b/post/cpu/ppc4xx/ether.c @@ -0,0 +1,395 @@ +/* + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Igor Lisitsin <igor@emcraft.com> + * + * 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> + +/* + * Ethernet test + * + * The Ethernet Media Access Controllers (EMAC) are tested in the + * internal loopback mode. + * The controllers are configured accordingly and several packets + * are transmitted. The configurable test parameters are: + *   MIN_PACKET_LENGTH - minimum size of packet to transmit + *   MAX_PACKET_LENGTH - maximum size of packet to transmit + *   TEST_NUM - number of tests + */ + +#ifdef CONFIG_POST + +#include <post.h> + +#if CONFIG_POST & CFG_POST_ETHER + +#include <asm/cache.h> +#include <asm/io.h> +#include <asm/processor.h> +#include <405_mal.h> +#include <ppc4xx_enet.h> +#include <malloc.h> + +DECLARE_GLOBAL_DATA_PTR; + +#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) +#define SDR0_MFR_ETH_CLK_SEL_V(n)	((0x01<<27) / (n+1)) +#endif + +#define MIN_PACKET_LENGTH	64 +#define MAX_PACKET_LENGTH	256 +#define TEST_NUM		1 + +static volatile mal_desc_t tx __cacheline_aligned; +static volatile mal_desc_t rx __cacheline_aligned; +static char *tx_buf; +static char *rx_buf; + +static void ether_post_init (int devnum, int hw_addr) +{ +	int i; +	unsigned mode_reg; +#if defined(CONFIG_440GX) || \ +    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ +    defined(CONFIG_440SP) || defined(CONFIG_440SPE) +	sys_info_t sysinfo; +#endif +#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || defined(CONFIG_440SPE) +	unsigned long mfr; +#endif + +#if defined(CONFIG_440GX) || \ +    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ +    defined(CONFIG_440SP) || defined(CONFIG_440SPE) +	/* Need to get the OPB frequency so we can access the PHY */ +	get_sys_info (&sysinfo); +#endif + +#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) +	/* provide clocks for EMAC internal loopback  */ +	mfsdr (sdr_mfr, mfr); +	mfr |= SDR0_MFR_ETH_CLK_SEL_V(devnum); +	mtsdr (sdr_mfr, mfr); +	sync (); +#endif +	/* reset emac */ +	out32 (EMAC_M0 + hw_addr, EMAC_M0_SRST); +	sync (); + +	for (i = 0;; i++) { +		if (!(in32 (EMAC_M0 + hw_addr) & EMAC_M0_SRST)) +			break; +		if (i >= 1000) { +			printf ("Timeout resetting EMAC\n"); +			break; +		} +		udelay (1000); +	} +#if defined(CONFIG_440GX) || \ +    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ +    defined(CONFIG_440SP) || defined(CONFIG_440SPE) +	/* Whack the M1 register */ +	mode_reg = 0x0; +	if (sysinfo.freqOPB <= 50000000); +	else if (sysinfo.freqOPB <= 66666667) +		mode_reg |= EMAC_M1_OBCI_66; +	else if (sysinfo.freqOPB <= 83333333) +		mode_reg |= EMAC_M1_OBCI_83; +	else if (sysinfo.freqOPB <= 100000000) +		mode_reg |= EMAC_M1_OBCI_100; +	else +		mode_reg |= EMAC_M1_OBCI_GT100; + +	out32 (EMAC_M1 + hw_addr, mode_reg); + +#endif /* defined(CONFIG_440GX) || defined(CONFIG_440SP) */ + +	/* set the Mal configuration reg */ +#if defined(CONFIG_440GX) || \ +    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ +    defined(CONFIG_440SP) || defined(CONFIG_440SPE) +	mtdcr (malmcr, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA | +	       MAL_CR_PLBLT_DEFAULT | 0x00330000); +#else +	mtdcr (malmcr, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA | MAL_CR_PLBLT_DEFAULT); +	/* Errata 1.12: MAL_1 -- Disable MAL bursting */ +	if (get_pvr() == PVR_440GP_RB) { +		mtdcr (malmcr, mfdcr(malmcr) & ~MAL_CR_PLBB); +	} +#endif +	/* setup buffer descriptors */ +	tx.ctrl = MAL_TX_CTRL_WRAP; +	tx.data_len = 0; +	tx.data_ptr = (char*)L1_CACHE_ALIGN((u32)tx_buf); + +	rx.ctrl = MAL_TX_CTRL_WRAP | MAL_RX_CTRL_EMPTY; +	rx.data_len = 0; +	rx.data_ptr = (char*)L1_CACHE_ALIGN((u32)rx_buf); + +	switch (devnum) { +	case 1: +		/* setup MAL tx & rx channel pointers */ +#if defined (CONFIG_405EP) || defined (CONFIG_440EP) || defined (CONFIG_440GR) +		mtdcr (maltxctp2r, &tx); +#else +		mtdcr (maltxctp1r, &tx); +#endif +#if defined(CONFIG_440) +		mtdcr (maltxbattr, 0x0); +		mtdcr (malrxbattr, 0x0); +#endif +		mtdcr (malrxctp1r, &rx); +		/* set RX buffer size */ +		mtdcr (malrcbs1, PKTSIZE_ALIGN / 16); +		break; +	case 0: +	default: +		/* setup MAL tx & rx channel pointers */ +#if defined(CONFIG_440) +		mtdcr (maltxbattr, 0x0); +		mtdcr (malrxbattr, 0x0); +#endif +		mtdcr (maltxctp0r, &tx); +		mtdcr (malrxctp0r, &rx); +		/* set RX buffer size */ +		mtdcr (malrcbs0, PKTSIZE_ALIGN / 16); +		break; +	} + +	/* Enable MAL transmit and receive channels */ +#if defined(CONFIG_405EP) || defined(CONFIG_440EP) || defined(CONFIG_440GR) +	mtdcr (maltxcasr, (MAL_TXRX_CASR >> (devnum*2))); +#else +	mtdcr (maltxcasr, (MAL_TXRX_CASR >> devnum)); +#endif +	mtdcr (malrxcasr, (MAL_TXRX_CASR >> devnum)); + +	/* set internal loopback mode */ +	out32 (EMAC_M1 + hw_addr, EMAC_M1_FDE | EMAC_M1_ILE | +	       EMAC_M1_RFS_4K | EMAC_M1_TX_FIFO_2K | +	       EMAC_M1_MF_100MBPS | EMAC_M1_IST | +	       in32 (EMAC_M1)); + +	/* set transmit enable & receive enable */ +	out32 (EMAC_M0 + hw_addr, EMAC_M0_TXE | EMAC_M0_RXE); + +	/* enable broadcast address */ +	out32 (EMAC_RXM + hw_addr, EMAC_RMR_BAE); + +	/* set transmit request threshold register */ +	out32 (EMAC_TRTR + hw_addr, 0x18000000);	/* 256 byte threshold */ + +	/* set receive	low/high water mark register */ +#if defined(CONFIG_440) +	/* 440s has a 64 byte burst length */ +	out32 (EMAC_RX_HI_LO_WMARK + hw_addr, 0x80009000); +#else +	/* 405s have a 16 byte burst length */ +	out32 (EMAC_RX_HI_LO_WMARK + hw_addr, 0x0f002000); +#endif /* defined(CONFIG_440) */ +	out32 (EMAC_TXM1 + hw_addr, 0xf8640000); + +	/* Set fifo limit entry in tx mode 0 */ +	out32 (EMAC_TXM0 + hw_addr, 0x00000003); +	/* Frame gap set */ +	out32 (EMAC_I_FRAME_GAP_REG + hw_addr, 0x00000008); +	sync (); +} + +static void ether_post_halt (int devnum, int hw_addr) +{ +	int i = 0; +#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) +	unsigned long mfr; +#endif + +	/* 1st reset MAL channel */ +	/* Note: writing a 0 to a channel has no effect */ +#if defined(CONFIG_405EP) || defined(CONFIG_440EP) || defined(CONFIG_440GR) +	mtdcr (maltxcarr, MAL_TXRX_CASR >> (devnum * 2)); +#else +	mtdcr (maltxcarr, MAL_TXRX_CASR >> devnum); +#endif +	mtdcr (malrxcarr, MAL_TXRX_CASR >> devnum); + +	/* wait for reset */ +	while (mfdcr (malrxcasr) & (MAL_TXRX_CASR >> devnum)) { +		if (i++ >= 1000) +			break; +		udelay (1000); +	} +	/* emac reset */ +	out32 (EMAC_M0 + hw_addr, EMAC_M0_SRST); + +#if defined(CONFIG_440SPE) || defined(CONFIG_440EPX) || defined(CONFIG_440GRX) +	/* remove clocks for EMAC internal loopback  */ +	mfsdr (sdr_mfr, mfr); +	mfr &= ~SDR0_MFR_ETH_CLK_SEL_V(devnum); +	mtsdr (sdr_mfr, mfr); +#endif +} + +static void ether_post_send (int devnum, int hw_addr, void *packet, int length) +{ +	int i = 0; + +	while (tx.ctrl & MAL_TX_CTRL_READY) { +		if (i++ > 100) { +			printf ("TX timeout\n"); +			return; +		} +		udelay (1000); +	} +	tx.ctrl = MAL_TX_CTRL_READY | MAL_TX_CTRL_WRAP | MAL_TX_CTRL_LAST | +		EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP; +	tx.data_len = length; +	memcpy (tx.data_ptr, packet, length); +	sync (); + +	out32 (EMAC_TXM0 + hw_addr, in32 (EMAC_TXM0 + hw_addr) | EMAC_TXM0_GNP0); +	sync (); +} + +static int ether_post_recv (int devnum, int hw_addr, void *packet, int max_length) +{ +	int length; +	int i = 0; + +	while (rx.ctrl & MAL_RX_CTRL_EMPTY) { +		if (i++ > 100) { +			printf ("RX timeout\n"); +			return 0; +		} +		udelay (1000); +	} +	length = rx.data_len - 4; +	if (length <= max_length) +		memcpy(packet, rx.data_ptr, length); +	sync (); + +	rx.ctrl |= MAL_RX_CTRL_EMPTY; +	sync (); + +	return length; +} + +  /* +   * Test routines +   */ + +static void packet_fill (char *packet, int length) +{ +	char c = (char) length; +	int i; + +	/* set up ethernet header */ +	memset (packet, 0xff, 14); + +	for (i = 14; i < length; i++) { +		packet[i] = c++; +	} +} + +static int packet_check (char *packet, int length) +{ +	char c = (char) length; +	int i; + +	for (i = 14; i < length; i++) { +		if (packet[i] != c++) +			return -1; +	} + +	return 0; +} + +static int test_ctlr (int devnum, int hw_addr) +{ +	int res = -1; +	char packet_send[MAX_PACKET_LENGTH]; +	char packet_recv[MAX_PACKET_LENGTH]; +	int length; +	int i; +	int l; + +	ether_post_init (devnum, hw_addr); + +	for (i = 0; i < TEST_NUM; i++) { +		for (l = MIN_PACKET_LENGTH; l <= MAX_PACKET_LENGTH; l++) { +			packet_fill (packet_send, l); + +			ether_post_send (devnum, hw_addr, packet_send, l); + +			length = ether_post_recv (devnum, hw_addr, packet_recv, +						  sizeof (packet_recv)); + +			if (length != l || packet_check (packet_recv, length) < 0) { +				goto Done; +			} +		} +	} + +	res = 0; + +Done: + +	ether_post_halt (devnum, hw_addr); + +	if (res != 0) { +		post_log ("EMAC%d test failed\n", devnum); +	} + +	return res; +} + +int ether_post_test (int flags) +{ +	int res = 0; + +	/* Allocate tx & rx packet buffers */ +	tx_buf = malloc (PKTSIZE_ALIGN + CFG_CACHELINE_SIZE); +	rx_buf = malloc (PKTSIZE_ALIGN + CFG_CACHELINE_SIZE); + +	if (!tx_buf || !rx_buf) { +		printf ("Failed to allocate packet buffers\n"); +		res = -1; +		goto out_free; +	} + +	/* EMAC0 */ +	if (test_ctlr (0, 0)) +		res = -1; + +	/* EMAC1 */ +	if (test_ctlr (1, 0x100)) +		res = -1; + +out_free: +	free (tx_buf); +	free (rx_buf); + +	return res; +} + +#endif /* CONFIG_POST & CFG_POST_ETHER */ +#endif /* CONFIG_POST */ diff --git a/post/cpu/ppc4xx/fpu.c b/post/cpu/ppc4xx/fpu.c index 1935c011b..c2eb4a9bf 100644 --- a/post/cpu/ppc4xx/fpu.c +++ b/post/cpu/ppc4xx/fpu.c @@ -1,5 +1,8 @@  /* - *  Copyright (C) 2007 Wolfgang Denk <wd@denx.de> + * (C) Copyright 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Sergei Poselenov <sposelenov@emcraft.com>   *   * See file CREDITS for list of people who contributed to this   * project. @@ -34,7 +37,7 @@ int fpu_status(void)  {  	if (mfspr(ccr0) & CCR0_DAPUIB)  		return 0; /* Disabled */ -	else +	else   		return 1; /* Enabled */  } @@ -51,5 +54,6 @@ void fpu_enable(void)  	mtspr(ccr0, mfspr(ccr0) & ~CCR0_DAPUIB);  	mtmsr(mfmsr() | MSR_FP);  } +  #endif -#endif +#endif /* CONFIG_POST */ diff --git a/post/cpu/ppc4xx/spr.c b/post/cpu/ppc4xx/spr.c index f62526a17..be5a701f3 100644 --- a/post/cpu/ppc4xx/spr.c +++ b/post/cpu/ppc4xx/spr.c @@ -2,6 +2,8 @@   * (C) Copyright 2007   * Wolfgang Denk, DENX Software Engineering, wd@denx.de.   * + * Author: Igor Lisitsin <igor@emcraft.com> + *   * See file CREDITS for list of people who contributed to this   * project.   * @@ -39,6 +41,8 @@  #if CONFIG_POST & CFG_POST_SPR +#include <asm/processor.h> +  static struct  {      int number; @@ -60,8 +64,10 @@ static struct  	{0x113,	"SPRG3",	0x00000000,	0x00000000},  	{0x11f,	"PVR",		0x00000000,	0x00000000}, -	/* Additional Special-Purpose Registers */ - +	/* Additional Special-Purpose Registers. +	 * The values must match the initialization  +	 * values from cpu/ppc4xx/start.S +	 */  	{0x30,	"PID",		0x00000000,	0x00000000},  	{0x3a,	"CSRR0",	0x00000000,	0x00000000},  	{0x3b,	"CSRR1",	0x00000000,	0x00000000}, @@ -90,22 +96,22 @@ static struct  	{0x13f,	"DVC2",		0x00000000,	0x00000000},  	{0x150,	"TSR",		0x00000000,	0x00000000},  	{0x154,	"TCR",		0x00000000,	0x00000000}, -	{0x190,	"IVOR0",	0x00000000,	0x00000000}, -	{0x191,	"IVOR1",	0x00000000,	0x00000000}, -	{0x192,	"IVOR2",	0x00000000,	0x00000000}, -	{0x193,	"IVOR3",	0x00000000,	0x00000000}, -	{0x194,	"IVOR4",	0x00000000,	0x00000000}, -	{0x195,	"IVOR5",	0x00000000,	0x00000000}, -	{0x196,	"IVOR6",	0x00000000,	0x00000000}, -	{0x197,	"IVOR7",	0x00000000,	0x00000000}, -	{0x198,	"IVOR8",	0x00000000,	0x00000000}, +	{0x190,	"IVOR0",	0x0000fff0,	0x00000100}, +	{0x191,	"IVOR1",	0x0000fff0,	0x00000200}, +	{0x192,	"IVOR2",	0x0000fff0,	0x00000300}, +	{0x193,	"IVOR3",	0x0000fff0,	0x00000400}, +	{0x194,	"IVOR4",	0x0000fff0,	0x00000500}, +	{0x195,	"IVOR5",	0x0000fff0,	0x00000600}, +	{0x196,	"IVOR6",	0x0000fff0,	0x00000700}, +	{0x197,	"IVOR7",	0x0000fff0,	0x00000800}, +	{0x198,	"IVOR8",	0x0000fff0,	0x00000c00},  	{0x199,	"IVOR9",	0x00000000,	0x00000000}, -	{0x19a,	"IVOR10",	0x00000000,	0x00000000}, +	{0x19a,	"IVOR10",	0x0000fff0,	0x00000900},  	{0x19b,	"IVOR11",	0x00000000,	0x00000000},  	{0x19c,	"IVOR12",	0x00000000,	0x00000000}, -	{0x19d,	"IVOR13",	0x00000000,	0x00000000}, -	{0x19e,	"IVOR14",	0x00000000,	0x00000000}, -	{0x19f,	"IVOR15",	0x00000000,	0x00000000}, +	{0x19d,	"IVOR13",	0x0000fff0,	0x00001300}, +	{0x19e,	"IVOR14",	0x0000fff0,	0x00001400}, +	{0x19f,	"IVOR15",	0x0000fff0,	0x00002000},  	{0x23a,	"MCSRR0",	0x00000000,	0x00000000},  	{0x23b,	"MCSRR1",	0x00000000,	0x00000000},  	{0x23c,	"MCSR",		0x00000000,	0x00000000}, @@ -126,8 +132,8 @@ static struct  	{0x395,	"DTV1",		0x00000000,	0x00000000},  	{0x396,	"DTV2",		0x00000000,	0x00000000},  	{0x397,	"DTV3",		0x00000000,	0x00000000}, -	{0x398,	"DVLIM",	0x00000000,	0x00000000}, -	{0x399,	"IVLIM",	0x00000000,	0x00000000}, +	{0x398,	"DVLIM",	0x0fc1f83f,	0x0001f800}, +	{0x399,	"IVLIM",	0x0fc1f83f,	0x0001f800},  	{0x39b,	"RSTCFG",	0x00000000,	0x00000000},  	{0x39c,	"DCDBTRL",	0x00000000,	0x00000000},  	{0x39d,	"DCDBTRH",	0x00000000,	0x00000000}, @@ -172,5 +178,6 @@ int spr_post_test (int flags)  	return ret;  } +  #endif /* CONFIG_POST & CFG_POST_SPR */  #endif /* CONFIG_POST */ diff --git a/post/cpu/ppc4xx/uart.c b/post/cpu/ppc4xx/uart.c index f220dba17..b047d42df 100644 --- a/post/cpu/ppc4xx/uart.c +++ b/post/cpu/ppc4xx/uart.c @@ -2,6 +2,8 @@   * (C) Copyright 2007   * Wolfgang Denk, DENX Software Engineering, wd@denx.de.   * + * Author: Igor Lisitsin <igor@emcraft.com> + *   * See file CREDITS for list of people who contributed to this   * project.   * @@ -210,5 +212,4 @@ int uart_post_test (int flags)  }  #endif /* CONFIG_POST & CFG_POST_UART */ -  #endif /* CONFIG_POST */ diff --git a/post/cpu/ppc4xx/watchdog.c b/post/cpu/ppc4xx/watchdog.c index 3c76cfd34..bd4f4c985 100644 --- a/post/cpu/ppc4xx/watchdog.c +++ b/post/cpu/ppc4xx/watchdog.c @@ -2,6 +2,8 @@   * (C) Copyright 2007   * Wolfgang Denk, DENX Software Engineering, wd@denx.de.   * + * Author: Igor Lisitsin <igor@emcraft.com> + *   * See file CREDITS for list of people who contributed to this   * project.   * @@ -36,17 +38,18 @@  #ifdef CONFIG_POST  #include <post.h> -#include <watchdog.h>  #if CONFIG_POST & CFG_POST_WATCHDOG +#include <watchdog.h> +  int watchdog_post_test (int flags)  {  	if (flags & POST_REBOOT) {  		/* Test passed */ -  		return 0; -	} else { +	} +	else {  		/* 10-second delay */  		int ints = disable_interrupts ();  		ulong base = post_time_ms (0); diff --git a/post/drivers/Makefile b/post/drivers/Makefile index 068fa98b1..cb2f1deac 100644 --- a/post/drivers/Makefile +++ b/post/drivers/Makefile @@ -26,6 +26,6 @@ SUBDIRS =  LIB	= libpostdrivers.a -COBJS	= cache.o i2c.o memory.o rtc.o +COBJS	= i2c.o memory.o rtc.o  include $(TOPDIR)/post/rules.mk diff --git a/post/lib_ppc/Makefile b/post/lib_ppc/Makefile index 14354a032..9f1b329d7 100644 --- a/post/lib_ppc/Makefile +++ b/post/lib_ppc/Makefile @@ -21,6 +21,7 @@  # MA 02111-1307 USA  # +SUBDIRS = fpu  LIB	= libpostppc.a diff --git a/post/lib_ppc/fpu/20001122-1.c b/post/lib_ppc/fpu/20001122-1.c new file mode 100644 index 000000000..f689b8232 --- /dev/null +++ b/post/lib_ppc/fpu/20001122-1.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2007 + * 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 + */ +/* + * This file is originally a part of the GCC testsuite. + */ + +#include <common.h> + +#ifdef CONFIG_POST + +#include <post.h> + +#if CONFIG_POST & CFG_POST_FPU + +int fpu_post_test_math1 (void) +{ +	volatile double a, *p; +	double c, d; +	volatile double b; + +	d = 1.0; +	p = &b; + +	do +	{ +		c = d; +		d = c * 0.5; +		b = 1 + d; +	} while (b != 1.0); + +	a = 1.0 + c; + +	if (a == 1.0) { +		post_log ("Error in FPU math1 test\n"); +		return -1; +	} + +	return 0; +} + +#endif /* CONFIG_POST & CFG_POST_FPU */ +#endif /* CONFIG_POST */ diff --git a/post/lib_ppc/fpu/20010114-2.c b/post/lib_ppc/fpu/20010114-2.c new file mode 100644 index 000000000..6e60507f9 --- /dev/null +++ b/post/lib_ppc/fpu/20010114-2.c @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2007 + * 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 + */ +/* + * This file is originally a part of the GCC testsuite. + */ + +#include <common.h> + +#ifdef CONFIG_POST + +#include <post.h> + +#if CONFIG_POST & CFG_POST_FPU + +static float rintf (float x) +{ +	volatile float TWO23 = 8388608.0; + +	if (__builtin_fabs (x) < TWO23) +	{ +		if (x > 0.0) +		{ +			x += TWO23; +			x -= TWO23; +		} +		else if (x < 0.0) +		{ +			x = TWO23 - x; +			x = -(x - TWO23); +		} +	} + +	return x; +} + +int fpu_post_test_math2 (void) +{ +	if (rintf (-1.5) != -2.0) { +		post_log ("Error in FPU math2 test\n"); +		return -1; +	} +	return 0; +} + +#endif /* CONFIG_POST & CFG_POST_FPU */ +#endif /* CONFIG_POST */ diff --git a/post/lib_ppc/fpu/20010226-1.c b/post/lib_ppc/fpu/20010226-1.c new file mode 100644 index 000000000..b2c47e365 --- /dev/null +++ b/post/lib_ppc/fpu/20010226-1.c @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2007 + * 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 + */ +/* + * This file is originally a part of the GCC testsuite. + */ + +#include <common.h> + +#ifdef CONFIG_POST + +#include <post.h> + +#if CONFIG_POST & CFG_POST_FPU + +int fpu_post_test_math3 (void) +{ +	volatile long double dfrom = 1.1; +	volatile long double m1; +	volatile long double m2; +	volatile unsigned long mant_long; + +	m1 = dfrom / 2.0; +	m2 = m1 * 4294967296.0; +	mant_long = ((unsigned long) m2) & 0xffffffff; + +	if (mant_long != 0x8ccccccc) { +		post_log ("Error in FPU math3 test\n"); +		return -1; +	} +	return 0; +} + +#endif /* CONFIG_POST & CFG_POST_FPU */ +#endif /* CONFIG_POST */ diff --git a/post/lib_ppc/fpu/980619-1.c b/post/lib_ppc/fpu/980619-1.c new file mode 100644 index 000000000..990aa0c98 --- /dev/null +++ b/post/lib_ppc/fpu/980619-1.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2007 + * 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 + */ +/* + * This file is originally a part of the GCC testsuite. + */ + +#include <common.h> + +#ifdef CONFIG_POST + +#include <post.h> + +#if CONFIG_POST & CFG_POST_FPU + +int fpu_post_test_math4 (void) +{ +	volatile float reale = 1.0f; +	volatile float oneplus; +	int i; + +	if (sizeof (float) != 4) +		return 0; + +	for (i = 0; ; i++) +	{ +		oneplus = 1.0f + reale; +		if (oneplus == 1.0f) +			break; +		reale = reale / 2.0f; +	} +	/* Assumes ieee754 accurate arithmetic above.  */ +	if (i != 24) { +		post_log ("Error in FPU math4 test\n"); +		return -1; +	} +	return 0; +} + +#endif /* CONFIG_POST & CFG_POST_FPU */ +#endif /* CONFIG_POST */ diff --git a/post/lib_ppc/fpu/Makefile b/post/lib_ppc/fpu/Makefile new file mode 100644 index 000000000..82646c80d --- /dev/null +++ b/post/lib_ppc/fpu/Makefile @@ -0,0 +1,32 @@ +# +# (C) Copyright 2007 +# 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 +# + + +LIB	= libpostppcfpu.a + +COBJS	+= fpu.o 20001122-1.o 20010114-2.o 20010226-1.o 980619-1.o +COBJS	+= acc1.o compare-fp-1.o mul-subnormal-single-1.o + +include $(TOPDIR)/post/rules.mk + +CFLAGS += -mhard-float -fkeep-inline-functions diff --git a/post/lib_ppc/fpu/acc1.c b/post/lib_ppc/fpu/acc1.c new file mode 100644 index 000000000..4cecbf6a4 --- /dev/null +++ b/post/lib_ppc/fpu/acc1.c @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2007 + * 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 + */ +/* + * This file is originally a part of the GCC testsuite. + */ + +#include <common.h> + +#ifdef CONFIG_POST + +#include <post.h> + +#if CONFIG_POST & CFG_POST_FPU + +static double func (const double *array) +{ +	double d = *array; + +	if (d == 0.0) +		return d; +	else +		return d + func (array + 1); +} + +int fpu_post_test_math5 (void) +{ +	double values[] = { 0.1e-100, 1.0, -1.0, 0.0 }; + +	if (func (values) != 0.1e-100) { +		post_log ("Error in FPU math5 test\n"); +		return -1; +	} +	return 0; +} + +#endif /* CONFIG_POST & CFG_POST_FPU */ +#endif /* CONFIG_POST */ diff --git a/post/lib_ppc/fpu/compare-fp-1.c b/post/lib_ppc/fpu/compare-fp-1.c new file mode 100644 index 000000000..d866ad5a3 --- /dev/null +++ b/post/lib_ppc/fpu/compare-fp-1.c @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2007 + * 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 + */ +/* + * Test for correctness of composite floating-point comparisons. + * Written by Paolo Bonzini, 26th May 2004. + * This file is originally a part of the GCC testsuite. + */ + +#include <common.h> + +#ifdef CONFIG_POST + +#include <post.h> + +#if CONFIG_POST & CFG_POST_FPU + +static int failed; + +#define TEST(c) if ((c) != ok) failed++ +#define ORD(a, b) (!__builtin_isunordered ((a), (b))) +#define UNORD(a, b) (__builtin_isunordered ((a), (b))) +#define UNEQ(a, b) (__builtin_isunordered ((a), (b)) || ((a) == (b))) +#define UNLT(a, b) (__builtin_isunordered ((a), (b)) || ((a) < (b))) +#define UNLE(a, b) (__builtin_isunordered ((a), (b)) || ((a) <= (b))) +#define UNGT(a, b) (__builtin_isunordered ((a), (b)) || ((a) > (b))) +#define UNGE(a, b) (__builtin_isunordered ((a), (b)) || ((a) >= (b))) +#define LTGT(a, b) (__builtin_islessgreater ((a), (b))) + +static float pinf; +static float ninf; +static float NaN; + +static void iuneq (float x, float y, int ok) +{ +	TEST (UNEQ (x, y)); +	TEST (!LTGT (x, y)); +	TEST (UNLE (x, y) && UNGE (x,y)); +} + +static void ieq (float x, float y, int ok) +{ +	TEST (ORD (x, y) && UNEQ (x, y)); +} + +static void iltgt (float x, float y, int ok) +{ +	TEST (!UNEQ (x, y)); /* Not optimizable. */ +	TEST (LTGT (x, y)); /* Same, __builtin_islessgreater does not trap. */ +	TEST (ORD (x, y) && (UNLT (x, y) || UNGT (x,y))); +} + +static void ine (float x, float y, int ok) +{ +	TEST (UNLT (x, y) || UNGT (x, y)); +} + +static void iunlt (float x, float y, int ok) +{ +	TEST (UNLT (x, y)); +	TEST (UNORD (x, y) || (x < y)); +} + +static void ilt (float x, float y, int ok) +{ +	TEST (ORD (x, y) && UNLT (x, y)); /* Not optimized */ +	TEST ((x <= y) && (x != y)); +	TEST ((x <= y) && (y != x)); +	TEST ((x != y) && (x <= y)); /* Not optimized */ +	TEST ((y != x) && (x <= y)); /* Not optimized */ +} + +static void iunle (float x, float y, int ok) +{ +	TEST (UNLE (x, y)); +	TEST (UNORD (x, y) || (x <= y)); +} + +static void ile (float x, float y, int ok) +{ +	TEST (ORD (x, y) && UNLE (x, y)); /* Not optimized */ +	TEST ((x < y) || (x == y)); +	TEST ((y > x) || (x == y)); +	TEST ((x == y) || (x < y)); /* Not optimized */ +	TEST ((y == x) || (x < y)); /* Not optimized */ +} + +static void iungt (float x, float y, int ok) +{ +	TEST (UNGT (x, y)); +	TEST (UNORD (x, y) || (x > y)); +} + +static void igt (float x, float y, int ok) +{ +	TEST (ORD (x, y) && UNGT (x, y)); /* Not optimized */ +	TEST ((x >= y) && (x != y)); +	TEST ((x >= y) && (y != x)); +	TEST ((x != y) && (x >= y)); /* Not optimized */ +	TEST ((y != x) && (x >= y)); /* Not optimized */ +} + +static void iunge (float x, float y, int ok) +{ +	TEST (UNGE (x, y)); +	TEST (UNORD (x, y) || (x >= y)); +} + +static void ige (float x, float y, int ok) +{ +	TEST (ORD (x, y) && UNGE (x, y)); /* Not optimized */ +	TEST ((x > y) || (x == y)); +	TEST ((y < x) || (x == y)); +	TEST ((x == y) || (x > y)); /* Not optimized */ +	TEST ((y == x) || (x > y)); /* Not optimized */ +} + +int fpu_post_test_math6 (void) +{ +	pinf = __builtin_inf (); +	ninf = -__builtin_inf (); +	NaN = __builtin_nan (""); + +	iuneq (ninf, pinf, 0); +	iuneq (NaN, NaN, 1); +	iuneq (pinf, ninf, 0); +	iuneq (1, 4, 0); +	iuneq (3, 3, 1); +	iuneq (5, 2, 0); + +	ieq (1, 4, 0); +	ieq (3, 3, 1); +	ieq (5, 2, 0); + +	iltgt (ninf, pinf, 1); +	iltgt (NaN, NaN, 0); +	iltgt (pinf, ninf, 1); +	iltgt (1, 4, 1); +	iltgt (3, 3, 0); +	iltgt (5, 2, 1); + +	ine (1, 4, 1); +	ine (3, 3, 0); +	ine (5, 2, 1); + +	iunlt (NaN, ninf, 1); +	iunlt (pinf, NaN, 1); +	iunlt (pinf, ninf, 0); +	iunlt (pinf, pinf, 0); +	iunlt (ninf, ninf, 0); +	iunlt (1, 4, 1); +	iunlt (3, 3, 0); +	iunlt (5, 2, 0); + +	ilt (1, 4, 1); +	ilt (3, 3, 0); +	ilt (5, 2, 0); + +	iunle (NaN, ninf, 1); +	iunle (pinf, NaN, 1); +	iunle (pinf, ninf, 0); +	iunle (pinf, pinf, 1); +	iunle (ninf, ninf, 1); +	iunle (1, 4, 1); +	iunle (3, 3, 1); +	iunle (5, 2, 0); + +	ile (1, 4, 1); +	ile (3, 3, 1); +	ile (5, 2, 0); + +	iungt (NaN, ninf, 1); +	iungt (pinf, NaN, 1); +	iungt (pinf, ninf, 1); +	iungt (pinf, pinf, 0); +	iungt (ninf, ninf, 0); +	iungt (1, 4, 0); +	iungt (3, 3, 0); +	iungt (5, 2, 1); + +	igt (1, 4, 0); +	igt (3, 3, 0); +	igt (5, 2, 1); + +	iunge (NaN, ninf, 1); +	iunge (pinf, NaN, 1); +	iunge (ninf, pinf, 0); +	iunge (pinf, pinf, 1); +	iunge (ninf, ninf, 1); +	iunge (1, 4, 0); +	iunge (3, 3, 1); +	iunge (5, 2, 1); + +	ige (1, 4, 0); +	ige (3, 3, 1); +	ige (5, 2, 1); + +	if (failed) { +		post_log ("Error in FPU math6 test\n"); +		return -1; +	} +	return 0; +} + +#endif /* CONFIG_POST & CFG_POST_FPU */ +#endif /* CONFIG_POST */ diff --git a/post/lib_ppc/fpu/fpu.c b/post/lib_ppc/fpu/fpu.c new file mode 100644 index 000000000..07dcba8cc --- /dev/null +++ b/post/lib_ppc/fpu/fpu.c @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2007 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Author: Sergei Poselenov <sposelenov@emcraft.com> + * + * 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> + +/* + * FPU test + * + * This test checks the arithmetic logic unit (ALU) of CPU. + * It tests independently various groups of instructions using + * run-time modification of the code to reduce the memory footprint. + * For more details refer to post/cpu/ *.c files. + */ + +#ifdef CONFIG_POST + +#include <post.h> + +#if CONFIG_POST & CFG_POST_FPU + +#include <watchdog.h> + +extern int fpu_status (void); +extern void fpu_enable (void); +extern void fpu_disable (void); + +extern int fpu_post_test_math1 (void); +extern int fpu_post_test_math2 (void); +extern int fpu_post_test_math3 (void); +extern int fpu_post_test_math4 (void); +extern int fpu_post_test_math5 (void); +extern int fpu_post_test_math6 (void); +extern int fpu_post_test_math7 (void); + +int fpu_post_test (int flags) +{ +	int fpu = fpu_status (); + +	int ret = 0; + +	WATCHDOG_RESET (); + +	if (!fpu) +		fpu_enable (); + +	if (ret == 0) +		ret = fpu_post_test_math1 (); +	if (ret == 0) +		ret = fpu_post_test_math2 (); +	if (ret == 0) +		ret = fpu_post_test_math3 (); +	if (ret == 0) +		ret = fpu_post_test_math4 (); +	if (ret == 0) +		ret = fpu_post_test_math5 (); +	if (ret == 0) +		ret = fpu_post_test_math6 (); +	if (ret == 0) +		ret = fpu_post_test_math7 (); + +	if (!fpu) +		fpu_disable (); + +	WATCHDOG_RESET (); + +	return ret; +} + +#endif /* CONFIG_POST & CFG_POST_FPU */ +#endif /* CONFIG_POST */ diff --git a/post/lib_ppc/fpu/mul-subnormal-single-1.c b/post/lib_ppc/fpu/mul-subnormal-single-1.c new file mode 100644 index 000000000..67f48da33 --- /dev/null +++ b/post/lib_ppc/fpu/mul-subnormal-single-1.c @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2007 + * 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 + */ +/* + * This file is originally a part of the GCC testsuite. + * Check that certain subnormal numbers (formerly known as denormalized + * numbers) are rounded to within 0.5 ulp.  PR other/14354. + */ + +#include <common.h> + +#ifdef CONFIG_POST + +#include <post.h> + +#if CONFIG_POST & CFG_POST_FPU + +union uf +{ +	unsigned int u; +	float f; +}; + +static float +u2f (unsigned int v) +{ +	union uf u; +	u.u = v; +	return u.f; +} + +static unsigned int +f2u (float v) +{ +	union uf u; +	u.f = v; +	return u.u; +} + +static int ok = 1; + +static void +tstmul (unsigned int ux, unsigned int uy, unsigned int ur) +{ +	float x = u2f (ux); +	float y = u2f (uy); + +	if (f2u (x * y) != ur) +	/* Set a variable rather than aborting here, to simplify tracing when +	   several computations are wrong.  */ +		ok = 0; +} + +/* We don't want to make this const and static, or else we risk inlining +   causing the test to fold as constants at compile-time.  */ +struct +{ +  unsigned int p1, p2, res; +} static volatile expected[] = +{ +	{0xfff, 0x3f800400, 0xfff}, +	{0xf, 0x3fc88888, 0x17}, +	{0xf, 0x3f844444, 0xf} +}; + +int fpu_post_test_math7 (void) +{ +	unsigned int i; + +	for (i = 0; i < sizeof (expected) / sizeof (expected[0]); i++) +	{ +		tstmul (expected[i].p1, expected[i].p2, expected[i].res); +		tstmul (expected[i].p2, expected[i].p1, expected[i].res); +	} + +	if (!ok) { +		post_log ("Error in FPU math7 test\n"); +		return -1; +	} +	return 0; +} + +#endif /* CONFIG_POST & CFG_POST_FPU */ +#endif /* CONFIG_POST */ |