[U-Boot] [PATCH 0/4 v2] Clean up the Nomadik board and add OneNand

This patch-set cleans up some glitches in my first submission. I posted it as a single patch and a separate timer patch. The first one is split as JC asked, and the timer patch is there as well since it is conceptually in the same set, although I had no comments on the timer part yet.
JC: I didn't split "clean" and "onenand", since the change in partitioning information in the config file is part of introducing onenand. A split would have introduced a never-tested artificial middle version.
Alessandro Rubini (4): arm nomadik: rename board to nhk8815 arm nomadik: cleanup reset arm nomadik: allow Nand and OneNand to coexists arm nomadik: use 1000 as HZ value and rewrite timer code
Makefile | 10 +- board/st/{nmdk8815 => nhk8815}/Makefile | 2 +- board/st/{nmdk8815 => nhk8815}/config.mk | 0 .../st/{nmdk8815/nmdk8815.c => nhk8815/nhk8815.c} | 4 + board/st/{nmdk8815 => nhk8815}/platform.S | 0 cpu/arm926ejs/nomadik/reset.S | 13 +-- cpu/arm926ejs/nomadik/timer.c | 190 ++++++-------------- doc/{README.nmdk8815 => README.nhk8815} | 10 + include/configs/{nmdk8815.h => nhk8815.h} | 59 ++++--- 9 files changed, 109 insertions(+), 179 deletions(-) rename board/st/{nmdk8815 => nhk8815}/Makefile (98%) rename board/st/{nmdk8815 => nhk8815}/config.mk (100%) rename board/st/{nmdk8815/nmdk8815.c => nhk8815/nhk8815.c} (91%) rename board/st/{nmdk8815 => nhk8815}/platform.S (100%) rename doc/{README.nmdk8815 => README.nhk8815} (75%) rename include/configs/{nmdk8815.h => nhk8815.h} (76%)

