summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 7d37d05..2cdd674 100644
--- a/firmware/drivers/ata.c
+++ b/firmware/drivers/ata.c
@@ -201,6 +201,7 @@ static int perform_soft_reset(void);
static int set_multiple_mode(int sectors);
static int set_features(void);
+#ifndef ATA_TARGET_POLLING
STATICIRAM ICODE_ATTR int wait_for_bsy(void)
{
long timeout = current_tick + HZ*30;
@@ -235,6 +236,12 @@ STATICIRAM ICODE_ATTR int wait_for_rdy(void)
return 0; /* timeout */
}
+#else
+extern int ata_wait_for_bsy(void);
+extern int ata_wait_for_rdy(void);
+#define wait_for_bsy ata_wait_for_bsy
+#define wait_for_rdy ata_wait_for_rdy
+#endif
STATICIRAM ICODE_ATTR int wait_for_start_of_transfer(void)
{
diff --git a/firmware/target/arm/imx31/ata-imx31.c b/firmware/target/arm/imx31/ata-imx31.c
index 6ba49ca..c3e3c51 100644
--- a/firmware/target/arm/imx31/ata-imx31.c
+++ b/firmware/target/arm/imx31/ata-imx31.c
@@ -26,6 +26,7 @@
#include "power.h"
#include "panic.h"
#include "ata.h"
+#include "ata-defines.h"
#include "ata-target.h"
#include "ccm-imx31.h"
#ifdef HAVE_ATA_DMA
@@ -459,6 +460,7 @@ bool ata_dma_setup(void *addr, unsigned long bytes, bool write)
* shouldn't be reached based upon size. Otherwise we simply didn't
* understand the DMA mode setup. Force PIO in both cases. */
ATA_INTF_CONTROL = ATA_FIFO_RST | ATA_ATA_RST;
+ yield();
return false;
}
@@ -645,6 +647,43 @@ bool ata_dma_finish(void)
}
#endif /* HAVE_ATA_DMA */
+static int ata_wait_status(unsigned status, unsigned mask, int timeout)
+{
+ long busy_timeout = usec_timer() + 2;
+ long end_tick = current_tick + timeout;
+
+ while (1)
+ {
+ if ((ATA_DRIVE_STATUS & mask) == status)
+ return 1;
+
+ if (!TIME_AFTER(usec_timer(), busy_timeout))
+ continue;
+
+ ata_keep_active();
+
+ if (TIME_AFTER(current_tick, end_tick))
+ break;
+
+ sleep(0);
+ busy_timeout = usec_timer() + 2;
+ }
+
+ return 0; /* timed out */
+}
+
+int ata_wait_for_bsy(void)
+{
+ /* BSY = 0 */
+ return ata_wait_status(0, STATUS_BSY, 30*HZ);
+}
+
+int ata_wait_for_rdy(void)
+{
+ /* RDY = 1 && BSY = 0 */
+ return ata_wait_status(STATUS_RDY, STATUS_RDY | STATUS_BSY, 40*HZ);
+}
+
void ata_device_init(void)
{
/* 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 da1902a..24141c6 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);
#define ATA_SET_DEVICE_FEATURES
void ata_set_pio_timings(int mode);
+#define ATA_TARGET_POLLING
+
#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 978c7f7..1f177d4 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)
while (GPTCR & GPTCR_SWR);
/* No output
* No capture
- * Enable in run mode only (doesn't tick while in WFI)
+ * Enable in wait and run mode
* Freerun mode (count to 0xFFFFFFFF and roll-over to 0x00000000)
*/
- GPTCR = GPTCR_FRR | GPTCR_CLKSRC_IPG_CLK;
+ GPTCR = GPTCR_FRR | GPTCR_WAITEN | GPTCR_CLKSRC_IPG_CLK;
GPTPR = ipg_mhz - 1;
GPTCR |= GPTCR_EN;
}
diff --git a/firmware/target/arm/imx31/gigabeat-s/system-target.h b/firmware/target/arm/imx31/gigabeat-s/system-target.h
index f3ba719..4449b57 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 @@
/* Overdrive mode */
#define CPUFREQ_MAX 528000000
-static inline void udelay(unsigned int usecs)
+static inline void udelay(unsigned long usecs)
{
- unsigned stop = GPTCNT + usecs;
+ unsigned long stop = GPTCNT + usecs;
while (TIME_BEFORE(GPTCNT, stop));
}
+static inline unsigned long usec_timer(void)
+{
+ return GPTCNT;
+}
+
void watchdog_init(unsigned int half_seconds);
void watchdog_service(void);