diff options
author | Wolfgang Denk <wd@pollux.(none)> | 2005-09-25 01:48:28 +0200 |
---|---|---|
committer | Wolfgang Denk <wd@pollux.(none)> | 2005-09-25 01:48:28 +0200 |
commit | 74f4304ee717d0f4b3a27e7fd4a64944749b8783 (patch) | |
tree | 806aadd6a2be863b9a0e4e9649858468b4641c96 /board | |
parent | e2146b6aea0de16e55530cc5ff58fb626d9870cd (diff) | |
download | u-boot-imx-74f4304ee717d0f4b3a27e7fd4a64944749b8783.zip u-boot-imx-74f4304ee717d0f4b3a27e7fd4a64944749b8783.tar.gz u-boot-imx-74f4304ee717d0f4b3a27e7fd4a64944749b8783.tar.bz2 |
Add ARM946E cpu and core module targets; remap memory to 0x00000000
Patch by Peter Pearse, 2 Feb 2005
Diffstat (limited to 'board')
-rw-r--r-- | board/integratorap/Makefile | 3 | ||||
-rw-r--r-- | board/integratorap/integratorap.c | 137 | ||||
-rw-r--r-- | board/integratorap/memsetup.S | 30 | ||||
-rw-r--r-- | board/integratorap/platform.S | 12 | ||||
-rw-r--r-- | board/integratorcp/Makefile | 2 | ||||
-rw-r--r-- | board/integratorcp/integratorcp.c | 185 | ||||
-rw-r--r-- | board/integratorcp/memsetup.S | 30 | ||||
-rw-r--r-- | board/integratorcp/platform.S | 185 |
8 files changed, 571 insertions, 13 deletions
diff --git a/board/integratorap/Makefile b/board/integratorap/Makefile index 00336aa..154d1af 100644 --- a/board/integratorap/Makefile +++ b/board/integratorap/Makefile @@ -30,7 +30,7 @@ include $(TOPDIR)/config.mk LIB = lib$(BOARD).a OBJS := integratorap.o flash.o -SOBJS := platform.o +SOBJS := platform.o memsetup.o $(LIB): $(OBJS) $(SOBJS) $(AR) crv $@ $^ @@ -49,3 +49,4 @@ distclean: clean -include .depend ######################################################################### + diff --git a/board/integratorap/integratorap.c b/board/integratorap/integratorap.c index fb83c82..6140a7a 100644 --- a/board/integratorap/integratorap.c +++ b/board/integratorap/integratorap.c @@ -477,3 +477,140 @@ int dram_init (void) { return 0; } + +/* The Integrator/AP timer1 is clocked at 24MHz + * can be divided by 16 or 256 + * and is a 16-bit counter + */ +/* U-Boot expects a 32 bit timer running at CFG_HZ*/ +static ulong timestamp; /* U-Boot ticks since startup */ +static ulong total_count = 0; /* Total timer count */ +static ulong lastdec; /* Timer reading at last call */ +static ulong div_clock = 256; /* Divisor applied to the timer clock */ +static ulong div_timer = 1; /* Divisor to convert timer reading + * change to U-Boot ticks + */ +/* CFG_HZ = CFG_HZ_CLOCK/(div_clock * div_timer) */ + +#define TIMER_LOAD_VAL 0x0000FFFFL +#define READ_TIMER ((*(volatile ulong *)(CFG_TIMERBASE+4)) & 0x0000FFFFL) + +/* all function return values in U-Boot ticks i.e. (1/CFG_HZ) sec + * - unless otherwise stated + */ + +/* starts a counter + * - the Integrator/AP timer issues an interrupt + * each time it reaches zero + */ +int interrupt_init (void) +{ + /* Load timer with initial value */ + *(volatile ulong *)(CFG_TIMERBASE + 0) = TIMER_LOAD_VAL; + /* Set timer to be + * enabled 1 + * free-running 0 + * XX 00 + * divider 256 10 + * XX 00 + */ + *(volatile ulong *)(CFG_TIMERBASE + 8) = 0x00000088; + total_count = 0; + /* init the timestamp and lastdec value */ + reset_timer_masked(); + + div_timer = CFG_HZ_CLOCK / CFG_HZ; + div_timer /= div_clock; + + return (0); +} + +/* + * timer without interrupts + */ +void reset_timer (void) +{ + reset_timer_masked (); +} + +ulong get_timer (ulong base_ticks) +{ + return get_timer_masked () - base_ticks; +} + +void set_timer (ulong ticks) +{ + timestamp = ticks; + total_count = ticks * div_timer; + reset_timer_masked(); +} + +/* delay x useconds */ +void udelay (unsigned long usec) +{ + ulong tmo, tmp; + + /* Convert to U-Boot ticks */ + tmo = usec * CFG_HZ; + tmo /= (1000000L); + + tmp = get_timer_masked(); /* get current timestamp */ + tmo += tmp; /* wake up timestamp */ + + while (get_timer_masked () < tmo)/* loop till event */ + { + /*NOP*/; + } +} + +void reset_timer_masked (void) +{ + /* reset time */ + lastdec = READ_TIMER; /* capture current decrementer value */ + timestamp = 0; /* start "advancing" time stamp from 0 */ +} + +/* converts the timer reading to U-Boot ticks */ +/* the timestamp is the number of ticks since reset */ +/* This routine does not detect wraps unless called regularly + ASSUMES a call at least every 16 seconds to detect every reload */ +ulong get_timer_masked (void) +{ + ulong now = READ_TIMER; /* current count */ + + if(now > lastdec) + { + /* Must have wrapped */ + total_count += lastdec + TIMER_LOAD_VAL + 1 - now; + } else { + total_count += lastdec - now; + } + lastdec = now; + timestamp = total_count/div_timer; + + return timestamp; +} + +/* waits specified delay value and resets timestamp */ +void udelay_masked (unsigned long usec) +{ + udelay(usec); +} + +/* + * 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); +} + +/* + * Return the timebase clock frequency + * i.e. how often the timer decrements + */ +ulong get_tbclk (void) +{ + return CFG_HZ_CLOCK/div_clock; +} diff --git a/board/integratorap/memsetup.S b/board/integratorap/memsetup.S new file mode 100644 index 0000000..bdf6af9 --- /dev/null +++ b/board/integratorap/memsetup.S @@ -0,0 +1,30 @@ +/* + * Memory setup for integratorAP + * + * 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 + */ +/* + * Memory setup + * - the reset defaults are assumed sufficient + */ + +.globl memsetup +memsetup: + mov pc,lr + diff --git a/board/integratorap/platform.S b/board/integratorap/platform.S index 480e040..e9b0717 100644 --- a/board/integratorap/platform.S +++ b/board/integratorap/platform.S @@ -31,3 +31,15 @@ platformsetup: /* All done by Integrator's boot monitor! */ mov pc, lr + + /* Reset using CM control register */ +.global reset_cpu +reset_cpu: + mov r0, #CM_BASE + ldr r1,[r0,#OS_CTRL] + orr r1,r1,#CMMASK_RESET + str r1,[r0] + +reset_failed: + b reset_failed + diff --git a/board/integratorcp/Makefile b/board/integratorcp/Makefile index 9c97237..71532d1 100644 --- a/board/integratorcp/Makefile +++ b/board/integratorcp/Makefile @@ -26,7 +26,7 @@ include $(TOPDIR)/config.mk LIB = lib$(BOARD).a OBJS := integratorcp.o flash.o -SOBJS := platform.o +SOBJS := platform.o memsetup.o $(LIB): $(OBJS) $(SOBJS) $(AR) crv $@ $^ diff --git a/board/integratorcp/integratorcp.c b/board/integratorcp/integratorcp.c index 6fe8f05..db833f0 100644 --- a/board/integratorcp/integratorcp.c +++ b/board/integratorcp/integratorcp.c @@ -42,19 +42,12 @@ void peripheral_power_enable (void); #if defined(CONFIG_SHOW_BOOT_PROGRESS) void show_boot_progress(int progress) { - printf("Boot reached stage %d\n", progress); + printf("Boot reached stage %d\n", progress); } #endif #define COMP_MODE_ENABLE ((unsigned int)0x0000EAEF) -static inline void delay (unsigned long loops) -{ - __asm__ volatile ("1:\n" - "subs %0, %1, #1\n" - "bne 1b":"=r" (loops):"0" (loops)); -} - /* * Miscellaneous platform dependent initialisations */ @@ -71,6 +64,11 @@ int board_init (void) gd->flags = 0; +#ifdef CONFIG_CM_REMAP +extern void cm_remap(void); + cm_remap(); /* remaps writeable memory to 0x00000000 */ +#endif + icache_enable (); flash__init (); @@ -95,7 +93,7 @@ void flash__init (void) /************************************************************* Routine:ether__init Description: take the Ethernet controller out of reset and wait - for the EEPROM load to complete. + for the EEPROM load to complete. *************************************************************/ void ether__init (void) { @@ -107,5 +105,174 @@ void ether__init (void) ******************************/ int dram_init (void) { + DECLARE_GLOBAL_DATA_PTR; + + gd->bd->bi_dram[0].start = PHYS_SDRAM_1; + gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; + +#ifdef CONFIG_CM_SPD_DETECT + { +extern void dram_query(void); + unsigned long cm_reg_sdram; + unsigned long sdram_shift; + + dram_query(); /* Assembler accesses to CM registers */ + /* Queries the SPD values */ + + /* Obtain the SDRAM size from the CM SDRAM register */ + + cm_reg_sdram = *(volatile ulong *)(CM_BASE + OS_SDRAM); + /* Register SDRAM size + * + * 0xXXXXXXbbb000bb 16 MB + * 0xXXXXXXbbb001bb 32 MB + * 0xXXXXXXbbb010bb 64 MB + * 0xXXXXXXbbb011bb 128 MB + * 0xXXXXXXbbb100bb 256 MB + * + */ + sdram_shift = ((cm_reg_sdram & 0x0000001C)/4)%4; + gd->bd->bi_dram[0].size = 0x01000000 << sdram_shift; + + } +#endif /* CM_SPD_DETECT */ + return 0; } + +/* The Integrator/CP timer1 is clocked at 1MHz + * can be divided by 16 or 256 + * and can be set up as a 32-bit timer + */ +/* U-Boot expects a 32 bit timer, running at CFG_HZ */ +/* Keep total timer count to avoid losing decrements < div_timer */ +static unsigned long long total_count = 0; +static unsigned long long lastdec; /* Timer reading at last call */ +static unsigned long long div_clock = 1; /* Divisor applied to timer clock */ +static unsigned long long div_timer = 1; /* Divisor to convert timer reading + * change to U-Boot ticks + */ +/* CFG_HZ = CFG_HZ_CLOCK/(div_clock * div_timer) */ +static ulong timestamp; /* U-Boot ticks since startup */ + +#define TIMER_LOAD_VAL ((ulong)0xFFFFFFFF) +#define READ_TIMER (*(volatile ulong *)(CFG_TIMERBASE+4)) + +/* all function return values in U-Boot ticks i.e. (1/CFG_HZ) sec + * - unless otherwise stated + */ + +/* starts up a counter + * - the Integrator/CP timer can be set up to issue an interrupt */ +int interrupt_init (void) +{ + /* Load timer with initial value */ + *(volatile ulong *)(CFG_TIMERBASE + 0) = TIMER_LOAD_VAL; + /* Set timer to be + * enabled 1 + * periodic 1 + * no interrupts 0 + * X 0 + * divider 1 00 == less rounding error + * 32 bit 1 + * wrapping 0 + */ + *(volatile ulong *)(CFG_TIMERBASE + 8) = 0x000000C2; + /* init the timestamp */ + total_count = 0ULL; + reset_timer_masked(); + + div_timer = (unsigned long long)(CFG_HZ_CLOCK / CFG_HZ); + div_timer /= div_clock; + + return (0); +} + +/* + * timer without interrupts + */ +void reset_timer (void) +{ + reset_timer_masked (); +} + +ulong get_timer (ulong base_ticks) +{ + return get_timer_masked () - base_ticks; +} + +void set_timer (ulong ticks) +{ + timestamp = ticks; + total_count = (unsigned long long)ticks * div_timer; +} + +/* delay usec useconds */ +void udelay (unsigned long usec) +{ + ulong tmo, tmp; + + /* Convert to U-Boot ticks */ + tmo = usec * CFG_HZ; + tmo /= (1000000L); + + tmp = get_timer_masked(); /* get current timestamp */ + tmo += tmp; /* form target timestamp */ + + while (get_timer_masked () < tmo)/* loop till event */ + { + /*NOP*/; + } +} + +void reset_timer_masked (void) +{ + /* capure current decrementer value */ + lastdec = (unsigned long long)READ_TIMER; + /* start "advancing" time stamp from 0 */ + timestamp = 0L; +} + +/* converts the timer reading to U-Boot ticks */ +/* the timestamp is the number of ticks since reset */ +ulong get_timer_masked (void) +{ + /* get current count */ + unsigned long long now = (unsigned long long)READ_TIMER; + + if(now > lastdec) + { + /* Must have wrapped */ + total_count += lastdec + TIMER_LOAD_VAL + 1 - now; + } else { + total_count += lastdec - now; + } + lastdec = now; + timestamp = (ulong)(total_count/div_timer); + + return timestamp; +} + +/* waits specified delay value and resets timestamp */ +void udelay_masked (unsigned long usec) +{ + udelay(usec); +} + +/* + * 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 (unsigned long long)get_timer(0); +} + +/* + * Return the timebase clock frequency + * i.e. how often the timer decrements + */ +ulong get_tbclk (void) +{ + return (ulong)(((unsigned long long)CFG_HZ_CLOCK)/div_clock); +} diff --git a/board/integratorcp/memsetup.S b/board/integratorcp/memsetup.S new file mode 100644 index 0000000..bdf6af9 --- /dev/null +++ b/board/integratorcp/memsetup.S @@ -0,0 +1,30 @@ +/* + * Memory setup for integratorAP + * + * 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 + */ +/* + * Memory setup + * - the reset defaults are assumed sufficient + */ + +.globl memsetup +memsetup: + mov pc,lr + diff --git a/board/integratorcp/platform.S b/board/integratorcp/platform.S index c02051b..73d6922 100644 --- a/board/integratorcp/platform.S +++ b/board/integratorcp/platform.S @@ -26,8 +26,189 @@ #include <config.h> #include <version.h> +/* Reset using CM control register */ +.global reset_cpu +reset_cpu: + mov r0, #CM_BASE + ldr r1,[r0,#OS_CTRL] + orr r1,r1,#CMMASK_RESET + str r1,[r0] + +reset_failed: + b reset_failed + +/* set up the platform, once the cpu has been initialized */ .globl platformsetup platformsetup: + /* If U-Boot has been run after the ARM boot monitor + * then all the necessary actions have been done + * otherwise we are running from user flash mapped to 0x00000000 + * --- DO NOT REMAP BEFORE THE CODE HAS BEEN RELOCATED -- + * Changes to the (possibly soft) reset defaults of the processor + * itself should be performed in cpu/arm<>/start.S + * This function affects only the core module or board settings + */ + +#ifdef CONFIG_CM_INIT + /* CM has an initialization register + * - bits in it are wired into test-chip pins to force + * reset defaults + * - may need to change its contents for U-Boot + */ + + /* set the desired CM specific value */ + mov r2,#CMMASK_LOWVEC /* Vectors at 0x00000000 for all */ + +#if defined (CONFIG_CM10200E) || defined (CONFIG_CM10220E) + orr r2,r2,#CMMASK_INIT_102 +#else + +#if !defined (CONFIG_CM920T) && !defined (CONFIG_CM920T_ETM) && \ + !defined (CONFIG_CM940T) + +#ifdef CONFIG_CM_MULTIPLE_SSRAM + /* set simple mapping */ + and r2,r2,#CMMASK_MAP_SIMPLE +#endif /* #ifdef CONFIG_CM_MULTIPLE_SSRAM */ + +#ifdef CONFIG_CM_TCRAM + /* disable TCRAM */ + and r2,r2,#CMMASK_TCRAM_DISABLE +#endif /* #ifdef CONFIG_CM_TCRAM */ + +#if defined (CONFIG_CM926EJ_S) || defined (CONFIG_CM1026EJ_S) || \ + defined (CONFIG_CM1136JF_S) + + and r2,r2,#CMMASK_LE + +#endif /* cpu with little endian initialization */ + + orr r2,r2,#CMMASK_CMxx6_COMMON + +#endif /* CMxx6 code */ + +#endif /* ARM102xxE value */ + + /* read CM_INIT */ + mov r0, #CM_BASE + ldr r1, [r0, #OS_INIT] + /* check against desired bit setting */ + and r3,r1,r2 + cmp r3,r2 + beq init_reg_OK + + /* lock for change */ + mov r3, #CMVAL_LOCK + and r3,r3,#CMMASK_LOCK + str r3, [r0, #OS_LOCK] + /* set desired value */ + orr r1,r1,r2 + /* write & relock CM_INIT */ + str r1, [r0, #OS_INIT] + mov r1, #CMVAL_UNLOCK + str r1, [r0, #OS_LOCK] + + /* soft reset so new values used */ + b reset_cpu + +init_reg_OK: + +#endif /* CONFIG_CM_INIT */ + + mov pc, lr + +#ifdef CONFIG_CM_SPD_DETECT + /* Fast memory is available for the DRAM data + * - ensure it has been transferred, then summarize the data + * into a CM register + */ +.globl dram_query +dram_query: + stmfd r13!,{r4-r6,lr} + /* set up SDRAM info */ + /* - based on example code from the CM User Guide */ + mov r0, #CM_BASE + +readspdbit: + ldr r1, [r0, #OS_SDRAM] /* read the SDRAM register */ + and r1, r1, #0x20 /* mask SPD bit (5) */ + cmp r1, #0x20 /* test if set */ + bne readspdbit + +setupsdram: + add r0, r0, #OS_SPD /* address the copy of the SDP data */ + ldrb r1, [r0, #3] /* number of row address lines */ + ldrb r2, [r0, #4] /* number of column address lines */ + ldrb r3, [r0, #5] /* number of banks */ + ldrb r4, [r0, #31] /* module bank density */ + mul r5, r4, r3 /* size of SDRAM (MB divided by 4) */ + mov r5, r5, ASL#2 /* size in MB */ + mov r0, #CM_BASE /* reload for later code */ + cmp r5, #0x10 /* is it 16MB? */ + bne not16 + mov r6, #0x2 /* store size and CAS latency of 2 */ + b writesize + +not16: + cmp r5, #0x20 /* is it 32MB? */ + bne not32 + mov r6, #0x6 + b writesize + +not32: + cmp r5, #0x40 /* is it 64MB? */ + bne not64 + mov r6, #0xa + b writesize + +not64: + cmp r5, #0x80 /* is it 128MB? */ + bne not128 + mov r6, #0xe + b writesize + +not128: + /* if it is none of these sizes then it is either 256MB, or + * there is no SDRAM fitted so default to 256MB + */ + mov r6, #0x12 + +writesize: + mov r1, r1, ASL#8 /* row addr lines from SDRAM reg */ + orr r2, r1, r2, ASL#12 /* OR in column address lines */ + orr r3, r2, r3, ASL#16 /* OR in number of banks */ + orr r6, r6, r3 /* OR in size and CAS latency */ + str r6, [r0, #OS_SDRAM] /* store SDRAM parameters */ + +#endif /* #ifdef CONFIG_CM_SPD_DETECT */ + + ldmfd r13!,{r4-r6,pc} /* back to caller */ + +#ifdef CONFIG_CM_REMAP + /* CM remap bit is operational + * - use it to map writeable memory at 0x00000000, in place of flash + */ +.globl cm_remap +cm_remap: + stmfd r13!,{r4-r10,lr} + + mov r0, #CM_BASE + ldr r1, [r0, #OS_CTRL] + orr r1, r1, #CMMASK_REMAP /* set remap and led bits */ + str r1, [r0, #OS_CTRL] + + /* Now 0x00000000 is writeable, replace the vectors */ + ldr r0, =_start /* r0 <- start of vectors */ + ldr r2, =_armboot_start /* r2 <- past vectors */ + sub r1,r1,r1 /* destination 0x00000000 */ + +copy_vec: + 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] */ + ble copy_vec + + ldmfd r13!,{r4-r10,pc} /* back to caller */ + +#endif /* #ifdef CONFIG_CM_REMAP */ - /* All done by IntegratorCP's boot monitor! */ - mov pc, lr |