Generic udelay() with watchdog support

According to the PPC reference implementation the udelay() function is
responsible for resetting the watchdog timer as frequently as needed.
Most other architectures do not meet that requirement, so long-running
operations might result in a watchdog reset.

This patch adds a generic udelay() function which takes care of
resetting the watchdog before calling an architecture-specific
__udelay().

Signed-off-by: Ingo van Lil <inguin@gmx.de>
This commit is contained in:
Ingo van Lil 2009-11-24 14:09:21 +01:00 committed by Wolfgang Denk
parent 1c409bc710
commit 3eb90bad65
47 changed files with 98 additions and 62 deletions

View File

@ -124,7 +124,7 @@ void set_timer (ulong ticks)
}
/* delay usec useconds */
void udelay (unsigned long usec)
void __udelay (unsigned long usec)
{
ulong tmo, tmp;

View File

@ -72,7 +72,7 @@ static long fixed_sdram(void)
* Erratum DDR3 requires a 50ms delay after clearing DDRCDR[DDR_cfg],
* or the DDR2 controller may fail to initialize correctly.
*/
udelay(50000);
__udelay(50000);
im->ddr.csbnds[0].csbnds = (msize - 1) >> 24;
im->ddr.cs_config[0] = CONFIG_SYS_DDR_CONFIG;

View File

@ -152,7 +152,7 @@ void set_timer (ulong t)
}
/* delay x useconds AND perserve advance timstamp value */
void udelay (unsigned long usec)
void __udelay (unsigned long usec)
{
unsigned long long tmp;
ulong tmo;

View File

@ -74,7 +74,7 @@ void set_timer (ulong t)
}
/* delay x useconds AND perserve advance timstamp value */
void udelay (unsigned long usec)
void __udelay (unsigned long usec)
{
ulong tmo, tmp;

View File

@ -164,7 +164,7 @@ void set_timer(ulong t)
timestamp = t * (timer_load_val / (100 * CONFIG_SYS_HZ));
}
void udelay(unsigned long usec)
void __udelay(unsigned long usec)
{
unsigned long long tmp;
ulong tmo;

View File

@ -224,7 +224,7 @@ void set_timer (ulong t)
timestamp = t;
}
void udelay (unsigned long usec)
void __udelay (unsigned long usec)
{
ulong tmo;
@ -296,7 +296,7 @@ ulong get_timer (ulong base)
return timestamp - base;
}
void udelay (unsigned long usec)
void __udelay (unsigned long usec)
{
u32 ticks;

View File

@ -87,7 +87,7 @@ void set_timer (ulong t)
timestamp = t;
}
void udelay (unsigned long usec)
void __udelay (unsigned long usec)
{
udelay_masked(usec);
}

View File

@ -89,7 +89,7 @@ void udelay_masked (unsigned long usec)
} while (diff >= 0);
}
void udelay (unsigned long usec)
void __udelay (unsigned long usec)
{
udelay_masked(usec);
}

View File

