From 7bcfc38b4216b73afaeffec506a83debb7e58df2 Mon Sep 17 00:00:00 2001 From: Michael Sevakis Date: Fri, 23 Jan 2009 01:23:25 +0000 Subject: 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 --- firmware/export/imx31l.h | 86 ++++++++++++++++++++++ .../target/arm/imx31/gigabeat-s/button-imx31.c | 8 +- .../target/arm/imx31/gigabeat-s/system-imx31.c | 31 +++++++- .../target/arm/imx31/gigabeat-s/system-target.h | 17 ++--- 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); -- cgit v1.2.3