diff mbox

[U-Boot] Fixing IXP42x boards - some general questions

Message ID 20101223151341.GA31823@discworld.dascon.de
State RFC
Delegated to: Albert ARIBAUD
Headers show

Commit Message

Michael Schwingen Dec. 23, 2010, 3:13 p.m. UTC
On Thu, Dec 23, 2010 at 11:55:01AM +0100, Marek Vasut wrote:
> On Thursday 23 December 2010 11:10:37 Wolfgang Denk wrote:
> > 
> > > Timer system.
> > > 
> > >  - For IXP, there are two variants of the timer system - one using
> > > 
> > > interrupts, and one without interrupts. Both do not work currently.
> > > I have patches that fix the non-interrupt version, changing
> > > CONFIG_SYS_HZ from 66666666 to 1000, bringing it in line with what most
> > > other ARM platforms do.
> > 
> > I cannot nomment on this.  Marek?
> 
> http://download.intel.com/design/network/manuals/25248006.pdf page 411 or so.
> 
> What's the second variant ? Either way -- you should use the non-interrupt 
> version. Remember, you're writing a bootloader, use the KISS principle ; you 
> generally use the timer only to implement *delay() functions.
> 
> Therefore, as Wolfgang said, you use 1000 ticks per second in uboot's internal 
> counting, but "convert" it from/to your real timer's ticks in timer.c
> 
> What problem do you have there? Also, can you please let us see the patches?

I don't have any problems - I just want to know what the preferred way is in
doing this, before I spend time touching multiple boards.

Patch for the timer part is attached - note that this is work-in-progress
and probably needs some cleanup before submission.

cu
Michael
diff mbox

Patch

diff --git a/arch/arm/cpu/ixp/timer.c b/arch/arm/cpu/ixp/timer.c
index edf341f..9715eab 100644
--- a/arch/arm/cpu/ixp/timer.c
+++ b/arch/arm/cpu/ixp/timer.c
@@ -1,4 +1,7 @@ 
 /*
+ * (C) Copyright 2010
+ * Michael Schwingen, michael@schwingen.org
+ *
  * (C) Copyright 2006
  * Stefan Roese, DENX Software Engineering, sr@denx.de.
  *
@@ -31,11 +34,11 @@ 
 
 #include <common.h>
 #include <asm/arch/ixp425.h>
+#include <div64.h>
 
 #ifdef CONFIG_TIMER_IRQ
 
-#define FREQ		66666666
-#define CLOCK_TICK_RATE	(((FREQ / CONFIG_SYS_HZ & ~IXP425_OST_RELOAD_MASK) + 1) * CONFIG_SYS_HZ)
+#define CLOCK_TICK_RATE	(((CONFIG_IXP425_TIMER_CLK / CONFIG_SYS_HZ & ~IXP425_OST_RELOAD_MASK) + 1) * CONFIG_SYS_HZ)
 #define LATCH		((CLOCK_TICK_RATE + CONFIG_SYS_HZ/2) / CONFIG_SYS_HZ)	/* For divider */
 
 /*
@@ -79,57 +82,98 @@  int timer_init (void)
 
 	return 0;
 }
-#else
-ulong get_timer (ulong base)
+
+#else /* not CONFIG_TIMER_IRQ */
+
+/*
+ * The IXP42x time-stamp timer runs at 2*OSC_IN (66.666MHz when using a
+ * 33.333MHz crystal).
+ */
+static inline unsigned long long tick_to_time(unsigned long long tick)
 {
-       return get_timer_masked () - base;
+	tick *= CONFIG_SYS_HZ;
+	do_div(tick, CONFIG_IXP425_TIMER_CLK);
+	return tick;
 }
 