@ -81,7 +81,7 @@ void set_timer(ulong t)
timer_ticks = t;
}
void udelay(ulong usec)
void __udelay(ulong usec)
{
ulong start = get_timer_masked();
ulong end;

View File

@ -99,7 +99,7 @@ void set_timer(ulong t)
timestamp = t;
}
void udelay(unsigned long usec)
void __udelay (unsigned long usec)
{
ulong tmo;
ulong start = get_ticks();

View File

@ -81,7 +81,7 @@ void set_timer (ulong t)
}
/* delay x useconds AND preserve advance timestamp value */
void udelay (unsigned long usec)
void __udelay (unsigned long usec)
{
int32_t tmo = usec * (TIMER_CLOCK / 1000) / 1000;
uint32_t now, last = __raw_readl(CONFIG_SYS_TIMERBASE + READ_TIM);

View File

@ -105,7 +105,7 @@ ulong get_timer_masked(void)
return tick_to_time(get_ticks());
}
void udelay(unsigned long usec)
void __udelay(unsigned long usec)
{
unsigned long long tmp;
ulong tmo;

View File

@ -112,7 +112,7 @@ void set_timer(ulong t)
timestamp = t;
}
void udelay(unsigned long usec)
void __udelay(unsigned long usec)
{
ulong tmo;
ulong endtime;

View File

@ -125,7 +125,7 @@ void set_timer(ulong t)
timestamp = t;
}
void udelay(unsigned long usec)
void __udelay(unsigned long usec)
{
uint current;
ulong delayticks;

View File

@ -177,7 +177,7 @@ void set_timer (ulong t)
}
/* delay x useconds AND preserve advance timstamp value */
void udelay (unsigned long usec)
void __udelay (unsigned long usec)
{
unsigned long long tmp;
ulong tmo;

View File

@ -59,7 +59,7 @@ ulong get_timer(ulong base)
}
/* Delay x useconds */
void udelay(unsigned long usec)
void __udelay(unsigned long usec)
{
ulong ini, end;

View File

@ -80,7 +80,7 @@ void set_timer (ulong t)
}
/* delay x useconds AND perserve advance timstamp value */
void udelay (unsigned long usec)
void __udelay (unsigned long usec)
{
ulong tmo, tmp;

View File

@ -109,7 +109,7 @@ void set_timer (ulong t)
}
/* delay x useconds AND perserve advance timstamp value */
void udelay (unsigned long usec)
void __udelay (unsigned long usec)
{
ulong tmo, tmp;

View File

@ -82,7 +82,7 @@ void set_timer(ulong t)
}
/* delay x useconds */
void udelay(unsigned long usec)
void __udelay(unsigned long usec)
{
long tmo = usec * (TIMER_CLOCK / 1000) / 1000;
unsigned long now, last = readl(&timer_base->tcrr);

View File

@ -115,7 +115,7 @@ void set_timer(unsigned long t)
}
/* delay x useconds */
void udelay(unsigned long usec)
void __udelay(unsigned long usec)
{
unsigned long tmo, tmp;

View File

@ -96,7 +96,7 @@ void set_timer(unsigned long t)
/*
* For short delays only. It will overflow after a few seconds.
*/
void udelay(unsigned long usec)
void __udelay(unsigned long usec)
{
unsigned long cycles;
unsigned long base;

View File

@ -64,7 +64,7 @@ int disable_interrupts(void)
return 1;
}
void udelay(unsigned long usec)
void __udelay(unsigned long usec)
{
unsigned long delay, start, stop;
unsigned long cclk;

View File

@ -68,7 +68,7 @@ int timer_init(void)
return 0;
}
void udelay(unsigned long usec)
void __udelay(unsigned long usec)
{
int m = 0;
long u;

View File

@ -505,8 +505,8 @@ reset_endless:
/*
* 0 <= r0 <= 2000
*/
.globl udelay
udelay:
.globl __udelay
__udelay:
mov r2, #0x6800
orr r2, r2, #0x00db
mul r0, r2, r0

View File

@ -99,7 +99,7 @@ void ixp425_udelay(unsigned long usec)
while (!(*IXP425_OSST & IXP425_OSST_TIMER_1_PEND));
}
void udelay (unsigned long usec)
void __udelay (unsigned long usec)
{
while (usec--) ixp425_udelay(1);
}

View File

@ -90,7 +90,7 @@ void set_timer (ulong t)
timestamp = t;
}
void udelay (unsigned long usec)
void __udelay (unsigned long usec)
{
ulong tmo,tmp;

View File

@ -40,7 +40,7 @@ static ulong timestamp;
#endif
extern void dtimer_intr_setup(void);
void udelay(unsigned long usec)
void __udelay(unsigned long usec)
{
volatile slt_t *timerp = (slt_t *) (CONFIG_SYS_UDELAY_BASE);
u32 now, freq;

View File

@ -78,7 +78,7 @@ void set_timer (ulong t)
/* nop */
}
void udelay (unsigned long usec)
void __udelay (unsigned long usec)
{
udelay_masked (usec);
}

View File

@ -75,7 +75,7 @@ void set_timer (ulong t)
timestamp = t;
}
void udelay (unsigned long usec)
void __udelay (unsigned long usec)
{
ulong tmo;

View File

@ -49,7 +49,7 @@ void set_timer (ulong t)
/* nop */
}
void udelay (unsigned long usec)
void __udelay (unsigned long usec)
{
udelay_masked (usec);
}

