From 845af676f8a37910613e7ce6b59dc229bb1a89c1 Mon Sep 17 00:00:00 2001 From: Thomas Martitz Date: Tue, 27 Apr 2010 09:34:29 +0000 Subject: as3525(v2): Add a somewhat inaccurate udelay (-0.5/+1.0µs). It should work good for some huge delays. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use it in fuzev2 to improve some big delays (correct the biggest one to actually wait for the fifo to empty), and use it in the sd drivers. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25734 a1c6a512-1295-4272-9138-f99709370657 --- firmware/target/arm/as3525/kernel-as3525.c | 7 --- .../target/arm/as3525/sansa-fuzev2/button-fuzev2.c | 15 +++--- firmware/target/arm/as3525/sd-as3525.c | 10 ++-- firmware/target/arm/as3525/sd-as3525v2.c | 2 +- firmware/target/arm/as3525/system-target.h | 59 +++++++++++++++++++++- 5 files changed, 68 insertions(+), 25 deletions(-) diff --git a/firmware/target/arm/as3525/kernel-as3525.c b/firmware/target/arm/as3525/kernel-as3525.c index ebaef71c99..4ae1a03809 100644 --- a/firmware/target/arm/as3525/kernel-as3525.c +++ b/firmware/target/arm/as3525/kernel-as3525.c @@ -24,13 +24,6 @@ #include "panic.h" #include "timer.h" -#ifdef HAVE_SCROLLWHEEL -/* let the timer interrupt twice as often for the scrollwheel polling */ -#define KERNEL_TIMER_FREQ (TIMER_FREQ/2) -#else -#define KERNEL_TIMER_FREQ TIMER_FREQ -#endif - #ifdef HAVE_SCROLLWHEEL #include "button-target.h" /* The scrollwheel is polled every 5 ms (the tick tasks only every 10) */ diff --git a/firmware/target/arm/as3525/sansa-fuzev2/button-fuzev2.c b/firmware/target/arm/as3525/sansa-fuzev2/button-fuzev2.c index d50df9f1c6..db08414ae5 100644 --- a/firmware/target/arm/as3525/sansa-fuzev2/button-fuzev2.c +++ b/firmware/target/arm/as3525/sansa-fuzev2/button-fuzev2.c @@ -58,29 +58,26 @@ void get_scrollwheel(void) int button_read_device(void) { int btn = 0; - volatile int delay; static bool hold_button_old = false; static long power_counter = 0; unsigned gpiod6; - /* if we remove this delay, we see screen corruption (the higher the CPU - * frequency the higher the corruption) */ - for(delay = 1000; delay; delay--) - nop; + + /* if we don't wait for the fifo to empty, we'll see screen corruption + * (the higher the CPU frequency the higher the corruption) */ + while ((DBOP_STAT & (1<<10)) == 0); get_scrollwheel(); CCU_IO &= ~(1<<12); GPIOB_PIN(0) = 1<<0; - for(delay = 500; delay; delay--) - nop; + udelay(1); gpiod6 = GPIOD_PIN(6); GPIOB_PIN(0) = 0; - for(delay = 240; delay; delay--) - nop; + udelay(1); if (GPIOC_PIN(1) & 1<<1) btn |= BUTTON_DOWN; diff --git a/firmware/target/arm/as3525/sd-as3525.c b/firmware/target/arm/as3525/sd-as3525.c index 5ccb659e00..1cf7e51cf8 100644 --- a/firmware/target/arm/as3525/sd-as3525.c +++ b/firmware/target/arm/as3525/sd-as3525.c @@ -141,13 +141,8 @@ static volatile unsigned int transfer_error[NUM_VOLUMES]; static unsigned char aligned_buffer[UNALIGNED_NUM_SECTORS* SD_BLOCK_SIZE] __attribute__((aligned(32))); /* align on cache line size */ static unsigned char *uncached_buffer = UNCACHED_ADDR(&aligned_buffer[0]); -static inline void mci_delay(void) -{ - int i = 0xffff; - do { - asm volatile("nop\n"); - } while (--i); -} + +static inline void mci_delay(void) { udelay(1000) ; } static inline bool card_detect_target(void) @@ -159,6 +154,7 @@ static inline bool card_detect_target(void) #endif } + #ifdef HAVE_HOTSWAP static int sd1_oneshot_callback(struct timeout *tmo) { diff --git a/firmware/target/arm/as3525/sd-as3525v2.c b/firmware/target/arm/as3525/sd-as3525v2.c index baf69760ab..2f263f7378 100644 --- a/firmware/target/arm/as3525/sd-as3525v2.c +++ b/firmware/target/arm/as3525/sd-as3525v2.c @@ -344,7 +344,7 @@ static volatile bool retry; int active_card = 0; #endif -static inline void mci_delay(void) { int i = 0xffff; while(i--) ; } +static inline void mci_delay(void) { udelay(1000); } void INT_NAND(void) { diff --git a/firmware/target/arm/as3525/system-target.h b/firmware/target/arm/as3525/system-target.h index 1173515ebb..1ccd3282db 100644 --- a/firmware/target/arm/as3525/system-target.h +++ b/firmware/target/arm/as3525/system-target.h @@ -23,19 +23,76 @@ #include "system-arm.h" #include "mmu-arm.h" +#include "panic.h" #include "clock-target.h" /* CPUFREQ_* are defined here */ +#ifdef HAVE_SCROLLWHEEL +/* let the timer interrupt twice as often for the scrollwheel polling */ +#define KERNEL_TIMER_FREQ (TIMER_FREQ/2) +#else +#define KERNEL_TIMER_FREQ TIMER_FREQ +#endif + #ifdef BOOTLOADER #define UNCACHED_ADDR(a) (a) #else #define UNCACHED_ADDR(a) ((typeof(a)) ((uintptr_t)(a) + 0x10000000)) #endif - #ifdef SANSA_C200V2 /* 0: Backlight on A5, 1: Backlight on A7 */ extern int c200v2_variant; +/* c200v2 changes the timer interval often due to software pwm */ +#define TIMER_PERIOD TIMER2_BGLOAD +#else +#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) +{ + int now, end; + + /** + * we're limited to 1.5us 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*2/3 + **/ + static const unsigned char udelay_lut[] = + { + 0, 1, 2, 2, 3, 4, 4, 5, 6, 6, + 7, 8, 8, 9, 10, 10, 11, 12, 12, 13, + }; + + + 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)) + 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 * 2 / 3; /* us * 1.5 = us*timer_period */ + end = now - delay; + } + /* underrun ? */ + if (end < 0) + end += TIMER_PERIOD; + while(TIMER2_VALUE != (unsigned)end); +} #endif /* SYSTEM_TARGET_H */ -- cgit v1.2.3