summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2009-01-23 01:23:25 +0000
committerMichael Sevakis <jethead71@rockbox.org>2009-01-23 01:23:25 +0000
commit7bcfc38b4216b73afaeffec506a83debb7e58df2 (patch)
tree8904a1a2ccc27f3eabc1a8c64fee91ea3dcf1f10
parentda76a3469437261bd8857c6eddeaafcc601f373e (diff)
Gigabeat S: Implement a genuine udelay function. Timer is gated to not run in WFI mode to save power and as such time until rollover is variable.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19820 a1c6a512-1295-4272-9138-f99709370657
-rwxr-xr-xfirmware/export/imx31l.h86
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/button-imx31.c8
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/system-imx31.c31
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/system-target.h17
4 files changed, 123 insertions, 19 deletions
diff --git a/firmware/export/imx31l.h b/firmware/export/imx31l.h
index b55a56b105..c9ef446e90 100755
--- a/firmware/export/imx31l.h
+++ b/firmware/export/imx31l.h
@@ -514,6 +514,92 @@
#define EPITSR_OCIF (1 << 0)
+/* GPT */
+#define GPTCR (*(REG32_PTR_T)(GPT1_BASE_ADDR+0x00))
+#define GPTPR (*(REG32_PTR_T)(GPT1_BASE_ADDR+0x04))
+#define GPTSR (*(REG32_PTR_T)(GPT1_BASE_ADDR+0x08))
+#define GPTIR (*(REG32_PTR_T)(GPT1_BASE_ADDR+0x0C))
+#define GPTOCR1 (*(REG32_PTR_T)(GPT1_BASE_ADDR+0x10))
+#define GPTOCR2 (*(REG32_PTR_T)(GPT1_BASE_ADDR+0x14))
+#define GPTOCR3 (*(REG32_PTR_T)(GPT1_BASE_ADDR+0x18))
+#define GPTICR1 (*(REG32_PTR_T)(GPT1_BASE_ADDR+0x1C))
+#define GPTICR2 (*(REG32_PTR_T)(GPT1_BASE_ADDR+0x20))
+#define GPTCNT (*(REG32_PTR_T)(GPT1_BASE_ADDR+0x24))
+
+/* GPTCR */
+#define GPTCR_FO3 (0x1 << 31)
+#define GPTCR_FO2 (0x1 << 30)
+#define GPTCR_FO1 (0x1 << 29)
+
+#define GPTCR_OM3 (0x7 << 26)
+#define GPTCR_OM3_DISCONNECTED (0x0 << 26)
+#define GPTCR_OM3_TOGGLE (0x1 << 26)
+#define GPTCR_OM3_CLEAR (0x2 << 26)
+#define GPTCR_OM3_SET (0x3 << 26)
+#define GPTCR_OM3_SINGLE_COUNT (0x4 << 26)
+ /* 0x5-0x7 same as 0x4 */
+
+#define GPTCR_OM2 (0x7 << 23)
+#define GPTCR_OM2_DISCONNECTED (0x0 << 23)
+#define GPTCR_OM2_TOGGLE (0x1 << 23)
+#define GPTCR_OM2_CLEAR (0x2 << 23)
+#define GPTCR_OM2_SET (0x3 << 23)
+#define GPTCR_OM2_SINGLE_COUNT (0x4 << 23)
+
+ /* 0x5-0x7 same as 0x4 */
+#define GPTCR_OM1 (0x7 << 20)
+#define GPTCR_OM1_DISCONNECTED (0x0 << 20)
+#define GPTCR_OM1_TOGGLE (0x1 << 20)
+#define GPTCR_OM1_CLEAR (0x2 << 20)
+#define GPTCR_OM1_SET (0x3 << 20)
+#define GPTCR_OM1_SINGLE_COUNT (0x4 << 20)
+
+ /* 0x5-0x7 same as 0x4 */
+#define GPTCR_IM2 (0x3 << 18)
+#define GPTCR_IM2_DISABLED (0x0 << 18)
+#define GPTCR_IM2_RISING (0x1 << 18)
+#define GPTCR_IM2_FALLING (0x2 << 18)
+#define GPTCR_IM2_BOTH (0x3 << 18)
+
+#define GPTCR_IM1 (0x3 << 16)
+#define GPTCR_IM1_DISABLED (0x0 << 16)
+#define GPTCR_IM1_RISING (0x1 << 16)
+#define GPTCR_IM1_FALLING (0x2 << 16)
+#define GPTCR_IM1_BOTH (0x3 << 16)
+
+#define GPTCR_SWR (0x1 << 15)
+#define GPTCR_FRR (0x1 << 9)
+
+#define GPTCR_CLKSRC (0x7 << 6)
+#define GPTCR_CLKSRC_NONE (0x0 << 6)
+#define GPTCR_CLKSRC_IPG_CLK (0x1 << 6)
+#define GPTCR_CLKSRC_IPG_CLK_HIGHFREQ (0x2 << 6)
+#define GPTCR_CLKSRC_IPG_CLK_32K (0x4 << 6)
+/* Other values not defined */
+
+#define GPTCR_STOPEN (0x1 << 5)
+#define GPTCR_DOZEN (0x1 << 4)
+#define GPTCR_WAITEN (0x1 << 3)
+#define GPTCR_DBGEN (0x1 << 2)
+#define GPTCR_ENMODE (0x1 << 1)
+#define GPTCR_EN (0x1 << 0)
+
+/* GPTSR */
+#define GPTSR_ROV (0x1 << 5)
+#define GPTSR_IF2 (0x1 << 4)
+#define GPTSR_IF1 (0x1 << 3)
+#define GPTSR_OF3 (0x1 << 2)
+#define GPTSR_OF2 (0x1 << 1)
+#define GPTSR_OF1 (0x1 << 0)
+
+/* GPTIR */
+#define GPTIR_ROV (0x1 << 5)
+#define GPTIR_IF2IE (0x1 << 4)
+#define GPTIR_IF1IE (0x1 << 3)
+#define GPTIR_OF3IE (0x1 << 2)
+#define GPTIR_OF2IE (0x1 << 1)
+#define GPTIR_OF1IE (0x1 << 0)
+
/* GPIO */
#define GPIO1_DR (*(REG32_PTR_T)(GPIO1_BASE_ADDR+0x00))
#define GPIO1_GDIR (*(REG32_PTR_T)(GPIO1_BASE_ADDR+0x04))
diff --git a/firmware/target/arm/imx31/gigabeat-s/button-imx31.c b/firmware/target/arm/imx31/gigabeat-s/button-imx31.c
index 7c432450c2..587e66e0bc 100644
--- a/firmware/target/arm/imx31/gigabeat-s/button-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/button-imx31.c
@@ -68,8 +68,6 @@ static __attribute__((interrupt("IRQ"))) void KPP_HANDLER(void)
for (col = 0; col < 3; col++) /* Col */
{
- int i;
-
/* 2. Write 1s to KPDR[10:8] setting column data to 1s */
KPP_KPDR |= (0x7 << 8);
@@ -78,8 +76,7 @@ static __attribute__((interrupt("IRQ"))) void KPP_HANDLER(void)
KPP_KPCR &= ~(0x7 << 8);
/* Give the columns time to discharge */
- for (i = 0; i < 128; i++) /* TODO: find minimum safe delay */
- asm volatile ("");
+ udelay(2);
/* 4. Configure columns as open-drain */
KPP_KPCR |= (0x7 << 8);
@@ -94,8 +91,7 @@ static __attribute__((interrupt("IRQ"))) void KPP_HANDLER(void)
/* Delay added to avoid propagating the 0 from column to row
* when scanning. */
- for (i = 0; i < 128; i++) /* TODO: find minimum safe delay */
- asm volatile ("");
+ udelay(2);
/* Read row input */
button |= (~KPP_KPDR & kms[col].mask) << kms[col].shift;
diff --git a/firmware/target/arm/imx31/gigabeat-s/system-imx31.c b/firmware/target/arm/imx31/gigabeat-s/system-imx31.c
index c339f4fe7c..7454806d07 100644
--- a/firmware/target/arm/imx31/gigabeat-s/system-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/system-imx31.c
@@ -32,6 +32,8 @@
#include "clkctl-imx31.h"
#include "mc13783.h"
+/** Watchdog timer routines **/
+
/* Initialize the watchdog timer */
void watchdog_init(unsigned int half_seconds)
{
@@ -57,6 +59,33 @@ void watchdog_service(void)
WDOG_WSR = 0xaaaa;
}
+/** GPT timer routines - basis for udelay **/
+
+/* Start the general-purpose timer (1MHz) */
+void gpt_start(void)
+{
+ imx31_clkctl_module_clock_gating(CG_GPT, CGM_ON_RUN_WAIT);
+ unsigned int ipg_mhz = imx31_clkctl_get_ipg_clk() / 1000000;
+
+ GPTCR &= ~GPTCR_EN; /* Disable counter */
+ GPTCR |= GPTCR_SWR; /* Reset module */
+ while (GPTCR & GPTCR_SWR);
+ /* No output
+ * No capture
+ * Enable in run mode only (doesn't tick while in WFI)
+ * Freerun mode (count to 0xFFFFFFFF and roll-over to 0x00000000)
+ */
+ GPTCR = GPTCR_FRR | GPTCR_CLKSRC_IPG_CLK;
+ GPTPR = ipg_mhz - 1;
+ GPTCR |= GPTCR_EN;
+}
+
+/* Stop the general-purpose timer */
+void gpt_stop(void)
+{
+ GPTCR &= ~GPTCR_EN;
+}
+
int system_memory_guard(int newmode)
{
(void)newmode;
@@ -84,7 +113,6 @@ void system_init(void)
/* CGR0 */
CG_SD_MMC1,
CG_SD_MMC2,
- CG_GPT,
CG_IIM,
CG_SDMA,
CG_CSPI3,
@@ -140,6 +168,7 @@ void system_init(void)
imx31_clkctl_module_clock_gating(disable_clocks[i], CGM_OFF);
avic_init();
+ gpt_start();
gpio_init();
}
diff --git a/firmware/target/arm/imx31/gigabeat-s/system-target.h b/firmware/target/arm/imx31/gigabeat-s/system-target.h
index b99b31d1b4..c7797e43c9 100644
--- a/firmware/target/arm/imx31/gigabeat-s/system-target.h
+++ b/firmware/target/arm/imx31/gigabeat-s/system-target.h
@@ -31,25 +31,18 @@
#define CPUFREQ_MAX CPU_FREQ
#endif
-/* For USB driver - no accuracy assurance */
static inline void udelay(unsigned int usecs)
{
- unsigned int x;
- for (x = 0; x < 300*usecs; x++)
- asm volatile ("");
+ unsigned stop = GPTCNT + usecs;
+ while (TIME_BEFORE(GPTCNT, stop));
}
-#if 0
-static inline void udelay(unsigned int usecs)
-{
- volatile signed int stop = EPITCNT1 - usecs;
- while ((signed int)EPITCNT1 > stop);
-}
-#endif
-
void watchdog_init(unsigned int half_seconds);
void watchdog_service(void);
+void gpt_start(void);
+void gpt_stop(void);
+
/* Prepare for transition to firmware */
void system_prepare_fw_start(void);
void tick_stop(void);