Add ARM946E cpu and core module targets; remap memory to 0x00000000
Patch by Peter Pearse, 2 Feb 2005
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);
+}