From: Alessandro Rubini rubini@unipv.it
This is an error in my side in the initial submission: nobody calls it ""nmdk8815", it's "nomadik hardware kit", nhk8815, instead.
Signed-off-by: Alessandro Rubini rubini@unipv.it Acked-by: Andrea Gallo andrea.gallo@stericsson.com --- Makefile | 6 +++--- board/st/{nmdk8815 => nhk8815}/Makefile | 2 +- board/st/{nmdk8815 => nhk8815}/config.mk | 0 .../st/{nmdk8815/nmdk8815.c => nhk8815/nhk8815.c} | 0 board/st/{nmdk8815 => nhk8815}/platform.S | 0 doc/{README.nmdk8815 => README.nhk8815} | 0 include/configs/{nmdk8815.h => nhk8815.h} | 3 ++- 7 files changed, 6 insertions(+), 5 deletions(-) rename board/st/{nmdk8815 => nhk8815}/Makefile (98%) rename board/st/{nmdk8815 => nhk8815}/config.mk (100%) rename board/st/{nmdk8815/nmdk8815.c => nhk8815/nhk8815.c} (100%) rename board/st/{nmdk8815 => nhk8815}/platform.S (100%) rename doc/{README.nmdk8815 => README.nhk8815} (100%) rename include/configs/{nmdk8815.h => nhk8815.h} (97%)
diff --git a/Makefile b/Makefile index bcc81c9..37e50f0 100644 --- a/Makefile +++ b/Makefile @@ -2839,8 +2839,8 @@ mx1fs2_config : unconfig netstar_config: unconfig @$(MKCONFIG) $(@:_config=) arm arm925t netstar
-nmdk8815_config \ -nmdk8815_onenand_config: unconfig +nhk8815_config \ +nhk8815_onenand_config: unconfig @mkdir -p $(obj)include @ > $(obj)include/config.h @if [ "$(findstring _onenand, $@)" ] ; then \ @@ -2849,7 +2849,7 @@ nmdk8815_onenand_config: unconfig else \ $(XECHO) "... configured for Nand Flash"; \ fi - @$(MKCONFIG) -a nmdk8815 arm arm926ejs nmdk8815 st nomadik + @$(MKCONFIG) -a nhk8815 arm arm926ejs nhk8815 st nomadik
omap1510inn_config : unconfig @$(MKCONFIG) $(@:_config=) arm arm925t omap1510inn diff --git a/board/st/nmdk8815/Makefile b/board/st/nhk8815/Makefile similarity index 98% rename from board/st/nmdk8815/Makefile rename to board/st/nhk8815/Makefile index be9a424..b37fe53 100644 --- a/board/st/nmdk8815/Makefile +++ b/board/st/nhk8815/Makefile @@ -29,7 +29,7 @@ include $(TOPDIR)/config.mk
LIB = $(obj)lib$(BOARD).a
-COBJS := nmdk8815.o +COBJS := nhk8815.o SOBJS := platform.o
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) diff --git a/board/st/nmdk8815/config.mk b/board/st/nhk8815/config.mk similarity index 100% rename from board/st/nmdk8815/config.mk rename to board/st/nhk8815/config.mk diff --git a/board/st/nmdk8815/nmdk8815.c b/board/st/nhk8815/nhk8815.c similarity index 100% rename from board/st/nmdk8815/nmdk8815.c rename to board/st/nhk8815/nhk8815.c diff --git a/board/st/nmdk8815/platform.S b/board/st/nhk8815/platform.S similarity index 100% rename from board/st/nmdk8815/platform.S rename to board/st/nhk8815/platform.S diff --git a/doc/README.nmdk8815 b/doc/README.nhk8815 similarity index 100% rename from doc/README.nmdk8815 rename to doc/README.nhk8815 diff --git a/include/configs/nmdk8815.h b/include/configs/nhk8815.h similarity index 97% rename from include/configs/nmdk8815.h rename to include/configs/nhk8815.h index 6d7b94f..df9d523 100644 --- a/include/configs/nmdk8815.h +++ b/include/configs/nhk8815.h @@ -1,7 +1,8 @@ /* * (C) Copyright 2005 * STMicroelectronics. - * Configuration settings for the STn8815 nomadik board. + * Configuration settings for the "Nomadik Hardware Kit" NHK-8815, + * the evaluation board for the Nomadik 8815 System on Chip. * * See file CREDITS for list of people who contributed to this * project.

From: Alessandro Rubini rubini@unipv.it
There is only one public release of the Nomadik chip, so the ifdef in reset code as well as a define in the config file are not needed
Signed-off-by: Alessandro Rubini rubini@unipv.it Acked-by: Andrea Gallo andrea.gallo@stericsson.com --- cpu/arm926ejs/nomadik/reset.S | 13 +------------ include/configs/nhk8815.h | 5 ++--- 2 files changed, 3 insertions(+), 15 deletions(-)
diff --git a/cpu/arm926ejs/nomadik/reset.S b/cpu/arm926ejs/nomadik/reset.S index 948996b..ec95472 100644 --- a/cpu/arm926ejs/nomadik/reset.S +++ b/cpu/arm926ejs/nomadik/reset.S @@ -6,20 +6,9 @@ .align 5 .globl reset_cpu reset_cpu: -#if defined CONFIG_NOMADIK_8815 - ldr r0, =NOMADIK_SRC_BASE + ldr r0, =NOMADIK_SRC_BASE /* System and Reset Controller */ ldr r1, =0x1 str r1, [r0, #0x18] -#else - ldr r1, rstctl1 /* get clkm1 reset ctl */ - mov r3, #0x0 - strh r3, [r1] /* clear it */ - mov r3, #0x8 - strh r3, [r1] /* force dsp+arm reset */ -#endif
_loop_forever: b _loop_forever - -rstctl1: - .word 0xfffece10 diff --git a/include/configs/nhk8815.h b/include/configs/nhk8815.h index df9d523..321adfa 100644 --- a/include/configs/nhk8815.h +++ b/include/configs/nhk8815.h @@ -30,9 +30,8 @@
#define CONFIG_ARM926EJS #define CONFIG_NOMADIK -#define CONFIG_NOMADIK_8815 -#define CONFIG_NOMADIK_NDK15 -#define CONFIG_NOMADIK_NHK15 +#define CONFIG_NOMADIK_8815 /* cpu variant */ +#define CONFIG_NOMADIK_NHK8815 /* board variant */
#define CONFIG_SKIP_LOWLEVEL_INIT /* we have already been loaded to RAM */

From: Alessandro Rubini rubini@unipv.it
The evaluation kit has both Nand and OneNand, both drivers are there and the two configurations only select a different default for the jffs partition. This adds the OneNand driver and cleans up storage.
Signed-off-by: Alessandro Rubini rubini@unipv.it Acked-by: Andrea Gallo andrea.gallo@stericsson.com --- Makefile | 4 +- board/st/nhk8815/nhk8815.c | 4 +++ doc/README.nhk8815 | 10 +++++++++ include/configs/nhk8815.h | 49 +++++++++++++++++++++++++++---------------- 4 files changed, 47 insertions(+), 20 deletions(-)
diff --git a/Makefile b/Makefile index 37e50f0..d2454c8 100644 --- a/Makefile +++ b/Makefile @@ -2845,9 +2845,9 @@ nhk8815_onenand_config: unconfig @ > $(obj)include/config.h @if [ "$(findstring _onenand, $@)" ] ; then \ echo "#define CONFIG_BOOT_ONENAND" >> $(obj)include/config.h; \ - $(XECHO) "... configured for OneNand Flash"; \ + $(XECHO) "... configured to boot from OneNand Flash"; \ else \ - $(XECHO) "... configured for Nand Flash"; \ + $(XECHO) "... configured to boot from Nand Flash"; \ fi @$(MKCONFIG) -a nhk8815 arm arm926ejs nhk8815 st nomadik
diff --git a/board/st/nhk8815/nhk8815.c b/board/st/nhk8815/nhk8815.c index edf4626..085a5e0 100644 --- a/board/st/nhk8815/nhk8815.c +++ b/board/st/nhk8815/nhk8815.c @@ -53,6 +53,10 @@ int board_init(void) writel(0x0000305b, REG_FSMC_BCR1); writel(0x00033f33, REG_FSMC_BTR1);
+ /* Set up SMCS0 for OneNand: sram-like once again */ + writel(0x000030db, NOMADIK_FSMC_BASE + 0x00); /* FSMC_BCR0 */ + writel(0x02100551, NOMADIK_FSMC_BASE + 0x04); /* FSMC_BTR0 */ + icache_enable(); return 0; } diff --git a/doc/README.nhk8815 b/doc/README.nhk8815 index 453cfae..9008e39 100644 --- a/doc/README.nhk8815 +++ b/doc/README.nhk8815 @@ -15,6 +15,16 @@ SDRAM configuration, PLL setup and initial loading from NAND is implemented in the X-Loader, so U-Boot is already running in SDRAM when control is handed over to it.
+The Makefile offers two different configurations to be used if you +boot from Nand or OneNand. + + make nhk8815_config + make nhk8815_onenand_config + +Both support OneNand and Nand. Since U-Boot, running in RAM, can't know +where it was loaded from, the configurations differ in where the filesystem +is looked for by default. +
On www.st.com/nomadik and on www.stnwireless.com there are documents, summary data and white papers on Nomadik. The full datasheet for diff --git a/include/configs/nhk8815.h b/include/configs/nhk8815.h index 321adfa..bf1a915 100644 --- a/include/configs/nhk8815.h +++ b/include/configs/nhk8815.h @@ -55,6 +55,7 @@ #define CONFIG_SYS_HUSH_PARSER #define CONFIG_SYS_PROMPT "Nomadik> " #define CONFIG_SYS_PROMPT_HUSH_PS2 "> " +#define CONFIG_CMDLINE_EDITING #define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */ #define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE \ + sizeof(CONFIG_SYS_PROMPT) + 16) @@ -90,6 +91,7 @@ #define CONFIG_SYS_MEMTEST_END 0x0FFFFFFF #define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 256 * 1024) #define CONFIG_SYS_GBL_DATA_SIZE 128 /* for initial data */ +#define CONFIG_SYS_64BIT_VSPRINTF /* mtd desires this */
#define CONFIG_MISC_INIT_R /* call misc_init_r during start up */
@@ -120,43 +122,54 @@ #define CONFIG_SMC_USE_32_BIT #define CONFIG_BOOTFILE "uImage"
-/* flash memory and filesystem information */ -#define CONFIG_DOS_PARTITION +/* Storage information: onenand and nand */ +#define CONFIG_CMD_ONENAND #define CONFIG_MTD_ONENAND_VERIFY_WRITE #define CONFIG_SYS_ONENAND_BASE 0x30000000 + +#define CONFIG_CMD_NAND #define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_SYS_NAND_BASE 0x40000000 /* SMPS0n */
+/* + * Filesystem information + * + * Since U-Boot has been loaded to RAM by vendor code, we could use + * either or both OneNand and Nand. However, we need to know where the + * filesystem lives. Comments below report vendor-selected partitions + */ #ifdef CONFIG_BOOT_ONENAND - -# define CONFIG_CMD_ONENAND /* Temporary: nand and onenand can't coexist */ /* Partition Size Start * XloaderTOC + X-Loader 256KB 0x00000000 * Memory init function 256KB 0x00040000 - * U-Boot 2MB 0x00080000 + * U-Boot + env 2MB 0x00080000 * Sysimage (kernel + ramdisk) 4MB 0x00280000 * JFFS2 Root filesystem 22MB 0x00680000 * JFFS2 User Data 227.5MB 0x01C80000 */ -# define CONFIG_JFFS2_PART_SIZE 0x400000 -# define CONFIG_JFFS2_PART_OFFSET 0x280000 - +# define CONFIG_JFFS2_DEV "onenand0" +# define CONFIG_JFFS2_PART_SIZE 0x01600000 +# define CONFIG_JFFS2_PART_OFFSET 0x00680000 # define CONFIG_ENV_IS_IN_ONENAND -# define CONFIG_ENV_SIZE (256 * 1024) -# define CONFIG_ENV_ADDR 0x30300000 - -#else /* ! CONFIG_BOOT_ONENAND */ - -# define CONFIG_CMD_NAND /* Temporary: nand and onenand can't coexist */ +# define CONFIG_ENV_SIZE 0x20000 /* 128 Kb - one sector */ +# define CONFIG_ENV_ADDR (0x00280000 - CONFIG_ENV_SIZE)
+#else /* BOOT_NAND */ + /* Partition Size Start + * XloaderTOC + X-Loader 256KB 0x00000000 + * Memory init function 256KB 0x00040000 + * U-Boot + env 2MB 0x00080000 + * Kernel Image 3MB 0x00280000 + * JFFS2 Root filesystem 22MB 0x00580000 + * JFFS2 User Data 100.5MB 0x01b80000 + */ # define CONFIG_JFFS2_DEV "nand0" # define CONFIG_JFFS2_NAND 1 /* For the jffs2 support*/ -# define CONFIG_JFFS2_PART_SIZE 0x00300000 -# define CONFIG_JFFS2_PART_OFFSET 0x00280000 - +# define CONFIG_JFFS2_PART_SIZE 0x01600000 +# define CONFIG_JFFS2_PART_OFFSET 0x00580000 # define CONFIG_ENV_IS_IN_NAND # define CONFIG_ENV_SIZE 0x20000 /* 128 Kb - one sector */ -# define CONFIG_ENV_OFFSET (0x8000000 - CONFIG_ENV_SIZE) +# define CONFIG_ENV_OFFSET (0x00280000 - CONFIG_ENV_SIZE)
#endif /* CONFIG_BOOT_ONENAND */