-void ixp425_udelay(unsigned long usec)
+static inline unsigned long long time_to_tick(unsigned long long time)
 {
-	/*
-	 * This function has a max usec, but since it is called from udelay
-	 * we should not have to worry... be happy
-	 */
-	unsigned long usecs = CONFIG_SYS_HZ/1000000L & ~IXP425_OST_RELOAD_MASK;
+	time *= CONFIG_IXP425_TIMER_CLK;
+	do_div(time, CONFIG_SYS_HZ);
+	return time;
+}
 
-	*IXP425_OSST = IXP425_OSST_TIMER_1_PEND;
-	usecs |= IXP425_OST_ONE_SHOT | IXP425_OST_ENABLE;
-	*IXP425_OSRT1 = usecs;
-	while (!(*IXP425_OSST & IXP425_OSST_TIMER_1_PEND));
+static inline unsigned long long us_to_tick(unsigned long long us)
+{
+	us = us * CONFIG_IXP425_TIMER_CLK + 999999;
+	do_div(us, 1000000);
+	return us;
 }
 
-void __udelay (unsigned long usec)
+static ulong timestamp;
+static ulong lastinc;
+
+unsigned long long get_ticks (void)
 {
-	while (usec--) ixp425_udelay(1);
+	ulong now = *IXP425_OSTS_B;
+
+	if (*IXP425_OSST & IXP425_OSST_TIMER_TS_PEND) {
+		/* rollover of timestamp timer register */
+		timestamp += (0xFFFFFFFF - lastinc) + now + 1;
+		*IXP425_OSST = IXP425_OSST_TIMER_TS_PEND;
+	}
+	else {
+		/* move stamp forward with absolut diff ticks */
+		timestamp += (now - lastinc);
+	}
+	lastinc = now;
+	return timestamp;
 }
 
-static ulong reload_constant = 0xfffffff0;
 
 void reset_timer_masked (void)
 {
-	ulong reload = reload_constant | IXP425_OST_ONE_SHOT | IXP425_OST_ENABLE;
+	/* reset time */
+	lastinc = *IXP425_OSTS_B; /* capture current timestamp counter */
+	timestamp = 0;          /* start "advancing" time stamp from 0 */
+}
 
-	*IXP425_OSST = IXP425_OSST_TIMER_1_PEND;
-	*IXP425_OSRT1 = reload;
+void reset_timer(void)
+{
+	reset_timer_masked();
 }
 
 ulong get_timer_masked (void)
 {
-	/*
-	 * Note that it is possible for this to wrap!
-	 * In this case we return max.
-	 */
-	ulong current = *IXP425_OST1;
-	if (*IXP425_OSST & IXP425_OSST_TIMER_1_PEND)
-	{
-		return reload_constant;
-	}
-	return (reload_constant - current);
+	return tick_to_time(get_ticks());
+}
+
+ulong get_timer (ulong base)
+{
+	return get_timer_masked() - base;
+}
+
+void set_timer (ulong t)
+{
+	timestamp = time_to_tick(t);
 }
 
+/* delay x useconds AND preserve advance timestamp value */
+void __udelay (unsigned long usec)
+{
+	unsigned long long tmp;
+
+	tmp = get_ticks() + us_to_tick(usec);
+
+	while (get_ticks() < tmp)
+		;
+}
+
+
 int timer_init(void)
 {
+	*IXP425_OSST = IXP425_OSST_TIMER_TS_PEND;
 	return 0;
 }
+
 #endif
diff --git a/arch/arm/include/asm/arch-ixp/ixp425.h b/arch/arm/include/asm/arch-ixp/ixp425.h
index 2114437..ddbf713 100644
--- a/arch/arm/include/asm/arch-ixp/ixp425.h
+++ b/arch/arm/include/asm/arch-ixp/ixp425.h
@@ -391,9 +391,8 @@ 
 #define IXP425_TIMER_REG(x) (IXP425_TIMER_BASE_PHYS+(x))
 #endif
 
