diff options
Diffstat (limited to 'cpu')
61 files changed, 1557 insertions, 608 deletions
| diff --git a/cpu/arm1136/mx31/timer.c b/cpu/arm1136/mx31/timer.c index 29b484e44..7972ba0dd 100644 --- a/cpu/arm1136/mx31/timer.c +++ b/cpu/arm1136/mx31/timer.c @@ -152,7 +152,7 @@ void set_timer (ulong t)  }  /* delay x useconds AND perserve advance timstamp value */ -void udelay (unsigned long usec) +void __udelay (unsigned long usec)  {  	unsigned long long tmp;  	ulong tmo; diff --git a/cpu/arm1136/omap24xx/timer.c b/cpu/arm1136/omap24xx/timer.c index 8dd8d7b00..67547490f 100644 --- a/cpu/arm1136/omap24xx/timer.c +++ b/cpu/arm1136/omap24xx/timer.c @@ -74,7 +74,7 @@ void set_timer (ulong t)  }  /* delay x useconds AND perserve advance timstamp value */ -void udelay (unsigned long usec) +void __udelay (unsigned long usec)  {  	ulong tmo, tmp; diff --git a/cpu/arm1176/cpu.c b/cpu/arm1176/cpu.c index d1a332748..2c0014f2b 100644 --- a/cpu/arm1176/cpu.c +++ b/cpu/arm1176/cpu.c @@ -33,7 +33,7 @@  #include <common.h>  #include <command.h> -#include <s3c6400.h> +#include <asm/arch/s3c6400.h>  #include <asm/system.h>  static void cache_flush (void); diff --git a/cpu/arm1176/s3c64xx/cpu_init.S b/cpu/arm1176/s3c64xx/cpu_init.S index 32bb467f2..df88cba34 100644 --- a/cpu/arm1176/s3c64xx/cpu_init.S +++ b/cpu/arm1176/s3c64xx/cpu_init.S @@ -24,7 +24,7 @@   */  #include <config.h> -#include <s3c6400.h> +#include <asm/arch/s3c6400.h>  	.globl mem_ctrl_asm_init  mem_ctrl_asm_init: diff --git a/cpu/arm1176/s3c64xx/reset.S b/cpu/arm1176/s3c64xx/reset.S index 315b13f8d..eae572e4f 100644 --- a/cpu/arm1176/s3c64xx/reset.S +++ b/cpu/arm1176/s3c64xx/reset.S @@ -21,7 +21,7 @@   * MA 02111-1307 USA   */ -#include <s3c6400.h> +#include <asm/arch/s3c6400.h>  .globl reset_cpu  reset_cpu: diff --git a/cpu/arm1176/s3c64xx/speed.c b/cpu/arm1176/s3c64xx/speed.c index 5c335a55a..11962acad 100644 --- a/cpu/arm1176/s3c64xx/speed.c +++ b/cpu/arm1176/s3c64xx/speed.c @@ -31,7 +31,7 @@   */  #include <common.h> -#include <s3c6400.h> +#include <asm/arch/s3c6400.h>  #define APLL 0  #define MPLL 1 diff --git a/cpu/arm1176/s3c64xx/timer.c b/cpu/arm1176/s3c64xx/timer.c index 22a5b7770..9768319ef 100644 --- a/cpu/arm1176/s3c64xx/timer.c +++ b/cpu/arm1176/s3c64xx/timer.c @@ -40,7 +40,7 @@  #include <common.h>  #include <asm/proc-armv/ptrace.h> -#include <s3c6400.h> +#include <asm/arch/s3c6400.h>  #include <div64.h>  static ulong timer_load_val; @@ -164,7 +164,7 @@ void set_timer(ulong t)  	timestamp = t * (timer_load_val / (100 * CONFIG_SYS_HZ));  } -void udelay(unsigned long usec) +void __udelay(unsigned long usec)  {  	unsigned long long tmp;  	ulong tmo; diff --git a/cpu/arm1176/start.S b/cpu/arm1176/start.S index cb891df17..68a356d13 100644 --- a/cpu/arm1176/start.S +++ b/cpu/arm1176/start.S @@ -35,7 +35,7 @@  #ifdef CONFIG_ENABLE_MMU  #include <asm/proc/domain.h>  #endif -#include <s3c6400.h> +#include <asm/arch/s3c6400.h>  #if !defined(CONFIG_ENABLE_MMU) && !defined(CONFIG_SYS_PHY_UBOOT_BASE)  #define CONFIG_SYS_PHY_UBOOT_BASE	CONFIG_SYS_UBOOT_BASE @@ -241,16 +241,11 @@ mmu_enable:  skip_hw_init:  	/* Set up the stack						    */  stack_setup: -#ifdef CONFIG_MEMORY_UPPER_CODE -	ldr	sp, =(CONFIG_SYS_UBOOT_BASE + CONFIG_SYS_UBOOT_SIZE - 0xc) -#else -	ldr	r0, _TEXT_BASE		/* upper 128 KiB: relocated uboot   */ +	ldr	r0, =CONFIG_SYS_UBOOT_BASE	/* base of copy in DRAM	    */  	sub	r0, r0, #CONFIG_SYS_MALLOC_LEN	/* malloc area                      */  	sub	r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo                        */  	sub	sp, r0, #12		/* leave 3 words for abort-stack    */ -#endif -  clear_bss:  	ldr	r0, _bss_start		/* find start of bss segment        */  	ldr	r1, _bss_end		/* stop here                        */ diff --git a/cpu/arm720t/interrupts.c b/cpu/arm720t/interrupts.c index 91d552cd2..eb8d42531 100644 --- a/cpu/arm720t/interrupts.c +++ b/cpu/arm720t/interrupts.c @@ -224,7 +224,7 @@ void set_timer (ulong t)  	timestamp = t;  } -void udelay (unsigned long usec) +void __udelay (unsigned long usec)  {  	ulong tmo; @@ -296,7 +296,7 @@ ulong get_timer (ulong base)  	return timestamp - base;  } -void udelay (unsigned long usec) +void __udelay (unsigned long usec)  {  	u32 ticks; diff --git a/cpu/arm920t/a320/Makefile b/cpu/arm920t/a320/Makefile new file mode 100644 index 000000000..f030c5362 --- /dev/null +++ b/cpu/arm920t/a320/Makefile @@ -0,0 +1,47 @@ +# +# (C) Copyright 2000-2006 +# 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 $(TOPDIR)/config.mk + +LIB	= $(obj)lib$(SOC).a + +SOBJS	+= reset.o +COBJS	+= timer.o +COBJS	+= ftsmc020.o + +SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS)) + +all:	$(obj).depend $(LIB) + +$(LIB):	$(OBJS) +	$(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/cpu/arm920t/a320/ftsmc020.c b/cpu/arm920t/a320/ftsmc020.c new file mode 100644 index 000000000..76465373e --- /dev/null +++ b/cpu/arm920t/a320/ftsmc020.c @@ -0,0 +1,51 @@ +/* + * (C) Copyright 2009 Faraday Technology + * Po-Yu Chuang <ratbert@faraday-tech.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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <config.h> +#include <common.h> +#include <asm/io.h> +#include <asm/arch/ftsmc020.h> + +struct ftsmc020_config { +	unsigned int	config; +	unsigned int	timing; +}; + +static struct ftsmc020_config config[] = CONFIG_SYS_FTSMC020_CONFIGS; + +static struct ftsmc020 *smc = (struct ftsmc020 *)CONFIG_FTSMC020_BASE; + +static void ftsmc020_setup_bank(unsigned int bank, struct ftsmc020_config *cfg) +{ +	if (bank > 3) { +		printf("bank # %u invalid\n", bank); +		return; +	} + +	writel(cfg->config, &smc->bank[bank].cr); +	writel(cfg->timing, &smc->bank[bank].tpr); +} + +void ftsmc020_init(void) +{ +	int i; + +	for (i = 0; i < ARRAY_SIZE(config); i++) +		ftsmc020_setup_bank(i, &config[i]); +} diff --git a/cpu/arm920t/a320/reset.S b/cpu/arm920t/a320/reset.S new file mode 100644 index 000000000..12ca527c5 --- /dev/null +++ b/cpu/arm920t/a320/reset.S @@ -0,0 +1,22 @@ +/* + * (C) Copyright 2009 Faraday Technology + * Po-Yu Chuang <ratbert@faraday-tech.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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +.global reset_cpu +reset_cpu: +	b	reset_cpu diff --git a/cpu/arm920t/a320/timer.c b/cpu/arm920t/a320/timer.c new file mode 100644 index 000000000..bb655930d --- /dev/null +++ b/cpu/arm920t/a320/timer.c @@ -0,0 +1,193 @@ +/* + * (C) Copyright 2009 Faraday Technology + * Po-Yu Chuang <ratbert@faraday-tech.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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/ftpmu010.h> +#include <asm/arch/fttmr010.h> + +static ulong timestamp; +static ulong lastdec; + +static struct fttmr010 *tmr = (struct fttmr010 *)CONFIG_FTTMR010_BASE; +static struct ftpmu010 *pmu = (struct ftpmu010 *)CONFIG_FTPMU010_BASE; + +#define TIMER_CLOCK	32768 +#define TIMER_LOAD_VAL	0xffffffff + +int timer_init(void) +{ +	unsigned int oscc; +	unsigned int cr; + +	debug("%s()\n", __func__); + +	/* disable timers */ +	writel(0, &tmr->cr); + +	/* +	 * use 32768Hz oscillator for RTC, WDT, TIMER +	 */ + +	/* enable the 32768Hz oscillator */ +	oscc = readl(&pmu->OSCC); +	oscc &= ~(FTPMU010_OSCC_OSCL_OFF | FTPMU010_OSCC_OSCL_TRI); +	writel(oscc, &pmu->OSCC); + +	/* wait until ready */ +	while (!(readl(&pmu->OSCC) & FTPMU010_OSCC_OSCL_STABLE)) +		; + +	/* select 32768Hz oscillator */ +	oscc = readl(&pmu->OSCC); +	oscc |= FTPMU010_OSCC_OSCL_RTCLSEL; +	writel(oscc, &pmu->OSCC); + +	/* setup timer */ +	writel(TIMER_LOAD_VAL, &tmr->timer3_load); +	writel(TIMER_LOAD_VAL, &tmr->timer3_counter); +	writel(0, &tmr->timer3_match1); +	writel(0, &tmr->timer3_match2); + +	/* we don't want timer to issue interrupts */ +	writel(FTTMR010_TM3_MATCH1 | +	       FTTMR010_TM3_MATCH2 | +	       FTTMR010_TM3_OVERFLOW, +	       &tmr->interrupt_mask); + +	cr = readl(&tmr->cr); +	cr |= FTTMR010_TM3_CLOCK;	/* use external clock */ +	cr |= FTTMR010_TM3_ENABLE; +	writel(cr, &tmr->cr); + +	/* init the timestamp and lastdec value */ +	reset_timer_masked(); + +	return 0; +} + +/* + * timer without interrupts + */ + +/* + * reset time + */ +void reset_timer_masked(void) +{ +	/* capure current decrementer value time */ +	lastdec = readl(&tmr->timer3_counter) / (TIMER_CLOCK / CONFIG_SYS_HZ); +	timestamp = 0;		/* start "advancing" time stamp from 0 */ + +	debug("%s(): lastdec = %lx\n", __func__, lastdec); +} + +void reset_timer(void) +{ +	debug("%s()\n", __func__); +	reset_timer_masked(); +} + +/* + * return timer ticks + */ +ulong get_timer_masked(void) +{ +	/* current tick value */ +	ulong now = readl(&tmr->timer3_counter) / (TIMER_CLOCK / CONFIG_SYS_HZ); + +	debug("%s(): now = %lx, lastdec = %lx\n", __func__, now, lastdec); + +	if (lastdec >= now) { +		/* +		 * normal mode (non roll) +		 * move stamp fordward with absoulte diff ticks +		 */ +		timestamp += lastdec - now; +	} else { +		/* +		 * we have overflow of the count down timer +		 * +		 * nts = ts + ld + (TLV - now) +		 * ts=old stamp, ld=time that passed before passing through -1 +		 * (TLV-now) amount of time after passing though -1 +		 * nts = new "advancing time stamp"...it could also roll and +		 * cause problems. +		 */ +		timestamp += lastdec + TIMER_LOAD_VAL - now; +	} + +	lastdec = now; + +	debug("%s() returns %lx\n", __func__, timestamp); + +	return timestamp; +} + +/* + * return difference between timer ticks and base + */ +ulong get_timer(ulong base) +{ +	debug("%s(%lx)\n", __func__, base); +	return get_timer_masked() - base; +} + +void set_timer(ulong t) +{ +	debug("%s(%lx)\n", __func__, t); +	timestamp = t; +} + +/* delay x useconds AND perserve advance timstamp value */ +void udelay(unsigned long usec) +{ +	long tmo = usec * (TIMER_CLOCK / 1000) / 1000; +	unsigned long now, last = readl(&tmr->timer3_counter); + +	debug("%s(%lu)\n", __func__, usec); +	while (tmo > 0) { +		now = readl(&tmr->timer3_counter); +		if (now > last) /* count down timer overflow */ +			tmo -= TIMER_LOAD_VAL + last - now; +		else +			tmo -= last - now; +		last = now; +	} +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ +	debug("%s()\n", __func__); +	return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk(void) +{ +	debug("%s()\n", __func__); +	return CONFIG_SYS_HZ; +} diff --git a/cpu/arm920t/at91rm9200/timer.c b/cpu/arm920t/at91rm9200/timer.c index 235d10738..9c54bbedb 100644 --- a/cpu/arm920t/at91rm9200/timer.c +++ b/cpu/arm920t/at91rm9200/timer.c @@ -87,7 +87,7 @@ void set_timer (ulong t)  	timestamp = t;  } -void udelay (unsigned long usec) +void __udelay (unsigned long usec)  {  	udelay_masked(usec);  } diff --git a/cpu/arm920t/imx/timer.c b/cpu/arm920t/imx/timer.c index 31ec588d9..b06b518f0 100644 --- a/cpu/arm920t/imx/timer.c +++ b/cpu/arm920t/imx/timer.c @@ -89,7 +89,7 @@ void udelay_masked (unsigned long usec)  	} while (diff >= 0);  } -void udelay (unsigned long usec) +void __udelay (unsigned long usec)  {  	udelay_masked(usec);  } diff --git a/cpu/arm920t/ks8695/timer.c b/cpu/arm920t/ks8695/timer.c index 22987bc48..886e37059 100644 --- a/cpu/arm920t/ks8695/timer.c +++ b/cpu/arm920t/ks8695/timer.c @@ -81,7 +81,7 @@ void set_timer(ulong t)  	timer_ticks = t;  } -void udelay(ulong usec) +void __udelay(ulong usec)  {  	ulong start = get_timer_masked();  	ulong end; diff --git a/cpu/arm920t/s3c24x0/interrupts.c b/cpu/arm920t/s3c24x0/interrupts.c index 914894613..879fda66a 100644 --- a/cpu/arm920t/s3c24x0/interrupts.c +++ b/cpu/arm920t/s3c24x0/interrupts.c @@ -31,11 +31,7 @@  #include <common.h> -#if defined(CONFIG_S3C2400) -#include <s3c2400.h> -#elif defined(CONFIG_S3C2410) -#include <s3c2410.h> -#endif +#include <asm/arch/s3c24x0_cpu.h>  #include <asm/proc-armv/ptrace.h>  void do_irq (struct pt_regs *pt_regs) diff --git a/cpu/arm920t/s3c24x0/speed.c b/cpu/arm920t/s3c24x0/speed.c index 136c7794a..b13283a79 100644 --- a/cpu/arm920t/s3c24x0/speed.c +++ b/cpu/arm920t/s3c24x0/speed.c @@ -30,15 +30,10 @@   */  #include <common.h> -#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) +#ifdef CONFIG_S3C24X0  #include <asm/io.h> - -#if defined(CONFIG_S3C2400) -#include <s3c2400.h> -#elif defined(CONFIG_S3C2410) -#include <s3c2410.h> -#endif +#include <asm/arch/s3c24x0_cpu.h>  #define MPLL 0  #define UPLL 1 @@ -100,6 +95,4 @@ ulong get_UCLK(void)  	return get_PLLCLK(UPLL);  } -#endif /* defined(CONFIG_S3C2400) || -	  defined (CONFIG_S3C2410) || -	  defined (CONFIG_TRAB) */ +#endif /* CONFIG_S3C24X0 */ diff --git a/cpu/arm920t/s3c24x0/timer.c b/cpu/arm920t/s3c24x0/timer.c index 20cedd463..fcc6c0cb1 100644 --- a/cpu/arm920t/s3c24x0/timer.c +++ b/cpu/arm920t/s3c24x0/timer.c @@ -30,17 +30,10 @@   */  #include <common.h> -#if defined(CONFIG_S3C2400) || \ -    defined(CONFIG_S3C2410) || \ -    defined(CONFIG_TRAB) +#ifdef CONFIG_S3C24X0  #include <asm/io.h> - -#if defined(CONFIG_S3C2400) -#include <s3c2400.h> -#elif defined(CONFIG_S3C2410) -#include <s3c2410.h> -#endif +#include <asm/arch/s3c24x0_cpu.h>  int timer_load_val = 0;  static ulong timer_clk; @@ -106,7 +99,7 @@ void set_timer(ulong t)  	timestamp = t;  } -void udelay(unsigned long usec) +void __udelay (unsigned long usec)  {  	ulong tmo;  	ulong start = get_ticks(); @@ -225,6 +218,4 @@ void reset_cpu(ulong ignored)  	/*NOTREACHED*/  } -#endif /* defined(CONFIG_S3C2400)  || -	  defined (CONFIG_S3C2410) || -	  defined (CONFIG_TRAB) */ +#endif /* CONFIG_S3C24X0 */ diff --git a/cpu/arm920t/s3c24x0/usb.c b/cpu/arm920t/s3c24x0/usb.c index b5ba8c4f3..e468ed08f 100644 --- a/cpu/arm920t/s3c24x0/usb.c +++ b/cpu/arm920t/s3c24x0/usb.c @@ -23,15 +23,11 @@  #include <common.h> -#if defined(CONFIG_USB_OHCI_NEW) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT) -# if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) - -#if defined(CONFIG_S3C2400) -# include <s3c2400.h> -#elif defined(CONFIG_S3C2410) -# include <s3c2410.h> -#endif +#if defined(CONFIG_USB_OHCI_NEW) && \ +    defined(CONFIG_SYS_USB_OHCI_CPU_INIT) && \ +    defined(CONFIG_S3C24X0) +#include <asm/arch/s3c24x0_cpu.h>  #include <asm/io.h>  int usb_cpu_init(void) @@ -70,5 +66,6 @@ int usb_cpu_init_fail(void)  	return 0;  } -# endif	/* defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) */ -#endif /* defined(CONFIG_USB_OHCI_NEW) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT) */ +#endif /* defined(CONFIG_USB_OHCI_NEW) && \ +	   defined(CONFIG_SYS_USB_OHCI_CPU_INIT) && \ +	   defined(CONFIG_S3C24X0) */ diff --git a/cpu/arm920t/s3c24x0/usb_ohci.c b/cpu/arm920t/s3c24x0/usb_ohci.c index 7672e4ce1..5aa8d64a5 100644 --- a/cpu/arm920t/s3c24x0/usb_ohci.c +++ b/cpu/arm920t/s3c24x0/usb_ohci.c @@ -36,14 +36,9 @@  #include <common.h>  /* #include <pci.h> no PCI on the S3C24X0 */ -#ifdef CONFIG_USB_OHCI - -#if defined(CONFIG_S3C2400) -#include <s3c2400.h> -#elif defined(CONFIG_S3C2410) -#include <s3c2410.h> -#endif +#if defined(CONFIG_USB_OHCI) && defined(CONFIG_S3C24X0) +#include <asm/arch/s3c24x0_cpu.h>  #include <asm/io.h>  #include <malloc.h>  #include <usb.h> @@ -1757,4 +1752,4 @@ int usb_lowlevel_stop(void)  	return 0;  } -#endif /* CONFIG_USB_OHCI */ +#endif /* defined(CONFIG_USB_OHCI) && defined(CONFIG_S3C24X0) */ diff --git a/cpu/arm920t/start.S b/cpu/arm920t/start.S index 114427a16..779f192e5 100644 --- a/cpu/arm920t/start.S +++ b/cpu/arm920t/start.S @@ -131,7 +131,7 @@ copyex:  	bne	copyex  #endif -#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) +#ifdef CONFIG_S3C24X0  	/* turn off the watchdog */  # if defined(CONFIG_S3C2400) @@ -166,7 +166,7 @@ copyex:  	ldr	r0, =CLKDIVN  	mov	r1, #3  	str	r1, [r0] -#endif	/* CONFIG_S3C2400 || CONFIG_S3C2410 */ +#endif	/* CONFIG_S3C24X0 */  	/*  	 * we do sys-critical inits only at reboot, diff --git a/cpu/arm925t/timer.c b/cpu/arm925t/timer.c index c16ef2577..7dfe2b564 100644 --- a/cpu/arm925t/timer.c +++ b/cpu/arm925t/timer.c @@ -81,7 +81,7 @@ void set_timer (ulong t)  }  /* delay x useconds AND preserve advance timestamp value */ -void udelay (unsigned long usec) +void __udelay (unsigned long usec)  {  	int32_t tmo = usec * (TIMER_CLOCK / 1000) / 1000;  	uint32_t now, last = __raw_readl(CONFIG_SYS_TIMERBASE + READ_TIM); diff --git a/cpu/arm926ejs/at91/timer.c b/cpu/arm926ejs/at91/timer.c index 811bb3c59..7352b5c33 100644 --- a/cpu/arm926ejs/at91/timer.c +++ b/cpu/arm926ejs/at91/timer.c @@ -105,7 +105,7 @@ ulong get_timer_masked(void)  	return tick_to_time(get_ticks());  } -void udelay(unsigned long usec) +void __udelay(unsigned long usec)  {  	unsigned long long tmp;  	ulong tmo; diff --git a/cpu/arm926ejs/davinci/cpu.c b/cpu/arm926ejs/davinci/cpu.c index 390cab8a2..fc3551c30 100644 --- a/cpu/arm926ejs/davinci/cpu.c +++ b/cpu/arm926ejs/davinci/cpu.c @@ -23,7 +23,7 @@  #include <common.h>  #include <netdev.h>  #include <asm/arch/hardware.h> - +#include <asm/io.h>  /* offsets from PLL controller base */  #define PLLC_PLLCTL	0x100 @@ -60,6 +60,54 @@  #define DDR_PLLDIV	PLLC_PLLDIV1  #endif +#ifdef CONFIG_SOC_DA8XX +const dv_reg * const sysdiv[7] = { +	&davinci_pllc_regs->plldiv1, &davinci_pllc_regs->plldiv2, +	&davinci_pllc_regs->plldiv3, &davinci_pllc_regs->plldiv4, +	&davinci_pllc_regs->plldiv5, &davinci_pllc_regs->plldiv6, +	&davinci_pllc_regs->plldiv7 +}; + +int clk_get(enum davinci_clk_ids id) +{ +	int pre_div; +	int pllm; +	int post_div; +	int pll_out; + +	pll_out = CONFIG_SYS_OSCIN_FREQ; + +	if (id == DAVINCI_AUXCLK_CLKID) +		goto out; + +	/* +	 * Lets keep this simple. Combining operations can result in +	 * unexpected approximations +	 */ +	pre_div = (readl(&davinci_pllc_regs->prediv) & +		   DAVINCI_PLLC_DIV_MASK) + 1; +	pllm = readl(&davinci_pllc_regs->pllm) + 1; + +	pll_out /= pre_div; +	pll_out *= pllm; + +	if (id == DAVINCI_PLLM_CLKID) +		goto out; + +	post_div = (readl(&davinci_pllc_regs->postdiv) & +		    DAVINCI_PLLC_DIV_MASK) + 1; + +	pll_out /= post_div; + +	if (id == DAVINCI_PLLC_CLKID) +		goto out; + +	pll_out /= (readl(sysdiv[id - 1]) & DAVINCI_PLLC_DIV_MASK) + 1; + +out: +	return pll_out; +} +#endif /* CONFIG_SOC_DA8XX */  #ifdef CONFIG_DISPLAY_CPUINFO diff --git a/cpu/arm926ejs/davinci/psc.c b/cpu/arm926ejs/davinci/psc.c index 5bb972f18..8273a7fae 100644 --- a/cpu/arm926ejs/davinci/psc.c +++ b/cpu/arm926ejs/davinci/psc.c @@ -25,6 +25,7 @@  #include <common.h>  #include <asm/arch/hardware.h> +#include <asm/io.h>  /*   * The PSC manages three inputs to a "module" which may be a peripheral or @@ -47,21 +48,45 @@  /* Works on Always On power domain only (no PD argument) */  void lpsc_on(unsigned int id)  { -	dv_reg_p mdstat, mdctl; +	dv_reg_p mdstat, mdctl, ptstat, ptcmd; +#ifdef CONFIG_SOC_DA8XX +	struct davinci_psc_regs *psc_regs; +#endif +#ifndef CONFIG_SOC_DA8XX  	if (id >= DAVINCI_LPSC_GEM)  		return;			/* Don't work on DSP Power Domain */  	mdstat = REG_P(PSC_MDSTAT_BASE + (id * 4));  	mdctl = REG_P(PSC_MDCTL_BASE + (id * 4)); +	ptstat = REG_P(PSC_PTSTAT); +	ptcmd = REG_P(PSC_PTCMD); +#else +	if (id < DAVINCI_LPSC_PSC1_BASE) { +		if (id >= PSC_PSC0_MODULE_ID_CNT) +			return; +		psc_regs = davinci_psc0_regs; +		mdstat = &psc_regs->psc0.mdstat[id]; +		mdctl = &psc_regs->psc0.mdctl[id]; +	} else { +		id -= DAVINCI_LPSC_PSC1_BASE; +		if (id >= PSC_PSC1_MODULE_ID_CNT) +			return; +		psc_regs = davinci_psc1_regs; +		mdstat = &psc_regs->psc1.mdstat[id]; +		mdctl = &psc_regs->psc1.mdctl[id]; +	} +	ptstat = &psc_regs->ptstat; +	ptcmd = &psc_regs->ptcmd; +#endif -	while (REG(PSC_PTSTAT) & 0x01) +	while (readl(ptstat) & 0x01)  		continue; -	if ((*mdstat & 0x1f) == 0x03) -		return;			/* Already on and enabled */ +	if ((readl(mdstat) & 0x1f) == 0x03) +		return; /* Already on and enabled */ -	*mdctl |= 0x03; +	writel(readl(mdctl) | 0x03, mdctl);  	switch (id) {  #ifdef CONFIG_SOC_DM644X @@ -80,16 +105,16 @@ void lpsc_on(unsigned int id)  	case DAVINCI_LPSC_MEMSTICK:  	case DAVINCI_LPSC_McBSP:  	case DAVINCI_LPSC_GPIO: -		*mdctl |= 0x200; +		writel(readl(mdctl) | 0x200, mdctl);  		break;  #endif  	} -	REG(PSC_PTCMD) = 0x01; +	writel(0x01, ptcmd); -	while (REG(PSC_PTSTAT) & 0x03) +	while (readl(ptstat) & 0x01)  		continue; -	while ((*mdstat & 0x1f) != 0x03)	/* Probably an overkill... */ +	while ((readl(mdstat) & 0x1f) != 0x03)  		continue;  } diff --git a/cpu/arm926ejs/davinci/timer.c b/cpu/arm926ejs/davinci/timer.c index 80751add8..9da7443f3 100644 --- a/cpu/arm926ejs/davinci/timer.c +++ b/cpu/arm926ejs/davinci/timer.c @@ -38,8 +38,9 @@   */  #include <common.h> +#include <asm/io.h> -typedef volatile struct { +struct davinci_timer {  	u_int32_t	pid12;  	u_int32_t	emumgt;  	u_int32_t	na1; @@ -51,9 +52,10 @@ typedef volatile struct {  	u_int32_t	tcr;  	u_int32_t	tgcr;  	u_int32_t	wdtcr; -} davinci_timer; +}; -davinci_timer		*timer = (davinci_timer *)CONFIG_SYS_TIMERBASE; +static struct davinci_timer * const timer = +	(struct davinci_timer *)CONFIG_SYS_TIMERBASE;  #define TIMER_LOAD_VAL	(CONFIG_SYS_HZ_CLOCK / CONFIG_SYS_HZ)  #define TIM_CLK_DIV	16 @@ -64,30 +66,30 @@ static ulong lastinc;  int timer_init(void)  {  	/* We are using timer34 in unchained 32-bit mode, full speed */ -	timer->tcr = 0x0; -	timer->tgcr = 0x0; -	timer->tgcr = 0x06 | ((TIM_CLK_DIV - 1) << 8); -	timer->tim34 = 0x0; -	timer->prd34 = TIMER_LOAD_VAL; +	writel(0x0, &timer->tcr); +	writel(0x0, &timer->tgcr); +	writel(0x06 | ((TIM_CLK_DIV - 1) << 8), &timer->tgcr); +	writel(0x0, &timer->tim34); +	writel(TIMER_LOAD_VAL, &timer->prd34);  	lastinc = 0;  	timestamp = 0; -	timer->tcr = 2 << 22; +	writel(2 << 22, &timer->tcr);  	return(0);  }  void reset_timer(void)  { -	timer->tcr = 0x0; -	timer->tim34 = 0; +	writel(0x0, &timer->tcr); +	writel(0x0, &timer->tim34);  	lastinc = 0;  	timestamp = 0; -	timer->tcr = 2 << 22; +	writel(2 << 22, &timer->tcr);  }  static ulong get_timer_raw(void)  { -	ulong now = timer->tim34; +	ulong now = readl(&timer->tim34);  	if (now >= lastinc) {  		/* normal mode */ @@ -110,7 +112,7 @@ void set_timer(ulong t)  	timestamp = t;  } -void udelay(unsigned long usec) +void __udelay(unsigned long usec)  {  	ulong tmo;  	ulong endtime; diff --git a/cpu/arm926ejs/kirkwood/timer.c b/cpu/arm926ejs/kirkwood/timer.c index 817ff4284..2ec6a9380 100644 --- a/cpu/arm926ejs/kirkwood/timer.c +++ b/cpu/arm926ejs/kirkwood/timer.c @@ -125,7 +125,7 @@ void set_timer(ulong t)  	timestamp = t;  } -void udelay(unsigned long usec) +void __udelay(unsigned long usec)  {  	uint current;  	ulong delayticks; diff --git a/cpu/arm926ejs/mx27/timer.c b/cpu/arm926ejs/mx27/timer.c index 90110581e..8f1d47bba 100644 --- a/cpu/arm926ejs/mx27/timer.c +++ b/cpu/arm926ejs/mx27/timer.c @@ -177,7 +177,7 @@ void set_timer (ulong t)  }  /* delay x useconds AND preserve advance timstamp value */ -void udelay (unsigned long usec) +void __udelay (unsigned long usec)  {  	unsigned long long tmp;  	ulong tmo; diff --git a/cpu/arm926ejs/nomadik/timer.c b/cpu/arm926ejs/nomadik/timer.c index 16067c900..047b9e351 100644 --- a/cpu/arm926ejs/nomadik/timer.c +++ b/cpu/arm926ejs/nomadik/timer.c @@ -59,7 +59,7 @@ ulong get_timer(ulong base)  }  /* Delay x useconds */ -void udelay(unsigned long usec) +void __udelay(unsigned long usec)  {  	ulong ini, end; diff --git a/cpu/arm926ejs/omap/timer.c b/cpu/arm926ejs/omap/timer.c index 392b158d5..2ac38c40b 100644 --- a/cpu/arm926ejs/omap/timer.c +++ b/cpu/arm926ejs/omap/timer.c @@ -80,7 +80,7 @@ void set_timer (ulong t)  }  /* delay x useconds AND perserve advance timstamp value */ -void udelay (unsigned long usec) +void __udelay (unsigned long usec)  {  	ulong tmo, tmp; diff --git a/cpu/arm926ejs/versatile/timer.c b/cpu/arm926ejs/versatile/timer.c index 50c13350a..563db3654 100755 --- a/cpu/arm926ejs/versatile/timer.c +++ b/cpu/arm926ejs/versatile/timer.c @@ -109,7 +109,7 @@ void set_timer (ulong t)  }  /* delay x useconds AND perserve advance timstamp value */ -void udelay (unsigned long usec) +void __udelay (unsigned long usec)  {  	ulong tmo, tmp; diff --git a/cpu/arm_cortexa8/omap3/mem.c b/cpu/arm_cortexa8/omap3/mem.c index 8b8cd6d61..dfb7e4c2a 100644 --- a/cpu/arm_cortexa8/omap3/mem.c +++ b/cpu/arm_cortexa8/omap3/mem.c @@ -161,10 +161,11 @@ void do_sdrc_init(u32 cs, u32 early)  		writel(0, &sdrc_base->sysconfig);  		/* setup sdrc to ball mux */ -		writel(SDP_SDRC_SHARING, &sdrc_base->sharing); +		writel(SDRC_SHARING, &sdrc_base->sharing);  		/* Disable Power Down of CKE cuz of 1 CKE on combo part */ -		writel(SRFRONRESET | PAGEPOLICY_HIGH, &sdrc_base->power); +		writel(WAKEUPPROC | PWDNEN | SRFRONRESET | PAGEPOLICY_HIGH, +				&sdrc_base->power);  		writel(ENADLL | DLLPHASE_90, &sdrc_base->dlla_ctrl);  		sdelay(0x20000); diff --git a/cpu/arm_cortexa8/omap3/sys_info.c b/cpu/arm_cortexa8/omap3/sys_info.c index 31b20033c..08fb32eaa 100644 --- a/cpu/arm_cortexa8/omap3/sys_info.c +++ b/cpu/arm_cortexa8/omap3/sys_info.c @@ -109,7 +109,7 @@ u32 get_cpu_rev(void)   ****************************************************/  u32 is_mem_sdr(void)  { -	if (readl(&sdrc_base->cs[CS0].mr) == SDP_SDRC_MR_0_SDR) +	if (readl(&sdrc_base->cs[CS0].mr) == SDRC_MR_0_SDR)  		return 1;  	return 0;  } diff --git a/cpu/arm_cortexa8/omap3/timer.c b/cpu/arm_cortexa8/omap3/timer.c index 12a16b321..401bfe6d0 100644 --- a/cpu/arm_cortexa8/omap3/timer.c +++ b/cpu/arm_cortexa8/omap3/timer.c @@ -82,7 +82,7 @@ void set_timer(ulong t)  }  /* delay x useconds */ -void udelay(unsigned long usec) +void __udelay(unsigned long usec)  {  	long tmo = usec * (TIMER_CLOCK / 1000) / 1000;  	unsigned long now, last = readl(&timer_base->tcrr); diff --git a/cpu/arm_cortexa8/s5pc1xx/timer.c b/cpu/arm_cortexa8/s5pc1xx/timer.c index cdba5d934..c5df5c5ab 100644 --- a/cpu/arm_cortexa8/s5pc1xx/timer.c +++ b/cpu/arm_cortexa8/s5pc1xx/timer.c @@ -115,7 +115,7 @@ void set_timer(unsigned long t)  }  /* delay x useconds */ -void udelay(unsigned long usec) +void __udelay(unsigned long usec)  {  	unsigned long tmo, tmp; diff --git a/cpu/at32ap/Makefile b/cpu/at32ap/Makefile index e08f27383..60899c79e 100644 --- a/cpu/at32ap/Makefile +++ b/cpu/at32ap/Makefile @@ -30,7 +30,7 @@ LIB	:= $(obj)lib$(CPU).a  START-y			+= start.o  COBJS-y			+= cpu.o -COBJS-y			+= hsdramc.o +COBJS-$(CONFIG_SYS_HSDRAMC) += hsdramc.o  COBJS-y			+= exception.o  COBJS-y			+= cache.o  COBJS-y			+= interrupts.o diff --git a/cpu/at32ap/hsdramc.c b/cpu/at32ap/hsdramc.c index f74121cd4..b6eae667c 100644 --- a/cpu/at32ap/hsdramc.c +++ b/cpu/at32ap/hsdramc.c @@ -21,7 +21,6 @@   */  #include <common.h> -#ifdef CONFIG_SYS_HSDRAMC  #include <asm/io.h>  #include <asm/sdram.h> @@ -116,5 +115,3 @@ unsigned long sdram_init(void *sdram_base, const struct sdram_config *config)  	return sdram_size;  } - -#endif /* CONFIG_SYS_HSDRAMC */ diff --git a/cpu/at32ap/interrupts.c b/cpu/at32ap/interrupts.c index 75cc39e94..c6d8d16e3 100644 --- a/cpu/at32ap/interrupts.c +++ b/cpu/at32ap/interrupts.c @@ -96,7 +96,7 @@ void set_timer(unsigned long t)  /*   * For short delays only. It will overflow after a few seconds.   */ -void udelay(unsigned long usec) +void __udelay(unsigned long usec)  {  	unsigned long cycles;  	unsigned long base; diff --git a/cpu/blackfin/interrupts.c b/cpu/blackfin/interrupts.c index 19456e5c1..921bfe0c0 100644 --- a/cpu/blackfin/interrupts.c +++ b/cpu/blackfin/interrupts.c @@ -64,7 +64,7 @@ int disable_interrupts(void)  	return 1;  } -void udelay(unsigned long usec) +void __udelay(unsigned long usec)  {  	unsigned long delay, start, stop;  	unsigned long cclk; diff --git a/cpu/i386/Makefile b/cpu/i386/Makefile index e98bd3d7d..c658c6e45 100644 --- a/cpu/i386/Makefile +++ b/cpu/i386/Makefile @@ -29,7 +29,7 @@ include $(TOPDIR)/config.mk  LIB	= $(obj)lib$(CPU).a  START	= start.o start16.o resetvec.o -COBJS	= serial.o interrupts.o exceptions.o cpu.o +COBJS	= serial.o interrupts.o cpu.o  SRCS	:= $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)  OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/cpu/i386/cpu.c b/cpu/i386/cpu.c index d91e33b94..3010519e7 100644 --- a/cpu/i386/cpu.c +++ b/cpu/i386/cpu.c @@ -37,7 +37,7 @@  #include <command.h>  #include <asm/interrupt.h> -int cpu_init(void) +int cpu_init_f(void)  {  	/* initialize FPU, reset EM, set MP and NE */  	asm ("fninit\n" \ @@ -46,10 +46,13 @@ int cpu_init(void)  	     "orl  $0x22, %eax\n" \  	     "movl %eax, %cr0\n" ); +	return 0; +} + +int cpu_init_r(void) +{  	/* Initialize core interrupt and exception functionality of CPU */  	cpu_init_interrupts (); -	cpu_init_exceptions (); -  	return 0;  } @@ -74,6 +77,8 @@ void __attribute__ ((regparm(0))) generate_gpf(void);  /* segment 0x70 is an arbitrary segment which does not exist */  asm(".globl generate_gpf\n" +    ".hidden generate_gpf\n" +    ".type generate_gpf, @function\n"      "generate_gpf:\n"      "ljmp   $0x70, $0x47114711\n"); diff --git a/cpu/i386/exceptions.c b/cpu/i386/exceptions.c deleted file mode 100644 index bc3d43460..000000000 --- a/cpu/i386/exceptions.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * (C) Copyright 2002 - * Daniel Engström, Omicron Ceti AB, daniel@omicron.se. - * - * 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 <asm/interrupt.h> - -asm (".globl exp_return\n" -     "exp_return:\n" -     "     addl  $12, %esp\n" -     "     pop   %esp\n" -     "     popa\n" -     "     iret\n"); - -char exception_stack[4096]; - -/* - * For detailed description of each exception, refer to: - * Intel® 64 and IA-32 Architectures Software Developer's Manual - * Volume 1: Basic Architecture - * Order Number: 253665-029US, November 2008 - * Table 6-1. Exceptions and Interrupts - */ -DECLARE_EXCEPTION(0, divide_error_entry); -DECLARE_EXCEPTION(1, debug_entry); -DECLARE_EXCEPTION(2, nmi_interrupt_entry); -DECLARE_EXCEPTION(3, breakpoint_entry); -DECLARE_EXCEPTION(4, overflow_entry); -DECLARE_EXCEPTION(5, bound_range_exceeded_entry); -DECLARE_EXCEPTION(6, invalid_opcode_entry); -DECLARE_EXCEPTION(7, device_not_available_entry); -DECLARE_EXCEPTION(8, double_fault_entry); -DECLARE_EXCEPTION(9, coprocessor_segment_overrun_entry); -DECLARE_EXCEPTION(10, invalid_tss_entry); -DECLARE_EXCEPTION(11, segment_not_present_entry); -DECLARE_EXCEPTION(12, stack_segment_fault_entry); -DECLARE_EXCEPTION(13, general_protection_entry); -DECLARE_EXCEPTION(14, page_fault_entry); -DECLARE_EXCEPTION(15, reserved_exception_entry); -DECLARE_EXCEPTION(16, floating_point_error_entry); -DECLARE_EXCEPTION(17, alignment_check_entry); -DECLARE_EXCEPTION(18, machine_check_entry); -DECLARE_EXCEPTION(19, simd_floating_point_exception_entry); -DECLARE_EXCEPTION(20, reserved_exception_entry); -DECLARE_EXCEPTION(21, reserved_exception_entry); -DECLARE_EXCEPTION(22, reserved_exception_entry); -DECLARE_EXCEPTION(23, reserved_exception_entry); -DECLARE_EXCEPTION(24, reserved_exception_entry); -DECLARE_EXCEPTION(25, reserved_exception_entry); -DECLARE_EXCEPTION(26, reserved_exception_entry); -DECLARE_EXCEPTION(27, reserved_exception_entry); -DECLARE_EXCEPTION(28, reserved_exception_entry); -DECLARE_EXCEPTION(29, reserved_exception_entry); -DECLARE_EXCEPTION(30, reserved_exception_entry); -DECLARE_EXCEPTION(31, reserved_exception_entry); - -__isr__ reserved_exception_entry(int cause, int ip, int seg) -{ -	printf("Reserved Exception %d at %04x:%08x\n", cause, seg, ip); -} - -__isr__ divide_error_entry(int cause, int ip, int seg) -{ -	printf("Divide Error (Division by zero) at %04x:%08x\n", seg, ip); -	while(1); -} - -__isr__ debug_entry(int cause, int ip, int seg) -{ -	printf("Debug Interrupt (Single step) at %04x:%08x\n", seg, ip); -} - -__isr__ nmi_interrupt_entry(int cause, int ip, int seg) -{ -	printf("NMI Interrupt at %04x:%08x\n", seg, ip); -} - -__isr__ breakpoint_entry(int cause, int ip, int seg) -{ -	printf("Breakpoint at %04x:%08x\n", seg, ip); -} - -__isr__ overflow_entry(int cause, int ip, int seg) -{ -	printf("Overflow at %04x:%08x\n", seg, ip); -	while(1); -} - -__isr__ bound_range_exceeded_entry(int cause, int ip, int seg) -{ -	printf("BOUND Range Exceeded at %04x:%08x\n", seg, ip); -	while(1); -} - -__isr__ invalid_opcode_entry(int cause, int ip, int seg) -{ -	printf("Invalid Opcode (UnDefined Opcode) at %04x:%08x\n", seg, ip); -	while(1); -} - -__isr__ device_not_available_entry(int cause, int ip, int seg) -{ -	printf("Device Not Available (No Math Coprocessor) at %04x:%08x\n", seg, ip); -	while(1); -} - -__isr__ double_fault_entry(int cause, int ip, int seg) -{ -	printf("Double fault at %04x:%08x\n", seg, ip); -	while(1); -} - -__isr__ coprocessor_segment_overrun_entry(int cause, int ip, int seg) -{ -	printf("Co-processor segment overrun at %04x:%08x\n", seg, ip); -	while(1); -} - -__isr__ invalid_tss_entry(int cause, int ip, int seg) -{ -	printf("Invalid TSS at %04x:%08x\n", seg, ip); -} - -__isr__ segment_not_present_entry(int cause, int ip, int seg) -{ -	printf("Segment Not Present at %04x:%08x\n", seg, ip); -	while(1); -} - -__isr__ stack_segment_fault_entry(int cause, int ip, int seg) -{ -	printf("Stack Segment Fault at %04x:%08x\n", seg, ip); -	while(1); -} - -__isr__ general_protection_entry(int cause, int ip, int seg) -{ -	printf("General Protection at %04x:%08x\n", seg, ip); -} - -__isr__ page_fault_entry(int cause, int ip, int seg) -{ -	printf("Page fault at %04x:%08x\n", seg, ip); -	while(1); -} - -__isr__ floating_point_error_entry(int cause, int ip, int seg) -{ -	printf("Floating-Point Error (Math Fault) at %04x:%08x\n", seg, ip); -} - -__isr__ alignment_check_entry(int cause, int ip, int seg) -{ -	printf("Alignment check at %04x:%08x\n", seg, ip); -} - -__isr__ machine_check_entry(int cause, int ip, int seg) -{ -	printf("Machine Check at %04x:%08x\n", seg, ip); -} - -__isr__ simd_floating_point_exception_entry(int cause, int ip, int seg) -{ -	printf("SIMD Floating-Point Exception at %04x:%08x\n", seg, ip); -} - -int cpu_init_exceptions(void) -{ -	/* Just in case... */ -	disable_interrupts(); - -	/* Setup exceptions */ -	set_vector(0x00, exp_0); -	set_vector(0x01, exp_1); -	set_vector(0x02, exp_2); -	set_vector(0x03, exp_3); -	set_vector(0x04, exp_4); -	set_vector(0x05, exp_5); -	set_vector(0x06, exp_6); -	set_vector(0x07, exp_7); -	set_vector(0x08, exp_8); -	set_vector(0x09, exp_9); -	set_vector(0x0a, exp_10); -	set_vector(0x0b, exp_11); -	set_vector(0x0c, exp_12); -	set_vector(0x0d, exp_13); -	set_vector(0x0e, exp_14); -	set_vector(0x0f, exp_15); -	set_vector(0x10, exp_16); -	set_vector(0x11, exp_17); -	set_vector(0x12, exp_18); -	set_vector(0x13, exp_19); -	set_vector(0x14, exp_20); -	set_vector(0x15, exp_21); -	set_vector(0x16, exp_22); -	set_vector(0x17, exp_23); -	set_vector(0x18, exp_24); -	set_vector(0x19, exp_25); -	set_vector(0x1a, exp_26); -	set_vector(0x1b, exp_27); -	set_vector(0x1c, exp_28); -	set_vector(0x1d, exp_29); -	set_vector(0x1e, exp_30); -	set_vector(0x1f, exp_31); - -	/* It is now safe to enable interrupts */ -	enable_interrupts(); - -	return 0; -} diff --git a/cpu/i386/interrupts.c b/cpu/i386/interrupts.c index 063ea42cd..4b5743719 100644 --- a/cpu/i386/interrupts.c +++ b/cpu/i386/interrupts.c @@ -1,4 +1,7 @@  /* + * (C) Copyright 2008 + * Graeme Russ, graeme.russ@gmail.com. + *   * (C) Copyright 2002   * Daniel Engström, Omicron Ceti AB, daniel@omicron.se.   * @@ -24,6 +27,16 @@  #include <common.h>  #include <asm/interrupt.h> +#define DECLARE_INTERRUPT(x) \ +	".globl irq_"#x"\n" \ +	".hidden irq_"#x"\n" \ +	".type irq_"#x", @function\n" \ +	"irq_"#x":\n" \ +	"pushl %ebp\n" \ +	"movl %esp,%ebp\n" \ +	"pusha\n" \ +	"pushl $"#x"\n" \ +	"jmp irq_common_entry\n"  struct idt_entry {  	u16	base_low; @@ -33,35 +46,37 @@ struct idt_entry {  	u16	base_high;  } __attribute__ ((packed)); +struct desc_ptr { +	unsigned short size; +	unsigned long address; +	unsigned short segment; +} __attribute__((packed));  struct idt_entry idt[256]; +struct desc_ptr idt_ptr; -asm (".globl irq_return\n" -     "irq_return:\n" -     "     addl  $4, %esp\n" -     "     popa\n" -     "     iret\n"); - -void __attribute__ ((regparm(0))) default_isr(void); -asm ("default_isr: iret\n"); - -asm ("idt_ptr:\n" -	".word	0x800\n" /* size of the table 8*256 bytes */ -	".long	idt\n"	 /* offset */ -	".word	0x18\n");/* data segment */ +static inline void load_idt(const struct desc_ptr *dtr) +{ +	asm volatile("cs lidt %0"::"m" (*dtr)); +}  void set_vector(u8 intnum, void *routine)  { -	idt[intnum].base_high = (u16)((u32)(routine + gd->reloc_off) >> 16); -	idt[intnum].base_low = (u16)((u32)(routine + gd->reloc_off) & 0xffff); +	idt[intnum].base_high = (u16)((u32)(routine) >> 16); +	idt[intnum].base_low = (u16)((u32)(routine) & 0xffff);  } +void irq_0(void); +void irq_1(void);  int cpu_init_interrupts(void)  {  	int i; +	int irq_entry_size = irq_1 - irq_0; +	void *irq_entry = (void *)irq_0; +  	/* Just in case... */  	disable_interrupts(); @@ -70,10 +85,15 @@ int cpu_init_interrupts(void)  		idt[i].access = 0x8e;  		idt[i].res = 0;  		idt[i].selector = 0x10; -		set_vector(i, default_isr); +		set_vector(i, irq_entry); +		irq_entry += irq_entry_size;  	} -	asm ("cs lidt idt_ptr\n"); +	idt_ptr.size = 256 * 8; +	idt_ptr.address = (unsigned long) idt; +	idt_ptr.segment = 0x18; + +	load_idt(&idt_ptr);  	/* It is now safe to enable interrupts */  	enable_interrupts(); @@ -81,6 +101,12 @@ int cpu_init_interrupts(void)  	return 0;  } +void __do_irq(int irq) +{ +	printf("Unhandled IRQ : %d\n", irq); +} +void do_irq(int irq) __attribute__((weak, alias("__do_irq"))); +  void enable_interrupts(void)  {  	asm("sti\n"); @@ -94,3 +120,382 @@ int disable_interrupts(void)  	return (flags&0x200); /* IE flags is bit 9 */  } + +/* IRQ Low-Level Service Routine */ +__isr__ irq_llsr(int ip, int seg, int irq) +{ +	/* +	 * For detailed description of each exception, refer to: +	 * Intel® 64 and IA-32 Architectures Software Developer's Manual +	 * Volume 1: Basic Architecture +	 * Order Number: 253665-029US, November 2008 +	 * Table 6-1. Exceptions and Interrupts +	 */ +	switch (irq) { +	case 0x00: +		printf("Divide Error (Division by zero) at %04x:%08x\n", seg, ip); +		while(1); +		break; +	case 0x01: +		printf("Debug Interrupt (Single step) at %04x:%08x\n", seg, ip); +		break; +	case 0x02: +		printf("NMI Interrupt at %04x:%08x\n", seg, ip); +		break; +	case 0x03: +		printf("Breakpoint at %04x:%08x\n", seg, ip); +		break; +	case 0x04: +		printf("Overflow at %04x:%08x\n", seg, ip); +		while(1); +		break; +	case 0x05: +		printf("BOUND Range Exceeded at %04x:%08x\n", seg, ip); +		while(1); +		break; +	case 0x06: +		printf("Invalid Opcode (UnDefined Opcode) at %04x:%08x\n", seg, ip); +		while(1); +		break; +	case 0x07: +		printf("Device Not Available (No Math Coprocessor) at %04x:%08x\n", seg, ip); +		while(1); +		break; +	case 0x08: +		printf("Double fault at %04x:%08x\n", seg, ip); +		while(1); +		break; +	case 0x09: +		printf("Co-processor segment overrun at %04x:%08x\n", seg, ip); +		while(1); +		break; +	case 0x0a: +		printf("Invalid TSS at %04x:%08x\n", seg, ip); +		break; +	case 0x0b: +		printf("Segment Not Present at %04x:%08x\n", seg, ip); +		while(1); +		break; +	case 0x0c: +		printf("Stack Segment Fault at %04x:%08x\n", seg, ip); +		while(1); +		break; +	case 0x0d: +		printf("General Protection at %04x:%08x\n", seg, ip); +		break; +	case 0x0e: +		printf("Page fault at %04x:%08x\n", seg, ip); +		while(1); +		break; +	case 0x0f: +		printf("Floating-Point Error (Math Fault) at %04x:%08x\n", seg, ip); +		break; +	case 0x10: +		printf("Alignment check at %04x:%08x\n", seg, ip); +		break; +	case 0x11: +		printf("Machine Check at %04x:%08x\n", seg, ip); +		break; +	case 0x12: +		printf("SIMD Floating-Point Exception at %04x:%08x\n", seg, ip); +		break; +	case 0x13: +	case 0x14: +	case 0x15: +	case 0x16: +	case 0x17: +	case 0x18: +	case 0x19: +	case 0x1a: +	case 0x1b: +	case 0x1c: +	case 0x1d: +	case 0x1e: +	case 0x1f: +		printf("Reserved Exception %d at %04x:%08x\n", irq, seg, ip); +		break; + +	default: +		/* Hardware or User IRQ */ +		do_irq(irq); +	} +} + +/* + * OK - This looks really horrible, but it serves a purpose - It helps create + * fully relocatable code. + *  - The call to irq_llsr will be a relative jump + *  - The IRQ entries will be guaranteed to be in order + * It's a bit annoying that we need to waste 3 bytes per interrupt entry + * (total of 768 code bytes), but we MUST create a Stack Frame and this is + * the easiest way I could do it. Maybe it can be made better later. + */ +asm(".globl irq_common_entry\n" \ +	".hidden irq_common_entry\n" \ +	".type irq_common_entry, @function\n" \ +	"irq_common_entry:\n" \ +	"pushl $0\n" \ +	"pushl $0\n" \ +	"call irq_llsr\n" \ +	"popl %eax\n" \ +	"popl %eax\n" \ +	"popl %eax\n" \ +	"popa\n" \ +	"leave\n"\ +	"iret\n" \ +	DECLARE_INTERRUPT(0) \ +	DECLARE_INTERRUPT(1) \ +	DECLARE_INTERRUPT(2) \ +	DECLARE_INTERRUPT(3) \ +	DECLARE_INTERRUPT(4) \ +	DECLARE_INTERRUPT(5) \ +	DECLARE_INTERRUPT(6) \ +	DECLARE_INTERRUPT(7) \ +	DECLARE_INTERRUPT(8) \ +	DECLARE_INTERRUPT(9) \ +	DECLARE_INTERRUPT(10) \ +	DECLARE_INTERRUPT(11) \ +	DECLARE_INTERRUPT(12) \ +	DECLARE_INTERRUPT(13) \ +	DECLARE_INTERRUPT(14) \ +	DECLARE_INTERRUPT(15) \ +	DECLARE_INTERRUPT(16) \ +	DECLARE_INTERRUPT(17) \ +	DECLARE_INTERRUPT(18) \ +	DECLARE_INTERRUPT(19) \ +	DECLARE_INTERRUPT(20) \ +	DECLARE_INTERRUPT(21) \ +	DECLARE_INTERRUPT(22) \ +	DECLARE_INTERRUPT(23) \ +	DECLARE_INTERRUPT(24) \ +	DECLARE_INTERRUPT(25) \ +	DECLARE_INTERRUPT(26) \ +	DECLARE_INTERRUPT(27) \ +	DECLARE_INTERRUPT(28) \ +	DECLARE_INTERRUPT(29) \ +	DECLARE_INTERRUPT(30) \ +	DECLARE_INTERRUPT(31) \ +	DECLARE_INTERRUPT(32) \ +	DECLARE_INTERRUPT(33) \ +	DECLARE_INTERRUPT(34) \ +	DECLARE_INTERRUPT(35) \ +	DECLARE_INTERRUPT(36) \ +	DECLARE_INTERRUPT(37) \ +	DECLARE_INTERRUPT(38) \ +	DECLARE_INTERRUPT(39) \ +	DECLARE_INTERRUPT(40) \ +	DECLARE_INTERRUPT(41) \ +	DECLARE_INTERRUPT(42) \ +	DECLARE_INTERRUPT(43) \ +	DECLARE_INTERRUPT(44) \ +	DECLARE_INTERRUPT(45) \ +	DECLARE_INTERRUPT(46) \ +	DECLARE_INTERRUPT(47) \ +	DECLARE_INTERRUPT(48) \ +	DECLARE_INTERRUPT(49) \ +	DECLARE_INTERRUPT(50) \ +	DECLARE_INTERRUPT(51) \ +	DECLARE_INTERRUPT(52) \ +	DECLARE_INTERRUPT(53) \ +	DECLARE_INTERRUPT(54) \ +	DECLARE_INTERRUPT(55) \ +	DECLARE_INTERRUPT(56) \ +	DECLARE_INTERRUPT(57) \ +	DECLARE_INTERRUPT(58) \ +	DECLARE_INTERRUPT(59) \ +	DECLARE_INTERRUPT(60) \ +	DECLARE_INTERRUPT(61) \ +	DECLARE_INTERRUPT(62) \ +	DECLARE_INTERRUPT(63) \ +	DECLARE_INTERRUPT(64) \ +	DECLARE_INTERRUPT(65) \ +	DECLARE_INTERRUPT(66) \ +	DECLARE_INTERRUPT(67) \ +	DECLARE_INTERRUPT(68) \ +	DECLARE_INTERRUPT(69) \ +	DECLARE_INTERRUPT(70) \ +	DECLARE_INTERRUPT(71) \ +	DECLARE_INTERRUPT(72) \ +	DECLARE_INTERRUPT(73) \ +	DECLARE_INTERRUPT(74) \ +	DECLARE_INTERRUPT(75) \ +	DECLARE_INTERRUPT(76) \ +	DECLARE_INTERRUPT(77) \ +	DECLARE_INTERRUPT(78) \ +	DECLARE_INTERRUPT(79) \ +	DECLARE_INTERRUPT(80) \ +	DECLARE_INTERRUPT(81) \ +	DECLARE_INTERRUPT(82) \ +	DECLARE_INTERRUPT(83) \ +	DECLARE_INTERRUPT(84) \ +	DECLARE_INTERRUPT(85) \ +	DECLARE_INTERRUPT(86) \ +	DECLARE_INTERRUPT(87) \ +	DECLARE_INTERRUPT(88) \ +	DECLARE_INTERRUPT(89) \ +	DECLARE_INTERRUPT(90) \ +	DECLARE_INTERRUPT(91) \ +	DECLARE_INTERRUPT(92) \ +	DECLARE_INTERRUPT(93) \ +	DECLARE_INTERRUPT(94) \ +	DECLARE_INTERRUPT(95) \ +	DECLARE_INTERRUPT(97) \ +	DECLARE_INTERRUPT(96) \ +	DECLARE_INTERRUPT(98) \ +	DECLARE_INTERRUPT(99) \ +	DECLARE_INTERRUPT(100) \ +	DECLARE_INTERRUPT(101) \ +	DECLARE_INTERRUPT(102) \ +	DECLARE_INTERRUPT(103) \ +	DECLARE_INTERRUPT(104) \ +	DECLARE_INTERRUPT(105) \ +	DECLARE_INTERRUPT(106) \ +	DECLARE_INTERRUPT(107) \ +	DECLARE_INTERRUPT(108) \ +	DECLARE_INTERRUPT(109) \ +	DECLARE_INTERRUPT(110) \ +	DECLARE_INTERRUPT(111) \ +	DECLARE_INTERRUPT(112) \ +	DECLARE_INTERRUPT(113) \ +	DECLARE_INTERRUPT(114) \ +	DECLARE_INTERRUPT(115) \ +	DECLARE_INTERRUPT(116) \ +	DECLARE_INTERRUPT(117) \ +	DECLARE_INTERRUPT(118) \ +	DECLARE_INTERRUPT(119) \ +	DECLARE_INTERRUPT(120) \ +	DECLARE_INTERRUPT(121) \ +	DECLARE_INTERRUPT(122) \ +	DECLARE_INTERRUPT(123) \ +	DECLARE_INTERRUPT(124) \ +	DECLARE_INTERRUPT(125) \ +	DECLARE_INTERRUPT(126) \ +	DECLARE_INTERRUPT(127) \ +	DECLARE_INTERRUPT(128) \ +	DECLARE_INTERRUPT(129) \ +	DECLARE_INTERRUPT(130) \ +	DECLARE_INTERRUPT(131) \ +	DECLARE_INTERRUPT(132) \ +	DECLARE_INTERRUPT(133) \ +	DECLARE_INTERRUPT(134) \ +	DECLARE_INTERRUPT(135) \ +	DECLARE_INTERRUPT(136) \ +	DECLARE_INTERRUPT(137) \ +	DECLARE_INTERRUPT(138) \ +	DECLARE_INTERRUPT(139) \ +	DECLARE_INTERRUPT(140) \ +	DECLARE_INTERRUPT(141) \ +	DECLARE_INTERRUPT(142) \ +	DECLARE_INTERRUPT(143) \ +	DECLARE_INTERRUPT(144) \ +	DECLARE_INTERRUPT(145) \ +	DECLARE_INTERRUPT(146) \ +	DECLARE_INTERRUPT(147) \ +	DECLARE_INTERRUPT(148) \ +	DECLARE_INTERRUPT(149) \ +	DECLARE_INTERRUPT(150) \ +	DECLARE_INTERRUPT(151) \ +	DECLARE_INTERRUPT(152) \ +	DECLARE_INTERRUPT(153) \ +	DECLARE_INTERRUPT(154) \ +	DECLARE_INTERRUPT(155) \ +	DECLARE_INTERRUPT(156) \ +	DECLARE_INTERRUPT(157) \ +	DECLARE_INTERRUPT(158) \ +	DECLARE_INTERRUPT(159) \ +	DECLARE_INTERRUPT(160) \ +	DECLARE_INTERRUPT(161) \ +	DECLARE_INTERRUPT(162) \ +	DECLARE_INTERRUPT(163) \ +	DECLARE_INTERRUPT(164) \ +	DECLARE_INTERRUPT(165) \ +	DECLARE_INTERRUPT(166) \ +	DECLARE_INTERRUPT(167) \ +	DECLARE_INTERRUPT(168) \ +	DECLARE_INTERRUPT(169) \ +	DECLARE_INTERRUPT(170) \ +	DECLARE_INTERRUPT(171) \ +	DECLARE_INTERRUPT(172) \ +	DECLARE_INTERRUPT(173) \ +	DECLARE_INTERRUPT(174) \ +	DECLARE_INTERRUPT(175) \ +	DECLARE_INTERRUPT(176) \ +	DECLARE_INTERRUPT(177) \ +	DECLARE_INTERRUPT(178) \ +	DECLARE_INTERRUPT(179) \ +	DECLARE_INTERRUPT(180) \ +	DECLARE_INTERRUPT(181) \ +	DECLARE_INTERRUPT(182) \ +	DECLARE_INTERRUPT(183) \ +	DECLARE_INTERRUPT(184) \ +	DECLARE_INTERRUPT(185) \ +	DECLARE_INTERRUPT(186) \ +	DECLARE_INTERRUPT(187) \ +	DECLARE_INTERRUPT(188) \ +	DECLARE_INTERRUPT(189) \ +	DECLARE_INTERRUPT(190) \ +	DECLARE_INTERRUPT(191) \ +	DECLARE_INTERRUPT(192) \ +	DECLARE_INTERRUPT(193) \ +	DECLARE_INTERRUPT(194) \ +	DECLARE_INTERRUPT(195) \ +	DECLARE_INTERRUPT(196) \ +	DECLARE_INTERRUPT(197) \ +	DECLARE_INTERRUPT(198) \ +	DECLARE_INTERRUPT(199) \ +	DECLARE_INTERRUPT(200) \ +	DECLARE_INTERRUPT(201) \ +	DECLARE_INTERRUPT(202) \ +	DECLARE_INTERRUPT(203) \ +	DECLARE_INTERRUPT(204) \ +	DECLARE_INTERRUPT(205) \ +	DECLARE_INTERRUPT(206) \ +	DECLARE_INTERRUPT(207) \ +	DECLARE_INTERRUPT(208) \ +	DECLARE_INTERRUPT(209) \ +	DECLARE_INTERRUPT(210) \ +	DECLARE_INTERRUPT(211) \ +	DECLARE_INTERRUPT(212) \ +	DECLARE_INTERRUPT(213) \ +	DECLARE_INTERRUPT(214) \ +	DECLARE_INTERRUPT(215) \ +	DECLARE_INTERRUPT(216) \ +	DECLARE_INTERRUPT(217) \ +	DECLARE_INTERRUPT(218) \ +	DECLARE_INTERRUPT(219) \ +	DECLARE_INTERRUPT(220) \ +	DECLARE_INTERRUPT(221) \ +	DECLARE_INTERRUPT(222) \ +	DECLARE_INTERRUPT(223) \ +	DECLARE_INTERRUPT(224) \ +	DECLARE_INTERRUPT(225) \ +	DECLARE_INTERRUPT(226) \ +	DECLARE_INTERRUPT(227) \ +	DECLARE_INTERRUPT(228) \ +	DECLARE_INTERRUPT(229) \ +	DECLARE_INTERRUPT(230) \ +	DECLARE_INTERRUPT(231) \ +	DECLARE_INTERRUPT(232) \ +	DECLARE_INTERRUPT(233) \ +	DECLARE_INTERRUPT(234) \ +	DECLARE_INTERRUPT(235) \ +	DECLARE_INTERRUPT(236) \ +	DECLARE_INTERRUPT(237) \ +	DECLARE_INTERRUPT(238) \ +	DECLARE_INTERRUPT(239) \ +	DECLARE_INTERRUPT(240) \ +	DECLARE_INTERRUPT(241) \ +	DECLARE_INTERRUPT(242) \ +	DECLARE_INTERRUPT(243) \ +	DECLARE_INTERRUPT(244) \ +	DECLARE_INTERRUPT(245) \ +	DECLARE_INTERRUPT(246) \ +	DECLARE_INTERRUPT(247) \ +	DECLARE_INTERRUPT(248) \ +	DECLARE_INTERRUPT(249) \ +	DECLARE_INTERRUPT(250) \ +	DECLARE_INTERRUPT(251) \ +	DECLARE_INTERRUPT(252) \ +	DECLARE_INTERRUPT(253) \ +	DECLARE_INTERRUPT(254) \ +	DECLARE_INTERRUPT(255)); diff --git a/cpu/i386/sc520/sc520_timer.c b/cpu/i386/sc520/sc520_timer.c index 23de14bdd..93b5b555c 100644 --- a/cpu/i386/sc520/sc520_timer.c +++ b/cpu/i386/sc520/sc520_timer.c @@ -35,6 +35,12 @@ void sc520_timer_isr(void)  int timer_init(void)  { +	/* Register the SC520 specific timer interrupt handler */ +	register_timer_isr (sc520_timer_isr); + +	/* Install interrupt handler for GP Timer 1 */ +	irq_install_handler (0, timer_isr, NULL); +  	/* Map GP Timer 1 to Master PIC IR0  */  	sc520_mmcr->gp_tmr_int_map[1] = 0x01; @@ -54,11 +60,6 @@ int timer_init(void)  	sc520_mmcr->gptmr1maxcmpa = 100;  	sc520_mmcr->gptmr1ctl = 0xe009; -	/* Register the SC520 specific timer interrupt handler */ -	register_timer_isr (sc520_timer_isr); - -	/* Install interrupt handler for GP Timer 1 */ -	irq_install_handler (0, timer_isr, NULL);  	unmask_irq (0);  	/* Clear the GP Timer 1 status register to get the show rolling*/ @@ -67,7 +68,7 @@ int timer_init(void)  	return 0;  } -void udelay(unsigned long usec) +void __udelay(unsigned long usec)  {  	int m = 0;  	long u; diff --git a/cpu/i386/start.S b/cpu/i386/start.S index 59089ef59..25d32e658 100644 --- a/cpu/i386/start.S +++ b/cpu/i386/start.S @@ -63,11 +63,8 @@ early_board_init_ret:  	jmp     mem_init  mem_init_ret: -	/* check ammount of configured memory -	 * (we need atleast bss start+bss size+stack size) */ -	movl	$_i386boot_bss_start, %ecx        /* BSS start */ -	addl	$_i386boot_bss_size, %ecx         /* BSS size */ -	addl	$CONFIG_SYS_STACK_SIZE, %ecx +	/* Check we have enough memory for stack */ +	movl	$CONFIG_SYS_STACK_SIZE, %ecx  	cmpl	%ecx, %eax  	jae	mem_ok @@ -78,6 +75,8 @@ mem_init_ret:  .progress0a:  	jmp	die  mem_ok: +	/* Set stack pointer to upper memory limit*/ +	movl    %eax, %esp  	/* indicate progress */  	movw	$0x02, %ax @@ -85,12 +84,7 @@ mem_ok:  	jmp	show_boot_progress_asm  .progress1: -	/* create a stack after the bss */ -	movl    $_i386boot_bss_start, %eax -	addl	$_i386boot_bss_size, %eax -	addl	$CONFIG_SYS_STACK_SIZE, %eax -	movl    %eax, %esp - +	/* Test the stack */  	pushl	$0  	popl	%eax  	cmpl	$0, %eax @@ -116,115 +110,19 @@ stack_ok:  	jmp	show_boot_progress_asm  .progress2: -	/* copy data section to ram, size must be 4-byte aligned */ -	movl	$_i386boot_romdata_dest, %edi	  /* destination address */ -	movl	$_i386boot_romdata_start, %esi	  /* source address */ -	movl	$_i386boot_romdata_size, %ecx     /* number of bytes to copy */ -	movl	%ecx, %eax -	andl	$3, %eax -	jnz	data_fail - -	shrl	$2, %ecx	                  /* copy 4 byte each time */ -	cld -	cmpl	$0, %ecx -	je	data_ok -data_segment: -	movsl -	loop	data_segment -	jmp	data_ok -data_fail: -	/* indicate (lack of) progress */ -	movw	$0x83, %ax -	movl	$.progress2a, %ebp -	jmp	show_boot_progress_asm -.progress2a: -	jmp	die - -data_ok: - -	/* indicate progress */ -	movw	$0x04, %ax -	movl	$.progress3, %ebp -	jmp	show_boot_progress_asm -.progress3: - -	/* clear bss section in ram, size must be 4-byte aligned  */ -	movl	$_i386boot_bss_start, %edi        /* MK_CHG BSS start */ -	movl	$_i386boot_bss_size, %ecx         /* BSS size */ -	movl	%ecx, %eax -	andl	$3, %eax -	jnz	bss_fail -	shrl	$2, %ecx	                  /* clear 4 byte each time */ -	cld -	cmpl	$0, %ecx -	je	bss_ok -bss: -	movl	$0, (%edi) -	add	$4, %edi -	loop	bss -	jmp	bss_ok - -bss_fail: -	/* indicate (lack of) progress */ -	movw	$0x84, %ax -	movl	$.progress3a, %ebp -	jmp	show_boot_progress_asm -.progress3a: -	jmp	die - -bss_ok: -#ifndef CONFIG_SKIP_RELOCATE_UBOOT -	/* indicate progress */ -	movw	$0x06, %ax -	movl	$.progress6, %ebp -	jmp	show_boot_progress_asm -.progress6: - -	/* copy text section to ram, size must be 4-byte aligned */ -	movl	$CONFIG_SYS_BL_START_RAM, %edi		/* destination address */ -	movl	$TEXT_BASE, %esi		/* source address */ -	movl	$_i386boot_text_size, %ecx	/* number of bytes to copy */ -	movl	%ecx, %eax -	andl	$3, %eax -	jz	text_copy			/* Already 4-byte aligned */ -	subl    $4, %eax			/* Add extra bytes to size */ -	addl	%eax, %ecx -text_copy: -	shrl	$2, %ecx			/* copy 4 byte each time */ -	cld -	cmpl	$0, %ecx -	je	text_ok -text_segment: -	movsl -	loop	text_segment -	jmp	text_ok -text_fail: -	/* indicate (lack of) progress */ -	movw	$0x86, %ax -	movl	$.progress5a, %ebp -	jmp	show_boot_progress_asm -.progress5a: -	jmp	die - -text_ok: -#endif  	wbinvd +	/* Get upper memory limit */ +	movl %esp, %ecx +	subl $CONFIG_SYS_STACK_SIZE, %ecx -	/* indicate progress */ -	movw	$0x05, %ax -	movl	$.progress4, %ebp -	jmp	show_boot_progress_asm -.progress4: +	/* Create a Stack Frame */ +	pushl %ebp +	movl %esp, %ebp -#ifndef CONFIG_SKIP_RELOCATE_UBOOT -	/* Jump to the RAM copy of start_i386boot */ -	movl	$start_i386boot, %ebp -	addl	$(CONFIG_SYS_BL_START_RAM - TEXT_BASE), %ebp -	call	*%ebp		/* Enter, U-boot! */ -#else -	call	start_i386boot  /* Enter, U-boot! */ -#endif +	/* stack_limit parameter */ +	pushl	%ecx +	call	board_init_f	/* Enter, U-boot! */  	/* indicate (lack of) progress */  	movw	$0x85, %ax diff --git a/cpu/ixp/start.S b/cpu/ixp/start.S index 196ba5db2..5ebce5338 100644 --- a/cpu/ixp/start.S +++ b/cpu/ixp/start.S @@ -505,8 +505,8 @@ reset_endless:  /*   * 0 <= r0 <= 2000   */ -.globl udelay -udelay: +.globl __udelay +__udelay:  	mov	r2,     #0x6800  	orr	r2, r2, #0x00db  	mul	r0, r2, r0 diff --git a/cpu/ixp/timer.c b/cpu/ixp/timer.c index 685614966..edf341ff9 100644 --- a/cpu/ixp/timer.c +++ b/cpu/ixp/timer.c @@ -99,7 +99,7 @@ void ixp425_udelay(unsigned long usec)  	while (!(*IXP425_OSST & IXP425_OSST_TIMER_1_PEND));  } -void udelay (unsigned long usec) +void __udelay (unsigned long usec)  {  	while (usec--) ixp425_udelay(1);  } diff --git a/cpu/lh7a40x/timer.c b/cpu/lh7a40x/timer.c index f9b5be010..2691315d8 100644 --- a/cpu/lh7a40x/timer.c +++ b/cpu/lh7a40x/timer.c @@ -90,7 +90,7 @@ void set_timer (ulong t)  	timestamp = t;  } -void udelay (unsigned long usec) +void __udelay (unsigned long usec)  {  	ulong tmo,tmp; diff --git a/cpu/mcf547x_8x/slicetimer.c b/cpu/mcf547x_8x/slicetimer.c index 67e81894a..8dc010a35 100644 --- a/cpu/mcf547x_8x/slicetimer.c +++ b/cpu/mcf547x_8x/slicetimer.c @@ -40,7 +40,7 @@ static ulong timestamp;  #endif  extern void dtimer_intr_setup(void); -void udelay(unsigned long usec) +void __udelay(unsigned long usec)  {  	volatile slt_t *timerp = (slt_t *) (CONFIG_SYS_UDELAY_BASE);  	u32 now, freq; diff --git a/cpu/mpc85xx/u-boot-nand.lds b/cpu/mpc85xx/u-boot-nand.lds index a0fc8f138..b4c63e2a2 100644 --- a/cpu/mpc85xx/u-boot-nand.lds +++ b/cpu/mpc85xx/u-boot-nand.lds @@ -58,7 +58,6 @@ SECTIONS    .text      :    {      *(.text) -    *(.fixup)      *(.got1)     } :text      _etext = .; diff --git a/cpu/ppc4xx/4xx_pci.c b/cpu/ppc4xx/4xx_pci.c index fa521f041..eed4534e5 100644 --- a/cpu/ppc4xx/4xx_pci.c +++ b/cpu/ppc4xx/4xx_pci.c @@ -73,23 +73,30 @@  #include <common.h>  #include <command.h> -#if !defined(CONFIG_440)  #include <asm/4xx_pci.h> -#endif  #include <asm/processor.h> +#include <asm/io.h>  #include <pci.h>  #ifdef CONFIG_PCI  DECLARE_GLOBAL_DATA_PTR; +#if defined(CONFIG_405GP) || defined(CONFIG_405EP) + +#if defined(CONFIG_PMC405) +ushort pmc405_pci_subsys_deviceid(void); +#endif + +/*#define DEBUG*/ +  /*   * Board-specific pci initialization   * Platform code can reimplement pci_pre_init() if needed   */  int __pci_pre_init(struct pci_controller *hose)  { -#if defined (CONFIG_405EP) +#if defined(CONFIG_405EP)  	/*  	 * Enable the internal PCI arbiter by default.  	 * @@ -105,15 +112,8 @@ int __pci_pre_init(struct pci_controller *hose)  	return 1;  } -int pci_pre_init(struct pci_controller *hose) __attribute__((weak, alias("__pci_pre_init"))); - -#if defined(CONFIG_405GP) || defined(CONFIG_405EP) - -#if defined(CONFIG_PMC405) -ushort pmc405_pci_subsys_deviceid(void); -#endif - -/*#define DEBUG*/ +int pci_pre_init(struct pci_controller *hose) +	__attribute__((weak, alias("__pci_pre_init")));  int __is_pci_host(struct pci_controller *hose)  { @@ -231,7 +231,7 @@ void pci_405gp_init(struct pci_controller *hose)  		pciauto_region_init(hose->pci_fb);  	/* Let board change/modify hose & do initial checks */ -	if (pci_pre_init (hose) == 0) { +	if (pci_pre_init(hose) == 0) {  		printf("PCI: Board-specific initialization failed.\n");  		printf("PCI: Configuration aborted.\n");  		return; @@ -478,6 +478,231 @@ void pci_init_board(void)  static struct pci_controller ppc440_hose = {0}; +/* + * This routine is called to determine if a pci scan should be + * performed. With various hardware environments (especially cPCI and + * PPMC) it's insufficient to depend on the state of the arbiter enable + * bit in the strap register, or generic host/adapter assumptions. + * + * Rather than hard-code a bad assumption in the general 440 code, the + * 440 pci code requires the board to decide at runtime. + * + * Return 0 for adapter mode, non-zero for host (monarch) mode. + * + * Weak default implementation: "Normal" boards implement the PCI + * host functionality. This can be overridden for PCI adapter boards. + */ +int __is_pci_host(struct pci_controller *hose) +{ +	return 1; +} +int is_pci_host(struct pci_controller *hose) +	__attribute__((weak, alias("__is_pci_host"))); + +#if defined(CONFIG_440EP) || defined(CONFIG_440EPX) || \ +    defined(CONFIG_440GR) || defined(CONFIG_440GRX) + +#if defined(CONFIG_SYS_PCI_TARGET_INIT) +/* + * pci_target_init + * + * The bootstrap configuration provides default settings for the pci + * inbound map (PIM). But the bootstrap config choices are limited and + * may not be sufficient for a given board. + */ +void __pci_target_init(struct pci_controller *hose) +{ +	/* +	 * Set up Direct MMIO registers +	 */ + +	/* +	 * PowerPC440 EP PCI Master configuration. +	 * Map one 1Gig range of PLB/processor addresses to PCI memory space. +	 * PLB address 0xA0000000-0xDFFFFFFF ==> PCI address 0xA0000000-0xDFFFFFFF +	 * Use byte reversed out routines to handle endianess. +	 * Make this region non-prefetchable. +	 */ +	/* PMM0 Mask/Attribute - disabled b4 setting */ +	out_le32((void *)PCIL0_PMM0MA, 0x00000000); +	/* PMM0 Local Address */ +	out_le32((void *)PCIL0_PMM0LA, CONFIG_SYS_PCI_MEMBASE); +	/* PMM0 PCI Low Address */ +	out_le32((void *)PCIL0_PMM0PCILA, CONFIG_SYS_PCI_MEMBASE); +	/* PMM0 PCI High Address */ +	out_le32((void *)PCIL0_PMM0PCIHA, 0x00000000); +	/* 512M + No prefetching, and enable region */ +	out_le32((void *)PCIL0_PMM0MA, 0xE0000001); + +	/* PMM1 Mask/Attribute - disabled b4 setting */ +	out_le32((void *)PCIL0_PMM1MA, 0x00000000); +	/* PMM1 Local Address */ +	out_le32((void *)PCIL0_PMM1LA, CONFIG_SYS_PCI_MEMBASE2); +	/* PMM1 PCI Low Address */ +	out_le32((void *)PCIL0_PMM1PCILA, CONFIG_SYS_PCI_MEMBASE2); +	/* PMM1 PCI High Address */ +	out_le32((void *)PCIL0_PMM1PCIHA, 0x00000000); +	/* 512M + No prefetching, and enable region */ +	out_le32((void *)PCIL0_PMM1MA, 0xE0000001); + +	out_le32((void *)PCIL0_PTM1MS, 0x00000001); /* Memory Size/Attribute */ +	out_le32((void *)PCIL0_PTM1LA, 0);	/* Local Addr. Reg */ +	out_le32((void *)PCIL0_PTM2MS, 0);	/* Memory Size/Attribute */ +	out_le32((void *)PCIL0_PTM2LA, 0);	/* Local Addr. Reg */ + +	/* +	 * Set up Configuration registers +	 */ + +	/* Program the board's subsystem id/vendor id */ +	pci_write_config_word(0, PCI_SUBSYSTEM_VENDOR_ID, +			      CONFIG_SYS_PCI_SUBSYS_VENDORID); +	pci_write_config_word(0, PCI_SUBSYSTEM_ID, CONFIG_SYS_PCI_SUBSYS_ID); + +	/* Configure command register as bus master */ +	pci_write_config_word(0, PCI_COMMAND, PCI_COMMAND_MASTER); + +	/* 240nS PCI clock */ +	pci_write_config_word(0, PCI_LATENCY_TIMER, 1); + +	/* No error reporting */ +	pci_write_config_word(0, PCI_ERREN, 0); + +	pci_write_config_dword(0, PCI_BRDGOPT2, 0x00000101); +} +#endif /* CONFIG_SYS_PCI_TARGET_INIT */ + +/* + * pci_pre_init + * + * This routine is called just prior to registering the hose and gives + * the board the opportunity to check things. Returning a value of zero + * indicates that things are bad & PCI initialization should be aborted. + * + * Different boards may wish to customize the pci controller structure + * (add regions, override default access routines, etc) or perform + * certain pre-initialization actions. + * + */ +int __pci_pre_init(struct pci_controller *hose) +{ +	u32 reg; + +	/* +	 * Set priority for all PLB3 devices to 0. +	 * Set PLB3 arbiter to fair mode. +	 */ +	mfsdr(SD0_AMP1, reg); +	mtsdr(SD0_AMP1, (reg & 0x000000FF) | 0x0000FF00); +	reg = mfdcr(PLB3_ACR); +	mtdcr(PLB3_ACR, reg | 0x80000000); + +	/* +	 * Set priority for all PLB4 devices to 0. +	 */ +	mfsdr(SD0_AMP0, reg); +	mtsdr(SD0_AMP0, (reg & 0x000000FF) | 0x0000FF00); +	reg = mfdcr(PLB4_ACR) | 0xa0000000; +	mtdcr(PLB4_ACR, reg); + +	/* +	 * Set Nebula PLB4 arbiter to fair mode. +	 */ +	/* Segment0 */ +	reg = (mfdcr(PLB0_ACR) & ~PLB0_ACR_PPM_MASK) | PLB0_ACR_PPM_FAIR; +	reg = (reg & ~PLB0_ACR_HBU_MASK) | PLB0_ACR_HBU_ENABLED; +	reg = (reg & ~PLB0_ACR_RDP_MASK) | PLB0_ACR_RDP_4DEEP; +	reg = (reg & ~PLB0_ACR_WRP_MASK) | PLB0_ACR_WRP_2DEEP; +	mtdcr(PLB0_ACR, reg); + +	/* Segment1 */ +	reg = (mfdcr(PLB1_ACR) & ~PLB1_ACR_PPM_MASK) | PLB1_ACR_PPM_FAIR; +	reg = (reg & ~PLB1_ACR_HBU_MASK) | PLB1_ACR_HBU_ENABLED; +	reg = (reg & ~PLB1_ACR_RDP_MASK) | PLB1_ACR_RDP_4DEEP; +	reg = (reg & ~PLB1_ACR_WRP_MASK) | PLB1_ACR_WRP_2DEEP; +	mtdcr(PLB1_ACR, reg); + +#if defined(CONFIG_SYS_PCI_BOARD_FIXUP_IRQ) +	hose->fixup_irq = board_pci_fixup_irq; +#endif + +	return 1; +} + +#else /* defined(CONFIG_440EP) ... */ + +#if defined(CONFIG_SYS_PCI_TARGET_INIT) +void __pci_target_init(struct pci_controller * hose) +{ +	/* +	 * Disable everything +	 */ +	out_le32((void *)PCIL0_PIM0SA, 0); /* disable */ +	out_le32((void *)PCIL0_PIM1SA, 0); /* disable */ +	out_le32((void *)PCIL0_PIM2SA, 0); /* disable */ +	out_le32((void *)PCIL0_EROMBA, 0); /* disable expansion rom */ + +	/* +	 * Map all of SDRAM to PCI address 0x0000_0000. Note that the 440 +	 * strapping options do not support sizes such as 128/256 MB. +	 */ +	out_le32((void *)PCIL0_PIM0LAL, CONFIG_SYS_SDRAM_BASE); +	out_le32((void *)PCIL0_PIM0LAH, 0); +	out_le32((void *)PCIL0_PIM0SA, ~(gd->ram_size - 1) | 1); +	out_le32((void *)PCIL0_BAR0, 0); + +	/* +	 * Program the board's subsystem id/vendor id +	 */ +	out_le16((void *)PCIL0_SBSYSVID, CONFIG_SYS_PCI_SUBSYS_VENDORID); +	out_le16((void *)PCIL0_SBSYSID, CONFIG_SYS_PCI_SUBSYS_DEVICEID); + +	out_le16((void *)PCIL0_CMD, in_le16((void *)PCIL0_CMD) | +		 PCI_COMMAND_MEMORY); +} +#endif /* CONFIG_SYS_PCI_TARGET_INIT */ + +int __pci_pre_init(struct pci_controller *hose) +{ +	/* +	 * This board is always configured as the host & requires the +	 * PCI arbiter to be enabled. +	 */ +	if (!pci_arbiter_enabled()) { +		printf("PCI: PCI Arbiter disabled!\n"); +		return 0; +	} + +	return 1; +} + +#endif /* defined(CONFIG_440EP) ... */ + +#if defined(CONFIG_SYS_PCI_TARGET_INIT) +void pci_target_init(struct pci_controller * hose) +	__attribute__((weak, alias("__pci_target_init"))); +#endif /* CONFIG_SYS_PCI_TARGET_INIT */ + +int pci_pre_init(struct pci_controller *hose) +	__attribute__((weak, alias("__pci_pre_init"))); + +#if defined(CONFIG_SYS_PCI_MASTER_INIT) +void __pci_master_init(struct pci_controller *hose) +{ +	u16 reg; + +	/* +	 * Write the PowerPC440 EP PCI Configuration regs. +	 * Enable PowerPC440 EP to be a master on the PCI bus (PMM). +	 * Enable PowerPC440 EP to act as a PCI memory target (PTM). +	 */ +	pci_read_config_word(0, PCI_COMMAND, ®); +	pci_write_config_word(0, PCI_COMMAND, reg | +			      PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY); +} +void pci_master_init(struct pci_controller *hose) +	__attribute__((weak, alias("__pci_master_init"))); +#endif /* CONFIG_SYS_PCI_MASTER_INIT */  int pci_440_init (struct pci_controller *hose)  { @@ -548,7 +773,7 @@ int pci_440_init (struct pci_controller *hose)  	pci_setup_indirect(hose, PCIL0_CFGADR, PCIL0_CFGDATA);  	/* Let board change/modify hose & do initial checks */ -	if (pci_pre_init (hose) == 0) { +	if (pci_pre_init(hose) == 0) {  		printf("PCI: Board-specific initialization failed.\n");  		printf("PCI: Configuration aborted.\n");  		return -1; diff --git a/cpu/ppc4xx/4xx_pcie.c b/cpu/ppc4xx/4xx_pcie.c index 19d2c7dd2..d9605c30b 100644 --- a/cpu/ppc4xx/4xx_pcie.c +++ b/cpu/ppc4xx/4xx_pcie.c @@ -48,6 +48,125 @@ enum {  	LNKW_X8			= 0x8  }; +static struct pci_controller pcie_hose[CONFIG_SYS_PCIE_NR_PORTS]; + +/* + * Per default, all cards are present, so we need to check if the + * link comes up. + */ +int __board_pcie_card_present(int port) +{ +	return 1; +} +int board_pcie_card_present(int port) +	__attribute__((weak, alias("__board_pcie_card_present"))); + +/* + * Some boards have runtime detection of the first and last PCIe + * slot used, so let's provide weak default functions for the + * common version. + */ +int __board_pcie_first(void) +{ +	return 0; +} +int board_pcie_first(void) +	__attribute__((weak, alias("__board_pcie_first"))); + +int __board_pcie_last(void) +{ +	return CONFIG_SYS_PCIE_NR_PORTS - 1; +} +int board_pcie_last(void) +	__attribute__((weak, alias("__board_pcie_last"))); + +void __board_pcie_setup_port(int port, int rootpoint) +{ +	/* noting in this weak default implementation */ +} +void board_pcie_setup_port(int port, int rootpoint) +	__attribute__((weak, alias("__board_pcie_setup_port"))); + +void pcie_setup_hoses(int busno) +{ +	struct pci_controller *hose; +	int i, bus; +	int ret = 0; +	char *env; +	unsigned int delay; +	int first = board_pcie_first(); +	int last = board_pcie_last(); + +	/* +	 * Assume we're called after the PCI(X) hose(s) are initialized, +	 * which takes bus ID 0... and therefore start numbering PCIe's +	 * from the next number. +	 */ +	bus = busno; + +	for (i = first; i <= last; i++) { +		/* +		 * Some boards (e.g. Katmai) can detects via hardware +		 * if a PCIe card is plugged, so let's check this. +		 */ +		if (!board_pcie_card_present(i)) +			continue; + +		if (is_end_point(i)) { +			board_pcie_setup_port(i, 0); +			ret = ppc4xx_init_pcie_endport(i); +		} else { +			board_pcie_setup_port(i, 1); +			ret = ppc4xx_init_pcie_rootport(i); +		} +		if (ret == -ENODEV) +			continue; +		if (ret) { +			printf("PCIE%d: initialization as %s failed\n", i, +			       is_end_point(i) ? "endpoint" : "root-complex"); +			continue; +		} + +		hose = &pcie_hose[i]; +		hose->first_busno = bus; +		hose->last_busno = bus; +		hose->current_busno = bus; + +		/* setup mem resource */ +		pci_set_region(hose->regions + 0, +			       CONFIG_SYS_PCIE_MEMBASE + i * CONFIG_SYS_PCIE_MEMSIZE, +			       CONFIG_SYS_PCIE_MEMBASE + i * CONFIG_SYS_PCIE_MEMSIZE, +			       CONFIG_SYS_PCIE_MEMSIZE, +			       PCI_REGION_MEM); +		hose->region_count = 1; +		pci_register_hose(hose); + +		if (is_end_point(i)) { +			ppc4xx_setup_pcie_endpoint(hose, i); +			/* +			 * Reson for no scanning is endpoint can not generate +			 * upstream configuration accesses. +			 */ +		} else { +			ppc4xx_setup_pcie_rootpoint(hose, i); +			env = getenv ("pciscandelay"); +			if (env != NULL) { +				delay = simple_strtoul(env, NULL, 10); +				if (delay > 5) +					printf("Warning, expect noticable delay before " +					       "PCIe scan due to 'pciscandelay' value!\n"); +				mdelay(delay * 1000); +			} + +			/* +			 * Config access can only go down stream +			 */ +			hose->last_busno = pci_hose_scan(hose); +			bus = hose->last_busno + 1; +		} +	} +} +  static int validate_endpoint(struct pci_controller *hose)  {  	if (hose->cfg_data == (u8 *)CONFIG_SYS_PCIE0_CFGBASE) diff --git a/cpu/ppc4xx/cmd_chip_config.c b/cpu/ppc4xx/cmd_chip_config.c index d360d5bee..ba57211dd 100644 --- a/cpu/ppc4xx/cmd_chip_config.c +++ b/cpu/ppc4xx/cmd_chip_config.c @@ -52,6 +52,12 @@ static int do_chip_config(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  	int cur_config_nr = -1;  	u8 cur_config[CONFIG_4xx_CONFIG_BLOCKSIZE]; +	/* +	 * First switch to correct I2C bus. This is I2C bus 0 +	 * for all currently available 4xx derivats. +	 */ +	I2C_SET_BUS(0); +  #ifdef CONFIG_CMD_EEPROM  	ret = eeprom_read(CONFIG_4xx_CONFIG_I2C_EEPROM_ADDR,  			  CONFIG_4xx_CONFIG_I2C_EEPROM_OFFSET, diff --git a/cpu/ppc4xx/config.mk b/cpu/ppc4xx/config.mk index 00ad39b60..979004b7d 100644 --- a/cpu/ppc4xx/config.mk +++ b/cpu/ppc4xx/config.mk @@ -32,3 +32,6 @@ PLATFORM_CPPFLAGS += -Wa,-m440 -mcpu=440  else  PLATFORM_CPPFLAGS += -Wa,-m405 -mcpu=405  endif + +# Use default linker script.  Board port can override in board/*/config.mk +LDSCRIPT := $(SRCTREE)/cpu/ppc4xx/u-boot.lds diff --git a/cpu/ppc4xx/cpu.c b/cpu/ppc4xx/cpu.c index e1b00a74c..73d4d06af 100644 --- a/cpu/ppc4xx/cpu.c +++ b/cpu/ppc4xx/cpu.c @@ -81,7 +81,7 @@ static int pci_async_enabled(void)  #if defined(CONFIG_PCI) && !defined(CONFIG_IOP480) && \      !defined(CONFIG_405) && !defined(CONFIG_405EX) -static int pci_arbiter_enabled(void) +int pci_arbiter_enabled(void)  {  #if defined(CONFIG_405GP)  	return (mfdcr(CPC0_PSR) & PSR_PCI_ARBIT_EN); diff --git a/cpu/ppc4xx/i2c.c b/cpu/ppc4xx/i2c.c index e3e1bab64..7976e75e0 100644 --- a/cpu/ppc4xx/i2c.c +++ b/cpu/ppc4xx/i2c.c @@ -1,5 +1,5 @@  /* - * (C) Copyright 2007 + * (C) Copyright 2007-2009   * Stefan Roese, DENX Software Engineering, sr@denx.de.   *   * based on work by Anne Sophie Harnois <anne-sophie.harnois@nextream.fr> @@ -37,7 +37,8 @@  DECLARE_GLOBAL_DATA_PTR;  #if defined(CONFIG_I2C_MULTI_BUS) -/* Initialize the bus pointer to whatever one the SPD EEPROM is on. +/* + * Initialize the bus pointer to whatever one the SPD EEPROM is on.   * Default is bus 0.  This is necessary because the DDR initialization   * runs from ROM, and we can't switch buses because we can't modify   * the global variables. @@ -45,59 +46,63 @@ DECLARE_GLOBAL_DATA_PTR;  #ifndef CONFIG_SYS_SPD_BUS_NUM  #define CONFIG_SYS_SPD_BUS_NUM	0  #endif -static unsigned int i2c_bus_num __attribute__ ((section (".data"))) = CONFIG_SYS_SPD_BUS_NUM; +static unsigned int i2c_bus_num __attribute__ ((section (".data"))) = +	CONFIG_SYS_SPD_BUS_NUM;  #endif /* CONFIG_I2C_MULTI_BUS */  static void _i2c_bus_reset(void)  { +	struct ppc4xx_i2c *i2c = (struct ppc4xx_i2c *)I2C_BASE_ADDR;  	int i;  	u8 dc;  	/* Reset status register */  	/* write 1 in SCMP and IRQA to clear these fields */ -	out_8((u8 *)IIC_STS, 0x0A); +	out_8(&i2c->sts, 0x0A);  	/* write 1 in IRQP IRQD LA ICT XFRA to clear these fields */ -	out_8((u8 *)IIC_EXTSTS, 0x8F); +	out_8(&i2c->extsts, 0x8F);  	/* Place chip in the reset state */ -	out_8((u8 *)IIC_XTCNTLSS, IIC_XTCNTLSS_SRST); +	out_8(&i2c->xtcntlss, IIC_XTCNTLSS_SRST);  	/* Check if bus is free */ -	dc = in_8((u8 *)IIC_DIRECTCNTL); +	dc = in_8(&i2c->directcntl);  	if (!DIRCTNL_FREE(dc)){  		/* Try to set bus free state */ -		out_8((u8 *)IIC_DIRECTCNTL, IIC_DIRCNTL_SDAC | IIC_DIRCNTL_SCC); +		out_8(&i2c->directcntl, IIC_DIRCNTL_SDAC | IIC_DIRCNTL_SCC);  		/* Wait until we regain bus control */  		for (i = 0; i < 100; ++i) { -			dc = in_8((u8 *)IIC_DIRECTCNTL); +			dc = in_8(&i2c->directcntl);  			if (DIRCTNL_FREE(dc))  				break;  			/* Toggle SCL line */  			dc ^= IIC_DIRCNTL_SCC; -			out_8((u8 *)IIC_DIRECTCNTL, dc); +			out_8(&i2c->directcntl, dc);  			udelay(10);  			dc ^= IIC_DIRCNTL_SCC; -			out_8((u8 *)IIC_DIRECTCNTL, dc); +			out_8(&i2c->directcntl, dc);  		}  	}  	/* Remove reset */ -	out_8((u8 *)IIC_XTCNTLSS, 0); +	out_8(&i2c->xtcntlss, 0);  } -void i2c_init(int speed, int slaveadd) +void i2c_init(int speed, int slaveaddr)  { -	unsigned long freqOPB; +	struct ppc4xx_i2c *i2c = (struct ppc4xx_i2c *)I2C_BASE_ADDR;  	int val, divisor;  	int bus;  #ifdef CONFIG_SYS_I2C_INIT_BOARD -	/* call board specific i2c bus reset routine before accessing the   */ -	/* environment, which might be in a chip on that bus. For details   */ -	/* about this problem see doc/I2C_Edge_Conditions.                  */ +	/* +	 * Call board specific i2c bus reset routine before accessing the +	 * environment, which might be in a chip on that bus. For details +	 * about this problem see doc/I2C_Edge_Conditions. +	 */  	i2c_init_board();  #endif @@ -109,54 +114,52 @@ void i2c_init(int speed, int slaveadd)  		_i2c_bus_reset();  		/* clear lo master address */ -		out_8((u8 *)IIC_LMADR, 0); +		out_8(&i2c->lmadr, 0);  		/* clear hi master address */ -		out_8((u8 *)IIC_HMADR, 0); +		out_8(&i2c->hmadr, 0);  		/* clear lo slave address */ -		out_8((u8 *)IIC_LSADR, 0); +		out_8(&i2c->lsadr, 0);  		/* clear hi slave address */ -		out_8((u8 *)IIC_HSADR, 0); +		out_8(&i2c->hsadr, 0);  		/* Clock divide Register */ -		/* get OPB frequency */ -		freqOPB = get_OPB_freq(); -		/* set divisor according to freqOPB */ -		divisor = (freqOPB - 1) / 10000000; +		/* set divisor according to freq_opb */ +		divisor = (get_OPB_freq() - 1) / 10000000;  		if (divisor == 0)  			divisor = 1; -		out_8((u8 *)IIC_CLKDIV, divisor); +		out_8(&i2c->clkdiv, divisor);  		/* no interrupts */ -		out_8((u8 *)IIC_INTRMSK, 0); +		out_8(&i2c->intrmsk, 0);  		/* clear transfer count */ -		out_8((u8 *)IIC_XFRCNT, 0); +		out_8(&i2c->xfrcnt, 0);  		/* clear extended control & stat */  		/* write 1 in SRC SRS SWC SWS to clear these fields */ -		out_8((u8 *)IIC_XTCNTLSS, 0xF0); +		out_8(&i2c->xtcntlss, 0xF0);  		/* Mode Control Register  		   Flush Slave/Master data buffer */ -		out_8((u8 *)IIC_MDCNTL, IIC_MDCNTL_FSDB | IIC_MDCNTL_FMDB); +		out_8(&i2c->mdcntl, IIC_MDCNTL_FSDB | IIC_MDCNTL_FMDB); -		val = in_8((u8 *)IIC_MDCNTL); +		val = in_8(&i2c->mdcntl);  		/* Ignore General Call, slave transfers are ignored,  		 * disable interrupts, exit unknown bus state, enable hold  		 * SCL 100kHz normaly or FastMode for 400kHz and above  		 */ -		val |= IIC_MDCNTL_EUBS|IIC_MDCNTL_HSCL; +		val |= IIC_MDCNTL_EUBS | IIC_MDCNTL_HSCL;  		if (speed >= 400000)  			val |= IIC_MDCNTL_FSM; -		out_8((u8 *)IIC_MDCNTL, val); +		out_8(&i2c->mdcntl, val);  		/* clear control reg */ -		out_8((u8 *)IIC_CNTL, 0x00); +		out_8(&i2c->cntl, 0x00);  	}  	/* set to SPD bus as default bus upon powerup */ @@ -195,13 +198,14 @@ static int i2c_transfer(unsigned char cmd_type,  			unsigned char data[],  			unsigned short data_len)  { -	unsigned char* ptr; +	struct ppc4xx_i2c *i2c = (struct ppc4xx_i2c *)I2C_BASE_ADDR; +	u8 *ptr;  	int reading; -	int tran,cnt; +	int tran, cnt;  	int result;  	int status;  	int i; -	uchar creg; +	u8 creg;  	if (data == 0 || data_len == 0) {  		/* Don't support data transfer of no length or to address 0 */ @@ -219,12 +223,13 @@ static int i2c_transfer(unsigned char cmd_type,  	}  	/* Clear Stop Complete Bit */ -	out_8((u8 *)IIC_STS, IIC_STS_SCMP); +	out_8(&i2c->sts, IIC_STS_SCMP); +  	/* Check init */  	i = 10;  	do {  		/* Get status */ -		status = in_8((u8 *)IIC_STS); +		status = in_8(&i2c->sts);  		i--;  	} while ((status & IIC_STS_PT) && (i > 0)); @@ -232,13 +237,16 @@ static int i2c_transfer(unsigned char cmd_type,  		result = IIC_NOK_TOUT;  		return(result);  	} +  	/* flush the Master/Slave Databuffers */ -	out_8((u8 *)IIC_MDCNTL, ((in_8((u8 *)IIC_MDCNTL))|IIC_MDCNTL_FMDB|IIC_MDCNTL_FSDB)); +	out_8(&i2c->mdcntl, in_8(&i2c->mdcntl) | +	      IIC_MDCNTL_FMDB | IIC_MDCNTL_FSDB); +  	/* need to wait 4 OPB clocks? code below should take that long */  	/* 7-bit adressing */ -	out_8((u8 *)IIC_HMADR, 0); -	out_8((u8 *)IIC_LMADR, chip); +	out_8(&i2c->hmadr, 0); +	out_8(&i2c->lmadr, chip);  	tran = 0;  	result = IIC_OK; @@ -247,9 +255,10 @@ static int i2c_transfer(unsigned char cmd_type,  	while (tran != cnt && (result == IIC_OK)) {  		int  bc,j; -		/* Control register = -		 * Normal transfer, 7-bits adressing, Transfer up to bc bytes, Normal start, -		 * Transfer is a sequence of transfers +		/* +		 * Control register = +		 * Normal transfer, 7-bits adressing, Transfer up to +		 * bc bytes, Normal start, Transfer is a sequence of transfers  		 */  		creg |= IIC_CNTL_PT; @@ -259,32 +268,36 @@ static int i2c_transfer(unsigned char cmd_type,  		if ((!cmd_type && (ptr == addr)) || ((tran + bc) != cnt))  			creg |= IIC_CNTL_CHT; -		if (reading) +		if (reading) {  			creg |= IIC_CNTL_READ; -		else -			for(j=0; j < bc; j++) +		} else { +			for(j = 0; j < bc; j++) {  				/* Set buffer */ -				out_8((u8 *)IIC_MDBUF, ptr[tran+j]); -		out_8((u8 *)IIC_CNTL, creg); +				out_8(&i2c->mdbuf, ptr[tran + j]); +			} +		} +		out_8(&i2c->cntl, creg); -		/* Transfer is in progress +		/* +		 * Transfer is in progress  		 * we have to wait for upto 5 bytes of data  		 * 1 byte chip address+r/w bit then bc bytes  		 * of data.  		 * udelay(10) is 1 bit time at 100khz  		 * Doubled for slop. 20 is too small.  		 */ -		i = 2*5*8; +		i = 2 * 5 * 8;  		do {  			/* Get status */ -			status = in_8((u8 *)IIC_STS); +			status = in_8(&i2c->sts);  			udelay(10);  			i--; -		} while ((status & IIC_STS_PT) && !(status & IIC_STS_ERR) && (i > 0)); +		} while ((status & IIC_STS_PT) && !(status & IIC_STS_ERR) && +			 (i > 0));  		if (status & IIC_STS_ERR) {  			result = IIC_NOK; -			status = in_8((u8 *)IIC_EXTSTS); +			status = in_8(&i2c->extsts);  			/* Lost arbitration? */  			if (status & IIC_EXTSTS_LA)  				result = IIC_NOK_LA; @@ -297,19 +310,21 @@ static int i2c_transfer(unsigned char cmd_type,  		} else if ( status & IIC_STS_PT) {  			result = IIC_NOK_TOUT;  		} +  		/* Command is reading => get buffer */  		if ((reading) && (result == IIC_OK)) {  			/* Are there data in buffer */  			if (status & IIC_STS_MDBS) {  				/* -				 * even if we have data we have to wait 4OPB clocks -				 * for it to hit the front of the FIFO, after that -				 * we can just read. We should check XFCNT here and -				 * if the FIFO is full there is no need to wait. +				 * even if we have data we have to wait 4OPB +				 * clocks for it to hit the front of the FIFO, +				 * after that we can just read. We should check +				 * XFCNT here and if the FIFO is full there is +				 * no need to wait.  				 */  				udelay(1); -				for (j=0; j<bc; j++) -					ptr[tran+j] = in_8((u8 *)IIC_MDBUF); +				for (j = 0; j < bc; j++) +					ptr[tran + j] = in_8(&i2c->mdbuf);  			} else  				result = IIC_NOK_DATA;  		} @@ -324,7 +339,7 @@ static int i2c_transfer(unsigned char cmd_type,  				creg = IIC_CNTL_RPST;  		}  	} -	return (result); +	return result;  }  int i2c_probe(uchar chip) @@ -338,17 +353,17 @@ int i2c_probe(uchar chip)  	 * address was <ACK>ed (i.e. there was a chip at that address which  	 * drove the data line low).  	 */ -	return (i2c_transfer(1, chip << 1, 0,0, buf, 1) != 0); +	return (i2c_transfer(1, chip << 1, 0, 0, buf, 1) != 0);  } - -int i2c_read(uchar chip, uint addr, int alen, uchar * buffer, int len) +static int ppc4xx_i2c_transfer(uchar chip, uint addr, int alen, uchar *buffer, +			       int len, int read)  {  	uchar xaddr[4];  	int ret;  	if (alen > 4) { -		printf ("I2C read: addr len %d not supported\n", alen); +		printf("I2C: addr len %d not supported\n", alen);  		return 1;  	} @@ -373,50 +388,30 @@ int i2c_read(uchar chip, uint addr, int alen, uchar * buffer, int len)  	 * hidden in the chip address.  	 */  	if (alen > 0) -		chip |= ((addr >> (alen * 8)) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW); +		chip |= ((addr >> (alen * 8)) & +			 CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);  #endif -	if ((ret = i2c_transfer(1, chip<<1, &xaddr[4-alen], alen, buffer, len)) != 0) { -		if (gd->have_console) -			printf( "I2c read: failed %d\n", ret); +	if ((ret = i2c_transfer(read, chip << 1, &xaddr[4 - alen], alen, +				buffer, len)) != 0) { +		if (gd->have_console) { +			printf("I2C %s: failed %d\n", +			       read ? "read" : "write", ret); +		} +  		return 1;  	} +  	return 0;  } -int i2c_write(uchar chip, uint addr, int alen, uchar * buffer, int len) +int i2c_read(uchar chip, uint addr, int alen, uchar * buffer, int len)  { -	uchar xaddr[4]; - -	if (alen > 4) { -		printf ("I2C write: addr len %d not supported\n", alen); -		return 1; - -	} - -	if (alen > 0) { -		xaddr[0] = (addr >> 24) & 0xFF; -		xaddr[1] = (addr >> 16) & 0xFF; -		xaddr[2] = (addr >> 8) & 0xFF; -		xaddr[3] = addr & 0xFF; -	} - -#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW -	/* -	 * EEPROM chips that implement "address overflow" are ones -	 * like Catalyst 24WC04/08/16 which has 9/10/11 bits of -	 * address and the extra bits end up in the "chip address" -	 * bit slots. This makes a 24WC08 (1Kbyte) chip look like -	 * four 256 byte chips. -	 * -	 * Note that we consider the length of the address field to -	 * still be one byte because the extra address bits are -	 * hidden in the chip address. -	 */ -	if (alen > 0) -		chip |= ((addr >> (alen * 8)) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW); -#endif +	return ppc4xx_i2c_transfer(chip, addr, alen, buffer, len, 1); +} -	return (i2c_transfer(0, chip<<1, &xaddr[4-alen], alen, buffer, len ) != 0); +int i2c_write(uchar chip, uint addr, int alen, uchar * buffer, int len) +{ +	return ppc4xx_i2c_transfer(chip, addr, alen, buffer, len, 0);  }  #if defined(CONFIG_I2C_MULTI_BUS) diff --git a/cpu/ppc4xx/u-boot.lds b/cpu/ppc4xx/u-boot.lds new file mode 100644 index 000000000..2b47934a2 --- /dev/null +++ b/cpu/ppc4xx/u-boot.lds @@ -0,0 +1,169 @@ +/* + * Copyright 2007-2009 Freescale Semiconductor, Inc. + * + * 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"	/* CONFIG_BOARDDIR */ + +#ifndef RESET_VECTOR_ADDRESS +#define RESET_VECTOR_ADDRESS	0xfffffffc +#endif + +OUTPUT_ARCH(powerpc) +/* Do we need any of these for elf? +   __DYNAMIC = 0;    */ +PHDRS +{ +  text PT_LOAD; +  bss PT_LOAD; +} + +SECTIONS +{ +  /* Read-only sections, merged into text segment: */ +  . = + SIZEOF_HEADERS; +  .interp : { *(.interp) } +  .hash          : { *(.hash)		} +  .dynsym        : { *(.dynsym)		} +  .dynstr        : { *(.dynstr)		} +  .rel.text      : { *(.rel.text)		} +  .rela.text     : { *(.rela.text)	} +  .rel.data      : { *(.rel.data)		} +  .rela.data     : { *(.rela.data)	} +  .rel.rodata    : { *(.rel.rodata)	} +  .rela.rodata   : { *(.rela.rodata)	} +  .rel.got       : { *(.rel.got)		} +  .rela.got      : { *(.rela.got)		} +  .rel.ctors     : { *(.rel.ctors)	} +  .rela.ctors    : { *(.rela.ctors)	} +  .rel.dtors     : { *(.rel.dtors)	} +  .rela.dtors    : { *(.rela.dtors)	} +  .rel.bss       : { *(.rel.bss)		} +  .rela.bss      : { *(.rela.bss)		} +  .rel.plt       : { *(.rel.plt)		} +  .rela.plt      : { *(.rela.plt)		} +  .init          : { *(.init)	} +  .plt : { *(.plt) } +  .text      : +  { +    *(.text) +    *(.got1) +   } :text +    _etext = .; +    PROVIDE (etext = .); +    .rodata    : +   { +    *(.eh_frame) +    *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) +  } :text +  .fini      : { *(.fini)    } =0 +  .ctors     : { *(.ctors)   } +  .dtors     : { *(.dtors)   } + +  /* Read-write section, merged into data segment: */ +  . = (. + 0x00FF) & 0xFFFFFF00; +  _erotext = .; +  PROVIDE (erotext = .); +  .reloc   : +  { +    *(.got) +    _GOT2_TABLE_ = .; +    *(.got2) +    _FIXUP_TABLE_ = .; +    *(.fixup) +  } +  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2; +  __fixup_entries = (. - _FIXUP_TABLE_) >> 2; + +  .data    : +  { +    *(.data) +    *(.data1) +    *(.sdata) +    *(.sdata2) +    *(.dynamic) +    CONSTRUCTORS +  } +  _edata  =  .; +  PROVIDE (edata = .); + +  . = .; +  __u_boot_cmd_start = .; +  .u_boot_cmd : { *(.u_boot_cmd) } +  __u_boot_cmd_end = .; + +  . = .; +  __start___ex_table = .; +  __ex_table : { *(__ex_table) } +  __stop___ex_table = .; + +  . = ALIGN(256); +  __init_begin = .; +  .text.init : { *(.text.init) } +  .data.init : { *(.data.init) } +  . = ALIGN(256); +  __init_end = .; + +#ifdef CONFIG_440 +  .bootpg RESET_VECTOR_ADDRESS - 0xffc : +  { +    cpu/ppc4xx/start.o	(.bootpg) + +    /* +     * PPC440 board need a board specific object with the +     * TLB definitions. This needs to get included right after +     * start.o, since the first shadow TLB only covers 4k +     * of address space. +     */ +    CONFIG_BOARDDIR/init.o	(.bootpg) +  } :text = 0xffff +#endif + +  .resetvec RESET_VECTOR_ADDRESS : +  { +    *(.resetvec) +  } :text = 0xffff + +  . = RESET_VECTOR_ADDRESS + 0x4; + +  /* +   * Make sure that the bss segment isn't linked at 0x0, otherwise its +   * address won't be updated during relocation fixups.  Note that +   * this is a temporary fix.  Code to dynamically the fixup the bss +   * location will be added in the future.  When the bss relocation +   * fixup code is present this workaround should be removed. +   */ +#if (RESET_VECTOR_ADDRESS == 0xfffffffc) +  . |= 0x10; +#endif + +  __bss_start = .; +  .bss (NOLOAD)       : +  { +   *(.sbss) *(.scommon) +   *(.dynbss) +   *(.bss) +   *(COMMON) +  } :bss + +  . = ALIGN(4); +  _end = . ; +  PROVIDE (end = .); +} diff --git a/cpu/pxa/timer.c b/cpu/pxa/timer.c index e2df3a57f..8d0f82679 100644 --- a/cpu/pxa/timer.c +++ b/cpu/pxa/timer.c @@ -78,7 +78,7 @@ void set_timer (ulong t)  	/* nop */  } -void udelay (unsigned long usec) +void __udelay (unsigned long usec)  {  	udelay_masked (usec);  } diff --git a/cpu/s3c44b0/timer.c b/cpu/s3c44b0/timer.c index 34184abb7..6f1d8f677 100644 --- a/cpu/s3c44b0/timer.c +++ b/cpu/s3c44b0/timer.c @@ -75,7 +75,7 @@ void set_timer (ulong t)  	timestamp = t;  } -void udelay (unsigned long usec) +void __udelay (unsigned long usec)  {  	ulong tmo; diff --git a/cpu/sa1100/timer.c b/cpu/sa1100/timer.c index 3f77e815c..020750125 100644 --- a/cpu/sa1100/timer.c +++ b/cpu/sa1100/timer.c @@ -49,7 +49,7 @@ void set_timer (ulong t)  	/* nop */  } -void udelay (unsigned long usec) +void __udelay (unsigned long usec)  {  	udelay_masked (usec);  } |