From: Alessandro Rubini rubini@unipv.it
This sets CONFIG_SYS_HZ to 1000 as required, and completely rewrites timer code, which is now both correct and much smaller. Unused functions like udelay_masked() have been removed as no driver uses them, even the ones that are not currently active for this board.
Signed-off-by: Alessandro Rubini rubini@unipv.it Acked-by: Andrea Gallo andrea.gallo@stericsson.com --- cpu/arm926ejs/nomadik/timer.c | 190 +++++++++++----------------------------- include/configs/nhk8815.h | 2 +- 2 files changed, 53 insertions(+), 139 deletions(-)
diff --git a/cpu/arm926ejs/nomadik/timer.c b/cpu/arm926ejs/nomadik/timer.c index 2870d24..3618c4a 100644 --- a/cpu/arm926ejs/nomadik/timer.c +++ b/cpu/arm926ejs/nomadik/timer.c @@ -1,20 +1,5 @@ /* - * (C) Copyright 2003 - * Texas Instruments <www.ti.com> - * - * (C) Copyright 2002 - * Sysgo Real-Time Solutions, GmbH <www.elinos.com> - * Marius Groeger mgroeger@sysgo.de - * - * (C) Copyright 2002 - * Sysgo Real-Time Solutions, GmbH <www.elinos.com> - * Alex Zuepke azu@sysgo.de - * - * (C) Copyright 2002-2004 - * Gary Jennejohn, DENX Software Engineering, garyj@denx.de - * - * (C) Copyright 2004 - * Philippe Robin, ARM Ltd. philippe.robin@arm.com + * (C) Copyright 2009 Alessandro Rubini * * See file CREDITS for list of people who contributed to this * project. @@ -38,145 +23,74 @@ #include <common.h> #include <asm/io.h>
-#define TIMER_LOAD_VAL 0xffffffff +/* + * Registers in the MTU block -- same as <mach/mtu.h> in linux +*/ + +#define MTU_IMSC 0x00 /* Interrupt mask set/clear */ +#define MTU_RIS 0x04 /* Raw interrupt status */ +#define MTU_MIS 0x08 /* Masked interrupt status */ +#define MTU_ICR 0x0C /* Interrupt clear register */ + +/* per-timer registers take 0..3 as argument */ +#define MTU_LR(x) (0x10 + 0x10 * (x) + 0x00) /* Load value */ +#define MTU_VAL(x) (0x10 + 0x10 * (x) + 0x04) /* Current value */ +#define MTU_CR(x) (0x10 + 0x10 * (x) + 0x08) /* Control reg */ +#define MTU_BGLR(x) (0x10 + 0x10 * (x) + 0x0c) /* At next overflow */ + +/* bits for the control register */ +#define MTU_CRn_ENA 0x80 +#define MTU_CRn_PERIODIC 0x40 /* if 0 = free-running */ +#define MTU_CRn_PRESCALE_MASK 0x0c +#define MTU_CRn_PRESCALE_1 0x00 +#define MTU_CRn_PRESCALE_16 0x04 +#define MTU_CRn_PRESCALE_256 0x08 +#define MTU_CRn_32BITS 0x02 +#define MTU_CRn_ONESHOT 0x01 /* if 0 = wraps reloading from BGLR*/
-/* macro to read the 32 bit timer */ -#define READ_TIMER readl(CONFIG_SYS_TIMERBASE + 20)
-static ulong timestamp; -static ulong lastdec; +/* + * The timer is a decrementer, we'll left it free running at 2.4MHz. + * We have 2.4 ticks per microsecond and an overflow in almost 30min + */ +#define TIMER_CLOCK (24*100*1000) +#define COUNT_TO_USEC(x) ((x)*5/12) /* overflows at 6min */ +#define USEC_TO_COUNT(x) ((x)*12/5) /* overflows at 6min */ +#define TICKS_PER_HZ (TIMER_CLOCK/CONFIG_SYS_HZ) +#define TICKS_TO_HZ(x) ((x)/TICKS_PER_HZ) + +/* macro to read the 32 bit timer: since it decrements, we invert read value */ +#define READ_TIMER() (~readl(CONFIG_SYS_TIMERBASE + MTU_VAL(0)))
-/* nothing really to do with interrupts, just starts up a counter. */ +/* Configure a free-running, auto-wrap counter with no prescaler */ int timer_init(void) { - /* Load timer with initial value */ - writel(TIMER_LOAD_VAL, CONFIG_SYS_TIMERBASE + 16); - - /* - * Set timer to be enabled, free-running, no interrupts, 256 divider, - * 32-bit, wrap-mode - */ - writel(0x8a, CONFIG_SYS_TIMERBASE + 24); - - /* init the timestamp and lastdec value */ - reset_timer_masked(); - + writel(MTU_CRn_ENA | MTU_CRn_PRESCALE_1 | MTU_CRn_32BITS, + CONFIG_SYS_TIMERBASE + MTU_CR(0)); + reset_timer(); return 0; }
-/* - * timer without interrupts - */ +/* Restart counting from 0 */ void reset_timer(void) { - reset_timer_masked(); + writel(0, CONFIG_SYS_TIMERBASE + MTU_LR(0)); /* Immediate effect */ }
+/* Return how many HZ passed since "base" */ ulong get_timer(ulong base) { - return get_timer_masked() - base; -} - -void set_timer(ulong t) -{ - timestamp = t; + ulong res = TICKS_TO_HZ(READ_TIMER()) - base; + return res; }
-/* delay x useconds AND perserve advance timstamp value */ +/* Delay x useconds */ void udelay(unsigned long usec) { - ulong tmo, tmp; - - if (usec >= 1000) { - /* if "big" number, spread normalization to seconds */ - tmo = usec / 1000; /* start to normalize */ - tmo *= CONFIG_SYS_HZ; /* find number of "ticks" */ - tmo /= 1000; /* finish normalize. */ - } else { - /* small number, don't kill it prior to HZ multiply */ - tmo = usec * CONFIG_SYS_HZ; - tmo /= (1000 * 1000); - } - - tmp = get_timer(0); /* get current timestamp */ - if ((tmo + tmp + 1) < tmp) /* will roll time stamp? */ - reset_timer_masked(); /* reset to 0, set lastdec value */ - else - tmo += tmp; - - while (get_timer_masked() < tmo) - /* nothing */ ; -} - -void reset_timer_masked(void) -{ - /* reset time */ - lastdec = READ_TIMER; /* capure current decrementer value time */ - timestamp = 0; /* start "advancing" time stamp from 0 */ -} - -ulong get_timer_masked(void) -{ - ulong now = READ_TIMER; /* current tick value */ - - if (lastdec >= now) { /* normal mode (non roll) */ - /* move stamp fordward */ - timestamp += lastdec - now; - } else { - /* - * An overflow is expected. - * nts = ts + ld + (TLV - now) - * ts=old stamp, ld=time that passed before passing through -1 - * (TLV-now) amount of time after passing though -1 - * nts = new "advancing time stamp"...it could also roll - */ - timestamp += lastdec + TIMER_LOAD_VAL - now; - } - lastdec = now; - - return timestamp; -} - -/* waits specified delay value and resets timestamp */ -void udelay_masked(unsigned long usec) -{ - ulong tmo; - - if (usec >= 1000) { - /* if "big" number, spread normalization to seconds */ - tmo = usec / 1000; /* start to normalize */ - tmo *= CONFIG_SYS_HZ; /* find number of "ticks" */ - tmo /= 1000; /* finish normalize. */ - } else { - /* else small number, don't kill it prior to HZ multiply */ - tmo = usec * CONFIG_SYS_HZ; - tmo /= (1000*1000); - } - - reset_timer_masked(); - /* set "advancing" timestamp to 0, set lastdec vaule */ - - while (get_timer_masked() < tmo) - /* nothing */ ; -} - -/* - * 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); -} - -/* - * This function is derived from PowerPC code (timebase clock frequency). - * On ARM it returns the number of timer ticks per second. - */ -ulong get_tbclk(void) -{ - ulong tbclk; + ulong ini, end;
- tbclk = CONFIG_SYS_HZ; - return tbclk; + ini = READ_TIMER(); + end = ini + USEC_TO_COUNT(usec); + while ((signed)(end - READ_TIMER()) > 0) + ; } diff --git a/include/configs/nhk8815.h b/include/configs/nhk8815.h index bf1a915..3e2e09f 100644 --- a/include/configs/nhk8815.h +++ b/include/configs/nhk8815.h @@ -96,7 +96,7 @@ #define CONFIG_MISC_INIT_R /* call misc_init_r during start up */
/* timing informazion */ -#define CONFIG_SYS_HZ (2400000 / 256) /* Timer0: 2.4Mhz + divider */ +#define CONFIG_SYS_HZ 1000 /* Mandatory... */ #define CONFIG_SYS_TIMERBASE 0x101E2000
/* serial port (PL011) configuration */

