diff options
author | Rafaël Carré <rafael.carre@gmail.com> | 2010-06-18 19:14:08 +0000 |
---|---|---|
committer | Rafaël Carré <rafael.carre@gmail.com> | 2010-06-18 19:14:08 +0000 |
commit | 7a9033179f34ba5175b5dc13c674d21235f2f98a (patch) | |
tree | 0c76fc01b163dae4b4fa9fbf9a828b539a10ea00 /firmware/target | |
parent | 955bb4004fcfbc762db7c9364665a40fa2018e7e (diff) | |
download | rockbox-7a9033179f34ba5175b5dc13c674d21235f2f98a.tar.gz rockbox-7a9033179f34ba5175b5dc13c674d21235f2f98a.zip |
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
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/arm/as3525/system-as3525.c | 20 | ||||
-rw-r--r-- | firmware/target/arm/as3525/system-target.h | 63 | ||||
-rw-r--r-- | firmware/target/arm/as3525/usb-drv-as3525.c | 3 |
3 files changed, 22 insertions, 64 deletions
diff --git a/firmware/target/arm/as3525/system-as3525.c b/firmware/target/arm/as3525/system-as3525.c index 940f183c63..aa98aff852 100644 --- a/firmware/target/arm/as3525/system-as3525.c +++ b/firmware/target/arm/as3525/system-as3525.c | |||
@@ -326,6 +326,26 @@ int system_memory_guard(int newmode) | |||
326 | return 0; | 326 | return 0; |
327 | } | 327 | } |
328 | 328 | ||
329 | void udelay(unsigned short usecs) | ||
330 | { | ||
331 | unsigned cycles_per_usec; | ||
332 | unsigned delay; | ||
333 | |||
334 | if (cpu_frequency == CPUFREQ_MAX) { | ||
335 | cycles_per_usec = (CPUFREQ_MAX + 999999) / 1000000; | ||
336 | } else { | ||
337 | cycles_per_usec = (CPUFREQ_NORMAL + 999999) / 1000000; | ||
338 | } | ||
339 | |||
340 | delay = (usecs * cycles_per_usec + 3) / 4; | ||
341 | |||
342 | asm volatile( | ||
343 | "1: subs %0, %0, #1 \n" /* 1 cycle */ | ||
344 | " bne 1b \n" /* 3 cycles */ | ||
345 | : : "r"(delay) | ||
346 | ); | ||
347 | } | ||
348 | |||
329 | #ifndef BOOTLOADER | 349 | #ifndef BOOTLOADER |
330 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | 350 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
331 | 351 | ||
diff --git a/firmware/target/arm/as3525/system-target.h b/firmware/target/arm/as3525/system-target.h index 523237ffcd..90e5e3a882 100644 --- a/firmware/target/arm/as3525/system-target.h +++ b/firmware/target/arm/as3525/system-target.h | |||
@@ -49,66 +49,5 @@ extern int c200v2_variant; | |||
49 | #define TIMER_PERIOD (KERNEL_TIMER_FREQ/HZ) | 49 | #define TIMER_PERIOD (KERNEL_TIMER_FREQ/HZ) |
50 | #endif | 50 | #endif |
51 | 51 | ||
52 | /* | 52 | void udelay(unsigned short usecs); |
53 | * This function is not overly accurate, so rather call it with an usec more | ||
54 | * than less (see below comment) | ||
55 | * | ||
56 | * if inlined it expands to a really small and fast function if it's called | ||
57 | * with compile time constants */ | ||
58 | static inline void udelay(unsigned usecs) __attribute__((always_inline)); | ||
59 | static inline void udelay(unsigned usecs) | ||
60 | { | ||
61 | unsigned now; | ||
62 | int end; | ||
63 | |||
64 | /** | ||
65 | * we're limited to 0.666us multiplies due to the odd timer frequency (1.5MHz), | ||
66 | * to avoid calculating which is safer (need to round up for small values) | ||
67 | * and saves spending time in the divider we have a lut for | ||
68 | * small us values, it should be roughly us*3/2 | ||
69 | **/ | ||
70 | static const unsigned char udelay_lut[] = | ||
71 | { | ||
72 | 0, 2, 3, 5, 6, 8, 9, 11, 12, 14, | ||
73 | 15, 17, 18, 20, 21, 23, 24, 26, 27, 29, | ||
74 | }; | ||
75 | |||
76 | |||
77 | now = TIMER2_VALUE; | ||
78 | /* we don't want to handle multiple overflows, so limit the numbers | ||
79 | * (if you want to wait more than a tick just poll current_tick, or | ||
80 | * call sleep()) */ | ||
81 | if (UNLIKELY(usecs >= (TIMER_PERIOD*2/3))) | ||
82 | panicf("%s(): %d too high!", __func__, usecs); | ||
83 | if (UNLIKELY(usecs <= 0)) | ||
84 | return; | ||
85 | if (usecs < ARRAYLEN(udelay_lut)) | ||
86 | { /* the timer decrements */ | ||
87 | end = now - udelay_lut[usecs]; | ||
88 | } | ||
89 | else | ||
90 | { /* to usecs */ | ||
91 | int delay = usecs * 3 / 2; /* us * 0.666 = us*timer_period */ | ||
92 | end = now - delay; | ||
93 | } | ||
94 | |||
95 | unsigned old; | ||
96 | |||
97 | /* underrun ? */ | ||
98 | if (end < 0) | ||
99 | { | ||
100 | do { | ||
101 | old = now; | ||
102 | now = TIMER2_VALUE; | ||
103 | } while(now <= old); /* if the new value is higher then we wrapped */ | ||
104 | |||
105 | end += TIMER_PERIOD; | ||
106 | } | ||
107 | |||
108 | do { | ||
109 | /* if timer wraps then we missed our end value */ | ||
110 | old = now; | ||
111 | now = TIMER2_VALUE; | ||
112 | } while(now > (unsigned)end && now <= old); | ||
113 | } | ||
114 | #endif /* SYSTEM_TARGET_H */ | 53 | #endif /* SYSTEM_TARGET_H */ |
diff --git a/firmware/target/arm/as3525/usb-drv-as3525.c b/firmware/target/arm/as3525/usb-drv-as3525.c index 0b73713c51..0b69e8953b 100644 --- a/firmware/target/arm/as3525/usb-drv-as3525.c +++ b/firmware/target/arm/as3525/usb-drv-as3525.c | |||
@@ -80,8 +80,7 @@ void usb_attach(void) | |||
80 | /* delay is in milliseconds */ | 80 | /* delay is in milliseconds */ |
81 | static inline void usb_delay(int delay) | 81 | static inline void usb_delay(int delay) |
82 | { | 82 | { |
83 | while(delay--) | 83 | udelay(1000 * delay); |
84 | udelay(1000); | ||
85 | } | 84 | } |
86 | 85 | ||
87 | static void usb_phy_on(void) | 86 | static void usb_phy_on(void) |