View File

@ -44,6 +44,7 @@ EXT_COBJ_FILES-$(CONFIG_API) += lib_generic/crc32.o
EXT_COBJ_FILES-$(CONFIG_API) += lib_generic/ctype.o
EXT_COBJ_FILES-$(CONFIG_API) += lib_generic/div64.o
EXT_COBJ_FILES-$(CONFIG_API) += lib_generic/string.o
EXT_COBJ_FILES-$(CONFIG_API) += lib_generic/time.o
EXT_COBJ_FILES-$(CONFIG_API) += lib_generic/vsprintf.o
ifeq ($(ARCH),ppc)
EXT_SOBJ_FILES-$(CONFIG_API) += lib_ppc/ppcstring.o

View File

@ -74,7 +74,7 @@ void putc (const char c)
ub_putc(c);
}
void udelay(unsigned long usec)
void __udelay(unsigned long usec)
{
ub_udelay(usec);
}

View File

@ -47,7 +47,7 @@ extern __inline__ void __delay(unsigned long loops)
* first constant multiplications gets optimized away if the delay is
* a constant)
*/
extern __inline__ void udelay(unsigned long usecs)
extern __inline__ void __udelay(unsigned long usecs)
{
__delay(usecs);
}

View File

@ -607,11 +607,14 @@ unsigned long long get_ticks(void);
void wait_ticks (unsigned long);
/* lib_$(ARCH)/time.c */
void udelay (unsigned long);
void __udelay (unsigned long);
ulong usec2ticks (unsigned long usec);
ulong ticks2usec (unsigned long ticks);
int init_timebase (void);
/* lib_generic/time.c */
void udelay (unsigned long);
/* lib_generic/vsprintf.c */
ulong simple_strtoul(const char *cp,char **endp,unsigned int base);
#ifdef CONFIG_SYS_64BIT_VSPRINTF

View File

@ -16,7 +16,7 @@ void install_hdlr(int, interrupt_handler_t*, void*);
void free_hdlr(int);
void *malloc(size_t);
void free(void*);
void udelay(unsigned long);
void __udelay(unsigned long);
unsigned long get_timer(unsigned long);
void vprintf(const char *, va_list);
void do_reset (void);

View File

@ -44,6 +44,7 @@ COBJS-y += sha1.o
COBJS-$(CONFIG_SHA256) += sha256.o
COBJS-y += string.o
COBJS-y += strmhz.o
COBJS-y += time.o
COBJS-y += vsprintf.o
COBJS-y += zlib.o
COBJS-$(CONFIG_RBTREE) += rbtree.o

43
lib_generic/time.c Normal file
View File

@ -0,0 +1,43 @@
/*
* (C) Copyright 2000-2009
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <watchdog.h>
#ifndef CONFIG_WD_PERIOD
# define CONFIG_WD_PERIOD (10 * 1000 * 1000) /* 10 seconds default*/
#endif
/* ------------------------------------------------------------------------- */
void udelay(unsigned long usec)
{
ulong kv;
do {
WATCHDOG_RESET();
kv = usec > CONFIG_WD_PERIOD ? CONFIG_WD_PERIOD : usec;
__udelay (kv);
usec -= kv;
} while(usec);
}

View File