On 11:19 Mon 22 Jun , Alessandro Rubini wrote:
From: Alessandro Rubini rubini@unipv.it
This sets CONFIG_SYS_HZ to 1000 as required, and completely rewrites timer code, which is now both correct and much smaller. Unused functions like udelay_masked() have been removed as no driver uses them, even the ones that are not currently active for this board.
Signed-off-by: Alessandro Rubini rubini@unipv.it Acked-by: Andrea Gallo andrea.gallo@stericsson.com
for the record what is its precision now?
cpu/arm926ejs/nomadik/timer.c | 190 +++++++++++----------------------------- include/configs/nhk8815.h | 2 +- 2 files changed, 53 insertions(+), 139 deletions(-)
diff --git a/cpu/arm926ejs/nomadik/timer.c b/cpu/arm926ejs/nomadik/timer.c index 2870d24..3618c4a 100644 --- a/cpu/arm926ejs/nomadik/timer.c +++ b/cpu/arm926ejs/nomadik/timer.c @@ -1,20 +1,5 @@ /*
- (C) Copyright 2003
- Texas Instruments <www.ti.com>
- (C) Copyright 2002
- Sysgo Real-Time Solutions, GmbH <www.elinos.com>
- Marius Groeger mgroeger@sysgo.de
- (C) Copyright 2002
- Sysgo Real-Time Solutions, GmbH <www.elinos.com>
- Alex Zuepke azu@sysgo.de
- (C) Copyright 2002-2004
- Gary Jennejohn, DENX Software Engineering, garyj@denx.de
- (C) Copyright 2004
- Philippe Robin, ARM Ltd. philippe.robin@arm.com
- (C) Copyright 2009 Alessandro Rubini
- See file CREDITS for list of people who contributed to this
- project.
@@ -38,145 +23,74 @@ #include <common.h> #include <asm/io.h>
-#define TIMER_LOAD_VAL 0xffffffff +/*
- Registers in the MTU block -- same as <mach/mtu.h> in linux
so please simply import it
+*/
+#define MTU_IMSC 0x00 /* Interrupt mask set/clear */ +#define MTU_RIS 0x04 /* Raw interrupt status */ +#define MTU_MIS 0x08 /* Masked interrupt status */ +#define MTU_ICR 0x0C /* Interrupt clear register */
+/* per-timer registers take 0..3 as argument */ +#define MTU_LR(x) (0x10 + 0x10 * (x) + 0x00) /* Load value */ +#define MTU_VAL(x) (0x10 + 0x10 * (x) + 0x04) /* Current value */ +#define MTU_CR(x) (0x10 + 0x10 * (x) + 0x08) /* Control reg */ +#define MTU_BGLR(x) (0x10 + 0x10 * (x) + 0x0c) /* At next overflow */
+/* bits for the control register */ +#define MTU_CRn_ENA 0x80 +#define MTU_CRn_PERIODIC 0x40 /* if 0 = free-running */ +#define MTU_CRn_PRESCALE_MASK 0x0c +#define MTU_CRn_PRESCALE_1 0x00 +#define MTU_CRn_PRESCALE_16 0x04 +#define MTU_CRn_PRESCALE_256 0x08 +#define MTU_CRn_32BITS 0x02 +#define MTU_CRn_ONESHOT 0x01 /* if 0 = wraps reloading from BGLR*/
-/* macro to read the 32 bit timer */ -#define READ_TIMER readl(CONFIG_SYS_TIMERBASE + 20)
-static ulong timestamp; -static ulong lastdec; +/*
- The timer is a decrementer, we'll left it free running at 2.4MHz.
- We have 2.4 ticks per microsecond and an overflow in almost 30min
- */
+#define TIMER_CLOCK (24*100*1000) +#define COUNT_TO_USEC(x) ((x)*5/12) /* overflows at 6min */
please add space before and after */
+#define USEC_TO_COUNT(x) ((x)*12/5) /* overflows at 6min */ +#define TICKS_PER_HZ (TIMER_CLOCK/CONFIG_SYS_HZ) +#define TICKS_TO_HZ(x) ((x)/TICKS_PER_HZ)
+/* macro to read the 32 bit timer: since it decrements, we invert read value */ +#define READ_TIMER() (~readl(CONFIG_SYS_TIMERBASE + MTU_VAL(0)))
-/* nothing really to do with interrupts, just starts up a counter. */ +/* Configure a free-running, auto-wrap counter with no prescaler */ int timer_init(void) {
- /* Load timer with initial value */
- writel(TIMER_LOAD_VAL, CONFIG_SYS_TIMERBASE + 16);
- /*
* Set timer to be enabled, free-running, no interrupts, 256 divider,
* 32-bit, wrap-mode
*/
- writel(0x8a, CONFIG_SYS_TIMERBASE + 24);
- /* init the timestamp and lastdec value */
- reset_timer_masked();
- writel(MTU_CRn_ENA | MTU_CRn_PRESCALE_1 | MTU_CRn_32BITS,
CONFIG_SYS_TIMERBASE + MTU_CR(0));
- reset_timer(); return 0;
}
-/*
- timer without interrupts
- */
+/* Restart counting from 0 */ void reset_timer(void) {
- reset_timer_masked();
- writel(0, CONFIG_SYS_TIMERBASE + MTU_LR(0)); /* Immediate effect */
}
+/* Return how many HZ passed since "base" */ ulong get_timer(ulong base) {
- return get_timer_masked() - base;
-}
-void set_timer(ulong t) -{
- timestamp = t;
- ulong res = TICKS_TO_HZ(READ_TIMER()) - base;
please return directly
- return res;
}
Best Regards, J.

