Add ARM946E cpu and core module targets; remap memory to 0x00000000
Patch by Peter Pearse, 2 Feb 2005
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 @@
 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 @@
 #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 @@
 
 	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 @@
 /*************************************************************
  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 @@
 ******************************/
 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
+	 */
 
-	/* All done by IntegratorCP's boot monitor! */
-	mov pc, lr
+#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 */
+