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>
master
Michael Schwingen 13 years ago committed by Albert ARIBAUD
parent 009e464802
commit ce04bb41a6
  1. 5
      arch/arm/cpu/ixp/cpu.c
  2. 59
      arch/arm/cpu/ixp/start.S
  3. 124
      arch/arm/cpu/ixp/timer.c
  4. 5
      arch/arm/include/asm/arch-ixp/ixp425.h
  5. 3
      arch/arm/include/asm/global_data.h

@ -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;
}

@ -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 */

@ -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 *)&timestamp);
/* setup the Timer counter value */
*IXP425_OSRT2 = (LATCH & ~IXP425_OST_RELOAD_MASK) | IXP425_OST_ENABLE;
ulong now = readl(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

@ -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)

@ -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 */

Loading…
Cancel
Save