diff options
Diffstat (limited to 'arch/arm/cpu')
| -rw-r--r-- | arch/arm/cpu/ixp/cpu.c | 5 | ||||
| -rw-r--r-- | arch/arm/cpu/ixp/start.S | 59 | ||||
| -rw-r--r-- | arch/arm/cpu/ixp/timer.c | 122 | 
3 files changed, 62 insertions, 124 deletions
| diff --git a/arch/arm/cpu/ixp/cpu.c b/arch/arm/cpu/ixp/cpu.c index ce275e5f3..942845d54 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 561c1f479..faa9a8ff9 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 edf341ff9..9f3ea42ec 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); +	ulong now = readl(IXP425_OSTS_B); -	/* setup the Timer counter value */ -	*IXP425_OSRT2 = (LATCH & ~IXP425_OST_RELOAD_MASK) | IXP425_OST_ENABLE; +	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 |