diff options
author | Wolfgang Denk <wd@denx.de> | 2009-12-15 23:38:34 +0100 |
---|---|---|
committer | Wolfgang Denk <wd@denx.de> | 2009-12-15 23:38:34 +0100 |
commit | bb3bcfa2426cc6a0aecec7270e3ee67ca843a125 (patch) | |
tree | 0314e3d8e8d9e4d568a496fca27db33d66e68bb4 /cpu | |
parent | a200a7c04d89853d2a1395b96d8ca5e3dd754551 (diff) | |
parent | 4b142febff71eabdb7ddbb125c7b583b24ddc434 (diff) | |
download | u-boot-imx-bb3bcfa2426cc6a0aecec7270e3ee67ca843a125.zip u-boot-imx-bb3bcfa2426cc6a0aecec7270e3ee67ca843a125.tar.gz u-boot-imx-bb3bcfa2426cc6a0aecec7270e3ee67ca843a125.tar.bz2 |
Merge branch 'next' of ../next
Diffstat (limited to 'cpu')
64 files changed, 1560 insertions, 613 deletions
diff --git a/cpu/arm1136/mx31/timer.c b/cpu/arm1136/mx31/timer.c index 29b484e..7972ba0 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 8dd8d7b..6754749 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 d1a3327..2c0014f 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 32bb467..df88cba 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 315b13f..eae572e 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 5c335a5..11962ac 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 22a5b77..9768319 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 cb891df..68a356d 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 91d552c..eb8d425 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 0000000..f030c53 --- /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 0000000..7646537 --- /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 0000000..12ca527 --- /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 0000000..bb65593 --- /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 235d107..9c54bbe 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 31ec588..b06b518 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 22987bc..886e370 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 9148946..879fda6 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 136c779..b13283a 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 a27f0e2..7d47354 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(); @@ -227,6 +220,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 b5ba8c4..e468ed0 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 7672e4c..5aa8d64 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 114427a..779f192 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 c16ef25..7dfe2b5 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 811bb3c..7352b5c 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 390cab8..fc3551c 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 5bb972f..8273a7f 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 80751ad..9da7443 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 817ff42..2ec6a93 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 9011058..8f1d47b 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 16067c9..047b9e3 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 392b158..2ac38c4 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 50c1335..563db36 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 8b8cd6d..dfb7e4c 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 31b2003..08fb32e 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 12a16b3..401bfe6 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 cdba5d9..c5df5c5 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 e08f273..60899c7 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 f74121c..b6eae66 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 75cc39e..c6d8d16 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 19456e5..921bfe0 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 e98bd3d..c658c6e 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 d91e33b..3010519 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 bc3d434..0000000 --- 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 063ea42..4b57437 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 23de14b..93b5b55 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 59089ef..25d32e6 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: - -#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 + /* Create a Stack Frame */ + pushl %ebp + movl %esp, %ebp + + /* 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 196ba5d..5ebce53 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 6856149..edf341f 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 f9b5be0..2691315 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 67e8189..8dc010a 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/mpc512x/cpu.c b/cpu/mpc512x/cpu.c index 42ccd81..dac48db 100644 --- a/cpu/mpc512x/cpu.c +++ b/cpu/mpc512x/cpu.c @@ -197,6 +197,7 @@ void ft_cpu_setup(void *blob, bd_t *bd) #ifdef CONFIG_HAS_ETH0 fdt_fixup_ethernet(blob); #endif + fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize); } #endif diff --git a/cpu/mpc5xxx/cpu.c b/cpu/mpc5xxx/cpu.c index efa64c7..2a28df4 100644 --- a/cpu/mpc5xxx/cpu.c +++ b/cpu/mpc5xxx/cpu.c @@ -157,6 +157,7 @@ void ft_cpu_setup(void *blob, bd_t *bd) } #endif + fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize); } #endif diff --git a/cpu/mpc85xx/mp.c b/cpu/mpc85xx/mp.c index 00b6450..7626eb8 100644 --- a/cpu/mpc85xx/mp.c +++ b/cpu/mpc85xx/mp.c @@ -90,11 +90,7 @@ int cpu_release(int nr, int argc, char *argv[]) return 1; } -#ifdef CONFIG_SYS_64BIT_STRTOUL boot_addr = simple_strtoull(argv[0], NULL, 16); -#else - boot_addr = simple_strtoul(argv[0], NULL, 16); -#endif /* handle pir, r3, r6 */ for (i = 1; i < 4; i++) { diff --git a/cpu/mpc85xx/u-boot-nand.lds b/cpu/mpc85xx/u-boot-nand.lds index a0fc8f1..b4c63e2 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 fa521f0..eed4534 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 19d2c7d..d9605c3 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 d360d5b..ba57211 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 00ad39b..979004b 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 e1b00a7..73d4d06 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 e3e1bab..7976e75 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 0000000..2b47934 --- /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 e2df3a5..8d0f826 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 34184ab..6f1d8f6 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 3f77e81..0207501 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); } |