From: Alessandro Rubini rubini@unipv.it
This sets CONFIG_SYS_HZ to 1000 as required, and completely rewrites timer code, which is now both correct and much smaller. Unused functions like udelay_masked() have been removed as no driver uses them, even the ones that are not currently active for this board. mtu.h is copied literally from the kernel sources.
Signed-off-by: Alessandro Rubini rubini@unipv.it Acked-by: Andrea Gallo andrea.gallo@stericsson.com ---
I've used mtu.h from kernel sources and done the other changes as requested (the extra variable just to return it was a mishap from an earlier printf I needed to find a misconfig).
for the record what is its precision now?
it counts at 2.4MHz, so the 1000HZ tick has no approximation and udelay is correct with sub-microsecond error. I'll use in soft_i2c, needed to turn on the LCD light.
cpu/arm926ejs/nomadik/mtu.h | 45 +++++++++++ cpu/arm926ejs/nomadik/timer.c | 166 +++++++---------------------------------- include/configs/nhk8815.h | 2 +- 3 files changed, 73 insertions(+), 140 deletions(-) create mode 100644 cpu/arm926ejs/nomadik/mtu.h
diff --git a/cpu/arm926ejs/nomadik/mtu.h b/cpu/arm926ejs/nomadik/mtu.h new file mode 100644 index 0000000..21b4a7a --- /dev/null +++ b/cpu/arm926ejs/nomadik/mtu.h @@ -0,0 +1,45 @@ + +#ifndef __ASM_ARCH_MTU_H +#define __ASM_ARCH_MTU_H + +/* + * The MTU device hosts four different counters, with 4 set of + * registers. These are register names. + */ + +#define MTU_IMSC 0x00 /* Interrupt mask set/clear */ +#define MTU_RIS 0x04 /* Raw interrupt status */ +#define MTU_MIS 0x08 /* Masked interrupt status */ +#define MTU_ICR 0x0C /* Interrupt clear register */ + +/* per-timer registers take 0..3 as argument */ +#define MTU_LR(x) (0x10 + 0x10 * (x) + 0x00) /* Load value */ +#define MTU_VAL(x) (0x10 + 0x10 * (x) + 0x04) /* Current value */ +#define MTU_CR(x) (0x10 + 0x10 * (x) + 0x08) /* Control reg */ +#define MTU_BGLR(x) (0x10 + 0x10 * (x) + 0x0c) /* At next overflow */ + +/* bits for the control register */ +#define MTU_CRn_ENA 0x80 +#define MTU_CRn_PERIODIC 0x40 /* if 0 = free-running */ +#define MTU_CRn_PRESCALE_MASK 0x0c +#define MTU_CRn_PRESCALE_1 0x00 +#define MTU_CRn_PRESCALE_16 0x04 +#define MTU_CRn_PRESCALE_256 0x08 +#define MTU_CRn_32BITS 0x02 +#define MTU_CRn_ONESHOT 0x01 /* if 0 = wraps reloading from BGLR*/ + +/* Other registers are usual amba/primecell registers, currently not used */ +#define MTU_ITCR 0xff0 +#define MTU_ITOP 0xff4 + +#define MTU_PERIPH_ID0 0xfe0 +#define MTU_PERIPH_ID1 0xfe4 +#define MTU_PERIPH_ID2 0xfe8 +#define MTU_PERIPH_ID3 0xfeC + +#define MTU_PCELL0 0xff0 +#define MTU_PCELL1 0xff4 +#define MTU_PCELL2 0xff8 +#define MTU_PCELL3 0xffC + +#endif /* __ASM_ARCH_MTU_H */ diff --git a/cpu/arm926ejs/nomadik/timer.c b/cpu/arm926ejs/nomadik/timer.c index 2870d24..d0946ec 100644 --- a/cpu/arm926ejs/nomadik/timer.c +++ b/cpu/arm926ejs/nomadik/timer.c @@ -1,20 +1,5 @@ /* - * (C) Copyright 2003 - * Texas Instruments <www.ti.com> - * - * (C) Copyright 2002 - * Sysgo Real-Time Solutions, GmbH <www.elinos.com> - * Marius Groeger mgroeger@sysgo.de - * - * (C) Copyright 2002 - * Sysgo Real-Time Solutions, GmbH <www.elinos.com> - * Alex Zuepke azu@sysgo.de - * - * (C) Copyright 2002-2004 - * Gary Jennejohn, DENX Software Engineering, garyj@denx.de - * - * (C) Copyright 2004 - * Philippe Robin, ARM Ltd. philippe.robin@arm.com + * (C) Copyright 2009 Alessandro Rubini * * See file CREDITS for list of people who contributed to this * project. @@ -37,146 +22,49 @@
#include <common.h> #include <asm/io.h> +#include "mtu.h"
-#define TIMER_LOAD_VAL 0xffffffff - -/* macro to read the 32 bit timer */ -#define READ_TIMER readl(CONFIG_SYS_TIMERBASE + 20) +/* + * The timer is a decrementer, we'll left it free running at 2.4MHz. + * We have 2.4 ticks per microsecond and an overflow in almost 30min + */ +#define TIMER_CLOCK (24 * 100 * 1000) +#define COUNT_TO_USEC(x) ((x) * 5 / 12) /* overflows at 6min */ +#define USEC_TO_COUNT(x) ((x) * 12 / 5) /* overflows at 6min */ +#define TICKS_PER_HZ (TIMER_CLOCK / CONFIG_SYS_HZ) +#define TICKS_TO_HZ(x) ((x) / TICKS_PER_HZ)
-static ulong timestamp; -static ulong lastdec; +/* macro to read the 32 bit timer: since it decrements, we invert read value */ +#define READ_TIMER() (~readl(CONFIG_SYS_TIMERBASE + MTU_VAL(0)))
-/* nothing really to do with interrupts, just starts up a counter. */ +/* Configure a free-running, auto-wrap counter with no prescaler */ int timer_init(void) { - /* Load timer with initial value */ - writel(TIMER_LOAD_VAL, CONFIG_SYS_TIMERBASE + 16); - - /* - * Set timer to be enabled, free-running, no interrupts, 256 divider, - * 32-bit, wrap-mode - */ - writel(0x8a, CONFIG_SYS_TIMERBASE + 24); - - /* init the timestamp and lastdec value */ - reset_timer_masked(); - + writel(MTU_CRn_ENA | MTU_CRn_PRESCALE_1 | MTU_CRn_32BITS, + CONFIG_SYS_TIMERBASE + MTU_CR(0)); + reset_timer(); return 0; }
-/* - * timer without interrupts - */ +/* Restart counting from 0 */ void reset_timer(void) { - reset_timer_masked(); + writel(0, CONFIG_SYS_TIMERBASE + MTU_LR(0)); /* Immediate effect */ }
+/* Return how many HZ passed since "base" */ ulong get_timer(ulong base) { - return get_timer_masked() - base; + return TICKS_TO_HZ(READ_TIMER()) - base; }
-void set_timer(ulong t) -{ - timestamp = t; -} - -/* delay x useconds AND perserve advance timstamp value */ +/* Delay x useconds */ void udelay(unsigned long usec) { - ulong tmo, tmp; - - if (usec >= 1000) { - /* if "big" number, spread normalization to seconds */ - tmo = usec / 1000; /* start to normalize */ - tmo *= CONFIG_SYS_HZ; /* find number of "ticks" */ - tmo /= 1000; /* finish normalize. */ - } else { - /* small number, don't kill it prior to HZ multiply */ - tmo = usec * CONFIG_SYS_HZ; - tmo /= (1000 * 1000); - } - - tmp = get_timer(0); /* get current timestamp */ - if ((tmo + tmp + 1) < tmp) /* will roll time stamp? */ - reset_timer_masked(); /* reset to 0, set lastdec value */ - else - tmo += tmp; - - while (get_timer_masked() < tmo) - /* nothing */ ; -} - -void reset_timer_masked(void) -{ - /* reset time */ - lastdec = READ_TIMER; /* capure current decrementer value time */ - timestamp = 0; /* start "advancing" time stamp from 0 */ -} - -ulong get_timer_masked(void) -{ - ulong now = READ_TIMER; /* current tick value */ - - if (lastdec >= now) { /* normal mode (non roll) */ - /* move stamp fordward */ - timestamp += lastdec - now; - } else { - /* - * An overflow is expected. - * nts = ts + ld + (TLV - now) - * ts=old stamp, ld=time that passed before passing through -1 - * (TLV-now) amount of time after passing though -1 - * nts = new "advancing time stamp"...it could also roll - */ - timestamp += lastdec + TIMER_LOAD_VAL - now; - } - lastdec = now; - - return timestamp; -} - -/* waits specified delay value and resets timestamp */ -void udelay_masked(unsigned long usec) -{ - ulong tmo; - - if (usec >= 1000) { - /* if "big" number, spread normalization to seconds */ - tmo = usec / 1000; /* start to normalize */ - tmo *= CONFIG_SYS_HZ; /* find number of "ticks" */ - tmo /= 1000; /* finish normalize. */ - } else { - /* else small number, don't kill it prior to HZ multiply */ - tmo = usec * CONFIG_SYS_HZ; - tmo /= (1000*1000); - } - - reset_timer_masked(); - /* set "advancing" timestamp to 0, set lastdec vaule */ - - while (get_timer_masked() < tmo) - /* nothing */ ; -} - -/* - * 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); -} - -/* - * This function is derived from PowerPC code (timebase clock frequency). - * On ARM it returns the number of timer ticks per second. - */ -ulong get_tbclk(void) -{ - ulong tbclk; + ulong ini, end;
- tbclk = CONFIG_SYS_HZ; - return tbclk; + ini = READ_TIMER(); + end = ini + USEC_TO_COUNT(usec); + while ((signed)(end - READ_TIMER()) > 0) + ; } diff --git a/include/configs/nhk8815.h b/include/configs/nhk8815.h index bf1a915..3e2e09f 100644 --- a/include/configs/nhk8815.h +++ b/include/configs/nhk8815.h @@ -96,7 +96,7 @@ #define CONFIG_MISC_INIT_R /* call misc_init_r during start up */
/* timing informazion */ -#define CONFIG_SYS_HZ (2400000 / 256) /* Timer0: 2.4Mhz + divider */ +#define CONFIG_SYS_HZ 1000 /* Mandatory... */ #define CONFIG_SYS_TIMERBASE 0x101E2000
/* serial port (PL011) configuration */

