as3525*: make udelay() be a simple busy loop
it achieves all the requirements, work fine on c200v2, and is much simpler git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26933 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
955bb4004f
commit
7a9033179f
3 changed files with 22 additions and 64 deletions
|
@ -326,6 +326,26 @@ int system_memory_guard(int newmode)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void udelay(unsigned short usecs)
|
||||
{
|
||||
unsigned cycles_per_usec;
|
||||
unsigned delay;
|
||||
|
||||
if (cpu_frequency == CPUFREQ_MAX) {
|
||||
cycles_per_usec = (CPUFREQ_MAX + 999999) / 1000000;
|
||||
} else {
|
||||
cycles_per_usec = (CPUFREQ_NORMAL + 999999) / 1000000;
|
||||
}
|
||||
|
||||
delay = (usecs * cycles_per_usec + 3) / 4;
|
||||
|
||||
asm volatile(
|
||||
"1: subs %0, %0, #1 \n" /* 1 cycle */
|
||||
" bne 1b \n" /* 3 cycles */
|
||||
: : "r"(delay)
|
||||
);
|
||||
}
|
||||
|
||||
#ifndef BOOTLOADER
|
||||
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
||||
|
||||
|
|
|
@ -49,66 +49,5 @@ extern int c200v2_variant;
|
|||
#define TIMER_PERIOD (KERNEL_TIMER_FREQ/HZ)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This function is not overly accurate, so rather call it with an usec more
|
||||
* than less (see below comment)
|
||||
*
|
||||
* if inlined it expands to a really small and fast function if it's called
|
||||
* with compile time constants */
|
||||
static inline void udelay(unsigned usecs) __attribute__((always_inline));
|
||||
static inline void udelay(unsigned usecs)
|
||||
{
|
||||
unsigned now;
|
||||
int end;
|
||||
|
||||
/**
|
||||
* we're limited to 0.666us multiplies due to the odd timer frequency (1.5MHz),
|
||||
* to avoid calculating which is safer (need to round up for small values)
|
||||
* and saves spending time in the divider we have a lut for
|
||||
* small us values, it should be roughly us*3/2
|
||||
**/
|
||||
static const unsigned char udelay_lut[] =
|
||||
{
|
||||
0, 2, 3, 5, 6, 8, 9, 11, 12, 14,
|
||||
15, 17, 18, 20, 21, 23, 24, 26, 27, 29,
|
||||
};
|
||||
|
||||
|
||||
now = TIMER2_VALUE;
|
||||
/* we don't want to handle multiple overflows, so limit the numbers
|
||||
* (if you want to wait more than a tick just poll current_tick, or
|
||||
* call sleep()) */
|
||||
if (UNLIKELY(usecs >= (TIMER_PERIOD*2/3)))
|
||||
panicf("%s(): %d too high!", __func__, usecs);
|
||||
if (UNLIKELY(usecs <= 0))
|
||||
return;
|
||||
if (usecs < ARRAYLEN(udelay_lut))
|
||||
{ /* the timer decrements */
|
||||
end = now - udelay_lut[usecs];
|
||||
}
|
||||
else
|
||||
{ /* to usecs */
|
||||
int delay = usecs * 3 / 2; /* us * 0.666 = us*timer_period */
|
||||
end = now - delay;
|
||||
}
|
||||
|
||||
unsigned old;
|
||||
|
||||
/* underrun ? */
|
||||
if (end < 0)
|
||||
{
|
||||
do {
|
||||
old = now;
|
||||
now = TIMER2_VALUE;
|
||||
} while(now <= old); /* if the new value is higher then we wrapped */
|
||||
|
||||
end += TIMER_PERIOD;
|
||||
}
|
||||
|
||||
do {
|
||||
/* if timer wraps then we missed our end value */
|
||||
old = now;
|
||||
now = TIMER2_VALUE;
|
||||
} while(now > (unsigned)end && now <= old);
|
||||
}
|
||||
void udelay(unsigned short usecs);
|
||||
#endif /* SYSTEM_TARGET_H */
|
||||
|
|
|
@ -80,8 +80,7 @@ void usb_attach(void)
|
|||
/* delay is in milliseconds */
|
||||
static inline void usb_delay(int delay)
|
||||
{
|
||||
while(delay--)
|
||||
udelay(1000);
|
||||
udelay(1000 * delay);
|
||||
}
|
||||
|
||||
static void usb_phy_on(void)
|
||||
|
|
Loading…
Reference in a new issue