@ -71,7 +71,7 @@ static u16 read_pit(void)
}
/* this is not very exact */
void udelay (unsigned long usec)
void __udelay (unsigned long usec)
{
int counter;
int wraps;

View File

@ -47,7 +47,7 @@ static volatile ulong timestamp = 0;
#endif
extern void dtimer_intr_setup(void);
void udelay(unsigned long usec)
void __udelay(unsigned long usec)
{
volatile dtmr_t *timerp = (dtmr_t *) (CONFIG_SYS_UDELAY_BASE);
uint start, now, tmp;
@ -139,7 +139,7 @@ void set_timer(ulong t)
static unsigned short lastinc;
void udelay(unsigned long usec)
void __udelay(unsigned long usec)
{
volatile pit_t *timerp = (pit_t *) (CONFIG_SYS_UDELAY_BASE);
uint tmp;

View File

@ -27,14 +27,14 @@
#include <common.h>
#ifdef CONFIG_SYS_TIMER_0
void udelay (unsigned long usec)
void __udelay (unsigned long usec)
{
int i;
i = get_timer (0);
while ((get_timer (0) - i) < (usec / 1000)) ;
}
#else
void udelay (unsigned long usec)
void __udelay (unsigned long usec)
{
unsigned int i;
for (i = 0; i < (usec * CONFIG_XILINX_CLOCK_FREQ / 10000000); i++);

View File

@ -70,7 +70,7 @@ void set_timer(ulong t)
write_c0_compare(read_c0_count() + CYCLES_PER_JIFFY);
}
void udelay(unsigned long usec)
void __udelay(unsigned long usec)
{
unsigned int tmo;

View File

@ -27,13 +27,12 @@
extern void dly_clks( unsigned long ticks );
void udelay(unsigned long usec)
void __udelay(unsigned long usec)
{
/* The Nios core doesn't have a timebase, so we do our
* best for now and call a low-level loop that counts
* cpu clocks.
*/
unsigned long cnt = (CONFIG_SYS_CLK_FREQ/1000000) * usec;
WATCHDOG_RESET (); /* trigger watchdog if needed */
dly_clks (cnt);
}

View File

@ -27,13 +27,12 @@
extern void dly_clks( unsigned long ticks );
void udelay(unsigned long usec)
void __udelay(unsigned long usec)
{
/* The Nios core doesn't have a timebase, so we do our
* best for now and call a low-level loop that counts
* cpu clocks.
*/
unsigned long cnt = (CONFIG_SYS_CLK_FREQ/1000000) * usec;
WATCHDOG_RESET (); /* trigger watchdog if needed */
dly_clks (cnt);
}

View File

@ -23,10 +23,6 @@
#include <common.h>
#ifndef CONFIG_WD_PERIOD
# define CONFIG_WD_PERIOD (10 * 1000 * 1000) /* 10 seconds default*/
#endif
/* ------------------------------------------------------------------------- */
/*
@ -54,16 +50,10 @@ unsigned long usec2ticks(unsigned long usec)
* microseconds to wait) into a number of time base ticks; then we
* watch the time base until it has incremented by that amount.
*/
void udelay(unsigned long usec)
void __udelay(unsigned long usec)
{
ulong ticks, kv;
do {
kv = usec > CONFIG_WD_PERIOD ? CONFIG_WD_PERIOD : usec;
ticks = usec2ticks (kv);
wait_ticks (ticks);
usec -= kv;
} while(usec);
ulong ticks = usec2ticks (usec);
wait_ticks (ticks);
}
/* ------------------------------------------------------------------------- */

View File

@ -105,7 +105,7 @@ unsigned long long get_ticks (void)
return 0 - readl(TCNT0);
}
void udelay (unsigned long usec)
void __udelay (unsigned long usec)
{
unsigned long long tmp;
ulong tmo;

View File

@ -103,7 +103,7 @@ void reset_timer(void)
cmt_timer_start(0);
}
void udelay(unsigned long usec)
void __udelay(unsigned long usec)
{
unsigned long end = get_usec() + usec;

View File

@ -53,7 +53,7 @@ unsigned long usec2ticks(unsigned long usec)
* microseconds to wait) into a number of time base ticks; then we
* watch the time base until it has incremented by that amount.
*/
void udelay(unsigned long usec)
void __udelay(unsigned long usec)
{
ulong ticks = usec2ticks(usec);