Fix IXP code to work after relocation was added

- 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>
This commit is contained in:
Michael Schwingen 2011-05-23 00:00:00 +02:00 committed by Albert ARIBAUD
parent 009e464802
commit ce04bb41a6
5 changed files with 82 additions and 142 deletions

View File

@ -36,8 +36,6 @@
#include <asm/arch/ixp425.h> #include <asm/arch/ixp425.h>
#include <asm/system.h> #include <asm/system.h>
ulong loops_per_jiffy;
static void cache_flush(void); static void cache_flush(void);
#if defined(CONFIG_DISPLAY_CPUINFO) #if defined(CONFIG_DISPLAY_CPUINFO)
@ -51,17 +49,14 @@ int print_cpuinfo (void)
puts("CPU: Intel IXP425 at "); puts("CPU: Intel IXP425 at ");
switch ((id & 0x000003f0) >> 4) { switch ((id & 0x000003f0) >> 4) {
case 0x1c: case 0x1c:
loops_per_jiffy = 887467;
speed = 533; speed = 533;
break; break;
case 0x1d: case 0x1d:
loops_per_jiffy = 666016;
speed = 400; speed = 400;
break; break;
case 0x1f: case 0x1f:
loops_per_jiffy = 442901;
speed = 266; speed = 266;
break; break;
} }

View File

@ -65,7 +65,8 @@
.endm .endm
.globl _start .globl _start
_start: b reset _start:
ldr pc, _reset
ldr pc, _undefined_instruction ldr pc, _undefined_instruction
ldr pc, _software_interrupt ldr pc, _software_interrupt
ldr pc, _prefetch_abort ldr pc, _prefetch_abort
@ -74,6 +75,7 @@ _start: b reset
ldr pc, _irq ldr pc, _irq
ldr pc, _fiq ldr pc, _fiq
_reset: .word reset
_undefined_instruction: .word undefined_instruction _undefined_instruction: .word undefined_instruction
_software_interrupt: .word software_interrupt _software_interrupt: .word software_interrupt
_prefetch_abort: .word prefetch_abort _prefetch_abort: .word prefetch_abort
@ -167,12 +169,6 @@ reset:
str r1, [r2] str r1, [r2]
/* make sure flash is visible at 0 */ /* 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 mov r1, #CONFIG_SYS_SDR_CONFIG
ldr r2, =IXP425_SDR_CONFIG ldr r2, =IXP425_SDR_CONFIG
str r1, [r2] str r1, [r2]
@ -216,19 +212,6 @@ reset:
str r1, [r4] str r1, [r4]
DELAY_FOR 0x4000, r0 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 */ /* invalidate I & D caches & BTB */
mcr p15, 0, r0, c7, c7, 0 mcr p15, 0, r0, c7, c7, 0
CPWAIT r0 CPWAIT r0
@ -241,19 +224,12 @@ reset:
mcr p15, 0, r0, c7, c10, 4 mcr p15, 0, r0, c7, c10, 4
CPWAIT r0 CPWAIT r0
/* move flash to 0x50000000 */ /* remove flash mirror at 0x00000000 */
ldr r2, =IXP425_EXP_CFG0 ldr r2, =IXP425_EXP_CFG0
ldr r1, [r2] ldr r1, [r2]
bic r1, r1, #0x80000000 bic r1, r1, #0x80000000
str r1, [r2] str r1, [r2]
nop
nop
nop
nop
nop
nop
/* invalidate I & Data TLB */ /* invalidate I & Data TLB */
mcr p15, 0, r0, c8, c7, 0 mcr p15, 0, r0, c8, c7, 0
CPWAIT r0 CPWAIT r0
@ -269,7 +245,7 @@ reset:
orr r0,r0,#0x13 orr r0,r0,#0x13
msr cpsr,r0 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: call_board_init_f:
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
@ -580,28 +556,3 @@ reset_endless:
b 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 */

View File

