summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2011-01-22 09:23:31 +0000
committerMichael Sevakis <jethead71@rockbox.org>2011-01-22 09:23:31 +0000
commit060609a2023bfcc99472cfe4e94a2cc3704bd92c (patch)
treecc51f89e8dc4cca19ff4453195cd712888314368
parent5729be4017c6e6081069c56637c4339aaddddd0b (diff)
downloadrockbox-060609a2023bfcc99472cfe4e94a2cc3704bd92c.tar.gz
rockbox-060609a2023bfcc99472cfe4e94a2cc3704bd92c.zip
i.MX31: Busy wait for a couple microseconds at most then sleep until next tick when polling drive status. This prevents pointless jumps to overdrive speed from perceived high load when waiting for lengthy ops to complete such as spinup and sleep.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29108 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/drivers/ata.c7
-rw-r--r--firmware/target/arm/imx31/ata-imx31.c39
-rw-r--r--firmware/target/arm/imx31/ata-target.h2
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/system-gigabeat-s.c4
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/system-target.h9
5 files changed, 57 insertions, 4 deletions
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c
index 7d37d051c9..2cdd67482a 100644
--- a/firmware/drivers/ata.c
+++ b/firmware/drivers/ata.c
@@ -201,6 +201,7 @@ static int perform_soft_reset(void);
201static int set_multiple_mode(int sectors); 201static int set_multiple_mode(int sectors);
202static int set_features(void); 202static int set_features(void);
203 203
204#ifndef ATA_TARGET_POLLING
204STATICIRAM ICODE_ATTR int wait_for_bsy(void) 205STATICIRAM ICODE_ATTR int wait_for_bsy(void)
205{ 206{
206 long timeout = current_tick + HZ*30; 207 long timeout = current_tick + HZ*30;
@@ -235,6 +236,12 @@ STATICIRAM ICODE_ATTR int wait_for_rdy(void)
235 236
236 return 0; /* timeout */ 237 return 0; /* timeout */
237} 238}
239#else
240extern int ata_wait_for_bsy(void);
241extern int ata_wait_for_rdy(void);
242#define wait_for_bsy ata_wait_for_bsy
243#define wait_for_rdy ata_wait_for_rdy
244#endif
238 245
239STATICIRAM ICODE_ATTR int wait_for_start_of_transfer(void) 246STATICIRAM ICODE_ATTR int wait_for_start_of_transfer(void)
240{ 247{
diff --git a/firmware/target/arm/imx31/ata-imx31.c b/firmware/target/arm/imx31/ata-imx31.c
index 6ba49cada0..c3e3c51e63 100644
--- a/firmware/target/arm/imx31/ata-imx31.c
+++ b/firmware/target/arm/imx31/ata-imx31.c
@@ -26,6 +26,7 @@
26#include "power.h" 26#include "power.h"
27#include "panic.h" 27#include "panic.h"
28#include "ata.h" 28#include "ata.h"
29#include "ata-defines.h"
29#include "ata-target.h" 30#include "ata-target.h"
30#include "ccm-imx31.h" 31#include "ccm-imx31.h"
31#ifdef HAVE_ATA_DMA 32#ifdef HAVE_ATA_DMA
@@ -459,6 +460,7 @@ bool ata_dma_setup(void *addr, unsigned long bytes, bool write)
459 * shouldn't be reached based upon size. Otherwise we simply didn't 460 * shouldn't be reached based upon size. Otherwise we simply didn't
460 * understand the DMA mode setup. Force PIO in both cases. */ 461 * understand the DMA mode setup. Force PIO in both cases. */
461 ATA_INTF_CONTROL = ATA_FIFO_RST | ATA_ATA_RST; 462 ATA_INTF_CONTROL = ATA_FIFO_RST | ATA_ATA_RST;
463 yield();
462 return false; 464 return false;
463 } 465 }
464 466
@@ -645,6 +647,43 @@ bool ata_dma_finish(void)
645} 647}
646#endif /* HAVE_ATA_DMA */ 648#endif /* HAVE_ATA_DMA */
647 649
650static int ata_wait_status(unsigned status, unsigned mask, int timeout)
651{
652 long busy_timeout = usec_timer() + 2;
653 long end_tick = current_tick + timeout;
654
655 while (1)
656 {
657 if ((ATA_DRIVE_STATUS & mask) == status)
658 return 1;
659
660 if (!TIME_AFTER(usec_timer(), busy_timeout))
661 continue;
662
663 ata_keep_active();
664
665 if (TIME_AFTER(current_tick, end_tick))
666 break;
667
668 sleep(0);
669 busy_timeout = usec_timer() + 2;
670 }
671
672 return 0; /* timed out */
673}
674
675int ata_wait_for_bsy(void)
676{
677 /* BSY = 0 */
678 return ata_wait_status(0, STATUS_BSY, 30*HZ);
679}
680
681int ata_wait_for_rdy(void)
682{
683 /* RDY = 1 && BSY = 0 */
684 return ata_wait_status(STATUS_RDY, STATUS_RDY | STATUS_BSY, 40*HZ);
685}
686
648void ata_device_init(void) 687void ata_device_init(void)
649{ 688{
650 /* Make sure we're not in reset mode */ 689 /* Make sure we're not in reset mode */
diff --git a/firmware/target/arm/imx31/ata-target.h b/firmware/target/arm/imx31/ata-target.h
index da1902acea..24141c6aa7 100644
--- a/firmware/target/arm/imx31/ata-target.h
+++ b/firmware/target/arm/imx31/ata-target.h
@@ -53,4 +53,6 @@ bool ata_is_coldstart(void);
53#define ATA_SET_DEVICE_FEATURES 53#define ATA_SET_DEVICE_FEATURES
54void ata_set_pio_timings(int mode); 54void ata_set_pio_timings(int mode);
55 55
56#define ATA_TARGET_POLLING
57
56#endif /* ATA_TARGET_H */ 58#endif /* ATA_TARGET_H */
diff --git a/firmware/target/arm/imx31/gigabeat-s/system-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/system-gigabeat-s.c
index 978c7f77cd..1f177d4252 100644
--- a/firmware/target/arm/imx31/gigabeat-s/system-gigabeat-s.c
+++ b/firmware/target/arm/imx31/gigabeat-s/system-gigabeat-s.c
@@ -97,10 +97,10 @@ void gpt_start(void)
97 while (GPTCR & GPTCR_SWR); 97 while (GPTCR & GPTCR_SWR);
98 /* No output 98 /* No output
99 * No capture 99 * No capture
100 * Enable in run mode only (doesn't tick while in WFI) 100 * Enable in wait and run mode
101 * Freerun mode (count to 0xFFFFFFFF and roll-over to 0x00000000) 101 * Freerun mode (count to 0xFFFFFFFF and roll-over to 0x00000000)
102 */ 102 */
103 GPTCR = GPTCR_FRR | GPTCR_CLKSRC_IPG_CLK; 103 GPTCR = GPTCR_FRR | GPTCR_WAITEN | GPTCR_CLKSRC_IPG_CLK;
104 GPTPR = ipg_mhz - 1; 104 GPTPR = ipg_mhz - 1;
105 GPTCR |= GPTCR_EN; 105 GPTCR |= GPTCR_EN;
106} 106}
diff --git a/firmware/target/arm/imx31/gigabeat-s/system-target.h b/firmware/target/arm/imx31/gigabeat-s/system-target.h
index f3ba719443..4449b570f7 100644
--- a/firmware/target/arm/imx31/gigabeat-s/system-target.h
+++ b/firmware/target/arm/imx31/gigabeat-s/system-target.h
@@ -31,12 +31,17 @@
31/* Overdrive mode */ 31/* Overdrive mode */
32#define CPUFREQ_MAX 528000000 32#define CPUFREQ_MAX 528000000
33 33
34static inline void udelay(unsigned int usecs) 34static inline void udelay(unsigned long usecs)
35{ 35{
36 unsigned stop = GPTCNT + usecs; 36 unsigned long stop = GPTCNT + usecs;
37 while (TIME_BEFORE(GPTCNT, stop)); 37 while (TIME_BEFORE(GPTCNT, stop));
38} 38}
39 39
40static inline unsigned long usec_timer(void)
41{
42 return GPTCNT;
43}
44
40void watchdog_init(unsigned int half_seconds); 45void watchdog_init(unsigned int half_seconds);
41void watchdog_service(void); 46void watchdog_service(void);
42 47