-#if 0 /* test-only: also defined in npe/include/... */
-#define IXP425_OSTS	IXP425_TIMER_REG(IXP425_OSTS_OFFSET)
-#endif
+/* _B to avoid collision: also defined in npe/include/... */
+#define IXP425_OSTS_B	IXP425_TIMER_REG(IXP425_OSTS_OFFSET) 
 #define IXP425_OST1	IXP425_TIMER_REG(IXP425_OST1_OFFSET)
 #define IXP425_OSRT1	IXP425_TIMER_REG(IXP425_OSRT1_OFFSET)
 #define IXP425_OST2	IXP425_TIMER_REG(IXP425_OST2_OFFSET)
diff --git a/include/configs/actux3.h b/include/configs/actux3.h
index 76acf5a..4afe5ac 100644
--- a/include/configs/actux3.h
+++ b/include/configs/actux3.h
@@ -28,6 +28,7 @@ 
 
 #define CONFIG_IXP425			1
 #define CONFIG_ACTUX3			1
+#define CONFIG_USE_FUNCTION_SECTIONS    1
 
 #define CONFIG_DISPLAY_CPUINFO		1
 #define CONFIG_DISPLAY_BOARDINFO	1
@@ -37,6 +38,7 @@ 
 #define CONFIG_BAUDRATE			115200
 #define CONFIG_BOOTDELAY		3
 #define CONFIG_ZERO_BOOTDELAY_CHECK	/* check for keypress on bootdelay==0 */
+#define CONFIG_BOARD_EARLY_INIT_F	1
 
 /***************************************************************
  * U-boot generic defines start here.
@@ -83,8 +85,9 @@ 
 #define CONFIG_SYS_MEMTEST_START		0x00400000
 #define CONFIG_SYS_MEMTEST_END			0x00800000
 
-/* spec says 66.666 MHz, but it appears to be 33 */
-#define CONFIG_SYS_HZ				3333333
+/* timer clock - 2* OSC_IN system clock */
+#define CONFIG_IXP425_TIMER_CLK                 66666666
+#define CONFIG_SYS_HZ				1000
 
 /* default load address */
 #define CONFIG_SYS_LOAD_ADDR			0x00010000
@@ -111,7 +114,7 @@ 
 /* SDRAM settings */
 #define CONFIG_NR_DRAM_BANKS		1
 #define PHYS_SDRAM_1			0x00000000
-#define CONFIG_SYS_DRAM_BASE			0x00000000
+#define CONFIG_SYS_SDRAM_BASE			0x00000000
 
 /* 16MB SDRAM */
 #define CONFIG_SYS_SDR_CONFIG			0x3A
@@ -121,6 +124,7 @@ 
 #define CONFIG_SYS_DRAM_SIZE			0x01000000
 
 /* FLASH organization */
+#define CONFIG_SYS_TEXT_BASE		0x50000000
 #define CONFIG_SYS_MAX_FLASH_BANKS		1
 /* max number of sectors on one chip */
 #define CONFIG_SYS_MAX_FLASH_SECT		140
@@ -150,6 +154,11 @@ 
 #define	CONFIG_PHY_ADDR			0x10
 /* MII PHY management */
 #define CONFIG_MII			1
+/* fixed-speed switch without standard PHY registers on MII */
+#define CONFIG_MII_NPE0_FIXEDLINK       1
+#define CONFIG_MII_NPE0_SPEED           100
+#define CONFIG_MII_NPE0_FULLDUPLEX      1
+
 /* Number of ethernet rx buffers & descriptors */
 #define CONFIG_SYS_RX_ETH_BUFFER		16
 #define CONFIG_RESET_PHY_R		1
@@ -223,4 +232,8 @@ 
 	" tftpboot ${loadaddr} ${kernelfile};"				\
 	" bootm\0"
 
+/* additions for new relocation code, must be added to all boards */
+#define CONFIG_SYS_INIT_SP_ADDR        \
+	(CONFIG_SYS_SDRAM_BASE + 0x1000 - GENERATED_GBL_DATA_SIZE)
+
 #endif /* __CONFIG_H */