Message ID | 1302126558-1318-5-git-send-email-michael@schwingen.org |
---|---|
State | Superseded |
Delegated to: | Marek Vasut |
Headers | show |
On Wednesday, April 06, 2011 11:49:05 PM Michael Schwingen wrote: > - jump to real flash location after reset before turning off flash mirror > - fix timer system to use HZ == 1000, remove broken interrupt-based code > > Signed-off-by: Michael Schwingen <michael@schwingen.org> > --- > Changes for V2: > - fix patch description > Changes for V3: > - use I/O accessors > - move timestamp variable from BSS to global data > - coding style fixes > Changes for V4: > - add changelog > > arch/arm/cpu/ixp/cpu.c | 5 -- > arch/arm/cpu/ixp/start.S | 59 ++-------------- > arch/arm/cpu/ixp/timer.c | 124 > +++++++++++++++----------------- arch/arm/include/asm/arch-ixp/ixp425.h | > 5 +- > arch/arm/include/asm/global_data.h | 3 + > 5 files changed, 68 insertions(+), 128 deletions(-) > > diff --git a/arch/arm/cpu/ixp/cpu.c b/arch/arm/cpu/ixp/cpu.c > index ce275e5..942845d 100644 > --- a/arch/arm/cpu/ixp/cpu.c > +++ b/arch/arm/cpu/ixp/cpu.c > @@ -36,8 +36,6 @@ > #include <asm/arch/ixp425.h> > #include <asm/system.h> > > -ulong loops_per_jiffy; > - > static void cache_flush(void); > > #if defined(CONFIG_DISPLAY_CPUINFO) > @@ -51,17 +49,14 @@ int print_cpuinfo (void) > puts("CPU: Intel IXP425 at "); > switch ((id & 0x000003f0) >> 4) { > case 0x1c: > - loops_per_jiffy = 887467; > speed = 533; > break; > > case 0x1d: > - loops_per_jiffy = 666016; > speed = 400; > break; > > case 0x1f: > - loops_per_jiffy = 442901; > speed = 266; > break; > } > diff --git a/arch/arm/cpu/ixp/start.S b/arch/arm/cpu/ixp/start.S > index 561c1f4..faa9a8f 100644 > --- a/arch/arm/cpu/ixp/start.S > +++ b/arch/arm/cpu/ixp/start.S > @@ -65,7 +65,8 @@ > .endm > > .globl _start > -_start: b reset > +_start: > + ldr pc, _reset > ldr pc, _undefined_instruction > ldr pc, _software_interrupt > ldr pc, _prefetch_abort > @@ -74,6 +75,7 @@ _start: b reset > ldr pc, _irq > ldr pc, _fiq > > +_reset: .word reset > _undefined_instruction: .word undefined_instruction > _software_interrupt: .word software_interrupt > _prefetch_abort: .word prefetch_abort > @@ -167,12 +169,6 @@ reset: > str r1, [r2] > > /* make sure flash is visible at 0 */ > -#if 0 > - ldr r2, =IXP425_EXP_CFG0 > - ldr r1, [r2] > - orr r1, r1, #0x80000000 > - str r1, [r2] > -#endif > mov r1, #CONFIG_SYS_SDR_CONFIG > ldr r2, =IXP425_SDR_CONFIG > str r1, [r2] > @@ -216,19 +212,6 @@ reset: > str r1, [r4] > DELAY_FOR 0x4000, r0 > > - /* copy */ > - mov r0, #0 > - mov r4, r0 > - add r2, r0, #CONFIG_SYS_MONITOR_LEN > - mov r1, #0x10000000 > - mov r5, r1 > - > - 30: > - ldr r3, [r0], #4 > - str r3, [r1], #4 > - cmp r0, r2 > - bne 30b > - > /* invalidate I & D caches & BTB */ > mcr p15, 0, r0, c7, c7, 0 > CPWAIT r0 > @@ -241,19 +224,12 @@ reset: > mcr p15, 0, r0, c7, c10, 4 > CPWAIT r0 > > - /* move flash to 0x50000000 */ > + /* remove flash mirror at 0x00000000 */ > ldr r2, =IXP425_EXP_CFG0 > ldr r1, [r2] > bic r1, r1, #0x80000000 > str r1, [r2] > > - nop > - nop > - nop > - nop > - nop > - nop > - > /* invalidate I & Data TLB */ > mcr p15, 0, r0, c8, c7, 0 > CPWAIT r0 > @@ -269,7 +245,7 @@ reset: > orr r0,r0,#0x13 > msr cpsr,r0 > > -/* Set stackpointer in internal RAM to call board_init_f */ > +/* Set initial stackpointer in SDRAM to call board_init_f */ > call_board_init_f: > ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) > bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ > @@ -580,28 +556,3 @@ reset_endless: > > b reset_endless > > -#ifdef CONFIG_USE_IRQ > - > -.LC0: .word loops_per_jiffy > - > -/* > - * 0 <= r0 <= 2000 > - */ > -.globl __udelay > -__udelay: > - mov r2, #0x6800 > - orr r2, r2, #0x00db > - mul r0, r2, r0 > - ldr r2, .LC0 > - ldr r2, [r2] @ max = 0x0fffffff > - mov r0, r0, lsr #11 @ max = 0x00003fff > - mov r2, r2, lsr #11 @ max = 0x0003ffff > - mul r0, r2, r0 @ max = 2^32-1 > - movs r0, r0, lsr #6 > - > -delay_loop: > - subs r0, r0, #1 > - bne delay_loop > - mov pc, lr > - > -#endif /* CONFIG_USE_IRQ */ > diff --git a/arch/arm/cpu/ixp/timer.c b/arch/arm/cpu/ixp/timer.c > index edf341f..7a44a08 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,105 +34,94 @@ > > #include <common.h> > #include <asm/arch/ixp425.h> > +#include <asm/io.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 LATCH ((CLOCK_TICK_RATE + CONFIG_SYS_HZ/2) > / CONFIG_SYS_HZ) /* For divider */ +DECLARE_GLOBAL_DATA_PTR; > > /* > - * When interrupts are enabled, use timer 2 for time/delay generation... > + * The IXP42x time-stamp timer runs at 2*OSC_IN (66.666MHz when using a > + * 33.333MHz crystal). > */ > - > -static volatile ulong timestamp; > - > -static void timer_isr(void *data) > +static inline unsigned long long tick_to_time(unsigned long long tick) > { > - unsigned int *pTime = (unsigned int *)data; > - > - (*pTime)++; > - > - /* > - * Reset IRQ source > - */ > - *IXP425_OSST = IXP425_OSST_TIMER_2_PEND; > + tick *= CONFIG_SYS_HZ; > + do_div(tick, CONFIG_IXP425_TIMER_CLK); > + return tick; > } > > -ulong get_timer (ulong base) > +static inline unsigned long long time_to_tick(unsigned long long time) > { > - return timestamp - base; > + time *= CONFIG_IXP425_TIMER_CLK; > + do_div(time, CONFIG_SYS_HZ); > + return time; > } > > -void reset_timer (void) > +static inline unsigned long long us_to_tick(unsigned long long us) > { > - timestamp = 0; > + us = us * CONFIG_IXP425_TIMER_CLK + 999999; > + do_div(us, 1000000); > + return us; > } > > -int timer_init (void) > +unsigned long long get_ticks(void) > { > - /* install interrupt handler for timer */ > - irq_install_handler(IXP425_TIMER_2_IRQ, timer_isr, (void *)×tamp); > - > - /* setup the Timer counter value */ > - *IXP425_OSRT2 = (LATCH & ~IXP425_OST_RELOAD_MASK) | IXP425_OST_ENABLE; > + ulong now = *IXP425_OSTS_B; Aren't you missing an IO accessor here ? > + > + if (readl(IXP425_OSST) & IXP425_OSST_TIMER_TS_PEND) { > + /* rollover of timestamp timer register */ > + gd->timestamp += (0xFFFFFFFF - gd->lastinc) + now + 1; > + writel(IXP425_OSST_TIMER_TS_PEND, IXP425_OSST); > + } else { > + /* move stamp forward with absolut diff ticks */ > + gd->timestamp += (now - gd->lastinc); > + } > + gd->lastinc = now; > + return gd->timestamp; > +} > > - /* enable timer irq */ > - *IXP425_ICMR = (1 << IXP425_TIMER_2_IRQ); > > - return 0; > -} > -#else > -ulong get_timer (ulong base) > +void reset_timer_masked(void) > { > - return get_timer_masked () - base; > + /* capture current timestamp counter */ > + gd->lastinc = readl(IXP425_OSTS_B); > + /* start "advancing" time stamp from 0 */ > + gd->timestamp = 0; > } > > -void ixp425_udelay(unsigned long usec) > +void reset_timer(void) > { > - /* > - * 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; > - > - *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)); > + reset_timer_masked(); > } > > -void __udelay (unsigned long usec) > +ulong get_timer_masked(void) > { > - while (usec--) ixp425_udelay(1); > + return tick_to_time(get_ticks()); > } > > -static ulong reload_constant = 0xfffffff0; > - > -void reset_timer_masked (void) > +ulong get_timer(ulong base) > { > - ulong reload = reload_constant | IXP425_OST_ONE_SHOT | IXP425_OST_ENABLE; > + return get_timer_masked() - base; > +} > > - *IXP425_OSST = IXP425_OSST_TIMER_1_PEND; > - *IXP425_OSRT1 = reload; > +void set_timer(ulong t) > +{ > + gd->timestamp = time_to_tick(t); > } > > -ulong get_timer_masked (void) > +/* delay x useconds AND preserve advance timestamp value */ > +void __udelay(unsigned long usec) > { > - /* > - * 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); > + unsigned long long tmp; > + > + tmp = get_ticks() + us_to_tick(usec); > + > + while (get_ticks() < tmp) > + ; > } > > int timer_init(void) > { > + writel(IXP425_OSST_TIMER_TS_PEND, IXP425_OSST); > 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..5132607 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) This will eventually enjoy being converted to struct ixp_timer_regset { ... } goo. If you already did it in some further patch, sorry, I didn't get there yet ;-) > diff --git a/arch/arm/include/asm/global_data.h > b/arch/arm/include/asm/global_data.h index 2a84d27..c1a59f2 100644 > --- a/arch/arm/include/asm/global_data.h > +++ b/arch/arm/include/asm/global_data.h > @@ -64,6 +64,9 @@ typedef struct global_data { > unsigned long long timer_reset_value; > unsigned long lastinc; > #endif > +#ifdef CONFIG_IXP425 > + unsigned long timestamp; > +#endif > unsigned long relocaddr; /* Start address of U-Boot in RAM */ > phys_size_t ram_size; /* RAM size */ > unsigned long mon_len; /* monitor len */
Am 05/21/2011 01:58 AM, schrieb Marek Vasut: > >> -int timer_init (void) >> +unsigned long long get_ticks(void) >> { >> - /* install interrupt handler for timer */ >> - irq_install_handler(IXP425_TIMER_2_IRQ, timer_isr, (void *)×tamp); >> - >> - /* setup the Timer counter value */ >> - *IXP425_OSRT2 = (LATCH & ~IXP425_OST_RELOAD_MASK) | IXP425_OST_ENABLE; >> + ulong now = *IXP425_OSTS_B; > Aren't you missing an IO accessor here ? Oops - you are correct. >> diff --git a/arch/arm/include/asm/arch-ixp/ixp425.h >> b/arch/arm/include/asm/arch-ixp/ixp425.h index 2114437..5132607 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) > This will eventually enjoy being converted to struct ixp_timer_regset { ... } > goo. If you already did it in some further patch, sorry, I didn't get there yet > ;-) That would probably require a major rework of all the Intel access/NPE library code - this is not something I want to touch now. Most of these defines are used inside the Intel code, so cleaning up only outside of that area would not improve the code much. cu Michael
On Sunday, May 22, 2011 09:15:03 PM Michael Schwingen wrote: > Am 05/21/2011 01:58 AM, schrieb Marek Vasut: > >> -int timer_init (void) > >> +unsigned long long get_ticks(void) > >> > >> { > >> > >> - /* install interrupt handler for timer */ > >> - irq_install_handler(IXP425_TIMER_2_IRQ, timer_isr, (void > >> *)×tamp); - > >> - /* setup the Timer counter value */ > >> - *IXP425_OSRT2 = (LATCH & ~IXP425_OST_RELOAD_MASK) | IXP425_OST_ENABLE; > >> + ulong now = *IXP425_OSTS_B; > > > > Aren't you missing an IO accessor here ? > > Oops - you are correct. > > >> diff --git a/arch/arm/include/asm/arch-ixp/ixp425.h > >> b/arch/arm/include/asm/arch-ixp/ixp425.h index 2114437..5132607 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) > > > > This will eventually enjoy being converted to struct ixp_timer_regset { > > ... } goo. If you already did it in some further patch, sorry, I didn't > > get there yet ;-) > > That would probably require a major rework of all the Intel access/NPE > library code - this is not something I want to touch now. > Most of these defines are used inside the Intel code, so cleaning up > only outside of that area would not improve the code much. It'd be cool to have this done in next cycle ;-) > > cu > Michael
diff --git a/arch/arm/cpu/ixp/cpu.c b/arch/arm/cpu/ixp/cpu.c index ce275e5..942845d 100644 --- a/arch/arm/cpu/ixp/cpu.c +++ b/arch/arm/cpu/ixp/cpu.c @@ -36,8 +36,6 @@ #include <asm/arch/ixp425.h> #include <asm/system.h> -ulong loops_per_jiffy; - static void cache_flush(void); #if defined(CONFIG_DISPLAY_CPUINFO) @@ -51,17 +49,14 @@ int print_cpuinfo (void) puts("CPU: Intel IXP425 at "); switch ((id & 0x000003f0) >> 4) { case 0x1c: - loops_per_jiffy = 887467; speed = 533; break; case 0x1d: - loops_per_jiffy = 666016; speed = 400; break; case 0x1f: - loops_per_jiffy = 442901; speed = 266; break; } diff --git a/arch/arm/cpu/ixp/start.S b/arch/arm/cpu/ixp/start.S index 561c1f4..faa9a8f 100644 --- a/arch/arm/cpu/ixp/start.S +++ b/arch/arm/cpu/ixp/start.S @@ -65,7 +65,8 @@ .endm .globl _start -_start: b reset +_start: + ldr pc, _reset ldr pc, _undefined_instruction ldr pc, _software_interrupt ldr pc, _prefetch_abort @@ -74,6 +75,7 @@ _start: b reset ldr pc, _irq ldr pc, _fiq +_reset: .word reset _undefined_instruction: .word undefined_instruction _software_interrupt: .word software_interrupt _prefetch_abort: .word prefetch_abort @@ -167,12 +169,6 @@ reset: str r1, [r2] /* make sure flash is visible at 0 */ -#if 0 - ldr r2, =IXP425_EXP_CFG0 - ldr r1, [r2] - orr r1, r1, #0x80000000 - str r1, [r2] -#endif mov r1, #CONFIG_SYS_SDR_CONFIG ldr r2, =IXP425_SDR_CONFIG str r1, [r2] @@ -216,19 +212,6 @@ reset: str r1, [r4] DELAY_FOR 0x4000, r0 - /* copy */ - mov r0, #0 - mov r4, r0 - add r2, r0, #CONFIG_SYS_MONITOR_LEN - mov r1, #0x10000000 - mov r5, r1 - - 30: - ldr r3, [r0], #4 - str r3, [r1], #4 - cmp r0, r2 - bne 30b - /* invalidate I & D caches & BTB */ mcr p15, 0, r0, c7, c7, 0 CPWAIT r0 @@ -241,19 +224,12 @@ reset: mcr p15, 0, r0, c7, c10, 4 CPWAIT r0 - /* move flash to 0x50000000 */ + /* remove flash mirror at 0x00000000 */ ldr r2, =IXP425_EXP_CFG0 ldr r1, [r2] bic r1, r1, #0x80000000 str r1, [r2] - nop - nop - nop - nop - nop - nop - /* invalidate I & Data TLB */ mcr p15, 0, r0, c8, c7, 0 CPWAIT r0 @@ -269,7 +245,7 @@ reset: orr r0,r0,#0x13 msr cpsr,r0 -/* Set stackpointer in internal RAM to call board_init_f */ +/* Set initial stackpointer in SDRAM to call board_init_f */ call_board_init_f: ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ @@ -580,28 +556,3 @@ reset_endless: b reset_endless -#ifdef CONFIG_USE_IRQ - -.LC0: .word loops_per_jiffy - -/* - * 0 <= r0 <= 2000 - */ -.globl __udelay -__udelay: - mov r2, #0x6800 - orr r2, r2, #0x00db - mul r0, r2, r0 - ldr r2, .LC0 - ldr r2, [r2] @ max = 0x0fffffff - mov r0, r0, lsr #11 @ max = 0x00003fff - mov r2, r2, lsr #11 @ max = 0x0003ffff - mul r0, r2, r0 @ max = 2^32-1 - movs r0, r0, lsr #6 - -delay_loop: - subs r0, r0, #1 - bne delay_loop - mov pc, lr - -#endif /* CONFIG_USE_IRQ */ diff --git a/arch/arm/cpu/ixp/timer.c b/arch/arm/cpu/ixp/timer.c index edf341f..7a44a08 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,105 +34,94 @@ #include <common.h> #include <asm/arch/ixp425.h> +#include <asm/io.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 LATCH ((CLOCK_TICK_RATE + CONFIG_SYS_HZ/2) / CONFIG_SYS_HZ) /* For divider */ +DECLARE_GLOBAL_DATA_PTR; /* - * When interrupts are enabled, use timer 2 for time/delay generation... + * The IXP42x time-stamp timer runs at 2*OSC_IN (66.666MHz when using a + * 33.333MHz crystal). */ - -static volatile ulong timestamp; - -static void timer_isr(void *data) +static inline unsigned long long tick_to_time(unsigned long long tick) { - unsigned int *pTime = (unsigned int *)data; - - (*pTime)++; - - /* - * Reset IRQ source - */ - *IXP425_OSST = IXP425_OSST_TIMER_2_PEND; + tick *= CONFIG_SYS_HZ; + do_div(tick, CONFIG_IXP425_TIMER_CLK); + return tick; } -ulong get_timer (ulong base) +static inline unsigned long long time_to_tick(unsigned long long time) { - return timestamp - base; + time *= CONFIG_IXP425_TIMER_CLK; + do_div(time, CONFIG_SYS_HZ); + return time; } -void reset_timer (void) +static inline unsigned long long us_to_tick(unsigned long long us) { - timestamp = 0; + us = us * CONFIG_IXP425_TIMER_CLK + 999999; + do_div(us, 1000000); + return us; } -int timer_init (void) +unsigned long long get_ticks(void) { - /* install interrupt handler for timer */ - irq_install_handler(IXP425_TIMER_2_IRQ, timer_isr, (void *)×tamp); - - /* setup the Timer counter value */ - *IXP425_OSRT2 = (LATCH & ~IXP425_OST_RELOAD_MASK) | IXP425_OST_ENABLE; + ulong now = *IXP425_OSTS_B; + + if (readl(IXP425_OSST) & IXP425_OSST_TIMER_TS_PEND) { + /* rollover of timestamp timer register */ + gd->timestamp += (0xFFFFFFFF - gd->lastinc) + now + 1; + writel(IXP425_OSST_TIMER_TS_PEND, IXP425_OSST); + } else { + /* move stamp forward with absolut diff ticks */ + gd->timestamp += (now - gd->lastinc); + } + gd->lastinc = now; + return gd->timestamp; +} - /* enable timer irq */ - *IXP425_ICMR = (1 << IXP425_TIMER_2_IRQ); - return 0; -} -#else -ulong get_timer (ulong base) +void reset_timer_masked(void) { - return get_timer_masked () - base; + /* capture current timestamp counter */ + gd->lastinc = readl(IXP425_OSTS_B); + /* start "advancing" time stamp from 0 */ + gd->timestamp = 0; } -void ixp425_udelay(unsigned long usec) +void reset_timer(void) { - /* - * 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; - - *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)); + reset_timer_masked(); } -void __udelay (unsigned long usec) +ulong get_timer_masked(void) { - while (usec--) ixp425_udelay(1); + return tick_to_time(get_ticks()); } -static ulong reload_constant = 0xfffffff0; - -void reset_timer_masked (void) +ulong get_timer(ulong base) { - ulong reload = reload_constant | IXP425_OST_ONE_SHOT | IXP425_OST_ENABLE; + return get_timer_masked() - base; +} - *IXP425_OSST = IXP425_OSST_TIMER_1_PEND; - *IXP425_OSRT1 = reload; +void set_timer(ulong t) +{ + gd->timestamp = time_to_tick(t); } -ulong get_timer_masked (void) +/* delay x useconds AND preserve advance timestamp value */ +void __udelay(unsigned long usec) { - /* - * 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); + unsigned long long tmp; + + tmp = get_ticks() + us_to_tick(usec); + + while (get_ticks() < tmp) + ; } int timer_init(void) { + writel(IXP425_OSST_TIMER_TS_PEND, IXP425_OSST); 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..5132607 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/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h index 2a84d27..c1a59f2 100644 --- a/arch/arm/include/asm/global_data.h +++ b/arch/arm/include/asm/global_data.h @@ -64,6 +64,9 @@ typedef struct global_data { unsigned long long timer_reset_value; unsigned long lastinc; #endif +#ifdef CONFIG_IXP425 + unsigned long timestamp; +#endif unsigned long relocaddr; /* Start address of U-Boot in RAM */ phys_size_t ram_size; /* RAM size */ unsigned long mon_len; /* monitor len */
- jump to real flash location after reset before turning off flash mirror - fix timer system to use HZ == 1000, remove broken interrupt-based code Signed-off-by: Michael Schwingen <michael@schwingen.org> --- Changes for V2: - fix patch description Changes for V3: - use I/O accessors - move timestamp variable from BSS to global data - coding style fixes Changes for V4: - add changelog arch/arm/cpu/ixp/cpu.c | 5 -- arch/arm/cpu/ixp/start.S | 59 ++-------------- arch/arm/cpu/ixp/timer.c | 124 +++++++++++++++----------------- arch/arm/include/asm/arch-ixp/ixp425.h | 5 +- arch/arm/include/asm/global_data.h | 3 + 5 files changed, 68 insertions(+), 128 deletions(-)