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 <mich...@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, mich...@schwingen.org > + * > * (C) Copyright 2006 > * Stefan Roese, DENX Software Engineering, s...@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 */ _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot