diff options
Diffstat (limited to 'cpu')
102 files changed, 5276 insertions, 2752 deletions
diff --git a/cpu/arm720t/lpc2292/mmc.c b/cpu/arm720t/lpc2292/mmc.c index fd7f149..beaffe9 100644 --- a/cpu/arm720t/lpc2292/mmc.c +++ b/cpu/arm720t/lpc2292/mmc.c @@ -93,12 +93,12 @@ static int mmc_hw_get_parameters(void) return 0; } -int mmc_init(int verbose) +int mmc_legacy_init(int verbose) { int ret = -ENODEV; if (verbose) - printf("mmc_init\n"); + printf("mmc_legacy_init\n"); spi_init(); /* this meeds to be done twice */ @@ -128,30 +128,4 @@ int mmc_init(int verbose) return ret; } -int mmc_write(uchar * src, ulong dst, int size) -{ -#ifdef MMC_DEBUG - printf("mmc_write: src=%p, dst=%lu, size=%u\n", src, dst, size); -#endif - /* Since mmc2info always returns 0 this function will never be called */ - return 0; -} - -int mmc_read(ulong src, uchar * dst, int size) -{ -#ifdef MMC_DEBUG - printf("mmc_read: src=%lu, dst=%p, size=%u\n", src, dst, size); -#endif - /* Since mmc2info always returns 0 this function will never be called */ - return 0; -} - -int mmc2info(ulong addr) -{ - /* This function is used by cmd_cp to determine if source or destination - address resides on MMC-card or not. We do not support copy to and from - MMC-card so we always return 0. */ - return 0; -} - #endif /* CONFIG_MMC */ diff --git a/cpu/arm920t/at91rm9200/lowlevel_init.S b/cpu/arm920t/at91rm9200/lowlevel_init.S index 66b07da..0913284 100644 --- a/cpu/arm920t/at91rm9200/lowlevel_init.S +++ b/cpu/arm920t/at91rm9200/lowlevel_init.S @@ -38,33 +38,7 @@ * turn is based on the boot.bin code from ATMEL * */ - -/* flash */ -#define MC_PUIA 0xFFFFFF10 -#define MC_PUP 0xFFFFFF50 -#define MC_PUER 0xFFFFFF54 -#define MC_ASR 0xFFFFFF04 -#define MC_AASR 0xFFFFFF08 -#define EBI_CFGR 0xFFFFFF64 -#define SMC_CSR0 0xFFFFFF70 - -/* clocks */ -#define PLLAR 0xFFFFFC28 -#define PLLBR 0xFFFFFC2C -#define MCKR 0xFFFFFC30 - -#define AT91C_BASE_CKGR 0xFFFFFC20 -#define CKGR_MOR 0 - -/* sdram */ -#define PIOC_ASR 0xFFFFF870 -#define PIOC_BSR 0xFFFFF874 -#define PIOC_PDR 0xFFFFF804 -#define EBI_CSA 0xFFFFFF60 -#define SDRC_CR 0xFFFFFF98 -#define SDRC_MR 0xFFFFFF90 -#define SDRC_TR 0xFFFFFF94 - +#include <asm/arch/AT91RM9200.h> _MTEXT_BASE: #undef START_FROM_MEM @@ -84,7 +58,7 @@ lowlevel_init: #else ldr r0, =0x0000FF00 /* Disable main oscillator, OSCOUNT = 0xFF */ #endif - str r0, [r1, #CKGR_MOR] + str r0, [r1, #AT91C_CKGR_MOR] /* Add loop to compensate Main Oscillator startup time */ ldr r0, =0x00000010 LoopOsc: @@ -134,72 +108,72 @@ LoopOsc: .ltorg SMRDATA: - .word MC_PUIA - .word MC_PUIA_VAL - .word MC_PUP - .word MC_PUP_VAL - .word MC_PUER - .word MC_PUER_VAL - .word MC_ASR - .word MC_ASR_VAL - .word MC_AASR - .word MC_AASR_VAL - .word EBI_CFGR - .word EBI_CFGR_VAL - .word SMC_CSR0 - .word SMC_CSR0_VAL - .word PLLAR - .word PLLAR_VAL - .word PLLBR - .word PLLBR_VAL - .word MCKR - .word MCKR_VAL + .word AT91C_MC_PUIA + .word CONFIG_SYS_MC_PUIA_VAL + .word AT91C_MC_PUP + .word CONFIG_SYS_MC_PUP_VAL + .word AT91C_MC_PUER + .word CONFIG_SYS_MC_PUER_VAL + .word AT91C_MC_ASR + .word CONFIG_SYS_MC_ASR_VAL + .word AT91C_MC_AASR + .word CONFIG_SYS_MC_AASR_VAL + .word AT91C_EBI_CFGR + .word CONFIG_SYS_EBI_CFGR_VAL + .word AT91C_SMC_CSR0 + .word CONFIG_SYS_SMC_CSR0_VAL + .word AT91C_PLLAR + .word CONFIG_SYS_PLLAR_VAL + .word AT91C_PLLBR + .word CONFIG_SYS_PLLBR_VAL + .word AT91C_MCKR + .word CONFIG_SYS_MCKR_VAL /* SMRDATA is 80 bytes long */ /* here there's a delay of 100 */ SMRDATA1: - .word PIOC_ASR - .word PIOC_ASR_VAL - .word PIOC_BSR - .word PIOC_BSR_VAL - .word PIOC_PDR - .word PIOC_PDR_VAL - .word EBI_CSA - .word EBI_CSA_VAL - .word SDRC_CR - .word SDRC_CR_VAL - .word SDRC_MR - .word SDRC_MR_VAL - .word SDRAM - .word SDRAM_VAL - .word SDRC_MR - .word SDRC_MR_VAL1 - .word SDRAM - .word SDRAM_VAL - .word SDRAM - .word SDRAM_VAL - .word SDRAM - .word SDRAM_VAL - .word SDRAM - .word SDRAM_VAL - .word SDRAM - .word SDRAM_VAL - .word SDRAM - .word SDRAM_VAL - .word SDRAM - .word SDRAM_VAL - .word SDRAM - .word SDRAM_VAL - .word SDRC_MR - .word SDRC_MR_VAL2 - .word SDRAM1 - .word SDRAM_VAL - .word SDRC_TR - .word SDRC_TR_VAL - .word SDRAM - .word SDRAM_VAL - .word SDRC_MR - .word SDRC_MR_VAL3 - .word SDRAM - .word SDRAM_VAL + .word AT91C_PIOC_ASR + .word CONFIG_SYS_PIOC_ASR_VAL + .word AT91C_PIOC_BSR + .word CONFIG_SYS_PIOC_BSR_VAL + .word AT91C_PIOC_PDR + .word CONFIG_SYS_PIOC_PDR_VAL + .word AT91C_EBI_CSA + .word CONFIG_SYS_EBI_CSA_VAL + .word AT91C_SDRC_CR + .word CONFIG_SYS_SDRC_CR_VAL + .word AT91C_SDRC_MR + .word CONFIG_SYS_SDRC_MR_VAL + .word CONFIG_SYS_SDRAM + .word CONFIG_SYS_SDRAM_VAL + .word AT91C_SDRC_MR + .word CONFIG_SYS_SDRC_MR_VAL1 + .word CONFIG_SYS_SDRAM + .word CONFIG_SYS_SDRAM_VAL + .word CONFIG_SYS_SDRAM + .word CONFIG_SYS_SDRAM_VAL + .word CONFIG_SYS_SDRAM + .word CONFIG_SYS_SDRAM_VAL + .word CONFIG_SYS_SDRAM + .word CONFIG_SYS_SDRAM_VAL + .word CONFIG_SYS_SDRAM + .word CONFIG_SYS_SDRAM_VAL + .word CONFIG_SYS_SDRAM + .word CONFIG_SYS_SDRAM_VAL + .word CONFIG_SYS_SDRAM + .word CONFIG_SYS_SDRAM_VAL + .word CONFIG_SYS_SDRAM + .word CONFIG_SYS_SDRAM_VAL + .word AT91C_SDRC_MR + .word CONFIG_SYS_SDRC_MR_VAL2 + .word CONFIG_SYS_SDRAM1 + .word CONFIG_SYS_SDRAM_VAL + .word AT91C_SDRC_TR + .word CONFIG_SYS_SDRC_TR_VAL + .word CONFIG_SYS_SDRAM + .word CONFIG_SYS_SDRAM_VAL + .word AT91C_SDRC_MR + .word CONFIG_SYS_SDRC_MR_VAL3 + .word CONFIG_SYS_SDRAM + .word CONFIG_SYS_SDRAM_VAL /* SMRDATA1 is 176 bytes long */ #endif /* CONFIG_SKIP_LOWLEVEL_INIT */ diff --git a/cpu/arm920t/s3c24x0/usb_ohci.c b/cpu/arm920t/s3c24x0/usb_ohci.c index 641f270..9cbd477 100644 --- a/cpu/arm920t/s3c24x0/usb_ohci.c +++ b/cpu/arm920t/s3c24x0/usb_ohci.c @@ -29,9 +29,7 @@ */ /* * IMPORTANT NOTES - * 1 - you MUST define LITTLEENDIAN in the configuration file for the - * board or this driver will NOT work! - * 2 - this driver is intended for use with USB Mass Storage Devices + * 1 - this driver is intended for use with USB Mass Storage Devices * (BBB) ONLY. There is NO support for Interrupt or Isochronous pipes! */ diff --git a/cpu/arm926ejs/nomadik/Makefile b/cpu/arm926ejs/nomadik/Makefile new file mode 100644 index 0000000..e3bd2ee --- /dev/null +++ b/cpu/arm926ejs/nomadik/Makefile @@ -0,0 +1,46 @@ +# +# (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 + +COBJS = timer.o +SOBJS = reset.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) $(addprefix $(obj),$(SOBJS)) + +all: $(obj).depend $(LIB) + +$(LIB): $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/cpu/arm926ejs/nomadik/reset.S b/cpu/arm926ejs/nomadik/reset.S new file mode 100644 index 0000000..948996b --- /dev/null +++ b/cpu/arm926ejs/nomadik/reset.S @@ -0,0 +1,25 @@ +#include <config.h> +/* + * Processor reset for Nomadik + */ + + .align 5 +.globl reset_cpu +reset_cpu: +#if defined CONFIG_NOMADIK_8815 + ldr r0, =NOMADIK_SRC_BASE + ldr r1, =0x1 + str r1, [r0, #0x18] +#else + ldr r1, rstctl1 /* get clkm1 reset ctl */ + mov r3, #0x0 + strh r3, [r1] /* clear it */ + mov r3, #0x8 + strh r3, [r1] /* force dsp+arm reset */ +#endif + +_loop_forever: + b _loop_forever + +rstctl1: + .word 0xfffece10 diff --git a/cpu/arm926ejs/nomadik/timer.c b/cpu/arm926ejs/nomadik/timer.c new file mode 100644 index 0000000..2b2208c --- /dev/null +++ b/cpu/arm926ejs/nomadik/timer.c @@ -0,0 +1,183 @@ +/* + * (C) Copyright 2003 + * Texas Instruments <www.ti.com> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002-2004 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * (C) Copyright 2004 + * Philippe Robin, ARM Ltd. <philippe.robin@arm.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/io.h> +#include <arm926ejs.h> + +#define TIMER_LOAD_VAL 0xffffffff + +/* macro to read the 32 bit timer */ +#define READ_TIMER readl(CONFIG_SYS_TIMERBASE + 20) + +static ulong timestamp; +static ulong lastdec; + +/* nothing really to do with interrupts, just starts up a counter. */ +int timer_init(void) +{ + /* Load timer with initial value */ + writel(TIMER_LOAD_VAL, CONFIG_SYS_TIMERBASE + 16); + + /* + * Set timer to be enabled, free-running, no interrupts, 256 divider, + * 32-bit, wrap-mode + */ + writel(0x8a, CONFIG_SYS_TIMERBASE + 24); + + /* init the timestamp and lastdec value */ + reset_timer_masked(); + + return 0; +} + +/* + * timer without interrupts + */ +void reset_timer(void) +{ + reset_timer_masked(); +} + +ulong get_timer(ulong base) +{ + return get_timer_masked() - base; +} + +void set_timer(ulong t) +{ + timestamp = t; +} + +/* delay x useconds AND perserve advance timstamp value */ +void udelay(unsigned long usec) +{ + ulong tmo, tmp; + + if (usec >= 1000) { + /* if "big" number, spread normalization to seconds */ + tmo = usec / 1000; /* start to normalize */ + tmo *= CONFIG_SYS_HZ; /* find number of "ticks" */ + tmo /= 1000; /* finish normalize. */ + } else { + /* small number, don't kill it prior to HZ multiply */ + tmo = usec * CONFIG_SYS_HZ; + tmo /= (1000 * 1000); + } + + tmp = get_timer(0); /* get current timestamp */ + if ((tmo + tmp + 1) < tmp) /* will roll time stamp? */ + reset_timer_masked(); /* reset to 0, set lastdec value */ + else + tmo += tmp; + + while (get_timer_masked() < tmo) + /* nothing */ ; +} + +void reset_timer_masked(void) +{ + /* reset time */ + lastdec = READ_TIMER; /* capure current decrementer value time */ + timestamp = 0; /* start "advancing" time stamp from 0 */ +} + +ulong get_timer_masked(void) +{ + ulong now = READ_TIMER; /* current tick value */ + + if (lastdec >= now) { /* normal mode (non roll) */ + /* move stamp fordward */ + timestamp += lastdec - now; + } else { + /* + * An overflow is expected. + * 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 + */ + timestamp += lastdec + TIMER_LOAD_VAL - now; + } + lastdec = now; + + return timestamp; +} + +/* waits specified delay value and resets timestamp */ +void udelay_masked(unsigned long usec) +{ + ulong tmo; + + if (usec >= 1000) { + /* if "big" number, spread normalization to seconds */ + tmo = usec / 1000; /* start to normalize */ + tmo *= CONFIG_SYS_HZ; /* find number of "ticks" */ + tmo /= 1000; /* finish normalize. */ + } else { + /* else small number, don't kill it prior to HZ multiply */ + tmo = usec * CONFIG_SYS_HZ; + tmo /= (1000*1000); + } + + reset_timer_masked(); + /* set "advancing" timestamp to 0, set lastdec vaule */ + + while (get_timer_masked() < tmo) + /* nothing */ ; +} + +/* + * 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) +{ + 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) +{ + ulong tbclk; + + tbclk = CONFIG_SYS_HZ; + return tbclk; +} diff --git a/cpu/arm_cortexa8/Makefile b/cpu/arm_cortexa8/Makefile new file mode 100644 index 0000000..ae20299 --- /dev/null +++ b/cpu/arm_cortexa8/Makefile @@ -0,0 +1,47 @@ +# +# (C) Copyright 2000-2003 +# 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$(CPU).a + +START := start.o +COBJS := cpu.o + +SRCS := $(START:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +START := $(addprefix $(obj),$(START)) + +all: $(obj).depend $(START) $(LIB) + +$(LIB): $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +#########################################################################
\ No newline at end of file diff --git a/cpu/arm_cortexa8/config.mk b/cpu/arm_cortexa8/config.mk new file mode 100644 index 0000000..b021762 --- /dev/null +++ b/cpu/arm_cortexa8/config.mk @@ -0,0 +1,36 @@ +# +# (C) Copyright 2002 +# Gary Jennejohn, DENX Software Engineering, <gj@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 +# +PLATFORM_RELFLAGS += -fno-strict-aliasing -fno-common -ffixed-r8 \ + -msoft-float + +# Make ARMv5 to allow more compilers to work, even though its v7a. +PLATFORM_CPPFLAGS += -march=armv5 +# ========================================================================= +# +# Supply options according to compiler version +# +# ========================================================================= +PLATFORM_CPPFLAGS +=$(call cc-option) +PLATFORM_CPPFLAGS +=$(call cc-option,-mno-thumb-interwork,) +PLATFORM_RELFLAGS +=$(call cc-option,-mshort-load-bytes,\ + $(call cc-option,-malignment-traps,))
\ No newline at end of file diff --git a/cpu/arm_cortexa8/cpu.c b/cpu/arm_cortexa8/cpu.c new file mode 100644 index 0000000..ad2085b --- /dev/null +++ b/cpu/arm_cortexa8/cpu.c @@ -0,0 +1,240 @@ +/* + * (C) Copyright 2008 Texas Insturments + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@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 + */ + +/* + * CPU specific code + */ + +#include <common.h> +#include <command.h> +#include <asm/arch/sys_proto.h> + +#ifdef CONFIG_USE_IRQ +DECLARE_GLOBAL_DATA_PTR; +#endif + +#ifndef CONFIG_L2_OFF +void l2cache_disable(void); +#endif + +static void cache_flush(void); + +/* read co-processor 15, register #1 (control register) */ +static unsigned long read_p15_c1(void) +{ + unsigned long value; + + __asm__ __volatile__("mrc p15, 0, %0, c1, c0, 0\ + @ read control reg\n":"=r"(value) + ::"memory"); + return value; +} + +/* write to co-processor 15, register #1 (control register) */ +static void write_p15_c1(unsigned long value) +{ + __asm__ __volatile__("mcr p15, 0, %0, c1, c0, 0\ + @ write it back\n"::"r"(value) + : "memory"); + + read_p15_c1(); +} + +static void cp_delay(void) +{ + /* Many OMAP regs need at least 2 nops */ + asm("nop"); + asm("nop"); +} + +/* See also ARM Ref. Man. */ +#define C1_MMU (1<<0) /* mmu off/on */ +#define C1_ALIGN (1<<1) /* alignment faults off/on */ +#define C1_DC (1<<2) /* dcache off/on */ +#define C1_WB (1<<3) /* merging write buffer on/off */ +#define C1_BIG_ENDIAN (1<<7) /* big endian off/on */ +#define C1_SYS_PROT (1<<8) /* system protection */ +#define C1_ROM_PROT (1<<9) /* ROM protection */ +#define C1_IC (1<<12) /* icache off/on */ +#define C1_HIGH_VECTORS (1<<13) /* location of vectors: low/high addresses */ +#define RESERVED_1 (0xf << 3) /* must be 111b for R/W */ + +int cpu_init(void) +{ + /* + * setup up stacks if necessary + */ +#ifdef CONFIG_USE_IRQ + IRQ_STACK_START = + _armboot_start - CONFIG_SYS_MALLOC_LEN - CONFIG_SYS_GBL_DATA_SIZE - 4; + FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ; +#endif + return 0; +} + +int cleanup_before_linux(void) +{ + unsigned int i; + + /* + * this function is called just before we call linux + * it prepares the processor for linux + * + * we turn off caches etc ... + */ + disable_interrupts(); + + /* turn off I/D-cache */ + icache_disable(); + dcache_disable(); + + /* invalidate I-cache */ + cache_flush(); + +#ifndef CONFIG_L2_OFF + /* turn off L2 cache */ + l2cache_disable(); + /* invalidate L2 cache also */ + v7_flush_dcache_all(get_device_type()); +#endif + i = 0; + /* mem barrier to sync up things */ + asm("mcr p15, 0, %0, c7, c10, 4": :"r"(i)); + +#ifndef CONFIG_L2_OFF + l2cache_enable(); +#endif + + return 0; +} + +int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + disable_interrupts(); + reset_cpu(0); + + /* NOTREACHED */ + return 0; +} + +void icache_enable(void) +{ + ulong reg; + + reg = read_p15_c1(); /* get control reg. */ + cp_delay(); + write_p15_c1(reg | C1_IC); +} + +void icache_disable(void) +{ + ulong reg; + + reg = read_p15_c1(); + cp_delay(); + write_p15_c1(reg & ~C1_IC); +} + +void dcache_disable (void) +{ + ulong reg; + + reg = read_p15_c1 (); + cp_delay (); + write_p15_c1 (reg & ~C1_DC); +} + +void l2cache_enable() +{ + unsigned long i; + volatile unsigned int j; + + /* ES2 onwards we can disable/enable L2 ourselves */ + if (get_cpu_rev() == CPU_3430_ES2) { + __asm__ __volatile__("mrc p15, 0, %0, c1, c0, 1":"=r"(i)); + __asm__ __volatile__("orr %0, %0, #0x2":"=r"(i)); + __asm__ __volatile__("mcr p15, 0, %0, c1, c0, 1":"=r"(i)); + } else { + /* Save r0, r12 and restore them after usage */ + __asm__ __volatile__("mov %0, r12":"=r"(j)); + __asm__ __volatile__("mov %0, r0":"=r"(i)); + + /* + * GP Device ROM code API usage here + * r12 = AUXCR Write function and r0 value + */ + __asm__ __volatile__("mov r12, #0x3"); + __asm__ __volatile__("mrc p15, 0, r0, c1, c0, 1"); + __asm__ __volatile__("orr r0, r0, #0x2"); + /* SMI instruction to call ROM Code API */ + __asm__ __volatile__(".word 0xE1600070"); + __asm__ __volatile__("mov r0, %0":"=r"(i)); + __asm__ __volatile__("mov r12, %0":"=r"(j)); + } + +} + +void l2cache_disable() +{ + unsigned long i; + volatile unsigned int j; + + /* ES2 onwards we can disable/enable L2 ourselves */ + if (get_cpu_rev() == CPU_3430_ES2) { + __asm__ __volatile__("mrc p15, 0, %0, c1, c0, 1":"=r"(i)); + __asm__ __volatile__("bic %0, %0, #0x2":"=r"(i)); + __asm__ __volatile__("mcr p15, 0, %0, c1, c0, 1":"=r"(i)); + } else { + /* Save r0, r12 and restore them after usage */ + __asm__ __volatile__("mov %0, r12":"=r"(j)); + __asm__ __volatile__("mov %0, r0":"=r"(i)); + + /* + * GP Device ROM code API usage here + * r12 = AUXCR Write function and r0 value + */ + __asm__ __volatile__("mov r12, #0x3"); + __asm__ __volatile__("mrc p15, 0, r0, c1, c0, 1"); + __asm__ __volatile__("bic r0, r0, #0x2"); + /* SMI instruction to call ROM Code API */ + __asm__ __volatile__(".word 0xE1600070"); + __asm__ __volatile__("mov r0, %0":"=r"(i)); + __asm__ __volatile__("mov r12, %0":"=r"(j)); + } +} + +int icache_status(void) +{ + return (read_p15_c1() & C1_IC) != 0; +} + +static void cache_flush(void) +{ + asm ("mcr p15, 0, %0, c7, c5, 0": :"r" (0)); +} diff --git a/cpu/arm_cortexa8/omap3/Makefile b/cpu/arm_cortexa8/omap3/Makefile new file mode 100644 index 0000000..b96b3dd --- /dev/null +++ b/cpu/arm_cortexa8/omap3/Makefile @@ -0,0 +1,46 @@ +# +# (C) Copyright 2000-2003 +# 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 := lowlevel_init.o +COBJS := sys_info.o board.o clock.o interrupts.o mem.o syslib.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS)) + +all: $(obj).depend $(LIB) + +$(LIB): $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/cpu/arm_cortexa8/omap3/board.c b/cpu/arm_cortexa8/omap3/board.c new file mode 100644 index 0000000..7bb3e28 --- /dev/null +++ b/cpu/arm_cortexa8/omap3/board.c @@ -0,0 +1,344 @@ +/* + * + * Common board functions for OMAP3 based boards. + * + * (C) Copyright 2004-2008 + * Texas Instruments, <www.ti.com> + * + * Author : + * Sunil Kumar <sunilsaini05@gmail.com> + * Shashi Ranjan <shashiranjanmca05@gmail.com> + * + * Derived from Beagle Board and 3430 SDP code by + * Richard Woodruff <r-woodruff2@ti.com> + * Syed Mohammed Khasim <khasim@ti.com> + * + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#include <common.h> +#include <asm/io.h> +#include <asm/arch/sys_proto.h> +#include <asm/arch/mem.h> + +extern omap3_sysinfo sysinfo; + +/****************************************************************************** + * Routine: delay + * Description: spinning delay to use before udelay works + *****************************************************************************/ +static inline void delay(unsigned long loops) +{ + __asm__ volatile ("1:\n" "subs %0, %1, #1\n" + "bne 1b":"=r" (loops):"0"(loops)); +} + +/****************************************************************************** + * Routine: secure_unlock + * Description: Setup security registers for access + * (GP Device only) + *****************************************************************************/ +void secure_unlock_mem(void) +{ + pm_t *pm_rt_ape_base = (pm_t *)PM_RT_APE_BASE_ADDR_ARM; + pm_t *pm_gpmc_base = (pm_t *)PM_GPMC_BASE_ADDR_ARM; + pm_t *pm_ocm_ram_base = (pm_t *)PM_OCM_RAM_BASE_ADDR_ARM; + pm_t *pm_iva2_base = (pm_t *)PM_IVA2_BASE_ADDR_ARM; + sms_t *sms_base = (sms_t *)OMAP34XX_SMS_BASE; + + /* Protection Module Register Target APE (PM_RT) */ + writel(UNLOCK_1, &pm_rt_ape_base->req_info_permission_1); + writel(UNLOCK_1, &pm_rt_ape_base->read_permission_0); + writel(UNLOCK_1, &pm_rt_ape_base->wirte_permission_0); + writel(UNLOCK_2, &pm_rt_ape_base->addr_match_1); + + writel(UNLOCK_3, &pm_gpmc_base->req_info_permission_0); + writel(UNLOCK_3, &pm_gpmc_base->read_permission_0); + writel(UNLOCK_3, &pm_gpmc_base->wirte_permission_0); + + writel(UNLOCK_3, &pm_ocm_ram_base->req_info_permission_0); + writel(UNLOCK_3, &pm_ocm_ram_base->read_permission_0); + writel(UNLOCK_3, &pm_ocm_ram_base->wirte_permission_0); + writel(UNLOCK_2, &pm_ocm_ram_base->addr_match_2); + + /* IVA Changes */ + writel(UNLOCK_3, &pm_iva2_base->req_info_permission_0); + writel(UNLOCK_3, &pm_iva2_base->read_permission_0); + writel(UNLOCK_3, &pm_iva2_base->wirte_permission_0); + + /* SDRC region 0 public */ + writel(UNLOCK_1, &sms_base->rg_att0); +} + +/****************************************************************************** + * Routine: secureworld_exit() + * Description: If chip is EMU and boot type is external + * configure secure registers and exit secure world + * general use. + *****************************************************************************/ +void secureworld_exit() +{ + unsigned long i; + + /* configrue non-secure access control register */ + __asm__ __volatile__("mrc p15, 0, %0, c1, c1, 2":"=r"(i)); + /* enabling co-processor CP10 and CP11 accesses in NS world */ + __asm__ __volatile__("orr %0, %0, #0xC00":"=r"(i)); + /* + * allow allocation of locked TLBs and L2 lines in NS world + * allow use of PLE registers in NS world also + */ + __asm__ __volatile__("orr %0, %0, #0x70000":"=r"(i)); + __asm__ __volatile__("mcr p15, 0, %0, c1, c1, 2":"=r"(i)); + + /* Enable ASA in ACR register */ + __asm__ __volatile__("mrc p15, 0, %0, c1, c0, 1":"=r"(i)); + __asm__ __volatile__("orr %0, %0, #0x10":"=r"(i)); + __asm__ __volatile__("mcr p15, 0, %0, c1, c0, 1":"=r"(i)); + + /* Exiting secure world */ + __asm__ __volatile__("mrc p15, 0, %0, c1, c1, 0":"=r"(i)); + __asm__ __volatile__("orr %0, %0, #0x31":"=r"(i)); + __asm__ __volatile__("mcr p15, 0, %0, c1, c1, 0":"=r"(i)); +} + +/****************************************************************************** + * Routine: setup_auxcr() + * Description: Write to AuxCR desired value using SMI. + * general use. + *****************************************************************************/ +void setup_auxcr() +{ + unsigned long i; + volatile unsigned int j; + /* Save r0, r12 and restore them after usage */ + __asm__ __volatile__("mov %0, r12":"=r"(j)); + __asm__ __volatile__("mov %0, r0":"=r"(i)); + + /* + * GP Device ROM code API usage here + * r12 = AUXCR Write function and r0 value + */ + __asm__ __volatile__("mov r12, #0x3"); + __asm__ __volatile__("mrc p15, 0, r0, c1, c0, 1"); + /* Enabling ASA */ + __asm__ __volatile__("orr r0, r0, #0x10"); + /* Enable L1NEON */ + __asm__ __volatile__("orr r0, r0, #1 << 5"); + /* SMI instruction to call ROM Code API */ + __asm__ __volatile__(".word 0xE1600070"); + __asm__ __volatile__("mov r0, %0":"=r"(i)); + __asm__ __volatile__("mov r12, %0":"=r"(j)); +} + +/****************************************************************************** + * Routine: try_unlock_sram() + * Description: If chip is GP/EMU(special) type, unlock the SRAM for + * general use. + *****************************************************************************/ +void try_unlock_memory() +{ + int mode; + int in_sdram = is_running_in_sdram(); + + /* + * if GP device unlock device SRAM for general use + * secure code breaks for Secure/Emulation device - HS/E/T + */ + mode = get_device_type(); + if (mode == GP_DEVICE) + secure_unlock_mem(); + + /* + * If device is EMU and boot is XIP external booting + * Unlock firewalls and disable L2 and put chip + * out of secure world + * + * Assuming memories are unlocked by the demon who put us in SDRAM + */ + if ((mode <= EMU_DEVICE) && (get_boot_type() == 0x1F) + && (!in_sdram)) { + secure_unlock_mem(); + secureworld_exit(); + } + + return; +} + +/****************************************************************************** + * Routine: s_init + * Description: Does early system init of muxing and clocks. + * - Called path is with SRAM stack. + *****************************************************************************/ +void s_init(void) +{ + int in_sdram = is_running_in_sdram(); + + watchdog_init(); + + try_unlock_memory(); + + /* + * Right now flushing at low MPU speed. + * Need to move after clock init + */ + v7_flush_dcache_all(get_device_type()); +#ifndef CONFIG_ICACHE_OFF + icache_enable(); +#endif + +#ifdef CONFIG_L2_OFF + l2cache_disable(); +#else + l2cache_enable(); +#endif + /* + * Writing to AuxCR in U-boot using SMI for GP DEV + * Currently SMI in Kernel on ES2 devices seems to have an issue + * Once that is resolved, we can postpone this config to kernel + */ + if (get_device_type() == GP_DEVICE) + setup_auxcr(); + + set_muxconf_regs(); + delay(100); + + prcm_init(); + + per_clocks_enable(); + + if (!in_sdram) + sdrc_init(); +} + +/****************************************************************************** + * Routine: wait_for_command_complete + * Description: Wait for posting to finish on watchdog + *****************************************************************************/ +void wait_for_command_complete(watchdog_t *wd_base) +{ + int pending = 1; + do { + pending = readl(&wd_base->wwps); + } while (pending); +} + +/****************************************************************************** + * Routine: watchdog_init + * Description: Shut down watch dogs + *****************************************************************************/ +void watchdog_init(void) +{ + watchdog_t *wd2_base = (watchdog_t *)WD2_BASE; + prcm_t *prcm_base = (prcm_t *)PRCM_BASE; + + /* + * There are 3 watch dogs WD1=Secure, WD2=MPU, WD3=IVA. WD1 is + * either taken care of by ROM (HS/EMU) or not accessible (GP). + * We need to take care of WD2-MPU or take a PRCM reset. WD3 + * should not be running and does not generate a PRCM reset. + */ + + sr32(&prcm_base->fclken_wkup, 5, 1, 1); + sr32(&prcm_base->iclken_wkup, 5, 1, 1); + wait_on_value(ST_WDT2, 0x20, &prcm_base->idlest_wkup, 5); + + writel(WD_UNLOCK1, &wd2_base->wspr); + wait_for_command_complete(wd2_base); + writel(WD_UNLOCK2, &wd2_base->wspr); +} + +/****************************************************************************** + * Routine: dram_init + * Description: sets uboots idea of sdram size + *****************************************************************************/ +int dram_init(void) +{ + DECLARE_GLOBAL_DATA_PTR; + unsigned int size0 = 0, size1 = 0; + u32 btype; + + btype = get_board_type(); + + display_board_info(btype); + + /* + * If a second bank of DDR is attached to CS1 this is + * where it can be started. Early init code will init + * memory on CS0. + */ + if ((sysinfo.mtype == DDR_COMBO) || (sysinfo.mtype == DDR_STACKED)) { + do_sdrc_init(CS1, NOT_EARLY); + make_cs1_contiguous(); + } + + size0 = get_sdr_cs_size(CS0); + size1 = get_sdr_cs_size(CS1); + + gd->bd->bi_dram[0].start = PHYS_SDRAM_1; + gd->bd->bi_dram[0].size = size0; + gd->bd->bi_dram[1].start = PHYS_SDRAM_1 + get_sdr_cs_offset(CS1); + gd->bd->bi_dram[1].size = size1; + + return 0; +} + +/****************************************************************************** + * Dummy function to handle errors for EABI incompatibility + *****************************************************************************/ +void raise(void) +{ +} + +/****************************************************************************** + * Dummy function to handle errors for EABI incompatibility + *****************************************************************************/ +void abort(void) +{ +} + +#ifdef CONFIG_NAND_OMAP_GPMC +/****************************************************************************** + * OMAP3 specific command to switch between NAND HW and SW ecc + *****************************************************************************/ +static int do_switch_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + if (argc != 2) + goto usage; + if (strncmp(argv[1], "hw", 2) == 0) + omap_nand_switch_ecc(1); + else if (strncmp(argv[1], "sw", 2) == 0) + omap_nand_switch_ecc(0); + else + goto usage; + + return 0; + +usage: + printf ("Usage: nandecc %s\n", cmdtp->help); + return 1; +} + +U_BOOT_CMD( + nandecc, 2, 1, do_switch_ecc, + "nandecc - switch OMAP3 NAND ECC calculation algorithm\n", + "[hw/sw] - Switch between NAND hardware (hw) or software (sw) ecc algorithm\n" + ); + +#endif /* CONFIG_NAND_OMAP_GPMC */ diff --git a/cpu/arm_cortexa8/omap3/clock.c b/cpu/arm_cortexa8/omap3/clock.c new file mode 100644 index 0000000..8ac31be --- /dev/null +++ b/cpu/arm_cortexa8/omap3/clock.c @@ -0,0 +1,381 @@ +/* + * (C) Copyright 2008 + * Texas Instruments, <www.ti.com> + * + * Author : + * Manikandan Pillai <mani.pillai@ti.com> + * + * Derived from Beagle Board and OMAP3 SDP code by + * Richard Woodruff <r-woodruff2@ti.com> + * Syed Mohammed Khasim <khasim@ti.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clocks.h> +#include <asm/arch/clocks_omap3.h> +#include <asm/arch/mem.h> +#include <asm/arch/sys_proto.h> +#include <environment.h> +#include <command.h> + +/****************************************************************************** + * get_sys_clk_speed() - determine reference oscillator speed + * based on known 32kHz clock and gptimer. + *****************************************************************************/ +u32 get_osc_clk_speed(void) +{ + u32 start, cstart, cend, cdiff, val; + prcm_t *prcm_base = (prcm_t *)PRCM_BASE; + prm_t *prm_base = (prm_t *)PRM_BASE; + gptimer_t *gpt1_base = (gptimer_t *)OMAP34XX_GPT1; + s32ktimer_t *s32k_base = (s32ktimer_t *)SYNC_32KTIMER_BASE; + + val = readl(&prm_base->clksrc_ctrl); + + /* If SYS_CLK is being divided by 2, remove for now */ + val = (val & (~SYSCLKDIV_2)) | SYSCLKDIV_1; + writel(val, &prm_base->clksrc_ctrl); + + /* enable timer2 */ + val = readl(&prcm_base->clksel_wkup) | CLKSEL_GPT1; + + /* select sys_clk for GPT1 */ + writel(val, &prcm_base->clksel_wkup); + + /* Enable I and F Clocks for GPT1 */ + val = readl(&prcm_base->iclken_wkup) | EN_GPT1 | EN_32KSYNC; + writel(val, &prcm_base->iclken_wkup); + val = readl(&prcm_base->fclken_wkup) | EN_GPT1; + writel(val, &prcm_base->fclken_wkup); + + writel(0, &gpt1_base->tldr); /* start counting at 0 */ + writel(GPT_EN, &gpt1_base->tclr); /* enable clock */ + + /* enable 32kHz source, determine sys_clk via gauging */ + + /* start time in 20 cycles */ + start = 20 + readl(&s32k_base->s32k_cr); + + /* dead loop till start time */ + while (readl(&s32k_base->s32k_cr) < start); + + /* get start sys_clk count */ + cstart = readl(&gpt1_base->tcrr); + + /* wait for 40 cycles */ + while (readl(&s32k_base->s32k_cr) < (start + 20)) ; + cend = readl(&gpt1_base->tcrr); /* get end sys_clk count */ + cdiff = cend - cstart; /* get elapsed ticks */ + + /* based on number of ticks assign speed */ + if (cdiff > 19000) + return S38_4M; + else if (cdiff > 15200) + return S26M; + else if (cdiff > 13000) + return S24M; + else if (cdiff > 9000) + return S19_2M; + else if (cdiff > 7600) + return S13M; + else + return S12M; +} + +/****************************************************************************** + * get_sys_clkin_sel() - returns the sys_clkin_sel field value based on + * input oscillator clock frequency. + *****************************************************************************/ +void get_sys_clkin_sel(u32 osc_clk, u32 *sys_clkin_sel) +{ + switch(osc_clk) { + case S38_4M: + *sys_clkin_sel = 4; + break; + case S26M: + *sys_clkin_sel = 3; + break; + case S19_2M: + *sys_clkin_sel = 2; + break; + case S13M: + *sys_clkin_sel = 1; + break; + case S12M: + default: + *sys_clkin_sel = 0; + } +} + +/****************************************************************************** + * prcm_init() - inits clocks for PRCM as defined in clocks.h + * called from SRAM, or Flash (using temp SRAM stack). + *****************************************************************************/ +void prcm_init(void) +{ + void (*f_lock_pll) (u32, u32, u32, u32); + int xip_safe, p0, p1, p2, p3; + u32 osc_clk = 0, sys_clkin_sel; + u32 clk_index, sil_index; + prm_t *prm_base = (prm_t *)PRM_BASE; + prcm_t *prcm_base = (prcm_t *)PRCM_BASE; + dpll_param *dpll_param_p; + + f_lock_pll = (void *) ((u32) &_end_vect - (u32) &_start + + SRAM_VECT_CODE); + + xip_safe = is_running_in_sram(); + + /* + * Gauge the input clock speed and find out the sys_clkin_sel + * value corresponding to the input clock. + */ + osc_clk = get_osc_clk_speed(); + get_sys_clkin_sel(osc_clk, &sys_clkin_sel); + + /* set input crystal speed */ + sr32(&prm_base->clksel, 0, 3, sys_clkin_sel); + + /* If the input clock is greater than 19.2M always divide/2 */ + if (sys_clkin_sel > 2) { + /* input clock divider */ + sr32(&prm_base->clksrc_ctrl, 6, 2, 2); + clk_index = sys_clkin_sel / 2; + } else { + /* input clock divider */ + sr32(&prm_base->clksrc_ctrl, 6, 2, 1); + clk_index = sys_clkin_sel; + } + + /* + * The DPLL tables are defined according to sysclk value and + * silicon revision. The clk_index value will be used to get + * the values for that input sysclk from the DPLL param table + * and sil_index will get the values for that SysClk for the + * appropriate silicon rev. + */ + sil_index = get_cpu_rev() - 1; + + /* Unlock MPU DPLL (slows things down, and needed later) */ + sr32(&prcm_base->clken_pll_mpu, 0, 3, PLL_LOW_POWER_BYPASS); + wait_on_value(ST_MPU_CLK, 0, &prcm_base->idlest_pll_mpu, LDELAY); + + /* Getting the base address of Core DPLL param table */ + dpll_param_p = (dpll_param *) get_core_dpll_param(); + + /* Moving it to the right sysclk and ES rev base */ + dpll_param_p = dpll_param_p + 3 * clk_index + sil_index; + if (xip_safe) { + /* + * CORE DPLL + * sr32(CM_CLKSEL2_EMU) set override to work when asleep + */ + sr32(&prcm_base->clken_pll, 0, 3, PLL_FAST_RELOCK_BYPASS); + wait_on_value(ST_CORE_CLK, 0, &prcm_base->idlest_ckgen, + LDELAY); + + /* + * For OMAP3 ES1.0 Errata 1.50, default value directly doesn't + * work. write another value and then default value. + */ + + /* m3x2 */ + sr32(&prcm_base->clksel1_emu, 16, 5, CORE_M3X2 + 1); + /* m3x2 */ + sr32(&prcm_base->clksel1_emu, 16, 5, CORE_M3X2); + /* Set M2 */ + sr32(&prcm_base->clksel1_pll, 27, 2, dpll_param_p->m2); + /* Set M */ + sr32(&prcm_base->clksel1_pll, 16, 11, dpll_param_p->m); + /* Set N */ + sr32(&prcm_base->clksel1_pll, 8, 7, dpll_param_p->n); + /* 96M Src */ + sr32(&prcm_base->clksel1_pll, 6, 1, 0); + /* ssi */ + sr32(&prcm_base->clksel_core, 8, 4, CORE_SSI_DIV); + /* fsusb */ + sr32(&prcm_base->clksel_core, 4, 2, CORE_FUSB_DIV); + /* l4 */ + sr32(&prcm_base->clksel_core, 2, 2, CORE_L4_DIV); + /* l3 */ + sr32(&prcm_base->clksel_core, 0, 2, CORE_L3_DIV); + /* gfx */ + sr32(&prcm_base->clksel_gfx, 0, 3, GFX_DIV); + /* reset mgr */ + sr32(&prcm_base->clksel_wkup, 1, 2, WKUP_RSM); + /* FREQSEL */ + sr32(&prcm_base->clken_pll, 4, 4, dpll_param_p->fsel); + /* lock mode */ + sr32(&prcm_base->clken_pll, 0, 3, PLL_LOCK); + + wait_on_value(ST_CORE_CLK, 1, &prcm_base->idlest_ckgen, + LDELAY); + } else if (is_running_in_flash()) { + /* + * if running from flash, jump to small relocated code + * area in SRAM. + */ + p0 = readl(&prcm_base->clken_pll); + sr32(&p0, 0, 3, PLL_FAST_RELOCK_BYPASS); + sr32(&p0, 4, 4, dpll_param_p->fsel); /* FREQSEL */ + + p1 = readl(&prcm_base->clksel1_pll); + sr32(&p1, 27, 2, dpll_param_p->m2); /* Set M2 */ + sr32(&p1, 16, 11, dpll_param_p->m); /* Set M */ + sr32(&p1, 8, 7, dpll_param_p->n); /* Set N */ + sr32(&p1, 6, 1, 0); /* set source for 96M */ + + p2 = readl(&prcm_base->clksel_core); + sr32(&p2, 8, 4, CORE_SSI_DIV); /* ssi */ + sr32(&p2, 4, 2, CORE_FUSB_DIV); /* fsusb */ + sr32(&p2, 2, 2, CORE_L4_DIV); /* l4 */ + sr32(&p2, 0, 2, CORE_L3_DIV); /* l3 */ + + p3 = (u32)&prcm_base->idlest_ckgen; + + (*f_lock_pll) (p0, p1, p2, p3); + } + + /* PER DPLL */ + sr32(&prcm_base->clken_pll, 16, 3, PLL_STOP); + wait_on_value(ST_PERIPH_CLK, 0, &prcm_base->idlest_ckgen, LDELAY); + + /* Getting the base address to PER DPLL param table */ + + /* Set N */ + dpll_param_p = (dpll_param *) get_per_dpll_param(); + + /* Moving it to the right sysclk base */ + dpll_param_p = dpll_param_p + clk_index; + + /* + * Errata 1.50 Workaround for OMAP3 ES1.0 only + * If using default divisors, write default divisor + 1 + * and then the actual divisor value + */ + sr32(&prcm_base->clksel1_emu, 24, 5, PER_M6X2 + 1); /* set M6 */ + sr32(&prcm_base->clksel1_emu, 24, 5, PER_M6X2); /* set M6 */ + sr32(&prcm_base->clksel_cam, 0, 5, PER_M5X2 + 1); /* set M5 */ + sr32(&prcm_base->clksel_cam, 0, 5, PER_M5X2); /* set M5 */ + sr32(&prcm_base->clksel_dss, 0, 5, PER_M4X2 + 1); /* set M4 */ + sr32(&prcm_base->clksel_dss, 0, 5, PER_M4X2); /* set M4 */ + sr32(&prcm_base->clksel_dss, 8, 5, PER_M3X2 + 1); /* set M3 */ + sr32(&prcm_base->clksel_dss, 8, 5, PER_M3X2); /* set M3 */ + sr32(&prcm_base->clksel3_pll, 0, 5, dpll_param_p->m2 + 1); /* set M2 */ + sr32(&prcm_base->clksel3_pll, 0, 5, dpll_param_p->m2); /* set M2 */ + /* Workaround end */ + + sr32(&prcm_base->clksel2_pll, 8, 11, dpll_param_p->m); /* set m */ + sr32(&prcm_base->clksel2_pll, 0, 7, dpll_param_p->n); /* set n */ + sr32(&prcm_base->clken_pll, 20, 4, dpll_param_p->fsel); /* FREQSEL */ + sr32(&prcm_base->clken_pll, 16, 3, PLL_LOCK); /* lock mode */ + wait_on_value(ST_PERIPH_CLK, 2, &prcm_base->idlest_ckgen, LDELAY); + + /* Getting the base address to MPU DPLL param table */ + dpll_param_p = (dpll_param *) get_mpu_dpll_param(); + + /* Moving it to the right sysclk and ES rev base */ + dpll_param_p = dpll_param_p + 3 * clk_index + sil_index; + + /* MPU DPLL (unlocked already) */ + + /* Set M2 */ + sr32(&prcm_base->clksel2_pll_mpu, 0, 5, dpll_param_p->m2); + /* Set M */ + sr32(&prcm_base->clksel1_pll_mpu, 8, 11, dpll_param_p->m); + /* Set N */ + sr32(&prcm_base->clksel1_pll_mpu, 0, 7, dpll_param_p->n); + /* FREQSEL */ + sr32(&prcm_base->clken_pll_mpu, 4, 4, dpll_param_p->fsel); + /* lock mode */ + sr32(&prcm_base->clken_pll_mpu, 0, 3, PLL_LOCK); + wait_on_value(ST_MPU_CLK, 1, &prcm_base->idlest_pll_mpu, LDELAY); + + /* Getting the base address to IVA DPLL param table */ + dpll_param_p = (dpll_param *) get_iva_dpll_param(); + + /* Moving it to the right sysclk and ES rev base */ + dpll_param_p = dpll_param_p + 3 * clk_index + sil_index; + + /* IVA DPLL (set to 12*20=240MHz) */ + sr32(&prcm_base->clken_pll_iva2, 0, 3, PLL_STOP); + wait_on_value(ST_IVA2_CLK, 0, &prcm_base->idlest_pll_iva2, LDELAY); + /* set M2 */ + sr32(&prcm_base->clksel2_pll_iva2, 0, 5, dpll_param_p->m2); + /* set M */ + sr32(&prcm_base->clksel1_pll_iva2, 8, 11, dpll_param_p->m); + /* set N */ + sr32(&prcm_base->clksel1_pll_iva2, 0, 7, dpll_param_p->n); + /* FREQSEL */ + sr32(&prcm_base->clken_pll_iva2, 4, 4, dpll_param_p->fsel); + /* lock mode */ + sr32(&prcm_base->clken_pll_iva2, 0, 3, PLL_LOCK); + wait_on_value(ST_IVA2_CLK, 1, &prcm_base->idlest_pll_iva2, LDELAY); + + /* Set up GPTimers to sys_clk source only */ + sr32(&prcm_base->clksel_per, 0, 8, 0xff); + sr32(&prcm_base->clksel_wkup, 0, 1, 1); + + sdelay(5000); +} + +/****************************************************************************** + * peripheral_enable() - Enable the clks & power for perifs (GPT2, UART1,...) + *****************************************************************************/ +void per_clocks_enable(void) +{ + prcm_t *prcm_base = (prcm_t *)PRCM_BASE; + + /* Enable GP2 timer. */ + sr32(&prcm_base->clksel_per, 0, 1, 0x1); /* GPT2 = sys clk */ + sr32(&prcm_base->iclken_per, 3, 1, 0x1); /* ICKen GPT2 */ + sr32(&prcm_base->fclken_per, 3, 1, 0x1); /* FCKen GPT2 */ + +#ifdef CONFIG_SYS_NS16550 + /* Enable UART1 clocks */ + sr32(&prcm_base->fclken1_core, 13, 1, 0x1); + sr32(&prcm_base->iclken1_core, 13, 1, 0x1); + + /* UART 3 Clocks */ + sr32(&prcm_base->fclken_per, 11, 1, 0x1); + sr32(&prcm_base->iclken_per, 11, 1, 0x1); +#endif +#ifdef CONFIG_DRIVER_OMAP34XX_I2C + /* Turn on all 3 I2C clocks */ + sr32(&prcm_base->fclken1_core, 15, 3, 0x7); + sr32(&prcm_base->iclken1_core, 15, 3, 0x7); /* I2C1,2,3 = on */ +#endif + /* Enable the ICLK for 32K Sync Timer as its used in udelay */ + sr32(&prcm_base->iclken_wkup, 2, 1, 0x1); + + sr32(&prcm_base->fclken_iva2, 0, 32, FCK_IVA2_ON); + sr32(&prcm_base->fclken1_core, 0, 32, FCK_CORE1_ON); + sr32(&prcm_base->iclken1_core, 0, 32, ICK_CORE1_ON); + sr32(&prcm_base->iclken2_core, 0, 32, ICK_CORE2_ON); + sr32(&prcm_base->fclken_wkup, 0, 32, FCK_WKUP_ON); + sr32(&prcm_base->iclken_wkup, 0, 32, ICK_WKUP_ON); + sr32(&prcm_base->fclken_dss, 0, 32, FCK_DSS_ON); + sr32(&prcm_base->iclken_dss, 0, 32, ICK_DSS_ON); + sr32(&prcm_base->fclken_cam, 0, 32, FCK_CAM_ON); + sr32(&prcm_base->iclken_cam, 0, 32, ICK_CAM_ON); + sr32(&prcm_base->fclken_per, 0, 32, FCK_PER_ON); + sr32(&prcm_base->iclken_per, 0, 32, ICK_PER_ON); + + sdelay(1000); +} diff --git a/cpu/arm_cortexa8/omap3/config.mk b/cpu/arm_cortexa8/omap3/config.mk new file mode 100644 index 0000000..fbb753e --- /dev/null +++ b/cpu/arm_cortexa8/omap3/config.mk @@ -0,0 +1,36 @@ +# +# (C) Copyright 2002 +# Gary Jennejohn, DENX Software Engineering, <gj@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 +# +PLATFORM_RELFLAGS += -fno-strict-aliasing -fno-common -ffixed-r8 \ + -msoft-float + +# Make ARMv5 to allow more compilers to work, even though its v7a. +PLATFORM_CPPFLAGS += -march=armv5 +# ========================================================================= +# +# Supply options according to compiler version +# +# ========================================================================= +PLATFORM_CPPFLAGS +=$(call cc-option) +PLATFORM_CPPFLAGS +=$(call cc-option,-mno-thumb-interwork,) +PLATFORM_RELFLAGS +=$(call cc-option,-mshort-load-bytes,\ + $(call cc-option,-malignment-traps,)) diff --git a/cpu/arm_cortexa8/omap3/interrupts.c b/cpu/arm_cortexa8/omap3/interrupts.c new file mode 100644 index 0000000..9e9817d --- /dev/null +++ b/cpu/arm_cortexa8/omap3/interrupts.c @@ -0,0 +1,297 @@ +/* + * (C) Copyright 2008 + * Texas Instruments + * + * Richard Woodruff <r-woodruff2@ti.com> + * Syed Moahmmed Khasim <khasim@ti.com> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/proc-armv/ptrace.h> + +#define TIMER_LOAD_VAL 0 + +#ifdef CONFIG_USE_IRQ +/* enable IRQ interrupts */ +void enable_interrupts(void) +{ + unsigned long temp; + __asm__ __volatile__("mrs %0, cpsr\n" + "bic %0, %0, #0x80\n" "msr cpsr_c, %0":"=r"(temp) + ::"memory"); +} + +/* + * disable IRQ/FIQ interrupts + * returns true if interrupts had been enabled before we disabled them + */ +int disable_interrupts(void) +{ + unsigned long old, temp; + __asm__ __volatile__("mrs %0, cpsr\n" + "orr %1, %0, #0xc0\n" + "msr cpsr_c, %1":"=r"(old), "=r"(temp) + ::"memory"); + return (old & 0x80) == 0; +} +#else +void enable_interrupts(void) +{ + return; +} +int disable_interrupts(void) +{ + return 0; +} +#endif + +void bad_mode(void) +{ + panic("Resetting CPU ...\n"); + reset_cpu(0); +} + +void show_regs(struct pt_regs *regs) +{ + unsigned long flags; + const char *processor_modes[] = { + "USER_26", "FIQ_26", "IRQ_26", "SVC_26", + "UK4_26", "UK5_26", "UK6_26", "UK7_26", + "UK8_26", "UK9_26", "UK10_26", "UK11_26", + "UK12_26", "UK13_26", "UK14_26", "UK15_26", + "USER_32", "FIQ_32", "IRQ_32", "SVC_32", + "UK4_32", "UK5_32", "UK6_32", "ABT_32", + "UK8_32", "UK9_32", "UK10_32", "UND_32", + "UK12_32", "UK13_32", "UK14_32", "SYS_32", + }; + + flags = condition_codes(regs); + + printf("pc : [<%08lx>] lr : [<%08lx>]\n" + "sp : %08lx ip : %08lx fp : %08lx\n", + instruction_pointer(regs), + regs->ARM_lr, regs->ARM_sp, regs->ARM_ip, regs->ARM_fp); + printf("r10: %08lx r9 : %08lx r8 : %08lx\n", + regs->ARM_r10, regs->ARM_r9, regs->ARM_r8); + printf("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n", + regs->ARM_r7, regs->ARM_r6, regs->ARM_r5, regs->ARM_r4); + printf("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n", + regs->ARM_r3, regs->ARM_r2, regs->ARM_r1, regs->ARM_r0); + printf("Flags: %c%c%c%c", + flags & CC_N_BIT ? 'N' : 'n', + flags & CC_Z_BIT ? 'Z' : 'z', + flags & CC_C_BIT ? 'C' : 'c', flags & CC_V_BIT ? 'V' : 'v'); + printf(" IRQs %s FIQs %s Mode %s%s\n", + interrupts_enabled(regs) ? "on" : "off", + fast_interrupts_enabled(regs) ? "on" : "off", + processor_modes[processor_mode(regs)], + thumb_mode(regs) ? " (T)" : ""); +} + +void do_undefined_instruction(struct pt_regs *pt_regs) +{ + printf("undefined instruction\n"); + show_regs(pt_regs); + bad_mode(); +} + +void do_software_interrupt(struct pt_regs *pt_regs) +{ + printf("software interrupt\n"); + show_regs(pt_regs); + bad_mode(); +} + +void do_prefetch_abort(struct pt_regs *pt_regs) +{ + printf("prefetch abort\n"); + show_regs(pt_regs); + bad_mode(); +} + +void do_data_abort(struct pt_regs *pt_regs) +{ + printf("data abort\n"); + show_regs(pt_regs); + bad_mode(); +} + +void do_not_used(struct pt_regs *pt_regs) +{ + printf("not used\n"); + show_regs(pt_regs); + bad_mode(); +} + +void do_fiq(struct pt_regs *pt_regs) +{ + printf("fast interrupt request\n"); + show_regs(pt_regs); + bad_mode(); +} + +void do_irq(struct pt_regs *pt_regs) +{ + printf("interrupt request\n"); + show_regs(pt_regs); + bad_mode(); +} + + +static ulong timestamp; +static ulong lastinc; +static gptimer_t *timer_base = (gptimer_t *)CONFIG_SYS_TIMERBASE; + +/* nothing really to do with interrupts, just starts up a counter. */ +int interrupt_init(void) +{ + /* start the counter ticking up, reload value on overflow */ + writel(TIMER_LOAD_VAL, &timer_base->tldr); + /* enable timer */ + writel((CONFIG_SYS_PVT << 2) | TCLR_PRE | TCLR_AR | TCLR_ST, + &timer_base->tclr); + + reset_timer_masked(); /* init the timestamp and lastinc value */ + + return 0; +} + +/* + * timer without interrupts + */ +void reset_timer(void) +{ + reset_timer_masked(); +} + +ulong get_timer(ulong base) +{ + return get_timer_masked() - base; +} + +void set_timer(ulong t) +{ + timestamp = t; +} + +/* delay x useconds AND perserve advance timstamp value */ +void udelay(unsigned long usec) +{ + ulong tmo, tmp; + + /* if "big" number, spread normalization to seconds */ + if (usec >= 1000) { + /* if "big" number, spread normalization to seconds */ + tmo = usec / 1000; + /* find number of "ticks" to wait to achieve target */ + tmo *= CONFIG_SYS_HZ; + tmo /= 1000; /* finish normalize. */ + } else {/* else small number, don't kill it prior to HZ multiply */ + tmo = usec * CONFIG_SYS_HZ; + tmo /= (1000 * 1000); + } + + tmp = get_timer(0); /* get current timestamp */ + /* if setting this forward will roll time stamp */ + if ((tmo + tmp + 1) < tmp) + /* reset "advancing" timestamp to 0, set lastinc value */ + reset_timer_masked(); + else + tmo += tmp; /* else, set advancing stamp wake up time */ + while (get_timer_masked() < tmo) /* loop till event */ + /*NOP*/; +} + +void reset_timer_masked(void) +{ + /* reset time, capture current incrementer value time */ + lastinc = readl(&timer_base->tcrr); + timestamp = 0; /* start "advancing" time stamp from 0 */ +} + +ulong get_timer_masked(void) +{ + ulong now = readl(&timer_base->tcrr); /* current tick value */ + + if (now >= lastinc) /* normal mode (non roll) */ + /* move stamp fordward with absoulte diff ticks */ + timestamp += (now - lastinc); + else /* we have rollover of incrementer */ + timestamp += (0xFFFFFFFF - lastinc) + now; + lastinc = now; + return timestamp; +} + +/* waits specified delay value and resets timestamp */ +void udelay_masked(unsigned long usec) +{ + ulong tmo; + ulong endtime; + signed long diff; + + /* if "big" number, spread normalization to seconds */ + if (usec >= 1000) { + /* start to normalize for usec to ticks per sec */ + tmo = usec / 1000; + /* find number of "ticks" to wait to achieve target */ + tmo *= CONFIG_SYS_HZ; + tmo /= 1000; /* finish normalize. */ + } else { /* else small number, */ + /* don't kill it prior to HZ multiply */ + tmo = usec * CONFIG_SYS_HZ; + tmo /= (1000 * 1000); + } + endtime = get_timer_masked() + tmo; + + do { + ulong now = get_timer_masked(); + diff = endtime - now; + } while (diff >= 0); +} + +/* + * 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) +{ + 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) +{ + ulong tbclk; + tbclk = CONFIG_SYS_HZ; + return tbclk; +} diff --git a/cpu/arm_cortexa8/omap3/lowlevel_init.S b/cpu/arm_cortexa8/omap3/lowlevel_init.S new file mode 100644 index 0000000..cf1f927 --- /dev/null +++ b/cpu/arm_cortexa8/omap3/lowlevel_init.S @@ -0,0 +1,361 @@ +/* + * Board specific setup info + * + * (C) Copyright 2008 + * Texas Instruments, <www.ti.com> + * + * Initial Code by: + * Richard Woodruff <r-woodruff2@ti.com> + * Syed Mohammed Khasim <khasim@ti.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <config.h> +#include <version.h> +#include <asm/arch/mem.h> +#include <asm/arch/clocks_omap3.h> + +_TEXT_BASE: + .word TEXT_BASE /* sdram load addr from config.mk */ + +#if !defined(CONFIG_SYS_NAND_BOOT) && !defined(CONFIG_SYS_NAND_BOOT) +/************************************************************************** + * cpy_clk_code: relocates clock code into SRAM where its safer to execute + * R1 = SRAM destination address. + *************************************************************************/ +.global cpy_clk_code + cpy_clk_code: + /* Copy DPLL code into SRAM */ + adr r0, go_to_speed /* get addr of clock setting code */ + mov r2, #384 /* r2 size to copy (div by 32 bytes) */ + mov r1, r1 /* r1 <- dest address (passed in) */ + add r2, r2, r0 /* r2 <- source end address */ +next2: + ldmia r0!, {r3 - r10} /* copy from source address [r0] */ + stmia r1!, {r3 - r10} /* copy to target address [r1] */ + cmp r0, r2 /* until source end address [r2] */ + bne next2 + mov pc, lr /* back to caller */ + +/* *************************************************************************** + * go_to_speed: -Moves to bypass, -Commits clock dividers, -puts dpll at speed + * -executed from SRAM. + * R0 = CM_CLKEN_PLL-bypass value + * R1 = CM_CLKSEL1_PLL-m, n, and divider values + * R2 = CM_CLKSEL_CORE-divider values + * R3 = CM_IDLEST_CKGEN - addr dpll lock wait + * + * Note: If core unlocks/relocks and SDRAM is running fast already it gets + * confused. A reset of the controller gets it back. Taking away its + * L3 when its not in self refresh seems bad for it. Normally, this + * code runs from flash before SDR is init so that should be ok. + ****************************************************************************/ +.global go_to_speed + go_to_speed: + stmfd sp!, {r4 - r6} + + /* move into fast relock bypass */ + ldr r4, pll_ctl_add + str r0, [r4] +wait1: + ldr r5, [r3] /* get status */ + and r5, r5, #0x1 /* isolate core status */ + cmp r5, #0x1 /* still locked? */ + beq wait1 /* if lock, loop */ + + /* set new dpll dividers _after_ in bypass */ + ldr r5, pll_div_add1 + str r1, [r5] /* set m, n, m2 */ + ldr r5, pll_div_add2 + str r2, [r5] /* set l3/l4/.. dividers*/ + ldr r5, pll_div_add3 /* wkup */ + ldr r2, pll_div_val3 /* rsm val */ + str r2, [r5] + ldr r5, pll_div_add4 /* gfx */ + ldr r2, pll_div_val4 + str r2, [r5] + ldr r5, pll_div_add5 /* emu */ + ldr r2, pll_div_val5 + str r2, [r5] + + /* now prepare GPMC (flash) for new dpll speed */ + /* flash needs to be stable when we jump back to it */ + ldr r5, flash_cfg3_addr + ldr r2, flash_cfg3_val + str r2, [r5] + ldr r5, flash_cfg4_addr + ldr r2, flash_cfg4_val + str r2, [r5] + ldr r5, flash_cfg5_addr + ldr r2, flash_cfg5_val + str r2, [r5] + ldr r5, flash_cfg1_addr + ldr r2, [r5] + orr r2, r2, #0x3 /* up gpmc divider */ + str r2, [r5] + + /* lock DPLL3 and wait a bit */ + orr r0, r0, #0x7 /* set up for lock mode */ + str r0, [r4] /* lock */ + nop /* ARM slow at this point working at sys_clk */ + nop + nop + nop +wait2: + ldr r5, [r3] /* get status */ + and r5, r5, #0x1 /* isolate core status */ + cmp r5, #0x1 /* still locked? */ + bne wait2 /* if lock, loop */ + nop + nop + nop + nop + ldmfd sp!, {r4 - r6} + mov pc, lr /* back to caller, locked */ + +_go_to_speed: .word go_to_speed + +/* these constants need to be close for PIC code */ +/* The Nor has to be in the Flash Base CS0 for this condition to happen */ +flash_cfg1_addr: + .word (GPMC_CONFIG_CS0 + GPMC_CONFIG1) +flash_cfg3_addr: + .word (GPMC_CONFIG_CS0 + GPMC_CONFIG3) +flash_cfg3_val: + .word STNOR_GPMC_CONFIG3 +flash_cfg4_addr: + .word (GPMC_CONFIG_CS0 + GPMC_CONFIG4) +flash_cfg4_val: + .word STNOR_GPMC_CONFIG4 +flash_cfg5_val: + .word STNOR_GPMC_CONFIG5 +flash_cfg5_addr: + .word (GPMC_CONFIG_CS0 + GPMC_CONFIG5) +pll_ctl_add: + .word CM_CLKEN_PLL +pll_div_add1: + .word CM_CLKSEL1_PLL +pll_div_add2: + .word CM_CLKSEL_CORE +pll_div_add3: + .word CM_CLKSEL_WKUP +pll_div_val3: + .word (WKUP_RSM << 1) +pll_div_add4: + .word CM_CLKSEL_GFX +pll_div_val4: + .word (GFX_DIV << 0) +pll_div_add5: + .word CM_CLKSEL1_EMU +pll_div_val5: + .word CLSEL1_EMU_VAL + +#endif + +.globl lowlevel_init +lowlevel_init: + ldr sp, SRAM_STACK + str ip, [sp] /* stash old link register */ + mov ip, lr /* save link reg across call */ + bl s_init /* go setup pll, mux, memory */ + ldr ip, [sp] /* restore save ip */ + mov lr, ip /* restore link reg */ + + /* back to arch calling code */ + mov pc, lr + + /* the literal pools origin */ + .ltorg + +REG_CONTROL_STATUS: + .word CONTROL_STATUS +SRAM_STACK: + .word LOW_LEVEL_SRAM_STACK + +/* DPLL(1-4) PARAM TABLES */ + +/* + * Each of the tables has M, N, FREQSEL, M2 values defined for nominal + * OPP (1.2V). The fields are defined according to dpll_param struct (clock.c). + * The values are defined for all possible sysclk and for ES1 and ES2. + */ + +mpu_dpll_param: +/* 12MHz */ +/* ES1 */ +.word MPU_M_12_ES1, MPU_N_12_ES1, MPU_FSEL_12_ES1, MPU_M2_12_ES1 +/* ES2 */ +.word MPU_M_12_ES2, MPU_N_12_ES2, MPU_FSEL_12_ES2, MPU_M2_ES2 +/* 3410 */ +.word MPU_M_12, MPU_N_12, MPU_FSEL_12, MPU_M2_12 + +/* 13MHz */ +/* ES1 */ +.word MPU_M_13_ES1, MPU_N_13_ES1, MPU_FSEL_13_ES1, MPU_M2_13_ES1 +/* ES2 */ +.word MPU_M_13_ES2, MPU_N_13_ES2, MPU_FSEL_13_ES2, MPU_M2_13_ES2 +/* 3410 */ +.word MPU_M_13, MPU_N_13, MPU_FSEL_13, MPU_M2_13 + +/* 19.2MHz */ +/* ES1 */ +.word MPU_M_19P2_ES1, MPU_N_19P2_ES1, MPU_FSEL_19P2_ES1, MPU_M2_19P2_ES1 +/* ES2 */ +.word MPU_M_19P2_ES2, MPU_N_19P2_ES2, MPU_FSEL_19P2_ES2, MPU_M2_19P2_ES2 +/* 3410 */ +.word MPU_M_19P2, MPU_N_19P2, MPU_FSEL_19P2, MPU_M2_19P2 + +/* 26MHz */ +/* ES1 */ +.word MPU_M_26_ES1, MPU_N_26_ES1, MPU_FSEL_26_ES1, MPU_M2_26_ES1 +/* ES2 */ +.word MPU_M_26_ES2, MPU_N_26_ES2, MPU_FSEL_26_ES2, MPU_M2_26_ES2 +/* 3410 */ +.word MPU_M_26, MPU_N_26, MPU_FSEL_26, MPU_M2_26 + +/* 38.4MHz */ +/* ES1 */ +.word MPU_M_38P4_ES1, MPU_N_38P4_ES1, MPU_FSEL_38P4_ES1, MPU_M2_38P4_ES1 +/* ES2 */ +.word MPU_M_38P4_ES2, MPU_N_38P4_ES2, MPU_FSEL_38P4_ES2, MPU_M2_38P4_ES2 +/* 3410 */ +.word MPU_M_38P4, MPU_N_38P4, MPU_FSEL_38P4, MPU_M2_38P4 + + +.globl get_mpu_dpll_param +get_mpu_dpll_param: + adr r0, mpu_dpll_param + mov pc, lr + +iva_dpll_param: +/* 12MHz */ +/* ES1 */ +.word IVA_M_12_ES1, IVA_N_12_ES1, IVA_FSEL_12_ES1, IVA_M2_12_ES1 +/* ES2 */ +.word IVA_M_12_ES2, IVA_N_12_ES2, IVA_FSEL_12_ES2, IVA_M2_12_ES2 +/* 3410 */ +.word IVA_M_12, IVA_N_12, IVA_FSEL_12, IVA_M2_12 + +/* 13MHz */ +/* ES1 */ +.word IVA_M_13_ES1, IVA_N_13_ES1, IVA_FSEL_13_ES1, IVA_M2_13_ES1 +/* ES2 */ +.word IVA_M_13_ES2, IVA_N_13_ES2, IVA_FSEL_13_ES2, IVA_M2_13_ES2 +/* 3410 */ +.word IVA_M_13, IVA_N_13, IVA_FSEL_13, IVA_M2_13 + +/* 19.2MHz */ +/* ES1 */ +.word IVA_M_19P2_ES1, IVA_N_19P2_ES1, IVA_FSEL_19P2_ES1, IVA_M2_19P2_ES1 +/* ES2 */ +.word IVA_M_19P2_ES2, IVA_N_19P2_ES2, IVA_FSEL_19P2_ES2, IVA_M2_19P2_ES2 +/* 3410 */ +.word IVA_M_19P2, IVA_N_19P2, IVA_FSEL_19P2, IVA_M2_19P2 + +/* 26MHz */ +/* ES1 */ +.word IVA_M_26_ES1, IVA_N_26_ES1, IVA_FSEL_26_ES1, IVA_M2_26_ES1 +/* ES2 */ +.word IVA_M_26_ES2, IVA_N_26_ES2, IVA_FSEL_26_ES2, IVA_M2_26_ES2 +/* 3410 */ +.word IVA_M_26, IVA_N_26, IVA_FSEL_26, IVA_M2_26 + +/* 38.4MHz */ +/* ES1 */ +.word IVA_M_38P4_ES1, IVA_N_38P4_ES1, IVA_FSEL_38P4_ES1, IVA_M2_38P4_ES1 +/* ES2 */ +.word IVA_M_38P4_ES2, IVA_N_38P4_ES2, IVA_FSEL_38P4_ES2, IVA_M2_38P4_ES2 +/* 3410 */ +.word IVA_M_38P4, IVA_N_38P4, IVA_FSEL_38P4, IVA_M2_38P4 + + +.globl get_iva_dpll_param +get_iva_dpll_param: + adr r0, iva_dpll_param + mov pc, lr + +/* Core DPLL targets for L3 at 166 & L133 */ +core_dpll_param: +/* 12MHz */ +/* ES1 */ +.word CORE_M_12_ES1, CORE_N_12_ES1, CORE_FSL_12_ES1, CORE_M2_12_ES1 +/* ES2 */ +.word CORE_M_12, CORE_N_12, CORE_FSEL_12, CORE_M2_12 +/* 3410 */ +.word CORE_M_12, CORE_N_12, CORE_FSEL_12, CORE_M2_12 + +/* 13MHz */ +/* ES1 */ +.word CORE_M_13_ES1, CORE_N_13_ES1, CORE_FSL_13_ES1, CORE_M2_13_ES1 +/* ES2 */ +.word CORE_M_13, CORE_N_13, CORE_FSEL_13, CORE_M2_13 +/* 3410 */ +.word CORE_M_13, CORE_N_13, CORE_FSEL_13, CORE_M2_13 + +/* 19.2MHz */ +/* ES1 */ +.word CORE_M_19P2_ES1, CORE_N_19P2_ES1, CORE_FSL_19P2_ES1, CORE_M2_19P2_ES1 +/* ES2 */ +.word CORE_M_19P2, CORE_N_19P2, CORE_FSEL_19P2, CORE_M2_19P2 +/* 3410 */ +.word CORE_M_19P2, CORE_N_19P2, CORE_FSEL_19P2, CORE_M2_19P2 + +/* 26MHz */ +/* ES1 */ +.word CORE_M_26_ES1, CORE_N_26_ES1, CORE_FSL_26_ES1, CORE_M2_26_ES1 +/* ES2 */ +.word CORE_M_26, CORE_N_26, CORE_FSEL_26, CORE_M2_26 +/* 3410 */ +.word CORE_M_26, CORE_N_26, CORE_FSEL_26, CORE_M2_26 + +/* 38.4MHz */ +/* ES1 */ +.word CORE_M_38P4_ES1, CORE_N_38P4_ES1, CORE_FSL_38P4_ES1, CORE_M2_38P4_ES1 +/* ES2 */ +.word CORE_M_38P4, CORE_N_38P4, CORE_FSEL_38P4, CORE_M2_38P4 +/* 3410 */ +.word CORE_M_38P4, CORE_N_38P4, CORE_FSEL_38P4, CORE_M2_38P4 + +.globl get_core_dpll_param +get_core_dpll_param: + adr r0, core_dpll_param + mov pc, lr + +/* PER DPLL values are same for both ES1 and ES2 */ +per_dpll_param: +/* 12MHz */ +.word PER_M_12, PER_N_12, PER_FSEL_12, PER_M2_12 + +/* 13MHz */ +.word PER_M_13, PER_N_13, PER_FSEL_13, PER_M2_13 + +/* 19.2MHz */ +.word PER_M_19P2, PER_N_19P2, PER_FSEL_19P2, PER_M2_19P2 + +/* 26MHz */ +.word PER_M_26, PER_N_26, PER_FSEL_26, PER_M2_26 + +/* 38.4MHz */ +.word PER_M_38P4, PER_N_38P4, PER_FSEL_38P4, PER_M2_38P4 + +.globl get_per_dpll_param +get_per_dpll_param: + adr r0, per_dpll_param + mov pc, lr diff --git a/cpu/arm_cortexa8/omap3/mem.c b/cpu/arm_cortexa8/omap3/mem.c new file mode 100644 index 0000000..3cc22c4 --- /dev/null +++ b/cpu/arm_cortexa8/omap3/mem.c @@ -0,0 +1,284 @@ +/* + * (C) Copyright 2008 + * Texas Instruments, <www.ti.com> + * + * Author : + * Manikandan Pillai <mani.pillai@ti.com> + * + * Initial Code from: + * Richard Woodruff <r-woodruff2@ti.com> + * Syed Mohammed Khasim <khasim@ti.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/mem.h> +#include <asm/arch/sys_proto.h> +#include <command.h> + +/* + * Only One NAND allowed on board at a time. + * The GPMC CS Base for the same + */ +unsigned int boot_flash_base; +unsigned int boot_flash_off; +unsigned int boot_flash_sec; +unsigned int boot_flash_type; +volatile unsigned int boot_flash_env_addr; + +#if defined(CONFIG_CMD_NAND) +static u32 gpmc_m_nand[GPMC_MAX_REG] = { + M_NAND_GPMC_CONFIG1, + M_NAND_GPMC_CONFIG2, + M_NAND_GPMC_CONFIG3, + M_NAND_GPMC_CONFIG4, + M_NAND_GPMC_CONFIG5, + M_NAND_GPMC_CONFIG6, 0 +}; + +gpmc_csx_t *nand_cs_base; +gpmc_t *gpmc_cfg_base; + +#if defined(CONFIG_ENV_IS_IN_NAND) +#define GPMC_CS 0 +#else +#define GPMC_CS 1 +#endif + +#endif + +#if defined(CONFIG_CMD_ONENAND) +static u32 gpmc_onenand[GPMC_MAX_REG] = { + ONENAND_GPMC_CONFIG1, + ONENAND_GPMC_CONFIG2, + ONENAND_GPMC_CONFIG3, + ONENAND_GPMC_CONFIG4, + ONENAND_GPMC_CONFIG5, + ONENAND_GPMC_CONFIG6, 0 +}; + +gpmc_csx_t *onenand_cs_base; + +#if defined(CONFIG_ENV_IS_IN_ONENAND) +#define GPMC_CS 0 +#else +#define GPMC_CS 1 +#endif + +#endif + +static sdrc_t *sdrc_base = (sdrc_t *)OMAP34XX_SDRC_BASE; + +/************************************************************************** + * make_cs1_contiguous() - for es2 and above remap cs1 behind cs0 to allow + * command line mem=xyz use all memory with out discontinuous support + * compiled in. Could do it at the ATAG, but there really is two banks... + * Called as part of 2nd phase DDR init. + **************************************************************************/ +void make_cs1_contiguous(void) +{ + u32 size, a_add_low, a_add_high; + + size = get_sdr_cs_size(CS0); + size /= SZ_32M; /* find size to offset CS1 */ + a_add_high = (size & 3) << 8; /* set up low field */ + a_add_low = (size & 0x3C) >> 2; /* set up high field */ + writel((a_add_high | a_add_low), &sdrc_base->cs_cfg); + +} + +/******************************************************** + * mem_ok() - test used to see if timings are correct + * for a part. Helps in guessing which part + * we are currently using. + *******************************************************/ +u32 mem_ok(u32 cs) +{ + u32 val1, val2, addr; + u32 pattern = 0x12345678; + + addr = OMAP34XX_SDRC_CS0 + get_sdr_cs_offset(cs); + + writel(0x0, addr + 0x400); /* clear pos A */ + writel(pattern, addr); /* pattern to pos B */ + writel(0x0, addr + 4); /* remove pattern off the bus */ + val1 = readl(addr + 0x400); /* get pos A value */ + val2 = readl(addr); /* get val2 */ + + if ((val1 != 0) || (val2 != pattern)) /* see if pos A val changed */ + return 0; + else + return 1; +} + +/******************************************************** + * sdrc_init() - init the sdrc chip selects CS0 and CS1 + * - early init routines, called from flash or + * SRAM. + *******************************************************/ +void sdrc_init(void) +{ + /* only init up first bank here */ + do_sdrc_init(CS0, EARLY_INIT); +} + +/************************************************************************* + * do_sdrc_init(): initialize the SDRAM for use. + * -code sets up SDRAM basic SDRC timings for CS0 + * -optimal settings can be placed here, or redone after i2c + * inspection of board info + * + * - code called once in C-Stack only context for CS0 and a possible 2nd + * time depending on memory configuration from stack+global context + **************************************************************************/ + +void do_sdrc_init(u32 cs, u32 early) +{ + sdrc_actim_t *sdrc_actim_base; + + if(cs) + sdrc_actim_base = (sdrc_actim_t *)SDRC_ACTIM_CTRL1_BASE; + else + sdrc_actim_base = (sdrc_actim_t *)SDRC_ACTIM_CTRL0_BASE; + + if (early) { + /* reset sdrc controller */ + writel(SOFTRESET, &sdrc_base->sysconfig); + wait_on_value(RESETDONE, RESETDONE, &sdrc_base->status, + 12000000); + writel(0, &sdrc_base->sysconfig); + + /* setup sdrc to ball mux */ + writel(SDP_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(ENADLL | DLLPHASE_90, &sdrc_base->dlla_ctrl); + sdelay(0x20000); + } + + writel(RASWIDTH_13BITS | CASWIDTH_10BITS | ADDRMUXLEGACY | + RAMSIZE_128 | BANKALLOCATION | B32NOT16 | B32NOT16 | + DEEPPD | DDR_SDRAM, &sdrc_base->cs[cs].mcfg); + writel(ARCV | ARE_ARCV_1, &sdrc_base->cs[cs].rfr_ctrl); + writel(V_ACTIMA_165, &sdrc_actim_base->ctrla); + writel(V_ACTIMB_165, &sdrc_actim_base->ctrlb); + + writel(CMD_NOP, &sdrc_base ->cs[cs].manual); + writel(CMD_PRECHARGE, &sdrc_base->cs[cs].manual); + writel(CMD_AUTOREFRESH, &sdrc_base->cs[cs].manual); + writel(CMD_AUTOREFRESH, &sdrc_base->cs[cs].manual); + + /* + * CAS latency 3, Write Burst = Read Burst, Serial Mode, + * Burst length = 4 + */ + writel(CASL3 | BURSTLENGTH4, &sdrc_base->cs[cs].mr); + + if (!mem_ok(cs)) + writel(0, &sdrc_base->cs[cs].mcfg); +} + +void enable_gpmc_config(u32 *gpmc_config, gpmc_csx_t *gpmc_cs_base, u32 base, + u32 size) +{ + writel(0, &gpmc_cs_base->config7); + sdelay(1000); + /* Delay for settling */ + writel(gpmc_config[0], &gpmc_cs_base->config1); + writel(gpmc_config[1], &gpmc_cs_base->config2); + writel(gpmc_config[2], &gpmc_cs_base->config3); + writel(gpmc_config[3], &gpmc_cs_base->config4); + writel(gpmc_config[4], &gpmc_cs_base->config5); + writel(gpmc_config[5], &gpmc_cs_base->config6); + /* Enable the config */ + writel((((size & 0xF) << 8) | ((base >> 24) & 0x3F) | + (1 << 6)), &gpmc_cs_base->config7); + sdelay(2000); +} + +/***************************************************** + * gpmc_init(): init gpmc bus + * Init GPMC for x16, MuxMode (SDRAM in x32). + * This code can only be executed from SRAM or SDRAM. + *****************************************************/ +void gpmc_init(void) +{ + /* putting a blanket check on GPMC based on ZeBu for now */ + u32 *gpmc_config = NULL; + gpmc_t *gpmc_base = (gpmc_t *)GPMC_BASE; + gpmc_csx_t *gpmc_cs_base = (gpmc_csx_t *)GPMC_CONFIG_CS0_BASE; + u32 base = 0; + u32 size = 0; + u32 f_off = CONFIG_SYS_MONITOR_LEN; + u32 f_sec = 0; + u32 config = 0; + + /* global settings */ + writel(0, &gpmc_base->irqenable); /* isr's sources masked */ + writel(0, &gpmc_base->timeout_control);/* timeout disable */ + + config = readl(&gpmc_base->config); + config &= (~0xf00); + writel(config, &gpmc_base->config); + + /* + * Disable the GPMC0 config set by ROM code + * It conflicts with our MPDB (both at 0x08000000) + */ + writel(0, &gpmc_cs_base->config7); + sdelay(1000); + +#if defined(CONFIG_CMD_NAND) /* CS 0 */ + gpmc_config = gpmc_m_nand; + gpmc_cfg_base = gpmc_base; + nand_cs_base = (gpmc_csx_t *)(GPMC_CONFIG_CS0_BASE + + (GPMC_CS * GPMC_CONFIG_WIDTH)); + base = PISMO1_NAND_BASE; + size = PISMO1_NAND_SIZE; + enable_gpmc_config(gpmc_config, nand_cs_base, base, size); +#if defined(CONFIG_ENV_IS_IN_NAND) + f_off = SMNAND_ENV_OFFSET; + f_sec = SZ_128K; + /* env setup */ + boot_flash_base = base; + boot_flash_off = f_off; + boot_flash_sec = f_sec; + boot_flash_env_addr = f_off; +#endif +#endif + +#if defined(CONFIG_CMD_ONENAND) + gpmc_config = gpmc_onenand; + onenand_cs_base = (gpmc_csx_t *)(GPMC_CONFIG_CS0_BASE + + (GPMC_CS * GPMC_CONFIG_WIDTH)); + base = PISMO1_ONEN_BASE; + size = PISMO1_ONEN_SIZE; + enable_gpmc_config(gpmc_config, onenand_cs_base, base, size); +#if defined(CONFIG_ENV_IS_IN_ONENAND) + f_off = ONENAND_ENV_OFFSET; + f_sec = SZ_128K; + /* env setup */ + boot_flash_base = base; + boot_flash_off = f_off; + boot_flash_sec = f_sec; + boot_flash_env_addr = f_off; +#endif +#endif +} diff --git a/cpu/arm_cortexa8/omap3/sys_info.c b/cpu/arm_cortexa8/omap3/sys_info.c new file mode 100644 index 0000000..28a1020 --- /dev/null +++ b/cpu/arm_cortexa8/omap3/sys_info.c @@ -0,0 +1,281 @@ +/* + * (C) Copyright 2008 + * Texas Instruments, <www.ti.com> + * + * Author : + * Manikandan Pillai <mani.pillai@ti.com> + * + * Derived from Beagle Board and 3430 SDP code by + * Richard Woodruff <r-woodruff2@ti.com> + * Syed Mohammed Khasim <khasim@ti.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/mem.h> /* get mem tables */ +#include <asm/arch/sys_proto.h> +#include <i2c.h> + +extern omap3_sysinfo sysinfo; +static gpmc_csx_t *gpmc_cs_base = (gpmc_csx_t *)GPMC_CONFIG_CS0_BASE; +static sdrc_t *sdrc_base = (sdrc_t *)OMAP34XX_SDRC_BASE; +static ctrl_t *ctrl_base = (ctrl_t *)OMAP34XX_CTRL_BASE; + +/****************************************** + * get_cpu_type(void) - extract cpu info + ******************************************/ +u32 get_cpu_type(void) +{ + return readl(&ctrl_base->ctrl_omap_stat); +} + +/****************************************** + * get_cpu_rev(void) - extract version info + ******************************************/ +u32 get_cpu_rev(void) +{ + u32 cpuid = 0; + + /* + * On ES1.0 the IDCODE register is not exposed on L4 + * so using CPU ID to differentiate + * between ES2.0 and ES1.0. + */ + __asm__ __volatile__("mrc p15, 0, %0, c0, c0, 0":"=r"(cpuid)); + if ((cpuid & 0xf) == 0x0) + return CPU_3430_ES1; + else + return CPU_3430_ES2; + +} + +/**************************************************** + * is_mem_sdr() - return 1 if mem type in use is SDR + ****************************************************/ +u32 is_mem_sdr(void) +{ + if (readl(&sdrc_base->cs[CS0].mr) == SDP_SDRC_MR_0_SDR) + return 1; + return 0; +} + +/*********************************************************************** + * get_cs0_size() - get size of chip select 0/1 + ************************************************************************/ +u32 get_sdr_cs_size(u32 cs) +{ + u32 size; + + /* get ram size field */ + size = readl(&sdrc_base->cs[cs].mcfg) >> 8; + size &= 0x3FF; /* remove unwanted bits */ + size *= SZ_2M; /* find size in MB */ + return size; +} + +/*********************************************************************** + * get_sdr_cs_offset() - get offset of cs from cs0 start + ************************************************************************/ +u32 get_sdr_cs_offset(u32 cs) +{ + u32 offset; + + if (!cs) + return 0; + + offset = readl(&sdrc_base->cs_cfg); + offset = (offset & 15) << 27 | (offset & 0x30) >> 17; + + return offset; +} + +/*********************************************************************** + * get_board_type() - get board type based on current production stats. + * - NOTE-1-: 2 I2C EEPROMs will someday be populated with proper info. + * when they are available we can get info from there. This should + * be correct of all known boards up until today. + * - NOTE-2- EEPROMs are populated but they are updated very slowly. To + * avoid waiting on them we will use ES version of the chip to get info. + * A later version of the FPGA migth solve their speed issue. + ************************************************************************/ +u32 get_board_type(void) +{ + if (get_cpu_rev() == CPU_3430_ES2) + return sysinfo.board_type_v2; + else + return sysinfo.board_type_v1; +} + +/*************************************************************************** + * get_gpmc0_base() - Return current address hardware will be + * fetching from. The below effectively gives what is correct, its a bit + * mis-leading compared to the TRM. For the most general case the mask + * needs to be also taken into account this does work in practice. + * - for u-boot we currently map: + * -- 0 to nothing, + * -- 4 to flash + * -- 8 to enent + * -- c to wifi + ****************************************************************************/ +u32 get_gpmc0_base(void) +{ + u32 b; + + b = readl(&gpmc_cs_base->config7); + b &= 0x1F; /* keep base [5:0] */ + b = b << 24; /* ret 0x0b000000 */ + return b; +} + +/******************************************************************* + * get_gpmc0_width() - See if bus is in x8 or x16 (mainly for nand) + *******************************************************************/ +u32 get_gpmc0_width(void) +{ + return WIDTH_16BIT; +} + +/************************************************************************* + * get_board_rev() - setup to pass kernel board revision information + * returns:(bit[0-3] sub version, higher bit[7-4] is higher version) + *************************************************************************/ +u32 get_board_rev(void) +{ + return 0x20; +} + +/********************************************************************* + * display_board_info() - print banner with board info. + *********************************************************************/ +void display_board_info(u32 btype) +{ + char *cpu_s, *mem_s, *sec_s; + + switch (get_cpu_type()) { + case OMAP3503: + cpu_s = "3503"; + break; + case OMAP3515: + cpu_s = "3515"; + break; + case OMAP3525: + cpu_s = "3525"; + break; + case OMAP3530: + cpu_s = "3530"; + break; + default: + cpu_s = "35XX"; + break; + } + + if (is_mem_sdr()) + mem_s = "mSDR"; + else + mem_s = "LPDDR"; + + switch (get_device_type()) { + case TST_DEVICE: + sec_s = "TST"; + break; + case EMU_DEVICE: + sec_s = "EMU"; + break; + case HS_DEVICE: + sec_s = "HS"; + break; + case GP_DEVICE: + sec_s = "GP"; + break; + default: + sec_s = "?"; + } + + + printf("OMAP%s-%s rev %d, CPU-OPP2 L3-165MHz\n", cpu_s, + sec_s, get_cpu_rev()); + printf("%s + %s/%s\n", sysinfo.board_string, + mem_s, sysinfo.nand_string); + +} + +/******************************************************** + * get_base(); get upper addr of current execution + *******************************************************/ +u32 get_base(void) +{ + u32 val; + + __asm__ __volatile__("mov %0, pc \n":"=r"(val)::"memory"); + val &= 0xF0000000; + val >>= 28; + return val; +} + +/******************************************************** + * is_running_in_flash() - tell if currently running in + * FLASH. + *******************************************************/ +u32 is_running_in_flash(void) +{ + if (get_base() < 4) + return 1; /* in FLASH */ + + return 0; /* running in SRAM or SDRAM */ +} + +/******************************************************** + * is_running_in_sram() - tell if currently running in + * SRAM. + *******************************************************/ +u32 is_running_in_sram(void) +{ + if (get_base() == 4) + return 1; /* in SRAM */ + + return 0; /* running in FLASH or SDRAM */ +} + +/******************************************************** + * is_running_in_sdram() - tell if currently running in + * SDRAM. + *******************************************************/ +u32 is_running_in_sdram(void) +{ + if (get_base() > 4) + return 1; /* in SDRAM */ + + return 0; /* running in SRAM or FLASH */ +} + +/*************************************************************** + * get_boot_type() - Is this an XIP type device or a stream one + * bits 4-0 specify type. Bit 5 says mem/perif + ***************************************************************/ +u32 get_boot_type(void) +{ + return (readl(&ctrl_base->status) & SYSBOOT_MASK); +} + +/************************************************************* + * get_device_type(): tell if GP/HS/EMU/TST + *************************************************************/ +u32 get_device_type(void) +{ + return ((readl(&ctrl_base->status) & (DEVICE_MASK)) >> 8); +} diff --git a/cpu/arm_cortexa8/omap3/syslib.c b/cpu/arm_cortexa8/omap3/syslib.c new file mode 100644 index 0000000..9ced495 --- /dev/null +++ b/cpu/arm_cortexa8/omap3/syslib.c @@ -0,0 +1,72 @@ +/* + * (C) Copyright 2008 + * Texas Instruments, <www.ti.com> + * + * Richard Woodruff <r-woodruff2@ti.com> + * Syed Mohammed Khasim <khasim@ti.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/mem.h> +#include <asm/arch/clocks.h> +#include <asm/arch/sys_proto.h> + +/************************************************************ + * sdelay() - simple spin loop. Will be constant time as + * its generally used in bypass conditions only. This + * is necessary until timers are accessible. + * + * not inline to increase chances its in cache when called + *************************************************************/ +void sdelay(unsigned long loops) +{ + __asm__ volatile ("1:\n" "subs %0, %1, #1\n" + "bne 1b":"=r" (loops):"0"(loops)); +} + +/***************************************************************** + * sr32 - clear & set a value in a bit range for a 32 bit address + *****************************************************************/ +void sr32(void *addr, u32 start_bit, u32 num_bits, u32 value) +{ + u32 tmp, msk = 0; + msk = 1 << num_bits; + --msk; + tmp = readl((u32)addr) & ~(msk << start_bit); + tmp |= value << start_bit; + writel(tmp, (u32)addr); +} + +/********************************************************************* + * wait_on_value() - common routine to allow waiting for changes in + * volatile regs. + *********************************************************************/ +u32 wait_on_value(u32 read_bit_mask, u32 match_value, void *read_addr, + u32 bound) +{ + u32 i = 0, val; + do { + ++i; + val = readl((u32)read_addr) & read_bit_mask; + if (val == match_value) + return 1; + if (i == bound) + return 0; + } while (1); +} diff --git a/cpu/arm_cortexa8/start.S b/cpu/arm_cortexa8/start.S new file mode 100644 index 0000000..07acdbd --- /dev/null +++ b/cpu/arm_cortexa8/start.S @@ -0,0 +1,516 @@ +/* + * armboot - Startup Code for OMAP3530/ARM Cortex CPU-core + * + * Copyright (c) 2004 Texas Instruments <r-woodruff2@ti.com> + * + * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> + * Copyright (c) 2002 Alex Züpke <azu@sysgo.de> + * Copyright (c) 2002 Gary Jennejohn <gj@denx.de> + * Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com> + * Copyright (c) 2003 Kshitij <kshitij@ti.com> + * Copyright (c) 2006-2008 Syed Mohammed Khasim <x0khasim@ti.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <config.h> +#include <version.h> + +.globl _start +_start: b reset + ldr pc, _undefined_instruction + ldr pc, _software_interrupt + ldr pc, _prefetch_abort + ldr pc, _data_abort + ldr pc, _not_used + ldr pc, _irq + ldr pc, _fiq + +_undefined_instruction: .word undefined_instruction +_software_interrupt: .word software_interrupt +_prefetch_abort: .word prefetch_abort +_data_abort: .word data_abort +_not_used: .word not_used +_irq: .word irq +_fiq: .word fiq +_pad: .word 0x12345678 /* now 16*4=64 */ +.global _end_vect +_end_vect: + + .balignl 16,0xdeadbeef +/************************************************************************* + * + * Startup Code (reset vector) + * + * do important init only if we don't start from memory! + * setup Memory and board specific bits prior to relocation. + * relocate armboot to ram + * setup stack + * + *************************************************************************/ + +_TEXT_BASE: + .word TEXT_BASE + +.globl _armboot_start +_armboot_start: + .word _start + +/* + * These are defined in the board-specific linker script. + */ +.globl _bss_start +_bss_start: + .word __bss_start + +.globl _bss_end +_bss_end: + .word _end + +#ifdef CONFIG_USE_IRQ +/* IRQ stack memory (calculated at run-time) */ +.globl IRQ_STACK_START +IRQ_STACK_START: + .word 0x0badc0de + +/* IRQ stack memory (calculated at run-time) */ +.globl FIQ_STACK_START +FIQ_STACK_START: + .word 0x0badc0de +#endif + +/* + * the actual reset code + */ + +reset: + /* + * set the cpu to SVC32 mode + */ + mrs r0, cpsr + bic r0, r0, #0x1f + orr r0, r0, #0xd3 + msr cpsr,r0 + +#if (CONFIG_OMAP34XX) + /* Copy vectors to mask ROM indirect addr */ + adr r0, _start @ r0 <- current position of code + add r0, r0, #4 @ skip reset vector + mov r2, #64 @ r2 <- size to copy + add r2, r0, r2 @ r2 <- source end address + mov r1, #SRAM_OFFSET0 @ build vect addr + mov r3, #SRAM_OFFSET1 + add r1, r1, r3 + mov r3, #SRAM_OFFSET2 + add r1, r1, r3 +next: + ldmia r0!, {r3 - r10} @ copy from source address [r0] + stmia r1!, {r3 - r10} @ copy to target address [r1] + cmp r0, r2 @ until source end address [r2] + bne next @ loop until equal */ +#if !defined(CONFIG_SYS_NAND_BOOT) && !defined(CONFIG_SYS_ONENAND_BOOT) + /* No need to copy/exec the clock code - DPLL adjust already done + * in NAND/oneNAND Boot. + */ + bl cpy_clk_code @ put dpll adjust code behind vectors +#endif /* NAND Boot */ +#endif + /* the mask ROM code should have PLL and others stable */ +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + bl cpu_init_crit +#endif + +#ifndef CONFIG_SKIP_RELOCATE_UBOOT +relocate: @ relocate U-Boot to RAM + adr r0, _start @ r0 <- current position of code + ldr r1, _TEXT_BASE @ test if we run from flash or RAM + cmp r0, r1 @ don't reloc during debug + beq stack_setup + + ldr r2, _armboot_start + ldr r3, _bss_start + sub r2, r3, r2 @ r2 <- size of armboot + add r2, r0, r2 @ r2 <- source end address + +copy_loop: @ copy 32 bytes at a time + ldmia r0!, {r3 - r10} @ copy from source address [r0] + stmia r1!, {r3 - r10} @ copy to target address [r1] + cmp r0, r2 @ until source end addreee [r2] + ble copy_loop +#endif /* CONFIG_SKIP_RELOCATE_UBOOT */ + + /* Set up the stack */ +stack_setup: + ldr r0, _TEXT_BASE @ upper 128 KiB: relocated uboot + sub r0, r0, #CONFIG_SYS_MALLOC_LEN @ malloc area + sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE @ bdinfo +#ifdef CONFIG_USE_IRQ + sub r0, r0, #(CONFIG_STACKSIZE_IRQ + CONFIG_STACKSIZE_FIQ) +#endif + sub sp, r0, #12 @ leave 3 words for abort-stack + and sp, sp, #~7 @ 8 byte alinged for (ldr/str)d + + /* Clear BSS (if any). Is below tx (watch load addr - need space) */ +clear_bss: + ldr r0, _bss_start @ find start of bss segment + ldr r1, _bss_end @ stop here + mov r2, #0x00000000 @ clear value +clbss_l: + str r2, [r0] @ clear BSS location + cmp r0, r1 @ are we at the end yet + add r0, r0, #4 @ increment clear index pointer + bne clbss_l @ keep clearing till at end + + ldr pc, _start_armboot @ jump to C code + +_start_armboot: .word start_armboot + + +/************************************************************************* + * + * CPU_init_critical registers + * + * setup important registers + * setup memory timing + * + *************************************************************************/ +cpu_init_crit: + /* + * Invalidate L1 I/D + */ + mov r0, #0 @ set up for MCR + mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs + mcr p15, 0, r0, c7, c5, 0 @ invalidate icache + + /* + * disable MMU stuff and caches + */ + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00002000 @ clear bits 13 (--V-) + bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM) + orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align + orr r0, r0, #0x00000800 @ set bit 12 (Z---) BTB + mcr p15, 0, r0, c1, c0, 0 + + /* + * Jump to board specific initialization... + * The Mask ROM will have already initialized + * basic memory. Go here to bump up clock rate and handle + * wake up conditions. + */ + mov ip, lr @ persevere link reg across call + bl lowlevel_init @ go setup pll,mux,memory + mov lr, ip @ restore link + mov pc, lr @ back to my caller +/* + ************************************************************************* + * + * Interrupt handling + * + ************************************************************************* + */ +@ +@ IRQ stack frame. +@ +#define S_FRAME_SIZE 72 + +#define S_OLD_R0 68 +#define S_PSR 64 +#define S_PC 60 +#define S_LR 56 +#define S_SP 52 + +#define S_IP 48 +#define S_FP 44 +#define S_R10 40 +#define S_R9 36 +#define S_R8 32 +#define S_R7 28 +#define S_R6 24 +#define S_R5 20 +#define S_R4 16 +#define S_R3 12 +#define S_R2 8 +#define S_R1 4 +#define S_R0 0 + +#define MODE_SVC 0x13 +#define I_BIT 0x80 + +/* + * use bad_save_user_regs for abort/prefetch/undef/swi ... + * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling + */ + + .macro bad_save_user_regs + sub sp, sp, #S_FRAME_SIZE @ carve out a frame on current + @ user stack + stmia sp, {r0 - r12} @ Save user registers (now in + @ svc mode) r0-r12 + + ldr r2, _armboot_start + sub r2, r2, #(CONFIG_SYS_MALLOC_LEN) + sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ set base 2 words into abort + @ stack + ldmia r2, {r2 - r3} @ get values for "aborted" pc + @ and cpsr (into parm regs) + add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack + + add r5, sp, #S_SP + mov r1, lr + stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr + mov r0, sp @ save current stack into r0 + @ (param register) + .endm + + .macro irq_save_user_regs + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Calling r0-r12 + add r8, sp, #S_PC @ !! R8 NEEDS to be saved !! + @ a reserved stack spot would + @ be good. + stmdb r8, {sp, lr}^ @ Calling SP, LR + str lr, [r8, #0] @ Save calling PC + mrs r6, spsr + str r6, [r8, #4] @ Save CPSR + str r0, [r8, #8] @ Save OLD_R0 + mov r0, sp + .endm + + .macro irq_restore_user_regs + ldmia sp, {r0 - lr}^ @ Calling r0 - lr + mov r0, r0 + ldr lr, [sp, #S_PC] @ Get PC + add sp, sp, #S_FRAME_SIZE + subs pc, lr, #4 @ return & move spsr_svc into + @ cpsr + .endm + + .macro get_bad_stack + ldr r13, _armboot_start @ setup our mode stack (enter + @ in banked mode) + sub r13, r13, #(CONFIG_SYS_MALLOC_LEN) @ move past malloc pool + sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ move to reserved a couple + @ spots for abort stack + + str lr, [r13] @ save caller lr in position 0 + @ of saved stack + mrs lr, spsr @ get the spsr + str lr, [r13, #4] @ save spsr in position 1 of + @ saved stack + + mov r13, #MODE_SVC @ prepare SVC-Mode + @ msr spsr_c, r13 + msr spsr, r13 @ switch modes, make sure + @ moves will execute + mov lr, pc @ capture return pc + movs pc, lr @ jump to next instruction & + @ switch modes. + .endm + + .macro get_bad_stack_swi + sub r13, r13, #4 @ space on current stack for + @ scratch reg. + str r0, [r13] @ save R0's value. + ldr r0, _armboot_start @ get data regions start + sub r0, r0, #(CONFIG_SYS_MALLOC_LEN) @ move past malloc pool + sub r0, r0, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ move past gbl and a couple + @ spots for abort stack + str lr, [r0] @ save caller lr in position 0 + @ of saved stack + mrs r0, spsr @ get the spsr + str lr, [r0, #4] @ save spsr in position 1 of + @ saved stack + ldr r0, [r13] @ restore r0 + add r13, r13, #4 @ pop stack entry + .endm + + .macro get_irq_stack @ setup IRQ stack + ldr sp, IRQ_STACK_START + .endm + + .macro get_fiq_stack @ setup FIQ stack + ldr sp, FIQ_STACK_START + .endm + +/* + * exception handlers + */ + .align 5 +undefined_instruction: + get_bad_stack + bad_save_user_regs + bl do_undefined_instruction + + .align 5 +software_interrupt: + get_bad_stack_swi + bad_save_user_regs + bl do_software_interrupt + + .align 5 +prefetch_abort: + get_bad_stack + bad_save_user_regs + bl do_prefetch_abort + + .align 5 +data_abort: + get_bad_stack + bad_save_user_regs + bl do_data_abort + + .align 5 +not_used: + get_bad_stack + bad_save_user_regs + bl do_not_used + +#ifdef CONFIG_USE_IRQ + + .align 5 +irq: + get_irq_stack + irq_save_user_regs + bl do_irq + irq_restore_user_regs + + .align 5 +fiq: + get_fiq_stack + /* someone ought to write a more effective fiq_save_user_regs */ + irq_save_user_regs + bl do_fiq + irq_restore_user_regs + +#else + + .align 5 +irq: + get_bad_stack + bad_save_user_regs + bl do_irq + + .align 5 +fiq: + get_bad_stack + bad_save_user_regs + bl do_fiq + +#endif + +/* + * v7_flush_dcache_all() + * + * Flush the whole D-cache. + * + * Corrupted registers: r0-r5, r7, r9-r11 + * + * - mm - mm_struct describing address space + */ + .align 5 +.global v7_flush_dcache_all +v7_flush_dcache_all: + stmfd r13!, {r0 - r5, r7, r9 - r12, r14} + + mov r7, r0 @ take a backup of device type + cmp r0, #0x3 @ check if the device type is + @ GP + moveq r12, #0x1 @ set up to invalide L2 +smi: .word 0x01600070 @ Call SMI monitor (smieq) + cmp r7, #0x3 @ compare again in case its + @ lost + beq finished_inval @ if GP device, inval done + @ above + + mrc p15, 1, r0, c0, c0, 1 @ read clidr + ands r3, r0, #0x7000000 @ extract loc from clidr + mov r3, r3, lsr #23 @ left align loc bit field + beq finished_inval @ if loc is 0, then no need to + @ clean + mov r10, #0 @ start clean at cache level 0 +inval_loop1: + add r2, r10, r10, lsr #1 @ work out 3x current cache + @ level + mov r1, r0, lsr r2 @ extract cache type bits from + @ clidr + and r1, r1, #7 @ mask of the bits for current + @ cache only + cmp r1, #2 @ see what cache we have at + @ this level + blt skip_inval @ skip if no cache, or just + @ i-cache + mcr p15, 2, r10, c0, c0, 0 @ select current cache level + @ in cssr + mov r2, #0 @ operand for mcr SBZ + mcr p15, 0, r2, c7, c5, 4 @ flush prefetch buffer to + @ sych the new cssr&csidr, + @ with armv7 this is 'isb', + @ but we compile with armv5 + mrc p15, 1, r1, c0, c0, 0 @ read the new csidr + and r2, r1, #7 @ extract the length of the + @ cache lines + add r2, r2, #4 @ add 4 (line length offset) + ldr r4, =0x3ff + ands r4, r4, r1, lsr #3 @ find maximum number on the + @ way size + clz r5, r4 @ find bit position of way + @ size increment + ldr r7, =0x7fff + ands r7, r7, r1, lsr #13 @ extract max number of the + @ index size +inval_loop2: + mov r9, r4 @ create working copy of max + @ way size +inval_loop3: + orr r11, r10, r9, lsl r5 @ factor way and cache number + @ into r11 + orr r11, r11, r7, lsl r2 @ factor index number into r11 + mcr p15, 0, r11, c7, c6, 2 @ invalidate by set/way + subs r9, r9, #1 @ decrement the way + bge inval_loop3 + subs r7, r7, #1 @ decrement the index + bge inval_loop2 +skip_inval: + add r10, r10, #2 @ increment cache number + cmp r3, r10 + bgt inval_loop1 +finished_inval: + mov r10, #0 @ swith back to cache level 0 + mcr p15, 2, r10, c0, c0, 0 @ select current cache level + @ in cssr + mcr p15, 0, r10, c7, c5, 4 @ flush prefetch buffer, + @ with armv7 this is 'isb', + @ but we compile with armv5 + + ldmfd r13!, {r0 - r5, r7, r9 - r12, pc} + + + .align 5 +.global reset_cpu +reset_cpu: + ldr r1, rstctl @ get addr for global reset + @ reg + mov r3, #0x2 @ full reset pll + mpu + str r3, [r1] @ force reset + mov r0, r0 +_loop_forever: + b _loop_forever +rstctl: + .word PRM_RSTCTRL diff --git a/cpu/blackfin/Makefile b/cpu/blackfin/Makefile index 8fed4b4..1378fd1 100644 --- a/cpu/blackfin/Makefile +++ b/cpu/blackfin/Makefile @@ -17,14 +17,15 @@ EXTRA := CEXTRA := initcode.o SEXTRA := start.o SOBJS := interrupt.o cache.o -COBJS := cpu.o traps.o interrupts.o reset.o serial.o i2c.o watchdog.o +COBJS-y := cpu.o traps.o interrupts.o reset.o serial.o watchdog.o +COBJS-$(CONFIG_JTAG_CONSOLE) += jtag-console.o ifeq ($(CONFIG_BFIN_BOOT_MODE),BFIN_BOOT_BYPASS) -COBJS += initcode.o +COBJS-y += initcode.o endif -SRCS := $(SEXTRA:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) -OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS)) +SRCS := $(SEXTRA:.o=.S) $(SOBJS:.o=.S) $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS-y) $(SOBJS)) EXTRA := $(addprefix $(obj),$(EXTRA)) CEXTRA := $(addprefix $(obj),$(CEXTRA)) SEXTRA := $(addprefix $(obj),$(SEXTRA)) @@ -46,6 +47,7 @@ $(obj)bootrom-asm-offsets.h: $(obj)bootrom-asm-offsets.s # make sure our initcode (which goes into LDR) does not # have relocs or external references +$(obj)initcode.o: CFLAGS += -fno-function-sections -fno-data-sections READINIT = env LC_ALL=C $(CROSS_COMPILE)readelf -s $< check_initcode: $(obj)initcode.o ifneq ($(CONFIG_BFIN_BOOT_MODE),BFIN_BOOT_BYPASS) diff --git a/cpu/blackfin/cache.S b/cpu/blackfin/cache.S index 51bdb30..6ed655a 100644 --- a/cpu/blackfin/cache.S +++ b/cpu/blackfin/cache.S @@ -1,5 +1,10 @@ -/* cache.S - low level cache handling routines - * Copyright (C) 2003-2007 Analog Devices Inc. +/* + * Blackfin cache control code + * + * Copyright 2003-2008 Analog Devices Inc. + * + * Enter bugs at http://blackfin.uclinux.org/ + * * Licensed under the GPL-2 or later. */ @@ -8,54 +13,75 @@ #include <asm/blackfin.h> .text -.align 2 -ENTRY(_blackfin_icache_flush_range) - R2 = -32; - R2 = R0 & R2; - P0 = R2; - P1 = R1; - CSYNC; +/* Since all L1 caches work the same way, we use the same method for flushing + * them. Only the actual flush instruction differs. We write this in asm as + * GCC can be hard to coax into writing nice hardware loops. + * + * Also, we assume the following register setup: + * R0 = start address + * R1 = end address + */ +.macro do_flush flushins:req optflushins optnopins label + + R2 = -L1_CACHE_BYTES; + + /* start = (start & -L1_CACHE_BYTES) */ + R0 = R0 & R2; + + /* end = ((end - 1) & -L1_CACHE_BYTES) + L1_CACHE_BYTES; */ + R1 += -1; + R1 = R1 & R2; + R1 += L1_CACHE_BYTES; + + /* count = (end - start) >> L1_CACHE_SHIFT */ + R2 = R1 - R0; + R2 >>= L1_CACHE_SHIFT; + P1 = R2; + +.ifnb \label +\label : +.endif + P0 = R0; + LSETUP (1f, 2f) LC1 = P1; 1: - IFLUSH[P0++]; - CC = P0 < P1(iu); - IF CC JUMP 1b(bp); - IFLUSH[P0]; - SSYNC; +.ifnb \optflushins + \optflushins [P0]; +.endif +#if ANOMALY_05000443 +.ifb \optnopins +2: +.endif + \flushins [P0++]; +.ifnb \optnopins +2: \optnopins; +.endif +#else +2: \flushins [P0++]; +#endif + RTS; +.endm + +/* Invalidate all instruction cache lines assocoiated with this memory area */ +ENTRY(_blackfin_icache_flush_range) + do_flush IFLUSH, , nop ENDPROC(_blackfin_icache_flush_range) +/* Flush all cache lines assocoiated with this area of memory. */ +ENTRY(_blackfin_icache_dcache_flush_range) + do_flush FLUSH, IFLUSH +ENDPROC(_blackfin_icache_dcache_flush_range) + +/* Throw away all D-cached data in specified region without any obligation to + * write them back. Since the Blackfin ISA does not have an "invalidate" + * instruction, we use flush/invalidate. Perhaps as a speed optimization we + * could bang on the DTEST MMRs ... + */ +ENTRY(_blackfin_dcache_flush_invalidate_range) + do_flush FLUSHINV +ENDPROC(_blackfin_dcache_flush_invalidate_range) + +/* Flush all data cache lines assocoiated with this memory area */ ENTRY(_blackfin_dcache_flush_range) - R2 = -32; - R2 = R0 & R2; - P0 = R2; - P1 = R1; - CSYNC; -1: - FLUSH[P0++]; - CC = P0 < P1(iu); - IF CC JUMP 1b(bp); - FLUSH[P0]; - SSYNC; - RTS; + do_flush FLUSH, , , .Ldfr ENDPROC(_blackfin_dcache_flush_range) - -ENTRY(_blackfin_dcache_invalidate_range) - R2 = -32; - R2 = R0 & R2; - P0 = R2; - P1 = R1; - CSYNC; -1: - FLUSHINV[P0++]; - CC = P0 < P1(iu); - IF CC JUMP 1b(bp); - - /* - * If the data crosses a cache line, then we'll be pointing to - * the last cache line, but won't have flushed/invalidated it yet, so do - * one more. - */ - FLUSHINV[P0]; - SSYNC; - RTS; -ENDPROC(_blackfin_dcache_invalidate_range) diff --git a/cpu/blackfin/cpu.c b/cpu/blackfin/cpu.c index 9efd88e..30c214b 100644 --- a/cpu/blackfin/cpu.c +++ b/cpu/blackfin/cpu.c @@ -14,11 +14,14 @@ #include <asm/blackfin.h> #include <asm/cplb.h> #include <asm/mach-common/bits/core.h> +#include <asm/mach-common/bits/ebiu.h> #include <asm/mach-common/bits/trace.h> #include "cpu.h" #include "serial.h" +ulong bfin_poweron_retx; + __attribute__ ((__noreturn__)) void cpu_init_f(ulong bootflag, ulong loaded_from_ldr) { @@ -48,6 +51,9 @@ void cpu_init_f(ulong bootflag, ulong loaded_from_ldr) bfin_write_EBIU_AMGCTL(CONFIG_EBIU_AMGCTL_VAL); #endif + /* Save RETX so we can pass it while booting Linux */ + bfin_poweron_retx = bootflag; + #ifdef CONFIG_DEBUG_DUMP /* Turn on hardware trace buffer */ bfin_write_TBUFCTL(TBUFPWR | TBUFEN); diff --git a/cpu/blackfin/i2c.c b/cpu/blackfin/i2c.c deleted file mode 100644 index 2a3e223..0000000 --- a/cpu/blackfin/i2c.c +++ /dev/null @@ -1,428 +0,0 @@ -/* - * i2c.c - driver for Blackfin on-chip TWI/I2C - * - * Copyright (c) 2006-2008 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include <common.h> - -#ifdef CONFIG_HARD_I2C - -#include <asm/blackfin.h> -#include <i2c.h> -#include <asm/io.h> -#include <asm/mach-common/bits/twi.h> - -/* Two-Wire Interface (0xFFC01400 - 0xFFC014FF) */ -#ifdef TWI0_CLKDIV -#define bfin_read_TWI_CLKDIV() bfin_read_TWI0_CLKDIV() -#define bfin_write_TWI_CLKDIV(val) bfin_write_TWI0_CLKDIV(val) -#define bfin_read_TWI_CONTROL() bfin_read_TWI0_CONTROL() -#define bfin_write_TWI_CONTROL(val) bfin_write_TWI0_CONTROL(val) -#define bfin_read_TWI_SLAVE_CTL() bfin_read_TWI0_SLAVE_CTL() -#define bfin_write_TWI_SLAVE_CTL(val) bfin_write_TWI0_SLAVE_CTL(val) -#define bfin_read_TWI_SLAVE_STAT() bfin_read_TWI0_SLAVE_STAT() -#define bfin_write_TWI_SLAVE_STAT(val) bfin_write_TWI0_SLAVE_STAT(val) -#define bfin_read_TWI_SLAVE_ADDR() bfin_read_TWI0_SLAVE_ADDR() -#define bfin_write_TWI_SLAVE_ADDR(val) bfin_write_TWI0_SLAVE_ADDR(val) -#define bfin_read_TWI_MASTER_CTL() bfin_read_TWI0_MASTER_CTL() -#define bfin_write_TWI_MASTER_CTL(val) bfin_write_TWI0_MASTER_CTL(val) -#define bfin_read_TWI_MASTER_STAT() bfin_read_TWI0_MASTER_STAT() -#define bfin_write_TWI_MASTER_STAT(val) bfin_write_TWI0_MASTER_STAT(val) -#define bfin_read_TWI_MASTER_ADDR() bfin_read_TWI0_MASTER_ADDR() -#define bfin_write_TWI_MASTER_ADDR(val) bfin_write_TWI0_MASTER_ADDR(val) -#define bfin_read_TWI_INT_STAT() bfin_read_TWI0_INT_STAT() -#define bfin_write_TWI_INT_STAT(val) bfin_write_TWI0_INT_STAT(val) -#define bfin_read_TWI_INT_MASK() bfin_read_TWI0_INT_MASK() -#define bfin_write_TWI_INT_MASK(val) bfin_write_TWI0_INT_MASK(val) -#define bfin_read_TWI_FIFO_CTL() bfin_read_TWI0_FIFO_CTL() -#define bfin_write_TWI_FIFO_CTL(val) bfin_write_TWI0_FIFO_CTL(val) -#define bfin_read_TWI_FIFO_STAT() bfin_read_TWI0_FIFO_STAT() -#define bfin_write_TWI_FIFO_STAT(val) bfin_write_TWI0_FIFO_STAT(val) -#define bfin_read_TWI_XMT_DATA8() bfin_read_TWI0_XMT_DATA8() -#define bfin_write_TWI_XMT_DATA8(val) bfin_write_TWI0_XMT_DATA8(val) -#define bfin_read_TWI_XMT_DATA_16() bfin_read_TWI0_XMT_DATA16() -#define bfin_write_TWI_XMT_DATA16(val) bfin_write_TWI0_XMT_DATA16(val) -#define bfin_read_TWI_RCV_DATA8() bfin_read_TWI0_RCV_DATA8() -#define bfin_write_TWI_RCV_DATA8(val) bfin_write_TWI0_RCV_DATA8(val) -#define bfin_read_TWI_RCV_DATA16() bfin_read_TWI0_RCV_DATA16() -#define bfin_write_TWI_RCV_DATA16(val) bfin_write_TWI0_RCV_DATA16(val) -#endif - -#ifdef DEBUG_I2C -#define PRINTD(fmt,args...) do { \ - DECLARE_GLOBAL_DATA_PTR; \ - if (gd->have_console) \ - printf(fmt ,##args); \ - } while (0) -#else -#define PRINTD(fmt,args...) -#endif - -#ifndef CONFIG_TWICLK_KHZ -#define CONFIG_TWICLK_KHZ 50 -#endif - -/* All transfers are described by this data structure */ -struct i2c_msg { - u16 addr; /* slave address */ - u16 flags; -#define I2C_M_STOP 0x2 -#define I2C_M_RD 0x1 - u16 len; /* msg length */ - u8 *buf; /* pointer to msg data */ -}; - -/** - * i2c_reset: - reset the host controller - */ -static void i2c_reset(void) -{ - /* Disable TWI */ - bfin_write_TWI_CONTROL(0); - SSYNC(); - - /* Set TWI internal clock as 10MHz */ - bfin_write_TWI_CONTROL(((get_sclk() / 1024 / 1024 + 5) / 10) & 0x7F); - - /* Set Twi interface clock as specified */ - if (CONFIG_TWICLK_KHZ > 400) - bfin_write_TWI_CLKDIV(((5 * 1024 / 400) << 8) | ((5 * 1024 / - 400) & 0xFF)); - else - bfin_write_TWI_CLKDIV(((5 * 1024 / - CONFIG_TWICLK_KHZ) << 8) | ((5 * 1024 / - CONFIG_TWICLK_KHZ) - & 0xFF)); - - /* Enable TWI */ - bfin_write_TWI_CONTROL(bfin_read_TWI_CONTROL() | TWI_ENA); - SSYNC(); -} - -int wait_for_completion(struct i2c_msg *msg, int timeout_count) -{ - unsigned short twi_int_stat; - unsigned short mast_stat; - int i; - - for (i = 0; i < timeout_count; i++) { - twi_int_stat = bfin_read_TWI_INT_STAT(); - mast_stat = bfin_read_TWI_MASTER_STAT(); - - if (XMTSERV & twi_int_stat) { - /* Transmit next data */ - if (msg->len > 0) { - bfin_write_TWI_XMT_DATA8(*(msg->buf++)); - msg->len--; - } else if (msg->flags & I2C_M_STOP) - bfin_write_TWI_MASTER_CTL - (bfin_read_TWI_MASTER_CTL() | STOP); - SSYNC(); - /* Clear status */ - bfin_write_TWI_INT_STAT(XMTSERV); - SSYNC(); - i = 0; - } - if (RCVSERV & twi_int_stat) { - if (msg->len > 0) { - /* Receive next data */ - *(msg->buf++) = bfin_read_TWI_RCV_DATA8(); - msg->len--; - } else if (msg->flags & I2C_M_STOP) { - bfin_write_TWI_MASTER_CTL - (bfin_read_TWI_MASTER_CTL() | STOP); - SSYNC(); - } - /* Clear interrupt source */ - bfin_write_TWI_INT_STAT(RCVSERV); - SSYNC(); - i = 0; - } - if (MERR & twi_int_stat) { - bfin_write_TWI_INT_STAT(MERR); - bfin_write_TWI_INT_MASK(0); - bfin_write_TWI_MASTER_STAT(0x3e); - bfin_write_TWI_MASTER_CTL(0); - SSYNC(); - /* - * if both err and complete int stats are set, - * return proper results. - */ - if (MCOMP & twi_int_stat) { - bfin_write_TWI_INT_STAT(MCOMP); - bfin_write_TWI_INT_MASK(0); - bfin_write_TWI_MASTER_CTL(0); - SSYNC(); - /* - * If it is a quick transfer, - * only address bug no data, not an err. - */ - if (msg->len == 0 && mast_stat & BUFRDERR) - return 0; - /* - * If address not acknowledged return -3, - * else return 0. - */ - else if (!(mast_stat & ANAK)) - return 0; - else - return -3; - } - return -1; - } - if (MCOMP & twi_int_stat) { - bfin_write_TWI_INT_STAT(MCOMP); - SSYNC(); - bfin_write_TWI_INT_MASK(0); - bfin_write_TWI_MASTER_CTL(0); - SSYNC(); - return 0; - } - } - if (msg->flags & I2C_M_RD) - return -4; - else - return -2; -} - -/** - * i2c_transfer: - Transfer one byte over the i2c bus - * - * This function can tranfer a byte over the i2c bus in both directions. - * It is used by the public API functions. - * - * @return: 0: transfer successful - * -1: transfer fail - * -2: transmit timeout - * -3: ACK missing - * -4: receive timeout - * -5: controller not ready - */ -int i2c_transfer(struct i2c_msg *msg) -{ - int ret = 0; - int timeout_count = 10000; - int len = msg->len; - - if (!(bfin_read_TWI_CONTROL() & TWI_ENA)) { - ret = -5; - goto transfer_error; - } - - while (bfin_read_TWI_MASTER_STAT() & BUSBUSY) - continue; - - /* Set Transmit device address */ - bfin_write_TWI_MASTER_ADDR(msg->addr); - - /* - * FIFO Initiation. - * Data in FIFO should be discarded before start a new operation. - */ - bfin_write_TWI_FIFO_CTL(0x3); - SSYNC(); - bfin_write_TWI_FIFO_CTL(0); - SSYNC(); - - if (!(msg->flags & I2C_M_RD)) { - /* Transmit first data */ - if (msg->len > 0) { - PRINTD("1 in i2c_transfer: buf=%d, len=%d\n", *msg->buf, - len); - bfin_write_TWI_XMT_DATA8(*(msg->buf++)); - msg->len--; - SSYNC(); - } - } - - /* clear int stat */ - bfin_write_TWI_INT_STAT(MERR | MCOMP | XMTSERV | RCVSERV); - - /* Interrupt mask . Enable XMT, RCV interrupt */ - bfin_write_TWI_INT_MASK(MCOMP | MERR | - ((msg->flags & I2C_M_RD) ? RCVSERV : XMTSERV)); - SSYNC(); - - if (len > 0 && len <= 255) - bfin_write_TWI_MASTER_CTL((len << 6)); - else if (msg->len > 255) { - bfin_write_TWI_MASTER_CTL((0xff << 6)); - msg->flags &= I2C_M_STOP; - } else - bfin_write_TWI_MASTER_CTL(0); - - /* Master enable */ - bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN | - ((msg->flags & I2C_M_RD) - ? MDIR : 0) | ((CONFIG_TWICLK_KHZ > - 100) ? FAST : 0)); - SSYNC(); - - ret = wait_for_completion(msg, timeout_count); - PRINTD("3 in i2c_transfer: ret=%d\n", ret); - - transfer_error: - switch (ret) { - case 1: - PRINTD(("i2c_transfer: error: transfer fail\n")); - break; - case 2: - PRINTD(("i2c_transfer: error: transmit timeout\n")); - break; - case 3: - PRINTD(("i2c_transfer: error: ACK missing\n")); - break; - case 4: - PRINTD(("i2c_transfer: error: receive timeout\n")); - break; - case 5: - PRINTD(("i2c_transfer: error: controller not ready\n")); - i2c_reset(); - break; - default: - break; - } - return ret; - -} - -/* ---------------------------------------------------------------------*/ -/* API Functions */ -/* ---------------------------------------------------------------------*/ - -void i2c_init(int speed, int slaveaddr) -{ - i2c_reset(); -} - -/** - * i2c_probe: - Test if a chip answers for a given i2c address - * - * @chip: address of the chip which is searched for - * @return: 0 if a chip was found, -1 otherwhise - */ - -int i2c_probe(uchar chip) -{ - struct i2c_msg msg; - u8 probebuf; - - i2c_reset(); - - probebuf = 0; - msg.addr = chip; - msg.flags = 0; - msg.len = 1; - msg.buf = &probebuf; - if (i2c_transfer(&msg)) - return -1; - - msg.addr = chip; - msg.flags = I2C_M_RD; - msg.len = 1; - msg.buf = &probebuf; - if (i2c_transfer(&msg)) - return -1; - - return 0; -} - -/** - * i2c_read: - Read multiple bytes from an i2c device - * - * chip: I2C chip address, range 0..127 - * addr: Memory (register) address within the chip - * alen: Number of bytes to use for addr (typically 1, 2 for larger - * memories, 0 for register type devices with only one - * register) - * buffer: Where to read/write the data - * len: How many bytes to read/write - * - * Returns: 0 on success, not 0 on failure - */ - -int i2c_read(uchar chip, uint addr, int alen, uchar * buffer, int len) -{ - struct i2c_msg msg; - u8 addr_bytes[3]; /* lowest...highest byte of data address */ - - PRINTD("i2c_read: chip=0x%x, addr=0x%x, alen=0x%x, len=0x%x\n", chip, - addr, alen, len); - - if (alen > 0) { - addr_bytes[0] = (u8) ((addr >> 0) & 0x000000FF); - addr_bytes[1] = (u8) ((addr >> 8) & 0x000000FF); - addr_bytes[2] = (u8) ((addr >> 16) & 0x000000FF); - msg.addr = chip; - msg.flags = 0; - msg.len = alen; - msg.buf = addr_bytes; - if (i2c_transfer(&msg)) - return -1; - } - - /* start read sequence */ - PRINTD(("i2c_read: start read sequence\n")); - msg.addr = chip; - msg.flags = I2C_M_RD; - msg.len = len; - msg.buf = buffer; - if (i2c_transfer(&msg)) - return -1; - - return 0; -} - -/** - * i2c_write: - Write multiple bytes to an i2c device - * - * chip: I2C chip address, range 0..127 - * addr: Memory (register) address within the chip - * alen: Number of bytes to use for addr (typically 1, 2 for larger - * memories, 0 for register type devices with only one - * register) - * buffer: Where to read/write the data - * len: How many bytes to read/write - * - * Returns: 0 on success, not 0 on failure - */ - -int i2c_write(uchar chip, uint addr, int alen, uchar * buffer, int len) -{ - struct i2c_msg msg; - u8 addr_bytes[3]; /* lowest...highest byte of data address */ - - PRINTD - ("i2c_write: chip=0x%x, addr=0x%x, alen=0x%x, len=0x%x, buf0=0x%x\n", - chip, addr, alen, len, buffer[0]); - - /* chip address write */ - if (alen > 0) { - addr_bytes[0] = (u8) ((addr >> 0) & 0x000000FF); - addr_bytes[1] = (u8) ((addr >> 8) & 0x000000FF); - addr_bytes[2] = (u8) ((addr >> 16) & 0x000000FF); - msg.addr = chip; - msg.flags = 0; - msg.len = alen; - msg.buf = addr_bytes; - if (i2c_transfer(&msg)) - return -1; - } - - /* start read sequence */ - PRINTD(("i2c_write: start write sequence\n")); - msg.addr = chip; - msg.flags = 0; - msg.len = len; - msg.buf = buffer; - if (i2c_transfer(&msg)) - return -1; - - return 0; - -} - -#endif /* CONFIG_HARD_I2C */ diff --git a/cpu/blackfin/initcode.c b/cpu/blackfin/initcode.c index ffc8420..3f3b479 100644 --- a/cpu/blackfin/initcode.c +++ b/cpu/blackfin/initcode.c @@ -20,7 +20,7 @@ #include "serial.h" __attribute__((always_inline)) -static inline uint32_t serial_init(void) +static inline void serial_init(void) { #ifdef __ADSPBF54x__ # ifdef BFIN_BOOT_UART_USE_RTS @@ -61,21 +61,16 @@ static inline uint32_t serial_init(void) } #endif - uint32_t old_baud = serial_early_get_baud(); - if (BFIN_DEBUG_EARLY_SERIAL) { + int ucen = *pUART_GCTL & UCEN; serial_early_init(); /* If the UART is off, that means we need to program * the baud rate ourselves initially. */ - if (!old_baud) { - old_baud = CONFIG_BAUDRATE; + if (ucen != UCEN) serial_early_set_baud(CONFIG_BAUDRATE); - } } - - return old_baud; } __attribute__((always_inline)) @@ -89,30 +84,6 @@ static inline void serial_deinit(void) #endif } -/* We need to reset the baud rate when we have early debug turned on - * or when we are booting over the UART. - * XXX: we should fix this to calc the old baud and restore it rather - * than hardcoding it via CONFIG_LDR_LOAD_BAUD ... but we have - * to figure out how to avoid the division in the baud calc ... - */ -__attribute__((always_inline)) -static inline void serial_reset_baud(uint32_t baud) -{ - if (!BFIN_DEBUG_EARLY_SERIAL && CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_UART) - return; - -#ifndef CONFIG_LDR_LOAD_BAUD -# define CONFIG_LDR_LOAD_BAUD 115200 -#endif - - if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_BYPASS) - serial_early_set_baud(baud); - else if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART) - serial_early_set_baud(CONFIG_LDR_LOAD_BAUD); - else - serial_early_set_baud(CONFIG_BAUDRATE); -} - __attribute__((always_inline)) static inline void serial_putc(char c) { @@ -129,12 +100,22 @@ static inline void serial_putc(char c) } -/* Max SCLK can be 133MHz ... dividing that by 4 gives - * us a freq of 33MHz for SPI which should generally be +/* Max SCLK can be 133MHz ... dividing that by (2*4) gives + * us a freq of 16MHz for SPI which should generally be * slow enough for the slow reads the bootrom uses. */ +#if !defined(CONFIG_SPI_FLASH_SLOW_READ) && \ + ((defined(__ADSPBF52x__) && __SILICON_REVISION__ >= 2) || \ + (defined(__ADSPBF54x__) && __SILICON_REVISION__ >= 1)) +# define BOOTROM_SUPPORTS_SPI_FAST_READ 1 +#else +# define BOOTROM_SUPPORTS_SPI_FAST_READ 0 +#endif #ifndef CONFIG_SPI_BAUD_INITBLOCK -# define CONFIG_SPI_BAUD_INITBLOCK 4 +# define CONFIG_SPI_BAUD_INITBLOCK (BOOTROM_SUPPORTS_SPI_FAST_READ ? 2 : 4) +#endif +#ifdef SPI0_BAUD +# define bfin_write_SPI_BAUD bfin_write_SPI0_BAUD #endif /* PLL_DIV defines */ @@ -158,17 +139,24 @@ static inline void serial_putc(char c) #endif #ifndef CONFIG_PLL_CTL_VAL -# define CONFIG_PLL_CTL_VAL (SPORT_HYST | (CONFIG_VCO_MULT << 9)) +# define CONFIG_PLL_CTL_VAL (SPORT_HYST | (CONFIG_VCO_MULT << 9) | CONFIG_CLKIN_HALF) #endif #ifndef CONFIG_EBIU_RSTCTL_VAL # define CONFIG_EBIU_RSTCTL_VAL 0 /* only MDDRENABLE is useful */ #endif +#if ((CONFIG_EBIU_RSTCTL_VAL & 0xFFFFFFC4) != 0) +# error invalid EBIU_RSTCTL value: must not set reserved bits +#endif #ifndef CONFIG_EBIU_MBSCTL_VAL # define CONFIG_EBIU_MBSCTL_VAL 0 #endif +#if defined(CONFIG_EBIU_DDRQUE_VAL) && ((CONFIG_EBIU_DDRQUE_VAL & 0xFFFF8000) != 0) +# error invalid EBIU_DDRQUE value: must not set reserved bits +#endif + /* Make sure our voltage value is sane so we don't blow up! */ #ifndef CONFIG_VR_CTL_VAL # define BFIN_CCLK ((CONFIG_CLKIN_HZ * CONFIG_VCO_MULT) / CONFIG_CCLK_DIV) @@ -195,6 +183,9 @@ static inline void serial_putc(char c) # elif defined(__ADSPBF54x__) /* TBD; use default */ # undef CONFIG_VR_CTL_VLEV # define CONFIG_VR_CTL_VLEV VLEV_120 +# elif defined(__ADSPBF538__) || defined(__ADSPBF539__) /* TBD; use default */ +# undef CONFIG_VR_CTL_VLEV +# define CONFIG_VR_CTL_VLEV VLEV_125 # endif # ifdef CONFIG_BFIN_MAC @@ -212,10 +203,17 @@ static inline void serial_putc(char c) # define CONFIG_VR_CTL_VAL (CONFIG_VR_CTL_CLKBUF | CONFIG_VR_CTL_VLEV | CONFIG_VR_CTL_FREQ) #endif -__attribute__((saveall)) +BOOTROM_CALLED_FUNC_ATTR void initcode(ADI_BOOT_DATA *bootstruct) { - uint32_t old_baud = serial_init(); + /* Save the clock pieces that are used in baud rate calculation */ + unsigned int sdivB, divB, vcoB; + serial_init(); + if (BFIN_DEBUG_EARLY_SERIAL || CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART) { + sdivB = bfin_read_PLL_DIV() & 0xf; + vcoB = (bfin_read_PLL_CTL() >> 9) & 0x3f; + divB = serial_early_get_div(); + } #ifdef CONFIG_HW_WATCHDOG # ifndef CONFIG_HW_WATCHDOG_TIMEOUT_INITCODE @@ -240,12 +238,11 @@ void initcode(ADI_BOOT_DATA *bootstruct) * boot. Once we switch over to u-boot's SPI flash driver, we'll * increase the speed appropriately. */ - if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_SPI_MASTER) -#ifdef SPI0_BAUD - bfin_write_SPI0_BAUD(CONFIG_SPI_BAUD_INITBLOCK); -#else + if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_SPI_MASTER) { + if (BOOTROM_SUPPORTS_SPI_FAST_READ && CONFIG_SPI_BAUD_INITBLOCK < 4) + bootstruct->dFlags |= BFLAG_FASTREAD; bfin_write_SPI_BAUD(CONFIG_SPI_BAUD_INITBLOCK); -#endif + } serial_putc('B'); @@ -263,40 +260,69 @@ void initcode(ADI_BOOT_DATA *bootstruct) bfin_write_SIC_IWR(1); #endif - serial_putc('L'); - - bfin_write_PLL_LOCKCNT(CONFIG_PLL_LOCKCNT_VAL); - - serial_putc('A'); - - /* Only reprogram when needed to avoid triggering unnecessary - * PLL relock sequences. + /* With newer bootroms, we use the helper function to set up + * the memory controller. Older bootroms lacks such helpers + * so we do it ourselves. */ - if (bfin_read_VR_CTL() != CONFIG_VR_CTL_VAL) { - serial_putc('!'); - bfin_write_VR_CTL(CONFIG_VR_CTL_VAL); - asm("idle;"); - } +#define BOOTROM_CAPS_SYSCONTROL 0 + if (BOOTROM_CAPS_SYSCONTROL) { + serial_putc('S'); + + ADI_SYSCTRL_VALUES memory_settings; + memory_settings.uwVrCtl = CONFIG_VR_CTL_VAL; + memory_settings.uwPllCtl = CONFIG_PLL_CTL_VAL; + memory_settings.uwPllDiv = CONFIG_PLL_DIV_VAL; + memory_settings.uwPllLockCnt = CONFIG_PLL_LOCKCNT_VAL; + syscontrol(SYSCTRL_WRITE | SYSCTRL_VRCTL | SYSCTRL_PLLCTL | SYSCTRL_PLLDIV | SYSCTRL_LOCKCNT | + (CONFIG_VR_CTL_VAL & FREQ_MASK ? SYSCTRL_INTVOLTAGE : SYSCTRL_EXTVOLTAGE), &memory_settings, NULL); + } else { + serial_putc('L'); + + bfin_write_PLL_LOCKCNT(CONFIG_PLL_LOCKCNT_VAL); + + serial_putc('A'); + + /* Only reprogram when needed to avoid triggering unnecessary + * PLL relock sequences. + */ + if (bfin_read_VR_CTL() != CONFIG_VR_CTL_VAL) { + serial_putc('!'); + bfin_write_VR_CTL(CONFIG_VR_CTL_VAL); + asm("idle;"); + } - serial_putc('C'); + serial_putc('C'); - bfin_write_PLL_DIV(CONFIG_PLL_DIV_VAL); + bfin_write_PLL_DIV(CONFIG_PLL_DIV_VAL); - serial_putc('K'); + serial_putc('K'); - /* Only reprogram when needed to avoid triggering unnecessary - * PLL relock sequences. - */ - if (bfin_read_PLL_CTL() != CONFIG_PLL_CTL_VAL) { - serial_putc('!'); - bfin_write_PLL_CTL(CONFIG_PLL_CTL_VAL); - asm("idle;"); + /* Only reprogram when needed to avoid triggering unnecessary + * PLL relock sequences. + */ + if (bfin_read_PLL_CTL() != CONFIG_PLL_CTL_VAL) { + serial_putc('!'); + bfin_write_PLL_CTL(CONFIG_PLL_CTL_VAL); + asm("idle;"); + } } /* Since we've changed the SCLK above, we may need to update * the UART divisors (UART baud rates are based on SCLK). + * Do the division by hand as there are no native instructions + * for dividing which means we'd generate a libgcc reference. */ - serial_reset_baud(old_baud); + if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART) { + unsigned int sdivR, vcoR; + sdivR = bfin_read_PLL_DIV() & 0xf; + vcoR = (bfin_read_PLL_CTL() >> 9) & 0x3f; + int dividend = sdivB * divB * vcoR; + int divisor = vcoB * sdivR; + unsigned int quotient; + for (quotient = 0; dividend > 0; ++quotient) + dividend -= divisor; + serial_early_put_div(quotient - ANOMALY_05000230); + } serial_putc('F'); diff --git a/cpu/blackfin/jtag-console.c b/cpu/blackfin/jtag-console.c new file mode 100644 index 0000000..44c0a83 --- /dev/null +++ b/cpu/blackfin/jtag-console.c @@ -0,0 +1,125 @@ +/* + * jtag-console.c - console driver over Blackfin JTAG + * + * Copyright (c) 2008 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include <common.h> +#include <devices.h> +#include <asm/blackfin.h> + +#ifndef CONFIG_JTAG_CONSOLE_TIMEOUT +# define CONFIG_JTAG_CONSOLE_TIMEOUT 100 +#endif + +/* The Blackfin tends to be much much faster than the JTAG hardware. */ +static void jtag_write_emudat(uint32_t emudat) +{ + static bool overflowed = false; + ulong timeout = get_timer(0) + CONFIG_JTAG_CONSOLE_TIMEOUT; + while (bfin_read_DBGSTAT() & 0x1) { + if (overflowed) + return; + if (timeout < get_timer(0)) + overflowed = true; + } + overflowed = false; + __asm__ __volatile__("emudat = %0;" : : "d"(emudat)); +} +/* Transmit a buffer. The format is: + * [32bit length][actual data] + */ +static void jtag_send(const char *c, uint32_t len) +{ + uint32_t i; + + if (len == 0) + return; + + /* First send the length */ + jtag_write_emudat(len); + + /* Then send the data */ + for (i = 0; i < len; i += 4) + jtag_write_emudat((c[i] << 0) | (c[i+1] << 8) | (c[i+2] << 16) | (c[i+3] << 24)); +} +static void jtag_putc(const char c) +{ + jtag_send(&c, 1); +} +static void jtag_puts(const char *s) +{ + jtag_send(s, strlen(s)); +} + +static int jtag_tstc(void) +{ + return (bfin_read_DBGSTAT() & 0x2); +} + +/* Receive a buffer. The format is: + * [32bit length][actual data] + */ +static size_t inbound_len; +static int leftovers_len; +static uint32_t leftovers; +static int jtag_getc(void) +{ + int ret; + uint32_t emudat; + + /* see if any data is left over */ + if (leftovers_len) { + --leftovers_len; + ret = leftovers & 0xff; + leftovers >>= 8; + return ret; + } + + /* wait for new data ! */ + while (!jtag_tstc()) + continue; + __asm__("%0 = emudat;" : "=d"(emudat)); + + if (inbound_len == 0) { + /* grab the length */ + inbound_len = emudat; + } else { + /* store the bytes */ + leftovers_len = min(4, inbound_len); + inbound_len -= leftovers_len; + leftovers = emudat; + } + + return jtag_getc(); +} + +int drv_jtag_console_init(void) +{ + device_t dev; + int ret; + + memset(&dev, 0x00, sizeof(dev)); + strcpy(dev.name, "jtag"); + dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; + dev.putc = jtag_putc; + dev.puts = jtag_puts; + dev.tstc = jtag_tstc; + dev.getc = jtag_getc; + + ret = device_register(&dev); + return (ret == 0 ? 1 : ret); +} + +#ifdef CONFIG_UART_CONSOLE_IS_JTAG +/* Since the JTAG is always available (at power on), allow it to fake a UART */ +void serial_set_baud(uint32_t baud) {} +void serial_setbrg(void) {} +int serial_init(void) { return 0; } +void serial_putc(const char c) __attribute__((alias("jtag_putc"))); +void serial_puts(const char *s) __attribute__((alias("jtag_puts"))); +int serial_tstc(void) __attribute__((alias("jtag_tstc"))); +int serial_getc(void) __attribute__((alias("jtag_getc"))); +#endif diff --git a/cpu/blackfin/reset.c b/cpu/blackfin/reset.c index d1e34b3..284cea5 100644 --- a/cpu/blackfin/reset.c +++ b/cpu/blackfin/reset.c @@ -29,26 +29,35 @@ void bfin_reset(void) */ __builtin_bfin_ssync(); - while (1) { + /* The bootrom checks to see how it was reset and will + * automatically perform a software reset for us when + * it starts executing after the core reset. + */ + if (ANOMALY_05000353 || ANOMALY_05000386) { /* Initiate System software reset. */ bfin_write_SWRST(0x7); /* Due to the way reset is handled in the hardware, we need - * to delay for 7 SCLKS. The only reliable way to do this is - * to calculate the CCLK/SCLK ratio and multiply 7. For now, + * to delay for 10 SCLKS. The only reliable way to do this is + * to calculate the CCLK/SCLK ratio and multiply 10. For now, * we'll assume worse case which is a 1:15 ratio. */ asm( "LSETUP (1f, 1f) LC0 = %0\n" "1: nop;" : - : "a" (15 * 7) + : "a" (15 * 10) : "LC0", "LB0", "LT0" ); /* Clear System software reset */ bfin_write_SWRST(0); + /* The BF526 ROM will crash during reset */ +#if defined(__ADSPBF522__) || defined(__ADSPBF524__) || defined(__ADSPBF526__) + bfin_read_SWRST(); +#endif + /* Wait for the SWRST write to complete. Cannot rely on SSYNC * though as the System state is all reset now. */ @@ -59,10 +68,11 @@ void bfin_reset(void) : "a" (15 * 1) : "LC1", "LB1", "LT1" ); + } + while (1) /* Issue core reset */ asm("raise 1"); - } } /* We need to trampoline ourselves up into L1 since our linker diff --git a/cpu/blackfin/serial.c b/cpu/blackfin/serial.c index 0d6f377..42534bd 100644 --- a/cpu/blackfin/serial.c +++ b/cpu/blackfin/serial.c @@ -29,6 +29,8 @@ #include <asm/blackfin.h> #include <asm/mach-common/bits/uart.h> +#ifdef CONFIG_UART_CONSOLE + #if defined(UART_LSR) && (CONFIG_UART_CONSOLE != 0) # error CONFIG_UART_CONSOLE must be 0 on parts with only one UART #endif @@ -170,3 +172,5 @@ void serial_puts(const char *s) while (*s) serial_putc(*s++); } + +#endif diff --git a/cpu/blackfin/serial.h b/cpu/blackfin/serial.h index ec40c26..ce39148 100644 --- a/cpu/blackfin/serial.h +++ b/cpu/blackfin/serial.h @@ -14,6 +14,10 @@ #include <asm/blackfin.h> #include <asm/mach-common/bits/uart.h> +#ifndef CONFIG_UART_CONSOLE +# define CONFIG_UART_CONSOLE 0 +#endif + #ifdef CONFIG_DEBUG_EARLY_SERIAL # define BFIN_DEBUG_EARLY_SERIAL 1 #else @@ -95,7 +99,16 @@ __attribute__((always_inline)) static inline void serial_do_portmux(void) { -#ifdef __ADSPBF52x__ +#if defined(__ADSPBF51x__) +# define DO_MUX(port, mux_tx, mux_rx, tx, rx) \ + bfin_write_PORT##port##_MUX((bfin_read_PORT##port##_MUX() & ~(PORT_x_MUX_##mux_tx##_MASK | PORT_x_MUX_##mux_rx##_MASK)) | PORT_x_MUX_##mux_tx##_FUNC_2 | PORT_x_MUX_##mux_rx##_FUNC_2); \ + bfin_write_PORT##port##_FER(bfin_read_PORT##port##_FER() | P##port##tx | P##port##rx); + switch (CONFIG_UART_CONSOLE) { + case 0: DO_MUX(G, 5, 5, 9, 10); break; /* Port G; mux 5; PG9 and PG10 */ + case 1: DO_MUX(F, 2, 3, 14, 15); break; /* Port H; mux 2/3; PH14 and PH15 */ + } + SSYNC(); +#elif defined(__ADSPBF52x__) # define DO_MUX(port, mux, tx, rx) \ bfin_write_PORT##port##_MUX((bfin_read_PORT##port##_MUX() & ~PORT_x_MUX_##mux##_MASK) | PORT_x_MUX_##mux##_FUNC_3); \ bfin_write_PORT##port##_FER(bfin_read_PORT##port##_FER() | P##port##tx | P##port##rx); @@ -143,16 +156,25 @@ static inline void serial_early_init(void) } __attribute__((always_inline)) -static inline uint32_t serial_early_get_baud(void) +static inline void serial_early_put_div(uint16_t divisor) { - /* If the UART isnt enabled, then we are booting an LDR - * from a non-UART source (so like flash) which means - * the baud rate here is meaningless. - */ - if ((*pUART_GCTL & UCEN) != UCEN) - return 0; + /* Set DLAB in LCR to Access DLL and DLH */ + ACCESS_LATCH(); + SSYNC(); + + /* Program the divisor to get the baud rate we want */ + *pUART_DLL = LOB(divisor); + *pUART_DLH = HIB(divisor); + SSYNC(); + + /* Clear DLAB in LCR to Access THR RBR IER */ + ACCESS_PORT_IER(); + SSYNC(); +} -#if (0) /* See comment for serial_reset_baud() in initcode.c */ +__attribute__((always_inline)) +static inline uint16_t serial_early_get_div(void) +{ /* Set DLAB in LCR to Access DLL and DLH */ ACCESS_LATCH(); SSYNC(); @@ -160,16 +182,12 @@ static inline uint32_t serial_early_get_baud(void) uint8_t dll = *pUART_DLL; uint8_t dlh = *pUART_DLH; uint16_t divisor = (dlh << 8) | dll; - uint32_t baud = get_sclk() / (divisor * 16); /* Clear DLAB in LCR to Access THR RBR IER */ ACCESS_PORT_IER(); SSYNC(); - return baud; -#else - return CONFIG_BAUDRATE; -#endif + return divisor; } __attribute__((always_inline)) @@ -179,20 +197,7 @@ static inline void serial_early_set_baud(uint32_t baud) * weird multiplication is to make sure we over sample just * a little rather than under sample the incoming signals. */ - uint16_t divisor = (get_sclk() + (baud * 8)) / (baud * 16) - ANOMALY_05000230; - - /* Set DLAB in LCR to Access DLL and DLH */ - ACCESS_LATCH(); - SSYNC(); - - /* Program the divisor to get the baud rate we want */ - *pUART_DLL = LOB(divisor); - *pUART_DLH = HIB(divisor); - SSYNC(); - - /* Clear DLAB in LCR to Access THR RBR IER */ - ACCESS_PORT_IER(); - SSYNC(); + serial_early_put_div((get_sclk() + (baud * 8)) / (baud * 16) - ANOMALY_05000230); } #ifndef BFIN_IN_INITCODE @@ -222,32 +227,6 @@ static inline void serial_early_puts(const char *s) #endif .endm -/* Recursively expand calls to _serial_putc for every byte - * passed to us. Append a newline when we're all done. - */ -.macro _serial_early_putc byte:req morebytes:vararg -#ifdef CONFIG_DEBUG_EARLY_SERIAL - R0 = \byte; - call _serial_putc; -.ifnb \morebytes - _serial_early_putc \morebytes -.else -.if (\byte != '\n') - _serial_early_putc '\n' -.endif -.endif -#endif -.endm - -/* Wrapper around recurisve _serial_early_putc macro which - * simply prepends the string "Early: " - */ -.macro serial_early_putc byte:req morebytes:vararg -#ifdef CONFIG_DEBUG_EARLY_SERIAL - _serial_early_putc 'E', 'a', 'r', 'l', 'y', ':', ' ', \byte, \morebytes -#endif -.endm - /* Since we embed the string right into our .text section, we need * to find its address. We do this by getting our PC and adding 2 * bytes (which is the length of the jump instruction). Then we diff --git a/cpu/blackfin/start.S b/cpu/blackfin/start.S index 9975a0c..6c8def4 100644 --- a/cpu/blackfin/start.S +++ b/cpu/blackfin/start.S @@ -125,8 +125,11 @@ ENTRY(_start) */ r6 = 1 (x); - /* Relocate from wherever are (FLASH/RAM/etc...) to the - * hardcoded monitor location in the end of RAM. + /* Relocate from wherever we are (FLASH/RAM/etc...) to the hardcoded + * monitor location in the end of RAM. We know that memcpy() only + * uses registers, so it is safe to call here. Note that this only + * copies to external memory ... we do not start executing out of + * it yet (see "lower to 15" below). */ serial_early_puts("Relocate"); call _get_pc; @@ -135,27 +138,16 @@ ENTRY(_start) r2.h = .Loffset; r3.l = _start; r3.h = _start; - r1 = r2 - r3; - - r0 = r0 - r1; - - cc = r0 == r3; + r2 = r2 - r3; + r1 = r0 - r2; + cc = r1 == r3; if cc jump .Lnorelocate; - r6 = 0 (x); - p1 = r0; - - p2.l = LO(CONFIG_SYS_MONITOR_BASE); - p2.h = HI(CONFIG_SYS_MONITOR_BASE); - p3 = 0x04; - p4.l = LO(CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN); - p4.h = HI(CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN); -.Lloop1: - r1 = [p1 ++ p3]; - [p2 ++ p3] = r1; - cc=p2==p4; - if !cc jump .Lloop1; + r0 = r3; + r2.l = LO(CONFIG_SYS_MONITOR_LEN); + r2.h = HI(CONFIG_SYS_MONITOR_LEN); + call _memcpy_ASM; /* Initialize BSS section ... we know that memset() does not * use the BSS, so it is safe to call here. The bootrom LDR @@ -173,9 +165,8 @@ ENTRY(_start) .Lnorelocate: /* Setup the actual stack in external memory */ - r0.h = HI(CONFIG_STACKBASE); - r0.l = LO(CONFIG_STACKBASE); - sp = r0; + sp.h = HI(CONFIG_STACKBASE); + sp.l = LO(CONFIG_STACKBASE); fp = sp; /* Now lower ourselves from the highest interrupt level to @@ -183,7 +174,9 @@ ENTRY(_start) * setting the 15 handler to ".Lenable_nested", raising the 15 * interrupt, and then returning from the highest interrupt * level to the dummy "jump" until the interrupt controller - * services the pending 15 interrupt. + * services the pending 15 interrupt. If executing out of + * flash, these steps also changes the code flow from flash + * to external memory. */ serial_early_puts("Lower to 15"); r0 = r7; diff --git a/cpu/blackfin/traps.c b/cpu/blackfin/traps.c index d17c0a1..a2c6f1e 100644 --- a/cpu/blackfin/traps.c +++ b/cpu/blackfin/traps.c @@ -111,23 +111,12 @@ void trap_c(struct pt_regs *regs) } if (i == ARRAY_SIZE(bfin_memory_map)) { printf("%cCPLB exception outside of memory map at 0x%p\n", - (data ? 'D' : 'I'), new_cplb_addr); + (data ? 'D' : 'I'), (void *)new_cplb_addr); bfin_panic(regs); } else debug("CPLB addr %p matches map 0x%p - 0x%p\n", new_cplb_addr, bfin_memory_map[i].start, bfin_memory_map[i].end); new_cplb_data = (data ? bfin_memory_map[i].data_flags : bfin_memory_map[i].inst_flags); - /* Turn the cache off */ - SSYNC(); - if (data) { - asm(" .align 8; "); - *pDMEM_CONTROL &= ~ENDCPLB; - } else { - asm(" .align 8; "); - *pIMEM_CONTROL &= ~ENICPLB; - } - SSYNC(); - if (data) { CPLB_ADDR_BASE = (uint32_t *)DCPLB_ADDR0; CPLB_DATA_BASE = (uint32_t *)DCPLB_DATA0; @@ -149,8 +138,17 @@ void trap_c(struct pt_regs *regs) debug("evicting entry %i: 0x%p 0x%08X\n", i, *CPLB_ADDR, *CPLB_DATA); last_evicted = i + 1; + + /* need to turn off cplbs whenever we muck with the cplb table */ +#if ENDCPLB != ENICPLB +# error cplb enable bit violates my sanity +#endif + uint32_t mem_control = (data ? DMEM_CONTROL : IMEM_CONTROL); + bfin_write32(mem_control, bfin_read32(mem_control) & ~ENDCPLB); *CPLB_ADDR = new_cplb_addr; *CPLB_DATA = new_cplb_data; + bfin_write32(mem_control, bfin_read32(mem_control) | ENDCPLB); + SSYNC(); /* dump current table for debugging purposes */ CPLB_ADDR = CPLB_ADDR_BASE; @@ -158,17 +156,6 @@ void trap_c(struct pt_regs *regs) for (i = 0; i < 16; ++i) debug("%2i 0x%p 0x%08X\n", i, *CPLB_ADDR++, *CPLB_DATA++); - /* Turn the cache back on */ - SSYNC(); - if (data) { - asm(" .align 8; "); - *pDMEM_CONTROL |= ENDCPLB; - } else { - asm(" .align 8; "); - *pIMEM_CONTROL |= ENICPLB; - } - SSYNC(); - break; } @@ -220,20 +207,21 @@ static const char *symbol_lookup(unsigned long addr, unsigned long *caddr) static void decode_address(char *buf, unsigned long address) { unsigned long sym_addr; + void *paddr = (void *)address; const char *sym = symbol_lookup(address, &sym_addr); if (sym) { - sprintf(buf, "<0x%p> { %s + 0x%x }", address, sym, address - sym_addr); + sprintf(buf, "<0x%p> { %s + 0x%lx }", paddr, sym, address - sym_addr); return; } if (!address) - sprintf(buf, "<0x%p> /* Maybe null pointer? */", address); + sprintf(buf, "<0x%p> /* Maybe null pointer? */", paddr); else if (address >= CONFIG_SYS_MONITOR_BASE && address < CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN) - sprintf(buf, "<0x%p> /* somewhere in u-boot */", address); + sprintf(buf, "<0x%p> /* somewhere in u-boot */", paddr); else - sprintf(buf, "<0x%p> /* unknown address */", address); + sprintf(buf, "<0x%p> /* unknown address */", paddr); } static char *strhwerrcause(uint16_t hwerrcause) @@ -273,7 +261,7 @@ static char *strexcause(uint16_t excause) void dump(struct pt_regs *fp) { char buf[150]; - size_t i; + int i; uint16_t hwerrcause, excause; if (!ENABLE_DUMP) @@ -288,8 +276,8 @@ void dump(struct pt_regs *fp) printf("SEQUENCER STATUS:\n"); printf(" SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", fp->seqstat, fp->ipend, fp->syscfg); - printf(" HWERRCAUSE: 0x%lx: %s\n", hwerrcause, strhwerrcause(hwerrcause)); - printf(" EXCAUSE : 0x%lx: %s\n", excause, strexcause(excause)); + printf(" HWERRCAUSE: 0x%x: %s\n", hwerrcause, strhwerrcause(hwerrcause)); + printf(" EXCAUSE : 0x%x: %s\n", excause, strexcause(excause)); for (i = 6; i <= 15; ++i) { if (fp->ipend & (1 << i)) { decode_address(buf, bfin_read32(EVT0 + 4*i)); @@ -323,7 +311,7 @@ void dump(struct pt_regs *fp) printf(" P0 : %08lx P1 : %08lx P2 : %08lx P3 : %08lx\n", fp->p0, fp->p1, fp->p2, fp->p3); printf(" P4 : %08lx P5 : %08lx FP : %08lx SP : %08lx\n", - fp->p4, fp->p5, fp->fp, fp); + fp->p4, fp->p5, fp->fp, (unsigned long)fp); printf(" LB0: %08lx LT0: %08lx LC0: %08lx\n", fp->lb0, fp->lt0, fp->lc0); printf(" LB1: %08lx LT1: %08lx LC1: %08lx\n", @@ -349,7 +337,7 @@ void dump_bfin_trace_buffer(void) { char buf[150]; unsigned long tflags; - size_t i = 0; + int i = 0; if (!ENABLE_DUMP) return; diff --git a/cpu/i386/Makefile b/cpu/i386/Makefile index 50534b6..f20675a 100644 --- a/cpu/i386/Makefile +++ b/cpu/i386/Makefile @@ -28,7 +28,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(CPU).a -START = start.o start16.o reset.o +START = start.o start16.o resetvec.o COBJS = serial.o interrupts.o cpu.o timer.o sc520.o SOBJS = sc520_asm.o diff --git a/cpu/i386/cpu.c b/cpu/i386/cpu.c index 5fd37c7..b9af5f8 100644 --- a/cpu/i386/cpu.c +++ b/cpu/i386/cpu.c @@ -35,6 +35,7 @@ #include <common.h> #include <command.h> +#include <asm/interrupt.h> int cpu_init(void) { @@ -64,3 +65,19 @@ void flush_cache (unsigned long dummy1, unsigned long dummy2) asm("wbinvd\n"); return; } + +void __attribute__ ((regparm(0))) generate_gpf(void); + +/* segment 0x70 is an arbitrary segment which does not exist */ +asm(".globl generate_gpf\n" + "generate_gpf:\n" + "ljmp $0x70, $0x47114711\n"); + +void __reset_cpu(ulong addr) +{ + printf("Resetting using i386 Triple Fault\n"); + set_vector(13, generate_gpf); /* general protection fault handler */ + set_vector(8, generate_gpf); /* double fault handler */ + generate_gpf(); /* start the show */ +} +void reset_cpu(ulong addr) __attribute__((weak, alias("__reset_cpu"))); diff --git a/cpu/i386/interrupts.c b/cpu/i386/interrupts.c index f6dbcca..badb30b 100644 --- a/cpu/i386/interrupts.c +++ b/cpu/i386/interrupts.c @@ -26,6 +26,7 @@ #include <asm/io.h> #include <asm/i8259.h> #include <asm/ibmpc.h> +#include <asm/interrupt.h> struct idt_entry { @@ -376,7 +377,7 @@ asm ("idt_ptr:\n" ".long idt\n" /* offset */ ".word 0x18\n");/* data segment */ -static void set_vector(int intnum, void *routine) +void set_vector(int intnum, void *routine) { idt[intnum].base_high = (u16)((u32)(routine)>>16); idt[intnum].base_low = (u16)((u32)(routine)&0xffff); @@ -507,19 +508,3 @@ int disable_interrupts(void) return (flags&0x200); /* IE flags is bit 9 */ } - - -#ifdef CONFIG_SYS_RESET_GENERIC - -void __attribute__ ((regparm(0))) generate_gpf(void); -asm(".globl generate_gpf\n" - "generate_gpf:\n" - "ljmp $0x70, $0x47114711\n"); /* segment 0x70 is an arbitrary segment which does not - * exist */ -void reset_cpu(ulong addr) -{ - set_vector(13, generate_gpf); /* general protection fault handler */ - set_vector(8, generate_gpf); /* double fault handler */ - generate_gpf(); /* start the show */ -} -#endif diff --git a/cpu/i386/reset.S b/cpu/i386/resetvec.S index 07a7384..d9222dd 100644 --- a/cpu/i386/reset.S +++ b/cpu/i386/resetvec.S @@ -26,7 +26,7 @@ .extern start16 -.section .reset, "ax" +.section .resetvec, "ax" .code16 reset_vector: cli diff --git a/cpu/i386/sc520.c b/cpu/i386/sc520.c index cb6bc03..b958f8d 100644 --- a/cpu/i386/sc520.c +++ b/cpu/i386/sc520.c @@ -25,9 +25,6 @@ * but idependent of implementation */ #include <config.h> - -#ifdef CONFIG_SC520 - #include <common.h> #include <config.h> #include <pci.h> @@ -344,7 +341,7 @@ void pci_sc520_init(struct pci_controller *hose) SC520_PCI_MEMORY_BUS, SC520_PCI_MEMORY_PHYS, SC520_PCI_MEMORY_SIZE, - PCI_REGION_MEM | PCI_REGION_MEMORY); + PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); /* PCI memory space */ pci_set_region(hose->regions + 1, @@ -507,4 +504,13 @@ u8 ssi_rx_byte(void) return read_mmcr_byte(SC520_SSIRCV); } -#endif /* CONFIG_SC520 */ +#ifdef CONFIG_SYS_RESET_SC520 +void reset_cpu(ulong addr) +{ + printf("Resetting using SC520 MMCR\n"); + /* Write a '1' to the SYS_RST of the RESCFG MMCR */ + write_mmcr_word(SC520_RESCFG, 0x0001); + + /* NOTREACHED */ +} +#endif diff --git a/cpu/ixp/Makefile b/cpu/ixp/Makefile index e1fb327..7e98d87 100644 --- a/cpu/ixp/Makefile +++ b/cpu/ixp/Makefile @@ -26,10 +26,14 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(CPU).a START = start.o -COBJS = serial.o interrupts.o cpu.o timer.o pci.o - -SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) -OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) +COBJS-y += cpu.o +COBJS-y += interrupts.o +ifndef CONFIG_USE_IRQ +COBJS-y += timer.o +endif + +SRCS := $(START:.o=.S) $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y)) START := $(addprefix $(obj),$(START)) all: $(obj).depend $(START) $(LIB) diff --git a/cpu/ixp/cpu.c b/cpu/ixp/cpu.c index 27872fb..fd545b5 100644 --- a/cpu/ixp/cpu.c +++ b/cpu/ixp/cpu.c @@ -86,9 +86,6 @@ int cpu_init (void) FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ; #endif -#if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI) - pci_init(); -#endif return 0; } diff --git a/cpu/ixp/npe/IxNpeDlImageMgr.c b/cpu/ixp/npe/IxNpeDlImageMgr.c index ccc0da7..9bcdc9c 100644 --- a/cpu/ixp/npe/IxNpeDlImageMgr.c +++ b/cpu/ixp/npe/IxNpeDlImageMgr.c @@ -133,20 +133,14 @@ typedef struct */ static IxNpeDlImageMgrStats ixNpeDlImageMgrStats; -/* default image */ -#ifdef CONFIG_IXP4XX_NPE_EXT_UCODE_BASE -static UINT32 *IxNpeMicroCodeImageLibrary = (UINT32 *)CONFIG_IXP4XX_NPE_EXT_UCODE_BASE; -#else -static UINT32 *IxNpeMicroCodeImageLibrary = (UINT32 *)IxNpeMicrocode_array; -#endif - static UINT32* getIxNpeMicroCodeImageLibrary(void) { char *s; + if ((s = getenv("npe_ucode")) != NULL) return (UINT32*) simple_strtoul(s, NULL, 16); else - return IxNpeMicroCodeImageLibrary; + return NULL; } /* @@ -422,7 +416,7 @@ ixNpeDlImageMgrSignatureCheck (UINT32 *microCodeImageLibrary) (IxNpeDlImageMgrImageLibraryHeader *) microCodeImageLibrary; BOOL result = TRUE; - if (header->signature != IX_NPEDL_IMAGEMGR_SIGNATURE) + if (!header || header->signature != IX_NPEDL_IMAGEMGR_SIGNATURE) { result = FALSE; ixNpeDlImageMgrStats.invalidSignature++; @@ -643,6 +637,11 @@ ixNpeDlImageMgrImageFind ( } #else imageLibrary = getIxNpeMicroCodeImageLibrary(); + if (imageLibrary == NULL) + { + printf ("npe: ERROR, no Microcode found in memory\n"); + return IX_FAIL; + } #endif /* IX_NPEDL_READ_MICROCODE_FROM_FILE */ } diff --git a/cpu/ixp/npe/Makefile b/cpu/ixp/npe/Makefile index 25117d7..f4f97bd 100644 --- a/cpu/ixp/npe/Makefile +++ b/cpu/ixp/npe/Makefile @@ -25,11 +25,11 @@ include $(TOPDIR)/config.mk LIB := $(obj)libnpe.a -LOCAL_CFLAGS += -I$(TOPDIR)/cpu/ixp/npe/include -DCONFIG_IXP425_COMPONENT_ETHDB +LOCAL_CFLAGS += -I$(TOPDIR)/cpu/ixp/npe/include -DCONFIG_IXP425_COMPONENT_ETHDB -D__linux CFLAGS += $(LOCAL_CFLAGS) HOST_CFLAGS += $(LOCAL_CFLAGS) -COBJS := npe.o \ +COBJS-$(CONFIG_IXP4XX_NPE) := npe.o \ miiphy.o \ IxOsalBufferMgt.o \ IxOsalIoMem.o \ @@ -79,17 +79,13 @@ COBJS := npe.o \ IxNpeMhSolicitedCbMgr.o \ IxNpeMhUnsolicitedCbMgr.o -ifndef CONFIG_IXP4XX_NPE_EXT_UCODE_BASE -COBJS += IxNpeMicrocode.o -endif - -SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) -OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) -START := $(addprefix $(obj),$(START)) +SRCS := $(SOBJS:.o=.S) $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS-y)) +SOBJS := $(addprefix $(obj),$(SOBJS)) all: $(LIB) -$(LIB): $(OBJS) +$(LIB): $(obj).depend $(OBJS) $(AR) $(ARFLAGS) $@ $(OBJS) ######################################################################### diff --git a/cpu/ixp/npe/npe.c b/cpu/ixp/npe/npe.c index bd77fed..03e3bf7 100644 --- a/cpu/ixp/npe/npe.c +++ b/cpu/ixp/npe/npe.c @@ -44,8 +44,6 @@ #include <npe.h> -#ifdef CONFIG_IXP4XX_NPE - static IxQMgrDispatcherFuncPtr qDispatcherFunc = NULL; static int npe_exists[NPE_NUM_PORTS]; static int npe_used[NPE_NUM_PORTS]; @@ -690,5 +688,3 @@ int npe_initialize(bd_t * bis) return 1; } - -#endif /* CONFIG_IXP4XX_NPE */ diff --git a/cpu/ixp/pci.c b/cpu/ixp/pci.c deleted file mode 100644 index 8c6b0b2..0000000 --- a/cpu/ixp/pci.c +++ /dev/null @@ -1,575 +0,0 @@ -/* - * IXP PCI Init - * (C) Copyright 2004 eslab.whut.edu.cn - * Yue Hu(huyue_whut@yahoo.com.cn), Ligong Xue(lgxue@hotmail.com) - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - - -#include <common.h> - -#ifdef CONFIG_PCI - -#include <asm/processor.h> -#include <asm/io.h> -#include <pci.h> -#include <asm/arch/ixp425.h> -#include <asm/arch/ixp425pci.h> - -static void non_prefetch_read (unsigned int addr, unsigned int cmd, - unsigned int *data); -static void non_prefetch_write (unsigned int addr, unsigned int cmd, - unsigned int data); -static void configure_pins (void); -static void sys_pci_gpio_clock_config (void); -static void pci_bus_scan (void); -static int pci_device_exists (unsigned int deviceNo); -static void sys_pci_bar_info_get (unsigned int devnum, unsigned int bus, - unsigned int dev, unsigned int func); -static void sys_pci_device_bars_write (void); -static void calc_bars (PciBar * Bars[], unsigned int nBars, - unsigned int startAddr); - -#define PCI_MEMORY_BUS 0x00000000 -#define PCI_MEMORY_PHY 0x48000000 -#define PCI_MEMORY_SIZE 0x04000000 - -#define PCI_MEM_BUS 0x40000000 -#define PCI_MEM_PHY 0x00000000 -#define PCI_MEM_SIZE 0x04000000 - -#define PCI_IO_BUS 0x40000000 -#define PCI_IO_PHY 0x50000000 -#define PCI_IO_SIZE 0x10000000 - -struct pci_controller hose; - -unsigned int nDevices; -unsigned int nMBars; -unsigned int nIOBars; -PciBar *memBars[IXP425_PCI_MAX_BAR]; -PciBar *ioBars[IXP425_PCI_MAX_BAR]; -PciDevice devices[IXP425_PCI_MAX_FUNC_ON_BUS]; - -int pci_read_config_dword (pci_dev_t dev, int where, unsigned int *val) -{ - unsigned int retval; - unsigned int addr; - - /*address bits 31:28 specify the device 10:8 specify the function */ - /*Set the address to be read */ - addr = BIT ((31 - dev)) | (where & ~3); - non_prefetch_read (addr, NP_CMD_CONFIGREAD, &retval); - - *val = retval; - - return (OK); -} - -int pci_read_config_word (pci_dev_t dev, int where, unsigned short *val) -{ - unsigned int n; - unsigned int retval; - unsigned int addr; - unsigned int byteEnables; - - n = where % 4; - /*byte enables are 4 bits active low, the position of each - bit maps to the byte that it enables */ - byteEnables = - (~(BIT (n) | BIT ((n + 1)))) & - IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK; - byteEnables = byteEnables << PCI_NP_CBE_BESL; - /*address bits 31:28 specify the device 10:8 specify the function */ - /*Set the address to be read */ - addr = BIT ((31 - dev)) | (where & ~3); - non_prefetch_read (addr, byteEnables | NP_CMD_CONFIGREAD, &retval); - - /*Pick out the word we are interested in */ - *val = (retval >> (8 * n)); - - return (OK); -} - -int pci_read_config_byte (pci_dev_t dev, int where, unsigned char *val) -{ - unsigned int retval; - unsigned int n; - unsigned int byteEnables; - unsigned int addr; - - n = where % 4; - /*byte enables are 4 bits, active low, the position of each - bit maps to the byte that it enables */ - byteEnables = (~BIT (n)) & IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK; - byteEnables = byteEnables << PCI_NP_CBE_BESL; - - /*address bits 31:28 specify the device, 10:8 specify the function */ - /*Set the address to be read */ - addr = BIT ((31 - dev)) | (where & ~3); - non_prefetch_read (addr, byteEnables | NP_CMD_CONFIGREAD, &retval); - /*Pick out the byte we are interested in */ - *val = (retval >> (8 * n)); - - return (OK); -} - -int pci_write_config_byte (pci_dev_t dev, int where, unsigned char val) -{ - unsigned int addr; - unsigned int byteEnables; - unsigned int n; - unsigned int ldata; - - n = where % 4; - /*byte enables are 4 bits active low, the position of each - bit maps to the byte that it enables */ - byteEnables = (~BIT (n)) & IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK; - byteEnables = byteEnables << PCI_NP_CBE_BESL; - ldata = val << (8 * n); - /*address bits 31:28 specify the device 10:8 specify the function */ - /*Set the address to be written */ - addr = BIT ((31 - dev)) | (where & ~3); - non_prefetch_write (addr, byteEnables | NP_CMD_CONFIGWRITE, ldata); - - return (OK); -} - -int pci_write_config_word (pci_dev_t dev, int where, unsigned short val) -{ - unsigned int addr; - unsigned int byteEnables; - unsigned int n; - unsigned int ldata; - - n = where % 4; - /*byte enables are 4 bits active low, the position of each - bit maps to the byte that it enables */ - byteEnables = - (~(BIT (n) | BIT ((n + 1)))) & - IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK; - byteEnables = byteEnables << PCI_NP_CBE_BESL; - ldata = val << (8 * n); - /*address bits 31:28 specify the device 10:8 specify the function */ - /*Set the address to be written */ - addr = BIT (31 - dev) | (where & ~3); - non_prefetch_write (addr, byteEnables | NP_CMD_CONFIGWRITE, ldata); - - return (OK); -} - -int pci_write_config_dword (pci_dev_t dev, int where, unsigned int val) -{ - unsigned int addr; - - /*address bits 31:28 specify the device 10:8 specify the function */ - /*Set the address to be written */ - addr = BIT (31 - dev) | (where & ~3); - non_prefetch_write (addr, NP_CMD_CONFIGWRITE, val); - - return (OK); -} - -void non_prefetch_read (unsigned int addr, - unsigned int cmd, unsigned int *data) -{ - REG_WRITE (PCI_CSR_BASE, PCI_NP_AD_OFFSET, addr); - - /*set up and execute the read */ - REG_WRITE (PCI_CSR_BASE, PCI_NP_CBE_OFFSET, cmd); - - /*The result of the read is now in np_rdata */ - REG_READ (PCI_CSR_BASE, PCI_NP_RDATA_OFFSET, *data); - - return; -} - -void non_prefetch_write (unsigned int addr, - unsigned int cmd, unsigned int data) -{ - - REG_WRITE (PCI_CSR_BASE, PCI_NP_AD_OFFSET, addr); - /*set up the write */ - REG_WRITE (PCI_CSR_BASE, PCI_NP_CBE_OFFSET, cmd); - /*Execute the write by writing to NP_WDATA */ - REG_WRITE (PCI_CSR_BASE, PCI_NP_WDATA_OFFSET, data); - - return; -} - -/* - * PCI controller config registers are accessed through these functions - * i.e. these allow us to set up our own BARs etc. - */ -void crp_read (unsigned int offset, unsigned int *data) -{ - REG_WRITE (PCI_CSR_BASE, PCI_CRP_AD_CBE_OFFSET, offset); - REG_READ (PCI_CSR_BASE, PCI_CRP_RDATA_OFFSET, *data); -} - -void crp_write (unsigned int offset, unsigned int data) -{ - /*The CRP address register bit 16 indicates that we want to do a write */ - REG_WRITE (PCI_CSR_BASE, PCI_CRP_AD_CBE_OFFSET, - PCI_CRP_WRITE | offset); - REG_WRITE (PCI_CSR_BASE, PCI_CRP_WDATA_OFFSET, data); -} - -/*struct pci_controller *hose*/ -void pci_ixp_init (struct pci_controller *hose) -{ - unsigned int regval; - - hose->first_busno = 0; - hose->last_busno = 0x00; - - /* System memory space */ - pci_set_region (hose->regions + 0, - PCI_MEMORY_BUS, - PCI_MEMORY_PHY, PCI_MEMORY_SIZE, PCI_REGION_MEMORY); - - /* PCI memory space */ - pci_set_region (hose->regions + 1, - PCI_MEM_BUS, - PCI_MEM_PHY, PCI_MEM_SIZE, PCI_REGION_MEM); - /* PCI I/O space */ - pci_set_region (hose->regions + 2, - PCI_IO_BUS, PCI_IO_PHY, PCI_IO_SIZE, PCI_REGION_IO); - - hose->region_count = 3; - - pci_register_hose (hose); - -/* - ========================================================== - Init IXP PCI - ========================================================== -*/ - REG_READ (PCI_CSR_BASE, PCI_CSR_OFFSET, regval); - regval |= 1 << 2; - REG_WRITE (PCI_CSR_BASE, PCI_CSR_OFFSET, regval); - - configure_pins (); - - READ_GPIO_REG (IXP425_GPIO_GPOUTR, regval); - WRITE_GPIO_REG (IXP425_GPIO_GPOUTR, regval & (~(1 << 13))); - udelay (533); - sys_pci_gpio_clock_config (); - REG_WRITE (PCI_CSR_BASE, PCI_INTEN_OFFSET, 0); - udelay (100); - READ_GPIO_REG (IXP425_GPIO_GPOUTR, regval); - WRITE_GPIO_REG (IXP425_GPIO_GPOUTR, regval | (1 << 13)); - udelay (533); - crp_write (PCI_CFG_BASE_ADDRESS_0, IXP425_PCI_BAR_0_DEFAULT); - crp_write (PCI_CFG_BASE_ADDRESS_1, IXP425_PCI_BAR_1_DEFAULT); - crp_write (PCI_CFG_BASE_ADDRESS_2, IXP425_PCI_BAR_2_DEFAULT); - crp_write (PCI_CFG_BASE_ADDRESS_3, IXP425_PCI_BAR_3_DEFAULT); - crp_write (PCI_CFG_BASE_ADDRESS_4, IXP425_PCI_BAR_4_DEFAULT); - crp_write (PCI_CFG_BASE_ADDRESS_5, IXP425_PCI_BAR_5_DEFAULT); - /*Setup PCI-AHB and AHB-PCI address mappings */ - REG_WRITE (PCI_CSR_BASE, PCI_AHBMEMBASE_OFFSET, - IXP425_PCI_AHBMEMBASE_DEFAULT); - - REG_WRITE (PCI_CSR_BASE, PCI_AHBIOBASE_OFFSET, - IXP425_PCI_AHBIOBASE_DEFAULT); - - REG_WRITE (PCI_CSR_BASE, PCI_PCIMEMBASE_OFFSET, - IXP425_PCI_PCIMEMBASE_DEFAULT); - - crp_write (PCI_CFG_SUB_VENDOR_ID, IXP425_PCI_SUB_VENDOR_SYSTEM); - - REG_READ (PCI_CSR_BASE, PCI_CSR_OFFSET, regval); - regval |= PCI_CSR_IC | PCI_CSR_ABE | PCI_CSR_PDS; - REG_WRITE (PCI_CSR_BASE, PCI_CSR_OFFSET, regval); - crp_write (PCI_CFG_COMMAND, PCI_CFG_CMD_MAE | PCI_CFG_CMD_BME); - udelay (1000); - - pci_write_config_word (0, PCI_CFG_COMMAND, INITIAL_PCI_CMD); - REG_WRITE (PCI_CSR_BASE, PCI_ISR_OFFSET, PCI_ISR_PSE - | PCI_ISR_PFE | PCI_ISR_PPE | PCI_ISR_AHBE); -#ifdef CONFIG_PCI_SCAN_SHOW - printf ("Device bus dev func deviceID vendorID \n"); -#endif - pci_bus_scan (); -} - -void configure_pins (void) -{ - unsigned int regval; - - /* Disable clock on GPIO PIN 14 */ - READ_GPIO_REG (IXP425_GPIO_GPCLKR, regval); - WRITE_GPIO_REG (IXP425_GPIO_GPCLKR, regval & (~(1 << 8))); - READ_GPIO_REG (IXP425_GPIO_GPCLKR, regval); - - READ_GPIO_REG (IXP425_GPIO_GPOER, regval); - WRITE_GPIO_REG (IXP425_GPIO_GPOER, - (((~(3 << 13)) & regval) | (0xf << 8))); - READ_GPIO_REG (IXP425_GPIO_GPOER, regval); - - READ_GPIO_REG (IXP425_GPIO_GPIT2R, regval); - WRITE_GPIO_REG (IXP425_GPIO_GPIT2R, - (regval & - ((0x1 << 9) | (0x1 << 6) | (0x1 << 3) | 0x1))); - READ_GPIO_REG (IXP425_GPIO_GPIT2R, regval); - - READ_GPIO_REG (IXP425_GPIO_GPISR, regval); - WRITE_GPIO_REG (IXP425_GPIO_GPISR, (regval | (0xf << 8))); - READ_GPIO_REG (IXP425_GPIO_GPISR, regval); -} - -void sys_pci_gpio_clock_config (void) -{ - unsigned int regval; - - READ_GPIO_REG (IXP425_GPIO_GPCLKR, regval); - regval |= 0x1 << 4; - WRITE_GPIO_REG (IXP425_GPIO_GPCLKR, regval); - READ_GPIO_REG (IXP425_GPIO_GPCLKR, regval); - regval |= 0x1 << 8; - WRITE_GPIO_REG (IXP425_GPIO_GPCLKR, regval); -} - -void pci_bus_scan (void) -{ - unsigned int bus = 0, dev, func = 0; - unsigned short data16; - unsigned int data32; - unsigned char intPin; - - /* Assign first device to ourselves */ - devices[0].bus = 0; - devices[0].device = 0; - devices[0].func = 0; - - crp_read (PCI_CFG_VENDOR_ID, &data32); - - devices[0].vendor_id = data32 & IXP425_PCI_BOTTOM_WORD_OF_LONG_MASK; - devices[0].device_id = data32 >> 16; - devices[0].error = FALSE; - devices[0].bar[NO_BAR].size = 0; /*dummy - required */ - - nDevices = 1; - - nMBars = 0; - nIOBars = 0; - - for (dev = 0; dev < IXP425_PCI_MAX_DEV; dev++) { - - /*Check whether a device is present */ - if (pci_device_exists (dev) != TRUE) { - - /*Clear error bits in ISR, write 1 to clear */ - REG_WRITE (PCI_CSR_BASE, PCI_ISR_OFFSET, PCI_ISR_PSE - | PCI_ISR_PFE | PCI_ISR_PPE | - PCI_ISR_AHBE); - continue; - } - - /*A device is present, add an entry to the array */ - devices[nDevices].bus = bus; - devices[nDevices].device = dev; - devices[nDevices].func = func; - - pci_read_config_word (dev, PCI_CFG_VENDOR_ID, &data16); - - devices[nDevices].vendor_id = data16; - - pci_read_config_word (dev, PCI_CFG_DEVICE_ID, &data16); - devices[nDevices].device_id = data16; - - /*The device is functioning correctly, set error to FALSE */ - devices[nDevices].error = FALSE; - - /*Figure out what BARs are on this device */ - sys_pci_bar_info_get (nDevices, bus, dev, func); - /*Figure out what INTX# line the card uses */ - pci_read_config_byte (dev, PCI_CFG_DEV_INT_PIN, &intPin); - - /*assign the appropriate irq line */ - if (intPin > PCI_IRQ_LINES) { - devices[nDevices].error = TRUE; - } else if (intPin != 0) { - /*This device uses an interrupt line */ - /*devices[nDevices].irq = ixp425PciIntTranslate[dev][intPin-1]; */ - devices[nDevices].irq = intPin; - } -#ifdef CONFIG_PCI_SCAN_SHOW - printf ("%06d %03d %03d %04d %08d %08x\n", nDevices, - devices[nDevices].vendor_id); -#endif - nDevices++; - - } - - calc_bars (memBars, nMBars, IXP425_PCI_BAR_MEM_BASE); - sys_pci_device_bars_write (); - - REG_WRITE (PCI_CSR_BASE, PCI_ISR_OFFSET, PCI_ISR_PSE - | PCI_ISR_PFE | PCI_ISR_PPE | PCI_ISR_AHBE); -} - -void sys_pci_bar_info_get (unsigned int devnum, - unsigned int bus, - unsigned int dev, unsigned int func) -{ - unsigned int data32; - unsigned int tmp; - unsigned int size; - - pci_write_config_dword (devnum, - PCI_CFG_BASE_ADDRESS_0, IXP425_PCI_BAR_QUERY); - pci_read_config_dword (devnum, PCI_CFG_BASE_ADDRESS_0, &data32); - - devices[devnum].bar[0].address = (data32 & 1); - - if (data32 & 1) { - /* IO space */ - tmp = data32 & ~0x3; - size = ~(tmp - 1); - devices[devnum].bar[0].size = size; - - if (nIOBars < IXP425_PCI_MAX_BAR) { - ioBars[nIOBars++] = &devices[devnum].bar[0]; - } - } else { - /* Mem space */ - tmp = data32 & ~IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK; - size = ~(tmp - 1); - devices[devnum].bar[0].size = size; - - if (nMBars < IXP425_PCI_MAX_BAR) { - memBars[nMBars++] = &devices[devnum].bar[0]; - } else { - devices[devnum].error = TRUE; - } - - } - - devices[devnum].bar[1].size = 0; -} - -void sortBars (PciBar * Bars[], unsigned int nBars) -{ - unsigned int i, j; - PciBar *tmp; - - if (nBars == 0) { - return; - } - - /* Sort biggest to smallest */ - for (i = 0; i < nBars - 1; i++) { - for (j = i + 1; j < nBars; j++) { - if (Bars[j]->size > Bars[i]->size) { - /* swap them */ - tmp = Bars[i]; - Bars[i] = Bars[j]; - Bars[j] = tmp; - } - } - } -} - -void calc_bars (PciBar * Bars[], unsigned int nBars, unsigned int startAddr) -{ - unsigned int i; - - if (nBars == 0) { - return; - } - - for (i = 0; i < nBars; i++) { - Bars[i]->address |= startAddr; - startAddr += Bars[i]->size; - } -} - -void sys_pci_device_bars_write (void) -{ - unsigned int i; - int addr; - - for (i = 1; i < nDevices; i++) { - if (devices[i].error) { - continue; - } - - pci_write_config_dword (devices[i].device, - PCI_CFG_BASE_ADDRESS_0, - devices[i].bar[0].address); - addr = BIT (31 - devices[i].device) | - (0 << PCI_NP_AD_FUNCSL) | - (PCI_CFG_BASE_ADDRESS_0 & ~3); - pci_write_config_dword (devices[i].device, - PCI_CFG_DEV_INT_LINE, devices[i].irq); - - pci_write_config_word (devices[i].device, - PCI_CFG_COMMAND, INITIAL_PCI_CMD); - - } -} - - -int pci_device_exists (unsigned int deviceNo) -{ - unsigned int vendorId; - unsigned int regval; - - pci_read_config_dword (deviceNo, PCI_CFG_VENDOR_ID, &vendorId); - - /* There are two ways to find out an empty device. - * 1. check Master Abort bit after the access. - * 2. check whether the vendor id read back is 0x0. - */ - REG_READ (PCI_CSR_BASE, PCI_ISR_OFFSET, regval); - if ((vendorId != 0x0) && ((regval & PCI_ISR_PFE) == 0)) { - return TRUE; - } - /*no device present, make sure that the master abort bit is reset */ - - REG_WRITE (PCI_CSR_BASE, PCI_ISR_OFFSET, PCI_ISR_PFE); - return FALSE; -} - -pci_dev_t pci_find_devices (struct pci_device_id * ids, int devNo) -{ - unsigned int i; - unsigned int devdidvid; - unsigned int didvid; - unsigned int vendorId, deviceId; - - vendorId = ids->vendor; - deviceId = ids->device; - didvid = ((deviceId << 16) & IXP425_PCI_TOP_WORD_OF_LONG_MASK) | - (vendorId & IXP425_PCI_BOTTOM_WORD_OF_LONG_MASK); - - for (i = devNo + 1; i < nDevices; i++) { - - pci_read_config_dword (devices[i].device, PCI_CFG_VENDOR_ID, - &devdidvid); - - if (devdidvid == didvid) { - return devices[i].device; - } - } - return -1; -} -#endif /* CONFIG_PCI */ diff --git a/cpu/ixp/serial.c b/cpu/ixp/serial.c deleted file mode 100644 index dd26af4..0000000 --- a/cpu/ixp/serial.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * (C) Copyright 2002 - * Wolfgang Denk, DENX Software Engineering, <wd@denx.de> - * - * (C) Copyright 2002 - * Sysgo Real-Time Solutions, GmbH <www.elinos.com> - * Marius Groeger <mgroeger@sysgo.de> - * - * (C) Copyright 2002 - * Sysgo Real-Time Solutions, GmbH <www.elinos.com> - * Alex Zuepke <azu@sysgo.de> - * - * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) - * - * 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/arch/ixp425.h> - -/* - * 14.7456 MHz - * Baud Rate = -------------- - * 16 x Divisor - */ -#define SERIAL_CLOCK 921600 - -DECLARE_GLOBAL_DATA_PTR; - -void serial_setbrg (void) -{ - unsigned int quot = 0; - int uart = CONFIG_SYS_IXP425_CONSOLE; - - if ((gd->baudrate <= SERIAL_CLOCK) && (SERIAL_CLOCK % gd->baudrate == 0)) - quot = SERIAL_CLOCK / gd->baudrate; - else - hang (); - - IER(uart) = 0; /* Disable for now */ - FCR(uart) = 0; /* No fifos enabled */ - - /* set baud rate */ - LCR(uart) = LCR_WLS0 | LCR_WLS1 | LCR_DLAB; - DLL(uart) = quot & 0xff; - DLH(uart) = quot >> 8; - LCR(uart) = LCR_WLS0 | LCR_WLS1; -#ifdef CONFIG_SERIAL_RTS_ACTIVE - MCR(uart) = MCR_RTS; /* set RTS active */ -#else - MCR(uart) = 0; /* set RTS inactive */ -#endif - IER(uart) = IER_UUE; -} - -/* - * Initialise the serial port with the given baudrate. The settings - * are always 8 data bits, no parity, 1 stop bit, no start bits. - * - */ -int serial_init (void) -{ - serial_setbrg (); - - return (0); -} - - -/* - * Output a single byte to the serial port. - */ -void serial_putc (const char c) -{ - /* wait for room in the tx FIFO on UART */ - while ((LSR(CONFIG_SYS_IXP425_CONSOLE) & LSR_TEMT) == 0); - - THR(CONFIG_SYS_IXP425_CONSOLE) = c; - - /* If \n, also do \r */ - if (c == '\n') - serial_putc ('\r'); -} - -/* - * Read a single byte from the serial port. Returns 1 on success, 0 - * otherwise. When the function is succesfull, the character read is - * written into its argument c. - */ -int serial_tstc (void) -{ - return LSR(CONFIG_SYS_IXP425_CONSOLE) & LSR_DR; -} - -/* - * Read a single byte from the serial port. Returns 1 on success, 0 - * otherwise. When the function is succesfull, the character read is - * written into its argument c. - */ -int serial_getc (void) -{ - while (!(LSR(CONFIG_SYS_IXP425_CONSOLE) & LSR_DR)); - - return (char) RBR(CONFIG_SYS_IXP425_CONSOLE) & 0xff; -} - -void -serial_puts (const char *s) -{ - while (*s) { - serial_putc (*s++); - } -} diff --git a/cpu/ixp/timer.c b/cpu/ixp/timer.c index 09d8ad5..deb227a 100644 --- a/cpu/ixp/timer.c +++ b/cpu/ixp/timer.c @@ -32,7 +32,6 @@ #include <common.h> #include <asm/arch/ixp425.h> -#ifndef CONFIG_USE_IRQ ulong get_timer (ulong base) { return get_timer_masked () - base; @@ -80,4 +79,3 @@ ulong get_timer_masked (void) } return (reload_constant - current); } -#endif /* #ifndef CONFIG_USE_IRQ */ diff --git a/cpu/mcf52x2/cpu_init.c b/cpu/mcf52x2/cpu_init.c index 66f9164..11f70b0 100644 --- a/cpu/mcf52x2/cpu_init.c +++ b/cpu/mcf52x2/cpu_init.c @@ -181,9 +181,14 @@ void cpu_init_f(void) /* FlexBus Chipselect */ init_fbcs(); +#ifdef CONFIG_SYS_MCF_SYNCR + /* Set clockspeed according to board header file */ + mbar_writeLong(MCF_FMPLL_SYNCR, CONFIG_SYS_MCF_SYNCR); +#else /* Set clockspeed to 100MHz */ - mbar_writeShort(MCF_FMPLL_SYNCR, + mbar_writeLong(MCF_FMPLL_SYNCR, MCF_FMPLL_SYNCR_MFD(0) | MCF_FMPLL_SYNCR_RFD(0)); +#endif while (!mbar_readByte(MCF_FMPLL_SYNSR) & MCF_FMPLL_SYNSR_LOCK) ; } @@ -219,7 +224,8 @@ int fecpin_setclear(struct eth_device *dev, int setclear) { if (setclear) { /* Enable Ethernet pins */ - mbar_writeByte(MCF_GPIO_PAR_FECI2C, CONFIG_SYS_FECI2C); + mbar_writeByte(MCF_GPIO_PAR_FECI2C, + (mbar_readByte(MCF_GPIO_PAR_FECI2C) | 0xF0)); } else { } diff --git a/cpu/mcf52x2/speed.c b/cpu/mcf52x2/speed.c index fe51fb4..c93a518 100644 --- a/cpu/mcf52x2/speed.c +++ b/cpu/mcf52x2/speed.c @@ -77,7 +77,8 @@ int get_clocks (void) #endif gd->cpu_clk = CONFIG_SYS_CLK; -#if defined(CONFIG_M5249) || defined(CONFIG_M5253) || defined(CONFIG_M5275) +#if defined(CONFIG_M5249) || defined(CONFIG_M5253) || \ + defined(CONFIG_M5271) || defined(CONFIG_M5275) gd->bus_clk = gd->cpu_clk / 2; #else gd->bus_clk = gd->cpu_clk; diff --git a/cpu/mcf5445x/pci.c b/cpu/mcf5445x/pci.c index c4a3b05..7f9784c 100644 --- a/cpu/mcf5445x/pci.c +++ b/cpu/mcf5445x/pci.c @@ -146,7 +146,7 @@ void pci_mcf5445x_init(struct pci_controller *hose) pci_set_region(hose->regions + 2, CONFIG_SYS_PCI_SYS_MEM_BUS, CONFIG_SYS_PCI_SYS_MEM_PHYS, CONFIG_SYS_PCI_SYS_MEM_SIZE, - PCI_REGION_MEM | PCI_REGION_MEMORY); + PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); hose->region_count = 3; diff --git a/cpu/mcf547x_8x/pci.c b/cpu/mcf547x_8x/pci.c index f5c2536..f867dc1 100644 --- a/cpu/mcf547x_8x/pci.c +++ b/cpu/mcf547x_8x/pci.c @@ -149,7 +149,7 @@ void pci_mcf547x_8x_init(struct pci_controller *hose) pci_set_region(hose->regions + 2, CONFIG_SYS_PCI_SYS_MEM_BUS, CONFIG_SYS_PCI_SYS_MEM_PHYS, CONFIG_SYS_PCI_SYS_MEM_SIZE, - PCI_REGION_MEM | PCI_REGION_MEMORY); + PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); hose->region_count = 3; diff --git a/cpu/microblaze/cache.c b/cpu/microblaze/cache.c index 4b7866f..3b7c4d4 100644 --- a/cpu/microblaze/cache.c +++ b/cpu/microblaze/cache.c @@ -25,8 +25,6 @@ #include <common.h> #include <asm/asm.h> -#if defined(CONFIG_CMD_CACHE) - int dcache_status (void) { int i = 0; @@ -62,4 +60,3 @@ void dcache_enable (void) { void dcache_disable(void) { MSRCLR(0x80); } -#endif diff --git a/cpu/mips/Makefile b/cpu/mips/Makefile index 5091781..28a1cbb 100644 --- a/cpu/mips/Makefile +++ b/cpu/mips/Makefile @@ -25,6 +25,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(CPU).a +START = start.o SOBJS-y = cache.o COBJS-y = cpu.o interrupts.o diff --git a/cpu/mips/au1x00_usb_ohci.c b/cpu/mips/au1x00_usb_ohci.c index 17489da..ea02efb 100644 --- a/cpu/mips/au1x00_usb_ohci.c +++ b/cpu/mips/au1x00_usb_ohci.c @@ -27,9 +27,7 @@ */ /* * IMPORTANT NOTES - * 1 - you MUST define LITTLEENDIAN in the configuration file for the - * board or this driver will NOT work! - * 2 - this driver is intended for use with USB Mass Storage Devices + * 1 - this driver is intended for use with USB Mass Storage Devices * (BBB) ONLY. There is NO support for Interrupt or Isochronous pipes! */ @@ -56,7 +54,7 @@ #define USBH_ENABLE_CE (1<<3) #define USBH_ENABLE_RD (1<<4) -#ifdef LITTLEENDIAN +#ifdef __LITTLE_ENDIAN #define USBH_ENABLE_INIT (USBH_ENABLE_CE | USBH_ENABLE_E | USBH_ENABLE_C) #else #define USBH_ENABLE_INIT (USBH_ENABLE_CE | USBH_ENABLE_E | USBH_ENABLE_C | USBH_ENABLE_BE) diff --git a/cpu/mips/cpu.c b/cpu/mips/cpu.c index b7180b0..d5a1604 100644 --- a/cpu/mips/cpu.c +++ b/cpu/mips/cpu.c @@ -65,6 +65,34 @@ void flush_cache(ulong start_addr, ulong size) } } +void flush_dcache_range(ulong start_addr, ulong stop) +{ + unsigned long lsize = CONFIG_SYS_CACHELINE_SIZE; + unsigned long addr = start_addr & ~(lsize - 1); + unsigned long aend = (stop - 1) & ~(lsize - 1); + + while (1) { + cache_op(Hit_Writeback_Inv_D, addr); + if (addr == aend) + break; + addr += lsize; + } +} + +void invalidate_dcache_range(ulong start_addr, ulong stop) +{ + unsigned long lsize = CONFIG_SYS_CACHELINE_SIZE; + unsigned long addr = start_addr & ~(lsize - 1); + unsigned long aend = (stop - 1) & ~(lsize - 1); + + while (1) { + cache_op(Hit_Invalidate_D, addr); + if (addr == aend) + break; + addr += lsize; + } +} + void write_one_tlb(int index, u32 pagemask, u32 hi, u32 low0, u32 low1) { write_c0_entrylo0(low0); diff --git a/cpu/mpc512x/Makefile b/cpu/mpc512x/Makefile index e8f1060..297d135 100644 --- a/cpu/mpc512x/Makefile +++ b/cpu/mpc512x/Makefile @@ -26,6 +26,9 @@ LIB = $(obj)lib$(CPU).a START = start.o COBJS = traps.o cpu.o cpu_init.o speed.o interrupts.o serial.o i2c.o iopin.o +ifdef CONFIG_IIM +COBJS += iim.o +endif SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/cpu/mpc512x/iim.c b/cpu/mpc512x/iim.c new file mode 100644 index 0000000..6cdc422 --- /dev/null +++ b/cpu/mpc512x/iim.c @@ -0,0 +1,394 @@ +/* + * Copyright 2008 Silicon Turnkey Express, Inc. + * Martha Marx <mmarx@silicontkx.com> + * + * ADS5121 IIM (Fusebox) Interface + * + * 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 <command.h> +#include <asm/io.h> + +#ifdef CONFIG_CMD_FUSE + +DECLARE_GLOBAL_DATA_PTR; + +static char cur_bank = '1'; + +char *iim_err_msg(u32 err) +{ + static char *IIM_errs[] = { + "Parity Error in cache", + "Explicit Sense Cycle Error", + "Write to Locked Register Error", + "Read Protect Error", + "Override Protect Error", + "Write Protect Error"}; + + int i; + + if (!err) + return ""; + for (i = 1; i < 8; i++) + if (err & (1 << i)) + printf("IIM - %s\n", IIM_errs[i-1]); + return ""; +} + +int in_range(int n, int min, int max, char *err, char *usg) +{ + if (n > max || n < min) { + printf(err); + printf("Usage:\n%s\n", usg); + return 0; + } + return 1; +} + +int ads5121_fuse_read(int bank, int fstart, int num) +{ + iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim; + u32 *iim_fb, dummy; + int f, ctr; + + out_be32(&iim->err, in_be32(&iim->err)); + if (bank == 0) + iim_fb = (u32 *)&(iim->fbac0); + else + iim_fb = (u32 *)&(iim->fbac1); +/* try a read to see if Read Protect is set */ + dummy = in_be32(&iim_fb[0]); + if (in_be32(&iim->err) & IIM_ERR_RPE) { + printf("\tRead protect fuse is set\n"); + out_be32(&iim->err, IIM_ERR_RPE); + return 0; + } + printf("Reading Bank %d cache\n", bank); + for (f = fstart, ctr = 0; num > 0; ctr++, num--, f++) { + if (ctr % 4 == 0) + printf("F%2d:", f); + printf("\t%#04x", (u8)(iim_fb[f])); + if (ctr % 4 == 3) + printf("\n"); + } + if (ctr % 4 != 0) + printf("\n"); +} + +int ads5121_fuse_override(int bank, int f, u8 val) +{ + iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim; + u32 *iim_fb; + u32 iim_stat; + int i; + + out_be32(&iim->err, in_be32(&iim->err)); + if (bank == 0) + iim_fb = (u32 *)&(iim->fbac0); + else + iim_fb = (u32 *)&(iim->fbac1); +/* try a read to see if Read Protect is set */ + iim_stat = in_be32(&iim_fb[0]); + if (in_be32(&iim->err) & IIM_ERR_RPE) { + printf("Read protect fuse is set on bank %d;" + "Override protect may also be set\n", bank); + printf("An attempt will be made to override\n"); + out_be32(&iim->err, IIM_ERR_RPE); + } + if (iim_stat & IIM_FBAC_FBOP) { + printf("Override protect fuse is set on bank %d\n", bank); + return 1; + } + if (f > IIM_FMAX) /* reset the entire bank */ + for (i = 0; i < IIM_FMAX + 1; i++) + out_be32(&iim_fb[i], 0); + else + out_be32(&iim_fb[f], val); + return 0; +} + +int ads5121_fuse_prog(cmd_tbl_t *cmdtp, int bank, char *fuseno_bitno) +{ + iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim; + int f, i, bitno; + u32 stat, err; + + f = simple_strtol(fuseno_bitno, NULL, 10); + if (f == 0 && fuseno_bitno[0] != '0') + f = -1; + if (!in_range(f, 0, IIM_FMAX, + "<frow> must be between 0-31\n\n", cmdtp->usage)) + return 1; + bitno = -1; + for (i = 0; i < 6; i++) { + if (fuseno_bitno[i] == '_') { + bitno = simple_strtol(&(fuseno_bitno[i+1]), NULL, 10); + if (bitno == 0 && fuseno_bitno[i+1] != '0') + bitno = -1; + break; + } + } + if (!in_range(bitno, 0, 7, "Bit number ranges from 0-7\n" + "Example of <frow_bitno>: \"18_4\" sets bit 4 of row 18\n", + cmdtp->usage)) + return 1; + out_be32(&iim->err, in_be32(&iim->err)); + out_be32(&iim->prg_p, IIM_PRG_P_SET); + out_be32(&iim->ua, IIM_SET_UA(bank, f)); + out_be32(&iim->la, IIM_SET_LA(f, bitno)); +#ifdef DEBUG + printf("Programming disabled with DEBUG defined \n"); + printf(""Set up to pro + printf("iim.ua = %x; iim.la = %x\n", iim->ua, iim->la); +#else + out_be32(&iim->fctl, IIM_FCTL_PROG_PULSE | IIM_FCTL_PROG); + do + udelay(20); + while ((stat = in_be32(&iim->stat)) & IIM_STAT_BUSY); + out_be32(&iim->prg_p, 0); + err = in_be32(&iim->err); + if (stat & IIM_STAT_PRGD) { + if (!(err & (IIM_ERR_WPE | IIM_ERR_WPE))) { + printf("Fuse is successfully set"); + if (err) + printf(" - however there are other errors"); + printf("\n"); + } + iim->stat = 0; + } + if (err) { + iim_err_msg(err); + out_be32(&iim->err, in_be32(&iim->err)); + } +#endif +} + +int ads5121_fuse_sense(int bank, int fstart, int num) +{ + iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim; + u32 iim_fbac; + u32 stat, err, err_hold = 0; + int f, ctr; + + out_be32(&iim->err, in_be32(&iim->err)); + if (bank == 0) + iim_fbac = in_be32(&iim->fbac0); + else + iim_fbac = in_be32(&iim->fbac1); + if (iim_fbac & IIM_FBAC_FBESP) { + printf("\tSense Protect disallows this operation\n"); + out_be32(&iim->err, IIM_FBAC_FBESP); + return 1; + } + err = in_be32(&iim->err); + if (err) { + iim_err_msg(err); + err_hold |= err; + } + if (err & IIM_ERR_RPE) + printf("\tRead protect fuse is set; " + "Sense Protect may be set but will be attempted\n"); + if (err) + out_be32(&iim->err, err); + printf("Sensing fuse(s) on Bank %d\n", bank); + for (f = fstart, ctr = 0; num > 0; ctr++, f++, num--) { + out_be32(&iim->ua, IIM_SET_UA(bank, f)); + out_be32(&iim->la, IIM_SET_LA(f, 0)); + out_be32(&iim->fctl, IIM_FCTL_ESNS_N); + do + udelay(20); + while ((stat = in_be32(&iim->stat)) & IIM_STAT_BUSY); + err = in_be32(&iim->err); + if (err & IIM_ERR_SNSE) { + iim_err_msg(err); + out_be32(&iim->err, IIM_ERR_SNSE); + return 1; + } + if (stat & IIM_STAT_SNSD) { + out_be32(&iim->stat, 0); + if (ctr % 4 == 0) + printf("F%2d:", f); + printf("\t%#04x", (u8)iim->sdat); + if (ctr % 4 == 3) + printf("\n"); + } + if (err) { + err_hold |= err; + out_be32(&iim->err, err); + } + } + if (ctr % 4 != 0) + printf("\n"); + if (err_hold) + iim_err_msg(err_hold); + + return 0; +} + +int ads5121_fuse_stat(int bank) +{ + iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim; + u32 iim_fbac; + u32 err; + + out_be32(&iim->err, in_be32(&iim->err)); + if (bank == 0) + iim_fbac = in_be32(&iim->fbac0); + else + iim_fbac = in_be32(&iim->fbac1); + err = in_be32(&iim->err); + if (err) + iim_err_msg(err); + if (err & IIM_ERR_RPE || iim_fbac & IIM_FBAC_FBRP) { + if (iim_fbac == 0) + printf("Since protection settings can't be read - " + "try sensing fuse row 0;\n"); + return 0; + } + if (iim_fbac & IIM_PROTECTION) + printf("Protection Fuses Bank %d = %#04x:\n", bank, iim_fbac); + else if (!(err & IIM_ERR_RPE)) + printf("No Protection fuses are set\n"); + if (iim_fbac & IIM_FBAC_FBWP) + printf("\tWrite Protect fuse is set\n"); + if (iim_fbac & IIM_FBAC_FBOP) + printf("\tOverride Protect fuse is set\n"); + if (iim_fbac & IIM_FBAC_FBESP) + printf("\tSense Protect Fuse is set\n"); + out_be32(&iim->err, in_be32(&iim->err)); + + return 0; +} + +int do_ads5121_fuse(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int frow, n, v, bank; + + if (cur_bank == '0') + bank = 0; + else + bank = 1; + + switch (argc) { + case 0: + case 1: + printf("Usage:\n%s\n", cmdtp->usage); + return 1; + case 2: + if (strncmp(argv[1], "stat", 4) == 0) + return ads5121_fuse_stat(bank); + if (strncmp(argv[1], "read", 4) == 0) + return ads5121_fuse_read(bank, 0, IIM_FMAX + 1); + if (strncmp(argv[1], "sense", 5) == 0) + return ads5121_fuse_sense(bank, 0, IIM_FMAX + 1); + if (strncmp(argv[1], "ovride", 6) == 0) + return ads5121_fuse_override(bank, IIM_FMAX + 1, 0); + if (strncmp(argv[1], "bank", 4) == 0) { + printf("Active Fuse Bank is %c\n", cur_bank); + return 0; + } + printf("Usage:\n%s\n", cmdtp->usage); + return 1; + case 3: + if (strncmp(argv[1], "bank", 4) == 0) { + if (argv[2][0] == '0') + cur_bank = '0'; + else if (argv[2][0] == '1') + cur_bank = '1'; + else { + printf("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + printf("Setting Active Fuse Bank to %c\n", cur_bank); + return 0; + } + if (strncmp(argv[1], "prog", 4) == 0) + return ads5121_fuse_prog(cmdtp, bank, argv[2]); + + frow = (int)simple_strtol(argv[2], NULL, 10); + if (frow == 0 && argv[2][0] != '0') + frow = -1; + if (!in_range(frow, 0, IIM_FMAX, + "<frow> must be between 0-31\n\n", cmdtp->usage)) + return 1; + if (strncmp(argv[1], "read", 4) == 0) + return ads5121_fuse_read(bank, frow, 1); + if (strncmp(argv[1], "ovride", 6) == 0) + return ads5121_fuse_override(bank, frow, 0); + if (strncmp(argv[1], "sense", 5) == 0) + return ads5121_fuse_sense(bank, frow, 1); + printf("Usage:\n%s\n", cmdtp->usage); + return 1; + case 4: + frow = (int)simple_strtol(argv[2], NULL, 10); + if (frow == 0 && argv[2][0] != '0') + frow = -1; + if (!in_range(frow, 0, IIM_FMAX, + "<frow> must be between 0-31\n\n", cmdtp->usage)) + return 1; + if (strncmp(argv[1], "read", 4) == 0) { + n = (int)simple_strtol(argv[3], NULL, 10); + if (!in_range(frow + n, frow + 1, IIM_FMAX + 1, + "<frow>+<n> must be between 1-32\n\n", + cmdtp->usage)) + return 1; + return ads5121_fuse_read(bank, frow, n); + } + if (strncmp(argv[1], "ovride", 6) == 0) { + v = (int)simple_strtol(argv[3], NULL, 10); + return ads5121_fuse_override(bank, frow, v); + } + if (strncmp(argv[1], "sense", 5) == 0) { + n = (int)simple_strtol(argv[3], NULL, 10); + if (!in_range(frow + n, frow + 1, IIM_FMAX + 1, + "<frow>+<n> must be between 1-32\n\n", + cmdtp->usage)) + return 1; + return ads5121_fuse_sense(bank, frow, n); + } + printf("Usage:\n%s\n", cmdtp->usage); + return 1; + default: /* at least 5 args */ + printf("Usage:\n%s\n", cmdtp->usage); + return 1; + } +} + +U_BOOT_CMD( + fuse, CONFIG_SYS_MAXARGS, 0, do_ads5121_fuse, + " - Read, Sense, Override or Program Fuses\n", + "bank <n> - sets active Fuse Bank to 0 or 1\n" + " no args shows current active bank\n" + "fuse stat - print active fuse bank's protection status\n" + "fuse read [<frow> [<n>]] - print <n> fuse rows starting at <frow>\n" + " no args to print entire bank's fuses\n" + "fuse ovride [<frow> [<v>]]- override fuses at <frow> with <v>\n" + " no <v> defaults to 0 for the row\n" + " no args resets entire bank to 0\n" + " NOTE - settings persist until hard reset\n" + "fuse sense [<frow>] - senses current fuse at <frow>\n" + " no args for entire bank\n" + "fuse prog <frow_bit> - program fuse at row <frow>, bit <_bit>\n" + " <frow> is 0-31, <bit> is 0-7; eg. 13_2 \n" + " WARNING - this is permanent\n" + ); +#endif /* CONFIG_CMD_FUSE */ diff --git a/cpu/mpc512x/speed.c b/cpu/mpc512x/speed.c index 542bf21..5992111 100644 --- a/cpu/mpc512x/speed.c +++ b/cpu/mpc512x/speed.c @@ -137,7 +137,7 @@ int do_clocks (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) } U_BOOT_CMD(clocks, 1, 0, do_clocks, - "clocks - print clock configuration\n", + "print clock configuration", " clocks\n" ); diff --git a/cpu/mpc5xxx/pci_mpc5200.c b/cpu/mpc5xxx/pci_mpc5200.c index a3251ab..225738a 100644 --- a/cpu/mpc5xxx/pci_mpc5200.c +++ b/cpu/mpc5xxx/pci_mpc5200.c @@ -93,7 +93,7 @@ void pci_mpc5xxx_init (struct pci_controller *hose) CONFIG_PCI_MEMORY_BUS, CONFIG_PCI_MEMORY_PHYS, CONFIG_PCI_MEMORY_SIZE, - PCI_REGION_MEM | PCI_REGION_MEMORY); + PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); /* PCI memory space */ pci_set_region(hose->regions + 1, diff --git a/cpu/mpc8220/pci.c b/cpu/mpc8220/pci.c index a78a828..7ef43b7 100644 --- a/cpu/mpc8220/pci.c +++ b/cpu/mpc8220/pci.c @@ -165,7 +165,7 @@ pci_mpc8220_init(struct pci_controller *hose) CONFIG_PCI_SYS_MEM_BUS, CONFIG_PCI_SYS_MEM_PHYS, CONFIG_PCI_SYS_MEM_SIZE, - PCI_REGION_MEM | PCI_REGION_MEMORY); + PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); hose->region_count = 3; diff --git a/cpu/mpc824x/Makefile b/cpu/mpc824x/Makefile index f249dd7..a57ad12 100644 --- a/cpu/mpc824x/Makefile +++ b/cpu/mpc824x/Makefile @@ -44,7 +44,7 @@ $(LIB): $(OBJS) $(AR) $(ARFLAGS) $@ $(OBJS) $(obj)bedbug_603e.c: - ln -s $(src)../mpc8260/bedbug_603e.c $(obj)bedbug_603e.c + ln -sf $(src)../mpc8260/bedbug_603e.c $(obj)bedbug_603e.c ######################################################################### diff --git a/cpu/mpc824x/pci.c b/cpu/mpc824x/pci.c index 7e3c4c3..cf9cf41 100644 --- a/cpu/mpc824x/pci.c +++ b/cpu/mpc824x/pci.c @@ -34,7 +34,7 @@ void pci_mpc824x_init (struct pci_controller *hose) CHRP_PCI_MEMORY_BUS, CHRP_PCI_MEMORY_PHYS, CHRP_PCI_MEMORY_SIZE, - PCI_REGION_MEM | PCI_REGION_MEMORY); + PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); /* PCI memory space */ pci_set_region(hose->regions + 1, diff --git a/cpu/mpc8260/Makefile b/cpu/mpc8260/Makefile index 80d7852..9f0c2dd 100644 --- a/cpu/mpc8260/Makefile +++ b/cpu/mpc8260/Makefile @@ -1,5 +1,5 @@ # -# (C) Copyright 2000-2006 +# (C) Copyright 2000-2008 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. # # See file CREDITS for list of people who contributed to this @@ -27,9 +27,13 @@ LIB = $(obj)lib$(CPU).a START = start.o kgdb.o COBJS = traps.o serial_smc.o serial_scc.o cpu.o cpu_init.o speed.o \ - interrupts.o ether_scc.o ether_fcc.o i2c.o commproc.o \ + interrupts.o ether_fcc.o i2c.o commproc.o \ bedbug_603e.o pci.o spi.o +COBJS-$(CONFIG_ETHER_ON_SCC) = ether_scc.o + +COBJS += $(COBJS-y) + SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) START := $(addprefix $(obj),$(START)) diff --git a/cpu/mpc8260/bedbug_603e.c b/cpu/mpc8260/bedbug_603e.c index f1be485..c969ff6 100644 --- a/cpu/mpc8260/bedbug_603e.c +++ b/cpu/mpc8260/bedbug_603e.c @@ -72,7 +72,7 @@ void bedbug603e_do_break (cmd_tbl_t *cmdtp, int flag, int argc, if (argc < 2) { - printf ("Usage:\n%s\n", cmdtp->usage); + cmd_usage(cmdtp); return; } @@ -119,7 +119,7 @@ void bedbug603e_do_break (cmd_tbl_t *cmdtp, int flag, int argc, (( argv[ 1 ][ 0 ] >= 'a' ) && ( argv[ 1 ][ 0 ] <= 'f' )) || (( argv[ 1 ][ 0 ] >= 'A' ) && ( argv[ 1 ][ 0 ] <= 'F' )))) { - printf ("Usage:\n%s\n", cmdtp->usage); + cmd_usage(cmdtp); return; } diff --git a/cpu/mpc8260/cpu.c b/cpu/mpc8260/cpu.c index b9e748a..1b034cd 100644 --- a/cpu/mpc8260/cpu.c +++ b/cpu/mpc8260/cpu.c @@ -326,5 +326,8 @@ int cpu_eth_init(bd_t *bis) #if defined(CONFIG_ETHER_ON_FCC) fec_initialize(bis); #endif +#if defined(CONFIG_ETHER_ON_SCC) + mpc82xx_scc_enet_initialize(bis); +#endif return 0; } diff --git a/cpu/mpc8260/ether_scc.c b/cpu/mpc8260/ether_scc.c index c65f0e0..3671ef1 100644 --- a/cpu/mpc8260/ether_scc.c +++ b/cpu/mpc8260/ether_scc.c @@ -10,6 +10,12 @@ * Advent Networks, Inc. <http://www.adventnetworks.com> * Jay Monkman <jtm@smoothsmoothie.com> * + * Modified so that it plays nicely when more than one ETHERNET interface + * is in use a la ether_fcc.c. + * (C) Copyright 2008 + * DENX Software Engineerin GmbH + * Gary Jennejohn <garyj@denx.de> + * * See file CREDITS for list of people who contributed to this * project. * @@ -32,11 +38,14 @@ #include <common.h> #include <asm/cpm_8260.h> #include <mpc8260.h> +#include <malloc.h> #include <net.h> #include <command.h> #include <config.h> -#if defined(CONFIG_ETHER_ON_SCC) && defined(CONFIG_CMD_NET) +#ifndef CONFIG_NET_MULTI +#error "CONFIG_NET_MULTI must be defined." +#endif #if (CONFIG_ETHER_INDEX == 1) # define PROFF_ENET PROFF_SCC1 @@ -100,7 +109,7 @@ typedef volatile struct CommonBufferDescriptor { static RTXBD *rtx; -int eth_send(volatile void *packet, int length) +static int sec_send(struct eth_device *dev, volatile void *packet, int length) { int i; int result = 0; @@ -137,7 +146,7 @@ int eth_send(volatile void *packet, int length) } -int eth_rx(void) +static int sec_rx(struct eth_device *dev) { int length; @@ -184,7 +193,7 @@ int eth_rx(void) * *************************************************************/ -int eth_init(bd_t *bis) +static int sec_init(struct eth_device *dev, bd_t *bis) { int i; volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR; @@ -194,9 +203,14 @@ int eth_init(bd_t *bis) rxIdx = 0; txIdx = 0; - /* assign static pointer to BD area */ - dpaddr = m8260_cpm_dpalloc(sizeof(RTXBD) + 2, 16); - rtx = (RTXBD *)&immr->im_dprambase[dpaddr]; + /* + * Assign static pointer to BD area. + * Avoid exhausting DPRAM, which would cause a panic. + */ + if (rtx == NULL) { + dpaddr = m8260_cpm_dpalloc(sizeof(RTXBD) + 2, 16); + rtx = (RTXBD *)&immr->im_dprambase[dpaddr]; + } /* 24.21 - (1-3): ioports have been set up already */ @@ -338,7 +352,7 @@ int eth_init(bd_t *bis) } -void eth_halt(void) +static void sec_halt(struct eth_device *dev) { volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR; immr->im_scc[CONFIG_ETHER_INDEX-1].scc_gsmrl &= ~(SCC_GSMRL_ENR | @@ -346,7 +360,7 @@ void eth_halt(void) } #if 0 -void restart(void) +static void sec_restart(void) { volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR; immr->im_cpm.cp_scc[CONFIG_ETHER_INDEX-1].scc_gsmrl |= (SCC_GSMRL_ENR | @@ -354,4 +368,20 @@ void restart(void) } #endif -#endif +int mpc82xx_scc_enet_initialize(bd_t *bis) +{ + struct eth_device *dev; + + dev = (struct eth_device *) malloc(sizeof *dev); + memset(dev, 0, sizeof *dev); + + sprintf(dev->name, "SCC ETHERNET"); + dev->init = sec_init; + dev->halt = sec_halt; + dev->send = sec_send; + dev->recv = sec_rx; + + eth_register(dev); + + return 1; +} diff --git a/cpu/mpc8260/pci.c b/cpu/mpc8260/pci.c index 378d6c5..f1e9bb4 100644 --- a/cpu/mpc8260/pci.c +++ b/cpu/mpc8260/pci.c @@ -410,12 +410,12 @@ void pci_mpc8250_init (struct pci_controller *hose) pci_set_region (hose->regions + 0, PCI_SLV_MEM_BUS, PCI_SLV_MEM_LOCAL, - gd->ram_size, PCI_REGION_MEM | PCI_REGION_MEMORY); + gd->ram_size, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); #else pci_set_region (hose->regions + 0, CONFIG_SYS_SDRAM_BASE, CONFIG_SYS_SDRAM_BASE, - 0x4000000, PCI_REGION_MEM | PCI_REGION_MEMORY); + 0x4000000, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); #endif /* PCI memory space */ diff --git a/cpu/mpc8260/serial_smc.c b/cpu/mpc8260/serial_smc.c index a6efa66..fbb3fb0 100644 --- a/cpu/mpc8260/serial_smc.c +++ b/cpu/mpc8260/serial_smc.c @@ -64,6 +64,23 @@ DECLARE_GLOBAL_DATA_PTR; #endif +#if !defined(CONFIG_SYS_SMC_RXBUFLEN) +#define CONFIG_SYS_SMC_RXBUFLEN 1 +#define CONFIG_SYS_MAXIDLE 0 +#else +#if !defined(CONFIG_SYS_MAXIDLE) +#error "you must define CONFIG_SYS_MAXIDLE" +#endif +#endif + +typedef volatile struct serialbuffer { + cbd_t rxbd; /* Rx BD */ + cbd_t txbd; /* Tx BD */ + uint rxindex; /* index for next character to read */ + volatile uchar rxbuf[CONFIG_SYS_SMC_RXBUFLEN];/* rx buffers */ + volatile uchar txbuf; /* tx buffers */ +} serialbuffer_t; + /* map rs_table index to baud rate generator index */ static unsigned char brg_map[] = { 6, /* BRG7 for SMC1 */ @@ -79,9 +96,9 @@ int serial_init (void) volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR; volatile smc_t *sp; volatile smc_uart_t *up; - volatile cbd_t *tbdf, *rbdf; volatile cpm8260_t *cp = &(im->im_cpm); uint dpaddr; + volatile serialbuffer_t *rtx; /* initialize pointers to SMC */ @@ -89,8 +106,7 @@ int serial_init (void) *(ushort *)(&im->im_dprambase[PROFF_SMC_BASE]) = PROFF_SMC; up = (smc_uart_t *)&im->im_dprambase[PROFF_SMC]; - /* Disable transmitter/receiver. - */ + /* Disable transmitter/receiver. */ sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); /* NOTE: I/O port pins are set up via the iop_conf_tab[] table */ @@ -99,20 +115,23 @@ int serial_init (void) * damm: allocating space after the two buffers for rx/tx data */ - dpaddr = m8260_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16); + /* allocate size of struct serialbuffer with bd rx/tx, + * buffer rx/tx and rx index + */ + dpaddr = m8260_cpm_dpalloc((sizeof(serialbuffer_t)), 16); + + rtx = (serialbuffer_t *)&im->im_dprambase[dpaddr]; /* Set the physical address of the host memory buffers in * the buffer descriptors. */ - rbdf = (cbd_t *)&im->im_dprambase[dpaddr]; - rbdf->cbd_bufaddr = (uint) (rbdf+2); - rbdf->cbd_sc = 0; - tbdf = rbdf + 1; - tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1; - tbdf->cbd_sc = 0; + rtx->rxbd.cbd_bufaddr = (uint) &rtx->rxbuf; + rtx->rxbd.cbd_sc = 0; + + rtx->txbd.cbd_bufaddr = (uint) &rtx->txbuf; + rtx->txbd.cbd_sc = 0; - /* Set up the uart parameters in the parameter ram. - */ + /* Set up the uart parameters in the parameter ram. */ up->smc_rbase = dpaddr; up->smc_tbase = dpaddr+sizeof(cbd_t); up->smc_rfcr = CPMFCR_EB; @@ -126,8 +145,7 @@ int serial_init (void) */ sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART; - /* Mask all interrupts and remove anything pending. - */ + /* Mask all interrupts and remove anything pending. */ sp->smc_smcm = 0; sp->smc_smce = 0xff; @@ -136,22 +154,19 @@ int serial_init (void) */ im->im_cpmux.cmx_smr = (im->im_cpmux.cmx_smr&~CMXSMR_MASK)|CMXSMR_VALUE; - /* Set up the baud rate generator. - */ + /* Set up the baud rate generator. */ serial_setbrg (); - /* Make the first buffer the only buffer. - */ - tbdf->cbd_sc |= BD_SC_WRAP; - rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP; + /* Make the first buffer the only buffer. */ + rtx->txbd.cbd_sc |= BD_SC_WRAP; + rtx->rxbd.cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP; - /* Single character receive. - */ - up->smc_mrblr = 1; - up->smc_maxidl = 0; + /* single/multi character receive. */ + up->smc_mrblr = CONFIG_SYS_SMC_RXBUFLEN; + up->smc_maxidl = CONFIG_SYS_MAXIDLE; + rtx->rxindex = 0; - /* Initialize Tx/Rx parameters. - */ + /* Initialize Tx/Rx parameters. */ while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */ ; @@ -162,8 +177,7 @@ int serial_init (void) while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */ ; - /* Enable transmitter/receiver. - */ + /* Enable transmitter/receiver. */ sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN; return (0); @@ -183,27 +197,23 @@ serial_setbrg (void) void serial_putc(const char c) { - volatile cbd_t *tbdf; - volatile char *buf; volatile smc_uart_t *up; volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR; + volatile serialbuffer_t *rtx; if (c == '\n') serial_putc ('\r'); up = (smc_uart_t *)&(im->im_dprambase[PROFF_SMC]); - tbdf = (cbd_t *)&im->im_dprambase[up->smc_tbase]; + rtx = (serialbuffer_t *)&im->im_dprambase[up->smc_rbase]; - /* Wait for last character to go. - */ - buf = (char *)tbdf->cbd_bufaddr; - while (tbdf->cbd_sc & BD_SC_READY) + /* Wait for last character to go. */ + while (rtx->txbd.cbd_sc & BD_SC_READY & BD_SC_READY) ; - - *buf = c; - tbdf->cbd_datlen = 1; - tbdf->cbd_sc |= BD_SC_READY; + rtx->txbuf = c; + rtx->txbd.cbd_datlen = 1; + rtx->txbd.cbd_sc |= BD_SC_READY; } void @@ -217,39 +227,44 @@ serial_puts (const char *s) int serial_getc(void) { - volatile cbd_t *rbdf; - volatile unsigned char *buf; volatile smc_uart_t *up; volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR; - unsigned char c; + volatile serialbuffer_t *rtx; + unsigned char c; up = (smc_uart_t *)&(im->im_dprambase[PROFF_SMC]); - rbdf = (cbd_t *)&im->im_dprambase[up->smc_rbase]; + rtx = (serialbuffer_t *)&im->im_dprambase[up->smc_rbase]; - /* Wait for character to show up. - */ - buf = (unsigned char *)rbdf->cbd_bufaddr; - while (rbdf->cbd_sc & BD_SC_EMPTY) + /* Wait for character to show up. */ + while (rtx->rxbd.cbd_sc & BD_SC_EMPTY) ; - c = *buf; - rbdf->cbd_sc |= BD_SC_EMPTY; + /* the characters are read one by one, + * use the rxindex to know the next char to deliver + */ + c = *(unsigned char *) (rtx->rxbd.cbd_bufaddr + rtx->rxindex); + rtx->rxindex++; + + /* check if all char are readout, then make prepare for next receive */ + if (rtx->rxindex >= rtx->rxbd.cbd_datlen) { + rtx->rxindex = 0; + rtx->rxbd.cbd_sc |= BD_SC_EMPTY; + } return(c); } int serial_tstc() { - volatile cbd_t *rbdf; volatile smc_uart_t *up; volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR; + volatile serialbuffer_t *rtx; up = (smc_uart_t *)&(im->im_dprambase[PROFF_SMC]); + rtx = (serialbuffer_t *)&im->im_dprambase[up->smc_rbase]; - rbdf = (cbd_t *)&im->im_dprambase[up->smc_rbase]; - - return(!(rbdf->cbd_sc & BD_SC_EMPTY)); + return !(rtx->rxbd.cbd_sc & BD_SC_EMPTY); } #endif /* CONFIG_CONS_ON_SMC */ @@ -309,8 +324,7 @@ kgdb_serial_init (void) *(ushort *)(&im->im_dprambase[KGDB_PROFF_SMC_BASE]) = KGDB_PROFF_SMC; up = (smc_uart_t *)&im->im_dprambase[KGDB_PROFF_SMC]; - /* Disable transmitter/receiver. - */ + /* Disable transmitter/receiver. */ sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); /* NOTE: I/O port pins are set up via the iop_conf_tab[] table */ @@ -331,8 +345,7 @@ kgdb_serial_init (void) tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1; tbdf->cbd_sc = 0; - /* Set up the uart parameters in the parameter ram. - */ + /* Set up the uart parameters in the parameter ram. */ up->smc_rbase = dpaddr; up->smc_tbase = dpaddr+sizeof(cbd_t); up->smc_rfcr = CPMFCR_EB; @@ -346,8 +359,7 @@ kgdb_serial_init (void) */ sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART; - /* Mask all interrupts and remove anything pending. - */ + /* Mask all interrupts and remove anything pending. */ sp->smc_smcm = 0; sp->smc_smce = 0xff; @@ -357,8 +369,7 @@ kgdb_serial_init (void) im->im_cpmux.cmx_smr = (im->im_cpmux.cmx_smr & ~KGDB_CMXSMR_MASK) | KGDB_CMXSMR_VALUE; - /* Set up the baud rate generator. - */ + /* Set up the baud rate generator. */ #if defined(CONFIG_KGDB_USE_EXTC) m8260_cpm_extcbrg(brg_map[KGDB_SMC_INDEX], speed, CONFIG_KGDB_EXTC_RATE, CONFIG_KGDB_EXTC_PINSEL); @@ -366,18 +377,15 @@ kgdb_serial_init (void) m8260_cpm_setbrg(brg_map[KGDB_SMC_INDEX], speed); #endif - /* Make the first buffer the only buffer. - */ + /* Make the first buffer the only buffer. */ tbdf->cbd_sc |= BD_SC_WRAP; rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP; - /* Single character receive. - */ + /* Single character receive. */ up->smc_mrblr = 1; up->smc_maxidl = 0; - /* Initialize Tx/Rx parameters. - */ + /* Initialize Tx/Rx parameters. */ while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */ ; @@ -388,8 +396,7 @@ kgdb_serial_init (void) while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */ ; - /* Enable transmitter/receiver. - */ + /* Enable transmitter/receiver. */ sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN; printf("SMC%d at %dbps ", CONFIG_KGDB_INDEX, speed); @@ -410,8 +417,7 @@ putDebugChar(const char c) tbdf = (cbd_t *)&im->im_dprambase[up->smc_tbase]; - /* Wait for last character to go. - */ + /* Wait for last character to go. */ buf = (char *)tbdf->cbd_bufaddr; while (tbdf->cbd_sc & BD_SC_READY) ; @@ -442,8 +448,7 @@ getDebugChar(void) rbdf = (cbd_t *)&im->im_dprambase[up->smc_rbase]; - /* Wait for character to show up. - */ + /* Wait for character to show up. */ buf = (unsigned char *)rbdf->cbd_bufaddr; while (rbdf->cbd_sc & BD_SC_EMPTY) ; diff --git a/cpu/mpc83xx/Makefile b/cpu/mpc83xx/Makefile index fcb6a52..dd35e6b 100644 --- a/cpu/mpc83xx/Makefile +++ b/cpu/mpc83xx/Makefile @@ -39,6 +39,7 @@ COBJS-y += ecc.o COBJS-$(CONFIG_QE) += qe_io.o COBJS-$(CONFIG_FSL_SERDES) += serdes.o COBJS-$(CONFIG_83XX_GENERIC_PCI) += pci.o +COBJS-$(CONFIG_83XX_GENERIC_PCIE) += pcie.o COBJS-$(CONFIG_OF_LIBFDT) += fdt.o COBJS := $(COBJS-y) diff --git a/cpu/mpc83xx/cpu.c b/cpu/mpc83xx/cpu.c index 587fca3..9e0a05d 100644 --- a/cpu/mpc83xx/cpu.c +++ b/cpu/mpc83xx/cpu.c @@ -34,6 +34,7 @@ #include <libfdt.h> #include <tsec.h> #include <netdev.h> +#include <fsl_esdhc.h> DECLARE_GLOBAL_DATA_PTR; @@ -385,3 +386,16 @@ int cpu_eth_init(bd_t *bis) #endif return 0; } + +/* + * Initializes on-chip MMC controllers. + * to override, implement board_mmc_init() + */ +int cpu_mmc_init(bd_t *bis) +{ +#ifdef CONFIG_FSL_ESDHC + return fsl_esdhc_mmc_init(bis); +#else + return 0; +#endif +} diff --git a/cpu/mpc83xx/ecc.c b/cpu/mpc83xx/ecc.c index 5ab169f..f3942b4 100644 --- a/cpu/mpc83xx/ecc.c +++ b/cpu/mpc83xx/ecc.c @@ -119,7 +119,7 @@ int do_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) writeback[1] = 0x89abcdefUL; if (argc > 4) { - printf("Usage:\n%s\n", cmdtp->usage); + cmd_usage(cmdtp); return 1; } @@ -350,12 +350,12 @@ int do_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) return 0; } } - printf("Usage:\n%s\n", cmdtp->usage); + cmd_usage(cmdtp); return 1; } U_BOOT_CMD(ecc, 4, 0, do_ecc, - "ecc - support for DDR ECC features\n", + "support for DDR ECC features", "status - print out status info\n" "ecc captureclear - clear capture regs data\n" "ecc sbecnt <val> - set Single-Bit Error counter\n" diff --git a/cpu/mpc83xx/pci.c b/cpu/mpc83xx/pci.c index ab0760b..5fe8964 100644 --- a/cpu/mpc83xx/pci.c +++ b/cpu/mpc83xx/pci.c @@ -89,7 +89,7 @@ static void pci_init_bus(int bus, struct pci_region *reg) hose->regions[i].bus_start = 0; hose->regions[i].phys_start = 0; hose->regions[i].size = gd->ram_size; - hose->regions[i].flags = PCI_REGION_MEM | PCI_REGION_MEMORY; + hose->regions[i].flags = PCI_REGION_MEM | PCI_REGION_SYS_MEMORY; hose->first_busno = 0; hose->last_busno = 0xff; @@ -118,10 +118,12 @@ static void pci_init_bus(int bus, struct pci_region *reg) #ifdef CONFIG_PCI_SCAN_SHOW printf("PCI: Bus Dev VenId DevId Class Int\n"); #endif +#ifndef CONFIG_PCISLAVE /* * Hose scan. */ hose->last_busno = pci_hose_scan(hose); +#endif } /* @@ -190,6 +192,9 @@ void mpc83xx_pcislave_unlock(int bus) pci_hose_read_config_word (hose, dev, PCI_FUNCTION_CONFIG, ®16); reg16 &= ~(PCI_FUNCTION_CFG_LOCK); pci_hose_write_config_word (hose, dev, PCI_FUNCTION_CONFIG, reg16); + + /* The configuration bit is now unlocked, so we can scan the bus */ + hose->last_busno = pci_hose_scan(hose); } #endif diff --git a/cpu/mpc83xx/pcie.c b/cpu/mpc83xx/pcie.c new file mode 100644 index 0000000..12b5f69 --- /dev/null +++ b/cpu/mpc83xx/pcie.c @@ -0,0 +1,314 @@ +/* + * Copyright (C) 2007-2009 Freescale Semiconductor, Inc. + * Copyright (C) 2008-2009 MontaVista Software, Inc. + * + * Authors: Tony Li <tony.li@freescale.com> + * Anton Vorontsov <avorontsov@ru.mvista.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <pci.h> +#include <mpc83xx.h> +#include <asm/io.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define PCIE_MAX_BUSES 2 + +#ifdef CONFIG_83XX_GENERIC_PCIE_REGISTER_HOSES + +static int mpc83xx_pcie_remap_cfg(struct pci_controller *hose, pci_dev_t dev) +{ + int bus = PCI_BUS(dev) - hose->first_busno; + immap_t *immr = (immap_t *)CONFIG_SYS_IMMR; + pex83xx_t *pex = &immr->pciexp[bus]; + struct pex_outbound_window *out_win = &pex->bridge.pex_outbound_win[0]; + u8 devfn = PCI_DEV(dev) << 3 | PCI_FUNC(dev); + u32 dev_base = bus << 24 | devfn << 16; + + if (hose->indirect_type == INDIRECT_TYPE_NO_PCIE_LINK) + return -1; + /* + * Workaround for the HW bug: for Type 0 configure transactions the + * PCI-E controller does not check the device number bits and just + * assumes that the device number bits are 0. + */ + if (devfn & 0xf8) + return -1; + + out_le32(&out_win->tarl, dev_base); + return 0; +} + +#define cfg_read(val, addr, type, op) \ + do { *val = op((type)(addr)); } while (0) +#define cfg_write(val, addr, type, op) \ + do { op((type *)(addr), (val)); } while (0) + +#define PCIE_OP(rw, size, type, op) \ +static int pcie_##rw##_config_##size(struct pci_controller *hose, \ + pci_dev_t dev, int offset, \ + type val) \ +{ \ + int ret; \ + \ + ret = mpc83xx_pcie_remap_cfg(hose, dev); \ + if (ret) \ + return ret; \ + cfg_##rw(val, (void *)hose->cfg_addr + offset, type, op); \ + return 0; \ +} + +PCIE_OP(read, byte, u8 *, in_8) +PCIE_OP(read, word, u16 *, in_le16) +PCIE_OP(read, dword, u32 *, in_le32) +PCIE_OP(write, byte, u8, out_8) +PCIE_OP(write, word, u16, out_le16) +PCIE_OP(write, dword, u32, out_le32) + +static void mpc83xx_pcie_register_hose(int bus, struct pci_region *reg, + u8 link) +{ + extern void disable_addr_trans(void); /* start.S */ + static struct pci_controller pcie_hose[PCIE_MAX_BUSES]; + static int max_bus; + struct pci_controller *hose = &pcie_hose[bus]; + int i; + + /* + * There are no spare BATs to remap all PCI-E windows for U-Boot, so + * disable translations. In general, this is not great solution, and + * that's why we don't register PCI-E hoses by default. + */ + disable_addr_trans(); + + for (i = 0; i < 2; i++, reg++) { + if (reg->size == 0) + break; + + hose->regions[i] = *reg; + hose->region_count++; + } + + i = hose->region_count++; + hose->regions[i].bus_start = 0; + hose->regions[i].phys_start = 0; + hose->regions[i].size = gd->ram_size; + hose->regions[i].flags = PCI_REGION_MEM | PCI_REGION_SYS_MEMORY; + + i = hose->region_count++; + hose->regions[i].bus_start = CONFIG_SYS_IMMR; + hose->regions[i].phys_start = CONFIG_SYS_IMMR; + hose->regions[i].size = 0x100000; + hose->regions[i].flags = PCI_REGION_MEM | PCI_REGION_SYS_MEMORY; + + hose->first_busno = max_bus; + hose->last_busno = 0xff; + + if (bus == 0) + hose->cfg_addr = (unsigned int *)CONFIG_SYS_PCIE1_CFG_BASE; + else + hose->cfg_addr = (unsigned int *)CONFIG_SYS_PCIE2_CFG_BASE; + + pci_set_ops(hose, + pcie_read_config_byte, + pcie_read_config_word, + pcie_read_config_dword, + pcie_write_config_byte, + pcie_write_config_word, + pcie_write_config_dword); + + if (!link) + hose->indirect_type = INDIRECT_TYPE_NO_PCIE_LINK; + + pci_register_hose(hose); + +#ifdef CONFIG_PCI_SCAN_SHOW + printf("PCI: Bus Dev VenId DevId Class Int\n"); +#endif + /* + * Hose scan. + */ + hose->last_busno = pci_hose_scan(hose); + max_bus = hose->last_busno + 1; +} + +#else + +static void mpc83xx_pcie_register_hose(int bus, struct pci_region *reg, + u8 link) {} + +#endif /* CONFIG_83XX_GENERIC_PCIE_REGISTER_HOSES */ + +static void mpc83xx_pcie_init_bus(int bus, struct pci_region *reg) +{ + immap_t *immr = (immap_t *)CONFIG_SYS_IMMR; + pex83xx_t *pex = &immr->pciexp[bus]; + struct pex_outbound_window *out_win; + struct pex_inbound_window *in_win; + void *hose_cfg_base; + unsigned int ram_sz; + unsigned int barl; + unsigned int tar; + u16 reg16; + int i; + + /* Enable pex csb bridge inbound & outbound transactions */ + out_le32(&pex->bridge.pex_csb_ctrl, + in_le32(&pex->bridge.pex_csb_ctrl) | PEX_CSB_CTRL_OBPIOE | + PEX_CSB_CTRL_IBPIOE); + + /* Enable bridge outbound */ + out_le32(&pex->bridge.pex_csb_obctrl, PEX_CSB_OBCTRL_PIOE | + PEX_CSB_OBCTRL_MEMWE | PEX_CSB_OBCTRL_IOWE | + PEX_CSB_OBCTRL_CFGWE); + + out_win = &pex->bridge.pex_outbound_win[0]; + if (bus) { + out_le32(&out_win->ar, PEX_OWAR_EN | PEX_OWAR_TYPE_CFG | + CONFIG_SYS_PCIE2_CFG_SIZE); + out_le32(&out_win->bar, CONFIG_SYS_PCIE2_CFG_BASE); + } else { + out_le32(&out_win->ar, PEX_OWAR_EN | PEX_OWAR_TYPE_CFG | + CONFIG_SYS_PCIE1_CFG_SIZE); + out_le32(&out_win->bar, CONFIG_SYS_PCIE1_CFG_BASE); + } + out_le32(&out_win->tarl, 0); + out_le32(&out_win->tarh, 0); + + for (i = 0; i < 2; i++, reg++) { + u32 ar; + + if (reg->size == 0) + break; + + out_win = &pex->bridge.pex_outbound_win[i + 1]; + out_le32(&out_win->bar, reg->phys_start); + out_le32(&out_win->tarl, reg->bus_start); + out_le32(&out_win->tarh, 0); + ar = PEX_OWAR_EN | (reg->size & PEX_OWAR_SIZE); + if (reg->flags & PCI_REGION_IO) + ar |= PEX_OWAR_TYPE_IO; + else + ar |= PEX_OWAR_TYPE_MEM; + out_le32(&out_win->ar, ar); + } + + out_le32(&pex->bridge.pex_csb_ibctrl, PEX_CSB_IBCTRL_PIOE); + + ram_sz = gd->ram_size; + barl = 0; + tar = 0; + i = 0; + while (ram_sz > 0) { + in_win = &pex->bridge.pex_inbound_win[i]; + out_le32(&in_win->barl, barl); + out_le32(&in_win->barh, 0x0); + out_le32(&in_win->tar, tar); + if (ram_sz >= 0x10000000) { + /* The maxium windows size is 256M */ + out_le32(&in_win->ar, PEX_IWAR_EN | PEX_IWAR_NSOV | + PEX_IWAR_TYPE_PF | 0x0FFFF000); + barl += 0x10000000; + tar += 0x10000000; + ram_sz -= 0x10000000; + } else { + /* The UM is not clear here. + * So, round up to even Mb boundary */ + + ram_sz = ram_sz >> (20 + + ((ram_sz & 0xFFFFF) ? 1 : 0)); + if (!(ram_sz % 2)) + ram_sz -= 1; + out_le32(&in_win->ar, PEX_IWAR_EN | PEX_IWAR_NSOV | + PEX_IWAR_TYPE_PF | (ram_sz << 20) | 0xFF000); + ram_sz = 0; + } + i++; + } + + in_win = &pex->bridge.pex_inbound_win[i]; + out_le32(&in_win->barl, CONFIG_SYS_IMMR); + out_le32(&in_win->barh, 0); + out_le32(&in_win->tar, CONFIG_SYS_IMMR); + out_le32(&in_win->ar, PEX_IWAR_EN | + PEX_IWAR_TYPE_NO_PF | PEX_IWAR_SIZE_1M); + + /* Enable the host virtual INTX interrupts */ + out_le32(&pex->bridge.pex_int_axi_misc_enb, + in_le32(&pex->bridge.pex_int_axi_misc_enb) | 0x1E0); + + /* Hose configure header is memory-mapped */ + hose_cfg_base = (void *)pex; + + get_clocks(); + /* Configure the PCIE controller core clock ratio */ + out_le32(hose_cfg_base + PEX_GCLK_RATIO, + (((bus ? gd->pciexp2_clk : gd->pciexp1_clk) / 1000000) * 16) + / 333); + udelay(1000000); + + /* Do Type 1 bridge configuration */ + out_8(hose_cfg_base + PCI_PRIMARY_BUS, 0); + out_8(hose_cfg_base + PCI_SECONDARY_BUS, 1); + out_8(hose_cfg_base + PCI_SUBORDINATE_BUS, 255); + + /* + * Write to Command register + */ + reg16 = in_le16(hose_cfg_base + PCI_COMMAND); + reg16 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO | + PCI_COMMAND_SERR | PCI_COMMAND_PARITY; + out_le16(hose_cfg_base + PCI_COMMAND, reg16); + + /* + * Clear non-reserved bits in status register. + */ + out_le16(hose_cfg_base + PCI_STATUS, 0xffff); + out_8(hose_cfg_base + PCI_LATENCY_TIMER, 0x80); + out_8(hose_cfg_base + PCI_CACHE_LINE_SIZE, 0x08); + + printf("PCIE%d: ", bus); + + reg16 = in_le16(hose_cfg_base + PCI_LTSSM); + if (reg16 >= PCI_LTSSM_L0) + printf("link\n"); + else + printf("No link\n"); + + mpc83xx_pcie_register_hose(bus, reg, reg16 >= PCI_LTSSM_L0); +} + +/* + * The caller must have already set SCCR, SERDES and the PCIE_LAW BARs + * must have been set to cover all of the requested regions. + */ +void mpc83xx_pcie_init(int num_buses, struct pci_region **reg, int warmboot) +{ + int i; + + /* + * Release PCI RST Output signal. + * Power on to RST high must be at least 100 ms as per PCI spec. + * On warm boots only 1 ms is required. + */ + udelay(warmboot ? 1000 : 100000); + + for (i = 0; i < num_buses; i++) + mpc83xx_pcie_init_bus(i, reg[i]); +} diff --git a/cpu/mpc83xx/speed.c b/cpu/mpc83xx/speed.c index bf9bf36..9b7e7b5 100644 --- a/cpu/mpc83xx/speed.c +++ b/cpu/mpc83xx/speed.c @@ -132,7 +132,7 @@ int get_clocks(void) u32 qe_clk; u32 brg_clk; #endif -#if defined(CONFIG_MPC837X) +#if defined(CONFIG_MPC837X) || defined(CONFIG_MPC831X) u32 pciexp1_clk; u32 pciexp2_clk; #endif @@ -328,7 +328,7 @@ int get_clocks(void) i2c2_clk = csb_clk; /* i2c-2 clk is equal to csb clk */ #endif -#if defined(CONFIG_MPC837X) +#if defined(CONFIG_MPC837X) || defined(CONFIG_MPC831X) switch ((sccr & SCCR_PCIEXP1CM) >> SCCR_PCIEXP1CM_SHIFT) { case 0: pciexp1_clk = 0; @@ -544,6 +544,6 @@ int do_clocks (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) } U_BOOT_CMD(clocks, 1, 0, do_clocks, - "clocks - print clock configuration\n", + "print clock configuration", " clocks\n" ); diff --git a/cpu/mpc83xx/start.S b/cpu/mpc83xx/start.S index 792b2c8..26e3106 100644 --- a/cpu/mpc83xx/start.S +++ b/cpu/mpc83xx/start.S @@ -109,6 +109,45 @@ version_string: .ascii " (", U_BOOT_DATE, " - ", U_BOOT_TIME, ")" .ascii " ", CONFIG_IDENT_STRING, "\0" + .align 2 + + .globl enable_addr_trans +enable_addr_trans: + /* enable address translation */ + mfmsr r5 + ori r5, r5, (MSR_IR | MSR_DR) + mtmsr r5 + isync + blr + + .globl disable_addr_trans +disable_addr_trans: + /* disable address translation */ + mflr r4 + mfmsr r3 + andi. r0, r3, (MSR_IR | MSR_DR) + beqlr + andc r3, r3, r0 + mtspr SRR0, r4 + mtspr SRR1, r3 + rfi + + .globl get_pvr +get_pvr: + mfspr r3, PVR + blr + + .globl ppcDWstore +ppcDWstore: + lfd 1, 0(r4) + stfd 1, 0(r3) + blr + + .globl ppcDWload +ppcDWload: + lfd 1, 0(r3) + stfd 1, 0(r4) + blr #ifndef CONFIG_DEFAULT_IMMR #error CONFIG_DEFAULT_IMMR must be defined @@ -161,9 +200,23 @@ boot_cold: /* time t 3 */ nop boot_warm: /* time t 5 */ mfmsr r5 /* save msr contents */ + + /* 83xx manuals prescribe a specific sequence for updating IMMRBAR. */ + bl 1f +1: mflr r7 + lis r3, CONFIG_SYS_IMMR@h ori r3, r3, CONFIG_SYS_IMMR@l + + lwz r6, IMMRBAR(r4) + isync + stw r3, IMMRBAR(r4) + lwz r6, 0(r7) /* Arbitrary external load */ + isync + + lwz r6, IMMRBAR(r3) + isync /* Initialise the E300 processor core */ /*------------------------------------------*/ @@ -173,9 +226,7 @@ boot_warm: /* time t 5 */ * is loaded. Wait for the rest before branching * to another flash page. */ - addi r7, r3, 0x50b0 -1: dcbi 0, r7 - lwz r6, 0(r7) +1: lwz r6, 0x50b0(r3) andi. r6, r6, 1 beq 1b #endif @@ -698,27 +749,6 @@ setup_bats: blr - .globl enable_addr_trans -enable_addr_trans: - /* enable address translation */ - mfmsr r5 - ori r5, r5, (MSR_IR | MSR_DR) - mtmsr r5 - isync - blr - - .globl disable_addr_trans -disable_addr_trans: - /* disable address translation */ - mflr r4 - mfmsr r3 - andi. r0, r3, (MSR_IR | MSR_DR) - beqlr - andc r3, r3, r0 - mtspr SRR0, r4 - mtspr SRR1, r3 - rfi - /* Cache functions. * * Note: requires that all cache bits in @@ -796,23 +826,6 @@ flush_dcache: b 1b 2: blr - .globl get_pvr -get_pvr: - mfspr r3, PVR - blr - - .globl ppcDWstore -ppcDWstore: - lfd 1, 0(r4) - stfd 1, 0(r3) - blr - - .globl ppcDWload -ppcDWload: - lfd 1, 0(r3) - stfd 1, 0(r4) - blr - /*-------------------------------------------------------------------*/ /* diff --git a/cpu/mpc85xx/Makefile b/cpu/mpc85xx/Makefile index 627e61b..99d88a8 100644 --- a/cpu/mpc85xx/Makefile +++ b/cpu/mpc85xx/Makefile @@ -48,6 +48,7 @@ COBJS-$(CONFIG_MPC8544) += ddr-gen2.o # supports ddr1/2/3 COBJS-$(CONFIG_MPC8572) += ddr-gen3.o COBJS-$(CONFIG_MPC8536) += ddr-gen3.o +COBJS-$(CONFIG_P2020) += ddr-gen3.o COBJS-$(CONFIG_MPC8536) += mpc8536_serdes.o COBJS = traps.o cpu.o cpu_init.o speed.o interrupts.o tlb.o \ diff --git a/cpu/mpc85xx/cpu.c b/cpu/mpc85xx/cpu.c index 943602f..5b72fe5 100644 --- a/cpu/mpc85xx/cpu.c +++ b/cpu/mpc85xx/cpu.c @@ -31,6 +31,7 @@ #include <command.h> #include <tsec.h> #include <netdev.h> +#include <fsl_esdhc.h> #include <asm/cache.h> #include <asm/io.h> @@ -62,6 +63,8 @@ struct cpu_type cpu_type_list [] = { CPU_TYPE_ENTRY(8568, 8568_E), CPU_TYPE_ENTRY(8572, 8572), CPU_TYPE_ENTRY(8572, 8572_E), + CPU_TYPE_ENTRY(P2020, P2020), + CPU_TYPE_ENTRY(P2020, P2020_E), }; struct cpu_type *identify_cpu(u32 ver) @@ -77,8 +80,6 @@ struct cpu_type *identify_cpu(u32 ver) int checkcpu (void) { sys_info_t sysinfo; - uint lcrr; /* local bus clock ratio register */ - uint clkdiv; /* clock divider portion of lcrr */ uint pvr, svr; uint fam; uint ver; @@ -92,6 +93,7 @@ int checkcpu (void) #else u32 ddr_ratio = 0; #endif + int i; svr = get_svr(); ver = SVR_SOC_VER(svr); @@ -143,9 +145,14 @@ int checkcpu (void) get_sys_info(&sysinfo); - puts("Clock Configuration:\n"); - printf(" CPU:%-4s MHz, ", strmhz(buf1, sysinfo.freqProcessor)); - printf("CCB:%-4s MHz,\n", strmhz(buf1, sysinfo.freqSystemBus)); + puts("Clock Configuration:"); + for (i = 0; i < CONFIG_NUM_CPUS; i++) { + if (!(i & 3)) + printf ("\n "); + printf("CPU%d:%-4s MHz, ", + i,strmhz(buf1, sysinfo.freqProcessor[i])); + } + printf("\n CCB:%-4s MHz,\n", strmhz(buf1, sysinfo.freqSystemBus)); switch (ddr_ratio) { case 0x0: @@ -165,30 +172,11 @@ int checkcpu (void) break; } -#if defined(CONFIG_SYS_LBC_LCRR) - lcrr = CONFIG_SYS_LBC_LCRR; -#else - { - volatile ccsr_lbc_t *lbc = (void *)(CONFIG_SYS_MPC85xx_LBC_ADDR); - - lcrr = lbc->lcrr; - } -#endif - clkdiv = lcrr & 0x0f; - if (clkdiv == 2 || clkdiv == 4 || clkdiv == 8) { -#if defined(CONFIG_MPC8548) || defined(CONFIG_MPC8544) || \ - defined(CONFIG_MPC8572) || defined(CONFIG_MPC8536) - /* - * Yes, the entire PQ38 family use the same - * bit-representation for twice the clock divider values. - */ - clkdiv *= 2; -#endif - printf("LBC:%-4s MHz\n", - strmhz(buf1, sysinfo.freqSystemBus / clkdiv)); - } else { - printf("LBC: unknown (lcrr: 0x%08x)\n", lcrr); - } + if (sysinfo.freqLocalBus > LCRR_CLKDIV) + printf("LBC:%-4s MHz\n", strmhz(buf1, sysinfo.freqLocalBus)); + else + printf("LBC: unknown (LCRR[CLKDIV] = 0x%02lx)\n", + sysinfo.freqLocalBus); #ifdef CONFIG_CPM2 printf("CPM: %s MHz\n", strmhz(buf1, sysinfo.freqSystemBus)); @@ -408,5 +396,19 @@ int cpu_eth_init(bd_t *bis) #if defined(CONFIG_TSEC_ENET) || defined(CONFIG_MPC85XX_FEC) tsec_standard_init(bis); #endif + return 0; } + +/* + * Initializes on-chip MMC controllers. + * to override, implement board_mmc_init() + */ +int cpu_mmc_init(bd_t *bis) +{ +#ifdef CONFIG_FSL_ESDHC + return fsl_esdhc_mmc_init(bis); +#else + return 0; +#endif +} diff --git a/cpu/mpc85xx/ddr-gen3.c b/cpu/mpc85xx/ddr-gen3.c index a2b45c5..8dc2b3a 100644 --- a/cpu/mpc85xx/ddr-gen3.c +++ b/cpu/mpc85xx/ddr-gen3.c @@ -19,6 +19,7 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, { unsigned int i; volatile ccsr_ddr_t *ddr; + u32 temp_sdram_cfg; switch (ctrl_num) { case 0: @@ -78,6 +79,10 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, out_be32(&ddr->ddr_sdram_rcw_1, regs->ddr_sdram_rcw_1); out_be32(&ddr->ddr_sdram_rcw_2, regs->ddr_sdram_rcw_2); + /* Do not enable the memory */ + temp_sdram_cfg = in_be32(&ddr->sdram_cfg); + temp_sdram_cfg &= ~(SDRAM_CFG_MEM_EN); + out_be32(&ddr->sdram_cfg, temp_sdram_cfg); /* * For 8572 DDR1 erratum - DDR controller may enter illegal state * when operatiing in 32-bit bus mode with 4-beat bursts, @@ -99,7 +104,9 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, udelay(200); asm volatile("sync;isync"); - out_be32(&ddr->sdram_cfg, regs->ddr_sdram_cfg); + /* Let the controller go */ + temp_sdram_cfg = in_be32(&ddr->sdram_cfg); + out_be32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_MEM_EN); /* Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done. */ while (in_be32(&ddr->sdram_cfg_2) & 0x10) { diff --git a/cpu/mpc85xx/fdt.c b/cpu/mpc85xx/fdt.c index 59aafb1..1fae47c 100644 --- a/cpu/mpc85xx/fdt.c +++ b/cpu/mpc85xx/fdt.c @@ -28,11 +28,12 @@ #include <fdt_support.h> #include <asm/processor.h> +DECLARE_GLOBAL_DATA_PTR; + extern void ft_qe_setup(void *blob); #ifdef CONFIG_MP #include "mp.h" -DECLARE_GLOBAL_DATA_PTR; void ft_fixup_cpu(void *blob, u64 memory_limit) { @@ -212,6 +213,10 @@ void fdt_add_enet_stashing(void *fdt) void ft_cpu_setup(void *blob, bd_t *bd) { + int off; + int val; + sys_info_t sysinfo; + /* delete crypto node if not on an E-processor */ if (!IS_E_PROCESSOR(get_svr())) fdt_fixup_crypto_node(blob, 0); @@ -227,10 +232,22 @@ void ft_cpu_setup(void *blob, bd_t *bd) "timebase-frequency", bd->bi_busfreq / 8, 1); do_fixup_by_prop_u32(blob, "device_type", "cpu", 4, "bus-frequency", bd->bi_busfreq, 1); - do_fixup_by_prop_u32(blob, "device_type", "cpu", 4, - "clock-frequency", bd->bi_intfreq, 1); + get_sys_info(&sysinfo); + off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4); + while (off != -FDT_ERR_NOTFOUND) { + u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", 0); + val = cpu_to_fdt32(sysinfo.freqProcessor[*reg]); + fdt_setprop(blob, off, "clock-frequency", &val, 4); + off = fdt_node_offset_by_prop_value(blob, off, "device_type", + "cpu", 4); + } do_fixup_by_prop_u32(blob, "device_type", "soc", 4, "bus-frequency", bd->bi_busfreq, 1); + + do_fixup_by_compat_u32(blob, "fsl,pq3-localbus", + "bus-frequency", gd->lbc_clk, 1); + do_fixup_by_compat_u32(blob, "fsl,elbc", + "bus-frequency", gd->lbc_clk, 1); #ifdef CONFIG_QE ft_qe_setup(blob); #endif diff --git a/cpu/mpc85xx/pci.c b/cpu/mpc85xx/pci.c index 787c6eb..fedf1a5 100644 --- a/cpu/mpc85xx/pci.c +++ b/cpu/mpc85xx/pci.c @@ -31,6 +31,22 @@ #if defined(CONFIG_PCI) && !defined(CONFIG_FSL_PCI_INIT) +#ifndef CONFIG_SYS_PCI1_MEM_BUS +#define CONFIG_SYS_PCI1_MEM_BUS CONFIG_SYS_PCI1_MEM_BASE +#endif + +#ifndef CONFIG_SYS_PCI1_IO_BUS +#define CONFIG_SYS_PCI1_IO_BUS CONFIG_SYS_PCI1_IO_BASE +#endif + +#ifndef CONFIG_SYS_PCI2_MEM_BUS +#define CONFIG_SYS_PCI2_MEM_BUS CONFIG_SYS_PCI2_MEM_BASE +#endif + +#ifndef CONFIG_SYS_PCI2_IO_BUS +#define CONFIG_SYS_PCI2_IO_BUS CONFIG_SYS_PCI2_IO_BASE +#endif + static struct pci_controller *pci_hose; void @@ -80,14 +96,14 @@ pci_mpc85xx_init(struct pci_controller *board_hose) pci_hose_write_config_word(hose, dev, PCIX_COMMAND, reg16); } - pcix->potar1 = (CONFIG_SYS_PCI1_MEM_BASE >> 12) & 0x000fffff; + pcix->potar1 = (CONFIG_SYS_PCI1_MEM_BUS >> 12) & 0x000fffff; pcix->potear1 = 0x00000000; pcix->powbar1 = (CONFIG_SYS_PCI1_MEM_PHYS >> 12) & 0x000fffff; pcix->powbear1 = 0x00000000; pcix->powar1 = (POWAR_EN | POWAR_MEM_READ | POWAR_MEM_WRITE | (__ilog2(CONFIG_SYS_PCI1_MEM_SIZE) - 1)); - pcix->potar2 = (CONFIG_SYS_PCI1_IO_BASE >> 12) & 0x000fffff; + pcix->potar2 = (CONFIG_SYS_PCI1_IO_BUS >> 12) & 0x000fffff; pcix->potear2 = 0x00000000; pcix->powbar2 = (CONFIG_SYS_PCI1_IO_PHYS >> 12) & 0x000fffff; pcix->powbear2 = 0x00000000; @@ -105,13 +121,13 @@ pci_mpc85xx_init(struct pci_controller *board_hose) pcix->piwar3 = 0; pci_set_region(hose->regions + 0, - CONFIG_SYS_PCI1_MEM_BASE, + CONFIG_SYS_PCI1_MEM_BUS, CONFIG_SYS_PCI1_MEM_PHYS, CONFIG_SYS_PCI1_MEM_SIZE, PCI_REGION_MEM); pci_set_region(hose->regions + 1, - CONFIG_SYS_PCI1_IO_BASE, + CONFIG_SYS_PCI1_IO_BUS, CONFIG_SYS_PCI1_IO_PHYS, CONFIG_SYS_PCI1_IO_SIZE, PCI_REGION_IO); @@ -165,14 +181,14 @@ pci_mpc85xx_init(struct pci_controller *board_hose) */ pci_hose_write_config_word(hose, dev, PCI_STATUS, 0xffff); - pcix2->potar1 = (CONFIG_SYS_PCI2_MEM_BASE >> 12) & 0x000fffff; + pcix2->potar1 = (CONFIG_SYS_PCI2_MEM_BUS >> 12) & 0x000fffff; pcix2->potear1 = 0x00000000; pcix2->powbar1 = (CONFIG_SYS_PCI2_MEM_PHYS >> 12) & 0x000fffff; pcix2->powbear1 = 0x00000000; pcix2->powar1 = (POWAR_EN | POWAR_MEM_READ | POWAR_MEM_WRITE | (__ilog2(CONFIG_SYS_PCI2_MEM_SIZE) - 1)); - pcix2->potar2 = (CONFIG_SYS_PCI2_IO_BASE >> 12) & 0x000fffff; + pcix2->potar2 = (CONFIG_SYS_PCI2_IO_BUS >> 12) & 0x000fffff; pcix2->potear2 = 0x00000000; pcix2->powbar2 = (CONFIG_SYS_PCI2_IO_PHYS >> 12) & 0x000fffff; pcix2->powbear2 = 0x00000000; @@ -190,13 +206,13 @@ pci_mpc85xx_init(struct pci_controller *board_hose) pcix2->piwar3 = 0; pci_set_region(hose->regions + 0, - CONFIG_SYS_PCI2_MEM_BASE, + CONFIG_SYS_PCI2_MEM_BUS, CONFIG_SYS_PCI2_MEM_PHYS, CONFIG_SYS_PCI2_MEM_SIZE, PCI_REGION_MEM); pci_set_region(hose->regions + 1, - CONFIG_SYS_PCI2_IO_BASE, + CONFIG_SYS_PCI2_IO_BUS, CONFIG_SYS_PCI2_IO_PHYS, CONFIG_SYS_PCI2_IO_SIZE, PCI_REGION_IO); diff --git a/cpu/mpc85xx/release.S b/cpu/mpc85xx/release.S index 7c3e8a1..54c936c 100644 --- a/cpu/mpc85xx/release.S +++ b/cpu/mpc85xx/release.S @@ -157,6 +157,7 @@ __secondary_start_page: mfspr r0,SPRN_PIR stw r0,ENTRY_PIR(r10) + mtspr IVPR,r12 /* * Coming here, we know the cpu has one TLB mapping in TLB1[0] * which maps 0xfffff000-0xffffffff one-to-one. We set up a diff --git a/cpu/mpc85xx/speed.c b/cpu/mpc85xx/speed.c index 1e0f483..b0f47e0 100644 --- a/cpu/mpc85xx/speed.c +++ b/cpu/mpc85xx/speed.c @@ -28,6 +28,7 @@ #include <common.h> #include <ppc_asm.tmpl> #include <asm/processor.h> +#include <asm/io.h> DECLARE_GLOBAL_DATA_PTR; @@ -37,17 +38,20 @@ void get_sys_info (sys_info_t * sysInfo) { volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); uint plat_ratio,e500_ratio,half_freqSystemBus; + uint lcrr_div; + int i; plat_ratio = (gur->porpllsr) & 0x0000003e; plat_ratio >>= 1; sysInfo->freqSystemBus = plat_ratio * CONFIG_SYS_CLK_FREQ; - e500_ratio = (gur->porpllsr) & 0x003f0000; - e500_ratio >>= 16; /* Divide before multiply to avoid integer * overflow for processor speeds above 2GHz */ half_freqSystemBus = sysInfo->freqSystemBus/2; - sysInfo->freqProcessor = e500_ratio*half_freqSystemBus; + for (i = 0; i < CONFIG_NUM_CPUS; i++) { + e500_ratio = ((gur->porpllsr) >> (i * 8 + 16)) & 0x3f; + sysInfo->freqProcessor[i] = e500_ratio * half_freqSystemBus; + } /* Note: freqDDRBus is the MCLK frequency, not the data rate. */ sysInfo->freqDDRBus = sysInfo->freqSystemBus; @@ -60,6 +64,30 @@ void get_sys_info (sys_info_t * sysInfo) sysInfo->freqDDRBus = ddr_ratio * CONFIG_DDR_CLK_FREQ; } #endif + +#if defined(CONFIG_SYS_LBC_LCRR) + /* We will program LCRR to this value later */ + lcrr_div = CONFIG_SYS_LBC_LCRR & LCRR_CLKDIV; +#else + { + volatile ccsr_lbc_t *lbc = (void *)(CONFIG_SYS_MPC85xx_LBC_ADDR); + lcrr_div = in_be32(&lbc->lcrr) & LCRR_CLKDIV; + } +#endif + if (lcrr_div == 2 || lcrr_div == 4 || lcrr_div == 8) { +#if !defined(CONFIG_MPC8540) && !defined(CONFIG_MPC8541) && \ + !defined(CONFIG_MPC8555) && !defined(CONFIG_MPC8560) + /* + * Yes, the entire PQ38 family use the same + * bit-representation for twice the clock divider values. + */ + lcrr_div *= 2; +#endif + sysInfo->freqLocalBus = sysInfo->freqSystemBus / lcrr_div; + } else { + /* In case anyone cares what the unknown value is */ + sysInfo->freqLocalBus = lcrr_div; + } } @@ -79,9 +107,10 @@ int get_clocks (void) dfbrg = (sccr & SCCR_DFBRG_MSK) >> SCCR_DFBRG_SHIFT; #endif get_sys_info (&sys_info); - gd->cpu_clk = sys_info.freqProcessor; + gd->cpu_clk = sys_info.freqProcessor[0]; gd->bus_clk = sys_info.freqSystemBus; gd->mem_clk = sys_info.freqDDRBus; + gd->lbc_clk = sys_info.freqLocalBus; /* * The base clock for I2C depends on the actual SOC. Unfortunately, diff --git a/cpu/mpc85xx/start.S b/cpu/mpc85xx/start.S index 8fa0ff7..80f9677 100644 --- a/cpu/mpc85xx/start.S +++ b/cpu/mpc85xx/start.S @@ -184,19 +184,19 @@ _start_e500: mtspr DBCR0,r0 #endif - /* create a temp mapping in AS=1 to the boot window */ + /* create a temp mapping in AS=1 to the 4M boot window */ lis r6,FSL_BOOKE_MAS0(1, 15, 0)@h ori r6,r6,FSL_BOOKE_MAS0(1, 15, 0)@l - lis r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_16M)@h - ori r7,r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_16M)@l + lis r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_4M)@h + ori r7,r7,FSL_BOOKE_MAS1(1, 1, 0, 1, BOOKE_PAGESZ_4M)@l - /* Align the mapping to 16MB */ - lis r8,FSL_BOOKE_MAS2(TEXT_BASE & 0xff000000, (MAS2_I|MAS2_G))@h - ori r8,r8,FSL_BOOKE_MAS2(TEXT_BASE & 0xff000000, (MAS2_I|MAS2_G))@l + lis r8,FSL_BOOKE_MAS2(TEXT_BASE & 0xffc00000, (MAS2_I|MAS2_G))@h + ori r8,r8,FSL_BOOKE_MAS2(TEXT_BASE & 0xffc00000, (MAS2_I|MAS2_G))@l - lis r9,FSL_BOOKE_MAS3(0xff000000, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@h - ori r9,r9,FSL_BOOKE_MAS3(0xff000000, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@l + /* The 85xx has the default boot window 0xff800000 - 0xffffffff */ + lis r9,FSL_BOOKE_MAS3(0xffc00000, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@h + ori r9,r9,FSL_BOOKE_MAS3(0xffc00000, 0, (MAS3_SX|MAS3_SW|MAS3_SR))@l mtspr MAS0,r6 mtspr MAS1,r7 diff --git a/cpu/mpc85xx/tlb.c b/cpu/mpc85xx/tlb.c index a2d16ae..c73bf05 100644 --- a/cpu/mpc85xx/tlb.c +++ b/cpu/mpc85xx/tlb.c @@ -26,6 +26,11 @@ #include <common.h> #include <asm/processor.h> #include <asm/mmu.h> +#ifdef CONFIG_ADDR_MAP +#include <addr_map.h> +#endif + +DECLARE_GLOBAL_DATA_PTR; void set_tlb(u8 tlb, u32 epn, u64 rpn, u8 perms, u8 wimge, @@ -47,6 +52,11 @@ void set_tlb(u8 tlb, u32 epn, u64 rpn, mtspr(MAS7, _mas7); #endif asm volatile("isync;msync;tlbwe;isync"); + +#ifdef CONFIG_ADDR_MAP + if ((tlb == 1) && (gd->flags & GD_FLG_RELOC)) + addrmap_set_entry(epn, rpn, (1UL << ((tsize * 2) + 10)), esel); +#endif } void disable_tlb(u8 esel) @@ -67,6 +77,11 @@ void disable_tlb(u8 esel) mtspr(MAS7, _mas7); #endif asm volatile("isync;msync;tlbwe;isync"); + +#ifdef CONFIG_ADDR_MAP + if (gd->flags & GD_FLG_RELOC) + addrmap_set_entry(0, 0, 0, esel); +#endif } void invalidate_tlb(u8 tlb) @@ -91,64 +106,67 @@ void init_tlbs(void) return ; } +#ifdef CONFIG_ADDR_MAP +void init_addr_map(void) +{ + int i; + + for (i = 0; i < num_tlb_entries; i++) { + if (tlb_table[i].tlb == 0) + continue; + + addrmap_set_entry(tlb_table[i].epn, + tlb_table[i].rpn, + (1UL << ((tlb_table[i].tsize * 2) + 10)), + tlb_table[i].esel); + } + + return ; +} +#endif + +#ifndef CONFIG_SYS_DDR_TLB_START +#define CONFIG_SYS_DDR_TLB_START 8 +#endif + unsigned int setup_ddr_tlbs(unsigned int memsize_in_meg) { unsigned int tlb_size; - unsigned int ram_tlb_index; - unsigned int ram_tlb_address; + unsigned int ram_tlb_index = CONFIG_SYS_DDR_TLB_START; + unsigned int ram_tlb_address = (unsigned int)CONFIG_SYS_DDR_SDRAM_BASE; + unsigned int max_cam = (mfspr(SPRN_TLB1CFG) >> 16) & 0xff; + u64 size, memsize = (u64)memsize_in_meg << 20; - /* - * Determine size of each TLB1 entry. - */ - switch (memsize_in_meg) { - case 16: - case 32: - tlb_size = BOOKE_PAGESZ_16M; - break; - case 64: - case 128: - tlb_size = BOOKE_PAGESZ_64M; - break; - case 256: - case 512: - tlb_size = BOOKE_PAGESZ_256M; - break; - case 1024: - case 2048: - if (PVR_VER(get_pvr()) > PVR_VER(PVR_85xx)) - tlb_size = BOOKE_PAGESZ_1G; - else - tlb_size = BOOKE_PAGESZ_256M; - break; - default: - puts("DDR: only 16M, 32M, 64M, 128M, 256M, 512M, 1G" - " and 2G are supported.\n"); - - /* - * The memory was not able to be mapped. - * Default to a small size. - */ - tlb_size = BOOKE_PAGESZ_64M; - memsize_in_meg = 64; - break; - } + size = min(memsize, CONFIG_MAX_MEM_MAPPED); + + /* Convert (4^max) kB to (2^max) bytes */ + max_cam = max_cam * 2 + 10; + + for (; size && ram_tlb_index < 16; ram_tlb_index++) { + u32 camsize = __ilog2_u64(size) & ~1U; + u32 align = __ilog2(ram_tlb_address) & ~1U; + + if (align == -2) align = max_cam; + if (camsize > align) + camsize = align; + + if (camsize > max_cam) + camsize = max_cam; + + tlb_size = (camsize - 10) / 2; - /* - * Configure DDR TLB1 entries. - * Starting at TLB1 8, use no more than 8 TLB1 entries. - */ - ram_tlb_index = 8; - ram_tlb_address = (unsigned int)CONFIG_SYS_DDR_SDRAM_BASE; - while (ram_tlb_address < (memsize_in_meg * 1024 * 1024) - && ram_tlb_index < 16) { set_tlb(1, ram_tlb_address, ram_tlb_address, MAS3_SX|MAS3_SW|MAS3_SR, 0, 0, ram_tlb_index, tlb_size, 1); - ram_tlb_address += (0x1000 << ((tlb_size - 1) * 2)); - ram_tlb_index++; + size -= 1ULL << camsize; + memsize -= 1ULL << camsize; + ram_tlb_address += 1UL << camsize; } + if (memsize) + printf("%lldM left unmapped\n", memsize >> 20); + /* * Confirm that the requested amount of memory was mapped. */ diff --git a/cpu/mpc86xx/cpu.c b/cpu/mpc86xx/cpu.c index 4cace98..c41616d 100644 --- a/cpu/mpc86xx/cpu.c +++ b/cpu/mpc86xx/cpu.c @@ -32,6 +32,17 @@ #include <asm/fsl_law.h> +/* + * Default board reset function + */ +static void +__board_reset(void) +{ + /* Do nothing */ +} +void board_reset(void) __attribute((weak, alias("__board_reset"))); + + int checkcpu(void) { @@ -39,51 +50,25 @@ checkcpu(void) uint pvr, svr; uint ver; uint major, minor; - uint lcrr; /* local bus clock ratio register */ - uint clkdiv; /* clock divider portion of lcrr */ + char buf1[32], buf2[32]; volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; volatile ccsr_gur_t *gur = &immap->im_gur; - - puts("Freescale PowerPC\n"); - - pvr = get_pvr(); - ver = PVR_VER(pvr); - major = PVR_MAJ(pvr); - minor = PVR_MIN(pvr); - - puts("CPU:\n"); - puts(" Core: "); - - switch (ver) { - case PVR_VER(PVR_86xx): - { - uint msscr0 = mfspr(MSSCR0); - printf("E600 Core %d", (msscr0 & 0x20) ? 1 : 0 ); - if (gur->pordevsr & MPC86xx_PORDEVSR_CORE1TE) - puts("\n Core1Translation Enabled"); - debug(" (MSSCR0=%x, PORDEVSR=%x)", msscr0, gur->pordevsr); - } - break; - default: - puts("Unknown"); - break; - } - printf(", Version: %d.%d, (0x%08x)\n", major, minor, pvr); + uint msscr0 = mfspr(MSSCR0); svr = get_svr(); ver = SVR_SOC_VER(svr); major = SVR_MAJ(svr); minor = SVR_MIN(svr); - puts(" System: "); + puts("CPU: "); + switch (ver) { case SVR_8641: - if (SVR_SUBVER(svr) == 1) { - puts("8641D"); - } else { puts("8641"); - } - break; + break; + case SVR_8641D: + puts("8641D"); + break; case SVR_8610: puts("8610"); break; @@ -92,109 +77,69 @@ checkcpu(void) break; } printf(", Version: %d.%d, (0x%08x)\n", major, minor, svr); + puts("Core: "); - get_sys_info(&sysinfo); + pvr = get_pvr(); + ver = PVR_E600_VER(pvr); + major = PVR_E600_MAJ(pvr); + minor = PVR_E600_MIN(pvr); - puts(" Clocks: "); - printf("CPU:%4lu MHz, ", sysinfo.freqProcessor / 1000000); - printf("MPX:%4lu MHz, ", sysinfo.freqSystemBus / 1000000); - printf("DDR:%4lu MHz, ", sysinfo.freqSystemBus / 2000000); + printf("E600 Core %d", (msscr0 & 0x20) ? 1 : 0 ); + if (gur->pordevsr & MPC86xx_PORDEVSR_CORE1TE) + puts("\n Core1Translation Enabled"); + debug(" (MSSCR0=%x, PORDEVSR=%x)", msscr0, gur->pordevsr); -#if defined(CONFIG_SYS_LBC_LCRR) - lcrr = CONFIG_SYS_LBC_LCRR; -#else - { - volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; - volatile ccsr_lbc_t *lbc = &immap->im_lbc; + printf(", Version: %d.%d, (0x%08x)\n", major, minor, pvr); - lcrr = lbc->lcrr; - } -#endif - clkdiv = lcrr & 0x0f; - if (clkdiv == 2 || clkdiv == 4 || clkdiv == 8) { - printf("LBC:%4lu MHz\n", - sysinfo.freqSystemBus / 1000000 / clkdiv); + get_sys_info(&sysinfo); + + puts("Clock Configuration:\n"); + printf(" CPU:%-4s MHz, ", strmhz(buf1, sysinfo.freqProcessor)); + printf("MPX:%-4s MHz\n", strmhz(buf1, sysinfo.freqSystemBus)); + printf(" DDR:%-4s MHz (%s MT/s data rate), ", + strmhz(buf1, sysinfo.freqSystemBus / 2), + strmhz(buf2, sysinfo.freqSystemBus)); + + if (sysinfo.freqLocalBus > LCRR_CLKDIV) { + printf("LBC:%-4s MHz\n", strmhz(buf1, sysinfo.freqLocalBus)); } else { - printf(" LBC: unknown (lcrr: 0x%08x)\n", lcrr); + printf("LBC: unknown (LCRR[CLKDIV] = 0x%02lx)\n", + sysinfo.freqLocalBus); } - puts(" L2: "); - if (get_l2cr() & 0x80000000) - puts("Enabled\n"); - else + puts("L1: D-cache 32 KB enabled\n"); + puts(" I-cache 32 KB enabled\n"); + + puts("L2: "); + if (get_l2cr() & 0x80000000) { +#if defined(CONFIG_MPC8610) + puts("256"); +#elif defined(CONFIG_MPC8641) + puts("512"); +#endif + puts(" KB enabled\n"); + } else { puts("Disabled\n"); + } return 0; } -static inline void -soft_restart(unsigned long addr) -{ -#if !defined(CONFIG_MPC8641HPCN) && !defined(CONFIG_MPC8610HPCD) - - /* - * SRR0 has system reset vector, SRR1 has default MSR value - * rfi restores MSR from SRR1 and sets the PC to the SRR0 value - */ - - __asm__ __volatile__ ("mtspr 26, %0" :: "r" (addr)); - __asm__ __volatile__ ("li 4, (1 << 6)" ::: "r4"); - __asm__ __volatile__ ("mtspr 27, 4"); - __asm__ __volatile__ ("rfi"); - -#else /* CONFIG_MPC8641HPCN */ - - out8(PIXIS_BASE + PIXIS_RST, 0); - -#endif /* !CONFIG_MPC8641HPCN */ - - while (1) ; /* not reached */ -} - - -/* - * No generic way to do board reset. Simply call soft_reset. - */ void do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { -#if !defined(CONFIG_MPC8641HPCN) && !defined(CONFIG_MPC8610HPCD) - -#ifdef CONFIG_SYS_RESET_ADDRESS - ulong addr = CONFIG_SYS_RESET_ADDRESS; -#else - /* - * note: when CONFIG_SYS_MONITOR_BASE points to a RAM address, - * CONFIG_SYS_MONITOR_BASE - sizeof (ulong) is usually a valid - * address. Better pick an address known to be invalid on your - * system and assign it to CONFIG_SYS_RESET_ADDRESS. - */ - ulong addr = CONFIG_SYS_MONITOR_BASE - sizeof(ulong); -#endif - - /* flush and disable I/D cache */ - __asm__ __volatile__ ("mfspr 3, 1008" ::: "r3"); - __asm__ __volatile__ ("ori 5, 5, 0xcc00" ::: "r5"); - __asm__ __volatile__ ("ori 4, 3, 0xc00" ::: "r4"); - __asm__ __volatile__ ("andc 5, 3, 5" ::: "r5"); - __asm__ __volatile__ ("sync"); - __asm__ __volatile__ ("mtspr 1008, 4"); - __asm__ __volatile__ ("isync"); - __asm__ __volatile__ ("sync"); - __asm__ __volatile__ ("mtspr 1008, 5"); - __asm__ __volatile__ ("isync"); - __asm__ __volatile__ ("sync"); - - soft_restart(addr); - -#else /* CONFIG_MPC8641HPCN */ + volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR; + volatile ccsr_gur_t *gur = &immap->im_gur; - out8(PIXIS_BASE + PIXIS_RST, 0); + /* Attempt board-specific reset */ + board_reset(); -#endif /* !CONFIG_MPC8641HPCN */ + /* Next try asserting HRESET_REQ */ + out_be32(&gur->rstcr, MPC86xx_RSTCR_HRST_REQ); - while (1) ; /* not reached */ + while (1) + ; } diff --git a/cpu/mpc86xx/cpu_init.c b/cpu/mpc86xx/cpu_init.c index a7e6036..4f29122 100644 --- a/cpu/mpc86xx/cpu_init.c +++ b/cpu/mpc86xx/cpu_init.c @@ -154,3 +154,30 @@ void setup_bats(void) return; } + +#ifdef CONFIG_ADDR_MAP +/* Initialize address mapping array */ +void init_addr_map(void) +{ + int i; + ppc_bat_t bat = DBAT0; + phys_size_t size; + unsigned long upper, lower; + + for (i = 0; i < CONFIG_SYS_NUM_ADDR_MAP; i++, bat++) { + if (read_bat(bat, &upper, &lower) != -1) { + if (!BATU_VALID(upper)) + size = 0; + else + size = BATU_SIZE(upper); + addrmap_set_entry(BATU_VADDR(upper), BATL_PADDR(lower), + size, i); + } +#ifdef CONFIG_HIGH_BATS + /* High bats are not contiguous with low BAT numbers */ + if (bat == DBAT3) + bat = DBAT4 - 1; +#endif + } +} +#endif diff --git a/cpu/mpc86xx/fdt.c b/cpu/mpc86xx/fdt.c index 3adfad9..383b06b 100644 --- a/cpu/mpc86xx/fdt.c +++ b/cpu/mpc86xx/fdt.c @@ -29,6 +29,13 @@ void ft_cpu_setup(void *blob, bd_t *bd) do_fixup_by_prop_u32(blob, "device_type", "soc", 4, "bus-frequency", bd->bi_busfreq, 1); +#if defined(CONFIG_MPC8641) + do_fixup_by_compat_u32(blob, "fsl,mpc8641-localbus", + "bus-frequency", gd->lbc_clk, 1); +#endif + do_fixup_by_compat_u32(blob, "fsl,elbc", + "bus-frequency", gd->lbc_clk, 1); + fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize); #if defined(CONFIG_HAS_ETH0) || defined(CONFIG_HAS_ETH1) \ diff --git a/cpu/mpc86xx/speed.c b/cpu/mpc86xx/speed.c index 415ac9d..64a3479 100644 --- a/cpu/mpc86xx/speed.c +++ b/cpu/mpc86xx/speed.c @@ -28,6 +28,7 @@ #include <common.h> #include <mpc86xx.h> #include <asm/processor.h> +#include <asm/io.h> DECLARE_GLOBAL_DATA_PTR; @@ -39,6 +40,7 @@ void get_sys_info(sys_info_t *sysInfo) volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; volatile ccsr_gur_t *gur = &immap->im_gur; uint plat_ratio, e600_ratio; + uint lcrr_div; plat_ratio = (gur->porpllsr) & 0x0000003e; plat_ratio >>= 1; @@ -90,6 +92,22 @@ void get_sys_info(sys_info_t *sysInfo) sysInfo->freqProcessor = e600_ratio + sysInfo->freqSystemBus; break; } + +#if defined(CONFIG_SYS_LBC_LCRR) + /* We will program LCRR to this value later */ + lcrr_div = CONFIG_SYS_LBC_LCRR & LCRR_CLKDIV; +#else + { + volatile ccsr_lbc_t *lbc = &immap->im_lbc; + lcrr_div = in_be32(&lbc->lcrr) & LCRR_CLKDIV; + } +#endif + if (lcrr_div == 2 || lcrr_div == 4 || lcrr_div == 8) { + sysInfo->freqLocalBus = sysInfo->freqSystemBus / (lcrr_div * 2); + } else { + /* In case anyone cares what the unknown value is */ + sysInfo->freqLocalBus = lcrr_div; + } } @@ -105,6 +123,7 @@ int get_clocks(void) get_sys_info(&sys_info); gd->cpu_clk = sys_info.freqProcessor; gd->bus_clk = sys_info.freqSystemBus; + gd->lbc_clk = sys_info.freqLocalBus; /* * The base clock for I2C depends on the actual SOC. Unfortunately, diff --git a/cpu/mpc8xx/bedbug_860.c b/cpu/mpc8xx/bedbug_860.c index 5d52366..0308bbb 100644 --- a/cpu/mpc8xx/bedbug_860.c +++ b/cpu/mpc8xx/bedbug_860.c @@ -71,7 +71,7 @@ void bedbug860_do_break (cmd_tbl_t *cmdtp, int flag, int argc, if (argc < 2) { - printf ("Usage:\n%s\n", cmdtp->usage); + cmd_usage(cmdtp); return; } @@ -122,7 +122,7 @@ void bedbug860_do_break (cmd_tbl_t *cmdtp, int flag, int argc, if( !isdigit( argv[ 1 ][ 0 ])) { - printf ("Usage:\n%s\n", cmdtp->usage); + cmd_usage(cmdtp); return; } diff --git a/cpu/mpc8xx/serial.c b/cpu/mpc8xx/serial.c index bd90dcd..664db65 100644 --- a/cpu/mpc8xx/serial.c +++ b/cpu/mpc8xx/serial.c @@ -65,6 +65,23 @@ DECLARE_GLOBAL_DATA_PTR; #endif /* CONFIG_8xx_CONS_SCCx */ +#if !defined(CONFIG_SYS_SMC_RXBUFLEN) +#define CONFIG_SYS_SMC_RXBUFLEN 1 +#define CONFIG_SYS_MAXIDLE 0 +#else +#if !defined(CONFIG_SYS_MAXIDLE) +#error "you must define CONFIG_SYS_MAXIDLE" +#endif +#endif + +typedef volatile struct serialbuffer { + cbd_t rxbd; /* Rx BD */ + cbd_t txbd; /* Tx BD */ + uint rxindex; /* index for next character to read */ + volatile uchar rxbuf[CONFIG_SYS_SMC_RXBUFLEN];/* rx buffers */ + volatile uchar txbuf; /* tx buffers */ +} serialbuffer_t; + static void serial_setdivisor(volatile cpm8xx_t *cp) { int divisor=(gd->cpu_clk + 8*gd->baudrate)/16/gd->baudrate; @@ -113,12 +130,12 @@ static int smc_init (void) volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR; volatile smc_t *sp; volatile smc_uart_t *up; - volatile cbd_t *tbdf, *rbdf; volatile cpm8xx_t *cp = &(im->im_cpm); #if (!defined(CONFIG_8xx_CONS_SMC1)) && (defined(CONFIG_MPC823) || defined(CONFIG_MPC850)) volatile iop8xx_t *ip = (iop8xx_t *)&(im->im_ioport); #endif uint dpaddr; + volatile serialbuffer_t *rtx; /* initialize pointers to SMC */ @@ -131,12 +148,10 @@ static int smc_init (void) up->smc_rpbase = 0; #endif - /* Disable transmitter/receiver. - */ + /* Disable transmitter/receiver. */ sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); - /* Enable SDMA. - */ + /* Enable SDMA. */ im->im_siu_conf.sc_sdcr = 1; /* clear error conditions */ @@ -154,21 +169,19 @@ static int smc_init (void) #endif #if defined(CONFIG_8xx_CONS_SMC1) - /* Use Port B for SMC1 instead of other functions. - */ + /* Use Port B for SMC1 instead of other functions. */ cp->cp_pbpar |= 0x000000c0; cp->cp_pbdir &= ~0x000000c0; cp->cp_pbodr &= ~0x000000c0; #else /* CONFIG_8xx_CONS_SMC2 */ # if defined(CONFIG_MPC823) || defined(CONFIG_MPC850) - /* Use Port A for SMC2 instead of other functions. - */ + /* Use Port A for SMC2 instead of other functions. */ ip->iop_papar |= 0x00c0; ip->iop_padir &= ~0x00c0; ip->iop_paodr &= ~0x00c0; # else /* must be a 860 then */ /* Use Port B for SMC2 instead of other functions. - */ + */ cp->cp_pbpar |= 0x00000c00; cp->cp_pbdir &= ~0x00000c00; cp->cp_pbodr &= ~0x00000c00; @@ -194,26 +207,28 @@ static int smc_init (void) */ #ifdef CONFIG_SYS_ALLOC_DPRAM - dpaddr = dpram_alloc_align (sizeof(cbd_t)*2 + 2, 8) ; + /* allocate + * size of struct serialbuffer with bd rx/tx, buffer rx/tx and rx index + */ + dpaddr = dpram_alloc_align((sizeof(serialbuffer_t)), 8); #else dpaddr = CPM_SERIAL_BASE ; #endif + rtx = (serialbuffer_t *)&cp->cp_dpmem[dpaddr]; /* Allocate space for two buffer descriptors in the DP ram. * For now, this address seems OK, but it may have to * change with newer versions of the firmware. * damm: allocating space after the two buffers for rx/tx data */ - rbdf = (cbd_t *)&cp->cp_dpmem[dpaddr]; - rbdf->cbd_bufaddr = (uint) (rbdf+2); - rbdf->cbd_sc = 0; - tbdf = rbdf + 1; - tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1; - tbdf->cbd_sc = 0; + rtx->rxbd.cbd_bufaddr = (uint) &rtx->rxbuf; + rtx->rxbd.cbd_sc = 0; - /* Set up the uart parameters in the parameter ram. - */ + rtx->txbd.cbd_bufaddr = (uint) &rtx->txbuf; + rtx->txbd.cbd_sc = 0; + + /* Set up the uart parameters in the parameter ram. */ up->smc_rbase = dpaddr; up->smc_tbase = dpaddr+sizeof(cbd_t); up->smc_rfcr = SMC_EB; @@ -254,19 +269,16 @@ static int smc_init (void) smc_setbrg (); #endif - /* Make the first buffer the only buffer. - */ - tbdf->cbd_sc |= BD_SC_WRAP; - rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP; + /* Make the first buffer the only buffer. */ + rtx->txbd.cbd_sc |= BD_SC_WRAP; + rtx->rxbd.cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP; - /* Single character receive. - */ - up->smc_mrblr = 1; - up->smc_maxidl = 0; - - /* Initialize Tx/Rx parameters. - */ + /* single/multi character receive. */ + up->smc_mrblr = CONFIG_SYS_SMC_RXBUFLEN; + up->smc_maxidl = CONFIG_SYS_MAXIDLE; + rtx->rxindex = 0; + /* Initialize Tx/Rx parameters. */ while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */ ; @@ -275,8 +287,7 @@ static int smc_init (void) while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */ ; - /* Enable transmitter/receiver. - */ + /* Enable transmitter/receiver. */ sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN; return (0); @@ -285,11 +296,10 @@ static int smc_init (void) static void smc_putc(const char c) { - volatile cbd_t *tbdf; - volatile char *buf; volatile smc_uart_t *up; volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR; volatile cpm8xx_t *cpmp = &(im->im_cpm); + volatile serialbuffer_t *rtx; #ifdef CONFIG_MODEM_SUPPORT if (gd->be_quiet) @@ -304,19 +314,15 @@ smc_putc(const char c) up = (smc_uart_t *) &cpmp->cp_dpmem[up->smc_rpbase]; #endif - tbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_tbase]; - - /* Wait for last character to go. - */ - - buf = (char *)tbdf->cbd_bufaddr; + rtx = (serialbuffer_t *)&cpmp->cp_dpmem[up->smc_rbase]; - *buf = c; - tbdf->cbd_datlen = 1; - tbdf->cbd_sc |= BD_SC_READY; + /* Wait for last character to go. */ + rtx->txbuf = c; + rtx->txbd.cbd_datlen = 1; + rtx->txbd.cbd_sc |= BD_SC_READY; __asm__("eieio"); - while (tbdf->cbd_sc & BD_SC_READY) { + while (rtx->txbd.cbd_sc & BD_SC_READY) { WATCHDOG_RESET (); __asm__("eieio"); } @@ -333,49 +339,52 @@ smc_puts (const char *s) static int smc_getc(void) { - volatile cbd_t *rbdf; - volatile unsigned char *buf; volatile smc_uart_t *up; volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR; volatile cpm8xx_t *cpmp = &(im->im_cpm); - unsigned char c; + volatile serialbuffer_t *rtx; + unsigned char c; up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC]; #ifdef CONFIG_SYS_SMC_UCODE_PATCH up = (smc_uart_t *) &cpmp->cp_dpmem[up->smc_rpbase]; #endif + rtx = (serialbuffer_t *)&cpmp->cp_dpmem[up->smc_rbase]; - rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase]; - - /* Wait for character to show up. - */ - buf = (unsigned char *)rbdf->cbd_bufaddr; - - while (rbdf->cbd_sc & BD_SC_EMPTY) + /* Wait for character to show up. */ + while (rtx->rxbd.cbd_sc & BD_SC_EMPTY) WATCHDOG_RESET (); - c = *buf; - rbdf->cbd_sc |= BD_SC_EMPTY; + /* the characters are read one by one, + * use the rxindex to know the next char to deliver + */ + c = *(unsigned char *) (rtx->rxbd.cbd_bufaddr+rtx->rxindex); + rtx->rxindex++; + /* check if all char are readout, then make prepare for next receive */ + if (rtx->rxindex >= rtx->rxbd.cbd_datlen) { + rtx->rxindex = 0; + rtx->rxbd.cbd_sc |= BD_SC_EMPTY; + } return(c); } static int smc_tstc(void) { - volatile cbd_t *rbdf; volatile smc_uart_t *up; volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR; volatile cpm8xx_t *cpmp = &(im->im_cpm); + volatile serialbuffer_t *rtx; up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC]; #ifdef CONFIG_SYS_SMC_UCODE_PATCH up = (smc_uart_t *) &cpmp->cp_dpmem[up->smc_rpbase]; #endif - rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase]; + rtx = (serialbuffer_t *)&cpmp->cp_dpmem[up->smc_rbase]; - return(!(rbdf->cbd_sc & BD_SC_EMPTY)); + return !(rtx->rxbd.cbd_sc & BD_SC_EMPTY); } struct serial_device serial_smc_device = @@ -445,8 +454,7 @@ static int scc_init (void) } #endif /* CONFIG_LWMON */ - /* Disable transmitter/receiver. - */ + /* Disable transmitter/receiver. */ sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); #if (SCC_INDEX == 2) && defined(CONFIG_MPC850) @@ -471,8 +479,7 @@ static int scc_init (void) ip->iop_pdpar |= ((3 << (2 * SCC_INDEX))); #endif - /* Allocate space for two buffer descriptors in the DP ram. - */ + /* Allocate space for two buffer descriptors in the DP ram. */ #ifdef CONFIG_SYS_ALLOC_DPRAM dpaddr = dpram_alloc_align (sizeof(cbd_t)*2 + 2, 8) ; @@ -480,8 +487,7 @@ static int scc_init (void) dpaddr = CPM_SERIAL2_BASE ; #endif - /* Enable SDMA. - */ + /* Enable SDMA. */ im->im_siu_conf.sc_sdcr = 0x0001; /* Set the physical address of the host memory buffers in @@ -495,17 +501,14 @@ static int scc_init (void) tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1; tbdf->cbd_sc = 0; - /* Set up the baud rate generator. - */ + /* Set up the baud rate generator. */ scc_setbrg (); - /* Set up the uart parameters in the parameter ram. - */ + /* Set up the uart parameters in the parameter ram. */ up->scc_genscc.scc_rbase = dpaddr; up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t); - /* Initialize Tx/Rx parameters. - */ + /* Initialize Tx/Rx parameters. */ while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */ ; cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SCC, CPM_CR_INIT_TRX) | CPM_CR_FLG; @@ -536,8 +539,7 @@ static int scc_init (void) up->scc_char8 = 0x8000; up->scc_rccm = 0xc0ff; - /* Set low latency / small fifo. - */ + /* Set low latency / small fifo. */ sp->scc_gsmrh = SCC_GSMRH_RFW; /* Set SCC(x) clock mode to 16x @@ -546,8 +548,7 @@ static int scc_init (void) * Wire BRG1 to SCCn */ - /* Set UART mode, clock divider 16 on Tx and Rx - */ + /* Set UART mode, clock divider 16 on Tx and Rx */ sp->scc_gsmrl &= ~0xF; sp->scc_gsmrl |= (SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16); @@ -555,20 +556,17 @@ static int scc_init (void) sp->scc_psmr = 0; sp->scc_psmr |= SCU_PSMR_CL; - /* Mask all interrupts and remove anything pending. - */ + /* Mask all interrupts and remove anything pending. */ sp->scc_sccm = 0; sp->scc_scce = 0xffff; sp->scc_dsr = 0x7e7e; sp->scc_psmr = 0x3000; - /* Make the first buffer the only buffer. - */ + /* Make the first buffer the only buffer. */ tbdf->cbd_sc |= BD_SC_WRAP; rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP; - /* Enable transmitter/receiver. - */ + /* Enable transmitter/receiver. */ sp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT); return (0); @@ -595,8 +593,7 @@ scc_putc(const char c) tbdf = (cbd_t *)&cpmp->cp_dpmem[up->scc_genscc.scc_tbase]; - /* Wait for last character to go. - */ + /* Wait for last character to go. */ buf = (char *)tbdf->cbd_bufaddr; @@ -633,8 +630,7 @@ scc_getc(void) rbdf = (cbd_t *)&cpmp->cp_dpmem[up->scc_genscc.scc_rbase]; - /* Wait for character to show up. - */ + /* Wait for character to show up. */ buf = (unsigned char *)rbdf->cbd_bufaddr; while (rbdf->cbd_sc & BD_SC_EMPTY) diff --git a/cpu/mpc8xxx/ddr/ctrl_regs.c b/cpu/mpc8xxx/ddr/ctrl_regs.c index 1783e92..292980d 100644 --- a/cpu/mpc8xxx/ddr/ctrl_regs.c +++ b/cpu/mpc8xxx/ddr/ctrl_regs.c @@ -167,7 +167,7 @@ static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr) | ((trrt_mclk & 0x3) << 26) /* RRT */ | ((twwt_mclk & 0x3) << 24) /* WWT */ | ((act_pd_exit_mclk & 0x7) << 20) /* ACT_PD_EXIT */ - | ((pre_pd_exit_mclk & 0x7) << 16) /* PRE_PD_EXIT */ + | ((pre_pd_exit_mclk & 0xF) << 16) /* PRE_PD_EXIT */ | ((taxpd_mclk & 0xf) << 8) /* ODT_PD_EXIT */ | ((tmrd_mclk & 0xf) << 0) /* MRS_CYC */ ); @@ -185,10 +185,14 @@ static void set_timing_cfg_3(fsl_ddr_cfg_regs_t *ddr, unsigned int ext_caslat = 0; /* Extended MCAS latency from READ cmd */ unsigned int cntl_adj = 0; /* Control Adjust */ + /* If the tRAS > 19 MCLK, we use the ext mode */ + if (picos_to_mclk(common_dimm->tRAS_ps) > 0x13) + ext_acttopre = 1; + ext_refrec = (picos_to_mclk(common_dimm->tRFC_ps) - 8) >> 4; ddr->timing_cfg_3 = (0 | ((ext_acttopre & 0x1) << 24) - | ((ext_refrec & 0x7) << 16) + | ((ext_refrec & 0xF) << 16) | ((ext_caslat & 0x1) << 12) | ((cntl_adj & 0x7) << 0) ); @@ -251,12 +255,12 @@ static void set_timing_cfg_1(fsl_ddr_cfg_regs_t *ddr, wrtord_mclk = picos_to_mclk(common_dimm->tWTR_ps); ddr->timing_cfg_1 = (0 - | ((pretoact_mclk & 0x07) << 28) + | ((pretoact_mclk & 0x0F) << 28) | ((acttopre_mclk & 0x0F) << 24) - | ((acttorw_mclk & 0x7) << 20) + | ((acttorw_mclk & 0xF) << 20) | ((caslat_ctrl & 0xF) << 16) | ((refrec_ctrl & 0xF) << 12) - | ((wrrec_mclk & 0x07) << 8) + | ((wrrec_mclk & 0x0F) << 8) | ((acttoact_mclk & 0x07) << 4) | ((wrtord_mclk & 0x07) << 0) ); @@ -309,13 +313,13 @@ static void set_timing_cfg_2(fsl_ddr_cfg_regs_t *ddr, four_act = picos_to_mclk(popts->tFAW_window_four_activates_ps); ddr->timing_cfg_2 = (0 - | ((add_lat_mclk & 0x7) << 28) + | ((add_lat_mclk & 0xf) << 28) | ((cpo & 0x1f) << 23) - | ((wr_lat & 0x7) << 19) + | ((wr_lat & 0xf) << 19) | ((rd_to_pre & 0x7) << 13) | ((wr_data_delay & 0x7) << 10) | ((cke_pls & 0x7) << 6) - | ((four_act & 0x1f) << 0) + | ((four_act & 0x3f) << 0) ); debug("FSLDDR: timing_cfg_2 = 0x%08x\n", ddr->timing_cfg_2); } @@ -332,7 +336,7 @@ static void set_ddr_sdram_cfg(fsl_ddr_cfg_regs_t *ddr, unsigned int sdram_type; /* Type of SDRAM */ unsigned int dyn_pwr; /* Dynamic power management mode */ unsigned int dbw; /* DRAM dta bus width */ - unsigned int eight_be; /* 8-beat burst enable */ + unsigned int eight_be = 0; /* 8-beat burst enable, DDR2 is zero */ unsigned int ncap = 0; /* Non-concurrent auto-precharge */ unsigned int threeT_en; /* Enable 3T timing */ unsigned int twoT_en; /* Enable 2T timing */ @@ -359,7 +363,9 @@ static void set_ddr_sdram_cfg(fsl_ddr_cfg_regs_t *ddr, dyn_pwr = popts->dynamic_power; dbw = popts->data_bus_width; - eight_be = 0; /* always 0 for DDR2 */ + /* DDR3 must use 8-beat bursts when using 32-bit bus mode */ + if ((sdram_type == SDRAM_TYPE_DDR3) && (dbw == 0x1)) + eight_be = 1; threeT_en = popts->threeT_en; twoT_en = popts->twoT_en; ba_intlv_ctl = popts->ba_intlv_ctl; @@ -691,10 +697,10 @@ static void set_timing_cfg_5(fsl_ddr_cfg_regs_t *ddr) unsigned int wodt_off = 0; /* Write to ODT off */ ddr->timing_cfg_5 = (0 - | ((rodt_on & 0xf) << 24) - | ((rodt_off & 0xf) << 20) - | ((wodt_on & 0xf) << 12) - | ((wodt_off & 0xf) << 8) + | ((rodt_on & 0x1f) << 24) + | ((rodt_off & 0x7) << 20) + | ((wodt_on & 0x1f) << 12) + | ((wodt_off & 0x7) << 8) ); debug("FSLDDR: timing_cfg_5 = 0x%08x\n", ddr->timing_cfg_5); } @@ -744,15 +750,14 @@ static void set_ddr_wrlvl_cntl(fsl_ddr_cfg_regs_t *ddr) | ((wrlvl_dqsen & 0x7) << 16) | ((wrlvl_smpl & 0xf) << 12) | ((wrlvl_wlr & 0x7) << 8) - | ((wrlvl_start & 0xF) << 0) + | ((wrlvl_start & 0x1F) << 0) ); } /* DDR Self Refresh Counter (DDR_SR_CNTR) */ -static void set_ddr_sr_cntr(fsl_ddr_cfg_regs_t *ddr) +static void set_ddr_sr_cntr(fsl_ddr_cfg_regs_t *ddr, unsigned int sr_it) { - unsigned int sr_it = 0; /* Self Refresh Idle Threshold */ - + /* Self Refresh Idle Threshold */ ddr->ddr_sr_cntr = (sr_it & 0xF) << 16; } @@ -855,6 +860,7 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts, unsigned int i; unsigned int cas_latency; unsigned int additive_latency; + unsigned int sr_it; memset(ddr, 0, sizeof(fsl_ddr_cfg_regs_t)); @@ -876,6 +882,10 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts, ? popts->additive_latency_override_value : common_dimm->additive_latency; + sr_it = (popts->auto_self_refresh_en) + ? popts->sr_it + : 0; + /* Chip Select Memory Bounds (CSn_BNDS) */ for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { phys_size_t sa = 0; @@ -1036,7 +1046,7 @@ compute_fsl_memctl_config_regs(const memctl_options_t *popts, set_ddr_wrlvl_cntl(ddr); set_ddr_pd_cntl(ddr); - set_ddr_sr_cntr(ddr); + set_ddr_sr_cntr(ddr, sr_it); set_ddr_sdram_rcw_1(ddr); set_ddr_sdram_rcw_2(ddr); diff --git a/cpu/mpc8xxx/ddr/main.c b/cpu/mpc8xxx/ddr/main.c index f1ad132..305f7fb 100644 --- a/cpu/mpc8xxx/ddr/main.c +++ b/cpu/mpc8xxx/ddr/main.c @@ -429,7 +429,7 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step) if (max_end >= 0xff) { printf("This U-Boot only supports < 4G of DDR\n"); printf("You could rebuild it with CONFIG_PHYS_64BIT\n"); - return 0; /* Ensure DDR setup failure. */ + return CONFIG_MAX_MEM_MAPPED; } #endif diff --git a/cpu/mpc8xxx/ddr/options.c b/cpu/mpc8xxx/ddr/options.c index af7f73a..29d4143 100644 --- a/cpu/mpc8xxx/ddr/options.c +++ b/cpu/mpc8xxx/ddr/options.c @@ -22,7 +22,9 @@ unsigned int populate_memctl_options(int all_DIMMs_registered, unsigned int ctrl_num) { unsigned int i; +#if (CONFIG_NUM_DDR_CONTROLLERS > 1) const char *p; +#endif /* Chip select options. */ @@ -142,7 +144,7 @@ unsigned int populate_memctl_options(int all_DIMMs_registered, * - number of components, number of active ranks * - how much time you want to spend playing around */ - popts->twoT_en = 1; + popts->twoT_en = 0; popts->threeT_en = 0; /* @@ -195,6 +197,7 @@ unsigned int populate_memctl_options(int all_DIMMs_registered, * requested ranks interleaved together such that the result * should be a subset of the requested configuration. */ +#if (CONFIG_NUM_DDR_CONTROLLERS > 1) if ((p = getenv("memctl_intlv_ctl")) != NULL) { if (pdimm[0].n_ranks == 0) { printf("There is no rank on CS0. Because only rank on " @@ -262,6 +265,7 @@ unsigned int populate_memctl_options(int all_DIMMs_registered, break; } } +#endif fsl_ddr_board_options(popts, pdimm, ctrl_num); diff --git a/cpu/nios2/sysid.c b/cpu/nios2/sysid.c index afd5d83..251204b 100644 --- a/cpu/nios2/sysid.c +++ b/cpu/nios2/sysid.c @@ -52,7 +52,7 @@ int do_sysid (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) U_BOOT_CMD( sysid, 1, 1, do_sysid, - "sysid - display Nios-II system id\n\n", + "display Nios-II system id", "\n - display Nios-II system id\n" ); #endif /* CONFIG_SYS_NIOS_SYSID_BASE */ diff --git a/cpu/ppc4xx/44x_spd_ddr2.c b/cpu/ppc4xx/44x_spd_ddr2.c index b40e4b1..33788cc 100644 --- a/cpu/ppc4xx/44x_spd_ddr2.c +++ b/cpu/ppc4xx/44x_spd_ddr2.c @@ -160,9 +160,6 @@ * SDRAM. This is because we only map the first 2GB on such systems, and therefore * the ECC parity byte of the remaining area can't be written. */ -#ifndef CONFIG_MAX_MEM_MAPPED -#define CONFIG_MAX_MEM_MAPPED ((phys_size_t)2 << 30) -#endif /* * Board-specific Platform code can reimplement spd_ddr_init_hang () if needed @@ -1104,11 +1101,8 @@ static void program_codt(unsigned long *dimm_populated, * Set the SDRAM Controller On Die Termination Register *-----------------------------------------------------------------*/ mfsdram(SDRAM_CODT, codt); - codt |= (SDRAM_CODT_IO_NMODE - & (~SDRAM_CODT_DQS_SINGLE_END - & ~SDRAM_CODT_CKSE_SINGLE_END - & ~SDRAM_CODT_FEEBBACK_RCV_SINGLE_END - & ~SDRAM_CODT_FEEBBACK_DRV_SINGLE_END)); + codt &= ~(SDRAM_CODT_DQS_SINGLE_END | SDRAM_CODT_CKSE_SINGLE_END); + codt |= SDRAM_CODT_IO_NMODE; for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { if (dimm_populated[dimm_num] != SDRAM_NONE) { diff --git a/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c b/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c index 1e3e20d..91bf582 100644 --- a/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c +++ b/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c @@ -61,6 +61,8 @@ #define NUMLOOPS 1 /* configure as you deem approporiate */ #define NUMMEMWORDS 16 +#define SDRAM_RDCC_RDSS_VAL(n) SDRAM_RDCC_RDSS_DECODE(ddr_rdss_opt(n)) + /* Private Structure Definitions */ struct autocal_regs { @@ -147,6 +149,13 @@ ulong __ddr_scan_option(ulong default_val) } ulong ddr_scan_option(ulong) __attribute__((weak, alias("__ddr_scan_option"))); +u32 __ddr_rdss_opt(u32 default_val) +{ + return default_val; +} +u32 ddr_rdss_opt(ulong) __attribute__((weak, alias("__ddr_rdss_opt"))); + + static u32 *get_membase(int bxcr_num) { ulong bxcf; @@ -341,6 +350,7 @@ static int short_mem_test(u32 *base_address) ppcDcbf((ulong)&(base_address[j])); } sync(); + iobarrier_rw(); for (l = 0; l < NUMLOOPS; l++) { for (j = 0; j < NUMMEMWORDS; j++) { if (base_address[j] != test[i][j]) { @@ -355,6 +365,7 @@ static int short_mem_test(u32 *base_address) ppcDcbf((u32)&(base_address[j])); } /* for (j = 0; j < NUMMEMWORDS; j++) */ sync(); + iobarrier_rw(); } /* for (l=0; l<NUMLOOPS; l++) */ } @@ -447,7 +458,8 @@ static u32 DQS_calibration_methodA(struct ddrautocal *cal) * Program RDCC register * Read sample cycle auto-update enable */ - mtsdram(SDRAM_RDCC, SDRAM_RDCC_RDSS_T1 | SDRAM_RDCC_RSAE_ENABLE); + mtsdram(SDRAM_RDCC, + ddr_rdss_opt(SDRAM_RDCC_RDSS_T2) | SDRAM_RDCC_RSAE_ENABLE); #ifdef DEBUG mfsdram(SDRAM_RDCC, temp); @@ -633,7 +645,8 @@ static u32 program_DQS_calibration_methodB(struct ddrautocal *ddrcal) * Program RDCC register * Read sample cycle auto-update enable */ - mtsdram(SDRAM_RDCC, SDRAM_RDCC_RDSS_T2 | SDRAM_RDCC_RSAE_ENABLE); + mtsdram(SDRAM_RDCC, + ddr_rdss_opt(SDRAM_RDCC_RDSS_T2) | SDRAM_RDCC_RSAE_ENABLE); #ifdef DEBUG mfsdram(SDRAM_RDCC, temp); @@ -1091,32 +1104,36 @@ u32 DQS_autocalibration(void) * if no passing window was found, or is the * size of the RFFD passing window. */ - if (result != 0) { - tcal.autocal.flags = 1; - debug("*** (%d)(%d) result passed window size: 0x%08x, " - "rqfd = 0x%08x, rffd = 0x%08x, rdcc = 0x%08x\n", - wdtr, clkp, result, ddrcal.rqfd, - ddrcal.rffd, ddrcal.rdcc); - /* - * Save the SDRAM_WRDTR and SDRAM_CLKTR - * settings for the largest returned - * RFFD passing window size. - */ - if (result > best_result) { + /* + * want the lowest Read Sample Cycle Select + */ + val = SDRAM_RDCC_RDSS_DECODE(val); + debug("*** (%d) (%d) current_rdcc, best_rdcc\n", + val, best_rdcc); + + if ((result != 0) && + (val >= SDRAM_RDCC_RDSS_VAL(SDRAM_RDCC_RDSS_T2))) { + if (((result == best_result) && (val < best_rdcc)) || + ((result > best_result) && (val <= best_rdcc))) { + tcal.autocal.flags = 1; + debug("*** (%d)(%d) result passed window " + "size: 0x%08x, rqfd = 0x%08x, " + "rffd = 0x%08x, rdcc = 0x%08x\n", + wdtr, clkp, result, ddrcal.rqfd, + ddrcal.rffd, ddrcal.rdcc); + /* - * want the lowest Read Sample Cycle Select + * Save the SDRAM_WRDTR and SDRAM_CLKTR + * settings for the largest returned + * RFFD passing window size. */ - val = (val & SDRAM_RDCC_RDSS_MASK) >> 30; - debug("*** (%d) (%d) current_rdcc, best_rdcc\n", - val, best_rdcc); - if (val <= best_rdcc) { - best_rdcc = val; - tcal.clocks.wrdtr = wdtr; - tcal.clocks.clktr = clkp; - tcal.clocks.rdcc = (val << 30); - tcal.autocal.rqfd = ddrcal.rqfd; - tcal.autocal.rffd = ddrcal.rffd; - best_result = result; + best_rdcc = val; + tcal.clocks.wrdtr = wdtr; + tcal.clocks.clktr = clkp; + tcal.clocks.rdcc = SDRAM_RDCC_RDSS_ENCODE(val); + tcal.autocal.rqfd = ddrcal.rqfd; + tcal.autocal.rffd = ddrcal.rffd; + best_result = result; if (verbose_lvl > 2) { printf("** (%d)(%d) " @@ -1152,9 +1169,8 @@ u32 DQS_autocalibration(void) "loop FCSR: 0x%08x\n", wdtr, clkp, val); } - } /* if (val <= best_rdcc) */ - } /* if (result >= best_result) */ - } /* if (result != 0) */ + } + } /* if ((result != 0) && (val >= (ddr_rdss_opt()))) */ scan_list++; } /* while ((scan_list->wrdtr != -1) && (scan_list->clktr != -1)) */ diff --git a/cpu/ppc4xx/4xx_pci.c b/cpu/ppc4xx/4xx_pci.c index e8871fc..6fd36de 100644 --- a/cpu/ppc4xx/4xx_pci.c +++ b/cpu/ppc4xx/4xx_pci.c @@ -179,7 +179,7 @@ void pci_405gp_init(struct pci_controller *hose) ptmpcila[i], ptmla[i], ~(ptmms[i] & 0xfffff000) + 1, PCI_REGION_MEM | - PCI_REGION_MEMORY); + PCI_REGION_SYS_MEMORY); } /* PCI memory spaces */ @@ -504,7 +504,7 @@ int pci_440_init (struct pci_controller *hose) CONFIG_PCI_SYS_MEM_BUS, CONFIG_PCI_SYS_MEM_PHYS, CONFIG_PCI_SYS_MEM_SIZE, - PCI_REGION_MEM | PCI_REGION_MEMORY ); + PCI_REGION_MEM | PCI_REGION_SYS_MEMORY ); #endif hose->region_count = reg_num; @@ -588,8 +588,9 @@ void pci_init_board(void) int busno; busno = pci_440_init (&ppc440_hose); -#if defined(CONFIG_440SPE) || \ - defined(CONFIG_460EX) || defined(CONFIG_460GT) +#if (defined(CONFIG_440SPE) || \ + defined(CONFIG_460EX) || defined(CONFIG_460GT)) && \ + !defined(CONFIG_PCI_DISABLE_PCIE) pcie_setup_hoses(busno + 1); #endif } diff --git a/cpu/ppc4xx/4xx_pcie.c b/cpu/ppc4xx/4xx_pcie.c index fd40d8a..07fbb0e 100644 --- a/cpu/ppc4xx/4xx_pcie.c +++ b/cpu/ppc4xx/4xx_pcie.c @@ -33,7 +33,7 @@ #if (defined(CONFIG_440SPE) || defined(CONFIG_405EX) || \ defined(CONFIG_460EX) || defined(CONFIG_460GT)) && \ - defined(CONFIG_PCI) + defined(CONFIG_PCI) && !defined(CONFIG_PCI_DISABLE_PCIE) #include <asm/4xx_pcie.h> @@ -1028,10 +1028,10 @@ void ppc4xx_setup_pcie_rootpoint(struct pci_controller *hose, int port) #endif } - /* Set up 16GB inbound memory window at 0 */ + /* Set up 4GB inbound memory window at 0 */ out_le32(mbase + PCI_BASE_ADDRESS_0, 0); out_le32(mbase + PCI_BASE_ADDRESS_1, 0); - out_le32(mbase + PECFG_BAR0HMPA, 0x7fffffc); + out_le32(mbase + PECFG_BAR0HMPA, 0x7ffffff); out_le32(mbase + PECFG_BAR0LMPA, 0); out_le32(mbase + PECFG_PIM01SAH, 0xffff0000); diff --git a/cpu/ppc4xx/bedbug_405.c b/cpu/ppc4xx/bedbug_405.c index 5ef5607..ef11cb6 100644 --- a/cpu/ppc4xx/bedbug_405.c +++ b/cpu/ppc4xx/bedbug_405.c @@ -71,7 +71,7 @@ void bedbug405_do_break (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) /* -------------------------------------------------- */ if (argc < 2) { - printf ("Usage:\n%s\n", cmdtp->usage); + cmd_usage(cmdtp); return; } @@ -125,7 +125,7 @@ void bedbug405_do_break (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) /* Set a breakpoint at the address */ if (!isdigit (argv[1][0])) { - printf ("Usage:\n%s\n", cmdtp->usage); + cmd_usage(cmdtp); return; } diff --git a/cpu/ppc4xx/fdt.c b/cpu/ppc4xx/fdt.c index c55e1cf..ba5c120 100644 --- a/cpu/ppc4xx/fdt.c +++ b/cpu/ppc4xx/fdt.c @@ -113,6 +113,7 @@ void fdt_pcie_setup(void *blob) void ft_cpu_setup(void *blob, bd_t *bd) { sys_info_t sys_info; + int off, ndepth = 0; get_sys_info(&sys_info); @@ -133,9 +134,28 @@ void ft_cpu_setup(void *blob, bd_t *bd) fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize); /* - * Setup all baudrates for the UARTs + * Fixup all UART clocks for CPU internal UARTs + * (only these UARTs are definitely clocked by gd->uart_clk) + * + * These UARTs are direct childs of /plb/opb. This code + * does not touch any UARTs that are connected to the ebc. */ - do_fixup_by_compat_u32(blob, "ns16550", "clock-frequency", gd->uart_clk, 1); + off = fdt_path_offset(blob, "/plb/opb"); + while ((off = fdt_next_node(blob, off, &ndepth)) >= 0) { + /* + * process all sub nodes and stop when we are back + * at the starting depth + */ + if (ndepth <= 0) + break; + + /* only update direct childs */ + if ((ndepth == 1) && + (fdt_node_check_compatible(blob, off, "ns16550") == 0)) + fdt_setprop(blob, off, + "clock-frequency", + (void*)&(gd->uart_clk), 4); + } /* * Fixup all ethernet nodes diff --git a/cpu/ppc4xx/sdram.c b/cpu/ppc4xx/sdram.c index 6d5f8d6..4365df9 100644 --- a/cpu/ppc4xx/sdram.c +++ b/cpu/ppc4xx/sdram.c @@ -259,6 +259,7 @@ phys_size_t initdram(int board_type) #ifndef CONFIG_SYS_SDRAM_TABLE sdram_conf_t mb0cf[] = { {(256 << 20), 13, 0x000C4001}, /* 256MB mode 3, 13x10(4) */ + {(128 << 20), 13, 0x000A4001}, /* 128MB mode 3, 13x10(4) */ {(64 << 20), 12, 0x00082001} /* 64MB mode 2, 12x9(4) */ }; #else @@ -269,6 +270,18 @@ sdram_conf_t mb0cf[] = CONFIG_SYS_SDRAM_TABLE; #define CONFIG_SYS_SDRAM0_TR0 0x41094012 #endif +#ifndef CONFIG_SYS_SDRAM0_WDDCTR +#define CONFIG_SYS_SDRAM0_WDDCTR 0x00000000 /* wrcp=0 dcd=0 */ +#endif + +#ifndef CONFIG_SYS_SDRAM0_RTR +#define CONFIG_SYS_SDRAM0_RTR 0x04100000 /* 7.8us @ 133MHz PLB */ +#endif + +#ifndef CONFIG_SYS_SDRAM0_CFG0 +#define CONFIG_SYS_SDRAM0_CFG0 0x82000000 /* DCEN=1, PMUD=0, 64-bit */ +#endif + #define N_MB0CF (sizeof(mb0cf) / sizeof(mb0cf[0])) #define NUM_TRIES 64 @@ -378,7 +391,7 @@ phys_size_t initdram(int board_type) mtsdram(mem_uabba, 0x00000000); /* ubba=0 (default) */ mtsdram(mem_slio, 0x00000000); /* rdre=0 wrre=0 rarw=0 */ mtsdram(mem_devopt, 0x00000000); /* dll=0 ds=0 (normal) */ - mtsdram(mem_wddctr, 0x00000000); /* wrcp=0 dcd=0 */ + mtsdram(mem_wddctr, CONFIG_SYS_SDRAM0_WDDCTR); mtsdram(mem_clktr, 0x40000000); /* clkp=1 (90 deg wr) dcdt=0 */ /* @@ -387,31 +400,63 @@ phys_size_t initdram(int board_type) mtsdram(mem_b0cr, mb0cf[i].reg); mtsdram(mem_tr0, CONFIG_SYS_SDRAM0_TR0); mtsdram(mem_tr1, 0x80800800); /* SS=T2 SL=STAGE 3 CD=1 CT=0x00*/ - mtsdram(mem_rtr, 0x04100000); /* Interval 7.8µs @ 133MHz PLB */ + mtsdram(mem_rtr, CONFIG_SYS_SDRAM0_RTR); mtsdram(mem_cfg1, 0x00000000); /* Self-refresh exit, disable PM*/ udelay(400); /* Delay 200 usecs (min) */ /* * Enable the controller, then wait for DCEN to complete */ - mtsdram(mem_cfg0, 0x82000000); /* DCEN=1, PMUD=0, 64-bit */ + mtsdram(mem_cfg0, CONFIG_SYS_SDRAM0_CFG0); udelay(10000); if (get_ram_size(0, mb0cf[i].size) == mb0cf[i].size) { + phys_size_t size = mb0cf[i].size; /* * Optimize TR1 to current hardware environment */ sdram_tr1_set(0x00000000, &tr1_bank1); mtsdram(mem_tr1, (tr1_bank1 | 0x80800800)); + + /* + * OK, size detected. Enable second bank if + * defined (assumes same type as bank 0) + */ +#ifdef CONFIG_SDRAM_BANK1 + mtsdram(mem_cfg0, 0); + mtsdram(mem_b1cr, mb0cf[i].size | mb0cf[i].reg); + mtsdram(mem_cfg0, CONFIG_SYS_SDRAM0_CFG0); + udelay(10000); + + /* + * Check if 2nd bank is really available. + * If the size not equal to the size of the first + * bank, then disable the 2nd bank completely. + */ + if (get_ram_size((long *)mb0cf[i].size, mb0cf[i].size) + != mb0cf[i].size) { + mtsdram(mem_cfg0, 0); + mtsdram(mem_b1cr, 0); + mtsdram(mem_cfg0, CONFIG_SYS_SDRAM0_CFG0); + udelay(10000); + } else { + /* + * We have two identical banks, so the size + * is twice the bank size + */ + size = 2 * size; + } +#endif + #ifdef CONFIG_SDRAM_ECC - ecc_init(0, mb0cf[i].size); + ecc_init(0, size); #endif /* * OK, size detected -> all done */ - return mb0cf[i].size; + return size; } } diff --git a/cpu/pxa/Makefile b/cpu/pxa/Makefile index 8b4367e..42903b2 100644 --- a/cpu/pxa/Makefile +++ b/cpu/pxa/Makefile @@ -26,7 +26,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(CPU).a START = start.o -COBJS = serial.o interrupts.o cpu.o i2c.o pxafb.o mmc.o usb.o +COBJS = serial.o interrupts.o cpu.o i2c.o pxafb.o usb.o SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/cpu/pxa/interrupts.c b/cpu/pxa/interrupts.c index ec8fb9e..40d8bf2 100644 --- a/cpu/pxa/interrupts.c +++ b/cpu/pxa/interrupts.c @@ -33,6 +33,14 @@ #error: interrupts not implemented yet #endif +#if defined(CONFIG_PXA27X) || defined(CONFIG_CPU_MONAHANS) +#define TIMER_FREQ_HZ 3250000 +#elif defined(CONFIG_PXA250) +#define TIMER_FREQ_HZ 3686400 +#else +#error "Timer frequency unknown - please config PXA CPU type" +#endif + int interrupt_init (void) { /* nothing happens here - we don't setup any IRQs */ @@ -67,7 +75,10 @@ void reset_timer_masked (void) ulong get_timer_masked (void) { - return OSCR; + unsigned long long ticks = get_ticks(); + + return (((ticks / TIMER_FREQ_HZ) * 1000) + + ((ticks % TIMER_FREQ_HZ) * 1000) / TIMER_FREQ_HZ); } void udelay_masked (unsigned long usec) @@ -78,17 +89,17 @@ void udelay_masked (unsigned long usec) if (usec >= 1000) { tmo = usec / 1000; - tmo *= CONFIG_SYS_HZ; + tmo *= TIMER_FREQ_HZ; tmo /= 1000; } else { - tmo = usec * CONFIG_SYS_HZ; + tmo = usec * TIMER_FREQ_HZ; tmo /= (1000*1000); } - endtime = get_timer_masked () + tmo; + endtime = get_ticks() + tmo; do { - ulong now = get_timer_masked (); + ulong now = get_ticks(); diff = endtime - now; } while (diff >= 0); } @@ -99,7 +110,7 @@ void udelay_masked (unsigned long usec) */ unsigned long long get_ticks(void) { - return get_timer(0); + return OSCR; } /* @@ -109,6 +120,6 @@ unsigned long long get_ticks(void) ulong get_tbclk (void) { ulong tbclk; - tbclk = CONFIG_SYS_HZ; + tbclk = TIMER_FREQ_HZ; return tbclk; } diff --git a/cpu/pxa/mmc.c b/cpu/pxa/mmc.c deleted file mode 100644 index d735c8d..0000000 --- a/cpu/pxa/mmc.c +++ /dev/null @@ -1,662 +0,0 @@ -/* - * (C) Copyright 2003 - * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net - * - * 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> -#include <common.h> -#include <mmc.h> -#include <asm/errno.h> -#include <asm/arch/hardware.h> -#include <part.h> - -#ifdef CONFIG_MMC - -extern int fat_register_device(block_dev_desc_t * dev_desc, int part_no); - -static block_dev_desc_t mmc_dev; - -block_dev_desc_t *mmc_get_dev(int dev) -{ - return ((block_dev_desc_t *) & mmc_dev); -} - -/* - * FIXME needs to read cid and csd info to determine block size - * and other parameters - */ -static uchar mmc_buf[MMC_BLOCK_SIZE]; -static uchar spec_ver; -static int mmc_ready = 0; -static int wide = 0; - -static uint32_t * -/****************************************************/ -mmc_cmd(ushort cmd, ushort argh, ushort argl, ushort cmdat) -/****************************************************/ -{ - static uint32_t resp[4], a, b, c; - ulong status; - int i; - - debug("mmc_cmd %u 0x%04x 0x%04x 0x%04x\n", cmd, argh, argl, - cmdat | wide); - MMC_STRPCL = MMC_STRPCL_STOP_CLK; - MMC_I_MASK = ~MMC_I_MASK_CLK_IS_OFF; - while (!(MMC_I_REG & MMC_I_REG_CLK_IS_OFF)) ; - MMC_CMD = cmd; - MMC_ARGH = argh; - MMC_ARGL = argl; - MMC_CMDAT = cmdat | wide; - MMC_I_MASK = ~MMC_I_MASK_END_CMD_RES; - MMC_STRPCL = MMC_STRPCL_START_CLK; - while (!(MMC_I_REG & MMC_I_REG_END_CMD_RES)) ; - - status = MMC_STAT; - debug("MMC status 0x%08x\n", status); - if (status & MMC_STAT_TIME_OUT_RESPONSE) { - return 0; - } - - /* Linux says: - * Did I mention this is Sick. We always need to - * discard the upper 8 bits of the first 16-bit word. - */ - a = (MMC_RES & 0xffff); - for (i = 0; i < 4; i++) { - b = (MMC_RES & 0xffff); - c = (MMC_RES & 0xffff); - resp[i] = (a << 24) | (b << 8) | (c >> 8); - a = c; - debug("MMC resp[%d] = %#08x\n", i, resp[i]); - } - - return resp; -} - -int -/****************************************************/ -mmc_block_read(uchar * dst, ulong src, ulong len) -/****************************************************/ -{ - ushort argh, argl; - ulong status; - - if (len == 0) { - return 0; - } - - debug("mmc_block_rd dst %lx src %lx len %d\n", (ulong) dst, src, len); - - argh = len >> 16; - argl = len & 0xffff; - - /* set block len */ - mmc_cmd(MMC_CMD_SET_BLOCKLEN, argh, argl, MMC_CMDAT_R1); - - /* send read command */ - argh = src >> 16; - argl = src & 0xffff; - MMC_STRPCL = MMC_STRPCL_STOP_CLK; - MMC_RDTO = 0xffff; - MMC_NOB = 1; - MMC_BLKLEN = len; - mmc_cmd(MMC_CMD_READ_SINGLE_BLOCK, argh, argl, - MMC_CMDAT_R1 | MMC_CMDAT_READ | MMC_CMDAT_BLOCK | - MMC_CMDAT_DATA_EN); - - MMC_I_MASK = ~MMC_I_MASK_RXFIFO_RD_REQ; - while (len) { - if (MMC_I_REG & MMC_I_REG_RXFIFO_RD_REQ) { -#ifdef CONFIG_PXA27X - int i; - for (i = min(len, 32); i; i--) { - *dst++ = *((volatile uchar *)&MMC_RXFIFO); - len--; - } -#else - *dst++ = MMC_RXFIFO; - len--; -#endif - } - status = MMC_STAT; - if (status & MMC_STAT_ERRORS) { - printf("MMC_STAT error %lx\n", status); - return -1; - } - } - MMC_I_MASK = ~MMC_I_MASK_DATA_TRAN_DONE; - while (!(MMC_I_REG & MMC_I_REG_DATA_TRAN_DONE)) ; - status = MMC_STAT; - if (status & MMC_STAT_ERRORS) { - printf("MMC_STAT error %lx\n", status); - return -1; - } - return 0; -} - -int -/****************************************************/ -mmc_block_write(ulong dst, uchar * src, int len) -/****************************************************/ -{ - ushort argh, argl; - ulong status; - - if (len == 0) { - return 0; - } - - debug("mmc_block_wr dst %lx src %lx len %d\n", dst, (ulong) src, len); - - argh = len >> 16; - argl = len & 0xffff; - - /* set block len */ - mmc_cmd(MMC_CMD_SET_BLOCKLEN, argh, argl, MMC_CMDAT_R1); - - /* send write command */ - argh = dst >> 16; - argl = dst & 0xffff; - MMC_STRPCL = MMC_STRPCL_STOP_CLK; - MMC_NOB = 1; - MMC_BLKLEN = len; - mmc_cmd(MMC_CMD_WRITE_BLOCK, argh, argl, - MMC_CMDAT_R1 | MMC_CMDAT_WRITE | MMC_CMDAT_BLOCK | - MMC_CMDAT_DATA_EN); - - MMC_I_MASK = ~MMC_I_MASK_TXFIFO_WR_REQ; - while (len) { - if (MMC_I_REG & MMC_I_REG_TXFIFO_WR_REQ) { - int i, bytes = min(32, len); - - for (i = 0; i < bytes; i++) { - MMC_TXFIFO = *src++; - } - if (bytes < 32) { - MMC_PRTBUF = MMC_PRTBUF_BUF_PART_FULL; - } - len -= bytes; - } - status = MMC_STAT; - if (status & MMC_STAT_ERRORS) { - printf("MMC_STAT error %lx\n", status); - return -1; - } - } - MMC_I_MASK = ~MMC_I_MASK_DATA_TRAN_DONE; - while (!(MMC_I_REG & MMC_I_REG_DATA_TRAN_DONE)) ; - MMC_I_MASK = ~MMC_I_MASK_PRG_DONE; - while (!(MMC_I_REG & MMC_I_REG_PRG_DONE)) ; - status = MMC_STAT; - if (status & MMC_STAT_ERRORS) { - printf("MMC_STAT error %lx\n", status); - return -1; - } - return 0; -} - -int -/****************************************************/ -mmc_read(ulong src, uchar * dst, int size) -/****************************************************/ -{ - ulong end, part_start, part_end, part_len, aligned_start, aligned_end; - ulong mmc_block_size, mmc_block_address; - - if (size == 0) { - return 0; - } - - if (!mmc_ready) { - printf("Please initial the MMC first\n"); - return -1; - } - - mmc_block_size = MMC_BLOCK_SIZE; - mmc_block_address = ~(mmc_block_size - 1); - - src -= CONFIG_SYS_MMC_BASE; - end = src + size; - part_start = ~mmc_block_address & src; - part_end = ~mmc_block_address & end; - aligned_start = mmc_block_address & src; - aligned_end = mmc_block_address & end; - - /* all block aligned accesses */ - debug - ("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", - src, (ulong) dst, end, part_start, part_end, aligned_start, - aligned_end); - if (part_start) { - part_len = mmc_block_size - part_start; - debug - ("ps src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", - src, (ulong) dst, end, part_start, part_end, aligned_start, - aligned_end); - if ((mmc_block_read(mmc_buf, aligned_start, mmc_block_size)) < - 0) { - return -1; - } - memcpy(dst, mmc_buf + part_start, part_len); - dst += part_len; - src += part_len; - } - debug - ("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", - src, (ulong) dst, end, part_start, part_end, aligned_start, - aligned_end); - for (; src < aligned_end; src += mmc_block_size, dst += mmc_block_size) { - debug - ("al src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", - src, (ulong) dst, end, part_start, part_end, aligned_start, - aligned_end); - if ((mmc_block_read((uchar *) (dst), src, mmc_block_size)) < 0) { - return -1; - } - } - debug - ("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", - src, (ulong) dst, end, part_start, part_end, aligned_start, - aligned_end); - if (part_end && src < end) { - debug - ("pe src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", - src, (ulong) dst, end, part_start, part_end, aligned_start, - aligned_end); - if ((mmc_block_read(mmc_buf, aligned_end, mmc_block_size)) < 0) { - return -1; - } - memcpy(dst, mmc_buf, part_end); - } - return 0; -} - -int -/****************************************************/ -mmc_write(uchar * src, ulong dst, int size) -/****************************************************/ -{ - ulong end, part_start, part_end, part_len, aligned_start, aligned_end; - ulong mmc_block_size, mmc_block_address; - - if (size == 0) { - return 0; - } - - if (!mmc_ready) { - printf("Please initial the MMC first\n"); - return -1; - } - - mmc_block_size = MMC_BLOCK_SIZE; - mmc_block_address = ~(mmc_block_size - 1); - - dst -= CONFIG_SYS_MMC_BASE; - end = dst + size; - part_start = ~mmc_block_address & dst; - part_end = ~mmc_block_address & end; - aligned_start = mmc_block_address & dst; - aligned_end = mmc_block_address & end; - - /* all block aligned accesses */ - debug - ("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", - src, (ulong) dst, end, part_start, part_end, aligned_start, - aligned_end); - if (part_start) { - part_len = mmc_block_size - part_start; - debug - ("ps src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", - (ulong) src, dst, end, part_start, part_end, aligned_start, - aligned_end); - if ((mmc_block_read(mmc_buf, aligned_start, mmc_block_size)) < - 0) { - return -1; - } - memcpy(mmc_buf + part_start, src, part_len); - if ((mmc_block_write(aligned_start, mmc_buf, mmc_block_size)) < - 0) { - return -1; - } - dst += part_len; - src += part_len; - } - debug - ("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", - src, (ulong) dst, end, part_start, part_end, aligned_start, - aligned_end); - for (; dst < aligned_end; src += mmc_block_size, dst += mmc_block_size) { - debug - ("al src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", - src, (ulong) dst, end, part_start, part_end, aligned_start, - aligned_end); - if ((mmc_block_write(dst, (uchar *) src, mmc_block_size)) < 0) { - return -1; - } - } - debug - ("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", - src, (ulong) dst, end, part_start, part_end, aligned_start, - aligned_end); - if (part_end && dst < end) { - debug - ("pe src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", - src, (ulong) dst, end, part_start, part_end, aligned_start, - aligned_end); - if ((mmc_block_read(mmc_buf, aligned_end, mmc_block_size)) < 0) { - return -1; - } - memcpy(mmc_buf, src, part_end); - if ((mmc_block_write(aligned_end, mmc_buf, mmc_block_size)) < 0) { - return -1; - } - } - return 0; -} - -ulong -/****************************************************/ -mmc_bread(int dev_num, ulong blknr, lbaint_t blkcnt, void *dst) -/****************************************************/ -{ - int mmc_block_size = MMC_BLOCK_SIZE; - ulong src = blknr * mmc_block_size + CONFIG_SYS_MMC_BASE; - - mmc_read(src, (uchar *) dst, blkcnt * mmc_block_size); - return blkcnt; -} - -#ifdef __GNUC__ -#define likely(x) __builtin_expect(!!(x), 1) -#define unlikely(x) __builtin_expect(!!(x), 0) -#else -#define likely(x) (x) -#define unlikely(x) (x) -#endif - -#define UNSTUFF_BITS(resp,start,size) \ - ({ \ - const int __size = size; \ - const uint32_t __mask = (__size < 32 ? 1 << __size : 0) - 1; \ - const int32_t __off = 3 - ((start) / 32); \ - const int32_t __shft = (start) & 31; \ - uint32_t __res; \ - \ - __res = resp[__off] >> __shft; \ - if (__size + __shft > 32) \ - __res |= resp[__off-1] << ((32 - __shft) % 32); \ - __res & __mask; \ - }) - -/* - * Given the decoded CSD structure, decode the raw CID to our CID structure. - */ -static void mmc_decode_cid(uint32_t * resp) -{ - if (IF_TYPE_SD == mmc_dev.if_type) { - /* - * SD doesn't currently have a version field so we will - * have to assume we can parse this. - */ - sprintf((char *)mmc_dev.vendor, - "Man %02x OEM %c%c \"%c%c%c%c%c\" Date %02u/%04u", - UNSTUFF_BITS(resp, 120, 8), UNSTUFF_BITS(resp, 112, 8), - UNSTUFF_BITS(resp, 104, 8), UNSTUFF_BITS(resp, 96, 8), - UNSTUFF_BITS(resp, 88, 8), UNSTUFF_BITS(resp, 80, 8), - UNSTUFF_BITS(resp, 72, 8), UNSTUFF_BITS(resp, 64, 8), - UNSTUFF_BITS(resp, 8, 4), UNSTUFF_BITS(resp, 12, - 8) + 2000); - sprintf((char *)mmc_dev.revision, "%d.%d", - UNSTUFF_BITS(resp, 60, 4), UNSTUFF_BITS(resp, 56, 4)); - sprintf((char *)mmc_dev.product, "%u", - UNSTUFF_BITS(resp, 24, 32)); - } else { - /* - * The selection of the format here is based upon published - * specs from sandisk and from what people have reported. - */ - switch (spec_ver) { - case 0: /* MMC v1.0 - v1.2 */ - case 1: /* MMC v1.4 */ - sprintf((char *)mmc_dev.vendor, - "Man %02x%02x%02x \"%c%c%c%c%c%c%c\" Date %02u/%04u", - UNSTUFF_BITS(resp, 120, 8), UNSTUFF_BITS(resp, - 112, - 8), - UNSTUFF_BITS(resp, 104, 8), UNSTUFF_BITS(resp, - 96, 8), - UNSTUFF_BITS(resp, 88, 8), UNSTUFF_BITS(resp, - 80, 8), - UNSTUFF_BITS(resp, 72, 8), UNSTUFF_BITS(resp, - 64, 8), - UNSTUFF_BITS(resp, 56, 8), UNSTUFF_BITS(resp, - 48, 8), - UNSTUFF_BITS(resp, 12, 4), UNSTUFF_BITS(resp, 8, - 4) + - 1997); - sprintf((char *)mmc_dev.revision, "%d.%d", - UNSTUFF_BITS(resp, 44, 4), UNSTUFF_BITS(resp, - 40, 4)); - sprintf((char *)mmc_dev.product, "%u", - UNSTUFF_BITS(resp, 16, 24)); - break; - - case 2: /* MMC v2.0 - v2.2 */ - case 3: /* MMC v3.1 - v3.3 */ - case 4: /* MMC v4 */ - sprintf((char *)mmc_dev.vendor, - "Man %02x OEM %04x \"%c%c%c%c%c%c\" Date %02u/%04u", - UNSTUFF_BITS(resp, 120, 8), UNSTUFF_BITS(resp, - 104, - 16), - UNSTUFF_BITS(resp, 96, 8), UNSTUFF_BITS(resp, - 88, 8), - UNSTUFF_BITS(resp, 80, 8), UNSTUFF_BITS(resp, - 72, 8), - UNSTUFF_BITS(resp, 64, 8), UNSTUFF_BITS(resp, - 56, 8), - UNSTUFF_BITS(resp, 12, 4), UNSTUFF_BITS(resp, 8, - 4) + - 1997); - sprintf((char *)mmc_dev.product, "%u", - UNSTUFF_BITS(resp, 16, 32)); - sprintf((char *)mmc_dev.revision, "N/A"); - break; - - default: - printf("MMC card has unknown MMCA version %d\n", - spec_ver); - break; - } - } - printf("%s card.\nVendor: %s\nProduct: %s\nRevision: %s\n", - (IF_TYPE_SD == mmc_dev.if_type) ? "SD" : "MMC", mmc_dev.vendor, - mmc_dev.product, mmc_dev.revision); -} - -/* - * Given a 128-bit response, decode to our card CSD structure. - */ -static void mmc_decode_csd(uint32_t * resp) -{ - unsigned int mult, csd_struct; - - if (IF_TYPE_SD == mmc_dev.if_type) { - csd_struct = UNSTUFF_BITS(resp, 126, 2); - if (csd_struct != 0) { - printf("SD: unrecognised CSD structure version %d\n", - csd_struct); - return; - } - } else { - /* - * We only understand CSD structure v1.1 and v1.2. - * v1.2 has extra information in bits 15, 11 and 10. - */ - csd_struct = UNSTUFF_BITS(resp, 126, 2); - if (csd_struct != 1 && csd_struct != 2) { - printf("MMC: unrecognised CSD structure version %d\n", - csd_struct); - return; - } - - spec_ver = UNSTUFF_BITS(resp, 122, 4); - mmc_dev.if_type = IF_TYPE_MMC; - } - - mult = 1 << (UNSTUFF_BITS(resp, 47, 3) + 2); - mmc_dev.lba = (1 + UNSTUFF_BITS(resp, 62, 12)) * mult; - mmc_dev.blksz = 1 << UNSTUFF_BITS(resp, 80, 4); - - /* FIXME: The following just makes assumes that's the partition type -- should really read it */ - mmc_dev.part_type = PART_TYPE_DOS; - mmc_dev.dev = 0; - mmc_dev.lun = 0; - mmc_dev.type = DEV_TYPE_HARDDISK; - mmc_dev.removable = 0; - mmc_dev.block_read = mmc_bread; - - printf("Detected: %lu blocks of %lu bytes (%luMB) ", - mmc_dev.lba, - mmc_dev.blksz, - mmc_dev.lba * mmc_dev.blksz / (1024 * 1024)); -} - -int -/****************************************************/ -mmc_init(int verbose) -/****************************************************/ -{ - int retries, rc = -ENODEV; - uint32_t cid_resp[4]; - uint32_t *resp; - uint16_t rca = 0; - - /* Reset device interface type */ - mmc_dev.if_type = IF_TYPE_UNKNOWN; - -#if defined (CONFIG_LUBBOCK) || (defined (CONFIG_GUMSTIX) && !defined(CONFIG_PXA27X)) - set_GPIO_mode(GPIO6_MMCCLK_MD); - set_GPIO_mode(GPIO8_MMCCS0_MD); -#endif - CKEN |= CKEN12_MMC; /* enable MMC unit clock */ - - MMC_CLKRT = MMC_CLKRT_0_3125MHZ; - MMC_RESTO = MMC_RES_TO_MAX; - MMC_SPI = MMC_SPI_DISABLE; - - /* reset */ - mmc_cmd(MMC_CMD_GO_IDLE_STATE, 0, 0, MMC_CMDAT_INIT | MMC_CMDAT_R0); - udelay(200000); - retries = 3; - while (retries--) { - resp = mmc_cmd(MMC_CMD_APP_CMD, 0, 0, MMC_CMDAT_R1); - if (!(resp[0] & 0x00000020)) { /* Card does not support APP_CMD */ - debug("Card does not support APP_CMD\n"); - break; - } - - /* Select 3.2-3.3V and 3.3-3.4V */ - resp = mmc_cmd(SD_CMD_APP_SEND_OP_COND, 0x0030, 0x0000, - MMC_CMDAT_R3 | (retries < 2 ? 0 - : MMC_CMDAT_INIT)); - if (resp[0] & 0x80000000) { - mmc_dev.if_type = IF_TYPE_SD; - debug("Detected SD card\n"); - break; - } -#ifdef CONFIG_PXA27X - udelay(10000); -#else - udelay(200000); -#endif - } - - if (retries <= 0 || !(IF_TYPE_SD == mmc_dev.if_type)) { - debug("Failed to detect SD Card, trying MMC\n"); - resp = - mmc_cmd(MMC_CMD_SEND_OP_COND, 0x00ff, 0x8000, MMC_CMDAT_R3); - - retries = 10; - while (retries-- && resp && !(resp[0] & 0x80000000)) { -#ifdef CONFIG_PXA27X - udelay(10000); -#else - udelay(200000); -#endif - resp = - mmc_cmd(MMC_CMD_SEND_OP_COND, 0x00ff, 0x8000, - MMC_CMDAT_R3); - } - } - - /* try to get card id */ - resp = - mmc_cmd(MMC_CMD_ALL_SEND_CID, 0, 0, MMC_CMDAT_R2 | MMC_CMDAT_BUSY); - if (resp) { - memcpy(cid_resp, resp, sizeof(cid_resp)); - - /* MMC exists, get CSD too */ - resp = mmc_cmd(MMC_CMD_SET_RELATIVE_ADDR, 0, 0, MMC_CMDAT_R1); - if (IF_TYPE_SD == mmc_dev.if_type) - rca = ((resp[0] & 0xffff0000) >> 16); - resp = mmc_cmd(MMC_CMD_SEND_CSD, rca, 0, MMC_CMDAT_R2); - if (resp) { - mmc_decode_csd(resp); - rc = 0; - mmc_ready = 1; - } - - mmc_decode_cid(cid_resp); - } - - MMC_CLKRT = 0; /* 20 MHz */ - resp = mmc_cmd(MMC_CMD_SELECT_CARD, rca, 0, MMC_CMDAT_R1); - -#ifdef CONFIG_PXA27X - if (IF_TYPE_SD == mmc_dev.if_type) { - resp = mmc_cmd(MMC_CMD_APP_CMD, rca, 0, MMC_CMDAT_R1); - resp = mmc_cmd(SD_CMD_APP_SET_BUS_WIDTH, 0, 2, MMC_CMDAT_R1); - wide = MMC_CMDAT_SD_4DAT; - } -#endif - - fat_register_device(&mmc_dev, 1); /* partitions start counting with 1 */ - - return rc; -} - -int mmc_ident(block_dev_desc_t * dev) -{ - return 0; -} - -int mmc2info(ulong addr) -{ - if (addr >= CONFIG_SYS_MMC_BASE - && addr < CONFIG_SYS_MMC_BASE + (mmc_dev.lba * mmc_dev.blksz)) { - return 1; - } - return 0; -} - -#endif /* CONFIG_MMC */ diff --git a/cpu/sh2/Makefile b/cpu/sh2/Makefile index e33ba0f..346d328 100644 --- a/cpu/sh2/Makefile +++ b/cpu/sh2/Makefile @@ -28,18 +28,23 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(CPU).a -START = start.o -OBJS = cpu.o interrupts.o watchdog.o +SOBJS = start.o +COBJS = cpu.o interrupts.o watchdog.o -all: .depend $(START) $(LIB) +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) -$(LIB): $(OBJS) - $(AR) $(ARFLAGS) $@ $(OBJS) +$(LIB): $(OBJS) $(SOBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS) -######################################################################### +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak $(obj).depend -.depend: Makefile $(START:.o=.S) $(OBJS:.o=.c) - $(CC) -M $(CFLAGS) $(START:.o=.S) $(OBJS:.o=.c) > $@ +######################################################################### # defines $(obj).depend target include $(SRCTREE)/rules.mk diff --git a/cpu/sh4/cpu.c b/cpu/sh4/cpu.c index d94e139..52b6cfd 100644 --- a/cpu/sh4/cpu.c +++ b/cpu/sh4/cpu.c @@ -82,3 +82,11 @@ int dcache_status (void) { return 0; } + +int cpu_eth_init(bd_t *bis) +{ +#ifdef CONFIG_SH_ETHER + sh_eth_initialize(bis); +#endif + return 0; +} |