summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 ebaef71..4ae1a03 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 d50df9f..db08414 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 5ccb659..1cf7e51 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 baf6976..2f263f7 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 1173515..1ccd328 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 */