summaryrefslogtreecommitdiff
path: root/firmware/target
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2010-04-27 09:34:29 +0000
committerThomas Martitz <kugel@rockbox.org>2010-04-27 09:34:29 +0000
commit845af676f8a37910613e7ce6b59dc229bb1a89c1 (patch)
tree0cc577ce1f31aea64a70b83f9323512da56912d4 /firmware/target
parentf2f34881ec84fb18020ae9a492f347e87c36359c (diff)
as3525(v2): Add a somewhat inaccurate udelay (-0.5/+1.0µs). It should work good for some huge delays.
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
Diffstat (limited to 'firmware/target')
-rw-r--r--firmware/target/arm/as3525/kernel-as3525.c7
-rw-r--r--firmware/target/arm/as3525/sansa-fuzev2/button-fuzev2.c15
-rw-r--r--firmware/target/arm/as3525/sd-as3525.c10
-rw-r--r--firmware/target/arm/as3525/sd-as3525v2.c2
-rw-r--r--firmware/target/arm/as3525/system-target.h59
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
@@ -25,13 +25,6 @@
#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) */
static int poll_scrollwheel = 0;
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 */