@ -1,4 +1,7 @@
/* /*
* (C) Copyright 2010
* Michael Schwingen, michael@schwingen.org
*
* (C) Copyright 2006 * (C) Copyright 2006
* Stefan Roese, DENX Software Engineering, sr@denx.de. * Stefan Roese, DENX Software Engineering, sr@denx.de.
* *
@ -31,105 +34,94 @@
#include <common.h> #include <common.h>
#include <asm/arch/ixp425.h> #include <asm/arch/ixp425.h>
#include <asm/io.h>
#include <div64.h>
#ifdef CONFIG_TIMER_IRQ DECLARE_GLOBAL_DATA_PTR;
#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 */
/* /*
* 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 inline unsigned long long tick_to_time(unsigned long long tick)
static volatile ulong timestamp;
static void timer_isr(void *data)
{ {
unsigned int *pTime = (unsigned int *)data; tick *= CONFIG_SYS_HZ;
do_div(tick, CONFIG_IXP425_TIMER_CLK);
(*pTime)++; return tick;
/*
* Reset IRQ source
*/
*IXP425_OSST = IXP425_OSST_TIMER_2_PEND;
} }
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 */ ulong now = readl(IXP425_OSTS_B);
irq_install_handler(IXP425_TIMER_2_IRQ, timer_isr, (void *)&timestamp);
/* setup the Timer counter value */ if (readl(IXP425_OSST) & IXP425_OSST_TIMER_TS_PEND) {
*IXP425_OSRT2 = (LATCH & ~IXP425_OST_RELOAD_MASK) | IXP425_OST_ENABLE; /* rollover of timestamp timer register */
gd->timestamp += (0xFFFFFFFF - gd->lastinc) + now + 1;
/* enable timer irq */ writel(IXP425_OSST_TIMER_TS_PEND, IXP425_OSST);
*IXP425_ICMR = (1 << IXP425_TIMER_2_IRQ); } else {
/* move stamp forward with absolut diff ticks */
return 0; gd->timestamp += (now - gd->lastinc);
}
#else
ulong get_timer (ulong base)
{
return get_timer_masked () - base;
}
void ixp425_udelay(unsigned long usec)
{
/*
* 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));
}
void __udelay (unsigned long usec)
{
while (usec--) ixp425_udelay(1);
}
static ulong reload_constant = 0xfffffff0;
void reset_timer_masked (void)
{
ulong reload = reload_constant | IXP425_OST_ONE_SHOT | IXP425_OST_ENABLE;
*IXP425_OSST = IXP425_OSST_TIMER_1_PEND;
*IXP425_OSRT1 = reload;
}
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); gd->lastinc = now;
return gd->timestamp;
}
void reset_timer_masked(void)
{
/* capture current timestamp counter */
gd->lastinc = readl(IXP425_OSTS_B);
/* start "advancing" time stamp from 0 */
gd->timestamp = 0;
}
void reset_timer(void)
{
reset_timer_masked();
}
ulong get_timer_masked(void)
{
return tick_to_time(get_ticks());
}
ulong get_timer(ulong base)
{
return get_timer_masked() - base;
}
void set_timer(ulong t)
{
gd->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) int timer_init(void)
{ {
writel(IXP425_OSST_TIMER_TS_PEND, IXP425_OSST);
return 0; return 0;
} }
#endif

View File

@ -391,9 +391,8 @@
#define IXP425_TIMER_REG(x) (IXP425_TIMER_BASE_PHYS+(x)) #define IXP425_TIMER_REG(x) (IXP425_TIMER_BASE_PHYS+(x))
#endif #endif
#if 0 /* test-only: also defined in npe/include/... */ /* _B to avoid collision: also defined in npe/include/... */
#define IXP425_OSTS IXP425_TIMER_REG(IXP425_OSTS_OFFSET) #define IXP425_OSTS_B IXP425_TIMER_REG(IXP425_OSTS_OFFSET)
#endif
#define IXP425_OST1 IXP425_TIMER_REG(IXP425_OST1_OFFSET) #define IXP425_OST1 IXP425_TIMER_REG(IXP425_OST1_OFFSET)
#define IXP425_OSRT1 IXP425_TIMER_REG(IXP425_OSRT1_OFFSET) #define IXP425_OSRT1 IXP425_TIMER_REG(IXP425_OSRT1_OFFSET)
#define IXP425_OST2 IXP425_TIMER_REG(IXP425_OST2_OFFSET) #define IXP425_OST2 IXP425_TIMER_REG(IXP425_OST2_OFFSET)

View File

@ -63,6 +63,9 @@ typedef struct global_data {
unsigned long tbu; unsigned long tbu;
unsigned long long timer_reset_value; unsigned long long timer_reset_value;
unsigned long lastinc; unsigned long lastinc;
#endif
#ifdef CONFIG_IXP425
unsigned long timestamp;
#endif #endif
unsigned long relocaddr; /* Start address of U-Boot in RAM */ unsigned long relocaddr; /* Start address of U-Boot in RAM */
phys_size_t ram_size; /* RAM size */ phys_size_t ram_size; /* RAM size */