On 12:52 Mon 29 Jun , Alessandro Rubini wrote:
From: Alessandro Rubini rubini@unipv.it
This sets CONFIG_SYS_HZ to 1000 as required, and completely rewrites timer code, which is now both correct and much smaller. Unused functions like udelay_masked() have been removed as no driver uses them, even the ones that are not currently active for this board. mtu.h is copied literally from the kernel sources.
Signed-off-by: Alessandro Rubini rubini@unipv.it Acked-by: Andrea Gallo andrea.gallo@stericsson.com
I've used mtu.h from kernel sources and done the other changes as requested (the extra variable just to return it was a mishap from an earlier printf I needed to find a misconfig).
for the record what is its precision now?
it counts at 2.4MHz, so the 1000HZ tick has no approximation and udelay is correct with sub-microsecond error. I'll use in soft_i2c, needed to turn on the LCD light.
cpu/arm926ejs/nomadik/mtu.h | 45 +++++++++++
if it's ok with I'll move it to include/asm-arm/arch-nomadik/
Best Regards, J.

On 11:18 Mon 22 Jun , Alessandro Rubini wrote:
This patch-set cleans up some glitches in my first submission. I posted it as a single patch and a separate timer patch. The first one is split as JC asked, and the timer patch is there as well since it is conceptually in the same set, although I had no comments on the timer part yet.
JC: I didn't split "clean" and "onenand", since the change in partitioning information in the config file is part of introducing onenand. A split would have introduced a never-tested artificial middle version.
fine
Alessandro Rubini (4): arm nomadik: rename board to nhk8815
ok
arm nomadik: cleanup reset
ok
arm nomadik: allow Nand and OneNand to coexists
ok
arm nomadik: use 1000 as HZ value and rewrite timer code
I'll take a look on it this WE
Best Regards, J.

On 11:18 Mon 22 Jun , Alessandro Rubini wrote:
This patch-set cleans up some glitches in my first submission. I posted it as a single patch and a separate timer patch. The first one is split as JC asked, and the timer patch is there as well since it is conceptually in the same set, although I had no comments on the timer part yet.
JC: I didn't split "clean" and "onenand", since the change in partitioning information in the config file is part of introducing onenand. A split would have introduced a never-tested artificial middle version.
Alessandro Rubini (4): arm nomadik: rename board to nhk8815 arm nomadik: cleanup reset arm nomadik: allow Nand and OneNand to coexists arm nomadik: use 1000 as HZ value and rewrite timer code
all applied to u-boot-arm patch 4 with the agreed update
Best Regards, J.
participants (2)
-
Alessandro Rubini
-
Jean-Christophe PLAGNIOL-VILLARD