[U-Boot] Fixing IXP42x boards - some general questions
Michael Schwingen
rincewind at discworld.dascon.de
Thu Dec 23 16:13:42 CET 2010
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 --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 at schwingen.org
+ *
* (C) Copyright 2006
* Stefan Roese, DENX Software Engineering, sr at 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 */
More information about the U-Boot
mailing list